From: Max Kellermann <mk@cm4all.com>
To: chrisw@sous-sol.org, linux-security-module@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Subject: [PATCH] /proc Security Hooks
Date: Tue, 16 Oct 2007 21:38:50 +0200 [thread overview]
Message-ID: <20071016193850.GA5418@roonstrasse.net> (raw)
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
}
next reply other threads:[~2007-10-16 19:46 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-10-16 19:38 Max Kellermann [this message]
2007-10-16 19:54 ` [PATCH] /proc Security Hooks Arjan van de Ven
2007-10-17 5:13 ` Max Kellermann
2007-10-17 5:21 ` Arjan van de Ven
2007-10-17 5:38 ` Greg KH
2007-10-16 20:20 ` Serge E. Hallyn
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20071016193850.GA5418@roonstrasse.net \
--to=mk@cm4all.com \
--cc=chrisw@sous-sol.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-security-module@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.