SYSCALL_DEFINE1(chroot, const char __user *, filename) { struct path path; int error; error = user_path_dir(filename, &path); if (error) goto out; error = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_CHDIR); if (error) goto dput_and_out; error = -EPERM; if (!capable(CAP_SYS_CHROOT)) goto dput_and_out; error = security_path_chroot(&path); if (error) goto dput_and_out; set_fs_root(current->fs, &path); error = 0; dput_and_out: path_put(&path); out: return error; }
asmlinkage long sys_chroot(const char __user * filename) { struct nameidata nd; struct fs_struct *fs; int error; error = __user_walk(filename, LOOKUP_FOLLOW | LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd); if (error) goto out; error = vfs_permission(d_get_inode_ro(nd.dentry), &nd, MAY_EXEC); if (error) goto dput_and_out; error = -EPERM; if (!capable(CAP_SYS_CHROOT)) goto dput_and_out; fs = tx_cache_get_fs(current); set_fs_root(fs, nd.mnt, parent(nd.dentry)); set_fs_altroot(); error = 0; dput_and_out: path_release(&nd); out: return error; }
SYSCALL_DEFINE1(chroot, const char __user *, filename) { struct path path; int error; error = user_path_dir(filename, &path); if (error) goto out; error = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_ACCESS); if (error) goto dput_and_out; error = -EPERM; if (!capable(CAP_SYS_CHROOT)) goto dput_and_out; if (gr_handle_chroot_chroot(path.dentry, path.mnt)) goto dput_and_out; if (gr_handle_chroot_caps(&path)) { error = -ENOMEM; goto dput_and_out; } set_fs_root(current->fs, &path); gr_handle_chroot_chdir(&path); error = 0; dput_and_out: path_put(&path); out: return error; }
asmlinkage long sys_chroot(const char * filename) { int error; struct nameidata nd; char *name; name = getname(filename); error = PTR_ERR(name); if (IS_ERR(name)) goto out; path_init(name, LOOKUP_POSITIVE | LOOKUP_FOLLOW | LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd); error = path_walk(name, &nd); putname(name); if (error) goto out; error = permission(nd.dentry->d_inode,MAY_EXEC); if (error) goto dput_and_out; error = -EPERM; if (!capable(CAP_SYS_CHROOT)) goto dput_and_out; set_fs_root(current->fs, nd.mnt, nd.dentry); set_fs_altroot(); error = 0; dput_and_out: path_release(&nd); out: return error; }
SYSCALL_DEFINE1(chroot, const char __user *, filename) { struct path path; int error; unsigned int lookup_flags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY; retry: error = user_path_at(AT_FDCWD, filename, lookup_flags, &path); if (error) goto out; error = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_CHDIR); if (error) goto dput_and_out; error = -EPERM; if (!nsown_capable(CAP_SYS_CHROOT)) goto dput_and_out; error = security_path_chroot(&path); if (error) goto dput_and_out; set_fs_root(current->fs, &path); error = 0; dput_and_out: path_put(&path); if (retry_estale(error, lookup_flags)) { lookup_flags |= LOOKUP_REVAL; goto retry; } out: return error; }
asmlinkage long sys_chroot(const char __user * filename) { struct nameidata nd; int error; error = __user_walk(filename, LOOKUP_FOLLOW | LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd); if (error) goto out; error = permission(nd.dentry->d_inode,MAY_EXEC,&nd); if (error) goto dput_and_out; error = -EPERM; if (!capable(CAP_SYS_CHROOT)) goto dput_and_out; set_fs_root(current->fs, nd.mnt, nd.dentry); set_fs_altroot(); error = 0; dput_and_out: path_release(&nd); out: return error; }
/** * Change current's root to configfs scheduler subsystem'root, and save * previous root in parameters. * * @param prev_root valid pointer to a struct path * * @return prev_rootmnt and prev_root are filled with the previous * root. They must be restored with chroot_restore, or * mntput/dput when not needed anymore. */ static void chroot_to_scheduler_subsystem(struct path *prev_root) { struct path new_root; /* * These two values won't change unless a pivot_root is running ... * but we assume that this can not happen. * Locking is more used for memory barriers than for anything else. */ read_lock(¤t->fs->lock); *prev_root = current->fs->root; path_get(prev_root); read_unlock(¤t->fs->lock); new_root.mnt = scheduler_fs_mount; new_root.dentry = krg_scheduler_subsys.su_group.cg_item.ci_dentry; set_fs_root(current->fs, &new_root); }
asmlinkage long sys_chroot(const char __user * filename) { struct path path; int error; error = user_path_dir(filename, &path); if (error) goto out; error = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_ACCESS); if (error) goto dput_and_out; error = -EPERM; if (!capable(CAP_SYS_CHROOT)) goto dput_and_out; set_fs_root(current->fs, &path); error = 0; dput_and_out: path_put(&path); out: return error; }
/* * Allocates utab entry (upd->fs) for mount/remount. This function should be * called *before* mount(2) syscall. The @fs is used as a read-only template. * * Returns: 0 on success, negative number on error, 1 if utabs update is * unnecessary. */ static int utab_new_entry(struct libmnt_update *upd, struct libmnt_fs *fs, unsigned long mountflags) { int rc = 0; const char *o = NULL, *a = NULL; char *u = NULL; assert(fs); assert(upd); assert(upd->fs == NULL); assert(!(mountflags & MS_MOVE)); DBG(UPDATE, mnt_debug("prepare utab entry")); o = mnt_fs_get_user_options(fs); a = mnt_fs_get_attributes(fs); upd->fs = NULL; if (o) { /* remove non-mtab options */ rc = mnt_optstr_get_options(o, &u, mnt_get_builtin_optmap(MNT_USERSPACE_MAP), MNT_NOMTAB); if (rc) goto err; } if (!u && !a) { DBG(UPDATE, mnt_debug("utab entry unnecessary (no options)")); return 1; } /* allocate the entry */ upd->fs = mnt_copy_fs(NULL, fs); if (!upd->fs) { rc = -ENOMEM; goto err; } rc = mnt_fs_set_options(upd->fs, u); if (rc) goto err; rc = mnt_fs_set_attributes(upd->fs, a); if (rc) goto err; if (!(mountflags & MS_REMOUNT)) { rc = set_fs_root(upd, fs, mountflags); if (rc) goto err; } free(u); DBG(UPDATE, mnt_debug("utab entry OK")); return 0; err: free(u); mnt_free_fs(upd->fs); upd->fs = NULL; return rc; }
static void chroot_restore(struct path *prev_root) { set_fs_root(current->fs, prev_root); path_put(prev_root); }