===== arch/i386/kernel/entry.S 1.88 vs edited ===== --- 1.88/arch/i386/kernel/entry.S 2004-12-12 18:37:55 +00:00 +++ edited/arch/i386/kernel/entry.S 2004-12-20 13:08:02 +00:00 @@ -861,7 +861,7 @@ .long sys_mq_getsetattr .long sys_ni_syscall /* reserved for kexec */ .long sys_waitid - .long sys_ni_syscall /* 285 */ /* available */ + .long sys_setaltroot /* 285 */ .long sys_add_key .long sys_request_key .long sys_keyctl ===== arch/ia64/kernel/entry.S 1.69 vs edited ===== --- 1.69/arch/ia64/kernel/entry.S 2004-11-23 20:18:30 +00:00 +++ edited/arch/ia64/kernel/entry.S 2004-12-20 13:08:02 +00:00 @@ -1531,7 +1531,7 @@ data8 sys_add_key data8 sys_request_key data8 sys_keyctl - data8 sys_ni_syscall + data8 sys_setaltroot data8 sys_ni_syscall // 1275 data8 sys_ni_syscall data8 sys_ni_syscall ===== arch/ppc/kernel/misc.S 1.63 vs edited ===== --- 1.63/arch/ppc/kernel/misc.S 2004-10-22 10:27:40 +01:00 +++ edited/arch/ppc/kernel/misc.S 2004-12-20 13:08:02 +00:00 @@ -1450,3 +1450,4 @@ .long sys_add_key .long sys_request_key /* 270 */ .long sys_keyctl + .long sys_setaltroot ===== arch/ppc64/kernel/misc.S 1.93 vs edited ===== --- 1.93/arch/ppc64/kernel/misc.S 2004-11-11 08:23:03 +00:00 +++ edited/arch/ppc64/kernel/misc.S 2004-12-20 13:08:02 +00:00 @@ -966,7 +966,8 @@ .llong .sys32_add_key .llong .sys32_request_key .llong .compat_sys_keyctl - + .llong .sys_setaltroot + .balign 8 _GLOBAL(sys_call_table) .llong .sys_restart_syscall /* 0 */ @@ -1241,3 +1242,4 @@ .llong .sys_add_key .llong .sys_request_key /* 270 */ .llong .sys_keyctl + .llong .sys_setaltroot ===== arch/sparc/kernel/systbls.S 1.29 vs edited ===== --- 1.29/arch/sparc/kernel/systbls.S 2004-11-08 02:08:03 +00:00 +++ edited/arch/sparc/kernel/systbls.S 2004-12-20 13:08:02 +00:00 @@ -75,7 +75,7 @@ /*265*/ .long sys_timer_delete, sys_timer_create, sys_nis_syscall, sys_io_setup, sys_io_destroy /*270*/ .long sys_io_submit, sys_io_cancel, sys_io_getevents, sys_mq_open, sys_mq_unlink /*275*/ .long sys_mq_timedsend, sys_mq_timedreceive, sys_mq_notify, sys_mq_getsetattr, sys_waitid -/*280*/ .long sys_ni_syscall, sys_add_key, sys_request_key, sys_keyctl +/*280*/ .long sys_setaltroot, sys_add_key, sys_request_key, sys_keyctl #ifdef CONFIG_SUNOS_EMUL /* Now the SunOS syscall table. */ ===== arch/sparc64/kernel/systbls.S 1.66 vs edited ===== --- 1.66/arch/sparc64/kernel/systbls.S 2004-11-11 08:23:03 +00:00 +++ edited/arch/sparc64/kernel/systbls.S 2004-12-20 13:08:02 +00:00 @@ -76,7 +76,7 @@ .word sys_timer_delete, sys32_timer_create, sys_ni_syscall, compat_sys_io_setup, sys_io_destroy /*270*/ .word sys32_io_submit, sys_io_cancel, compat_sys_io_getevents, sys32_mq_open, sys_mq_unlink .word sys_mq_timedsend, sys_mq_timedreceive, compat_sys_mq_notify, compat_sys_mq_getsetattr, compat_sys_waitid -/*280*/ .word sys_ni_syscall, sys_add_key, sys_request_key, sys_keyctl +/*280*/ .word sys_setaltroot, sys_add_key, sys_request_key, sys_keyctl #endif /* CONFIG_COMPAT */ @@ -142,7 +142,7 @@ .word sys_timer_delete, sys_timer_create, sys_ni_syscall, sys_io_setup, sys_io_destroy /*270*/ .word sys_io_submit, sys_io_cancel, sys_io_getevents, sys_mq_open, sys_mq_unlink .word sys_mq_timedsend, sys_mq_timedreceive, sys_mq_notify, sys_mq_getsetattr, sys_waitid -/*280*/ .word sys_nis_syscall, sys_add_key, sys_request_key, sys_keyctl +/*280*/ .word sys_setaltroot, sys_add_key, sys_request_key, sys_keyctl #if defined(CONFIG_SUNOS_EMUL) || defined(CONFIG_SOLARIS_EMUL) || \ defined(CONFIG_SOLARIS_EMUL_MODULE) ===== fs/binfmt_elf.c 1.92 vs edited ===== --- 1.92/fs/binfmt_elf.c 2004-11-16 19:01:21 +00:00 +++ edited/fs/binfmt_elf.c 2004-12-20 13:08:02 +00:00 @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -626,7 +627,7 @@ */ SET_PERSONALITY(loc->elf_ex, ibcs2_interpreter); - interpreter = open_exec(elf_interpreter); + interpreter = open_exec(elf_interpreter, LOOKUP_NOALT); retval = PTR_ERR(interpreter); if (IS_ERR(interpreter)) goto out_free_interp; ===== fs/binfmt_em86.c 1.8 vs edited ===== --- 1.8/fs/binfmt_em86.c 2004-05-10 12:25:55 +01:00 +++ edited/fs/binfmt_em86.c 2004-12-20 13:08:02 +00:00 @@ -19,6 +19,7 @@ #include #include #include +#include #define EM86_INTERP "/usr/bin/em86" @@ -82,7 +83,7 @@ * Note that we use open_exec() as the name is now in kernel * space, and we don't need to copy it. */ - file = open_exec(interp); + file = open_exec(interp, LOOKUP_NOALT); if (IS_ERR(file)) return PTR_ERR(file); ===== fs/binfmt_flat.c 1.11 vs edited ===== --- 1.11/fs/binfmt_flat.c 2004-10-19 06:26:36 +01:00 +++ edited/fs/binfmt_flat.c 2004-12-20 13:08:02 +00:00 @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -774,7 +775,7 @@ /* Open the file up */ bprm.filename = buf; - bprm.file = open_exec(bprm.filename); + bprm.file = open_exec(bprm.filename, LOOKUP_NOALT); res = PTR_ERR(bprm.file); if (IS_ERR(bprm.file)) return res; ===== fs/binfmt_misc.c 1.30 vs edited ===== --- 1.30/fs/binfmt_misc.c 2004-06-29 15:43:10 +01:00 +++ edited/fs/binfmt_misc.c 2004-12-20 13:08:02 +00:00 @@ -179,7 +179,7 @@ bprm->interp = iname; /* for binfmt_script */ - interp_file = open_exec (iname); + interp_file = open_exec (iname, LOOKUP_NOALT); retval = PTR_ERR (interp_file); if (IS_ERR (interp_file)) goto _error; ===== fs/binfmt_script.c 1.9 vs edited ===== --- 1.9/fs/binfmt_script.c 2004-06-29 22:35:34 +01:00 +++ edited/fs/binfmt_script.c 2004-12-20 13:08:03 +00:00 @@ -85,9 +85,14 @@ /* * OK, now restart the process with the interpreter's dentry. */ - file = open_exec(interp); + file = open_exec(interp, 0); if (IS_ERR(file)) return PTR_ERR(file); + + /* If we had an altroot (which may be untrusted) we can reset it + to the default for the personality now that we've got the + script's interpreter itself open. */ + set_fs_altroot(); bprm->file = file; retval = prepare_binprm(bprm); ===== fs/compat.c 1.47 vs edited ===== --- 1.47/fs/compat.c 2004-12-10 17:57:46 +00:00 +++ edited/fs/compat.c 2004-12-20 13:08:03 +00:00 @@ -1393,7 +1393,7 @@ goto out_ret; memset(bprm, 0, sizeof(*bprm)); - file = open_exec(filename); + file = open_exec(filename, 0); retval = PTR_ERR(file); if (IS_ERR(file)) goto out_kfree; @@ -1447,6 +1447,7 @@ free_arg_pages(bprm); /* execve success */ + set_fs_altroot(); security_bprm_free(bprm); kfree(bprm); return retval; ===== fs/exec.c 1.146 vs edited ===== --- 1.146/fs/exec.c 2004-12-10 17:57:46 +00:00 +++ edited/fs/exec.c 2004-12-20 13:08:03 +00:00 @@ -473,14 +473,14 @@ #endif /* CONFIG_MMU */ -struct file *open_exec(const char *name) +struct file *open_exec(const char *name, int flags) { struct nameidata nd; int err; struct file *file; nd.intent.open.flags = FMODE_READ; - err = path_lookup(name, LOOKUP_FOLLOW|LOOKUP_OPEN, &nd); + err = path_lookup(name, LOOKUP_FOLLOW|LOOKUP_OPEN|flags, &nd); file = ERR_PTR(err); if (!err) { @@ -1007,7 +1007,7 @@ loader = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *); - file = open_exec("/sbin/loader"); + file = open_exec("/sbin/loader", LOOKUP_NOALT); retval = PTR_ERR(file); if (IS_ERR(file)) return retval; @@ -1100,7 +1100,7 @@ goto out_ret; memset(bprm, 0, sizeof(*bprm)); - file = open_exec(filename); + file = open_exec(filename, 0); retval = PTR_ERR(file); if (IS_ERR(file)) goto out_kfree; @@ -1155,6 +1155,7 @@ free_arg_pages(bprm); /* execve success */ + set_fs_altroot(); security_bprm_free(bprm); kfree(bprm); return retval; ===== fs/namei.c 1.115 vs edited ===== --- 1.115/fs/namei.c 2004-10-28 08:39:57 +01:00 +++ edited/fs/namei.c 2004-12-20 13:08:03 +00:00 @@ -913,20 +913,20 @@ return 1; } -void set_fs_altroot(void) +int __set_fs_altroot(const char *altroot) { - char *emul = __emul_prefix(); struct nameidata nd; struct vfsmount *mnt = NULL, *oldmnt; struct dentry *dentry = NULL, *olddentry; int err; - - if (!emul) + if (!altroot) goto set_it; - err = path_lookup(emul, LOOKUP_FOLLOW|LOOKUP_DIRECTORY|LOOKUP_NOALT, &nd); + err = path_lookup(altroot, LOOKUP_FOLLOW|LOOKUP_DIRECTORY|LOOKUP_NOALT, &nd); if (!err) { mnt = nd.mnt; dentry = nd.dentry; + } else { + return err; } set_it: write_lock(¤t->fs->lock); @@ -939,6 +939,58 @@ dput(olddentry); mntput(oldmnt); } + return 0; +} + +void set_fs_altroot(void) +{ + char *emul = __emul_prefix(); + + __set_fs_altroot(emul); +} + +asmlinkage long sys_setaltroot(const char __user * altroot) +{ + char *emul = NULL; + int ret; + + if (altroot) { + emul = getname(altroot); + if (IS_ERR(emul)) { + ret = PTR_ERR(emul); + goto out; + } + } + + if (atomic_read(¤t->fs->count) != 1) { + struct fs_struct *fsp, *ofsp; + + fsp = copy_fs_struct(current->fs); + if (fsp == NULL) { + ret = -ENOMEM; + goto out_putname; + } + + task_lock(current); + ofsp = current->fs; + current->fs = fsp; + task_unlock(current); + + put_fs_struct(ofsp); + } + + /* + * At that point we are guaranteed to be the sole owner of + * current->fs. + */ + + ret = __set_fs_altroot(emul); + +out_putname: + if (emul) + putname(emul); +out: + return ret; } int fastcall path_lookup(const char *name, unsigned int flags, struct nameidata *nd) ===== include/asm-i386/unistd.h 1.43 vs edited ===== --- 1.43/include/asm-i386/unistd.h 2004-10-24 11:32:46 +01:00 +++ edited/include/asm-i386/unistd.h 2004-12-20 13:08:41 +00:00 @@ -290,7 +290,7 @@ #define __NR_mq_getsetattr (__NR_mq_open+5) #define __NR_sys_kexec_load 283 #define __NR_waitid 284 -/* #define __NR_sys_setaltroot 285 */ +#define __NR_setaltroot 285 #define __NR_add_key 286 #define __NR_request_key 287 #define __NR_keyctl 288 ===== include/asm-ia64/unistd.h 1.53 vs edited ===== --- 1.53/include/asm-ia64/unistd.h 2004-11-23 20:18:59 +00:00 +++ edited/include/asm-ia64/unistd.h 2004-12-20 13:08:03 +00:00 @@ -263,6 +263,7 @@ #define __NR_add_key 1271 #define __NR_request_key 1272 #define __NR_keyctl 1273 +#define __NR_setaltroot 1274 #ifdef __KERNEL__ ===== include/asm-ppc/unistd.h 1.34 vs edited ===== --- 1.34/include/asm-ppc/unistd.h 2004-10-22 10:27:40 +01:00 +++ edited/include/asm-ppc/unistd.h 2004-12-20 13:08:03 +00:00 @@ -276,8 +276,9 @@ #define __NR_add_key 269 #define __NR_request_key 270 #define __NR_keyctl 271 +#define __NR_setaltroot 272 -#define __NR_syscalls 272 +#define __NR_syscalls 273 #define __NR(n) #n ===== include/asm-ppc64/unistd.h 1.36 vs edited ===== --- 1.36/include/asm-ppc64/unistd.h 2004-11-16 03:29:08 +00:00 +++ edited/include/asm-ppc64/unistd.h 2004-12-20 13:08:03 +00:00 @@ -282,8 +282,9 @@ #define __NR_add_key 269 #define __NR_request_key 270 #define __NR_keyctl 271 +#define __NR_setaltroot 272 -#define __NR_syscalls 272 +#define __NR_syscalls 273 #ifdef __KERNEL__ #define NR_syscalls __NR_syscalls #endif ===== include/asm-sparc64/unistd.h 1.36 vs edited ===== --- 1.36/include/asm-sparc64/unistd.h 2004-10-24 10:47:46 +01:00 +++ edited/include/asm-sparc64/unistd.h 2004-12-20 13:09:06 +00:00 @@ -298,7 +298,7 @@ #define __NR_mq_notify 277 #define __NR_mq_getsetattr 278 #define __NR_waitid 279 -/*#define __NR_sys_setaltroot 280 available (was setaltroot) */ +#define __NR_setaltroot 280 #define __NR_add_key 281 #define __NR_request_key 282 #define __NR_keyctl 283 ===== include/linux/fs.h 1.362 vs edited ===== --- 1.362/include/linux/fs.h 2004-10-29 09:14:03 +01:00 +++ edited/include/linux/fs.h 2004-12-20 13:08:03 +00:00 @@ -1376,7 +1376,7 @@ extern int may_open(struct nameidata *, int, int); extern int kernel_read(struct file *, unsigned long, char *, unsigned long); -extern struct file * open_exec(const char *); +extern struct file * open_exec(const char *, int); /* fs/dcache.c -- generic fs support functions */ extern int is_subdir(struct dentry *, struct dentry *); ===== include/linux/syscalls.h 1.17 vs edited ===== --- 1.17/include/linux/syscalls.h 2004-10-24 10:47:46 +01:00 +++ edited/include/linux/syscalls.h 2004-12-20 13:08:03 +00:00 @@ -490,6 +490,7 @@ void __user *res); asmlinkage long sys_syslog(int type, char __user *buf, int len); asmlinkage long sys_uselib(const char __user *library); +asmlinkage long sys_setaltroot(const char __user *altroot); asmlinkage long sys_ni_syscall(void); asmlinkage long sys_add_key(const char __user *_type,