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);
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(¤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)
#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> */
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