]> git.hungrycats.org Git - linux/commitdiff
[PATCH] add sys_setaltroot()
authorSeth Rohit <rohit.seth@intel.com>
Mon, 18 Oct 2004 15:52:07 +0000 (08:52 -0700)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Mon, 18 Oct 2004 15:52:07 +0000 (08:52 -0700)
Add a new system call setaltroot(2).

Currently, using the altroot feature is accessible only via the
set_personality() system call.  It is accessible to user space only if there
is more than one exec domain in the system.  This patch allows using the
altroot feature on systems where there is only one exec domain.

It is possible to work around the issue by adding a dummy exec domain, but it
was rejected for not being very elegant.

If this feature is implemented in userspace, it adds a 16% overhead on a test
case which greps for a single word in the kernel source tree.

Signed-off-by: Zou Nanhai <nanhai.zou@intel.com>
Signed-off-by: Gordon Jin <gordon.jin@intel.com>
Signed-off-by: Arun Sharma <arun.sharma@intel.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
arch/i386/kernel/entry.S
arch/ia64/kernel/entry.S
fs/namei.c
include/asm-i386/unistd.h
include/asm-ia64/unistd.h
include/linux/syscalls.h

index 3a8c31eda60d808e5cc68378cc922cae8a8b75a1..5c1f205e589bdcf136b379aa4f0475965fb437af 100644 (file)
@@ -901,5 +901,6 @@ ENTRY(sys_call_table)
        .long sys_mq_getsetattr
        .long sys_ni_syscall            /* reserved for kexec */
        .long sys_waitid
+       .long sys_setaltroot
 
 syscall_table_size=(.-sys_call_table)
index 1fe9575c7f7b50099aba6cf2957e9ec25faf84f7..f9f71a58814b67073666d7f258a55732f1b7da36 100644 (file)
@@ -1527,7 +1527,7 @@ sys_call_table:
        data8 sys_mq_getsetattr
        data8 sys_ni_syscall                    // reserved for kexec_load
        data8 sys_ni_syscall
-       data8 sys_ni_syscall                    // 1270
+       data8 sys_setaltroot                    // 1270
        data8 sys_ni_syscall
        data8 sys_ni_syscall
        data8 sys_ni_syscall
index 0a7647e41d9e6060fefd1876c59eac417135355c..32244e239583f7018b970e42a5c761bdb8002b1b 100644 (file)
@@ -897,20 +897,20 @@ static int __emul_lookup_dentry(const char *name, struct nameidata *nd)
        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(&current->fs->lock);
@@ -923,6 +923,58 @@ set_it:
                dput(olddentry);
                mntput(oldmnt);
        }
+       return 0;
+}
+
+void set_fs_altroot()
+{
+       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(&current->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)
index be8c6ac56c7c5f7a1207fb020fd9f756d3e278f5..2d9e45d2d5f893fc85cc1149d8694f1fe8c79c2d 100644 (file)
 #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_syscalls 285
+#define NR_syscalls 286
 
 /* user-visible error numbers are in the range -1 - -124: see <asm-i386/errno.h> */
 
index 84e6989d6ea0fdce3bf4673c647d2662689079e5..6384693300fd5ff4b6624d5ba16ca650f945539d 100644 (file)
 #define __NR_mq_getsetattr             1267
 #define __NR_kexec_load                        1268
 #define __NR_vserver                   1269
+#define __NR_setaltroot                        1270
 
 #ifdef __KERNEL__
 
index bd26cf298d9a95d297fe2ab115ad62a1bbfec96c..2a8c7faf2dcc6abe619826215474c488e5f9beb0 100644 (file)
@@ -489,6 +489,7 @@ asmlinkage long sys_nfsservctl(int cmd,
                                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);
 
 #endif