diff options
author | Lauri Leukkunen <lle@rahina.org> | 2006-12-26 11:57:41 +0200 |
---|---|---|
committer | Lauri Leukkunen <lleukkun@leka.rahina.org> | 2006-12-26 11:57:41 +0200 |
commit | 2c10ab33f9e7c6332ab83cc16ac180418e202304 (patch) | |
tree | 5831b2af0d1c11d6e5f80e2720892e9909247829 | |
parent | 2880c5f37943937cbfed46d7f3efee27a82a57d4 (diff) |
* add a mapping cache, speeds things up enormously, almost to SB1 level
* fix a lot of subtle mis-behaviour by returning the untouched path in
cases where no mapping took place.
* mkdtemp can't use mapping at the moment, this should be revisited in
the future.
* add a few more mappings to default.lua, mainly autotools related
* main.lua fills in sane defaults for missing values in rules, makes
the rules files way cleaner and less verbose to write.
-rw-r--r-- | include/sb2.h | 10 | ||||
-rw-r--r-- | lua/lua_bindings.c | 253 | ||||
-rw-r--r-- | preload/libsb2.c | 63 | ||||
-rw-r--r-- | preload/sb_alien.c | 66 | ||||
-rw-r--r-- | redir_scripts/main.lua | 12 | ||||
-rw-r--r-- | redir_scripts/parts/default.lua | 86 |
6 files changed, 371 insertions, 119 deletions
diff --git a/include/sb2.h b/include/sb2.h index fd19ed2..473d7b8 100644 --- a/include/sb2.h +++ b/include/sb2.h @@ -3,4 +3,14 @@ #define DBGOUT(fmt...) fprintf(stderr, fmt) +extern int (*next_execve) (const char *filename, char *const argv [], char *const envp[]); + +int ld_so_run_app(char *file, char **argv, char *const *envp); +int run_app(char *file, char **argv, char *const *envp); +int run_cputransparency(char *file, char **argv, char *const *envp); + +int run_sbrsh(char *sbrsh_bin, char *target_root, char *file, char **argv, char *const *envp); +int run_qemu(char *qemu_bin, char *target_root, char *file, char **argv, char *const *envp); + + #endif diff --git a/lua/lua_bindings.c b/lua/lua_bindings.c index 717081d..c711b66 100644 --- a/lua/lua_bindings.c +++ b/lua/lua_bindings.c @@ -57,6 +57,193 @@ char *main_lua = NULL; pthread_mutex_t lua_lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; +struct path_entry { + struct path_entry *prev; + struct path_entry *next; + char name[PATH_MAX]; +}; + +static char *decolonize_path(const char *path) +{ + char *cpath, *index, *start; + char cwd[PATH_MAX]; + struct path_entry list; + struct path_entry *work; + struct path_entry *new; + char *buf = NULL; + + if (!path) { + DBGOUT("PATH IS CRAP\n"); + return NULL; + } + + buf = malloc((PATH_MAX + 1) * sizeof(char)); + memset(buf, '\0', PATH_MAX + 1); + + list.next = NULL; + list.prev = NULL; + work = &list; + + if (path[0] != '/') { + /* not an absolute path */ + memset(cwd, '\0', PATH_MAX); + if (syscall(__NR_getcwd, cwd, PATH_MAX) < 0) { + perror("error getting current work dir\n"); + return NULL; + } + unsigned int l = (strlen(cwd) + 1 + strlen(path) + 1); + cpath = malloc((strlen(cwd) + 1 + strlen(path) + 1) * sizeof(char)); + memset(cpath, '\0', l); + strcpy(cpath, cwd); + strcat(cpath, "/"); + strcat(cpath, path); + } else { + cpath = strdup(path); + } + start = cpath + 1; /* ignore leading '/' */ + while (1) { + index = strstr(start, "/"); + if (!index) { + /* add the last item */ + new = malloc(sizeof(struct path_entry)); + memset(new->name, '\0', PATH_MAX); + new->prev = work; + work->next = new; + new->next = NULL; + strcpy(new->name, start); + work = new; + break; + } + *index = '\0'; + if (strcmp(start, "..") == 0) { + /* travel up one */ + if (!work->prev) goto proceed; + work = work->prev; + free(work->next); + work->next = NULL; + } else if (strcmp(start, ".") == 0) { + /* ignore */ + goto proceed; + } else { + /* add an entry to our path_entry list */ + new = malloc(sizeof(struct path_entry)); + memset(new->name, '\0', PATH_MAX); + new->prev = work; + work->next = new; + new->next = NULL; + strcpy(new->name, start); + work = new; + } + +proceed: + *index = '/'; + start = index + 1; + } + + work = list.next; + while (work) { + struct path_entry *tmp; + strcat(buf, "/"); + strcat(buf, work->name); + //printf("entry name: %s\n", work->name); + tmp = work; + work = work->next; + free(tmp); + } + return buf; +} + + + +static char *create_sb2cache_path(const char *binary_name, const char *func_name, const char *path) +{ + char *target_dir = getenv("SBOX_TARGET_ROOT"); + char *cache_path; + unsigned int length; + + length = strlen(target_dir) + strlen(".sb2cache") + strlen(path) + 1 + strlen(binary_name) + 1 + strlen(func_name) + 4 + 1; + cache_path = malloc(length * sizeof(char)); + memset(cache_path, '\0', length); + strcpy(cache_path, target_dir); + strcat(cache_path, ".sb2cache"); + strcat(cache_path, path); + strcat(cache_path, "."); + strcat(cache_path, binary_name); + strcat(cache_path, "."); + strcat(cache_path, func_name); + strcat(cache_path, ".map"); + return cache_path; +} + +/* + * return NULL if not found from cache, or if cache doesn't exist + */ +static char *read_sb2cache(const char *binary_name, const char *func_name, const char *path) +{ + char *cache_path = create_sb2cache_path(binary_name, func_name, path); + char *link_path; + + link_path = malloc((PATH_MAX + 1) * sizeof(char)); + memset(link_path, '\0', PATH_MAX + 1); + + if (syscall(__NR_readlink, cache_path, link_path, PATH_MAX) < 0) { + //DBGOUT("read_sb2cache before free()\n"); + free(link_path); + //DBGOUT("read_sb2cache after free()\n"); + return NULL; + } + return link_path; +} + +/* + * if the cache dir doesn't exist, this will create it + */ +static int insert_sb2cache(const char *binary_name, const char *func_name, const char *path, const char *map_to) +{ + char *cache_path; + char *dcopy; + char *wrk; + struct stat64 s; + + cache_path = create_sb2cache_path(binary_name, func_name, path); + + dcopy = strdup(cache_path); + + /* make sure all the directory elements exist, + * this does nasty stuff in place to dcopy */ + wrk = dcopy; + while (*wrk != '\0') { + wrk = strstr(wrk + 1, "/"); + + if (!wrk) break; + + *wrk = '\0'; + //DBGOUT("checking path: %s\n", dcopy); + if (syscall(__NR_stat64, dcopy, &s) < 0) { + if (errno == ENOENT || errno == ENOTDIR) { + /* create the dir */ + if (syscall(__NR_mkdir, dcopy, ~0) < 0) { + perror("Unable to create dir in sb2cache\n"); + exit(1); + } + } else { + perror("Big trouble working the sb2cache\n"); + exit(1); + } + } + + *wrk = '/'; + wrk++; + } + + if (syscall(__NR_symlink, map_to, cache_path) < 0) { + perror("Error while creating symlink in sb2cache\n"); + exit(1); + } + return 0; +} + + static int sb_realpath(lua_State *l) { char *path; @@ -198,8 +385,43 @@ char *scratchbox_path(const char *func_name, const char *path) { char binary_name[PATH_MAX+1]; char work_dir[PATH_MAX+1]; - char *tmp; + char *tmp, *decolon_path; char pidlink[17]; /* /proc/2^8/exe */ + + if (!path) return NULL; + + decolon_path = decolonize_path(path); + + if (strstr(decolon_path, getenv("SBOX_TARGET_ROOT")) + || strstr(decolon_path, getenv("HOME"))) { + /* short circuit a direct reference to a file inside the sbox + * target dir, or to $HOME dir */ + //DBGOUT("about to short circuit: %s\n", func_name); + free(decolon_path); + return strdup(path); + } + + memset(binary_name, '\0', PATH_MAX+1); + tmp = getenv("__SB2_BINARYNAME"); + if (tmp) { + strcpy(binary_name, tmp); + } else { + strcpy(binary_name, "DUMMY"); + } + + /* first try from the cache */ + + tmp = read_sb2cache(binary_name, func_name, decolon_path); + + if (tmp) { + if (strcmp(tmp, decolon_path) == 0) { + free(decolon_path); + return strdup(path); + } else { + return tmp; + } + } + #if 1 if (pthread_mutex_trylock(&lua_lock) < 0) { pthread_mutex_lock(&lua_lock); @@ -220,13 +442,6 @@ char *scratchbox_path(const char *func_name, const char *path) strcat(main_lua, "/main.lua"); } - memset(binary_name, '\0', PATH_MAX+1); - tmp = getenv("__SB2_BINARYNAME"); - if (tmp) { - strcpy(binary_name, tmp); - } else { - strcpy(binary_name, "DUMMY"); - } memset(work_dir, '\0', PATH_MAX+1); snprintf(pidlink,16,"/proc/%i/exe",sb_getpid()); // if (syscall(__NR_readlink, pidlink, binary_name, PATH_MAX) < 0) { @@ -234,10 +449,11 @@ char *scratchbox_path(const char *func_name, const char *path) // } syscall(__NR_getcwd, work_dir, PATH_MAX); - /* RECURSIVE CALL BREAK */ - if (strncmp(path, rsdir, strlen(rsdir)) == 0) { + /* redir_scripts RECURSIVE CALL BREAK */ + if (strncmp(decolon_path, rsdir, strlen(rsdir)) == 0) { //pthread_mutex_unlock(&lua_lock); - return (char *)path; + //DBGOUT("cutting recursive call\n"); + return (char *)decolon_path; } if (!l) { @@ -265,16 +481,25 @@ char *scratchbox_path(const char *func_name, const char *path) lua_pushstring(l, binary_name); lua_pushstring(l, func_name); lua_pushstring(l, work_dir); - lua_pushstring(l, path); + lua_pushstring(l, decolon_path); lua_call(l, 4, 1); /* four arguments, one result */ - tmp = lua_tostring(l, -1); + tmp = (char *)lua_tostring(l, -1); if (tmp) { tmp = strdup(tmp); } lua_pop(l, 1); pthread_mutex_unlock(&lua_lock); - return tmp; + insert_sb2cache(binary_name, func_name, decolon_path, tmp); + //DBGOUT("returning path: [%s]\n", tmp); + if (strcmp(tmp, decolon_path) == 0) { + free(decolon_path); + free(tmp); + return strdup(path); + } else { + free(decolon_path); + return tmp; + } } diff --git a/preload/libsb2.c b/preload/libsb2.c index 9c6d24e..300aa52 100644 --- a/preload/libsb2.c +++ b/preload/libsb2.c @@ -85,7 +85,7 @@ * if ( amount /../ > amount /other/ ) ) remove extra /../ */ -#define narrow_chroot_path(path, fakechroot_path, fakechroot_ptr) \ +#define narrow_chroot_path(path, fakechroot_path) \ { \ if ((path) != NULL && *((char *)(path)) != '\0') { \ fakechroot_path = scratchbox_path(__FUNCTION__, path); \ @@ -120,11 +120,6 @@ } \ } -/* some useful prototypes */ - -int ld_so_run_app(char *file, char **argv, char *const *envp); -int run_app(char *file, char **argv, char *const *envp); -int run_cputransparency(char *file, char **argv, char *const *envp); #ifndef __GLIBC__ extern char **environ; @@ -1742,7 +1737,7 @@ int ftw64 (const char *dir, int (*fn)(const char *file, const struct stat64 *sb, /* #include <unistd.h> */ char * get_current_dir_name (void) { char *cwd, *oldptr, *newptr; - char *fakechroot_path, *fakechroot_ptr; + char *fakechroot_path; if (next_get_current_dir_name == NULL) fakechroot_init(); @@ -1750,7 +1745,7 @@ char * get_current_dir_name (void) { return NULL; } oldptr = cwd; - narrow_chroot_path(cwd, fakechroot_path, fakechroot_ptr); + narrow_chroot_path(cwd, fakechroot_path); if (cwd == NULL) { return NULL; } @@ -1769,14 +1764,14 @@ char * get_current_dir_name (void) { char * getcwd (char *buf, size_t size) { char *cwd; - char *fakechroot_path, *fakechroot_ptr; + char *fakechroot_path; if (next_getcwd == NULL) fakechroot_init(); if ((cwd = next_getcwd(buf, size)) == NULL) { return NULL; } - narrow_chroot_path(cwd, fakechroot_path, fakechroot_ptr); + narrow_chroot_path(cwd, fakechroot_path); return cwd; } @@ -1785,14 +1780,14 @@ char * getcwd (char *buf, size_t size) char * getwd (char *buf) { char *cwd; - char *fakechroot_path, *fakechroot_ptr; + char *fakechroot_path; if (next_getwd == NULL) fakechroot_init(); if ((cwd = next_getwd(buf)) == NULL) { return NULL; } - narrow_chroot_path(cwd, fakechroot_path, fakechroot_ptr); + narrow_chroot_path(cwd, fakechroot_path); return cwd; } @@ -1814,8 +1809,8 @@ int glob (const char *pattern, int flags, int (*errfunc) (const char *, int), gl { int rc; unsigned int i; - char tmp[FAKECHROOT_MAXPATH], *tmpptr; - char *fakechroot_path, *fakechroot_ptr; + char tmp[FAKECHROOT_MAXPATH]; + char *fakechroot_path; expand_chroot_path(pattern, fakechroot_path); @@ -1840,8 +1835,8 @@ int glob64 (const char *pattern, int flags, int (*errfunc) (const char *, int), { int rc; unsigned int i; - char tmp[FAKECHROOT_MAXPATH], *tmpptr; - char *fakechroot_path, *fakechroot_ptr; + char tmp[FAKECHROOT_MAXPATH]; + char *fakechroot_path; if (next_glob64 == NULL) fakechroot_init(); expand_chroot_path(pattern, fakechroot_path); @@ -2033,25 +2028,26 @@ int mkdir (const char *pathname, mode_t mode) char *mkdtemp (char *template) { char tmp[FAKECHROOT_MAXPATH], *oldtemplate, *ptr; - char *fakechroot_path, *fakechroot_ptr; + char *fakechroot_path; - oldtemplate = template; +// oldtemplate = template; - expand_chroot_path(template, fakechroot_path); +// expand_chroot_path(template, fakechroot_path); if (next_mkdtemp == NULL) fakechroot_init(); if (next_mkdtemp(template) == NULL) { return NULL; } - ptr = tmp; - strcpy(ptr, template); - narrow_chroot_path(ptr, fakechroot_path, fakechroot_ptr); - if (ptr == NULL) { - return NULL; - } - strcpy(oldtemplate, ptr); - return oldtemplate; +// ptr = tmp; +// strcpy(ptr, template); +// narrow_chroot_path(ptr, fakechroot_path); +// if (ptr == NULL) { +// return NULL; +// } +// strcpy(oldtemplate, ptr); +// DBGOUT("before returning from mkdtemp\n"); + return template; } #endif @@ -2085,7 +2081,7 @@ int mkstemp (char *template) { char tmp[FAKECHROOT_MAXPATH], *oldtemplate, *ptr; int fd; - char *fakechroot_path, *fakechroot_ptr; + char *fakechroot_path; oldtemplate = template; @@ -2098,7 +2094,7 @@ int mkstemp (char *template) } ptr = tmp; strcpy(ptr, template); - narrow_chroot_path(ptr, fakechroot_path, fakechroot_ptr); + narrow_chroot_path(ptr, fakechroot_path); if (ptr != NULL) { strcpy(oldtemplate, ptr); } @@ -2111,7 +2107,7 @@ int mkstemp64 (char *template) { char tmp[FAKECHROOT_MAXPATH], *oldtemplate, *ptr; int fd; - char *fakechroot_path, *fakechroot_ptr; + char *fakechroot_path; oldtemplate = template; @@ -2124,7 +2120,7 @@ int mkstemp64 (char *template) } ptr = tmp; strcpy(ptr, template); - narrow_chroot_path(ptr, fakechroot_path, fakechroot_ptr); + narrow_chroot_path(ptr, fakechroot_path); if (ptr != NULL) { strcpy(oldtemplate, ptr); } @@ -2258,12 +2254,12 @@ int readlink (const char *path, char *buf, READLINK_TYPE_ARG3) char *realpath (const char *name, char *resolved) { char *ptr; - char *fakechroot_path, *fakechroot_ptr; + char *fakechroot_path; if (next_realpath == NULL) fakechroot_init(); if ((ptr = next_realpath(name, resolved)) != NULL) { - narrow_chroot_path(ptr, fakechroot_path, fakechroot_ptr); + narrow_chroot_path(ptr, fakechroot_path); } return ptr; } @@ -2497,7 +2493,6 @@ int utimes (const char *filename, const struct timeval tv[2]) int uname(struct utsname *buf) { - char **t; if (next_uname == NULL) fakechroot_init(); if (next_uname(buf) < 0) { diff --git a/preload/sb_alien.c b/preload/sb_alien.c index 425978e..bedffb0 100644 --- a/preload/sb_alien.c +++ b/preload/sb_alien.c @@ -13,9 +13,6 @@ #define LD_LIB_PATH "/scratchbox/sarge/lib/:/scratchbox/sarge/lib/tls:/scratchbox/sarge/usr/lib" #define LD_SO "/scratchbox/sarge/lib/ld-linux.so.2" -extern int (*next_execve) (const char *filename, char *const argv [], char *const envp[]); - - static int endswith(char *haystack, char *needle) { return strcmp(&haystack[strlen(haystack)-strlen(needle)], needle)==0; @@ -115,46 +112,75 @@ char **post_args(char *fname) return padded_list(ret); } - int run_cputransparency(char *file, char **argv, char *const *envp) { - char **my_argv, **p; - char **my_envp; - char *tmp = NULL; - int i = 0; - - my_argv = (char **)calloc(elem_count(argv) + 4 + 1, sizeof(char *)); - my_envp = (char **)calloc(elem_count(envp) + 1, sizeof(char *)); + char *cputransp_bin, *target_root; + char *basec, *bname; - tmp = getenv("SBOX_CPUTRANSPARENCY_METHOD"); - if (!tmp) { + cputransp_bin = getenv("SBOX_CPUTRANSPARENCY_METHOD"); + if (!cputransp_bin) { fprintf(stderr, "SBOX_CPUTRANSPARENCY_METHOD not set, unable to execute the target binary\n"); return -1; } - my_argv[i++] = strdup(tmp); - my_argv[i++] = "-L"; - tmp = getenv("SBOX_TARGET_ROOT"); - if (!tmp) { + target_root = getenv("SBOX_TARGET_ROOT"); + if (!target_root) { fprintf(stderr, "SBOX_TARGET_ROOT not set, unable to execute the target binary\n"); return -1; } - my_argv[i++] = strdup(tmp); + + basec = strdup(cputransp_bin); + bname = basename(basec); + + if (strstr(bname, "qemu")) { + free(basec); + return run_qemu(cputransp_bin, target_root, file, argv, envp); + } else if (strstr(bname, "sbrsh")) { + free(basec); + return run_sbrsh(cputransp_bin, target_root, file, argv, envp); + } + + free(basec); + fprintf(stderr, "run_cputransparency() error: Unknown cputransparency method: [%s]\n", cputransp_bin); + return -1; +} + +int run_sbrsh(char *sbrsh_bin, char *target_root, char *file, char **argv, char *const *envp) +{ + return -1; +} + +int run_qemu(char *qemu_bin, char *target_root, char *file, char **argv, char *const *envp) +{ + char **my_argv, **p; + char **my_envp; + int i = 0; + //DBGOUT("about to run qemu: %s %s %s %s\n", qemu_bin, target_root, file, argv[0]); + my_argv = (char **)calloc(elem_count(argv) + 4 + 1, sizeof(char *)); + my_envp = (char **)calloc(elem_count((char **)envp) + 1, sizeof(char *)); + + my_argv[i++] = qemu_bin; + my_argv[i++] = "-L"; + + my_argv[i++] = target_root; my_argv[i++] = file; for (p=&argv[1]; *p; p++) { + //DBGOUT("processing args: [%s]\n", *p); my_argv[i++] = *p; } my_argv[i] = NULL; i = 0; for (p=(char **)envp; *p; p++) { - /* DBGOUT("ENV: [%s]\n", *p); */ + //DBGOUT("ENV: [%s]\n", *p); my_envp[i++] = *p; } my_envp[i] = NULL; - + //DBGOUT("just before running it [%s][%s]\n", my_argv[0], my_argv[1]); return next_execve(my_argv[0], my_argv, envp); + //DBGOUT("after running it\n"); + return -1; } int run_app(char *file, char **argv, char *const *envp) diff --git a/redir_scripts/main.lua b/redir_scripts/main.lua index cccae51..2c86ed9 100644 --- a/redir_scripts/main.lua +++ b/redir_scripts/main.lua @@ -49,6 +49,18 @@ if (t ~= nil) then -- from the chunk for i = 1,table.maxn(export_rules) do -- print("loading rule:" .. export_rules[i].binary) + -- fill in the default values + if (not export_rules[i].binary) then + export_rules[i].binary = ".*" + end + if (not export_rules[i].func_name) then + export_rules[i].func_name = ".*" + end + if (not export_rules[i].path) then + -- this is an error, report and exit + print("path not specified for a rule in " .. filename) + os.exit(1) + end table.insert(rules, export_rules[i]) end end diff --git a/redir_scripts/parts/default.lua b/redir_scripts/parts/default.lua index 85994ee..bb99b35 100644 --- a/redir_scripts/parts/default.lua +++ b/redir_scripts/parts/default.lua @@ -25,117 +25,101 @@ -- function(binary_name, func_name, work_dir, real_path, path, rule) -- and is expected to return the mapped path. rule argument contains -- the rule which triggered the function invocation. +-- Any undefined values are equivalent to nil values, except for +-- binary and func_name, in which case it means ".*" -- three exec rules for running binaries default_bin = { - binary = ".*", - func_name = ".*", - func_param = nil, path = "^/bin", - map_to = nil, - custom_map_func = nil } default_usrbin = { - binary = ".*", - func_name = ".*", - func_param = nil, path = "^/usr/bin", - map_to = nil, - custom_map_func = nil } default_usrlocalbin = { - binary = ".*", - func_name = ".*", - func_param = nil, path = "^/usr/local/bin", - map_to = nil, - custom_map_func = nil } default_home = { - binary = ".*", - func_name = ".*", - func_param = nil, path = "^/home", - map_to = nil, - custom_map_func = nil } default_proc = { - binary = ".*", - func_name = ".*", - func_param = nil, path = "^/proc", - map_to = nil, - custom_map_func = nil } default_tmp = { - binary = ".*", - func_name = ".*", - func_param = nil, path = "^/tmp", - map_to = nil, - custom_map_func = nil } default_etc = { - binary = ".*", - func_name = ".*", - func_param = nil, path = "^/etc", - map_to = nil, - custom_map_func = nil } default_scratchbox = { - binary = ".*", - func_name = ".*", - func_param = nil, path = "^/scratchbox", - map_to = nil, - custom_map_func = nil } default_dev = { - binary = ".*", - func_name = ".*", - func_param = nil, path = "^/dev", - map_to = nil, - custom_map_func = nil } libtool = { - binary = ".*", func_name = "exec.*", path = ".*libtool", map_to = "+/arch_tools/bin" } +libtoolm4 = { + path = ".*libtool.m4", + map_to = "+/arch_tools/share/aclocal" +} + +ltdlm4 = { + path = ".*ltdlm4", + map_to = "+/arch_tools/share/aclocal" +} + qemu = { binary = ".*qemu.*", - func_name = ".*", path = "^/", map_to = "=" } +autoconf = { + path = "^/usr/share/autoconf.*" +} + +automake = { + path = "^/usr/share/automake.*" +} + +aclocal = { + path = "^/usr/share/aclocal.*" +} + +perl = { + binary = ".*perl.*", + path = "^/usr/lib/perl.*" +} + -- catch all rule to map everything else to TARGETDIR/ default_rootdir = { - binary = ".*", - func_name = ".*", - func_param = nil, path = "^/", map_to = "=", - custom_map_func = nil } export_rules = { libtool, + libtoolm4, + ltdlm4, qemu, + autoconf, + automake, + aclocal, + perl, default_bin, default_usrbin, default_usrlocalbin, |