-chroot and -su options.
PATCH 1/1 -chroot and -su options.
Quick and dirty patch to teach qemu application emulation how to chroot (and drop privs), so you don't have to pollute a target filesystem with host code, and/or figure out how to build qemu static in order to run a dynamic binary.
linux-user/main.c +26 -0
@@ -1905,6 +1905,10 @@ void usage(void)"-cpu model select CPU (-cpu ? for list)\n" "-drop-ld-preload drop LD_PRELOAD for target process\n" "\n" +"Root options:\n" +"-chroot dir chroot to dir\n" +"-su uid:gid set numeric user and group IDs\n" +"\n" "Debug options:\n" "-d options activate log (logfile=%s)\n" "-p pagesize set the host page size to 'pagesize'\n"
@@ -2011,6 +2015,28 @@ int main(int argc, char **argv) drop_ld_preload =1 ; }else if (!strcmp (r,"strace" )) { do_strace =1 ; + }else if (!strcmp (r,"chroot" )) { +if (chdir (argv[optind++]) ||chroot ("." )) { +fprintf (stderr,"Can't chroot to '%s' (are you root?)\n" , + argv[--optind]); +_exit (1 ); + } + }else if (!strcmp (r,"su" )) { +int temp; +char *gid =strchr (argv[optind],':' ); +if (gid) { + temp =atoi (++gid); +if (setresgid (temp, temp, temp)) { +fprintf (stderr,"Can't set gid to %d (are you root?)\n" , + temp); +_exit (1 ); + } + } + temp =atoi (argv[optind++]); +if (setresuid (temp, temp, temp)) { +fprintf (stderr,"Can't set uid to %d (are you root?)\n" , temp); +_exit (1 ); + } }else {usage ();
Signature · 2 lines
"One of my most productive days was throwing away 1000 lines of code." - Ken Thompson.
Quoted 3 lines · Rob Landley
Quick and dirty patch to teach qemu application emulation how to chroot (and drop privs), so you don't have to pollute a target filesystem with host code, and/or figure out how to build qemu static in order to run a dynamic binary.
Hi Rob,
Right, doing the chroot from within qemu avoids the issue with polluting the target/. Thanks for the example.
The chroot approach still suffers from the need of initially having higher privileges. Personally, I still prefer the sysroot option and avoid that need but either way helps me.
Best regards
Signature · 2 lines
Edgar E. Iglesias Axis Communications AB
Quoted 8 lines · On Tuesday 04 March 2008 05:22:12 you wrote:
Quoted 4 lines · Rob Landley
Quick and dirty patch to teach qemu application emulation how to chroot (and drop privs), so you don't have to pollute a target filesystem with host code, and/or figure out how to build qemu static in order to run a dynamic binary.
Hi Rob,
Quoted 8 lines
Right, doing the chroot from within qemu avoids the issue with polluting the target/. Thanks for the example.
The chroot approach still suffers from the need of initially having higher privileges. Personally, I still prefer the sysroot option and avoid that need but either way helps me.
Best regards
Which sysroot option? (I may have missed a patch, I'm a month behind on the list. This is just something I've meant to submit for... about a year, I think.)
You can also teach a bunch of different qemu syscalls (open, unlink, mmap, exec, fcntl, and 3 dozen others...) to append a prefix to its path, and perhaps try to prevent them from playing games with symlinks or ".." to break out of that subdir. But that's a much, much, much more extensive/intrusive patch.
Rob
Signature · 2 lines
"One of my most productive days was throwing away 1000 lines of code." - Ken Thompson.
Quoted 22 lines · Rob Landley
Quoted 8 lines · On Tuesday 04 March 2008 05:22:12 you wrote:
Quoted 4 lines · Rob Landley
Quick and dirty patch to teach qemu application emulation how to chroot (and drop privs), so you don't have to pollute a target filesystem with host code, and/or figure out how to build qemu static in order to run a dynamic binary.
Hi Rob,
Quoted 8 lines
Right, doing the chroot from within qemu avoids the issue with polluting the target/. Thanks for the example.
The chroot approach still suffers from the need of initially having higher privileges. Personally, I still prefer the sysroot option and avoid that need but either way helps me.
Best regards
Which sysroot option? (I may have missed a patch, I'm a month behind on the list. This is just something I've meant to submit for... about a year, I think.)
Quoted 5 lines
You can also teach a bunch of different qemu syscalls (open, unlink, mmap, exec, fcntl, and 3 dozen others...) to append a prefix to its path, and perhaps try to prevent them from playing games with symlinks or ".." to break out of that subdir. But that's a much, much, much more extensive/intrusive patch.
Hi,
This is the updated example from my local git of how it could work, it only maps absolute paths.
I don't think taking care of relative paths involves much more code but so far this behaviour has been enough for me. The sim simulators in GDB have a similar --sysroot option which I beleive behaves very similar (or equal).
Please note that I'm not trying to jail in a program for security purposes, just for test and debug purposes.
My original post can be found here:
http://lists.gnu.org/archive/html/qemu-devel/2008-03/msg00027.html
Best regards
Signature · 2 lines
Edgar E. Iglesias Axis Communications AB
linux-user/main.c +8 -1
@@ -1904,6 +1904,7 @@ void usage(void)"-h print this help\n" "-g port wait gdb connection to port\n" "-L path set the elf interpreter prefix (default=%s)\n" +"-sysroot Root for system calls with absolute file-names\n" "-s size set the stack size in bytes (default=%ld)\n" "-cpu model select CPU (-cpu ? for list)\n" "-drop-ld-preload drop LD_PRELOAD for target process\n"
@@ -1943,6 +1944,7 @@ int main(int argc, char **argv)int gdbstub_port =0 ;int drop_ld_preload =0 , environ_count =0 ;char **target_environ, **wrk, **dst; +char *sysroot =NULL ;if (argc <=1 )usage ();
@@ -2014,6 +2016,8 @@ int main(int argc, char **argv) drop_ld_preload =1 ; }else if (!strcmp (r,"strace" )) { do_strace =1 ; + }else if (!strcmp (r,"sysroot" )) { + sysroot = argv[optind++]; }else {usage ();
@@ -2030,7 +2034,10 @@ int main(int argc, char **argv)memset (info,0 ,sizeof (struct image_info ));/* Scan interp_prefix dir for replacement files. */ -init_paths (interp_prefix); +if (sysroot) +init_paths (sysroot,1 ); +else +init_paths (interp_prefix,0 );if (cpu_model ==NULL ) {#if defined(TARGET_I386 )
linux-user/path.c +29 -10
@@ -25,6 +25,8 @@ struct pathelem };static struct pathelem *base; +static int use_sysroot; +static size_t sysroot_pathlen;/* First N chars of S1 match S2, and S2 is N chars long. */ static int strneq (const char *s1,unsigned int n,const char *s2)
@@ -118,7 +120,7 @@ follow_path(const struct pathelem *cursor, const char *name)return NULL ; } -void init_paths (const char *prefix) +void init_paths (const char *prefix,int sysroot) {char pref_buf[PATH_MAX ];
@@ -135,15 +137,25 @@ void init_paths(const char *prefix)strcat (pref_buf, prefix);free (cwd); }else -strcpy (pref_buf,prefix +1 ); - - base =new_entry ("" ,NULL , pref_buf); - base =add_dir_maybe (base); -if (base->num_entries ==0 ) { -free (base); - base =NULL ; +strcpy (pref_buf, prefix +1 ); + + use_sysroot = sysroot; +if (sysroot) { + base =malloc (sizeof (*base)); + sysroot_pathlen =strlen (pref_buf); + base->pathname =malloc (sysroot_pathlen +PATH_MAX +1 ); + base->pathname[0 ] ='/' ; +memcpy (base->pathname +1 , pref_buf, sysroot_pathlen); + sysroot_pathlen++; }else { -set_parents (base, base); + base =new_entry ("" ,NULL , pref_buf); + base =add_dir_maybe (base); +if (base->num_entries ==0 ) { +free (base); + base =NULL ; + }else { +set_parents (base, base); + } } }
@@ -155,5 +167,12 @@ const char *path(const char *name)if (!base || name[0 ] !='/' )return name; -return follow_path (base, name) ?: name; +if (use_sysroot) { +size_t name_len; +/* Prepend base->pathname to name. */ + name_len =strlen (name); +memcpy (base->pathname + sysroot_pathlen, name, name_len +1 ); +return base->pathname; + }else +return follow_path (base, name) ?: name; }
linux-user/qemu.h +1 -1
@@ -166,7 +166,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,void gemu_log (const char *fmt, ...) __attribute__((format (printf,1 ,2 )));extern CPUState *global_env;void cpu_loop (CPUState *env); -void init_paths (const char *prefix); +void init_paths (const char *prefix,int sysroot);const char *path (const char *pathname);char *target_strerror (int err);
Quoted 31 lines · On Wednesday 05 March 2008 01:54:08 Edgar E. Iglesias wrote:
Quoted 22 lines · Rob Landley
Quoted 8 lines · On Tuesday 04 March 2008 05:22:12 you wrote:
Quoted 4 lines · Rob Landley
Quick and dirty patch to teach qemu application emulation how to chroot (and drop privs), so you don't have to pollute a target filesystem with host code, and/or figure out how to build qemu static in order to run a dynamic binary.
Hi Rob,
Quoted 8 lines
Right, doing the chroot from within qemu avoids the issue with polluting the target/. Thanks for the example.
The chroot approach still suffers from the need of initially having higher privileges. Personally, I still prefer the sysroot option and avoid that need but either way helps me.
Best regards
Which sysroot option? (I may have missed a patch, I'm a month behind on the list. This is just something I've meant to submit for... about a year, I think.)
Quoted 5 lines
You can also teach a bunch of different qemu syscalls (open, unlink, mmap, exec, fcntl, and 3 dozen others...) to append a prefix to its path, and perhaps try to prevent them from playing games with symlinks or ".." to break out of that subdir. But that's a much, much, much more extensive/intrusive patch.
Hi,
Quoted 8 lines
This is the updated example from my local git of how it could work, it only maps absolute paths. I don't think taking care of relative paths involves much more code but so far this behaviour has been enough for me. The sim simulators in GDB have a similar --sysroot option which I beleive behaves very similar (or equal).
Please note that I'm not trying to jail in a program for security purposes, just for test and debug purposes.
Yeah, linux-user/path.c does seem to be trying to filter the paths. (Does -L do more than just adjust the elf interpreter prefix? The syscalls are wrapped in calls to path() which _could_ do something interesting, but doesn't. (And freeing the string would probably require a static pointer so the next call frees the previous one.)
Even then, attempting to deal with things like symlinks that point to absolute paths would be quite a headache, and considering the default busybox install does exactly that, it's not exactly an unheard of corner case...
Rob
Signature · 2 lines
"One of my most productive days was throwing away 1000 lines of code." - Ken Thompson.
Quoted 38 lines · Rob Landley
Quoted 37 lines · On Wednesday 05 March 2008 01:54:08 Edgar E. Iglesias wrote:
Quoted 22 lines · Rob Landley
Quoted 8 lines · On Tuesday 04 March 2008 05:22:12 you wrote:
Quoted 4 lines · Rob Landley
Quick and dirty patch to teach qemu application emulation how to chroot (and drop privs), so you don't have to pollute a target filesystem with host code, and/or figure out how to build qemu static in order to run a dynamic binary.
Hi Rob,
Quoted 8 lines
Right, doing the chroot from within qemu avoids the issue with polluting the target/. Thanks for the example.
The chroot approach still suffers from the need of initially having higher privileges. Personally, I still prefer the sysroot option and avoid that need but either way helps me.
Best regards
Which sysroot option? (I may have missed a patch, I'm a month behind on the list. This is just something I've meant to submit for... about a year, I think.)
Quoted 5 lines
You can also teach a bunch of different qemu syscalls (open, unlink, mmap, exec, fcntl, and 3 dozen others...) to append a prefix to its path, and perhaps try to prevent them from playing games with symlinks or ".." to break out of that subdir. But that's a much, much, much more extensive/intrusive patch.
Hi,
This is the updated example from my local git of how it could work, it only maps absolute paths. I don't think taking care of relative paths involves much more code but so far this behaviour has been enough for me. The sim simulators in GDB have a similar --sysroot option which I beleive behaves very similar (or equal).
Quoted 5 lines
Quoted 2 lines
Please note that I'm not trying to jail in a program for security purposes, just for test and debug purposes.
Yeah,
linux-user/path.cdoes seem to be trying to filter the paths. (Does -L do more than just adjust the elf interpreter prefix? The syscalls are
Yes, -L tries do map all paths. It's behavior depends on wether the file exists on the target dir or not. If the file does not exist on the target dir, I beleive it maps to the host fs. Also, it doesn't do anything with relative paths.
Quoted 7 lines
wrapped in calls to
path()which _could_ do something interesting, but doesn't. (And freeing the string would probably require a static pointer so the next call frees the previous one.)Even then, attempting to deal with things like symlinks that point to absolute paths would be quite a headache, and considering the default busybox install does exactly that, it's not exactly an unheard of corner case...
Hmm, our (axis) version of busybox uses relative paths for all symbolic links. It might be patched though, I haven't dug very deep. But otherwise yes, absolute symbolic links need to be considered with the sysroot approach.
Best regards
Signature · 2 lines
Edgar E. Iglesias Axis Communications AB
Quoted 9 lines · On Friday 14 March 2008 09:08:57 Edgar E. Iglesias wrote:
Quoted 4 lines
Even then, attempting to deal with things like symlinks that point to absolute paths would be quite a headache, and considering the default busybox install does exactly that, it's not exactly an unheard of corner case...
Hmm, our (axis) version of busybox uses relative paths for all symbolic links. It might be patched though, I haven't dug very deep. But otherwise yes, absolute symbolic links need to be considered with the sysroot approach.
It might help if you make "--sysroot" a synonym for "-L" and _document_ that it affects all application emulation syscalls. But also document that it's not a full solution. (In addition to relative paths, remember that symlinks can resolve to other symlinks, and that every path component can be a symlink so in a path like "one/two/three" if "two" is a symlink
to "../walrus/fruitbasket" and "walrus" is another symlink.... Implementing "readlink -f" isn't trivial. I should know, I worked out how to do it properly for toybox but haven't had time yet.)
Probably the easiest thing to do for the moment is have both the --chroot and the --sysroot options.
Quoted 1 line
Best regards
Rob
Signature · 2 lines
"One of my most productive days was throwing away 1000 lines of code." - Ken Thompson.
Hi,
Quoted 3 lines · Rob Landley
Quick and dirty patch to teach qemu application emulation how to chroot (and
drop privs), so you don't have to pollute a target filesystem with host code, and/or figure out how to build qemu static in order to run a dynamic binary.
I tested your patch, but it doesn't seem to work when the application forks a new process (the new process is attempted to run as a native host executable, instead of with qemu). Is that expected?
I tried enabling binfmt for it, but then qemu needs to be static, defeating the purpose of this option.
Regards,
Signature · 3 lines
Anderson Lizardo Instituto Nokia de Tecnologia Manaus - Brazil