All of lore.kernel.org
 help / color / mirror / Atom feed
From: Kees Cook <keescook@chromium.org>
To: Casey Schaufler <casey@schaufler-ca.com>
Cc: LKLM <linux-kernel@vger.kernel.org>,
	LSM <linux-security-module@vger.kernel.org>,
	SE Linux <selinux@tycho.nsa.gov>,
	James Morris <jmorris@namei.org>,
	John Johansen <john.johansen@canonical.com>,
	Eric Paris <eparis@redhat.com>,
	Tetsuo Handa <penguin-kernel@i-love.sakura.ne.jp>,
	Kees Cook <keescook@chromium.org>
Subject: Re: [PATCH v14 0/6] LSM: Multiple concurrent LSMs
Date: Mon, 5 Aug 2013 23:30:02 -0700	[thread overview]
Message-ID: <20130806063002.GF2280@outflux.net> (raw)
In-Reply-To: <51F16CFB.6040603@schaufler-ca.com>

On Thu, Jul 25, 2013 at 11:52 PM, Casey Schaufler <casey@schaufler-ca.com> wrote:
> The /proc/*/attr interfaces are given to one LSM. This can be
> done by setting CONFIG_SECURITY_PRESENT. Additional interfaces
> have been created in /proc/*/attr so that each LSM has its own
> named interfaces. The name of the presenting LSM can be read from

For me, this is one problem that was bothering me, but it was a cosmetic
one that I'd mentioned before: I really disliked the /proc/$pid/attr
interface being named "$lsm.$file". I feel it's important to build
directories in attr/ for each LSM. So, I spent time to figure out a way to
do this. This patch changes the interface to /proc/$pid/attr/$lsm/$file
instead, which I feel has a much more appealing organizational structure.

-Kees

---
Subject: [PATCH] LSM: use subdirectories for LSM attr files

Instead of filling the /proc/$pid/attr/ directory with every LSM's needed
attr files, insert a directory entry for each LSM which contains the
needed files.

Signed-off-by: Kees Cook <keescook@chromium.org>
---
 fs/proc/base.c           |   95 ++++++++++++++++++++++++++++++++++++----------
 fs/proc/internal.h       |    1 +
 include/linux/security.h |   11 +++---
 security/security.c      |   67 ++++++++++++++------------------
 4 files changed, 112 insertions(+), 62 deletions(-)

