]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - fs/proc/base.c
KVM: SVM: Move spec control call after restore of GS
[mirror_ubuntu-artful-kernel.git] / fs / proc / base.c
index 719c2e943ea1028f22cd2e400b7b6f9289ca6791..84ab5c4dd250dcaaadf33bc8a9aa8ee7df0e2daf 100644 (file)
@@ -139,9 +139,13 @@ struct pid_entry {
 #define REG(NAME, MODE, fops)                          \
        NOD(NAME, (S_IFREG|(MODE)), NULL, &fops, {})
 #define ONE(NAME, MODE, show)                          \
-       NOD(NAME, (S_IFREG|(MODE)),                     \
+       NOD(NAME, (S_IFREG|(MODE)),                     \
                NULL, &proc_single_file_operations,     \
                { .proc_show = show } )
+#define ATTR(LSM, NAME, MODE)                          \
+       NOD(NAME, (S_IFREG|(MODE)),                     \
+               NULL, &proc_pid_attr_operations,        \
+               { .lsm = LSM })
 
 /*
  * Count the number of hardlinks for the pid_entry table, excluding the .
@@ -664,10 +668,17 @@ int proc_setattr(struct dentry *dentry, struct iattr *attr)
 {
        int error;
        struct inode *inode = d_inode(dentry);
+       struct user_namespace *s_user_ns;
 
        if (attr->ia_valid & ATTR_MODE)
                return -EPERM;
 
+       /* Don't let anyone mess with weird proc files */
+       s_user_ns = inode->i_sb->s_user_ns;
+       if (!kuid_has_mapping(s_user_ns, inode->i_uid) ||
+           !kgid_has_mapping(s_user_ns, inode->i_gid))
+               return -EPERM;
+
        error = setattr_prepare(dentry, attr);
        if (error)
                return error;
@@ -1986,7 +1997,7 @@ static int map_files_get_link(struct dentry *dentry, struct path *path)
        down_read(&mm->mmap_sem);
        vma = find_exact_vma(mm, vm_start, vm_end);
        if (vma && vma->vm_file) {
-               *path = vma->vm_file->f_path;
+               *path = vma_pr_or_file(vma)->f_path;
                path_get(path);
                rc = 0;
        }
@@ -2495,7 +2506,7 @@ static ssize_t proc_pid_attr_read(struct file * file, char __user * buf,
        if (!task)
                return -ESRCH;
 
-       length = security_getprocattr(task,
+       length = security_getprocattr(task, PROC_I(inode)->op.lsm,
                                      (char*)file->f_path.dentry->d_name.name,
                                      &p);
        put_task_struct(task);
@@ -2541,7 +2552,8 @@ static ssize_t proc_pid_attr_write(struct file * file, const char __user * buf,
        if (length < 0)
                goto out_free;
 
-       length = security_setprocattr(file->f_path.dentry->d_name.name,
+       length = security_setprocattr(PROC_I(inode)->op.lsm,
+                                     file->f_path.dentry->d_name.name,
                                      page, count);
        mutex_unlock(&current->signal->cred_guard_mutex);
 out_free:
@@ -2558,13 +2570,88 @@ static const struct file_operations proc_pid_attr_operations = {
        .llseek         = generic_file_llseek,
 };
 
+#define LSM_DIR_OPS(LSM) \
+static int proc_##LSM##_attr_dir_iterate(struct file *filp, \
+                            struct dir_context *ctx) \
+{ \
+       return proc_pident_readdir(filp, ctx, \
+                                  LSM##_attr_dir_stuff, \
+                                  ARRAY_SIZE(LSM##_attr_dir_stuff)); \
+} \
+\
+static const struct file_operations proc_##LSM##_attr_dir_ops = { \
+       .read           = generic_read_dir, \
+       .iterate        = proc_##LSM##_attr_dir_iterate, \
+       .llseek         = default_llseek, \
+}; \
+\
+static struct dentry *proc_##LSM##_attr_dir_lookup(struct inode *dir, \
+                               struct dentry *dentry, unsigned int flags) \
+{ \
+       return proc_pident_lookup(dir, dentry, \
+                                 LSM##_attr_dir_stuff, \
+                                 ARRAY_SIZE(LSM##_attr_dir_stuff)); \
+} \
+\
+static const struct inode_operations proc_##LSM##_attr_dir_inode_ops = { \
+       .lookup         = proc_##LSM##_attr_dir_lookup, \
+       .getattr        = pid_getattr, \
+       .setattr        = proc_setattr, \
+}
+
+#ifdef CONFIG_SECURITY_SELINUX
+static const struct pid_entry selinux_attr_dir_stuff[] = {
+       ATTR("selinux", "current",      0666),
+       ATTR("selinux", "prev",         0444),
+       ATTR("selinux", "exec",         0666),
+       ATTR("selinux", "fscreate",     0666),
+       ATTR("selinux", "keycreate",    0666),
+       ATTR("selinux", "sockcreate",   0666),
+       ATTR("selinux", "context",      0666),
+};
+LSM_DIR_OPS(selinux);
+#endif
+
+#ifdef CONFIG_SECURITY_SMACK
+static const struct pid_entry smack_attr_dir_stuff[] = {
+       ATTR("smack", "current",        0666),
+       ATTR("smack", "context",        0666),
+};
+LSM_DIR_OPS(smack);
+#endif
+
+#ifdef CONFIG_SECURITY_APPARMOR
+static const struct pid_entry apparmor_attr_dir_stuff[] = {
+       ATTR("apparmor", "current",     0666),
+       ATTR("apparmor", "prev",        0444),
+       ATTR("apparmor", "exec",        0666),
+       ATTR("apparmor", "context",     0666),
+};
+LSM_DIR_OPS(apparmor);
+#endif
+
 static const struct pid_entry attr_dir_stuff[] = {
-       REG("current",    S_IRUGO|S_IWUGO, proc_pid_attr_operations),
-       REG("prev",       S_IRUGO,         proc_pid_attr_operations),
-       REG("exec",       S_IRUGO|S_IWUGO, proc_pid_attr_operations),
-       REG("fscreate",   S_IRUGO|S_IWUGO, proc_pid_attr_operations),
-       REG("keycreate",  S_IRUGO|S_IWUGO, proc_pid_attr_operations),
-       REG("sockcreate", S_IRUGO|S_IWUGO, proc_pid_attr_operations),
+       ATTR(NULL, "current",           0666),
+       ATTR(NULL, "prev",              0444),
+       ATTR(NULL, "exec",              0666),
+       ATTR(NULL, "fscreate",          0666),
+       ATTR(NULL, "keycreate",         0666),
+       ATTR(NULL, "sockcreate",        0666),
+       ATTR(NULL, "context",           0666),
+       ATTR(NULL, "display_lsm",       0666),
+
+#ifdef CONFIG_SECURITY_SELINUX
+       DIR("selinux",                  0555,
+           proc_selinux_attr_dir_inode_ops, proc_selinux_attr_dir_ops),
+#endif
+#ifdef CONFIG_SECURITY_SMACK
+       DIR("smack",                    0555,
+           proc_smack_attr_dir_inode_ops, proc_smack_attr_dir_ops),
+#endif
+#ifdef CONFIG_SECURITY_APPARMOR
+       DIR("apparmor",                 0555,
+           proc_apparmor_attr_dir_inode_ops, proc_apparmor_attr_dir_ops),
+#endif
 };
 
 static int proc_attr_dir_readdir(struct file *file, struct dir_context *ctx)