static int cp_compat_stat(struct kstat *stat, struct compat_stat __user *ubuf) { struct compat_stat tmp; if (!old_valid_dev(stat->dev) || !old_valid_dev(stat->rdev)) return -EOVERFLOW; memset(&tmp, 0, sizeof(tmp)); tmp.st_dev = old_encode_dev(stat->dev); tmp.st_ino = stat->ino; if (sizeof(tmp.st_ino) < sizeof(stat->ino) && tmp.st_ino != stat->ino) return -EOVERFLOW; tmp.st_mode = stat->mode; tmp.st_nlink = stat->nlink; if (tmp.st_nlink != stat->nlink) return -EOVERFLOW; SET_UID(tmp.st_uid, from_kuid_munged(current_user_ns(), stat->uid)); SET_GID(tmp.st_gid, from_kgid_munged(current_user_ns(), stat->gid)); tmp.st_rdev = old_encode_dev(stat->rdev); if ((u64) stat->size > MAX_NON_LFS) return -EOVERFLOW; tmp.st_size = stat->size; tmp.st_atime = stat->atime.tv_sec; tmp.st_atime_nsec = stat->atime.tv_nsec; tmp.st_mtime = stat->mtime.tv_sec; tmp.st_mtime_nsec = stat->mtime.tv_nsec; tmp.st_ctime = stat->ctime.tv_sec; tmp.st_ctime_nsec = stat->ctime.tv_nsec; tmp.st_blocks = stat->blocks; tmp.st_blksize = stat->blksize; return copy_to_user(ubuf, &tmp, sizeof(tmp)) ? -EFAULT : 0; }
static int check_quotactl_permission(struct super_block *sb, int type, int cmd, qid_t id) { switch (cmd) { /* these commands do not require any special privilegues */ case Q_GETFMT: case Q_SYNC: case Q_GETINFO: case Q_XGETQSTAT: case Q_XGETQSTATV: case Q_XQUOTASYNC: break; /* allow to query information for dquots we "own" */ case Q_GETQUOTA: case Q_XGETQUOTA: if ((type == USRQUOTA && uid_eq(current_euid(), make_kuid(current_user_ns(), id))) || (type == GRPQUOTA && in_egroup_p(make_kgid(current_user_ns(), id)))) break; /*FALLTHROUGH*/ default: if (!capable(CAP_SYS_ADMIN)) return -EPERM; } return security_quotactl(cmd, type, id, sb); }
static int cp_compat_stat64(struct kstat *stat, struct compat_stat64 __user *statbuf) { int err; err = put_user(huge_encode_dev(stat->dev), &statbuf->st_dev); err |= put_user(stat->ino, &statbuf->st_ino); err |= put_user(stat->mode, &statbuf->st_mode); err |= put_user(stat->nlink, &statbuf->st_nlink); err |= put_user(from_kuid_munged(current_user_ns(), stat->uid), &statbuf->st_uid); err |= put_user(from_kgid_munged(current_user_ns(), stat->gid), &statbuf->st_gid); err |= put_user(huge_encode_dev(stat->rdev), &statbuf->st_rdev); err |= put_user(0, (unsigned long __user *) &statbuf->__pad3[0]); err |= put_user(stat->size, &statbuf->st_size); err |= put_user(stat->blksize, &statbuf->st_blksize); err |= put_user(0, (unsigned int __user *) &statbuf->__pad4[0]); err |= put_user(0, (unsigned int __user *) &statbuf->__pad4[4]); err |= put_user(stat->blocks, &statbuf->st_blocks); err |= put_user(stat->atime.tv_sec, &statbuf->st_atime); err |= put_user(stat->atime.tv_nsec, &statbuf->st_atime_nsec); err |= put_user(stat->mtime.tv_sec, &statbuf->st_mtime); err |= put_user(stat->mtime.tv_nsec, &statbuf->st_mtime_nsec); err |= put_user(stat->ctime.tv_sec, &statbuf->st_ctime); err |= put_user(stat->ctime.tv_nsec, &statbuf->st_ctime_nsec); err |= put_user(0, &statbuf->__unused4); err |= put_user(0, &statbuf->__unused5); return err; }
static long cp_oldabi_stat64(struct kstat *stat, struct oldabi_stat64 __user *statbuf) { struct oldabi_stat64 tmp; tmp.st_dev = huge_encode_dev(stat->dev); tmp.__pad1 = 0; tmp.__st_ino = stat->ino; tmp.st_mode = stat->mode; tmp.st_nlink = stat->nlink; tmp.st_uid = from_kuid_munged(current_user_ns(), stat->uid); tmp.st_gid = from_kgid_munged(current_user_ns(), stat->gid); tmp.st_rdev = huge_encode_dev(stat->rdev); tmp.st_size = stat->size; tmp.st_blocks = stat->blocks; tmp.__pad2 = 0; tmp.st_blksize = stat->blksize; tmp.st_atime = stat->atime.tv_sec; tmp.st_atime_nsec = stat->atime.tv_nsec; tmp.st_mtime = stat->mtime.tv_sec; tmp.st_mtime_nsec = stat->mtime.tv_nsec; tmp.st_ctime = stat->ctime.tv_sec; tmp.st_ctime_nsec = stat->ctime.tv_nsec; tmp.st_ino = stat->ino; return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0; }
static long cp_new_stat64(struct kstat *stat, struct stat64 __user *statbuf) { struct stat64 tmp; INIT_STRUCT_STAT64_PADDING(tmp); #ifdef CONFIG_MIPS /* mips has weird padding, so we don't get 64 bits there */ tmp.st_dev = new_encode_dev(stat->dev); tmp.st_rdev = new_encode_dev(stat->rdev); #else tmp.st_dev = huge_encode_dev(stat->dev); tmp.st_rdev = huge_encode_dev(stat->rdev); #endif tmp.st_ino = stat->ino; if (sizeof(tmp.st_ino) < sizeof(stat->ino) && tmp.st_ino != stat->ino) return -EOVERFLOW; #ifdef STAT64_HAS_BROKEN_ST_INO tmp.__st_ino = stat->ino; #endif tmp.st_mode = stat->mode; tmp.st_nlink = stat->nlink; tmp.st_uid = from_kuid_munged(current_user_ns(), stat->uid); tmp.st_gid = from_kgid_munged(current_user_ns(), stat->gid); tmp.st_atime = stat->atime.tv_sec; tmp.st_atime_nsec = stat->atime.tv_nsec; tmp.st_mtime = stat->mtime.tv_sec; tmp.st_mtime_nsec = stat->mtime.tv_nsec; tmp.st_ctime = stat->ctime.tv_sec; tmp.st_ctime_nsec = stat->ctime.tv_nsec; tmp.st_size = stat->size; tmp.st_blocks = stat->blocks; tmp.st_blksize = stat->blksize; return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0; }
static int cp_hpux_stat(struct kstat *stat, struct hpux_stat64 __user *statbuf) { struct hpux_stat64 tmp; /* we probably want a different split here - is hpux 12:20? */ if (!new_valid_dev(stat->dev) || !new_valid_dev(stat->rdev)) return -EOVERFLOW; memset(&tmp, 0, sizeof(tmp)); tmp.st_dev = new_encode_dev(stat->dev); tmp.st_ino = stat->ino; tmp.st_mode = stat->mode; tmp.st_nlink = stat->nlink; tmp.st_uid = from_kuid_munged(current_user_ns(), stat->uid); tmp.st_gid = from_kgid_munged(current_user_ns(), stat->gid); tmp.st_rdev = new_encode_dev(stat->rdev); tmp.st_size = stat->size; tmp.st_atime = stat->atime.tv_sec; tmp.st_mtime = stat->mtime.tv_sec; tmp.st_ctime = stat->ctime.tv_sec; tmp.st_blocks = stat->blocks; tmp.st_blksize = stat->blksize; return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0; }
/* * Return the uid and gid of the last request for the mount * * When reconstructing an autofs mount tree with active mounts * we need to re-connect to mounts that may have used the original * process uid and gid (or string variations of them) for mount * lookups within the map entry. */ static int autofs_dev_ioctl_requester(struct file *fp, struct autofs_sb_info *sbi, struct autofs_dev_ioctl *param) { struct autofs_info *ino; struct path path; dev_t devid; int err = -ENOENT; /* param->path has been checked in validate_dev_ioctl() */ devid = sbi->sb->s_dev; param->requester.uid = param->requester.gid = -1; err = find_autofs_mount(param->path, &path, test_by_dev, &devid); if (err) goto out; ino = autofs_dentry_ino(path.dentry); if (ino) { err = 0; autofs_expire_wait(&path, 0); spin_lock(&sbi->fs_lock); param->requester.uid = from_kuid_munged(current_user_ns(), ino->uid); param->requester.gid = from_kgid_munged(current_user_ns(), ino->gid); spin_unlock(&sbi->fs_lock); } path_put(&path); out: return err; }
/* * Another set for IA32/LFS -- x86_64 struct stat is different due to * support for 64bit inode numbers. */ static int cp_stat64(struct stat64 __user *ubuf, struct kstat *stat) { typeof(ubuf->st_uid) uid = 0; typeof(ubuf->st_gid) gid = 0; SET_UID(uid, from_kuid_munged(current_user_ns(), stat->uid)); SET_GID(gid, from_kgid_munged(current_user_ns(), stat->gid)); if (!access_ok(VERIFY_WRITE, ubuf, sizeof(struct stat64)) || __put_user(huge_encode_dev(stat->dev), &ubuf->st_dev) || __put_user(stat->ino, &ubuf->__st_ino) || __put_user(stat->ino, &ubuf->st_ino) || __put_user(stat->mode, &ubuf->st_mode) || __put_user(stat->nlink, &ubuf->st_nlink) || __put_user(uid, &ubuf->st_uid) || __put_user(gid, &ubuf->st_gid) || __put_user(huge_encode_dev(stat->rdev), &ubuf->st_rdev) || __put_user(stat->size, &ubuf->st_size) || __put_user(stat->atime.tv_sec, &ubuf->st_atime) || __put_user(stat->atime.tv_nsec, &ubuf->st_atime_nsec) || __put_user(stat->mtime.tv_sec, &ubuf->st_mtime) || __put_user(stat->mtime.tv_nsec, &ubuf->st_mtime_nsec) || __put_user(stat->ctime.tv_sec, &ubuf->st_ctime) || __put_user(stat->ctime.tv_nsec, &ubuf->st_ctime_nsec) || __put_user(stat->blksize, &ubuf->st_blksize) || __put_user(stat->blocks, &ubuf->st_blocks)) return -EFAULT; return 0; }
static int chown_common(struct path *path, uid_t user, gid_t group) { struct inode *inode = path->dentry->d_inode; int error; struct iattr newattrs; kuid_t uid; kgid_t gid; uid = make_kuid(current_user_ns(), user); gid = make_kgid(current_user_ns(), group); newattrs.ia_valid = ATTR_CTIME; if (user != (uid_t) -1) { if (!uid_valid(uid)) return -EINVAL; newattrs.ia_valid |= ATTR_UID; newattrs.ia_uid = uid; } if (group != (gid_t) -1) { if (!gid_valid(gid)) return -EINVAL; newattrs.ia_valid |= ATTR_GID; newattrs.ia_gid = gid; } if (!S_ISDIR(inode->i_mode)) newattrs.ia_valid |= ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV; mutex_lock(&inode->i_mutex); error = security_path_chown(path, uid, gid); if (!error) error = notify_change(path->dentry, &newattrs); mutex_unlock(&inode->i_mutex); return error; }
static int ovl_whiteout(struct dentry *upperdir, struct dentry *dentry) { int err; struct dentry *newdentry; const struct cred *old_cred; struct cred *override_cred; /* FIXME: recheck lower dentry to see if whiteout is really needed */ err = -ENOMEM; override_cred = prepare_kernel_cred(NULL); if (!override_cred) goto out; override_cred->fsuid = make_kuid(current_user_ns(), 0); if (!uid_valid(override_cred->fsuid)) override_cred->fsuid = GLOBAL_ROOT_UID; override_cred->fsgid = make_kgid(current_user_ns(), 0); if (!gid_valid(override_cred->fsgid)) override_cred->fsgid = GLOBAL_ROOT_GID; old_cred = override_creds(override_cred); newdentry = lookup_one_len(dentry->d_name.name, upperdir, dentry->d_name.len); err = PTR_ERR(newdentry); if (IS_ERR(newdentry)) goto out_put_cred; /* Just been removed within the same locked region */ WARN_ON(newdentry->d_inode); err = vfs_symlink(upperdir->d_inode, newdentry, ovl_whiteout_symlink); if (err) goto out_dput; ovl_dentry_version_inc(dentry->d_parent); err = vfs_setxattr(newdentry, ovl_whiteout_xattr, "y", 1, 0); if (err) vfs_unlink(upperdir->d_inode, newdentry, NULL); out_dput: dput(newdentry); out_put_cred: revert_creds(old_cred); put_cred(override_cred); out: if (err) { /* * There's no way to recover from failure to whiteout. * What should we do? Log a big fat error and... ? */ pr_err("overlayfs: ERROR - failed to whiteout '%s'\n", dentry->d_name.name); } return err; }
static int mknod_ptmx(struct super_block *sb) { int mode; int rc = -ENOMEM; struct dentry *dentry; struct inode *inode; struct dentry *root = sb->s_root; struct pts_fs_info *fsi = DEVPTS_SB(sb); struct pts_mount_opts *opts = &fsi->mount_opts; kuid_t root_uid; kgid_t root_gid; root_uid = make_kuid(current_user_ns(), 0); root_gid = make_kgid(current_user_ns(), 0); if (!uid_valid(root_uid) || !gid_valid(root_gid)) return -EINVAL; mutex_lock(&root->d_inode->i_mutex); /* If we have already created ptmx node, return */ if (fsi->ptmx_dentry) { rc = 0; goto out; } dentry = d_alloc_name(root, "ptmx"); if (!dentry) { printk(KERN_NOTICE "Unable to alloc dentry for ptmx node\n"); goto out; } /* * Create a new 'ptmx' node in this mount of devpts. */ inode = new_inode(sb); if (!inode) { printk(KERN_ERR "Unable to alloc inode for ptmx node\n"); dput(dentry); goto out; } inode->i_ino = 2; inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; mode = S_IFCHR|opts->ptmxmode; init_special_inode(inode, mode, MKDEV(TTYAUX_MAJOR, 2)); inode->i_uid = root_uid; inode->i_gid = root_gid; d_add(dentry, inode); fsi->ptmx_dentry = dentry; rc = 0; out: mutex_unlock(&root->d_inode->i_mutex); return rc; }
/** * ecryptfs_miscdev_open * @inode: inode of miscdev handle (ignored) * @file: file for miscdev handle (ignored) * * Returns zero on success; non-zero otherwise */ static int ecryptfs_miscdev_open(struct inode *inode, struct file *file) { struct ecryptfs_daemon *daemon = NULL; uid_t euid = current_euid(); int rc; mutex_lock(&ecryptfs_daemon_hash_mux); rc = try_module_get(THIS_MODULE); if (rc == 0) { rc = -EIO; printk(KERN_ERR "%s: Error attempting to increment module use " "count; rc = [%d]\n", __func__, rc); goto out_unlock_daemon_list; } rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns()); if (rc || !daemon) { rc = ecryptfs_spawn_daemon(&daemon, euid, current_user_ns(), task_pid(current)); if (rc) { printk(KERN_ERR "%s: Error attempting to spawn daemon; " "rc = [%d]\n", __func__, rc); goto out_module_put_unlock_daemon_list; } } mutex_lock(&daemon->mux); if (daemon->pid != task_pid(current)) { rc = -EINVAL; printk(KERN_ERR "%s: pid [0x%p] has registered with euid [%d], " "but pid [0x%p] has attempted to open the handle " "instead\n", __func__, daemon->pid, daemon->euid, task_pid(current)); goto out_unlock_daemon; } if (daemon->flags & ECRYPTFS_DAEMON_MISCDEV_OPEN) { rc = -EBUSY; printk(KERN_ERR "%s: Miscellaneous device handle may only be " "opened once per daemon; pid [0x%p] already has this " "handle open\n", __func__, daemon->pid); goto out_unlock_daemon; } daemon->flags |= ECRYPTFS_DAEMON_MISCDEV_OPEN; file->private_data = daemon; atomic_inc(&ecryptfs_num_miscdev_opens); out_unlock_daemon: mutex_unlock(&daemon->mux); out_module_put_unlock_daemon_list: if (rc) module_put(THIS_MODULE); out_unlock_daemon_list: mutex_unlock(&ecryptfs_daemon_hash_mux); return rc; }
static int parse_options(char *options, struct omfs_sb_info *sbi) { char *p; substring_t args[MAX_OPT_ARGS]; int option; if (!options) return 1; while ((p = strsep(&options, ",")) != NULL) { int token; if (!*p) continue; token = match_token(p, tokens, args); switch (token) { case Opt_uid: if (match_int(&args[0], &option)) return 0; sbi->s_uid = make_kuid(current_user_ns(), option); if (!uid_valid(sbi->s_uid)) return 0; break; case Opt_gid: if (match_int(&args[0], &option)) return 0; sbi->s_gid = make_kgid(current_user_ns(), option); if (!gid_valid(sbi->s_gid)) return 0; break; case Opt_umask: if (match_octal(&args[0], &option)) return 0; sbi->s_fmask = sbi->s_dmask = option; break; case Opt_dmask: if (match_octal(&args[0], &option)) return 0; sbi->s_dmask = option; break; case Opt_fmask: if (match_octal(&args[0], &option)) return 0; sbi->s_fmask = option; break; default: return 0; } } return 1; }
/** * ecryptfs_miscdev_release * @inode: inode of fs/ecryptfs/euid handle (ignored) * @file: file for fs/ecryptfs/euid handle (ignored) * * This keeps the daemon registered until the daemon sends another * ioctl to fs/ecryptfs/ctl or until the kernel module unregisters. * * Returns zero on success; non-zero otherwise */ static int ecryptfs_miscdev_release(struct inode *inode, struct file *file) { struct ecryptfs_daemon *daemon = NULL; uid_t euid = current_euid(); int rc; mutex_lock(&ecryptfs_daemon_hash_mux); rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns()); if (rc || !daemon) daemon = file->private_data; mutex_lock(&daemon->mux); BUG_ON(!(daemon->flags & ECRYPTFS_DAEMON_MISCDEV_OPEN)); daemon->flags &= ~ECRYPTFS_DAEMON_MISCDEV_OPEN; atomic_dec(&ecryptfs_num_miscdev_opens); mutex_unlock(&daemon->mux); rc = ecryptfs_exorcise_daemon(daemon); if (rc) { printk(KERN_CRIT "%s: Fatal error whilst attempting to " "shut down daemon; rc = [%d]. Please report this " "bug.\n", __func__, rc); BUG(); } module_put(THIS_MODULE); mutex_unlock(&ecryptfs_daemon_hash_mux); return rc; }
/** * seccomp_attach_filter: Attaches a seccomp filter to current. * @fprog: BPF program to install * * Returns 0 on success or an errno on failure. */ static long seccomp_attach_filter(struct sock_fprog *fprog) { struct seccomp_filter *filter; unsigned long fp_size = fprog->len * sizeof(struct sock_filter); unsigned long total_insns = fprog->len; long ret; if (fprog->len == 0 || fprog->len > BPF_MAXINSNS) return -EINVAL; for (filter = current->seccomp.filter; filter; filter = filter->prev) total_insns += filter->len + 4; /* include a 4 instr penalty */ if (total_insns > MAX_INSNS_PER_PATH) return -ENOMEM; /* * Installing a seccomp filter requires that the task have * CAP_SYS_ADMIN in its namespace or be running with no_new_privs. * This avoids scenarios where unprivileged tasks can affect the * behavior of privileged children. */ if (!current->no_new_privs && security_capable_noaudit(current_cred(), current_user_ns(), CAP_SYS_ADMIN) != 0) return -EACCES; /* Allocate a new seccomp_filter */ filter = kzalloc(sizeof(struct seccomp_filter) + fp_size, GFP_KERNEL|__GFP_NOWARN); if (!filter) return -ENOMEM; atomic_set(&filter->usage, 1); filter->len = fprog->len; /* Copy the instructions from fprog. */ ret = -EFAULT; if (copy_from_user(filter->insns, fprog->filter, fp_size)) goto fail; /* Check and rewrite the fprog via the skb checker */ ret = sk_chk_filter(filter->insns, filter->len); if (ret) goto fail; /* Check and rewrite the fprog for seccomp use */ ret = seccomp_check_filter(filter->insns, filter->len); if (ret) goto fail; /* * If there is an existing filter, make it the prev and don't drop its * task reference. */ filter->prev = current->seccomp.filter; current->seccomp.filter = filter; return 0; fail: kfree(filter); return ret; }
static struct dentry *sysfs_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *data) { struct sysfs_super_info *info; enum kobj_ns_type type; struct super_block *sb; int error; if (!(flags & MS_KERNMOUNT) && !current_user_ns()->may_mount_sysfs) return ERR_PTR(-EPERM); info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) return ERR_PTR(-ENOMEM); for (type = KOBJ_NS_TYPE_NONE; type < KOBJ_NS_TYPES; type++) info->ns[type] = kobj_ns_grab_current(type); sb = sget(fs_type, sysfs_test_super, sysfs_set_super, flags, info); if (IS_ERR(sb) || sb->s_fs_info != info) free_sysfs_super_info(info); if (IS_ERR(sb)) return ERR_CAST(sb); if (!sb->s_root) { error = sysfs_fill_super(sb, data, flags & MS_SILENT ? 1 : 0); if (error) { deactivate_locked_super(sb); return ERR_PTR(error); } sb->s_flags |= MS_ACTIVE; } return dget(sb->s_root); }
static long force_sigsegv_info (int sig, void __user *addr) { unsigned long flags; struct siginfo si; clear_siginfo(&si); if (sig == SIGSEGV) { /* * Acquiring siglock around the sa_handler-update is almost * certainly overkill, but this isn't a * performance-critical path and I'd rather play it safe * here than having to debug a nasty race if and when * something changes in kernel/signal.c that would make it * no longer safe to modify sa_handler without holding the * lock. */ spin_lock_irqsave(¤t->sighand->siglock, flags); current->sighand->action[sig - 1].sa.sa_handler = SIG_DFL; spin_unlock_irqrestore(¤t->sighand->siglock, flags); } si.si_signo = SIGSEGV; si.si_errno = 0; si.si_code = SI_KERNEL; si.si_pid = task_pid_vnr(current); si.si_uid = from_kuid_munged(current_user_ns(), current_uid()); si.si_addr = addr; force_sig_info(SIGSEGV, &si, current); return 1; }
/** * cn_proc_mcast_ctl * @data: message sent from userspace via the connector */ static void cn_proc_mcast_ctl(struct cn_msg *msg, struct netlink_skb_parms *nsp) { enum proc_cn_mcast_op *mc_op = NULL; int err = 0; if (msg->len != sizeof(*mc_op)) return; /* * Events are reported with respect to the initial pid * and user namespaces so ignore requestors from * other namespaces. */ if ((current_user_ns() != &init_user_ns) || (task_active_pid_ns(current) != &init_pid_ns)) return; mc_op = (enum proc_cn_mcast_op *)msg->data; switch (*mc_op) { case PROC_CN_MCAST_LISTEN: atomic_inc(&proc_event_num_listeners); break; case PROC_CN_MCAST_IGNORE: atomic_dec(&proc_event_num_listeners); break; default: err = EINVAL; break; } cn_proc_ack(err, msg->seq, msg->ack); }
void posix_acl_fix_xattr_to_user(void *value, size_t size) { struct user_namespace *user_ns = current_user_ns(); if (user_ns == &init_user_ns) return; posix_acl_fix_xattr_userns(user_ns, &init_user_ns, value, size); }
/* * Get client information. * * \param inode device inode. * \param file_priv DRM file private. * \param cmd command. * \param arg user argument, pointing to a drm_client structure. * * \return zero on success or a negative number on failure. * * Searches for the client with the specified index and copies its information * into userspace */ static int drm_getclient(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_client *client = data; /* * Hollowed-out getclient ioctl to keep some dead old drm tests/tools * not breaking completely. Userspace tools stop enumerating one they * get -EINVAL, hence this is the return value we need to hand back for * no clients tracked. * * Unfortunately some clients (*cough* libva *cough*) use this in a fun * attempt to figure out whether they're authenticated or not. Since * that's the only thing they care about, give it to the directly * instead of walking one giant list. */ if (client->idx == 0) { client->auth = file_priv->authenticated; client->pid = pid_vnr(file_priv->pid); client->uid = from_kuid_munged(current_user_ns(), file_priv->uid); client->magic = 0; client->iocs = 0; return 0; } else { return -EINVAL; } }
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 (!ns_capable(current_user_ns(), 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; }
/** * ecryptfs_miscdev_poll * @file: dev file (ignored) * @pt: dev poll table (ignored) * * Returns the poll mask */ static unsigned int ecryptfs_miscdev_poll(struct file *file, poll_table *pt) { struct ecryptfs_daemon *daemon; unsigned int mask = 0; uid_t euid = current_euid(); int rc; mutex_lock(&ecryptfs_daemon_hash_mux); /* TODO: Just use file->private_data? */ rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns()); BUG_ON(rc || !daemon); mutex_lock(&daemon->mux); mutex_unlock(&ecryptfs_daemon_hash_mux); if (daemon->flags & ECRYPTFS_DAEMON_ZOMBIE) { printk(KERN_WARNING "%s: Attempt to poll on zombified " "daemon\n", __func__); goto out_unlock_daemon; } if (daemon->flags & ECRYPTFS_DAEMON_IN_READ) goto out_unlock_daemon; if (daemon->flags & ECRYPTFS_DAEMON_IN_POLL) goto out_unlock_daemon; daemon->flags |= ECRYPTFS_DAEMON_IN_POLL; mutex_unlock(&daemon->mux); poll_wait(file, &daemon->wait, pt); mutex_lock(&daemon->mux); if (!list_empty(&daemon->msg_ctx_out_queue)) mask |= POLLIN | POLLRDNORM; out_unlock_daemon: daemon->flags &= ~ECRYPTFS_DAEMON_IN_POLL; mutex_unlock(&daemon->mux); return mask; }
asmlinkage int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount) { int ret = -ENOSYS; if (!sysctl_modify_ldt) { printk_ratelimited(KERN_INFO "Denied a call to modify_ldt() from %s[%d] (uid: %d)." " Adjust sysctl if this was not an exploit attempt.\n", current->comm, task_pid_nr(current), from_kuid_munged(current_user_ns(), current_uid())); return ret; } switch (func) { case 0: ret = read_ldt(ptr, bytecount); break; case 1: ret = write_ldt(ptr, bytecount, 1); break; case 2: ret = read_default_ldt(ptr, bytecount); break; case 0x11: ret = write_ldt(ptr, bytecount, 0); break; } return ret; }
static int quota_setxquota(struct super_block *sb, int type, qid_t id, void __user *addr) { struct fs_disk_quota fdq; struct qc_dqblk qdq; struct kqid qid; if (copy_from_user(&fdq, addr, sizeof(fdq))) return -EFAULT; if (!sb->s_qcop->set_dqblk) return -ENOSYS; qid = make_kqid(current_user_ns(), type, id); if (!qid_valid(qid)) return -EINVAL; /* Are we actually setting timer / warning limits for all users? */ if (from_kqid(&init_user_ns, qid) == 0 && fdq.d_fieldmask & (FS_DQ_WARNS_MASK | FS_DQ_TIMER_MASK)) { struct qc_info qinfo; int ret; if (!sb->s_qcop->set_info) return -EINVAL; copy_qcinfo_from_xfs_dqblk(&qinfo, &fdq); ret = sb->s_qcop->set_info(sb, type, &qinfo); if (ret) return ret; /* These are already done */ fdq.d_fieldmask &= ~(FS_DQ_WARNS_MASK | FS_DQ_TIMER_MASK); } copy_from_xfs_dqblk(&qdq, &fdq); return sb->s_qcop->set_dqblk(sb, qid, &qdq); }
static int xfs_ioctl_setattr_check_projid( struct xfs_inode *ip, struct fsxattr *fa) { /* Disallow 32bit project ids if projid32bit feature is not enabled. */ if (fa->fsx_projid > (__uint16_t)-1 && !xfs_sb_version_hasprojid32bit(&ip->i_mount->m_sb)) return -EINVAL; /* * Project Quota ID state is only allowed to change from within the init * namespace. Enforce that restriction only if we are trying to change * the quota ID state. Everything else is allowed in user namespaces. */ if (current_user_ns() == &init_user_ns) return 0; if (xfs_get_projid(ip) != fa->fsx_projid) return -EINVAL; if ((fa->fsx_xflags & XFS_XFLAG_PROJINHERIT) != (ip->i_d.di_flags & XFS_DIFLAG_PROJINHERIT)) return -EINVAL; return 0; }
/* Do not directly use this function. Use ECRYPTFS_OVERRIDE_CRED() instead. */ const struct cred * ecryptfs_override_fsids(uid_t fsuid, gid_t fsgid) { struct cred * cred; const struct cred * old_cred; cred = prepare_creds(); if (!cred) return NULL; cred->fsuid = make_kuid(current_user_ns(), fsuid); cred->fsgid = make_kgid(current_user_ns(), fsgid); old_cred = override_creds(cred); return old_cred; }
static struct key *find_ge_key(key_serial_t id) { struct user_namespace *user_ns = current_user_ns(); struct rb_node *n = key_serial_tree.rb_node; struct key *minkey = NULL; while (n) { struct key *key = rb_entry(n, struct key, serial_node); if (id < key->serial) { if (!minkey || minkey->serial > key->serial) minkey = key; n = n->rb_left; } else if (id > key->serial) { n = n->rb_right; } else { minkey = key; break; } key = NULL; } if (!minkey) return NULL; for (;;) { if (minkey->user->user_ns == user_ns) return minkey; n = rb_next(&minkey->serial_node); if (!n) return NULL; minkey = rb_entry(n, struct key, serial_node); } }
static int debugfs_parse_options(char *data, struct debugfs_mount_opts *opts) { substring_t args[MAX_OPT_ARGS]; int option; int token; kuid_t uid; kgid_t gid; char *p; opts->mode = DEBUGFS_DEFAULT_MODE; while ((p = strsep(&data, ",")) != NULL) { if (!*p) continue; token = match_token(p, tokens, args); switch (token) { case Opt_uid: if (match_int(&args[0], &option)) return -EINVAL; uid = make_kuid(current_user_ns(), option); if (!uid_valid(uid)) return -EINVAL; opts->uid = uid; break; case Opt_gid: if (match_int(&args[0], &option)) return -EINVAL; gid = make_kgid(current_user_ns(), option); if (!gid_valid(gid)) return -EINVAL; opts->gid = gid; break; case Opt_mode: if (match_octal(&args[0], &option)) return -EINVAL; opts->mode = option & S_IALLUGO; break; /* * We might like to report bad mount options here; * but traditionally debugfs has ignored all mount options */ } } return 0; }
long ia64_rt_sigreturn (struct sigscratch *scr) { extern char ia64_strace_leave_kernel, ia64_leave_kernel; struct sigcontext __user *sc; struct siginfo si; sigset_t set; long retval; sc = &((struct sigframe __user *) (scr->pt.r12 + 16))->sc; /* * When we return to the previously executing context, r8 and r10 have already * been setup the way we want them. Indeed, if the signal wasn't delivered while * in a system call, we must not touch r8 or r10 as otherwise user-level state * could be corrupted. */ retval = (long) &ia64_leave_kernel; if (test_thread_flag(TIF_SYSCALL_TRACE) || test_thread_flag(TIF_SYSCALL_AUDIT)) /* * strace expects to be notified after sigreturn returns even though the * context to which we return may not be in the middle of a syscall. * Thus, the return-value that strace displays for sigreturn is * meaningless. */ retval = (long) &ia64_strace_leave_kernel; if (!access_ok(VERIFY_READ, sc, sizeof(*sc))) goto give_sigsegv; if (GET_SIGSET(&set, &sc->sc_mask)) goto give_sigsegv; set_current_blocked(&set); if (restore_sigcontext(sc, scr)) goto give_sigsegv; #if DEBUG_SIG printk("SIG return (%s:%d): sp=%lx ip=%lx\n", current->comm, current->pid, scr->pt.r12, scr->pt.cr_iip); #endif if (restore_altstack(&sc->sc_stack)) goto give_sigsegv; return retval; give_sigsegv: clear_siginfo(&si); si.si_signo = SIGSEGV; si.si_errno = 0; si.si_code = SI_KERNEL; si.si_pid = task_pid_vnr(current); si.si_uid = from_kuid_munged(current_user_ns(), current_uid()); si.si_addr = sc; force_sig_info(SIGSEGV, &si, current); return retval; }
static struct rb_node *__key_user_next(struct rb_node *n) { while (n) { struct key_user *user = rb_entry(n, struct key_user, node); if (user->user_ns == current_user_ns()) break; n = rb_next(n); } return n; }