Messages in this thread Patch in this message | | | Date | Tue, 16 Oct 2007 21:38:50 +0200 | From | Max Kellermann <> | Subject | [PATCH] /proc Security Hooks |
| |
Add two LSM hooks for limiting access to the proc file system.
security_proc_task() defines the visibility of tasks in /proc.
security_proc_generic() lets the LSM define who will see "generic" proc entries (see fs/proc/generic.c).
This patch attempts to unify duplicated code found in modules like Linux VServer.
Signed-off-by: Max Kellermann <mk@cm4all.com>
--- fs/proc/base.c | 9 +++++++++ fs/proc/generic.c | 15 +++++++++++++++ include/linux/security.h | 46 ++++++++++++++++++++++++++++++++++++++++++++++ security/Kconfig | 8 ++++++++ security/dummy.c | 16 ++++++++++++++++ 5 files changed, 94 insertions(+), 0 deletions(-)
diff --git a/fs/proc/base.c b/fs/proc/base.c index 19489b0..a6ebe2d 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -2317,6 +2317,10 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir) put_task_struct(task), task = next_tgid(tgid + 1)) { tgid = task->pid; filp->f_pos = tgid + TGID_OFFSET; +#ifdef CONFIG_SECURITY_PROC + if (security_proc_task(task) != 0) + continue; +#endif if (proc_pid_fill_cache(filp, dirent, filldir, task, tgid) < 0) { put_task_struct(task); goto out; @@ -2453,6 +2457,11 @@ static struct dentry *proc_task_lookup(struct inode *dir, struct dentry * dentry goto out; if (leader->tgid != task->tgid) goto out_drop_task; +#ifdef CONFIG_SECURITY_PROC + result = ERR_PTR(security_proc_task(task)); + if (IS_ERR(result)) + goto out_drop_task; +#endif result = proc_task_instantiate(dir, dentry, task, NULL); out_drop_task: diff --git a/fs/proc/generic.c b/fs/proc/generic.c index b5e7155..7b17ec3 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c @@ -21,6 +21,9 @@ #include <linux/bitops.h> #include <linux/spinlock.h> #include <linux/completion.h> +#ifdef CONFIG_SECURITY_PROC +#include <linux/security.h> +#endif #include <asm/uaccess.h> #include "internal.h" @@ -400,6 +403,11 @@ struct dentry *proc_lookup(struct inode * dir, struct dentry *dentry, struct nam unsigned int ino = de->low_ino; de_get(de); +#ifdef CONFIG_SECURITY_PROC + error = security_proc_generic(de); + if (error != 0) + break; +#endif spin_unlock(&proc_subdir_lock); error = -EINVAL; inode = proc_get_inode(dir->i_sb, ino, de); @@ -483,6 +491,10 @@ int proc_readdir(struct file * filp, /* filldir passes info to user space */ de_get(de); +#ifdef CONFIG_SECURITY_PROC + if (security_proc_generic(de) != 0) + goto skip; +#endif spin_unlock(&proc_subdir_lock); if (filldir(dirent, de->name, de->namelen, filp->f_pos, de->low_ino, de->mode >> 12) < 0) { @@ -490,6 +502,9 @@ int proc_readdir(struct file * filp, goto out; } spin_lock(&proc_subdir_lock); +#ifdef CONFIG_SECURITY_PROC + skip: +#endif filp->f_pos++; next = de->next; de_put(de); diff --git a/include/linux/security.h b/include/linux/security.h index 1a15526..3fbeacf 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -68,6 +68,10 @@ struct xfrm_policy; struct xfrm_state; struct xfrm_user_sec_ctx; +#ifdef CONFIG_SECURITY_PROC +struct proc_dir_entry; +#endif + extern int cap_netlink_send(struct sock *sk, struct sk_buff *skb); extern int cap_netlink_recv(struct sk_buff *skb, int cap); @@ -915,6 +919,17 @@ struct request_sock; * Return 1 if permission granted, 0 if permission denied and -ve it the * normal permissions model should be effected. * + * Security hooks affecting proc visibility + * + * @proc_task: + * Determines whether a task is visible. + * @task the requested task + * Return 0 if task is visible, -ENOENT if not, or -errno on other errors + * @proc_generic: + * Determines whether a generic proc entry is visible + * @de the requested proc_dir_entry structure + * Return 0 if entry is visible, -ENOENT if not, or -errno on other errors + * * Security hooks affecting all System V IPC operations. * * @ipc_permission: @@ -1399,6 +1414,11 @@ struct security_operations { #endif /* CONFIG_KEYS */ + #ifdef CONFIG_SECURITY_PROC + int (*proc_task)(struct task_struct *task); + int (*proc_generic)(struct proc_dir_entry *de); + #endif + }; /* global variables */ @@ -3314,5 +3334,31 @@ static inline int security_key_permission(key_ref_t key_ref, #endif #endif /* CONFIG_KEYS */ +#ifdef CONFIG_SECURITY_PROC +#ifdef CONFIG_SECURITY +static inline int security_proc_task(struct task_struct *task) +{ + return security_ops->proc_task(task); +} + +static inline int security_proc_generic(struct proc_dir_entry *de) +{ + return security_ops->proc_generic(de); +} + +#else + +static inline int security_proc_task(struct task_struct *task) +{ + return 0; +} + +static inline int security_proc_generic(struct proc_dir_entry *de) +{ + return 0; +} +#endif +#endif + #endif /* ! __LINUX_SECURITY_H */ diff --git a/security/Kconfig b/security/Kconfig index 460e5c9..bd6ad4b 100644 --- a/security/Kconfig +++ b/security/Kconfig @@ -73,6 +73,14 @@ config SECURITY_NETWORK_XFRM IPSec. If you are unsure how to answer this question, answer N. +config SECURITY_PROC + bool "/proc Security Hooks" + depends on PROC_FS && SECURITY + help + This enables the /proc security hooks. + These allow an LSM to hide nodes in the proc filesystem. + If you are unsure how to answer this question, answer N. + config SECURITY_CAPABILITIES tristate "Default Linux Capabilities" depends on SECURITY diff --git a/security/dummy.c b/security/dummy.c index 853ec22..3ec57be 100644 --- a/security/dummy.c +++ b/security/dummy.c @@ -949,6 +949,18 @@ static inline int dummy_key_permission(key_ref_t key_ref, } #endif /* CONFIG_KEYS */ +#ifdef CONFIG_SECURITY_PROC +static int dummy_proc_task(struct task_struct *task) +{ + return 0; +} + +static int dummy_proc_generic(struct proc_dir_entry *de) +{ + return 0; +} +#endif + struct security_operations dummy_security_ops; #define set_to_dummy_if_null(ops, function) \ @@ -1131,6 +1143,10 @@ void security_fixup_ops (struct security_operations *ops) set_to_dummy_if_null(ops, key_free); set_to_dummy_if_null(ops, key_permission); #endif /* CONFIG_KEYS */ +#ifdef CONFIG_SECURITY_PROC + set_to_dummy_if_null(ops, proc_task); + set_to_dummy_if_null(ops, proc_generic); +#endif } - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
| |