aboutsummaryrefslogtreecommitdiffstats
path: root/fs/proc
diff options
context:
space:
mode:
authorCasey Schaufler <casey@schaufler-ca.com>2018-09-21 20:16:59 -0400
committerKees Cook <keescook@chromium.org>2019-01-08 16:18:44 -0500
commit6d9c939dbe4d0bcea09cd4b410f624cde1acb678 (patch)
tree1388ba40fc9bf6a8274fb807fe83c8a8e225b4c5 /fs/proc
parentd117a154e6128abac5409d3f173584e7b25981a2 (diff)
procfs: add smack subdir to attrs
Back in 2007 I made what turned out to be a rather serious mistake in the implementation of the Smack security module. The SELinux module used an interface in /proc to manipulate the security context on processes. Rather than use a similar interface, I used the same interface. The AppArmor team did likewise. Now /proc/.../attr/current will tell you the security "context" of the process, but it will be different depending on the security module you're using. This patch provides a subdirectory in /proc/.../attr for Smack. Smack user space can use the "current" file in this subdirectory and never have to worry about getting SELinux attributes by mistake. Programs that use the old interface will continue to work (or fail, as the case may be) as before. The proposed S.A.R.A security module is dependent on the mechanism to create its own attr subdirectory. The original implementation is by Kees Cook. Signed-off-by: Casey Schaufler <casey@schaufler-ca.com> Reviewed-by: Kees Cook <keescook@chromium.org> Signed-off-by: Kees Cook <keescook@chromium.org>
Diffstat (limited to 'fs/proc')
-rw-r--r--fs/proc/base.c64
-rw-r--r--fs/proc/internal.h1
2 files changed, 56 insertions, 9 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 633a63462573..c9d775fd24ef 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -140,9 +140,13 @@ struct pid_entry {
140#define REG(NAME, MODE, fops) \ 140#define REG(NAME, MODE, fops) \
141 NOD(NAME, (S_IFREG|(MODE)), NULL, &fops, {}) 141 NOD(NAME, (S_IFREG|(MODE)), NULL, &fops, {})
142#define ONE(NAME, MODE, show) \ 142#define ONE(NAME, MODE, show) \
143 NOD(NAME, (S_IFREG|(MODE)), \ 143 NOD(NAME, (S_IFREG|(MODE)), \
144 NULL, &proc_single_file_operations, \ 144 NULL, &proc_single_file_operations, \
145 { .proc_show = show } ) 145 { .proc_show = show } )
146#define ATTR(LSM, NAME, MODE) \
147 NOD(NAME, (S_IFREG|(MODE)), \
148 NULL, &proc_pid_attr_operations, \
149 { .lsm = LSM })
146 150
147/* 151/*
148 * Count the number of hardlinks for the pid_entry table, excluding the . 152 * Count the number of hardlinks for the pid_entry table, excluding the .
@@ -2525,7 +2529,7 @@ static ssize_t proc_pid_attr_read(struct file * file, char __user * buf,
2525 if (!task) 2529 if (!task)
2526 return -ESRCH; 2530 return -ESRCH;
2527 2531
2528 length = security_getprocattr(task, 2532 length = security_getprocattr(task, PROC_I(inode)->op.lsm,
2529 (char*)file->f_path.dentry->d_name.name, 2533 (char*)file->f_path.dentry->d_name.name,
2530 &p); 2534 &p);
2531 put_task_struct(task); 2535 put_task_struct(task);
@@ -2574,7 +2578,9 @@ static ssize_t proc_pid_attr_write(struct file * file, const char __user * buf,
2574 if (rv < 0) 2578 if (rv < 0)
2575 goto out_free; 2579 goto out_free;
2576 2580
2577 rv = security_setprocattr(file->f_path.dentry->d_name.name, page, count); 2581 rv = security_setprocattr(PROC_I(inode)->op.lsm,
2582 file->f_path.dentry->d_name.name, page,
2583 count);
2578 mutex_unlock(&current->signal->cred_guard_mutex); 2584 mutex_unlock(&current->signal->cred_guard_mutex);
2579out_free: 2585out_free:
2580 kfree(page); 2586 kfree(page);
@@ -2588,13 +2594,53 @@ static const struct file_operations proc_pid_attr_operations = {
2588 .llseek = generic_file_llseek, 2594 .llseek = generic_file_llseek,
2589}; 2595};
2590 2596
2597#define LSM_DIR_OPS(LSM) \
2598static int proc_##LSM##_attr_dir_iterate(struct file *filp, \
2599 struct dir_context *ctx) \
2600{ \
2601 return proc_pident_readdir(filp, ctx, \
2602 LSM##_attr_dir_stuff, \
2603 ARRAY_SIZE(LSM##_attr_dir_stuff)); \
2604} \
2605\
2606static const struct file_operations proc_##LSM##_attr_dir_ops = { \
2607 .read = generic_read_dir, \
2608 .iterate = proc_##LSM##_attr_dir_iterate, \
2609 .llseek = default_llseek, \
2610}; \
2611\
2612static struct dentry *proc_##LSM##_attr_dir_lookup(struct inode *dir, \
2613 struct dentry *dentry, unsigned int flags) \
2614{ \
2615 return proc_pident_lookup(dir, dentry, \
2616 LSM##_attr_dir_stuff, \
2617 ARRAY_SIZE(LSM##_attr_dir_stuff)); \
2618} \
2619\
2620static const struct inode_operations proc_##LSM##_attr_dir_inode_ops = { \
2621 .lookup = proc_##LSM##_attr_dir_lookup, \
2622 .getattr = pid_getattr, \
2623 .setattr = proc_setattr, \
2624}
2625
2626#ifdef CONFIG_SECURITY_SMACK
2627static const struct pid_entry smack_attr_dir_stuff[] = {
2628 ATTR("smack", "current", 0666),
2629};
2630LSM_DIR_OPS(smack);
2631#endif
2632
2591static const struct pid_entry attr_dir_stuff[] = { 2633static const struct pid_entry attr_dir_stuff[] = {
2592 REG("current", S_IRUGO|S_IWUGO, proc_pid_attr_operations), 2634 ATTR(NULL, "current", 0666),
2593 REG("prev", S_IRUGO, proc_pid_attr_operations), 2635 ATTR(NULL, "prev", 0444),
2594 REG("exec", S_IRUGO|S_IWUGO, proc_pid_attr_operations), 2636 ATTR(NULL, "exec", 0666),
2595 REG("fscreate", S_IRUGO|S_IWUGO, proc_pid_attr_operations), 2637 ATTR(NULL, "fscreate", 0666),
2596 REG("keycreate", S_IRUGO|S_IWUGO, proc_pid_attr_operations), 2638 ATTR(NULL, "keycreate", 0666),
2597 REG("sockcreate", S_IRUGO|S_IWUGO, proc_pid_attr_operations), 2639 ATTR(NULL, "sockcreate", 0666),
2640#ifdef CONFIG_SECURITY_SMACK
2641 DIR("smack", 0555,
2642 proc_smack_attr_dir_inode_ops, proc_smack_attr_dir_ops),
2643#endif
2598}; 2644};
2599 2645
2600static int proc_attr_dir_readdir(struct file *file, struct dir_context *ctx) 2646static int proc_attr_dir_readdir(struct file *file, struct dir_context *ctx)
diff --git a/fs/proc/internal.h b/fs/proc/internal.h
index 5185d7f6a51e..d4f9989063d0 100644
--- a/fs/proc/internal.h
+++ b/fs/proc/internal.h
@@ -81,6 +81,7 @@ union proc_op {
81 int (*proc_show)(struct seq_file *m, 81 int (*proc_show)(struct seq_file *m,
82 struct pid_namespace *ns, struct pid *pid, 82 struct pid_namespace *ns, struct pid *pid,
83 struct task_struct *task); 83 struct task_struct *task);
84 const char *lsm;
84}; 85};
85 86
86struct proc_inode { 87struct proc_inode {