diff --git a/fs/proc/base.c b/fs/proc/base.c
index 941fe83..4c80ffd 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -138,6 +138,10 @@ struct pid_entry {
 	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 .
@@ -2292,7 +2296,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);
@@ -2335,7 +2339,7 @@ static ssize_t proc_pid_attr_write(struct file * file, const char __user * buf,
 	if (length < 0)
 		goto out_free;
 
-	length = security_setprocattr(task,
+	length = security_setprocattr(task, PROC_I(inode)->op.lsm,
 				      (char*)file->f_path.dentry->d_name.name,
 				      (void*)page, count);
 	mutex_unlock(&task->signal->cred_guard_mutex);
@@ -2353,29 +2357,82 @@ static const struct file_operations proc_pid_attr_operations = {
 	.llseek		= generic_file_llseek,
 };
 
+#define LSM_DIR_OPS(LSM) \
+static int proc_##LSM##_attr_dir_readdir(struct file * filp, \
+			     void * dirent, filldir_t filldir) \
+{ \
+	return proc_pident_readdir(filp, dirent, filldir, \
+				   LSM##_attr_dir_stuff, \
+				   ARRAY_SIZE(LSM##_attr_dir_stuff)); \
+} \
+\
+static const struct file_operations proc_##LSM##_attr_dir_ops = { \
+	.read		= generic_read_dir, \
+	.readdir	= proc_##LSM##_attr_dir_readdir, \
+	.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",	S_IRUGO|S_IWUGO),
+	ATTR("selinux", "prev",		S_IRUGO),
+	ATTR("selinux", "exec",		S_IRUGO|S_IWUGO),
+	ATTR("selinux", "fscreate",	S_IRUGO|S_IWUGO),
+	ATTR("selinux", "keycreate",	S_IRUGO|S_IWUGO),
+	ATTR("selinux", "sockcreate",	S_IRUGO|S_IWUGO),
+};
+LSM_DIR_OPS(selinux);
+#endif
+
+#ifdef CONFIG_SECURITY_SMACK
+static const struct pid_entry smack_attr_dir_stuff[] = {
+	ATTR("smack", "current",	S_IRUGO|S_IWUGO),
+};
+LSM_DIR_OPS(smack);
+#endif
+
+#ifdef CONFIG_SECURITY_APPARMOR
+static const struct pid_entry apparmor_attr_dir_stuff[] = {
+	ATTR("apparmor", "current",	S_IRUGO|S_IWUGO),
+	ATTR("apparmor", "prev",	S_IRUGO),
+	ATTR("apparmor", "exec",	S_IRUGO|S_IWUGO),
+};
+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),
-	REG("context",            S_IRUGO|S_IWUGO, proc_pid_attr_operations),
+	ATTR(NULL, "current",		S_IRUGO|S_IWUGO),
+	ATTR(NULL, "prev",		S_IRUGO),
+	ATTR(NULL, "exec",		S_IRUGO|S_IWUGO),
+	ATTR(NULL, "fscreate",		S_IRUGO|S_IWUGO),
+	ATTR(NULL, "keycreate",		S_IRUGO|S_IWUGO),
+	ATTR(NULL, "sockcreate",	S_IRUGO|S_IWUGO),
+	ATTR(NULL, "context",		S_IRUGO|S_IWUGO),
 #ifdef CONFIG_SECURITY_SELINUX
-	REG("selinux.current",    S_IRUGO|S_IWUGO, proc_pid_attr_operations),
-	REG("selinux.prev",       S_IRUGO,         proc_pid_attr_operations),
-	REG("selinux.exec",       S_IRUGO|S_IWUGO, proc_pid_attr_operations),
-	REG("selinux.fscreate",   S_IRUGO|S_IWUGO, proc_pid_attr_operations),
-	REG("selinux.keycreate",  S_IRUGO|S_IWUGO, proc_pid_attr_operations),
-	REG("selinux.sockcreate", S_IRUGO|S_IWUGO, proc_pid_attr_operations),
+	DIR("selinux",			S_IRUGO|S_IXUGO,
+	    proc_selinux_attr_dir_inode_ops, proc_selinux_attr_dir_ops),
 #endif
 #ifdef CONFIG_SECURITY_SMACK
-	REG("smack.current",      S_IRUGO|S_IWUGO, proc_pid_attr_operations),
+	DIR("smack",			S_IRUGO|S_IXUGO,
+	    proc_smack_attr_dir_inode_ops, proc_smack_attr_dir_ops),
 #endif
 #ifdef CONFIG_SECURITY_APPARMOR
-	REG("apparmor.current",   S_IRUGO|S_IWUGO, proc_pid_attr_operations),
-	REG("apparmor.prev",      S_IRUGO,         proc_pid_attr_operations),
-	REG("apparmor.exec",      S_IRUGO|S_IWUGO, proc_pid_attr_operations),
+	DIR("apparmor",			S_IRUGO|S_IXUGO,
+	    proc_apparmor_attr_dir_inode_ops, proc_apparmor_attr_dir_ops),
 #endif
 
 };
diff --git a/fs/proc/internal.h b/fs/proc/internal.h
index d600fb0..795f649 100644
--- a/fs/proc/internal.h
+++ b/fs/proc/internal.h
@@ -56,6 +56,7 @@ union proc_op {
 	int (*proc_show)(struct seq_file *m,
 		struct pid_namespace *ns, struct pid *pid,
 		struct task_struct *task);
+	const char *lsm;
 };
 
 struct proc_inode {
diff --git a/include/linux/security.h b/include/linux/security.h
index d60e21c..fa89618 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -2115,9 +2115,10 @@ int security_sem_semctl(struct sem_array *sma, int cmd);
 int security_sem_semop(struct sem_array *sma, struct sembuf *sops,
 			unsigned nsops, int alter);
 void security_d_instantiate(struct dentry *dentry, struct inode *inode);
-int security_getprocattr(struct task_struct *p, char *name, char **value);
-int security_setprocattr(struct task_struct *p, char *name, void *value,
-			 size_t size);
+int security_getprocattr(struct task_struct *p, const char *lsm, char *name,
+                         char **value);
+int security_setprocattr(struct task_struct *p, const char *lsm, char *name,
+                         void *value, size_t size);
 int security_netlink_send(struct sock *sk, struct sk_buff *skb);
 int security_secid_to_secctx(struct secids *secid, char **secdata, u32 *seclen,
 			     struct security_operations **secops);
@@ -2801,8 +2802,8 @@ static inline void security_d_instantiate(struct dentry *dentry,
 					  struct inode *inode)
 { }
 
-static inline int security_getprocattr(struct task_struct *p, char *name,
-				       char **value)
+static inline int security_getprocattr(struct task_struct *p, char *lsm,
+                       char *name, char **value)
 {
 	return -EINVAL;
 }
diff --git a/security/security.c b/security/security.c
index 119a377..499af30 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1897,74 +1897,65 @@ void security_d_instantiate(struct dentry *dentry, struct inode *inode)
 }
 EXPORT_SYMBOL(security_d_instantiate);
 
