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; }
asmlinkage long sys_chroot(const char * filename) { int error; struct nameidata nd; error = __user_walk(filename, LOOKUP_POSITIVE | LOOKUP_FOLLOW | LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd); 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; }
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 = vfs_permission(&nd, 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.path); set_fs_altroot(); error = 0; dput_and_out: path_put(&nd.path); out: return error; }
/* * Note that a shared library must be both readable and executable due to * security reasons. * * Also note that we take the address to load from from the file itself. */ asmlinkage long sys_uselib(const char __user * library) { struct file * file; struct nameidata nd; int error; nd.intent.open.flags = FMODE_READ; error = __user_walk(library, LOOKUP_FOLLOW|LOOKUP_OPEN, &nd); if (error) goto out; error = -EINVAL; if (!S_ISREG(nd.dentry->d_inode->i_mode)) goto exit; error = permission(nd.dentry->d_inode, MAY_READ | MAY_EXEC, &nd); if (error) goto exit; file = dentry_open(nd.dentry, nd.mnt, O_RDONLY); error = PTR_ERR(file); if (IS_ERR(file)) goto out; error = -ENOEXEC; if(file->f_op) { struct linux_binfmt * fmt; read_lock(&binfmt_lock); for (fmt = formats ; fmt ; fmt = fmt->next) { if (!fmt->load_shlib) continue; if (!try_module_get(fmt->module)) continue; read_unlock(&binfmt_lock); error = fmt->load_shlib(file); read_lock(&binfmt_lock); put_binfmt(fmt); if (error != -ENOEXEC) break; } read_unlock(&binfmt_lock); } fput(file); out: return error; exit: path_release(&nd); goto out; }
/* * access() needs to use the real uid/gid, not the effective uid/gid. * We do this by temporarily clearing all FS-related capabilities and * switching the fsuid/fsgid around to the real ones. */ asmlinkage long sys_access(const char __user * filename, int mode) { struct nameidata nd; int old_fsuid, old_fsgid; kernel_cap_t old_cap; int res; if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */ return -EINVAL; old_fsuid = current->fsuid; old_fsgid = current->fsgid; old_cap = current->cap_effective; current->fsuid = current->uid; current->fsgid = current->gid; /* * Clear the capabilities if we switch to a non-root user * * FIXME: There is a race here against sys_capset. The * capabilities can change yet we will restore the old * value below. We should hold task_capabilities_lock, * but we cannot because user_path_walk can sleep. */ if (current->uid) cap_clear(current->cap_effective); else current->cap_effective = current->cap_permitted; res = __user_walk(filename, LOOKUP_FOLLOW|LOOKUP_ACCESS, &nd); if (!res) { res = permission(nd.dentry->d_inode, mode, &nd); /* SuS v2 requires we report a read only fs too */ if(!res && (mode & S_IWOTH) && IS_RDONLY(nd.dentry->d_inode) && !special_file(nd.dentry->d_inode->i_mode)) res = -EROFS; path_release(&nd); } current->fsuid = old_fsuid; current->fsgid = old_fsgid; current->cap_effective = old_cap; return res; }
asmlinkage long sys_chdir(const char * filename) { int error; struct nameidata nd; error = __user_walk(filename,LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY,&nd); if (error) goto out; error = permission(nd.dentry->d_inode,MAY_EXEC); if (error) goto dput_and_out; set_fs_pwd(current->fs, nd.mnt, nd.dentry); dput_and_out: path_release(&nd); out: return error; }
asmlinkage long sys_chdir(const char __user * filename) { struct nameidata nd; int error; error = __user_walk(filename, LOOKUP_FOLLOW|LOOKUP_DIRECTORY|LOOKUP_CHDIR, &nd); if (error) goto out; error = vfs_permission(&nd, MAY_EXEC); if (error) goto dput_and_out; set_fs_pwd(current->fs, nd.mnt, nd.dentry); dput_and_out: path_release(&nd); out: return error; }
asmlinkage long sys_chdir(const char __user * filename) { struct nameidata nd; int error; struct fs_struct *fs; error = __user_walk(filename, LOOKUP_FOLLOW|LOOKUP_DIRECTORY|LOOKUP_CHDIR, &nd); if (error) goto out; error = vfs_permission(d_get_inode_ro(nd.dentry), &nd, MAY_EXEC); if (error) goto dput_and_out; fs = tx_cache_get_fs(current); set_fs_pwd(fs, nd.mnt, parent(nd.dentry)); dput_and_out: path_release(&nd); out: return error; }