-int security_getprocattr(struct task_struct *p, char *name, char **value)
+int security_getprocattr(struct task_struct *p, const char *lsm, char *name,
+			 char **value)
 {
 	struct security_operations *sop = NULL;
 	struct secids secid;
-	char *lsm;
-	int lsmlen;
 	int ret;
 
 	/*
-	 * Names will either be in the legacy form containing
-	 * no periods (".") or they will be the LSM name followed
-	 * by the legacy suffix. "current" or "selinux.current"
-	 * The exception is "context", which gets all of the LSMs.
-	 *
-	 * Legacy names are handled by the presenting LSM.
-	 * Suffixed names are handled by the named LSM.
+	 * Target LSM will be either NULL or looked up by name. Names with
+	 * a NULL LSM (legacy) are handled by the presenting LSM. The
+	 * exception is "context", which gets all of the LSMs.
 	 */
 	if (strcmp(name, "context") == 0) {
+		char *lsmname;
+		int lsmlen;
+
 		security_task_getsecid(p, &secid);
-		ret = security_secid_to_secctx(&secid, &lsm, &lsmlen, &sop);
+		ret = security_secid_to_secctx(&secid, &lsmname, &lsmlen, &sop);
 		if (ret == 0) {
-			*value = kstrdup(lsm, GFP_KERNEL);
+			*value = kstrdup(lsmname, GFP_KERNEL);
 			if (*value == NULL)
 				ret = -ENOMEM;
 			else
 				ret = strlen(*value);
-			security_release_secctx(lsm, lsmlen, sop);
+			security_release_secctx(lsmname, lsmlen, sop);
 		}
 		return ret;
 	}
 
-	if (present_ops && !strchr(name, '.'))
-		return present_getprocattr(p, name, value);
-
-	for_each_hook(sop, getprocattr) {
-		lsm = sop->name;
-		lsmlen = strlen(lsm);
-		if (!strncmp(name, lsm, lsmlen) && name[lsmlen] == '.')
-			return sop->getprocattr(p, name + lsmlen + 1, value);
+	if (!lsm) {
+		if (present_ops)
+			return present_getprocattr(p, name, value);
+	} else {
+		for_each_hook(sop, getprocattr) {
+			if (!strcmp(lsm, sop->name))
+				return sop->getprocattr(p, name, value);
+		}
 	}
 	return -EINVAL;
 }
 
-int security_setprocattr(struct task_struct *p, char *name, void *value,
-			 size_t size)
+int security_setprocattr(struct task_struct *p, const char *lsm, char *name,
+			 void *value, size_t size)
 {
 	struct security_operations *sop;
-	char *lsm;
-	int lsmlen;
 
 	/*
-	 * Names will either be in the legacy form containing
-	 * no periods (".") or they will be the LSM name followed
-	 * by the legacy suffix.
-	 * "current" or "selinux.current"
-	 *
-	 * Legacy names are handled by the presenting LSM.
-	 * Suffixed names are handled by the named LSM.
+	 * Target LSM will be either NULL or looked up by name. Names with
+	 * a NULL LSM (legacy) are handled by the presenting LSM. The
 	 */
 	if (present_ops && !strchr(name, '.'))
 		return present_setprocattr(p, name, value, size);
 
-	for_each_hook(sop, setprocattr) {
-		lsm = sop->name;
-		lsmlen = strlen(lsm);
-		if (!strncmp(name, lsm, lsmlen) && name[lsmlen] == '.')
-			return sop->setprocattr(p, name + lsmlen + 1, value,
-						size);
+	if (lsm) {
+		for_each_hook(sop, setprocattr) {
+			if (!strcmp(lsm, sop->name))
+				return sop->setprocattr(p, name, value,
+							size);
+		}
 	}
 	return -EINVAL;
 }
-- 
1.7.9.5


-- 
Kees Cook
Chrome OS Security

  parent reply	other threads:[~2013-08-06  6:30 UTC|newest]

Thread overview: 61+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-07-25 18:22 [PATCH v14 0/6] LSM: Multiple concurrent LSMs Casey Schaufler
2013-07-25 18:22 ` Casey Schaufler
2013-07-25 18:32 ` [PATCH v14 1/6] LSM: Security blob abstraction Casey Schaufler
2013-07-25 18:32   ` Casey Schaufler
2013-07-29 21:15   ` Kees Cook
2013-07-30  1:49     ` Casey Schaufler
2013-07-30  1:49       ` Casey Schaufler
2013-07-25 18:32 ` [PATCH v14 2/6] LSM: Move the capability LSM into the hook handlers Casey Schaufler
2013-07-25 18:32   ` Casey Schaufler
2013-07-25 18:32 ` [PATCH v14 3/6] LSM: Explicit individual LSM associations Casey Schaufler
2013-07-25 18:32   ` Casey Schaufler
2013-07-29 20:51   ` Kees Cook
2013-07-30  1:48     ` Casey Schaufler
2013-07-30  1:48       ` Casey Schaufler
2013-07-30 22:08   ` Paul Moore
2013-07-30 22:08     ` Paul Moore
2013-07-31 16:22     ` Casey Schaufler
2013-07-31 16:22       ` Casey Schaufler
2013-07-31 19:39       ` Paul Moore
2013-07-31 19:39         ` Paul Moore
2013-07-31 21:21         ` Casey Schaufler
2013-07-31 21:21           ` Casey Schaufler
2013-08-01 18:35           ` Paul Moore
2013-08-01 18:35             ` Paul Moore
2013-08-01 18:52             ` Casey Schaufler
2013-08-01 18:52               ` Casey Schaufler
2013-08-01 21:30               ` Paul Moore
2013-08-01 21:30                 ` Paul Moore
2013-08-01 22:15                 ` Casey Schaufler
2013-08-01 22:15                   ` Casey Schaufler
2013-08-01 22:18                   ` Paul Moore
2013-08-01 22:18                     ` Paul Moore
2013-07-25 18:32 ` [PATCH v14 4/6] LSM: List based multiple LSM hooks Casey Schaufler
2013-07-25 18:32   ` Casey Schaufler
2013-07-25 18:32 ` [PATCH v14 5/6] LSM: SO_PEERSEC configuration options Casey Schaufler
2013-07-25 18:32   ` Casey Schaufler
2013-07-30 21:47   ` Paul Moore
2013-07-30 21:47     ` Paul Moore
2013-07-31 15:45     ` Casey Schaufler
2013-07-31 15:45       ` Casey Schaufler
2013-07-31 17:56       ` Paul Moore
2013-07-31 17:56         ` Paul Moore
2013-07-25 18:32 ` [PATCH v14 6/6] LSM: Multiple LSM Documentation and cleanup Casey Schaufler
2013-07-25 18:32   ` Casey Schaufler
2013-07-26 23:17   ` Randy Dunlap
2013-07-28 18:46     ` Casey Schaufler
2013-07-28 18:46       ` Casey Schaufler
2013-08-01  2:48 ` [PATCH v14 0/6] LSM: Multiple concurrent LSMs Balbir Singh
2013-08-01 17:21   ` Casey Schaufler
2013-08-01 17:21     ` Casey Schaufler
2013-08-06  3:28     ` Balbir Singh
2013-08-06  6:30 ` Kees Cook [this message]
2013-08-06 22:25   ` Casey Schaufler
2013-08-06 22:25     ` Casey Schaufler
2013-08-06 22:36     ` Kees Cook
2013-08-27  2:29       ` Casey Schaufler
2013-08-27  2:29         ` Casey Schaufler
2013-08-28 15:55         ` Kees Cook
2013-09-05 18:48         ` Kees Cook
2013-09-06  6:44           ` Casey Schaufler
2013-09-06  6:44             ` Casey Schaufler

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=20130806063002.GF2280@outflux.net \
    --to=keescook@chromium.org \
    --cc=casey@schaufler-ca.com \
    --cc=eparis@redhat.com \
    --cc=jmorris@namei.org \
    --cc=john.johansen@canonical.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-security-module@vger.kernel.org \
    --cc=penguin-kernel@i-love.sakura.ne.jp \
    --cc=selinux@tycho.nsa.gov \
    /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.