Skip to contentSkip to conversation

LSM: Security blob abstraction

PATCH Superseded Casey Schaufler 6 participants 27 messages Apr 23, 2013 – Apr 25, 2013 1 message not in the archive

Subsystems (23)
Networking Documentation VFS USB +19 more subsystems

v13 of 14 Superseded Latest is v14 →

lore
Share & tools
lore

A message that is not in the archive (sent off-list or not yet received): [email protected]

Casey Schaufler

author maintainer
#1 lore raw

PATCH v13 1/9 LSM: Security blob abstraction

Subject: [PATCH v13 1/9] LSM: Security blob abstraction

Change the way that Linux security modules access security blobs in support of multiple concurrent LSMs. Replace uses of the task security field, the inode i_security field and similar blob pointers with calls to trivial functions that provide the pointers. In patch 8 of 9 these functions change to provide the pointer for a specific LSM.

---
 include/linux/lsm.h                 |  150 ++++++++++++++++
 security/apparmor/context.c         |   10 +-
 security/apparmor/domain.c          |    8 +-
 security/apparmor/include/context.h |   13 +-
 security/apparmor/lsm.c             |   36 ++--
 security/selinux/hooks.c            |  332 ++++++++++++++++++++---------------
 security/selinux/include/objsec.h   |    2 +
 security/selinux/include/xfrm.h     |    2 +-
 security/selinux/netlabel.c         |   13 +-
 security/selinux/selinuxfs.c        |    6 +-
 security/selinux/xfrm.c             |    9 +-
 security/smack/smack.h              |   15 +-
 security/smack/smack_access.c       |    2 +-
 security/smack/smack_lsm.c          |  322 ++++++++++++++++-----------------
 security/smack/smackfs.c            |   20 +--
 security/tomoyo/common.h            |    6 +-
 security/tomoyo/domain.c            |    2 +-
 security/tomoyo/securityfs_if.c     |    9 +-
 security/tomoyo/tomoyo.c            |   41 +++--
 19 files changed, 618 insertions(+), 380 deletions(-)
include/linux/lsm.h new file +150 -0
new file mode 100644
index 0000000..7c93865
@@ -0,0 +1,150 @@
+/*
+ *
+ * Copyright (C) 2012 Casey Schaufler <[email protected]>
+ * Copyright (C) 2012 Intel Corporation
+ *
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License as published by
+ *	the Free Software Foundation, version 2.
+ *
+ * Author:
+ *	Casey Schaufler <[email protected]>
+ *
+ * Abstraction layer for LSM security blobs.
+ * This is pointless by itself, but necessary for multiple concurrent
+ * modules support. Multiple concurrent module support is also refered
+ * to as module stacking.
+ *
+ */
+#ifndef _LINUX_LSM_H
+#define _LINUX_LSM_H
+
+#include <linux/cred.h>
+#include <linux/fs.h>
+#include <linux/msg.h>
+#include <linux/key.h>
+#include <net/sock.h>
+#include <linux/security.h>
+
+/*
+ * Trivial implementation for the one-LSM-at-a-time case
+ */
+static inline void *lsm_get_blob(const void *bp, const int lsm)
+{
+	return (void *)bp;
+}
+
+/*
+ * Trivial implementation for the one-LSM-at-a-time case
+ */
+static inline void lsm_set_blob(void **vpp, void *value, const int lsm)
+{
+	*vpp = value;
+}
+
+static inline void *lsm_get_cred(const struct cred *cred,
+					const struct security_operations *sop)
+{
+	return lsm_get_blob(cred->security, 0);
+}
+
+static inline void lsm_set_cred(struct cred *cred, void *value,
+					const struct security_operations *sop)
+{
+	lsm_set_blob(&cred->security, value, 0);
+}
+
+static inline int lsm_set_init_cred(struct cred *cred, void *value,
+					const struct security_operations *sop)
+{
+	cred->security = value;
+	return 0;
+}
+
+static inline void *lsm_get_file(const struct file *file,
+					const struct security_operations *sop)
+{
+	return lsm_get_blob(file->f_security, 0);
+}
+
+static inline void lsm_set_file(struct file *file, void *value,
+					const struct security_operations *sop)
+{
+	lsm_set_blob(&file->f_security, value, 0);
+}
+
+static inline void *lsm_get_inode(const struct inode *inode,
+					const struct security_operations *sop)
+{
+	return lsm_get_blob(inode->i_security, 0);
+}
+
+static inline void lsm_set_inode(struct inode *inode, void *value,
+					const struct security_operations *sop)
+{
+	lsm_set_blob(&inode->i_security, value, 0);
+}
+
+static inline void *lsm_get_super(const struct super_block *super,
+					const struct security_operations *sop)
+{
+	return lsm_get_blob(super->s_security, 0);
+}
+
+static inline void lsm_set_super(struct super_block *super, void *value,
+					const struct security_operations *sop)
+{
+	lsm_set_blob(&super->s_security, value, 0);
+}
+
+static inline void *lsm_get_ipc(const struct kern_ipc_perm *ipc,
+					const struct security_operations *sop)
+{
+	return lsm_get_blob(ipc->security, 0);
+}
+
+static inline void lsm_set_ipc(struct kern_ipc_perm *ipc, void *value,
+					const struct security_operations *sop)
+{
+	lsm_set_blob(&ipc->security, value, 0);
+}
+
+static inline void *lsm_get_msg(const struct msg_msg *msg,
+					const struct security_operations *sop)
+{
+	return lsm_get_blob(msg->security, 0);
+}
+
+static inline void lsm_set_msg(struct msg_msg *msg, void *value,
+					const struct security_operations *sop)
+{
+	lsm_set_blob(&msg->security, value, 0);
+}
+
+#ifdef CONFIG_KEYS
+static inline void *lsm_get_key(const struct key *key,
+					const struct security_operations *sop)
+{
+	return lsm_get_blob(key->security, 0);
+}
+
+static inline void lsm_set_key(struct key *key, void *value,
+					const struct security_operations *sop)
+{
+	lsm_set_blob(&key->security, value, 0);
+}
+#endif
+
+static inline void *lsm_get_sock(const struct sock *sock,
+					const struct security_operations *sop)
+{
+	return lsm_get_blob(sock->sk_security, 0);
+}
+
+static inline void lsm_set_sock(struct sock *sock, void *value,
+					const struct security_operations *sop)
+{
+	lsm_set_blob(&sock->sk_security, value, 0);
+}
+
+#endif /* ! _LINUX_LSM_H */
security/apparmor/context.c +5 -5
index 8a9b502..3d9e460 100644
@@ -76,7 +76,7 @@ void aa_dup_task_context(struct aa_task_cxt *new, const struct aa_task_cxt *old)
  */
 int aa_replace_current_profile(struct aa_profile *profile)
 {
-	struct aa_task_cxt *cxt = current_cred()->security;
+	struct aa_task_cxt *cxt = lsm_get_cred(current_cred(), &apparmor_ops);
 	struct cred *new;
 	BUG_ON(!profile);
 
@@ -87,7 +87,7 @@ int aa_replace_current_profile(struct aa_profile *profile)
 	if (!new)
 		return -ENOMEM;
 
-	cxt = new->security;
+	cxt = lsm_get_cred(new, &apparmor_ops);
 	if (unconfined(profile) || (cxt->profile->ns != profile->ns)) {
 		/* if switching to unconfined or a different profile namespace
 		 * clear out context state
@@ -123,7 +123,7 @@ int aa_set_current_onexec(struct aa_profile *profile)
 	if (!new)
 		return -ENOMEM;
 
-	cxt = new->security;
+	cxt = lsm_get_cred(new, &apparmor_ops);
 	aa_get_profile(profile);
 	aa_put_profile(cxt->onexec);
 	cxt->onexec = profile;
@@ -150,7 +150,7 @@ int aa_set_current_hat(struct aa_profile *profile, u64 token)
 		return -ENOMEM;
 	BUG_ON(!profile);
 
-	cxt = new->security;
+	cxt = lsm_get_cred(new, &apparmor_ops);
 	if (!cxt->previous) {
 		/* transfer refcount */
 		cxt->previous = cxt->profile;
@@ -187,7 +187,7 @@ int aa_restore_previous_profile(u64 token)
 	if (!new)
 		return -ENOMEM;
 
-	cxt = new->security;
+	cxt = lsm_get_cred(new, &apparmor_ops);
 	if (cxt->token != token) {
 		abort_creds(new);
 		return -EACCES;
security/apparmor/domain.c +4 -4
index 859abda..1614111 100644
@@ -360,7 +360,7 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
 	if (bprm->cred_prepared)
 		return 0;
 
-	cxt = bprm->cred->security;
+	cxt = lsm_get_cred(bprm->cred, &apparmor_ops);
 	BUG_ON(!cxt);
 
 	profile = aa_get_profile(aa_newest_version(cxt->profile));
@@ -557,7 +557,7 @@ int apparmor_bprm_secureexec(struct linux_binprm *bprm)
 void apparmor_bprm_committing_creds(struct linux_binprm *bprm)
 {
 	struct aa_profile *profile = __aa_current_profile();
-	struct aa_task_cxt *new_cxt = bprm->cred->security;
+	struct aa_task_cxt *new_cxt = lsm_get_cred(bprm->cred, &apparmor_ops);
 
 	/* bail out if unconfined or not changing profile */
 	if ((new_cxt->profile == profile) ||
@@ -634,7 +634,7 @@ int aa_change_hat(const char *hats[], int count, u64 token, bool permtest)
 
 	/* released below */
 	cred = get_current_cred();
-	cxt = cred->security;
+	cxt = lsm_get_cred(cred, &apparmor_ops);
 	profile = aa_cred_profile(cred);
 	previous_profile = cxt->previous;
 
@@ -770,7 +770,7 @@ int aa_change_profile(const char *ns_name, const char *hname, bool onexec,
 	}
 
 	cred = get_current_cred();
-	cxt = cred->security;
+	cxt = lsm_get_cred(cred, &apparmor_ops);
 	profile = aa_cred_profile(cred);
 
 	/*
security/apparmor/include/context.h +10 -3
index a9cbee4..8484e55 100644
@@ -18,6 +18,7 @@
 #include <linux/cred.h>
 #include <linux/slab.h>
 #include <linux/sched.h>
+#include <linux/lsm.h>
 
 #include "policy.h"
 
@@ -81,6 +82,8 @@ int aa_set_current_onexec(struct aa_profile *profile);
 int aa_set_current_hat(struct aa_profile *profile, u64 token);
 int aa_restore_previous_profile(u64 cookie);
 
+extern struct security_operations apparmor_ops;
+
 /**
  * __aa_task_is_confined - determine if @task has any confinement
  * @task: task to check confinement of  (NOT NULL)
@@ -89,7 +92,9 @@ int aa_restore_previous_profile(u64 cookie);
  */
 static inline bool __aa_task_is_confined(struct task_struct *task)
 {
-	struct aa_task_cxt *cxt = __task_cred(task)->security;
+	struct aa_task_cxt *cxt;
+
+	cxt = lsm_get_cred(__task_cred(task), &apparmor_ops);
 
 	BUG_ON(!cxt || !cxt->profile);
 	if (unconfined(aa_newest_version(cxt->profile)))
@@ -108,7 +113,7 @@ static inline bool __aa_task_is_confined(struct task_struct *task)
  */
 static inline struct aa_profile *aa_cred_profile(const struct cred *cred)
 {
-	struct aa_task_cxt *cxt = cred->security;
+	struct aa_task_cxt *cxt = lsm_get_cred(cred, &apparmor_ops);
 	BUG_ON(!cxt || !cxt->profile);
 	return aa_newest_version(cxt->profile);
 }
@@ -136,8 +141,10 @@ static inline struct aa_profile *__aa_current_profile(void)
  */
 static inline struct aa_profile *aa_current_profile(void)
 {
-	const struct aa_task_cxt *cxt = current_cred()->security;
+	const struct aa_task_cxt *cxt;
 	struct aa_profile *profile;
+
+	cxt = lsm_get_cred(current_cred(), &apparmor_ops);
 	BUG_ON(!cxt || !cxt->profile);
 
 	profile = aa_newest_version(cxt->profile);
security/apparmor/lsm.c +19 -17
index b21830e..8784681 100644
@@ -48,8 +48,8 @@ int apparmor_initialized __initdata;
  */
 static void apparmor_cred_free(struct cred *cred)
 {
-	aa_free_task_context(cred->security);
-	cred->security = NULL;
+	aa_free_task_context(lsm_get_cred(cred, &apparmor_ops));
+	lsm_set_cred(cred, NULL, &apparmor_ops);
 }
 
 /*
@@ -62,7 +62,7 @@ static int apparmor_cred_alloc_blank(struct cred *cred, gfp_t gfp)
 	if (!cxt)
 		return -ENOMEM;
 
-	cred->security = cxt;
+	lsm_set_cred(cred, cxt, &apparmor_ops);
 	return 0;
 }
 
@@ -77,8 +77,8 @@ static int apparmor_cred_prepare(struct cred *new, const struct cred *old,
 	if (!cxt)
 		return -ENOMEM;
 
-	aa_dup_task_context(cxt, old->security);
-	new->security = cxt;
+	aa_dup_task_context(cxt, lsm_get_cred(old, &apparmor_ops));
+	lsm_set_cred(new, cxt, &apparmor_ops);
 	return 0;
 }
 
@@ -87,8 +87,8 @@ static int apparmor_cred_prepare(struct cred *new, const struct cred *old,
  */
 static void apparmor_cred_transfer(struct cred *new, const struct cred *old)
 {
-	const struct aa_task_cxt *old_cxt = old->security;
-	struct aa_task_cxt *new_cxt = new->security;
+	const struct aa_task_cxt *old_cxt = lsm_get_cred(old, &apparmor_ops);
+	struct aa_task_cxt *new_cxt = lsm_get_cred(new, &apparmor_ops);
 
 	aa_dup_task_context(new_cxt, old_cxt);
 }
@@ -375,7 +375,7 @@ static int apparmor_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
 
 static int apparmor_file_open(struct file *file, const struct cred *cred)
 {
-	struct aa_file_cxt *fcxt = file->f_security;
+	struct aa_file_cxt *fcxt = lsm_get_file(file, &apparmor_ops);
 	struct aa_profile *profile;
 	int error = 0;
 
@@ -409,8 +409,8 @@ static int apparmor_file_open(struct file *file, const struct cred *cred)
 static int apparmor_file_alloc_security(struct file *file)
 {
 	/* freed by apparmor_file_free_security */
-	file->f_security = aa_alloc_file_context(GFP_KERNEL);
-	if (!file->f_security)
+	lsm_set_file(file, aa_alloc_file_context(GFP_KERNEL), &apparmor_ops);
+	if (!lsm_get_file(file, &apparmor_ops))
 		return -ENOMEM;
 	return 0;
 
@@ -418,14 +418,15 @@ static int apparmor_file_alloc_security(struct file *file)
 
 static void apparmor_file_free_security(struct file *file)
 {
-	struct aa_file_cxt *cxt = file->f_security;
+	struct aa_file_cxt *cxt = lsm_get_file(file, &apparmor_ops);
 
+	lsm_set_file(file, NULL, &apparmor_ops);
 	aa_free_file_context(cxt);
 }
 
 static int common_file_perm(int op, struct file *file, u32 mask)
 {
-	struct aa_file_cxt *fcxt = file->f_security;
+	struct aa_file_cxt *fcxt = lsm_get_file(file, &apparmor_ops);
 	struct aa_profile *profile, *fprofile = aa_cred_profile(file->f_cred);
 	int error = 0;
 
@@ -472,7 +473,7 @@ static int common_mmap(int op, struct file *file, unsigned long prot,
 	struct dentry *dentry;
 	int mask = 0;
 
-	if (!file || !file->f_security)
+	if (!file || !lsm_get_file(file, &apparmor_ops))
 		return 0;
 
 	if (prot & PROT_READ)
@@ -510,7 +511,7 @@ static int apparmor_getprocattr(struct task_struct *task, char *name,
 	struct aa_profile *profile;
 	/* released below */
 	const struct cred *cred = get_task_cred(task);
-	struct aa_task_cxt *cxt = cred->security;
+	struct aa_task_cxt *cxt = lsm_get_cred(cred, &apparmor_ops);
 	profile = aa_cred_profile(cred);
 
 	if (strcmp(name, "current") == 0)
@@ -614,7 +615,7 @@ static int apparmor_task_setrlimit(struct task_struct *task,
 	return error;
 }
 
-static struct security_operations apparmor_ops = {
+struct security_operations apparmor_ops = {
 	.name =				"apparmor",
 
 	.ptrace_access_check =		apparmor_ptrace_access_check,
@@ -878,6 +879,7 @@ static int param_set_mode(const char *val, struct kernel_param *kp)
  */
 static int __init set_init_cxt(void)
 {
+	int rc;
 	struct cred *cred = (struct cred *)current->real_cred;
 	struct aa_task_cxt *cxt;
 
@@ -886,9 +888,9 @@ static int __init set_init_cxt(void)
 		return -ENOMEM;
 
 	cxt->profile = aa_get_profile(root_ns->unconfined);
-	cred->security = cxt;
+	rc = lsm_set_init_cred(cred, cxt, &apparmor_ops);
 
-	return 0;
+	return rc;
 }
 
 static int __init apparmor_init(void)
security/selinux/hooks.c +190 -142

1,014 lines not on this page · raw message

security/selinux/include/objsec.h +2 -0
index aa47bca..c4f9cf1 100644
@@ -24,6 +24,7 @@
 #include <linux/binfmts.h>
 #include <linux/in.h>
 #include <linux/spinlock.h>
+#include <linux/lsm.h>
 #include "flask.h"
 #include "avc.h"
 
@@ -119,5 +120,6 @@ struct key_security_struct {
 };
 
 extern unsigned int selinux_checkreqprot;
+extern struct security_operations selinux_ops;
 
 #endif /* _SELINUX_OBJSEC_H_ */
security/selinux/include/xfrm.h +1 -1
index 65f67cb..1219221 100644
@@ -31,7 +31,7 @@ static inline struct inode_security_struct *get_sock_isec(struct sock *sk)
 	if (!sk->sk_socket)
 		return NULL;
 
-	return SOCK_INODE(sk->sk_socket)->i_security;
+	return lsm_get_inode(SOCK_INODE(sk->sk_socket), &selinux_ops);
 }
 
 #ifdef CONFIG_SECURITY_NETWORK_XFRM
security/selinux/netlabel.c +7 -6
index da4b8b2..7a9cbd0 100644
@@ -81,7 +81,7 @@ static int selinux_netlbl_sidlookup_cached(struct sk_buff *skb,
 static struct netlbl_lsm_secattr *selinux_netlbl_sock_genattr(struct sock *sk)
 {
 	int rc;
-	struct sk_security_struct *sksec = sk->sk_security;
+	struct sk_security_struct *sksec = lsm_get_sock(sk, &selinux_ops);
 	struct netlbl_lsm_secattr *secattr;
 
 	if (sksec->nlbl_secattr != NULL)
@@ -221,7 +221,8 @@ int selinux_netlbl_skbuff_setsid(struct sk_buff *skb,
 	 * being labeled by it's parent socket, if it is just exit */
 	sk = skb->sk;
 	if (sk != NULL) {
-		struct sk_security_struct *sksec = sk->sk_security;
+		struct sk_security_struct *sksec =
+					lsm_get_sock(sk, &selinux_ops);
 		if (sksec->nlbl_state != NLBL_REQSKB)
 			return 0;
 		secattr = sksec->nlbl_secattr;
@@ -283,7 +284,7 @@ inet_conn_request_return:
  */
 void selinux_netlbl_inet_csk_clone(struct sock *sk, u16 family)
 {
-	struct sk_security_struct *sksec = sk->sk_security;
+	struct sk_security_struct *sksec = lsm_get_sock(sk, &selinux_ops);
 
 	if (family == PF_INET)
 		sksec->nlbl_state = NLBL_LABELED;
@@ -304,7 +305,7 @@ void selinux_netlbl_inet_csk_clone(struct sock *sk, u16 family)
 int selinux_netlbl_socket_post_create(struct sock *sk, u16 family)
 {
 	int rc;
-	struct sk_security_struct *sksec = sk->sk_security;
+	struct sk_security_struct *sksec = lsm_get_sock(sk, &selinux_ops);
 	struct netlbl_lsm_secattr *secattr;
 
 	if (family != PF_INET)
@@ -402,7 +403,7 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock,
 {
 	int rc = 0;
 	struct sock *sk = sock->sk;
-	struct sk_security_struct *sksec = sk->sk_security;
+	struct sk_security_struct *sksec = lsm_get_sock(sk, &selinux_ops);
 	struct netlbl_lsm_secattr secattr;
 
 	if (level == IPPROTO_IP && optname == IP_OPTIONS &&
@@ -435,7 +436,7 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock,
 int selinux_netlbl_socket_connect(struct sock *sk, struct sockaddr *addr)
 {
 	int rc;
-	struct sk_security_struct *sksec = sk->sk_security;
+	struct sk_security_struct *sksec = lsm_get_sock(sk, &selinux_ops);
 	struct netlbl_lsm_secattr *secattr;
 
 	if (sksec->nlbl_state != NLBL_REQSKB &&
security/selinux/selinuxfs.c +3 -3
index ff42773..e9a10a5 100644
@@ -83,7 +83,7 @@ static int task_has_security(struct task_struct *tsk,
 	u32 sid = 0;
 
 	rcu_read_lock();
-	tsec = __task_cred(tsk)->security;
+	tsec = lsm_get_cred(__task_cred(tsk), &selinux_ops);
 	if (tsec)
 		sid = tsec->sid;
 	rcu_read_unlock();
@@ -1262,7 +1262,7 @@ static int sel_make_bools(void)
 		if (len >= PAGE_SIZE)
 			goto out;
 
-		isec = (struct inode_security_struct *)inode->i_security;
+		isec = lsm_get_inode(inode, &selinux_ops);
 		ret = security_genfs_sid("selinuxfs", page, SECCLASS_FILE, &sid);
 		if (ret)
 			goto out;
@@ -1827,7 +1827,7 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent)
 		goto err;
 
 	inode->i_ino = ++sel_last_ino;
-	isec = (struct inode_security_struct *)inode->i_security;
+	isec = lsm_get_inode(inode, &selinux_ops);
 	isec->sid = SECINITSID_DEVNULL;
 	isec->sclass = SECCLASS_CHR_FILE;
 	isec->initialized = 1;
security/selinux/xfrm.c +6 -3
index 8ab2951..5574ae4 100644
@@ -198,7 +198,8 @@ static int selinux_xfrm_sec_ctx_alloc(struct xfrm_sec_ctx **ctxp,
 	struct xfrm_user_sec_ctx *uctx, u32 sid)
 {
 	int rc = 0;
-	const struct task_security_struct *tsec = current_security();
+	const struct task_security_struct *tsec =
+				lsm_get_cred(current_cred(), &selinux_ops);
 	struct xfrm_sec_ctx *ctx = NULL;
 	char *ctx_str = NULL;
 	u32 str_len;
@@ -334,7 +335,8 @@ void selinux_xfrm_policy_free(struct xfrm_sec_ctx *ctx)
  */
 int selinux_xfrm_policy_delete(struct xfrm_sec_ctx *ctx)
 {
-	const struct task_security_struct *tsec = current_security();
+	const struct task_security_struct *tsec =
+				lsm_get_cred(current_cred(), &selinux_ops);
 	int rc = 0;
 
 	if (ctx) {
@@ -379,7 +381,8 @@ void selinux_xfrm_state_free(struct xfrm_state *x)
   */
 int selinux_xfrm_state_delete(struct xfrm_state *x)
 {
-	const struct task_security_struct *tsec = current_security();
+	const struct task_security_struct *tsec =
+				lsm_get_cred(current_cred(), &selinux_ops);
 	struct xfrm_sec_ctx *ctx = x->security;
 	int rc = 0;
 
security/smack/smack.h +10 -5
index 99b3612..d112298 100644
@@ -20,6 +20,7 @@
 #include <net/netlabel.h>
 #include <linux/list.h>
 #include <linux/rculist.h>
+#include <linux/lsm.h>
 #include <linux/lsm_audit.h>
 
 /*
@@ -203,6 +204,7 @@ struct smk_audit_info {
  * These functions are in smack_lsm.c
  */
 struct inode_smack *new_inode_smack(char *);
+int smk_setcurrent(char *, size_t);
 
 /*
  * These functions are in smack_access.c
@@ -221,6 +223,7 @@ u32 smack_to_secid(const char *);
 /*
  * Shared data.
  */
+extern int smack_use_netlbl;
 extern int smack_cipso_direct;
 extern int smack_cipso_mapped;
 extern char *smack_net_ambient;
@@ -243,18 +246,18 @@ extern struct security_operations smack_ops;
 /*
  * Is the directory transmuting?
  */
-static inline int smk_inode_transmutable(const struct inode *isp)
+static inline int smk_inode_transmutable(struct inode *isp)
 {
-	struct inode_smack *sip = isp->i_security;
+	struct inode_smack *sip = lsm_get_inode(isp, &smack_ops);
 	return (sip->smk_flags & SMK_INODE_TRANSMUTE) != 0;
 }
 
 /*
  * Present a pointer to the smack label in an inode blob.
  */
-static inline char *smk_of_inode(const struct inode *isp)
+static inline char *smk_of_inode(struct inode *isp)
 {
-	struct inode_smack *sip = isp->i_security;
+	struct inode_smack *sip = lsm_get_inode(isp, &smack_ops);
 	return sip->smk_inode;
 }
 
@@ -279,7 +282,9 @@ static inline char *smk_of_forked(const struct task_smack *tsp)
  */
 static inline char *smk_of_current(void)
 {
-	return smk_of_task(current_security());
+	struct task_smack *tsp = lsm_get_cred(current_cred(), &smack_ops);
+
+	return tsp->smk_task;
 }
 
 /*
security/smack/smack_access.c +1 -1
index db14689..b4b4044 100644
@@ -197,7 +197,7 @@ out_audit:
  */
 int smk_curacc(char *obj_label, u32 mode, struct smk_audit_info *a)
 {
-	struct task_smack *tsp = current_security();
+	struct task_smack *tsp = lsm_get_cred(current_cred(), &smack_ops);
 	char *sp = smk_of_task(tsp);
 	int may;
 	int rc;
security/smack/smack_lsm.c +163 -159

933 lines not on this page · raw message

security/smack/smackfs.c +9 -11
index 76a5dca..5335444 100644
@@ -108,7 +108,7 @@ struct smack_master_list {
 	struct smack_rule	*smk_rule;
 };
 
-LIST_HEAD(smack_rule_list);
+static LIST_HEAD(smack_rule_list);
 
 static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT;
 
@@ -1173,12 +1173,12 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
 	}
 	smk_netlabel_audit_set(&audit_info);
 
+	rc = 0;
 	if (found == 0) {
 		skp = kzalloc(sizeof(*skp), GFP_KERNEL);
 		if (skp == NULL)
 			rc = -ENOMEM;
 		else {
-			rc = 0;
 			skp->smk_host.sin_addr.s_addr = newname.sin_addr.s_addr;
 			skp->smk_mask.s_addr = mask.s_addr;
 			skp->smk_label = sp;
@@ -1191,8 +1191,6 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
 			rc = netlbl_cfg_unlbl_static_del(&init_net, NULL,
 					&skp->smk_host.sin_addr, &skp->smk_mask,
 					PF_INET, &audit_info);
-		else
-			rc = 0;
 		skp->smk_label = sp;
 	}
 
@@ -1582,7 +1580,7 @@ static ssize_t smk_write_onlycap(struct file *file, const char __user *buf,
 				 size_t count, loff_t *ppos)
 {
 	char *data;
-	char *sp = smk_of_task(current->cred->security);
+	char *sp = smk_of_task(lsm_get_cred(current->cred, &smack_ops));
 	int rc = count;
 
 	if (!smack_privileged(CAP_MAC_ADMIN))
@@ -1696,14 +1694,14 @@ static const struct file_operations smk_logging_ops = {
 
 static void *load_self_seq_start(struct seq_file *s, loff_t *pos)
 {
-	struct task_smack *tsp = current_security();
+	struct task_smack *tsp = lsm_get_cred(current_cred(), &smack_ops);
 
 	return smk_seq_start(s, pos, &tsp->smk_rules);
 }
 
 static void *load_self_seq_next(struct seq_file *s, void *v, loff_t *pos)
 {
-	struct task_smack *tsp = current_security();
+	struct task_smack *tsp = lsm_get_cred(current_cred(), &smack_ops);
 
 	return smk_seq_next(s, v, pos, &tsp->smk_rules);
 }
@@ -1750,7 +1748,7 @@ static int smk_open_load_self(struct inode *inode, struct file *file)
 static ssize_t smk_write_load_self(struct file *file, const char __user *buf,
 			      size_t count, loff_t *ppos)
 {
-	struct task_smack *tsp = current_security();
+	struct task_smack *tsp = lsm_get_cred(current_cred(), &smack_ops);
 
 	return smk_write_rules_list(file, buf, count, ppos, &tsp->smk_rules,
 				    &tsp->smk_rules_lock, SMK_FIXED24_FMT);
@@ -1905,14 +1903,14 @@ static const struct file_operations smk_load2_ops = {
 
 static void *load_self2_seq_start(struct seq_file *s, loff_t *pos)
 {
-	struct task_smack *tsp = current_security();
+	struct task_smack *tsp = lsm_get_cred(current_cred(), &smack_ops);
 
 	return smk_seq_start(s, pos, &tsp->smk_rules);
 }
 
 static void *load_self2_seq_next(struct seq_file *s, void *v, loff_t *pos)
 {
-	struct task_smack *tsp = current_security();
+	struct task_smack *tsp = lsm_get_cred(current_cred(), &smack_ops);
 
 	return smk_seq_next(s, v, pos, &tsp->smk_rules);
 }
@@ -1958,7 +1956,7 @@ static int smk_open_load_self2(struct inode *inode, struct file *file)
 static ssize_t smk_write_load_self2(struct file *file, const char __user *buf,
 			      size_t count, loff_t *ppos)
 {
-	struct task_smack *tsp = current_security();
+	struct task_smack *tsp = lsm_get_cred(current_cred(), &smack_ops);
 
 	return smk_write_rules_list(file, buf, count, ppos, &tsp->smk_rules,
 				    &tsp->smk_rules_lock, SMK_LONG_FMT);
security/tomoyo/common.h +4 -2
index d4f166b..ef0cdcc 100644
@@ -28,6 +28,7 @@
 #include <linux/in.h>
 #include <linux/in6.h>
 #include <linux/un.h>
+#include <linux/lsm.h>
 #include <net/sock.h>
 #include <net/af_unix.h>
 #include <net/ip.h>
@@ -1079,6 +1080,7 @@ extern struct list_head tomoyo_domain_list;
 extern struct list_head tomoyo_name_list[TOMOYO_MAX_HASH];
 extern struct list_head tomoyo_namespace_list;
 extern struct mutex tomoyo_policy_lock;
+extern struct security_operations tomoyo_security_ops;
 extern struct srcu_struct tomoyo_ss;
 extern struct tomoyo_domain_info tomoyo_kernel_domain;
 extern struct tomoyo_policy_namespace tomoyo_kernel_namespace;
@@ -1202,7 +1204,7 @@ static inline void tomoyo_put_group(struct tomoyo_group *group)
  */
 static inline struct tomoyo_domain_info *tomoyo_domain(void)
 {
-	return current_cred()->security;
+	return lsm_get_cred(current_cred(), &tomoyo_security_ops);
 }
 
 /**
@@ -1215,7 +1217,7 @@ static inline struct tomoyo_domain_info *tomoyo_domain(void)
 static inline struct tomoyo_domain_info *tomoyo_real_domain(struct task_struct
 							    *task)
 {
-	return task_cred_xxx(task, security);
+	return lsm_get_cred(__task_cred(task), &tomoyo_security_ops);
 }
 
 /**
security/tomoyo/domain.c +1 -1
index 3865145..15042e7 100644
@@ -840,7 +840,7 @@ force_jump_domain:
 		domain = old_domain;
 	/* Update reference count on "struct tomoyo_domain_info". */
 	atomic_inc(&domain->users);
-	bprm->cred->security = domain;
+	lsm_set_cred(bprm->cred, domain, &tomoyo_security_ops);
 	kfree(exename.name);
 	if (!retval) {
 		ee->r.domain = domain;
security/tomoyo/securityfs_if.c +6 -3
index fcf3278..2c0332c 100644
@@ -75,8 +75,10 @@ static ssize_t tomoyo_write_self(struct file *file, const char __user *buf,
 					error = -ENOMEM;
 				} else {
 					struct tomoyo_domain_info *old_domain =
-						cred->security;
-					cred->security = new_domain;
+						lsm_get_cred(cred,
+							&tomoyo_security_ops);
+					lsm_set_cred(cred, new_domain,
+							&tomoyo_security_ops);
 					atomic_inc(&new_domain->users);
 					atomic_dec(&old_domain->users);
 					commit_creds(cred);
@@ -242,7 +244,8 @@ static int __init tomoyo_initerface_init(void)
 	struct dentry *tomoyo_dir;
 
 	/* Don't create securityfs entries unless registered. */
-	if (current_cred()->security != &tomoyo_kernel_domain)
+	if (lsm_get_cred(current_cred(), &tomoyo_security_ops) !=
+			&tomoyo_kernel_domain)
 		return 0;
 
 	tomoyo_dir = securityfs_create_dir("tomoyo", NULL);
security/tomoyo/tomoyo.c +27 -14

95 lines not on this page · raw message

author maintainer
#2 lore raw

PATCH v13 2/9 LSM: Complete conversion to kill_pid_info_as_cred

In reply to a message not in the archive

Subject: [PATCH v13 2/9] LSM: Complete conversion to kill_pid_info_as_cred

The kill_pid_info_as_cred() function takes a secid as a parameter, but the value is always taken from the cred that is also passed as a parameter. Remove the secid parameter. Change the LSM interface to take the cred rather than the secid, eliminating the need to get or pass the secid in cases where it is unused.

The two LSMs that use this hook, SELinux and Smack, are updated.

---
 drivers/usb/core/devio.c   |   10 ++--------
 include/linux/sched.h      |    2 +-
 include/linux/security.h   |    9 +++++----
 kernel/signal.c            |    6 +++---
 security/selinux/hooks.c   |    7 +++----
 security/smack/smack_lsm.c |   10 +++++-----
 6 files changed, 19 insertions(+), 25 deletions(-)
drivers/usb/core/devio.c +2 -8
index 8823e98..18763ea 100644
@@ -75,7 +75,6 @@ struct dev_state {
 	const struct cred *cred;
 	void __user *disccontext;
 	unsigned long ifclaimed;
-	u32 secid;
 	u32 disabled_bulk_eps;
 };
 
@@ -91,7 +90,6 @@ struct async {
 	struct urb *urb;
 	unsigned int mem_usage;
 	int status;
-	u32 secid;
 	u8 bulk_addr;
 	u8 bulk_status;
 };
@@ -492,7 +490,6 @@ static void async_completed(struct urb *urb)
 	struct dev_state *ps = as->ps;
 	struct siginfo sinfo;
 	struct pid *pid = NULL;
-	u32 secid = 0;
 	const struct cred *cred = NULL;
 	int signr;
 
@@ -507,7 +504,6 @@ static void async_completed(struct urb *urb)
 		sinfo.si_addr = as->userurb;
 		pid = get_pid(as->pid);
 		cred = get_cred(as->cred);
-		secid = as->secid;
 	}
 	snoop(&urb->dev->dev, "urb complete\n");
 	snoop_urb(urb->dev, as->userurb, urb->pipe, urb->actual_length,
@@ -521,7 +517,7 @@ static void async_completed(struct urb *urb)
 	spin_unlock(&ps->lock);
 
 	if (signr) {
-		kill_pid_info_as_cred(sinfo.si_signo, &sinfo, pid, cred, secid);
+		kill_pid_info_as_cred(sinfo.si_signo, &sinfo, pid, cred);
 		put_pid(pid);
 		put_cred(cred);
 	}
@@ -815,7 +811,6 @@ static int usbdev_open(struct inode *inode, struct file *file)
 	ps->cred = get_current_cred();
 	ps->disccontext = NULL;
 	ps->ifclaimed = 0;
-	security_task_getsecid(current, &ps->secid);
 	smp_wmb();
 	list_add_tail(&ps->list, &dev->filelist);
 	file->private_data = ps;
@@ -1430,7 +1425,6 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
 	as->ifnum = ifnum;
 	as->pid = get_pid(task_pid(current));
 	as->cred = get_current_cred();
-	security_task_getsecid(current, &as->secid);
 	snoop_urb(ps->dev, as->userurb, as->urb->pipe,
 			as->urb->transfer_buffer_length, 0, SUBMIT,
 			NULL, 0);
@@ -2211,7 +2205,7 @@ static void usbdev_remove(struct usb_device *udev)
 			sinfo.si_code = SI_ASYNCIO;
 			sinfo.si_addr = ps->disccontext;
 			kill_pid_info_as_cred(ps->discsignr, &sinfo,
-					ps->disc_pid, ps->cred, ps->secid);
+					ps->disc_pid, ps->cred);
 		}
 	}
 }
include/linux/sched.h +1 -1
index e692a02..08a6871 100644
@@ -2164,7 +2164,7 @@ extern int force_sig_info(int, struct siginfo *, struct task_struct *);
 extern int __kill_pgrp_info(int sig, struct siginfo *info, struct pid *pgrp);
 extern int kill_pid_info(int sig, struct siginfo *info, struct pid *pid);
 extern int kill_pid_info_as_cred(int, struct siginfo *, struct pid *,
-				const struct cred *, u32);
+				const struct cred *);
 extern int kill_pgrp(struct pid *pid, int sig, int priv);
 extern int kill_pid(struct pid *pid, int sig, int priv);
 extern int kill_proc_info(int, struct siginfo *, pid_t);
include/linux/security.h +5 -4
index 032c366..a1079ab 100644
@@ -777,7 +777,7 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
  *	@p contains the task_struct for process.
  *	@info contains the signal information.
  *	@sig contains the signal value.
- *	@secid contains the sid of the process where the signal originated
+ *	@cred contains the sid of the process where the signal originated
  *	Return 0 if permission is granted.
  * @task_wait:
  *	Check permission before allowing a process to reap a child process @p
@@ -1546,7 +1546,8 @@ struct security_operations {
 	int (*task_getscheduler) (struct task_struct *p);
 	int (*task_movememory) (struct task_struct *p);
 	int (*task_kill) (struct task_struct *p,
-			  struct siginfo *info, int sig, u32 secid);
+			  struct siginfo *info, int sig,
+			  const struct cred *cred);
 	int (*task_wait) (struct task_struct *p);
 	int (*task_prctl) (int option, unsigned long arg2,
 			   unsigned long arg3, unsigned long arg4,
@@ -1808,7 +1809,7 @@ int security_task_setscheduler(struct task_struct *p);
 int security_task_getscheduler(struct task_struct *p);
 int security_task_movememory(struct task_struct *p);
 int security_task_kill(struct task_struct *p, struct siginfo *info,
-			int sig, u32 secid);
+			int sig, const struct cred *cred);
 int security_task_wait(struct task_struct *p);
 int security_task_prctl(int option, unsigned long arg2, unsigned long arg3,
 			unsigned long arg4, unsigned long arg5);
@@ -2377,7 +2378,7 @@ static inline int security_task_movememory(struct task_struct *p)
 
 static inline int security_task_kill(struct task_struct *p,
 				     struct siginfo *info, int sig,
-				     u32 secid)
+				     const struct cred *cred)
 {
 	return 0;
 }
kernel/signal.c +3 -3
index dd72567..c702648 100644
@@ -815,7 +815,7 @@ static int check_kill_permission(int sig, struct siginfo *info,
 		}
 	}
 
-	return security_task_kill(t, info, sig, 0);
+	return security_task_kill(t, info, sig, NULL);
 }
 
 /**
@@ -1388,7 +1388,7 @@ static int kill_as_cred_perm(const struct cred *cred,
 
 /* like kill_pid_info(), but doesn't use uid/euid of "current" */
 int kill_pid_info_as_cred(int sig, struct siginfo *info, struct pid *pid,
-			 const struct cred *cred, u32 secid)
+			 const struct cred *cred)
 {
 	int ret = -EINVAL;
 	struct task_struct *p;
@@ -1407,7 +1407,7 @@ int kill_pid_info_as_cred(int sig, struct siginfo *info, struct pid *pid,
 		ret = -EPERM;
 		goto out_unlock;
 	}
-	ret = security_task_kill(p, info, sig, secid);
+	ret = security_task_kill(p, info, sig, cred);
 	if (ret)
 		goto out_unlock;
 
security/selinux/hooks.c +3 -4
index ddaec58..9ff6d6d 100644
@@ -3476,7 +3476,7 @@ static int selinux_task_movememory(struct task_struct *p)
 }
 
 static int selinux_task_kill(struct task_struct *p, struct siginfo *info,
-				int sig, u32 secid)
+				int sig, const struct cred *crd)
 {
 	u32 perm;
 	int rc;
@@ -3486,9 +3486,8 @@ static int selinux_task_kill(struct task_struct *p, struct siginfo *info,
 	else
 		perm = signal_to_av(sig);
 
-	if (secid)
-		rc = avc_has_perm(secid, task_sid(p),
-				  SECCLASS_PROCESS, perm, NULL);
+	if (crd)
+		rc = cred_has_perm(crd, __task_cred(p), perm);
 	else
 		rc = current_has_perm(p, perm);
 	return rc;
security/smack/smack_lsm.c +5 -5
index 5fef975..223bbdf 100644
@@ -1664,7 +1664,7 @@ static int smack_task_movememory(struct task_struct *p)
  * @p: the task object
  * @info: unused
  * @sig: unused
- * @secid: identifies the smack to use in lieu of current's
+ * @subcred: identifies the smack to use in lieu of current's
  *
  * Return 0 if write access is permitted
  *
@@ -1672,7 +1672,7 @@ static int smack_task_movememory(struct task_struct *p)
  * in the USB code. Someday it may go away.
  */
 static int smack_task_kill(struct task_struct *p, struct siginfo *info,
-			   int sig, u32 secid)
+			   int sig, const struct cred *subcred)
 {
 	struct smk_audit_info ad;
 
@@ -1682,15 +1682,15 @@ static int smack_task_kill(struct task_struct *p, struct siginfo *info,
 	 * Sending a signal requires that the sender
 	 * can write the receiver.
 	 */
-	if (secid == 0)
+	if (subcred == NULL)
 		return smk_curacc(smk_of_task(task_security(p)), MAY_WRITE,
 				  &ad);
 	/*
-	 * If the secid isn't 0 we're dealing with some USB IO
+	 * If the subcred isn't NULL we're dealing with some USB IO
 	 * specific behavior. This is not clean. For one thing
 	 * we can't take privilege into account.
 	 */
-	return smk_access(smack_from_secid(secid),
+	return smk_access(smk_of_task(lsm_get_cred(subcred, &smack_ops)),
 			  smk_of_task(task_security(p)), MAY_WRITE, &ad);
 }
 

--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.

author maintainer
#3 lore raw

v13 cover LSM: Multiple concurrent LSMs

In reply to a message not in the archive

Subject: [PATCH v13 0/9] LSM: Multiple concurrent LSMs

Change the infrastructure for Linux Security Modules (LSM)s from a single vector of hook handlers to a list based method for handling multiple concurrent modules.

The "security=" boot option takes a comma separated list of LSMs, registering them in the order presented. The LSM hooks will be executed in the order registered. Hooks that return errors are not short circuited. All hooks are called even if one of the LSM hooks fails. The result returned will be that of the last LSM hook that failed.

All behavior from security/capability.c has been moved into the hook handling. The security/commoncap functions used to get called from the LSM specific code. The handling of the capability functions has been moved out of the LSMs and into the hook handling.

A level of indirection has been introduced in the handling of security blobs. LSMs no longer access ->security fields directly, instead they use an abstraction provided by lsm_[gs]et field functions.

The notion that "the security context" can be represented as a single u32 "secid" does not scale to the case where multiple LSMs want to provide "the security context". There are two types of use for secids, logging and networking. Logging is addressed by replacing the secid with a set of secids. Networking is addressed by allocating each scheme to a specific LSM.

The NetLabel, XFRM and secmark facilities are restricted to use by one LSM at a time. This is due to limitations of the underlying networking mechanisms. The good news is that viable configurations can be created. The bad news is that the complexity of configuring a system is necessarily increased.

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.

A "security context" may now contrain information processed by more than one LSM. The proper form of a security context identifies the information it contains by LSM:

	smack='Pop'selinux='system_u:object_r:etc_r:s0'

A security context without the LSM identifying lsm='<text>' gets passed through to all of the LSMs that use a security context. This maintains compatability in the case where there is only one LSM using the security context.

---
 Documentation/security/LSM.txt                     |   39 +-
 drivers/usb/core/devio.c                           |   10 +-
 fs/proc/base.c                                     |   29 +-
 fs/sysfs/dir.c                                     |    3 +-
 fs/sysfs/inode.c                                   |    5 +-
 fs/sysfs/sysfs.h                                   |    7 +-
 fs/xattr.c                                         |    8 +-
 include/linux/audit.h                              |    9 +-
 include/linux/cred.h                               |    3 +-
 include/linux/lsm.h                                |  167 ++
 include/linux/sched.h                              |    2 +-
 include/linux/security.h                           |  378 +++-
 include/net/af_unix.h                              |    3 +-
 include/net/netlabel.h                             |    3 +-
 include/net/scm.h                                  |    8 +-
 include/net/xfrm.h                                 |    4 +-
 kernel/audit.c                                     |   94 +-
 kernel/audit.h                                     |    4 +-
 kernel/auditfilter.c                               |   21 +-
 kernel/auditsc.c                                   |   80 +-
 kernel/cred.c                                      |    6 +-
 kernel/signal.c                                    |    6 +-
 net/ipv4/ip_sockglue.c                             |    8 +-
 .../netfilter/nf_conntrack_l3proto_ipv4_compat.c   |   11 +-
 net/netfilter/nf_conntrack_netlink.c               |   24 +-
 net/netfilter/nf_conntrack_standalone.c            |   11 +-
 net/netfilter/xt_SECMARK.c                         |    4 +-
 net/netlabel/netlabel_kapi.c                       |   37 +-
 net/netlabel/netlabel_unlabeled.c                  |   22 +-
 net/netlabel/netlabel_user.c                       |    4 +-
 net/netlabel/netlabel_user.h                       |   61 +-
 net/unix/af_unix.c                                 |   17 +-
 net/xfrm/xfrm_user.c                               |   16 +-
 security/Kconfig                                   |  176 +-
 security/Makefile                                  |    3 +-
 security/apparmor/context.c                        |   10 +-
 security/apparmor/domain.c                         |   19 +-
 security/apparmor/include/context.h                |   13 +-
 security/apparmor/lsm.c                            |   68 +-
 security/capability.c                              | 1105 -----------
 security/commoncap.c                               |    6 -
 security/inode.c                                   |   79 +-
 security/integrity/ima/ima_policy.c                |    7 +-
 security/security.c                                | 2014 ++++++++++++++++----
 security/selinux/hooks.c                           |  412 ++--
 security/selinux/include/objsec.h                  |    2 +
 security/selinux/include/xfrm.h                    |    2 +-
 security/selinux/netlabel.c                        |   17 +-
 security/selinux/selinuxfs.c                       |    6 +-
 security/selinux/xfrm.c                            |    9 +-
 security/smack/smack.h                             |   15 +-
 security/smack/smack_access.c                      |    2 +-
 security/smack/smack_lsm.c                         |  474 +++--
 security/smack/smackfs.c                           |   56 +-
 security/tomoyo/common.h                           |    6 +-
 security/tomoyo/domain.c                           |    2 +-
 security/tomoyo/securityfs_if.c                    |    9 +-
 security/tomoyo/tomoyo.c                           |   49 +-
 security/yama/Kconfig                              |    7 -
 security/yama/yama_lsm.c                           |   35 +-
 60 files changed, 3357 insertions(+), 2350 deletions(-)

--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.

maintainer
#4 lore raw

Re: [PATCH v13 0/9] LSM: Multiple concurrent LSMs

Quoted 12 lines · Casey Schaufler

Subject: [PATCH v13 0/9] LSM: Multiple concurrent LSMs

Change the infrastructure for Linux Security Modules (LSM)s from a single vector of hook handlers to a list based method for handling multiple concurrent modules.

The "security=" boot option takes a comma separated list of LSMs, registering them in the order presented. The LSM hooks will be executed in the order registered. Hooks that return errors are not short circuited. All hooks are called even if one of the LSM hooks fails. The result returned will be that of the last LSM hook that failed.

...

Quoted 5 lines

The NetLabel, XFRM and secmark facilities are restricted to use by one LSM at a time. This is due to limitations of the underlying networking mechanisms. The good news is that viable configurations can be created. The bad news is that the complexity of configuring a system is necessarily increased.

I know we had a good discussion about this a while back and I just wanted to hear from you about this current patchset; how does the labeled networking LSM assignment work? Is it first-come-first-served based on the 'security=' setting?

Signature · 2 lines
paul moore
www.paul-moore.com
author maintainer
#5 lore raw

Re: [PATCH v13 0/9] LSM: Multiple concurrent LSMs

Quoted 20 lines · Paul Moore
Quoted 12 lines · Casey Schaufler

Subject: [PATCH v13 0/9] LSM: Multiple concurrent LSMs

Change the infrastructure for Linux Security Modules (LSM)s from a single vector of hook handlers to a list based method for handling multiple concurrent modules.

The "security=" boot option takes a comma separated list of LSMs, registering them in the order presented. The LSM hooks will be executed in the order registered. Hooks that return errors are not short circuited. All hooks are called even if one of the LSM hooks fails. The result returned will be that of the last LSM hook that failed.

...

Quoted 5 lines

The NetLabel, XFRM and secmark facilities are restricted to use by one LSM at a time. This is due to limitations of the underlying networking mechanisms. The good news is that viable configurations can be created. The bad news is that the complexity of configuring a system is necessarily increased.

Quoted 4 lines

I know we had a good discussion about this a while back and I just wanted to hear from you about this current patchset; how does the labeled networking LSM assignment work? Is it first-come-first-served based on the 'security=' setting?

It's explicitly set in security/Kconfig. The problem with first-come-first-serve is that the LSMs don't actually register in the order specified, either at build time or boot time. Further, until the init phase is complete, you don't know which LSMs are actually going to register. That, and I promised Tetsuo I wouldn't go out of my way to prevent late module loading in the future.

I could do order checking on module registration and take the networking component away from an LSM that registered earlier, but with a larger order number I suppose.

The default configuration gives xfrm and secmark to SELinux and NetLabel to Smack. If Smack is not included NetLabel goes to SELinux. When LSMs using any of these facilities are added in the future we'll have to negotiate the defaults.

An interesting aside that may be relevant is that the error condition behavior makes it advisable to have the LSM you care about most go last. If the networking components were strictly FCFS you might have to chose an ordering you might not want for other reasons.

It would be possible to have a boot time specification for the networking components if you think it's important. I do worry about making it excessively complicated. I'd be much more concerned if more LSMs used the networking components.

maintainer
#6 lore raw

Re: [PATCH v13 0/9] LSM: Multiple concurrent LSMs

Quoted 14 lines · Casey Schaufler
Quoted 4 lines · Paul Moore

I know we had a good discussion about this a while back and I just wanted to hear from you about this current patchset; how does the labeled networking LSM assignment work? Is it first-come-first-served based on the 'security=' setting?

It's explicitly set in security/Kconfig. The problem with first-come-first-serve is that the LSMs don't actually register in the order specified, either at build time or boot time. Further, until the init phase is complete, you don't know which LSMs are actually going to register. That, and I promised Tetsuo I wouldn't go out of my way to prevent late module loading in the future.

Quoted 3 lines

I could do order checking on module registration and take the networking component away from an LSM that registered earlier, but with a larger order number I suppose.

Hmmm. How difficult would it be to enforce the order during LSM registration? As discussed previously, I'm not a big fan of assigning the network controls at compile time when the LSMs can be toggled at boot time.

The real solution is to just get the netdev folks to accept a security blob in the sk_buff so we can fix this (and many other problems) once and for all. I still haven't given up on this effort but I think it would be silly to hold up the stacking effort for the sk_buff security blob.

Quoted 4 lines

The default configuration gives xfrm and secmark to SELinux and NetLabel to Smack. If Smack is not included NetLabel goes to SELinux. When LSMs using any of these facilities are added in the future we'll have to negotiate the defaults.

The defaults are always going to be wrong for someone.

Quoted 5 lines

An interesting aside that may be relevant is that the error condition behavior makes it advisable to have the LSM you care about most go last. If the networking components were strictly FCFS you might have to chose an ordering you might not want for other reasons.

Well, maybe not ... I think. If we take a FCFS approach to the network controls then only one LSM is really ever going to throw an error on the network hooks, yes?

Quoted 4 lines

It would be possible to have a boot time specification for the networking components if you think it's important. I do worry about making it excessively complicated. I'd be much more concerned if more LSMs used the networking components.

I think the "excessively complicated" boat has already sailed :)

I'm still in favor of assigning the network hooks to the LSM at boot based on the "security=" configuration.

Signature · 2 lines
paul moore
www.paul-moore.com
maintainer
#7 lore raw

Re: [PATCH v13 0/9] LSM: Multiple concurrent LSMs

Quoted 50 lines · Paul Moore
Quoted 14 lines · Casey Schaufler
Quoted 4 lines · Paul Moore

I know we had a good discussion about this a while back and I just wanted to hear from you about this current patchset; how does the labeled networking LSM assignment work? Is it first-come-first-served based on the 'security=' setting?

It's explicitly set in security/Kconfig. The problem with first-come-first-serve is that the LSMs don't actually register in the order specified, either at build time or boot time. Further, until the init phase is complete, you don't know which LSMs are actually going to register. That, and I promised Tetsuo I wouldn't go out of my way to prevent late module loading in the future.

Quoted 3 lines

I could do order checking on module registration and take the networking component away from an LSM that registered earlier, but with a larger order number I suppose.

Hmmm. How difficult would it be to enforce the order during LSM registration? As discussed previously, I'm not a big fan of assigning the network controls at compile time when the LSMs can be toggled at boot time.

The real solution is to just get the netdev folks to accept a security blob in the sk_buff so we can fix this (and many other problems) once and for all. I still haven't given up on this effort but I think it would be silly to hold up the stacking effort for the sk_buff security blob.

Quoted 4 lines

The default configuration gives xfrm and secmark to SELinux and NetLabel to Smack. If Smack is not included NetLabel goes to SELinux. When LSMs using any of these facilities are added in the future we'll have to negotiate the defaults.

The defaults are always going to be wrong for someone.

Quoted 5 lines

An interesting aside that may be relevant is that the error condition behavior makes it advisable to have the LSM you care about most go last. If the networking components were strictly FCFS you might have to chose an ordering you might not want for other reasons.

Well, maybe not ... I think. If we take a FCFS approach to the network controls then only one LSM is really ever going to throw an error on the network hooks, yes?

Quoted 4 lines

It would be possible to have a boot time specification for the networking components if you think it's important. I do worry about making it excessively complicated. I'd be much more concerned if more LSMs used the networking components.

Quoted 5 lines

I think the "excessively complicated" boat has already sailed :)

I'm still in favor of assigning the network hooks to the LSM at boot based on the "security=" configuration.

yeah dealing with selection at boot time is going to be needed at some point, whether its now or later ...

author maintainer
#8 lore raw

Re: [PATCH v13 0/9] LSM: Multiple concurrent LSMs

Quoted 18 lines · John Johansen
Quoted 17 lines · Paul Moore
Quoted 16 lines · Casey Schaufler
Quoted 4 lines · Paul Moore

I know we had a good discussion about this a while back and I just wanted to hear from you about this current patchset; how does the labeled networking LSM assignment work? Is it first-come-first-served based on the 'security=' setting?

It's explicitly set in security/Kconfig. The problem with first-come-first-serve is that the LSMs don't actually register in the order specified, either at build time or boot time. Further, until the init phase is complete, you don't know which LSMs are actually going to register. That, and I promised Tetsuo I wouldn't go out of my way to prevent late module loading in the future.

I could do order checking on module registration and take the networking component away from an LSM that registered earlier, but with a larger order number I suppose.

Quoted 8 lines
Quoted 8 lines

Hmmm. How difficult would it be to enforce the order during LSM registration? As discussed previously, I'm not a big fan of assigning the network controls at compile time when the LSMs can be toggled at boot time.

The real solution is to just get the netdev folks to accept a security blob in the sk_buff so we can fix this (and many other problems) once and for all. I still haven't given up on this effort but I think it would be silly to hold up the stacking effort for the sk_buff security blob.

Fighting with hardcore networking people isn't my idea of fun either. Waiting for them to approve of a security facility has never been a winning strategy.

Quoted 6 lines
Quoted 6 lines
Quoted 4 lines

The default configuration gives xfrm and secmark to SELinux and NetLabel to Smack. If Smack is not included NetLabel goes to SELinux. When LSMs using any of these facilities are added in the future we'll have to negotiate the defaults.

The defaults are always going to be wrong for someone.

Quoted 8 lines
Quoted 8 lines
Quoted 5 lines

An interesting aside that may be relevant is that the error condition behavior makes it advisable to have the LSM you care about most go last. If the networking components were strictly FCFS you might have to chose an ordering you might not want for other reasons.

Well, maybe not ... I think. If we take a FCFS approach to the network controls then only one LSM is really ever going to throw an error on the network hooks, yes?

You set up the order you want to get the networking handled correctly and you could get filesystem hooks in the wrong order. Not that that really ought to be a problem, but there are wonky admin tools out there.

Quoted 5 lines
Quoted 5 lines
Quoted 4 lines

It would be possible to have a boot time specification for the networking components if you think it's important. I do worry about making it excessively complicated. I'd be much more concerned if more LSMs used the networking components.

I think the "excessively complicated" boat has already sailed :)

Fair enough.

Quoted 5 lines
Quoted 3 lines

I'm still in favor of assigning the network hooks to the LSM at boot based on the "security=" configuration.

yeah dealing with selection at boot time is going to be needed at some point, whether its now or later ...

I'll have a go at it then. What that would mean is that:

security=smack,selinux

gives Smack NetLabel and SELinux xfrm and secmark while

security=selinux,smack

gives SELinux all three. I would still like it to be possible to explicitly configure the allocation at build time.

Quoted 6 lines

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.

maintainer
#9 lore raw

Re: [PATCH v13 0/9] LSM: Multiple concurrent LSMs

Quoted 8 lines · Casey Schaufler
Quoted 5 lines
Quoted 3 lines

I'm still in favor of assigning the network hooks to the LSM at boot based on the "security=" configuration.

yeah dealing with selection at boot time is going to be needed at some point, whether its now or later ...

I'll have a go at it then. What that would mean is that:

Quoted 8 lines

security=smack,selinux

gives Smack NetLabel and SELinux xfrm and secmark while

security=selinux,smack

gives SELinux all three. I would still like it to be possible to explicitly configure the allocation at build time.

The problem is that it is difficult to control the registration order since each LSM module directly calls security_initcall() for registering themselves?

Then, what about replacing

  static int __init foo_init()
  {
    register_security(&foo_security_ops);
    return 0;
  }
  security_initcall(foo_init);

  static int __init bar_init()
  {
    register_security(&bar_security_ops);
    return 0;
  }
  security_initcall(bar_init);

with

  static int __init foo_init()
  {
    register_security(&foo_security_ops);
    return 0;
  }

  static int __init bar_init()
  {
    register_security(&bar_security_ops);
    return 0;
  }

  static int __init add_foo(void) {
    foo_security_ops.register = foo_init;
    list_add_tail(&foo_security_ops.list[lsm_candidate], &lsm_hooks[lsm_candidate]);
    return 0;
  }
  pure_initcall(add_foo);

  static int __init add_bar(void) {
    bar_security_ops.register = bar_init;
    list_add_tail(&bar_security_ops.list[lsm_candidate], &lsm_hooks[lsm_candidate]);
    return 0;
  }
  pure_initcall(add_bar);

and let security/security.c register in accordance with security= parameter (or compile-time config if none given)?

  static int __init register_lsms(void)
  {
    for_each_comma_separated_lsm_names_given() {
      bool found = 0;
      list_for_each_entry_safe(ops, tmp, &lsm_hooks[lsm_candidate]) {
        if (!strcmp(ops->name, name)) {
          if (ops->register() == 0)
            list_del(&ops->list[lsm_candidate]);
          found = 1;
          break;
        }
      }
      if (!found) {
        printk("LSM module %s was not found\n", name);
      }
    }
    list_for_each_entry_safe(ops, tmp, &lsm_hooks[lsm_candidate]) {
      list_del(&ops->list[lsm_candidate]);
      printk("LSM module %s was not enabled\n", ops->name);
    }
  }
  security_initcall(register_lsms);

(Well, list_add_tail() in pure_initcall functions should be optimized
by statically embedding into security/security.c at compile time?)

maintainer
#10 lore raw

Re: [PATCH v13 0/9] LSM: Multiple concurrent LSMs

In reply to Casey Schaufler
Quoted 3 lines · Casey Schaufler
Quoted 2 lines · John Johansen
Quoted 1 line · Paul Moore

On Wednesday, April 24, 2013 01:22:20 PM Casey Schaufler wrote:

...

Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 5 lines

An interesting aside that may be relevant is that the error condition behavior makes it advisable to have the LSM you care about most go last. If the networking components were strictly FCFS you might have to chose an ordering you might not want for other reasons.

Quoted 8 lines
Quoted 3 lines
Quoted 3 lines

Well, maybe not ... I think. If we take a FCFS approach to the network controls then only one LSM is really ever going to throw an error on the network hooks, yes?

You set up the order you want to get the networking handled correctly and you could get filesystem hooks in the wrong order. Not that that really ought to be a problem, but there are wonky admin tools out there.

I don't quite follow; can you be a bit more explicit about getting the filesystem hooks in the wrong order?

Quoted 8 lines
Quoted 5 lines
Quoted 2 lines

I'm still in favor of assigning the network hooks to the LSM at boot based on the "security=" configuration.

yeah dealing with selection at boot time is going to be needed at some point, whether its now or later ...

I'll have a go at it then. What that would mean is that:

Quoted 7 lines

security=smack,selinux

gives Smack NetLabel and SELinux xfrm and secmark while

security=selinux,smack

gives SELinux all three.

That seems reasonable, it also keeps the door open for adding a specific network hook ordering option, e.g. "security_net=", at a later date if necessary.

Quoted 2 lines

I would still like it to be possible to explicitly configure the allocation at build time.

I suppose I have no object to that, I would just place my vote to have the dynamic FCFS (or LCFS if that makes more sense) assignment be the Kconfig default.

Signature · 8 lines
paul moore
www.paul-moore.com


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to [email protected] with
the words "unsubscribe selinux" without quotes as the message.
author maintainer
#11 lore raw

Re: [PATCH v13 0/9] LSM: Multiple concurrent LSMs

Quoted 14 lines · Paul Moore
Quoted 3 lines · Casey Schaufler
Quoted 2 lines · John Johansen
Quoted 1 line · Paul Moore

On Wednesday, April 24, 2013 01:22:20 PM Casey Schaufler wrote:

...

Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 5 lines

An interesting aside that may be relevant is that the error condition behavior makes it advisable to have the LSM you care about most go last. If the networking components were strictly FCFS you might have to chose an ordering you might not want for other reasons.

Well, maybe not ... I think. If we take a FCFS approach to the network controls then only one LSM is really ever going to throw an error on the network hooks, yes?

Quoted 6 lines
Quoted 4 lines

You set up the order you want to get the networking handled correctly and you could get filesystem hooks in the wrong order. Not that that really ought to be a problem, but there are wonky admin tools out there.

I don't quite follow; can you be a bit more explicit about getting the filesystem hooks in the wrong order?

Let's assume that there's a case for the stat() system call that would get EPERM from SELinux and EACCES from Smack. A carefully crafted admin tool might take different actions based on the return code. If Smack ahead of SELinux in the list the tool will respond one way, whereas if SELinux is ahead it will behave the other way.

If this tool came with Fedora it will likely expect the SELinux error code. Thus, it will be somewhat important that Smack precede SELinux in the LSM ordering. That will grant Smack the NetLabel component. If you want SELinux to use NetLabel you'll have to explicitly configure that.

It's probably not going to be an issue that often. Making the ordering implications clear to those who may be affected by them is probably the best choice and biggest challenge. It would be nice to keep them to a minimum. I fear some future LSM author getting clever with error codes and demanding the ultimate position in all cases.

Quoted 17 lines
Quoted 6 lines
Quoted 4 lines
Quoted 2 lines

I'm still in favor of assigning the network hooks to the LSM at boot based on the "security=" configuration.

yeah dealing with selection at boot time is going to be needed at some point, whether its now or later ...

I'll have a go at it then. What that would mean is that:

Quoted 7 lines

security=smack,selinux

gives Smack NetLabel and SELinux xfrm and secmark while

security=selinux,smack

gives SELinux all three.

That seems reasonable, it also keeps the door open for adding a specific network hook ordering option, e.g. "security_net=", at a later date if necessary.

Quoted 6 lines
Quoted 2 lines

I would still like it to be possible to explicitly configure the allocation at build time.

I suppose I have no object to that, I would just place my vote to have the dynamic FCFS (or LCFS if that makes more sense) assignment be the Kconfig default.

--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.

maintainer
#12 lore raw

Re: [PATCH v13 0/9] LSM: Multiple concurrent LSMs

Quoted 38 lines · Casey Schaufler
Quoted 17 lines · Paul Moore
Quoted 3 lines · Casey Schaufler
Quoted 2 lines · John Johansen
Quoted 1 line · Paul Moore

On Wednesday, April 24, 2013 01:22:20 PM Casey Schaufler wrote:

...

Quoted 11 lines
Quoted 10 lines
Quoted 10 lines
Quoted 5 lines

An interesting aside that may be relevant is that the error condition behavior makes it advisable to have the LSM you care about most go last. If the networking components were strictly FCFS you might have to chose an ordering you might not want for other reasons.

Well, maybe not ... I think. If we take a FCFS approach to the network controls then only one LSM is really ever going to throw an error on the
network hooks, yes?

Quoted 7 lines
Quoted 4 lines

You set up the order you want to get the networking handled correctly and you could get filesystem hooks in the wrong order. Not that that really ought to be a problem, but there are wonky admin tools out there.

I don't quite follow; can you be a bit more explicit about getting the filesystem hooks in the wrong order?

Let's assume that there's a case for the stat() system call that would get EPERM from SELinux and EACCES from Smack. A carefully crafted admin tool might take different actions based on the return code. If Smack ahead of SELinux in the list the tool will respond one way, whereas if SELinux is ahead it will behave the other way.

If this tool came with Fedora it will likely expect the SELinux error code. Thus, it will be somewhat important that Smack precede SELinux in the LSM ordering. That will grant Smack the NetLabel component. If you want SELinux to use NetLabel you'll have to explicitly configure that.

Quoted 6 lines

It's probably not going to be an issue that often. Making the ordering implications clear to those who may be affected by them is probably the best choice and biggest challenge. It would be nice to keep them to a minimum. I fear some future LSM author getting clever with error codes and demanding the ultimate position in all cases.

I guess this begs the question, why does the stacking take the return value from the last LSM and not the first? I'm sure there was a design decision made here, I'm just curious about the reasons why.

To me, and maybe I'm the odd one out here, but I would think that the first LSM in the stacking order should get precedence; this is why I'm pushing for a FCFS for the network controls. If it turns out that the stacking patches give preference for the last LSM in the stacking order (I think this will always seem backwards to me) then we should probably give the networking controls to the last LSM.

Signature · 8 lines
paul moore
www.paul-moore.com


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to [email protected] with
the words "unsubscribe selinux" without quotes as the message.
author maintainer
#13 lore raw

Re: [PATCH v13 0/9] LSM: Multiple concurrent LSMs

Quoted 41 lines · Paul Moore
Quoted 34 lines · Casey Schaufler
Quoted 15 lines · Paul Moore
Quoted 3 lines · Casey Schaufler
Quoted 2 lines · John Johansen
Quoted 1 line · Paul Moore

On Wednesday, April 24, 2013 01:22:20 PM Casey Schaufler wrote:

...

Quoted 9 lines
Quoted 9 lines
Quoted 9 lines
Quoted 5 lines

An interesting aside that may be relevant is that the error condition behavior makes it advisable to have the LSM you care about most go last. If the networking components were strictly FCFS you might have to chose an ordering you might not want for other reasons.

Well, maybe not ... I think. If we take a FCFS approach to the network controls then only one LSM is really ever going to throw an error on the
network hooks, yes?

Quoted 6 lines
Quoted 4 lines

You set up the order you want to get the networking handled correctly and you could get filesystem hooks in the wrong order. Not that that really ought to be a problem, but there are wonky admin tools out there.

I don't quite follow; can you be a bit more explicit about getting the filesystem hooks in the wrong order?

Let's assume that there's a case for the stat() system call that would get EPERM from SELinux and EACCES from Smack. A carefully crafted admin tool might take different actions based on the return code. If Smack ahead of SELinux in the list the tool will respond one way, whereas if SELinux is ahead it will behave the other way.

If this tool came with Fedora it will likely expect the SELinux error code. Thus, it will be somewhat important that Smack precede SELinux in the LSM ordering. That will grant Smack the NetLabel component. If you want SELinux to use NetLabel you'll have to explicitly configure that.

Quoted 6 lines

It's probably not going to be an issue that often. Making the ordering implications clear to those who may be affected by them is probably the best choice and biggest challenge. It would be nice to keep them to a minimum. I fear some future LSM author getting clever with error codes and demanding the ultimate position in all cases.

Quoted 3 lines

I guess this begs the question, why does the stacking take the return value from the last LSM and not the first? I'm sure there was a design decision made here, I'm just curious about the reasons why.

The hook loop is trivially simpler if you return the last error than if you return the first error:

	if (thisrc)
		rc = thisrc;

vs

	if (thisrc && !rc)
		rc = thisrc;

If I had decided to do shortcutting (return on first failure) it would be a different story.

Quoted 1 line

To me, and maybe I'm the odd one out here,

I don't know that you're the only odd one here. :)

Quoted 2 lines

but I would think that the first
LSM in the stacking order should get precedence;

My desire and intent is that to the extent possible there should be no "principle" LSM. The choice of last error is purely driven by the fact that it's the easiest thing to do.

Quoted 5 lines

this is why I'm pushing for a
FCFS for the network controls. If it turns out that the stacking patches give preference for the last LSM in the stacking order (I think this will always seem backwards to me) then we should probably give the networking controls to the last LSM.

I actually think that FCFS for networking services and last error code hits closest to the sweet spot. "security=yama,smack,selinux" would give NetLabel to Smack and xfrm and secmark to SELinux. It would also give SELinux error returns in cases where there are multiple reasons for denial. Since SELinux has a more sophisticated runtime environment than Smack this is likely to make Fedora (for example) happier.

#14 lore raw

Re: [PATCH v13 0/9] LSM: Multiple concurrent LSMs

Quoted 77 lines · Casey Schaufler
Quoted 41 lines · Paul Moore
Quoted 34 lines · Casey Schaufler
Quoted 15 lines · Paul Moore
Quoted 3 lines · Casey Schaufler
Quoted 2 lines · John Johansen
Quoted 1 line · Paul Moore

On Wednesday, April 24, 2013 01:22:20 PM Casey Schaufler wrote:

...

Quoted 9 lines
Quoted 9 lines
Quoted 9 lines
Quoted 5 lines

An interesting aside that may be relevant is that the error condition behavior makes it advisable to have the LSM you care about most go last. If the networking components were strictly FCFS you might have to chose an ordering you might not want for other reasons.

Well, maybe not ... I think. If we take a FCFS approach to the network controls then only one LSM is really ever going to throw an error on the
network hooks, yes?

Quoted 6 lines
Quoted 4 lines

You set up the order you want to get the networking handled correctly and you could get filesystem hooks in the wrong order. Not that that really ought to be a problem, but there are wonky admin tools out there.

I don't quite follow; can you be a bit more explicit about getting the filesystem hooks in the wrong order?

Let's assume that there's a case for the stat() system call that would get EPERM from SELinux and EACCES from Smack. A carefully crafted admin tool might take different actions based on the return code. If Smack ahead of SELinux in the list the tool will respond one way, whereas if SELinux is ahead it will behave the other way.

If this tool came with Fedora it will likely expect the SELinux error code. Thus, it will be somewhat important that Smack precede SELinux in the LSM ordering. That will grant Smack the NetLabel component. If you want SELinux to use NetLabel you'll have to explicitly configure that.

Quoted 6 lines

It's probably not going to be an issue that often. Making the ordering implications clear to those who may be affected by them is probably the best choice and biggest challenge. It would be nice to keep them to a minimum. I fear some future LSM author getting clever with error codes and demanding the ultimate position in all cases.

Quoted 3 lines

I guess this begs the question, why does the stacking take the return value from the last LSM and not the first? I'm sure there was a design decision made here, I'm just curious about the reasons why.

The hook loop is trivially simpler if you return the last error than if you return the first error:

        if (thisrc)
                rc = thisrc;

vs

        if (thisrc && !rc)
                rc = thisrc;

If I had decided to do shortcutting (return on first failure) it would be a different story.

Quoted 1 line

To me, and maybe I'm the odd one out here,

I don't know that you're the only odd one here. :)

Quoted 2 lines

but I would think that the first
LSM in the stacking order should get precedence;

My desire and intent is that to the extent possible there should be no "principle" LSM. The choice of last error is purely driven by the fact that it's the easiest thing to do.

Quoted 5 lines

this is why I'm pushing for a
FCFS for the network controls. If it turns out that the stacking patches give preference for the last LSM in the stacking order (I think this will always seem backwards to me) then we should probably give the networking controls to the last LSM.

Quoted 6 lines

I actually think that FCFS for networking services and last error code hits closest to the sweet spot. "security=yama,smack,selinux" would give NetLabel to Smack and xfrm and secmark to SELinux. It would also give SELinux error returns in cases where there are multiple reasons for denial. Since SELinux has a more sophisticated runtime environment than Smack this is likely to make Fedora (for example) happier.

Yeah, this seems good to me too.

-Kees

--
Kees Cook
Chrome OS Security

maintainer
#15 lore raw

Re: [PATCH v13 0/9] LSM: Multiple concurrent LSMs

In reply to Casey Schaufler
Quoted 59 lines · Casey Schaufler
Quoted 47 lines · Paul Moore
Quoted 39 lines · Casey Schaufler
Quoted 18 lines · Paul Moore
Quoted 3 lines · Casey Schaufler
Quoted 2 lines · John Johansen
Quoted 1 line · Paul Moore

On Wednesday, April 24, 2013 01:22:20 PM Casey Schaufler wrote:

...

Quoted 12 lines
Quoted 11 lines
Quoted 11 lines
Quoted 5 lines

An interesting aside that may be relevant is that the error condition behavior makes it advisable to have the LSM you care about most go last. If the networking components were strictly FCFS you might have to chose an ordering you might not want for other reasons.

Well, maybe not ... I think. If we take a FCFS approach to the network
controls then only one LSM is really ever going to throw an error on the
network hooks, yes?

Quoted 7 lines
Quoted 4 lines

You set up the order you want to get the networking handled correctly and you could get filesystem hooks in the wrong order. Not that that really ought to be a problem, but there are wonky admin tools out there.

I don't quite follow; can you be a bit more explicit about getting the filesystem hooks in the wrong order?

Let's assume that there's a case for the stat() system call that would get EPERM from SELinux and EACCES from Smack. A carefully crafted admin tool might take different actions based on the return code. If Smack ahead of SELinux in the list the tool will respond one way, whereas if SELinux is ahead it will behave the other way.

If this tool came with Fedora it will likely expect the SELinux error code. Thus, it will be somewhat important that Smack precede SELinux in the LSM ordering. That will grant Smack the NetLabel component. If you want SELinux to use NetLabel you'll have to explicitly configure that.

Quoted 6 lines

It's probably not going to be an issue that often. Making the ordering implications clear to those who may be affected by them is probably the best choice and biggest challenge. It would be nice to keep them to a minimum. I fear some future LSM author getting clever with error codes and demanding the ultimate position in all cases.

Quoted 4 lines

I guess this begs the question, why does the stacking take the return value
from the last LSM and not the first? I'm sure there was a design decision made here, I'm just curious about the reasons why.

The hook loop is trivially simpler if you return the last error than if you return the first error:

	if (thisrc)
		rc = thisrc;
Quoted 7 lines

vs

	if (thisrc && !rc)
		rc = thisrc;

If I had decided to do shortcutting (return on first failure) it would be a different story.

Okay, fair enough. Thanks.

Quoted 10 lines
Quoted 1 line

To me, and maybe I'm the odd one out here,

I don't know that you're the only odd one here. :)

Quoted 2 lines

but I would think that the first LSM in the stacking order should get precedence;

My desire and intent is that to the extent possible there should be no "principle" LSM. The choice of last error is purely driven by the fact that it's the easiest thing to do.

I'm not sure if you can call it a "principle" LSM or not, but as long as we've got portions of the kernel that don't support LSM stacked, e.g. the network stack, we're always going to have one LSM that has a bit more control than others.

Quoted 11 lines
Quoted 4 lines

this is why I'm pushing for a FCFS for the network controls. If it turns out that the stacking patches give preference for the last LSM in the stacking order (I think this will always seem backwards to me) then we should probably give the networking controls to the last LSM.

I actually think that FCFS for networking services and last error code hits closest to the sweet spot. "security=yama,smack,selinux" would give NetLabel to Smack and xfrm and secmark to SELinux. It would also give SELinux error returns in cases where there are multiple reasons for denial. Since SELinux has a more sophisticated runtime environment than Smack this is likely to make Fedora (for example) happier.

Okay, works for me. The thing I'm most concerned about is just making sure we make the network bits a boot time configuration and not just a compile time option.

Signature · 2 lines
paul moore
www.paul-moore.com
author maintainer
#16 lore raw

PATCH v13 3/9 LSM: Multiple concurrent secids

In reply to a message not in the archive

Subject: [PATCH v13 3/9] LSM: Multiple concurrent secids

Change the representation of a secid from a single u32 to a structure containing multiple instances of u32s. This permits interfaces that require information about the security context maintained by multiple LSMs (i.e. audit) and hooks that provide that information to do so.

The networking interfaces that require a single secid have been changed to hook into the mechanism.

---
 include/linux/audit.h                              |    9 ++-
 include/linux/cred.h                               |    3 +-
 include/linux/security.h                           |   44 +++++++-----
 include/net/af_unix.h                              |    3 +-
 include/net/scm.h                                  |    4 +-
 include/net/xfrm.h                                 |    5 +-
 kernel/audit.c                                     |   73 +++++++++++---------
 kernel/audit.h                                     |    4 +-
 kernel/auditfilter.c                               |   16 +++--
 kernel/auditsc.c                                   |   66 +++++++++---------
 kernel/cred.c                                      |    6 +-
 net/ipv4/ip_sockglue.c                             |    5 +-
 .../netfilter/nf_conntrack_l3proto_ipv4_compat.c   |   11 ++-
 net/netfilter/nf_conntrack_netlink.c               |   14 +++-
 net/netfilter/nf_conntrack_standalone.c            |    7 +-
 net/netfilter/xt_SECMARK.c                         |    7 +-
 net/netlabel/netlabel_unlabeled.c                  |   33 +++++----
 net/netlabel/netlabel_user.c                       |    7 +-
 net/netlabel/netlabel_user.h                       |    5 +-
 net/unix/af_unix.c                                 |   17 ++++-
 net/xfrm/xfrm_user.c                               |   32 +++++----
 security/capability.c                              |    2 +-
 security/integrity/ima/ima_policy.c                |    7 +-
 security/security.c                                |   41 ++++++-----
 24 files changed, 256 insertions(+), 165 deletions(-)
include/linux/audit.h +6 -3
index 5a6d718..0be1759e 100644
@@ -43,6 +43,7 @@ struct mq_attr;
 struct mqstat;
 struct audit_watch;
 struct audit_tree;
+struct secids;
 
 struct audit_krule {
 	int			vers_ops;
@@ -423,9 +424,11 @@ extern void		    audit_log_link_denied(const char *operation,
 						  struct path *link);
 extern void		    audit_log_lost(const char *message);
 #ifdef CONFIG_SECURITY
-extern void 		    audit_log_secctx(struct audit_buffer *ab, u32 secid);
+extern void 		    audit_log_secctx(struct audit_buffer *ab,
+					     u32 secid);
 #else
-static inline void	    audit_log_secctx(struct audit_buffer *ab, u32 secid)
+static inline void	    audit_log_secctx(struct audit_buffer *ab,
+					     u32 secid)
 { }
 #endif
 
@@ -436,7 +439,7 @@ extern int audit_filter_user(void);
 extern int audit_filter_type(int type);
 extern int  audit_receive_filter(int type, int pid, int seq,
 				void *data, size_t datasz, kuid_t loginuid,
-				u32 sessionid, u32 sid);
+				u32 sessionid, struct secids *sid);
 extern int audit_enabled;
 #else /* CONFIG_AUDIT */
 static inline __printf(4, 5)
include/linux/cred.h +2 -1
index 04421e8..459302a 100644
@@ -22,6 +22,7 @@
 struct user_struct;
 struct cred;
 struct inode;
+struct secids;
 
 /*
  * COW Supplementary groups list
@@ -151,7 +152,7 @@ extern const struct cred *override_creds(const struct cred *);
 extern void revert_creds(const struct cred *);
 extern struct cred *prepare_kernel_cred(struct task_struct *);
 extern int change_create_files_as(struct cred *, struct inode *);
-extern int set_security_override(struct cred *, u32);
+extern int set_security_override(struct cred *, struct secids *);
 extern int set_security_override_from_ctx(struct cred *, const char *);
 extern int set_create_files_as(struct cred *, struct inode *);
 extern void __init cred_init(void);
include/linux/security.h +25 -19

143 lines not on this page · raw message

include/net/af_unix.h +1 -2
index 0a996a3..9cb2470 100644
@@ -32,12 +32,11 @@ struct unix_skb_parms {
 	const struct cred	*cred;
 	struct scm_fp_list	*fp;		/* Passed files		*/
 #ifdef CONFIG_SECURITY_NETWORK
-	u32			secid;		/* Security ID		*/
+	struct secids		*secid;		/* Security ID		*/
 #endif
 };
 
 #define UNIXCB(skb) 	(*(struct unix_skb_parms *)&((skb)->cb))
-#define UNIXSID(skb)	(&UNIXCB((skb)).secid)
 
 #define unix_state_lock(s)	spin_lock(&unix_sk(s)->lock)
 #define unix_state_unlock(s)	spin_unlock(&unix_sk(s)->lock)
include/net/scm.h +2 -2
index 975cca0..e0ce1eb 100644
@@ -30,7 +30,7 @@ struct scm_cookie {
 	struct scm_fp_list	*fp;		/* Passed files		*/
 	struct scm_creds	creds;		/* Skb credentials	*/
 #ifdef CONFIG_SECURITY_NETWORK
-	u32			secid;		/* Passed security ID 	*/
+	struct secids		secid;		/* Passed security ID 	*/
 #endif
 };
 
@@ -97,7 +97,7 @@ static inline void scm_passec(struct socket *sock, struct msghdr *msg, struct sc
 	int err;
 
 	if (test_bit(SOCK_PASSSEC, &sock->flags)) {
-		err = security_secid_to_secctx(scm->secid, &secdata, &seclen);
+		err = security_secid_to_secctx(&scm->secid, &secdata, &seclen);
 
 		if (!err) {
 			put_cmsg(msg, SOL_SOCKET, SCM_SECURITY, seclen, secdata);
include/net/xfrm.h +4 -1
index 24c8886..45976ad 100644
@@ -698,11 +698,14 @@ static inline void xfrm_audit_helper_usrinfo(kuid_t auid, u32 ses, u32 secid,
 {
 	char *secctx;
 	u32 secctx_len;
+	struct secids sid;
+
+	sid.si_lsm[0] = secid;
 
 	audit_log_format(audit_buf, " auid=%u ses=%u",
 			 from_kuid(&init_user_ns, auid), ses);
 	if (secid != 0 &&
-	    security_secid_to_secctx(secid, &secctx, &secctx_len) == 0) {
+	    security_secid_to_secctx(&sid, &secctx, &secctx_len) == 0) {
 		audit_log_format(audit_buf, " subj=%s", secctx);
 		security_release_secctx(secctx, secctx_len);
 	} else
kernel/audit.c +42 -31

241 lines not on this page · raw message

kernel/audit.h +1 -3
index d51cba8..a4d5d9a 100644
@@ -95,8 +95,6 @@ struct audit_netlink_list {
 
 int audit_send_list(void *);
 
-extern int selinux_audit_rule_update(void);
-
 extern struct mutex audit_filter_mutex;
 extern void audit_free_rule_rcu(struct rcu_head *);
 extern struct list_head audit_filter_list[];
@@ -150,7 +148,7 @@ extern char *audit_unpack_string(void **, size_t *, size_t);
 
 extern pid_t audit_sig_pid;
 extern kuid_t audit_sig_uid;
-extern u32 audit_sig_sid;
+extern struct secids audit_sig_sid;
 
 #ifdef CONFIG_AUDITSYSCALL
 extern int __audit_signal_info(int sig, struct task_struct *t);
kernel/auditfilter.c +9 -7
index f9fc54b..765873b 100644
@@ -1109,8 +1109,9 @@ static void audit_list_rules(int pid, int seq, struct sk_buff_head *q)
 }
 
 /* Log rule additions and removals */
-static void audit_log_rule_change(kuid_t loginuid, u32 sessionid, u32 sid,
-				  char *action, struct audit_krule *rule,
+static void audit_log_rule_change(kuid_t loginuid, u32 sessionid,
+				  struct secids *sid, char *action,
+				  struct audit_krule *rule,
 				  int res)
 {
 	struct audit_buffer *ab;
@@ -1123,11 +1124,11 @@ static void audit_log_rule_change(kuid_t loginuid, u32 sessionid, u32 sid,
 		return;
 	audit_log_format(ab, "auid=%u ses=%u",
 			 from_kuid(&init_user_ns, loginuid), sessionid);
-	if (sid) {
+	if (sid->si_count) {
 		char *ctx = NULL;
 		u32 len;
 		if (security_secid_to_secctx(sid, &ctx, &len))
-			audit_log_format(ab, " ssid=%u", sid);
+			audit_log_format(ab, " ssid=%u", sid->si_count);
 		else {
 			audit_log_format(ab, " subj=%s", ctx);
 			security_release_secctx(ctx, len);
@@ -1152,7 +1153,8 @@ static void audit_log_rule_change(kuid_t loginuid, u32 sessionid, u32 sid,
  * @sid: SE Linux Security ID of sender
  */
 int audit_receive_filter(int type, int pid, int seq, void *data,
-			 size_t datasz, kuid_t loginuid, u32 sessionid, u32 sid)
+			 size_t datasz, kuid_t loginuid, u32 sessionid,
+			 struct secids *sid)
 {
 	struct task_struct *tsk;
 	struct audit_netlink_list *dest;
@@ -1362,7 +1364,7 @@ static int audit_filter_user_rules(struct audit_krule *rule,
 	for (i = 0; i < rule->field_count; i++) {
 		struct audit_field *f = &rule->fields[i];
 		int result = 0;
-		u32 sid;
+		struct secids sid;
 
 		switch (f->type) {
 		case AUDIT_PID:
@@ -1385,7 +1387,7 @@ static int audit_filter_user_rules(struct audit_krule *rule,
 		case AUDIT_SUBJ_CLR:
 			if (f->lsm_rule) {
 				security_task_getsecid(current, &sid);
-				result = security_audit_rule_match(sid,
+				result = security_audit_rule_match(&sid,
 								   f->type,
 								   f->op,
 								   f->lsm_rule,
kernel/auditsc.c +35 -31

172 lines not on this page · raw message

kernel/cred.c +3 -3
index e0573a4..c94a3ff 100644
@@ -641,7 +641,7 @@ EXPORT_SYMBOL(prepare_kernel_cred);
  * Set the LSM security ID in a set of credentials so that the subjective
  * security is overridden when an alternative set of credentials is used.
  */
-int set_security_override(struct cred *new, u32 secid)
+int set_security_override(struct cred *new, struct secids *secid)
 {
 	return security_kernel_act_as(new, secid);
 }
@@ -659,14 +659,14 @@ EXPORT_SYMBOL(set_security_override);
  */
 int set_security_override_from_ctx(struct cred *new, const char *secctx)
 {
-	u32 secid;
+	struct secids secid;
 	int ret;
 
 	ret = security_secctx_to_secid(secctx, strlen(secctx), &secid);
 	if (ret < 0)
 		return ret;
 
-	return set_security_override(new, secid);
+	return set_security_override(new, &secid);
 }
 EXPORT_SYMBOL(set_security_override_from_ctx);
 
net/ipv4/ip_sockglue.c +3 -2
index d9c4f11..a55f8c0 100644
@@ -108,14 +108,15 @@ static void ip_cmsg_recv_retopts(struct msghdr *msg, struct sk_buff *skb)
 static void ip_cmsg_recv_security(struct msghdr *msg, struct sk_buff *skb)
 {
 	char *secdata;
-	u32 seclen, secid;
+	u32 seclen;
+	struct secids secid;
 	int err;
 
 	err = security_socket_getpeersec_dgram(NULL, skb, &secid);
 	if (err)
 		return;
 
-	err = security_secid_to_secctx(secid, &secdata, &seclen);
+	err = security_secid_to_secctx(&secid, &secdata, &seclen);
 	if (err)
 		return;
 
net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c +9 -2
index f2ca127..03dd794 100644
@@ -98,14 +98,21 @@ static int ct_show_secctx(struct seq_file *s, const struct nf_conn *ct)
 	int ret;
 	u32 len;
 	char *secctx;
+	struct secids secid;
+	struct security_operations *sop;
 
-	ret = security_secid_to_secctx(ct->secmark, &secctx, &len);
+	memset(&secid, 0, sizeof(secid));
+
+	secid.si_lsm[lsm_secmark_ops->order] = ct->secmark;
+	secid.si_count = 1;
+
+	ret = security_secid_to_secctx(&secid, &secctx, &len, &sop);
 	if (ret)
 		return 0;
 
 	ret = seq_printf(s, "secctx=%s ", secctx);
 
-	security_release_secctx(secctx, len);
+	security_release_secctx(secctx, len, sop);
 	return ret;
 }
 #else
net/netfilter/nf_conntrack_netlink.c +12 -2
index 9904b15..4a95072 100644
@@ -301,8 +301,13 @@ ctnetlink_dump_secctx(struct sk_buff *skb, const struct nf_conn *ct)
 	struct nlattr *nest_secctx;
 	int len, ret;
 	char *secctx;
+	struct secids secid;
 
-	ret = security_secid_to_secctx(ct->secmark, &secctx, &len);
+	memset(&secid, 0, sizeof(secid));
+
+	secid.si_lsm[0] = ct->secmark;
+
+	ret = security_secid_to_secctx(&secid, &secctx, &len);
 	if (ret)
 		return 0;
 
@@ -548,8 +553,13 @@ ctnetlink_secctx_size(const struct nf_conn *ct)
 {
 #ifdef CONFIG_NF_CONNTRACK_SECMARK
 	int len, ret;
+	struct secids secid;
+
+	memset(&secid, 0, sizeof(secid));
+
+	secid.si_lsm[0] = ct->secmark;
 
-	ret = security_secid_to_secctx(ct->secmark, NULL, &len);
+	ret = security_secid_to_secctx(&secid, NULL, &len);
 	if (ret)
 		return 0;
 
net/netfilter/nf_conntrack_standalone.c +6 -1
index fedee39..4e5bb3e 100644
@@ -123,8 +123,13 @@ static int ct_show_secctx(struct seq_file *s, const struct nf_conn *ct)
 	int ret;
 	u32 len;
 	char *secctx;
+	struct secids secid;
 
-	ret = security_secid_to_secctx(ct->secmark, &secctx, &len);
+	memset(&secid, 0, sizeof(secid));
+
+	secid.si_lsm[0] = ct->secmark;
+
+	ret = security_secid_to_secctx(&secid, &secctx, &len);
 	if (ret)
 		return 0;
 
net/netfilter/xt_SECMARK.c +6 -1
index 9faf5e0..0f7a066 100644
@@ -52,12 +52,17 @@ secmark_tg(struct sk_buff *skb, const struct xt_action_param *par)
 static int checkentry_lsm(struct xt_secmark_target_info *info)
 {
 	int err;
+	struct secids secid;
 
 	info->secctx[SECMARK_SECCTX_MAX - 1] = '\0';
 	info->secid = 0;
 
+	secid.si_lsm[0] = 0;
+
 	err = security_secctx_to_secid(info->secctx, strlen(info->secctx),
-				       &info->secid);
+					&secid);
+	info->secid = secid.si_lsm[0];
+
 	if (err) {
 		if (err == -EINVAL)
 			pr_info("invalid security context \'%s\'\n", info->secctx);
net/netlabel/netlabel_unlabeled.c +21 -12
index 8a6c6ea..520caaa 100644
@@ -396,6 +396,9 @@ int netlbl_unlhsh_add(struct net *net,
 	struct audit_buffer *audit_buf = NULL;
 	char *secctx = NULL;
 	u32 secctx_len;
+	struct secids sid;
+
+	sid.si_lsm[0] = secid;
 
 	if (addr_len != sizeof(struct in_addr) &&
 	    addr_len != sizeof(struct in6_addr))
@@ -458,7 +461,7 @@ int netlbl_unlhsh_add(struct net *net,
 unlhsh_add_return:
 	rcu_read_unlock();
 	if (audit_buf != NULL) {
-		if (security_secid_to_secctx(secid,
+		if (security_secid_to_secctx(&sid,
 					     &secctx,
 					     &secctx_len) == 0) {
 			audit_log_format(audit_buf, " sec_obj=%s", secctx);
@@ -495,6 +498,7 @@ static int netlbl_unlhsh_remove_addr4(struct net *net,
 	struct net_device *dev;
 	char *secctx;
 	u32 secctx_len;
+	struct secids sid;
 
 	spin_lock(&netlbl_unlhsh_lock);
 	list_entry = netlbl_af4list_remove(addr->s_addr, mask->s_addr,
@@ -514,8 +518,9 @@ static int netlbl_unlhsh_remove_addr4(struct net *net,
 					  addr->s_addr, mask->s_addr);
 		if (dev != NULL)
 			dev_put(dev);
+		sid.si_lsm[0] = entry->secid;
 		if (entry != NULL &&
-		    security_secid_to_secctx(entry->secid,
+		    security_secid_to_secctx(&sid,
 					     &secctx, &secctx_len) == 0) {
 			audit_log_format(audit_buf, " sec_obj=%s", secctx);
 			security_release_secctx(secctx, secctx_len);
@@ -557,6 +562,7 @@ static int netlbl_unlhsh_remove_addr6(struct net *net,
 	struct net_device *dev;
 	char *secctx;
 	u32 secctx_len;
+	struct secids sid;
 
 	spin_lock(&netlbl_unlhsh_lock);
 	list_entry = netlbl_af6list_remove(addr, mask, &iface->addr6_list);
@@ -575,8 +581,9 @@ static int netlbl_unlhsh_remove_addr6(struct net *net,
 					  addr, mask);
 		if (dev != NULL)
 			dev_put(dev);
+		sid.si_lsm[0] = entry->secid;
 		if (entry != NULL &&
-		    security_secid_to_secctx(entry->secid,
+		    security_secid_to_secctx(&sid,
 					     &secctx, &secctx_len) == 0) {
 			audit_log_format(audit_buf, " sec_obj=%s", secctx);
 			security_release_secctx(secctx, secctx_len);
@@ -902,7 +909,7 @@ static int netlbl_unlabel_staticadd(struct sk_buff *skb,
 	void *addr;
 	void *mask;
 	u32 addr_len;
-	u32 secid;
+	struct secids secid;
 	struct netlbl_audit audit_info;
 
 	/* Don't allow users to add both IPv4 and IPv6 addresses for a
@@ -931,7 +938,7 @@ static int netlbl_unlabel_staticadd(struct sk_buff *skb,
 		return ret_val;
 
 	return netlbl_unlhsh_add(&init_net,
-				 dev_name, addr, mask, addr_len, secid,
+				 dev_name, addr, mask, addr_len, secid.si_lsm[0],
 				 &audit_info);
 }
 
@@ -953,7 +960,7 @@ static int netlbl_unlabel_staticadddef(struct sk_buff *skb,
 	void *addr;
 	void *mask;
 	u32 addr_len;
-	u32 secid;
+	struct secids secid;
 	struct netlbl_audit audit_info;
 
 	/* Don't allow users to add both IPv4 and IPv6 addresses for a
@@ -980,7 +987,7 @@ static int netlbl_unlabel_staticadddef(struct sk_buff *skb,
 		return ret_val;
 
 	return netlbl_unlhsh_add(&init_net,
-				 NULL, addr, mask, addr_len, secid,
+				 NULL, addr, mask, addr_len, secid.si_lsm[0],
 				 &audit_info);
 }
 
@@ -1092,7 +1099,7 @@ static int netlbl_unlabel_staticlist_gen(u32 cmd,
 	struct netlbl_unlhsh_walk_arg *cb_arg = arg;
 	struct net_device *dev;
 	void *data;
-	u32 secid;
+	struct secids secid;
 	char *secctx;
 	u32 secctx_len;
 
@@ -1134,7 +1141,7 @@ static int netlbl_unlabel_staticlist_gen(u32 cmd,
 		if (ret_val != 0)
 			goto list_cb_failure;
 
-		secid = addr4->secid;
+		secid.si_lsm[0] = addr4->secid;
 	} else {
 		ret_val = nla_put(cb_arg->skb,
 				  NLBL_UNLABEL_A_IPV6ADDR,
@@ -1150,10 +1157,10 @@ static int netlbl_unlabel_staticlist_gen(u32 cmd,
 		if (ret_val != 0)
 			goto list_cb_failure;
 
-		secid = addr6->secid;
+		secid.si_lsm[0] = addr6->secid;
 	}
 
-	ret_val = security_secid_to_secctx(secid, &secctx, &secctx_len);
+	ret_val = security_secid_to_secctx(&secid, &secctx, &secctx_len);
 	if (ret_val != 0)
 		goto list_cb_failure;
 	ret_val = nla_put(cb_arg->skb,
@@ -1531,11 +1538,13 @@ int __init netlbl_unlabel_defconf(void)
 	int ret_val;
 	struct netlbl_dom_map *entry;
 	struct netlbl_audit audit_info;
+	struct secids secid;
 
 	/* Only the kernel is allowed to call this function and the only time
 	 * it is called is at bootup before the audit subsystem is reporting
 	 * messages so don't worry to much about these values. */
-	security_task_getsecid(current, &audit_info.secid);
+	security_task_getsecid(current, &secid);
+	audit_info.secid = secid.si_lsm[0];
 	audit_info.loginuid = GLOBAL_ROOT_UID;
 	audit_info.sessionid = 0;
 
net/netlabel/netlabel_user.c +4 -3
index 9650c4a..7ef8262 100644
@@ -100,10 +100,13 @@ struct audit_buffer *netlbl_audit_start_common(int type,
 	struct audit_buffer *audit_buf;
 	char *secctx;
 	u32 secctx_len;
+	struct secids secid;
 
 	if (audit_enabled == 0)
 		return NULL;
 
+	secid.si_lsm[0] = audit_info->secid;
+
 	audit_buf = audit_log_start(current->audit_context, GFP_ATOMIC, type);
 	if (audit_buf == NULL)
 		return NULL;
@@ -113,9 +116,7 @@ struct audit_buffer *netlbl_audit_start_common(int type,
 			 audit_info->sessionid);
 
 	if (audit_info->secid != 0 &&
-	    security_secid_to_secctx(audit_info->secid,
-				     &secctx,
-				     &secctx_len) == 0) {
+	    security_secid_to_secctx(&secid, &secctx, &secctx_len) == 0) {
 		audit_log_format(audit_buf, " subj=%s", secctx);
 		security_release_secctx(secctx, secctx_len);
 	}
net/netlabel/netlabel_user.h +4 -1
index 8196978..a6f1705 100644
@@ -49,7 +49,10 @@
 static inline void netlbl_netlink_auditinfo(struct sk_buff *skb,
 					    struct netlbl_audit *audit_info)
 {
-	security_task_getsecid(current, &audit_info->secid);
+	struct secids secid;
+
+	security_task_getsecid(current, &secid);
+	audit_info->secid = secid.si_lsm[0];
 	audit_info->loginuid = audit_get_loginuid(current);
 	audit_info->sessionid = audit_get_sessionid(current);
 }
net/unix/af_unix.c +15 -2
index 2db702d..0051f1b 100644
@@ -135,14 +135,27 @@ static struct hlist_head *unix_sockets_unbound(void *addr)
 #define UNIX_ABSTRACT(sk)	(unix_sk(sk)->addr->hash < UNIX_HASH_SIZE)
 
 #ifdef CONFIG_SECURITY_NETWORK
+/*
+ * Casey says - look for a memory leak here.
+ */
 static void unix_get_secdata(struct scm_cookie *scm, struct sk_buff *skb)
 {
-	memcpy(UNIXSID(skb), &scm->secid, sizeof(u32));
+	struct secids *sip = kzalloc(sizeof(*sip), GFP_KERNEL);
+
+	if (sip)
+		memcpy(sip, &scm->secid, sizeof(*sip));
+	UNIXCB(skb).secid = sip;
 }
 
 static inline void unix_set_secdata(struct scm_cookie *scm, struct sk_buff *skb)
 {
-	scm->secid = *UNIXSID(skb);
+	struct secids *sip = UNIXCB(skb).secid;
+
+	if (sip) {
+		memcpy(&scm->secid, sip, sizeof(scm->secid));
+		kfree(sip);
+	} else
+		memset(&scm->secid, 0, sizeof(scm->secid));
 }
 #else
 static inline void unix_get_secdata(struct scm_cookie *scm, struct sk_buff *skb)
net/xfrm/xfrm_user.c +18 -14
index fbd9e6c..5476610 100644
@@ -597,7 +597,7 @@ static int xfrm_add_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
 	struct km_event c;
 	kuid_t loginuid = audit_get_loginuid(current);
 	u32 sessionid = audit_get_sessionid(current);
-	u32 sid;
+	struct secids sid;
 
 	err = verify_newsa_info(p, attrs);
 	if (err)
@@ -614,7 +614,7 @@ static int xfrm_add_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
 		err = xfrm_state_update(x);
 
 	security_task_getsecid(current, &sid);
-	xfrm_audit_state_add(x, err ? 0 : 1, loginuid, sessionid, sid);
+	xfrm_audit_state_add(x, err ? 0 : 1, loginuid, sessionid, sid.si_lsm[0]);
 
 	if (err < 0) {
 		x->km.state = XFRM_STATE_DEAD;
@@ -676,7 +676,7 @@ static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
 	struct xfrm_usersa_id *p = nlmsg_data(nlh);
 	kuid_t loginuid = audit_get_loginuid(current);
 	u32 sessionid = audit_get_sessionid(current);
-	u32 sid;
+	struct secids sid;
 
 	x = xfrm_user_state_lookup(net, p, attrs, &err);
 	if (x == NULL)
@@ -702,7 +702,7 @@ static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
 
 out:
 	security_task_getsecid(current, &sid);
-	xfrm_audit_state_delete(x, err ? 0 : 1, loginuid, sessionid, sid);
+	xfrm_audit_state_delete(x, err ? 0 : 1, loginuid, sessionid, sid.si_lsm[0]);
 	xfrm_state_put(x);
 	return err;
 }
@@ -1395,7 +1395,7 @@ static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
 	int excl;
 	kuid_t loginuid = audit_get_loginuid(current);
 	u32 sessionid = audit_get_sessionid(current);
-	u32 sid;
+	struct secids sid;
 
 	err = verify_newpolicy_info(p);
 	if (err)
@@ -1415,7 +1415,7 @@ static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
 	excl = nlh->nlmsg_type == XFRM_MSG_NEWPOLICY;
 	err = xfrm_policy_insert(p->dir, xp, excl);
 	security_task_getsecid(current, &sid);
-	xfrm_audit_policy_add(xp, err ? 0 : 1, loginuid, sessionid, sid);
+	xfrm_audit_policy_add(xp, err ? 0 : 1, loginuid, sessionid, sid.si_lsm[0]);
 
 	if (err) {
 		security_xfrm_policy_free(xp->security);
@@ -1653,11 +1653,11 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
 	} else {
 		kuid_t loginuid = audit_get_loginuid(current);
 		u32 sessionid = audit_get_sessionid(current);
-		u32 sid;
+		struct secids sid;
 
 		security_task_getsecid(current, &sid);
 		xfrm_audit_policy_delete(xp, err ? 0 : 1, loginuid, sessionid,
-					 sid);
+					 sid.si_lsm[0]);
 
 		if (err != 0)
 			goto out;
@@ -1682,10 +1682,12 @@ static int xfrm_flush_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
 	struct xfrm_usersa_flush *p = nlmsg_data(nlh);
 	struct xfrm_audit audit_info;
 	int err;
+	struct secids secid;
 
 	audit_info.loginuid = audit_get_loginuid(current);
 	audit_info.sessionid = audit_get_sessionid(current);
-	security_task_getsecid(current, &audit_info.secid);
+	security_task_getsecid(current, &secid);
+	audit_info.secid = secid.si_lsm[0];
 	err = xfrm_state_flush(net, p->proto, &audit_info);
 	if (err) {
 		if (err == -ESRCH) /* empty table */
@@ -1871,6 +1873,7 @@ static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
 	u8 type = XFRM_POLICY_TYPE_MAIN;
 	int err;
 	struct xfrm_audit audit_info;
+	struct secids secid;
 
 	err = copy_from_user_policy_type(&type, attrs);
 	if (err)
@@ -1878,7 +1881,8 @@ static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
 
 	audit_info.loginuid = audit_get_loginuid(current);
 	audit_info.sessionid = audit_get_sessionid(current);
-	security_task_getsecid(current, &audit_info.secid);
+	security_task_getsecid(current, &secid);
+	audit_info.secid = secid.si_lsm[0];
 	err = xfrm_policy_flush(net, type, &audit_info);
 	if (err) {
 		if (err == -ESRCH) /* empty table */
@@ -1947,11 +1951,11 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
 	if (up->hard) {
 		kuid_t loginuid = audit_get_loginuid(current);
 		u32 sessionid = audit_get_sessionid(current);
-		u32 sid;
+		struct secids sid;
 
 		security_task_getsecid(current, &sid);
 		xfrm_policy_delete(xp, p->dir);
-		xfrm_audit_policy_delete(xp, 1, loginuid, sessionid, sid);
+		xfrm_audit_policy_delete(xp, 1, loginuid, sessionid, sid.si_lsm[0]);
 
 	} else {
 		// reset the timers here?
@@ -1990,11 +1994,11 @@ static int xfrm_add_sa_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
 	if (ue->hard) {
 		kuid_t loginuid = audit_get_loginuid(current);
 		u32 sessionid = audit_get_sessionid(current);
-		u32 sid;
+		struct secids sid;
 
 		security_task_getsecid(current, &sid);
 		__xfrm_state_delete(x);
-		xfrm_audit_state_delete(x, 1, loginuid, sessionid, sid);
+		xfrm_audit_state_delete(x, 1, loginuid, sessionid, sid.si_lsm[0]);
 	}
 	err = 0;
 out:
security/capability.c +1 -1
index 6783c3e..08bca78 100644
@@ -447,7 +447,7 @@ static int cap_task_wait(struct task_struct *p)
 }
 
 static int cap_task_kill(struct task_struct *p, struct siginfo *info,
-			 int sig, u32 secid)
+			 int sig, const struct cred *ucred)
 {
 	return 0;
 }
security/integrity/ima/ima_policy.c +4 -3
index 399433a..147d61c 100644
@@ -184,7 +184,8 @@ static bool ima_match_rules(struct ima_rule_entry *rule,
 		return false;
 	for (i = 0; i < MAX_LSM_RULES; i++) {
 		int rc = 0;
-		u32 osid, sid;
+		struct secids sid;
+		struct secids osid;
 		int retried = 0;
 
 		if (!rule->lsm[i].rule)
@@ -195,7 +196,7 @@ retry:
 		case LSM_OBJ_ROLE:
 		case LSM_OBJ_TYPE:
 			security_inode_getsecid(inode, &osid);
-			rc = security_filter_rule_match(osid,
+			rc = security_filter_rule_match(&osid,
 							rule->lsm[i].type,
 							Audit_equal,
 							rule->lsm[i].rule,
@@ -205,7 +206,7 @@ retry:
 		case LSM_SUBJ_ROLE:
 		case LSM_SUBJ_TYPE:
 			security_task_getsecid(tsk, &sid);
-			rc = security_filter_rule_match(sid,
+			rc = security_filter_rule_match(&sid,
 							rule->lsm[i].type,
 							Audit_equal,
 							rule->lsm[i].rule,
security/security.c +23 -18

102 lines not on this page · raw message

--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.

author maintainer
#17 lore raw

PATCH v13 4/9 LSM: Multiple security context maintenance

In reply to a message not in the archive

Subject: [PATCH v13 4/9] LSM: Multiple security context maintenance

The legacy use of a security context is that there is a text string which is interpreted by a single LSM. When there is more than one LSM that uses a security context the conbined string is managed by the lsm infrastructure. Because the blob release mechanism can't tell how the blob was allocated it's necessary to tell it. This is accomplished by providing the security operations pointer of the LSM that created the context or NULL if it was created by the lsm infrastructure.

---
 fs/sysfs/dir.c                          |    3 ++-
 fs/sysfs/inode.c                        |    5 +++--
 fs/sysfs/sysfs.h                        |    7 ++++---
 fs/xattr.c                              |    8 +++++---
 include/linux/security.h                |   22 ++++++++++++----------
 include/net/scm.h                       |    6 ++++--
 include/net/xfrm.h                      |    5 +++--
 kernel/audit.c                          |   23 +++++++++++++----------
 kernel/auditfilter.c                    |    5 +++--
 kernel/auditsc.c                        |   20 ++++++++++++--------
 net/ipv4/ip_sockglue.c                  |    5 +++--
 net/netfilter/nf_conntrack_netlink.c    |   12 +++++-------
 net/netfilter/nf_conntrack_standalone.c |    5 +++--
 net/netlabel/netlabel_unlabeled.c       |   21 +++++++++++++--------
 net/netlabel/netlabel_user.c            |    5 +++--
 security/security.c                     |   13 +++++++++----
 16 files changed, 97 insertions(+), 68 deletions(-)
fs/sysfs/dir.c +2 -1
index e145126..9470c42 100644
@@ -287,7 +287,8 @@ void release_sysfs_dirent(struct sysfs_dirent * sd)
 		kfree(sd->s_name);
 	if (sd->s_iattr && sd->s_iattr->ia_secdata)
 		security_release_secctx(sd->s_iattr->ia_secdata,
-					sd->s_iattr->ia_secdata_len);
+					sd->s_iattr->ia_secdata_len,
+					sd->s_iattr->ia_sop);
 	kfree(sd->s_iattr);
 	sysfs_free_ino(sd->s_ino);
 	kmem_cache_free(sysfs_dir_cachep, sd);
fs/sysfs/inode.c +3 -2
index 0ce3ccf..4c318a3 100644
@@ -157,6 +157,7 @@ static int sysfs_sd_setsecdata(struct sysfs_dirent *sd, void **secdata, u32 *sec
 int sysfs_setxattr(struct dentry *dentry, const char *name, const void *value,
 		size_t size, int flags)
 {
+	struct security_operations *sop;
 	struct sysfs_dirent *sd = dentry->d_fsdata;
 	void *secdata;
 	int error;
@@ -172,7 +173,7 @@ int sysfs_setxattr(struct dentry *dentry, const char *name, const void *value,
 		if (error)
 			goto out;
 		error = security_inode_getsecctx(dentry->d_inode,
-						&secdata, &secdata_len);
+						&secdata, &secdata_len, &sop);
 		if (error)
 			goto out;
 
@@ -181,7 +182,7 @@ int sysfs_setxattr(struct dentry *dentry, const char *name, const void *value,
 		mutex_unlock(&sysfs_mutex);
 
 		if (secdata)
-			security_release_secctx(secdata, secdata_len);
+			security_release_secctx(secdata, secdata_len, sop);
 	} else
 		return -EINVAL;
 out:
fs/sysfs/sysfs.h +4 -3
index d1e4043..3895884 100644
@@ -39,9 +39,10 @@ struct sysfs_elem_bin_attr {
 };
 
 struct sysfs_inode_attrs {
-	struct iattr	ia_iattr;
-	void		*ia_secdata;
-	u32		ia_secdata_len;
+	struct iattr			ia_iattr;
+	void				*ia_secdata;
+	u32				ia_secdata_len;
+	struct security_operations	*ia_sop;
 };
 
 /*
fs/xattr.c +5 -3
index 3377dff..542e78d 100644
@@ -146,15 +146,17 @@ ssize_t
 xattr_getsecurity(struct inode *inode, const char *name, void *value,
 			size_t size)
 {
+	struct security_operations *sop;
 	void *buffer = NULL;
 	ssize_t len;
 
 	if (!value || !size) {
-		len = security_inode_getsecurity(inode, name, &buffer, false);
+		len = security_inode_getsecurity(inode, name, &buffer,
+							false, &sop);
 		goto out_noalloc;
 	}
 
-	len = security_inode_getsecurity(inode, name, &buffer, true);
+	len = security_inode_getsecurity(inode, name, &buffer, true, &sop);
 	if (len < 0)
 		return len;
 	if (size < len) {
@@ -163,7 +165,7 @@ xattr_getsecurity(struct inode *inode, const char *name, void *value,
 	}
 	memcpy(value, buffer, len);
 out:
-	security_release_secctx(buffer, len);
+	security_release_secctx(buffer, len, sop);
 out_noalloc:
 	return len;
 }
include/linux/security.h +12 -10
index 038df6f..4430b09 100644
@@ -1323,9 +1323,11 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
  *	Convert secid to security context.  If secdata is NULL the length of
  *	the result will be returned in seclen, but no secdata will be returned.
  *	This does mean that the length could change between calls to check the
- *	length and the next call which actually allocates and returns the secdata.
- *	@secid contains the security ID.
- *	@secdata contains the pointer that stores the converted security context.
+ *	length and the next call which actually allocates and returns the
+ *	secdata.
+ *	@secid contains the security IDs.
+ *	@secdata contains the pointer that stores the converted security
+ *	context.
  *	@seclen pointer which contains the length of the data
  * @secctx_to_secid:
  *	Convert security context to secid.
@@ -1770,7 +1772,7 @@ int security_inode_listxattr(struct dentry *dentry);
 int security_inode_removexattr(struct dentry *dentry, const char *name);
 int security_inode_need_killpriv(struct dentry *dentry);
 int security_inode_killpriv(struct dentry *dentry);
-int security_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc);
+int security_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc, struct security_operations **secops);
 int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags);
 int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size);
 void security_inode_getsecid(const struct inode *inode, struct secids *secid);
@@ -1847,13 +1849,13 @@ 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_netlink_send(struct sock *sk, struct sk_buff *skb);
-int security_secid_to_secctx(struct secids *secid, char **secdata, u32 *seclen);
+int security_secid_to_secctx(struct secids *secid, char **secdata, u32 *seclen, struct security_operations **secops);
 int security_secctx_to_secid(const char *secdata, u32 seclen, struct secids *secid);
-void security_release_secctx(char *secdata, u32 seclen);
+void security_release_secctx(char *secdata, u32 seclen, struct security_operations *secops);
 
 int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen);
 int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen);
-int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen);
+int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen, struct security_operations **secops);
 #else /* CONFIG_SECURITY */
 struct security_mnt_opts {
 };
@@ -2178,7 +2180,7 @@ static inline int security_inode_killpriv(struct dentry *dentry)
 	return cap_inode_killpriv(dentry);
 }
 
-static inline int security_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc)
+static inline int security_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc, struct security_operations **secops)
 {
 	return -EOPNOTSUPP;
 }
@@ -2525,7 +2527,7 @@ static inline int security_netlink_send(struct sock *sk, struct sk_buff *skb)
 	return cap_netlink_send(sk, skb);
 }
 
-static inline int security_secid_to_secctx(struct secids *secid, char **secdata, u32 *seclen)
+static inline int security_secid_to_secctx(struct secids *secid, char **secdata, u32 *seclen, struct security_operations **secops)
 {
 	return -EOPNOTSUPP;
 }
@@ -2549,7 +2551,7 @@ static inline int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32
 {
 	return -EOPNOTSUPP;
 }
-static inline int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)
+static inline int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen, struct security_operations **secops)
 {
 	return -EOPNOTSUPP;
 }
include/net/scm.h +4 -2
index e0ce1eb..33d1dda 100644
@@ -92,16 +92,18 @@ static __inline__ int scm_send(struct socket *sock, struct msghdr *msg,
 #ifdef CONFIG_SECURITY_NETWORK
 static inline void scm_passec(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm)
 {
+	struct security_operations *sop;
 	char *secdata;
 	u32 seclen;
 	int err;
 
 	if (test_bit(SOCK_PASSSEC, &sock->flags)) {
-		err = security_secid_to_secctx(&scm->secid, &secdata, &seclen);
+		err = security_secid_to_secctx(&scm->secid, &secdata, &seclen,
+						&sop);
 
 		if (!err) {
 			put_cmsg(msg, SOL_SOCKET, SCM_SECURITY, seclen, secdata);
-			security_release_secctx(secdata, seclen);
+			security_release_secctx(secdata, seclen, sop);
 		}
 	}
 }
include/net/xfrm.h +3 -2
index 45976ad..1dd770e 100644
@@ -699,15 +699,16 @@ static inline void xfrm_audit_helper_usrinfo(kuid_t auid, u32 ses, u32 secid,
 	char *secctx;
 	u32 secctx_len;
 	struct secids sid;
+	struct security_operations *sop;
 
 	sid.si_lsm[0] = secid;
 
 	audit_log_format(audit_buf, " auid=%u ses=%u",
 			 from_kuid(&init_user_ns, auid), ses);
 	if (secid != 0 &&
-	    security_secid_to_secctx(&sid, &secctx, &secctx_len) == 0) {
+	    security_secid_to_secctx(&sid, &secctx, &secctx_len, &sop) == 0) {
 		audit_log_format(audit_buf, " subj=%s", secctx);
-		security_release_secctx(secctx, secctx_len);
+		security_release_secctx(secctx, secctx_len, sop);
 	} else
 		audit_log_task_context(audit_buf);
 }
kernel/audit.c +13 -10
index eab4b52..a01ab21 100644
@@ -268,6 +268,7 @@ static int audit_log_config_change(char *function_name, int new, int old,
 				   kuid_t loginuid, u32 sessionid,
 				   struct secids *sid, int allow_changes)
 {
+	struct security_operations *sop;
 	struct audit_buffer *ab;
 	int rc = 0;
 
@@ -280,13 +281,13 @@ static int audit_log_config_change(char *function_name, int new, int old,
 		char *ctx = NULL;
 		u32 len;
 
-		rc = security_secid_to_secctx(sid, &ctx, &len);
+		rc = security_secid_to_secctx(sid, &ctx, &len, &sop);
 		if (rc) {
 			audit_log_format(ab, " sid=%u", sid->si_count);
 			allow_changes = 0; /* Something weird, deny request */
 		} else {
 			audit_log_format(ab, " subj=%s", ctx);
-			security_release_secctx(ctx, len);
+			security_release_secctx(ctx, len, sop);
 		}
 	}
 	audit_log_format(ab, " res=%d", allow_changes);
@@ -611,6 +612,7 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type)
 static int audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type,
 				     kuid_t auid, u32 ses, struct secids *sid)
 {
+	struct security_operations *sop;
 	int rc = 0;
 	char *ctx = NULL;
 	u32 len;
@@ -628,12 +630,12 @@ static int audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type,
 			 from_kuid(&init_user_ns, current_uid()),
 			 from_kuid(&init_user_ns, auid), ses);
 	if (sid) {
-		rc = security_secid_to_secctx(sid, &ctx, &len);
+		rc = security_secid_to_secctx(sid, &ctx, &len, &sop);
 		if (rc)
 			audit_log_format(*ab, " ssid=%u", sid->si_count);
 		else {
 			audit_log_format(*ab, " subj=%s", ctx);
-			security_release_secctx(ctx, len);
+			security_release_secctx(ctx, len, sop);
 		}
 	}
 
@@ -642,6 +644,7 @@ static int audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type,
 
 static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 {
+	struct security_operations *sop;
 	u32			seq;
 	struct secids		sid;
 	void			*data;
@@ -850,21 +853,21 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 		len = 0;
 		if (audit_sig_sid.si_count) {
 			err = security_secid_to_secctx(&audit_sig_sid, &ctx,
-							&len);
+							&len, &sop);
 			if (err)
 				return err;
 		}
 		sig_data = kmalloc(sizeof(*sig_data) + len, GFP_KERNEL);
 		if (!sig_data) {
 			if (audit_sig_sid.si_count)
-				security_release_secctx(ctx, len);
+				security_release_secctx(ctx, len, sop);
 			return -ENOMEM;
 		}
 		sig_data->uid = from_kuid(&init_user_ns, audit_sig_uid);
 		sig_data->pid = audit_sig_pid;
 		if (audit_sig_sid.si_count) {
 			memcpy(sig_data->ctx, ctx, len);
-			security_release_secctx(ctx, len);
+			security_release_secctx(ctx, len, sop);
 		}
 		audit_send_reply(NETLINK_CB(skb).portid, seq, AUDIT_SIGNAL_INFO,
 				0, 0, sig_data, sizeof(*sig_data) + len);
@@ -1544,17 +1547,17 @@ void audit_log_secctx(struct audit_buffer *ab, u32 secid)
 	u32 len;
 	char *secctx;
 	struct secids secids;
+	struct security_operations *sop;
 
 	memset(&secids, 0, sizeof(secids));
 
 	secids.si_lsm[0] = secid;
-	secids.si_count = 1;
 
-	if (security_secid_to_secctx(&secids, &secctx, &len)) {
+	if (security_secid_to_secctx(&secids, &secctx, &len, &sop)) {
 		audit_panic("Cannot convert secid to context");
 	} else {
 		audit_log_format(ab, " obj=%s", secctx);
-		security_release_secctx(secctx, len);
+		security_release_secctx(secctx, len, sop);
 	}
 }
 EXPORT_SYMBOL(audit_log_secctx);
kernel/auditfilter.c +3 -2
index 765873b..9a65644 100644
@@ -1114,6 +1114,7 @@ static void audit_log_rule_change(kuid_t loginuid, u32 sessionid,
 				  struct audit_krule *rule,
 				  int res)
 {
+	struct security_operations *sop;
 	struct audit_buffer *ab;
 
 	if (!audit_enabled)
@@ -1127,11 +1128,11 @@ static void audit_log_rule_change(kuid_t loginuid, u32 sessionid,
 	if (sid->si_count) {
 		char *ctx = NULL;
 		u32 len;
-		if (security_secid_to_secctx(sid, &ctx, &len))
+		if (security_secid_to_secctx(sid, &ctx, &len, &sop))
 			audit_log_format(ab, " ssid=%u", sid->si_count);
 		else {
 			audit_log_format(ab, " subj=%s", ctx);
-			security_release_secctx(ctx, len);
+			security_release_secctx(ctx, len, sop);
 		}
 	}
 	audit_log_format(ab, " op=");
kernel/auditsc.c +12 -8
index e7e788b..c00fe05 100644
@@ -1109,12 +1109,13 @@ void audit_log_task_context(struct audit_buffer *ab)
 	unsigned len;
 	int error;
 	struct secids sid;
+	struct security_operations *sop;
 
 	security_task_getsecid(current, &sid);
 	if (sid.si_count == 0)
 		return;
 
-	error = security_secid_to_secctx(&sid, &ctx, &len);
+	error = security_secid_to_secctx(&sid, &ctx, &len, &sop);
 	if (error) {
 		if (error != -EINVAL)
 			goto error_path;
@@ -1122,7 +1123,7 @@ void audit_log_task_context(struct audit_buffer *ab)
 	}
 
 	audit_log_format(ab, " subj=%s", ctx);
-	security_release_secctx(ctx, len);
+	security_release_secctx(ctx, len, sop);
 	return;
 
 error_path:
@@ -1190,6 +1191,7 @@ static int audit_log_pid_context(struct audit_context *context, pid_t pid,
 				 unsigned int sessionid, struct secids *sid,
 				 char *comm)
 {
+	struct security_operations *sop;
 	struct audit_buffer *ab;
 	char *ctx = NULL;
 	u32 len;
@@ -1202,12 +1204,12 @@ static int audit_log_pid_context(struct audit_context *context, pid_t pid,
 	audit_log_format(ab, "opid=%d oauid=%d ouid=%d oses=%d", pid,
 			 from_kuid(&init_user_ns, auid),
 			 from_kuid(&init_user_ns, uid), sessionid);
-	if (security_secid_to_secctx(sid, &ctx, &len)) {
+	if (security_secid_to_secctx(sid, &ctx, &len, &sop)) {
 		audit_log_format(ab, " obj=(none)");
 		rc = 1;
 	} else {
 		audit_log_format(ab, " obj=%s", ctx);
-		security_release_secctx(ctx, len);
+		security_release_secctx(ctx, len, sop);
 	}
 	audit_log_format(ab, " ocomm=");
 	audit_log_untrustedstring(ab, comm);
@@ -1432,6 +1434,7 @@ static void audit_log_fcaps(struct audit_buffer *ab, struct audit_names *name)
 
 static void show_special(struct audit_context *context, int *call_panic)
 {
+	struct security_operations *sop;
 	struct audit_buffer *ab;
 	int i;
 
@@ -1457,12 +1460,12 @@ static void show_special(struct audit_context *context, int *call_panic)
 		if (sip->si_count) {
 			char *ctx = NULL;
 			u32 len;
-			if (security_secid_to_secctx(sip, &ctx, &len)) {
+			if (security_secid_to_secctx(sip, &ctx, &len, &sop)) {
 				audit_log_format(ab, " osid=%u", sip->si_count);
 				*call_panic = 1;
 			} else {
 				audit_log_format(ab, " obj=%s", ctx);
-				security_release_secctx(ctx, len);
+				security_release_secctx(ctx, len, sop);
 			}
 		}
 		if (context->ipc.has_perm) {
@@ -1530,6 +1533,7 @@ static void show_special(struct audit_context *context, int *call_panic)
 static void audit_log_name(struct audit_context *context, struct audit_names *n,
 			   int record_num, int *call_panic)
 {
+	struct security_operations *sop;
 	struct audit_buffer *ab;
 	ab = audit_log_start(context, GFP_KERNEL, AUDIT_PATH);
 	if (!ab)
@@ -1574,12 +1578,12 @@ static void audit_log_name(struct audit_context *context, struct audit_names *n,
 	if (n->osid.si_count != 0) {
 		char *ctx = NULL;
 		u32 len;
-		if (security_secid_to_secctx(&n->osid, &ctx, &len)) {
+		if (security_secid_to_secctx(&n->osid, &ctx, &len, &sop)) {
 			audit_log_format(ab, " osid=%u", n->osid.si_count);
 			*call_panic = 2;
 		} else {
 			audit_log_format(ab, " obj=%s", ctx);
-			security_release_secctx(ctx, len);
+			security_release_secctx(ctx, len, sop);
 		}
 	}
 
net/ipv4/ip_sockglue.c +3 -2
index a55f8c0..7f0c3bb 100644
@@ -110,18 +110,19 @@ static void ip_cmsg_recv_security(struct msghdr *msg, struct sk_buff *skb)
 	char *secdata;
 	u32 seclen;
 	struct secids secid;
+	struct security_operations *sop;
 	int err;
 
 	err = security_socket_getpeersec_dgram(NULL, skb, &secid);
 	if (err)
 		return;
 
-	err = security_secid_to_secctx(&secid, &secdata, &seclen);
+	err = security_secid_to_secctx(&secid, &secdata, &seclen, &sop);
 	if (err)
 		return;
 
 	put_cmsg(msg, SOL_IP, SCM_SECURITY, seclen, secdata);
-	security_release_secctx(secdata, seclen);
+	security_release_secctx(secdata, seclen, sop);
 }
 
 static void ip_cmsg_recv_dstaddr(struct msghdr *msg, struct sk_buff *skb)
net/netfilter/nf_conntrack_netlink.c +5 -7
index 4a95072..cdcf9ab 100644
@@ -302,12 +302,11 @@ ctnetlink_dump_secctx(struct sk_buff *skb, const struct nf_conn *ct)
 	int len, ret;
 	char *secctx;
 	struct secids secid;
-
-	memset(&secid, 0, sizeof(secid));
+	struct security_operations *sop;
 
 	secid.si_lsm[0] = ct->secmark;
 
-	ret = security_secid_to_secctx(&secid, &secctx, &len);
+	ret = security_secid_to_secctx(&secid, &secctx, &len, &sop);
 	if (ret)
 		return 0;
 
@@ -322,7 +321,7 @@ ctnetlink_dump_secctx(struct sk_buff *skb, const struct nf_conn *ct)
 
 	ret = 0;
 nla_put_failure:
-	security_release_secctx(secctx, len);
+	security_release_secctx(secctx, len, sop);
 	return ret;
 }
 #else
@@ -554,12 +553,11 @@ ctnetlink_secctx_size(const struct nf_conn *ct)
 #ifdef CONFIG_NF_CONNTRACK_SECMARK
 	int len, ret;
 	struct secids secid;
-
-	memset(&secid, 0, sizeof(secid));
+	struct security_operations *sop;
 
 	secid.si_lsm[0] = ct->secmark;
 
-	ret = security_secid_to_secctx(&secid, NULL, &len);
+	ret = security_secid_to_secctx(&secid, NULL, &len, &sop);
 	if (ret)
 		return 0;
 
net/netfilter/nf_conntrack_standalone.c +3 -2
index 4e5bb3e..fc571d4 100644
@@ -124,18 +124,19 @@ static int ct_show_secctx(struct seq_file *s, const struct nf_conn *ct)
 	u32 len;
 	char *secctx;
 	struct secids secid;
+	struct security_operations *sop;
 
 	memset(&secid, 0, sizeof(secid));
 
 	secid.si_lsm[0] = ct->secmark;
 
-	ret = security_secid_to_secctx(&secid, &secctx, &len);
+	ret = security_secid_to_secctx(&secid, &secctx, &len, &sop);
 	if (ret)
 		return 0;
 
 	ret = seq_printf(s, "secctx=%s ", secctx);
 
-	security_release_secctx(secctx, len);
+	security_release_secctx(secctx, len, sop);
 	return ret;
 }
 #else
net/netlabel/netlabel_unlabeled.c +13 -8
index 520caaa..d77e085 100644
@@ -397,6 +397,7 @@ int netlbl_unlhsh_add(struct net *net,
 	char *secctx = NULL;
 	u32 secctx_len;
 	struct secids sid;
+	struct security_operations *sop;
 
 	sid.si_lsm[0] = secid;
 
@@ -463,9 +464,10 @@ unlhsh_add_return:
 	if (audit_buf != NULL) {
 		if (security_secid_to_secctx(&sid,
 					     &secctx,
-					     &secctx_len) == 0) {
+					     &secctx_len,
+					     &sop) == 0) {
 			audit_log_format(audit_buf, " sec_obj=%s", secctx);
-			security_release_secctx(secctx, secctx_len);
+			security_release_secctx(secctx, secctx_len, sop);
 		}
 		audit_log_format(audit_buf, " res=%u", ret_val == 0 ? 1 : 0);
 		audit_log_end(audit_buf);
@@ -499,6 +501,7 @@ static int netlbl_unlhsh_remove_addr4(struct net *net,
 	char *secctx;
 	u32 secctx_len;
 	struct secids sid;
+	struct security_operations *sop;
 
 	spin_lock(&netlbl_unlhsh_lock);
 	list_entry = netlbl_af4list_remove(addr->s_addr, mask->s_addr,
@@ -521,9 +524,9 @@ static int netlbl_unlhsh_remove_addr4(struct net *net,
 		sid.si_lsm[0] = entry->secid;
 		if (entry != NULL &&
 		    security_secid_to_secctx(&sid,
-					     &secctx, &secctx_len) == 0) {
+					     &secctx, &secctx_len, &sop) == 0) {
 			audit_log_format(audit_buf, " sec_obj=%s", secctx);
-			security_release_secctx(secctx, secctx_len);
+			security_release_secctx(secctx, secctx_len, sop);
 		}
 		audit_log_format(audit_buf, " res=%u", entry != NULL ? 1 : 0);
 		audit_log_end(audit_buf);
@@ -563,6 +566,7 @@ static int netlbl_unlhsh_remove_addr6(struct net *net,
 	char *secctx;
 	u32 secctx_len;
 	struct secids sid;
+	struct security_operations *sop;
 
 	spin_lock(&netlbl_unlhsh_lock);
 	list_entry = netlbl_af6list_remove(addr, mask, &iface->addr6_list);
@@ -584,9 +588,9 @@ static int netlbl_unlhsh_remove_addr6(struct net *net,
 		sid.si_lsm[0] = entry->secid;
 		if (entry != NULL &&
 		    security_secid_to_secctx(&sid,
-					     &secctx, &secctx_len) == 0) {
+					     &secctx, &secctx_len, &sop) == 0) {
 			audit_log_format(audit_buf, " sec_obj=%s", secctx);
-			security_release_secctx(secctx, secctx_len);
+			security_release_secctx(secctx, secctx_len, sop);
 		}
 		audit_log_format(audit_buf, " res=%u", entry != NULL ? 1 : 0);
 		audit_log_end(audit_buf);
@@ -1100,6 +1104,7 @@ static int netlbl_unlabel_staticlist_gen(u32 cmd,
 	struct net_device *dev;
 	void *data;
 	struct secids secid;
+	struct security_operations *sop;
 	char *secctx;
 	u32 secctx_len;
 
@@ -1160,14 +1165,14 @@ static int netlbl_unlabel_staticlist_gen(u32 cmd,
 		secid.si_lsm[0] = addr6->secid;
 	}
 
-	ret_val = security_secid_to_secctx(&secid, &secctx, &secctx_len);
+	ret_val = security_secid_to_secctx(&secid, &secctx, &secctx_len, &sop);
 	if (ret_val != 0)
 		goto list_cb_failure;
 	ret_val = nla_put(cb_arg->skb,
 			  NLBL_UNLABEL_A_SECCTX,
 			  secctx_len,
 			  secctx);
-	security_release_secctx(secctx, secctx_len);
+	security_release_secctx(secctx, secctx_len, sop);
 	if (ret_val != 0)
 		goto list_cb_failure;
 
net/netlabel/netlabel_user.c +3 -2
index 7ef8262..469aa0e 100644
@@ -101,6 +101,7 @@ struct audit_buffer *netlbl_audit_start_common(int type,
 	char *secctx;
 	u32 secctx_len;
 	struct secids secid;
+	struct security_operations *sop;
 
 	if (audit_enabled == 0)
 		return NULL;
@@ -116,9 +117,9 @@ struct audit_buffer *netlbl_audit_start_common(int type,
 			 audit_info->sessionid);
 
 	if (audit_info->secid != 0 &&
-	    security_secid_to_secctx(&secid, &secctx, &secctx_len) == 0) {
+	    security_secid_to_secctx(&secid, &secctx, &secctx_len, &sop) == 0) {
 		audit_log_format(audit_buf, " subj=%s", secctx);
-		security_release_secctx(secctx, secctx_len);
+		security_release_secctx(secctx, secctx_len, sop);
 	}
 
 	return audit_buf;
security/security.c +9 -4
index 000a1fc..6594d8d 100644
@@ -627,7 +627,9 @@ int security_inode_killpriv(struct dentry *dentry)
 	return security_ops->inode_killpriv(dentry);
 }
 
-int security_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc)
+int security_inode_getsecurity(const struct inode *inode, const char *name,
+				void **buffer, bool alloc,
+				struct security_operations **secops)
 {
 	if (unlikely(IS_PRIVATE(inode)))
 		return -EOPNOTSUPP;
@@ -1047,7 +1049,8 @@ int security_netlink_send(struct sock *sk, struct sk_buff *skb)
 	return security_ops->netlink_send(sk, skb);
 }
 
-int security_secid_to_secctx(struct secids *secid, char **secdata, u32 *seclen)
+int security_secid_to_secctx(struct secids *secid, char **secdata, u32 *seclen,
+				struct security_operations **secops)
 {
 	return security_ops->secid_to_secctx(secid->si_lsm[0], secdata, seclen);
 }
@@ -1061,7 +1064,8 @@ int security_secctx_to_secid(const char *secdata, u32 seclen,
 }
 EXPORT_SYMBOL(security_secctx_to_secid);
 
-void security_release_secctx(char *secdata, u32 seclen)
+void security_release_secctx(char *secdata, u32 seclen,
+				struct security_operations *sop)
 {
 	security_ops->release_secctx(secdata, seclen);
 }
@@ -1079,7 +1083,8 @@ int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen)
 }
 EXPORT_SYMBOL(security_inode_setsecctx);
 
-int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)
+int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen,
+				struct security_operations **secops)
 {
 	return security_ops->inode_getsecctx(inode, ctx, ctxlen);
 }

--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.

author maintainer
#18 lore raw

PATCH v13 5/9 LSM: Networking component isolation

In reply to a message not in the archive

Subject: [PATCH v13 5/9] LSM: Networking component isolation

The NetLabel, XFRM and secmark networking mechanisms are limited to providing security information managed by one LSM. These changes interface the single LSM networking components with the multiple LSM system. Each of the networking components will identify the security ops vector of the LSM that will use it. There are various wrapper functions provided to make this obvious and painless.

---
 include/linux/security.h                           |   45 ++++++++++
 include/net/netlabel.h                             |    3 +-
 include/net/xfrm.h                                 |    8 +-
 .../netfilter/nf_conntrack_l3proto_ipv4_compat.c   |    2 +-
 net/netfilter/xt_SECMARK.c                         |    9 +-
 net/netlabel/netlabel_kapi.c                       |   37 ++++++--
 net/netlabel/netlabel_unlabeled.c                  |   56 +++++-------
 net/netlabel/netlabel_user.c                       |   10 +--
 net/netlabel/netlabel_user.h                       |   64 ++++++++++++-
 net/xfrm/xfrm_user.c                               |   44 +++++----
 security/security.c                                |    4 +-
 security/selinux/hooks.c                           |    8 +-
 security/selinux/netlabel.c                        |    4 +-
 security/smack/smack_lsm.c                         |   94 ++++++++++++--------
 security/smack/smackfs.c                           |   34 ++++++-
 15 files changed, 282 insertions(+), 140 deletions(-)
include/linux/security.h +45 -0
index 4430b09..da0fc7f 100644
@@ -1690,6 +1690,7 @@ struct security_operations {
 	void (*audit_rule_free) (void *lsmrule);
 #endif /* CONFIG_AUDIT */
 };
+extern struct security_operations *security_ops;
 
 /* prototypes */
 extern int security_init(void);
@@ -2604,6 +2605,15 @@ int security_tun_dev_open(void *security);
 
 void security_skb_owned_by(struct sk_buff *skb, struct sock *sk);
 
+static inline int security_secmark_secctx_to_secid(const char *secdata,
+						u32 seclen, u32 *secid)
+{
+	if (security_ops && security_ops->secctx_to_secid)
+		return security_ops->secctx_to_secid(secdata, seclen, secid);
+	*secid = 0;
+	return 0;
+}
+
 #else	/* CONFIG_SECURITY_NETWORK */
 static inline int security_unix_stream_connect(struct sock *sock,
 					       struct sock *other,
@@ -2767,6 +2777,13 @@ static inline void security_secmark_refcount_dec(void)
 {
 }
 
+static inline int security_secmark_secctx_to_secid(const char *secdata,
+						u32 seclen, u32 *secid)
+{
+	*secid = 0;
+	return 0;
+}
+
 static inline int security_tun_dev_alloc_security(void **security)
 {
 	return 0;
@@ -2820,6 +2837,23 @@ int security_xfrm_state_pol_flow_match(struct xfrm_state *x,
 int security_xfrm_decode_session(struct sk_buff *skb, u32 *secid);
 void security_skb_classify_flow(struct sk_buff *skb, struct flowi *fl);
 
+static inline void security_xfrm_task_getsecid(struct task_struct *p,
+						u32 *secid)
+{
+	if (security_ops && security_ops->task_getsecid)
+		security_ops->task_getsecid(p, secid);
+	else
+		*secid = 0;
+}
+
+static inline int security_xfrm_secid_to_secctx(u32 secid, char **secdata,
+						u32 *seclen)
+{
+	if (security_ops && security_ops->secid_to_secctx)
+		return security_ops->secid_to_secctx(secid, secdata, seclen);
+	return 0;
+}
+
 #else	/* CONFIG_SECURITY_NETWORK_XFRM */
 
 static inline int security_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp, struct xfrm_user_sec_ctx *sec_ctx)
@@ -2882,6 +2916,17 @@ static inline void security_skb_classify_flow(struct sk_buff *skb, struct flowi
 {
 }
 
+static inline void security_xfrm_task_getsecid(struct task_struct *p,
+						u32 *secid)
+{
+	*secid = 0;
+}
+
+static inline int security_xfrm_secid_to_secctx(u32 secid, char **secdata,
+						u32 *seclen)
+{
+	return 0;
+}
 #endif	/* CONFIG_SECURITY_NETWORK_XFRM */
 
 #ifdef CONFIG_SECURITY_PATH
include/net/netlabel.h +2 -1
index 2c95d55..c0cf965 100644
@@ -406,7 +406,8 @@ int netlbl_secattr_catmap_setrng(struct netlbl_lsm_secattr_catmap *catmap,
 /*
  * LSM protocol operations (NetLabel LSM/kernel API)
  */
-int netlbl_enabled(void);
+int netlbl_register_lsm(struct security_operations *lsmops);
+int netlbl_enabled(struct security_operations *lsmops);
 int netlbl_sock_setattr(struct sock *sk,
 			u16 family,
 			const struct netlbl_lsm_secattr *secattr);
include/net/xfrm.h +2 -6
index 1dd770e..a9f22be 100644
@@ -698,17 +698,13 @@ static inline void xfrm_audit_helper_usrinfo(kuid_t auid, u32 ses, u32 secid,
 {
 	char *secctx;
 	u32 secctx_len;
-	struct secids sid;
-	struct security_operations *sop;
-
-	sid.si_lsm[0] = secid;
 
 	audit_log_format(audit_buf, " auid=%u ses=%u",
 			 from_kuid(&init_user_ns, auid), ses);
 	if (secid != 0 &&
-	    security_secid_to_secctx(&sid, &secctx, &secctx_len, &sop) == 0) {
+	    security_xfrm_secid_to_secctx(secid, &secctx, &secctx_len) == 0) {
 		audit_log_format(audit_buf, " subj=%s", secctx);
-		security_release_secctx(secctx, secctx_len, sop);
+		security_release_secctx(secctx, secctx_len, security_ops);
 	} else
 		audit_log_task_context(audit_buf);
 }
net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c +1 -1
index 03dd794..b42e160 100644
@@ -103,7 +103,7 @@ static int ct_show_secctx(struct seq_file *s, const struct nf_conn *ct)
 
 	memset(&secid, 0, sizeof(secid));
 
-	secid.si_lsm[lsm_secmark_ops->order] = ct->secmark;
+	secid.si_lsm[0] = ct->secmark;
 	secid.si_count = 1;
 
 	ret = security_secid_to_secctx(&secid, &secctx, &len, &sop);
net/netfilter/xt_SECMARK.c +2 -7
index 0f7a066..e6e51c4 100644
@@ -52,17 +52,12 @@ secmark_tg(struct sk_buff *skb, const struct xt_action_param *par)
 static int checkentry_lsm(struct xt_secmark_target_info *info)
 {
 	int err;
-	struct secids secid;
 
 	info->secctx[SECMARK_SECCTX_MAX - 1] = '\0';
 	info->secid = 0;
 
-	secid.si_lsm[0] = 0;
-
-	err = security_secctx_to_secid(info->secctx, strlen(info->secctx),
-					&secid);
-	info->secid = secid.si_lsm[0];
-
+	err = security_secmark_secctx_to_secid(info->secctx,
+					strlen(info->secctx), &info->secid);
 	if (err) {
 		if (err == -EINVAL)
 			pr_info("invalid security context \'%s\'\n", info->secctx);
net/netlabel/netlabel_kapi.c +31 -6
index 7c94aed..2881d48 100644
@@ -607,23 +607,48 @@ int netlbl_secattr_catmap_setrng(struct netlbl_lsm_secattr_catmap *catmap,
  * LSM Functions
  */
 
+struct security_operations *netlbl_active_lsm;
+/**
+ * netlbl_register_lsm - Reserve the NetLabel subsystem for an LSM
+ *
+ * Description:
+ * To avoid potential conflicting views between LSMs over
+ * what should go in the network label reserve the Netlabel
+ * mechanism for use by one LSM. netlbl_enabled will return
+ * false for all other LSMs.
+ *
+ */
+int netlbl_register_lsm(struct security_operations *lsm)
+{
+	if (lsm == NULL)
+		return -EINVAL;
+
+	if (netlbl_active_lsm == NULL)
+		netlbl_active_lsm = lsm;
+	else if (netlbl_active_lsm != lsm)
+		return -EBUSY;
+
+	printk(KERN_INFO "NetLabel: Registered LSM \"%s\".\n", lsm->name);
+	return 0;
+}
+
 /**
  * netlbl_enabled - Determine if the NetLabel subsystem is enabled
  *
  * Description:
  * The LSM can use this function to determine if it should use NetLabel
- * security attributes in it's enforcement mechanism.  Currently, NetLabel is
- * considered to be enabled when it's configuration contains a valid setup for
+ * security attributes in it's enforcement mechanism.  NetLabel is
+ * considered to be enabled when the LSM making the call is registered and
+ * the netlabel configuration contains a valid setup for
  * at least one labeled protocol (i.e. NetLabel can understand incoming
  * labeled packets of at least one type); otherwise NetLabel is considered to
  * be disabled.
  *
  */
-int netlbl_enabled(void)
+int netlbl_enabled(struct security_operations *lsm)
 {
-	/* At some point we probably want to expose this mechanism to the user
-	 * as well so that admins can toggle NetLabel regardless of the
-	 * configuration */
+	if (netlbl_active_lsm != lsm)
+		return 0;
 	return (atomic_read(&netlabel_mgmt_protocount) > 0);
 }
 
net/netlabel/netlabel_unlabeled.c +21 -35

170 lines not on this page · raw message

net/netlabel/netlabel_user.c +4 -6
index 469aa0e..e3b486d 100644
@@ -100,14 +100,10 @@ struct audit_buffer *netlbl_audit_start_common(int type,
 	struct audit_buffer *audit_buf;
 	char *secctx;
 	u32 secctx_len;
-	struct secids secid;
-	struct security_operations *sop;
 
 	if (audit_enabled == 0)
 		return NULL;
 
-	secid.si_lsm[0] = audit_info->secid;
-
 	audit_buf = audit_log_start(current->audit_context, GFP_ATOMIC, type);
 	if (audit_buf == NULL)
 		return NULL;
@@ -117,9 +113,11 @@ struct audit_buffer *netlbl_audit_start_common(int type,
 			 audit_info->sessionid);
 
 	if (audit_info->secid != 0 &&
-	    security_secid_to_secctx(&secid, &secctx, &secctx_len, &sop) == 0) {
+	    netlbl_secid_to_secctx(audit_info->secid,
+				     &secctx,
+				     &secctx_len) == 0) {
 		audit_log_format(audit_buf, " subj=%s", secctx);
-		security_release_secctx(secctx, secctx_len, sop);
+		netlbl_release_secctx(secctx, secctx_len);
 	}
 
 	return audit_buf;
net/netlabel/netlabel_user.h +60 -4

76 lines not on this page · raw message

net/xfrm/xfrm_user.c +20 -24

125 lines not on this page · raw message

security/security.c +3 -1
index 6594d8d..d0b768c 100644
@@ -32,7 +32,9 @@
 static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1] =
 	CONFIG_DEFAULT_SECURITY;
 
-static struct security_operations *security_ops;
+struct security_operations *security_ops;
+EXPORT_SYMBOL(security_ops);
+
 static struct security_operations default_security_ops = {
 	.name	= "default",
 };
security/selinux/hooks.c +4 -4
index 9ff6d6d..7104c6b 100644
@@ -4188,7 +4188,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
 		return selinux_sock_rcv_skb_compat(sk, skb, family);
 
 	secmark_active = selinux_secmark_enabled();
-	peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled();
+	peerlbl_active = netlbl_enabled(&selinux_ops) || selinux_xfrm_enabled();
 	if (!secmark_active && !peerlbl_active)
 		return 0;
 
@@ -4571,7 +4571,7 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex,
 		return NF_ACCEPT;
 
 	secmark_active = selinux_secmark_enabled();
-	netlbl_active = netlbl_enabled();
+	netlbl_active = netlbl_enabled(&selinux_ops);
 	peerlbl_active = netlbl_active || selinux_xfrm_enabled();
 	if (!secmark_active && !peerlbl_active)
 		return NF_ACCEPT;
@@ -4636,7 +4636,7 @@ static unsigned int selinux_ip_output(struct sk_buff *skb,
 {
 	u32 sid;
 
-	if (!netlbl_enabled())
+	if (!netlbl_enabled(&selinux_ops))
 		return NF_ACCEPT;
 
 	/* we do this in the LOCAL_OUT path and not the POST_ROUTING path
@@ -4725,7 +4725,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
 		return NF_ACCEPT;
 #endif
 	secmark_active = selinux_secmark_enabled();
-	peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled();
+	peerlbl_active = netlbl_enabled(&selinux_ops) || selinux_xfrm_enabled();
 	if (!secmark_active && !peerlbl_active)
 		return NF_ACCEPT;
 
security/selinux/netlabel.c +2 -2
index 7a9cbd0..471dce1 100644
@@ -180,7 +180,7 @@ int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
 	int rc;
 	struct netlbl_lsm_secattr secattr;
 
-	if (!netlbl_enabled()) {
+	if (!netlbl_enabled(&selinux_ops)) {
 		*sid = SECSID_NULL;
 		return 0;
 	}
@@ -351,7 +351,7 @@ int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
 	u32 perm;
 	struct netlbl_lsm_secattr secattr;
 
-	if (!netlbl_enabled())
+	if (!netlbl_enabled(&selinux_ops))
 		return 0;
 
 	netlbl_secattr_init(&secattr);
security/smack/smack_lsm.c +55 -39

143 lines not on this page · raw message

security/smack/smackfs.c +30 -4
index 5335444..f51f98f 100644
@@ -115,6 +115,13 @@ static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT;
 const char *smack_cipso_option = SMACK_CIPSO_OPTION;
 
 /*
+ * If another LSM has registered the Netlabel system
+ * this gets set false, indicating that all packets should get
+ * treated as if they are unlabeled, hence ambient.
+ */
+int smack_use_netlbl;
+
+/*
  * Values for parsing cipso rules
  * SMK_DIGITLEN: Length of a digit field in a rule.
  * SMK_CIPSOMIN: Minimum possible cipso rule length.
@@ -624,6 +631,22 @@ static void smk_cipso_doi(void)
 	struct cipso_v4_doi *doip;
 	struct netlbl_audit nai;
 
+	if (smack_net_ambient == NULL)
+		smack_net_ambient = smack_known_floor.smk_known;
+
+	/*
+	 * If someone else has registered use of netlbl abort
+	 */
+	if (!smack_use_netlbl) {
+		rc = netlbl_register_lsm(&smack_ops);
+		if (rc) {
+			printk(KERN_WARNING "%s:%d Netlabel use denied\n",
+				__func__, __LINE__);
+			return;
+		}
+		smack_use_netlbl = 1;
+	}
+
 	smk_netlabel_audit_set(&nai);
 
 	rc = netlbl_cfg_map_del(NULL, PF_INET, NULL, NULL, &nai);
@@ -1185,9 +1208,12 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
 			smk_netlbladdr_insert(skp);
 		}
 	} else {
-		/* we delete the unlabeled entry, only if the previous label
-		 * wasn't the special CIPSO option */
-		if (skp->smk_label != smack_cipso_option)
+		/*
+		 * Delete the unlabeled entry if the previous label
+		 * wasn't the special CIPSO option or if some other
+		 * LSM owns Netlabel.
+		 */
+		if (skp->smk_label != smack_cipso_option && smack_use_netlbl)
 			rc = netlbl_cfg_unlbl_static_del(&init_net, NULL,
 					&skp->smk_host.sin_addr, &skp->smk_mask,
 					PF_INET, &audit_info);
@@ -1199,7 +1225,7 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
 	 * this host so that incoming packets get labeled.
 	 * but only if we didn't get the special CIPSO option
 	 */
-	if (rc == 0 && sp != smack_cipso_option)
+	if (rc == 0 && sp != smack_cipso_option && smack_use_netlbl)
 		rc = netlbl_cfg_unlbl_static_add(&init_net, NULL,
 			&skp->smk_host.sin_addr, &skp->smk_mask, PF_INET,
 			smack_to_secid(skp->smk_label), &audit_info);

--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.

maintainer
#19 lore raw

Re: [PATCH v13 5/9] LSM: Networking component isolation

Quoted 12 lines · Casey Schaufler

Subject: [PATCH v13 5/9] LSM: Networking component isolation

The NetLabel, XFRM and secmark networking mechanisms are limited to providing security information managed by one LSM. These changes interface the single LSM networking components with the multiple LSM system. Each of the networking components will identify the security ops vector of the LSM that will use it. There are various wrapper functions provided to make this obvious and painless.

...

include/net/netlabel.h int netlbl_secattr_catmap_setrng(struct netlbl_lsm_secattr_catmap *catmap, · line 409

Quoted 10 lines
include/net/netlabel.h +0 -0
index 2c95d55..c0cf965 100644
@@ -406,7 +406,8 @@ int netlbl_secattr_catmap_setrng(struct

netlbl_lsm_secattr_catmap *catmap, /*
* LSM protocol operations (NetLabel LSM/kernel API) */

include/net/netlabel.h +1 -1
-int netlbl_enabled(void);
+int netlbl_register_lsm(struct security_operations *lsmops);

Nit picky, but I'd prefer "netlbl_lsm_register()".

Quoted 4 lines
include/net/netlabel.h +1 -0
+int netlbl_enabled(struct security_operations *lsmops);
 int netlbl_sock_setattr(struct sock *sk,
 			u16 family,
 			const struct netlbl_lsm_secattr *secattr);

...

Quoted 9 lines
net/netlabel/netlabel_kapi.c +0 -0
index 7c94aed..2881d48 100644
@@ -607,23 +607,48 @@ int netlbl_secattr_catmap_setrng(struct

netlbl_lsm_secattr_catmap *catmap, * LSM Functions
*/

net/netlabel/netlabel_kapi.c +1 -0
+struct security_operations *netlbl_active_lsm;

net/netlabel/netlabel_kapi.c int netlbl_secattr_catmap_setrng(struct netlbl_lsm_secattr_catmap *catmap, · line 620

Quoted 10 lines
net/netlabel/netlabel_kapi.c +10 -0
+/**
+ * netlbl_register_lsm - Reserve the NetLabel subsystem for an LSM
+ *
+ * Description:
+ * To avoid potential conflicting views between LSMs over
+ * what should go in the network label reserve the Netlabel
+ * mechanism for use by one LSM. netlbl_enabled will return
+ * false for all other LSMs.
+ *
+ */

You need a description for the 'lsm' parameter in the comment header above.

Also, this is extremely nit picky but I'd like to see some vertical whitespace between the netlbl_active_lsm declaration and the function header.

Quoted 19 lines
net/netlabel/netlabel_kapi.c +14 -0
+int netlbl_register_lsm(struct security_operations *lsm)
+{
+	if (lsm == NULL)
+		return -EINVAL;
+
+	if (netlbl_active_lsm == NULL)
+		netlbl_active_lsm = lsm;
+	else if (netlbl_active_lsm != lsm)
+		return -EBUSY;
+
+	printk(KERN_INFO "NetLabel: Registered LSM \"%s\".\n", lsm->name);
+	return 0;
+}
+
 /**
  * netlbl_enabled - Determine if the NetLabel subsystem is enabled
  *
  * Description:
  * The LSM can use this function to determine if it should use NetLabel

net/netlabel/netlabel_kapi.c int netlbl_secattr_catmap_setrng(struct netlbl_lsm_secattr_catmap *catmap, · line 647

Quoted 10 lines
net/netlabel/netlabel_kapi.c +3 -2
- * security attributes in it's enforcement mechanism.  Currently, NetLabel
- * considered to be enabled when it's configuration contains a valid
+ * security attributes in it's enforcement mechanism.  NetLabel
+ * considered to be enabled when the LSM making the call is registered
+ * the netlabel configuration contains a valid setup for
  * at least one labeled protocol (i.e. NetLabel can understand incoming
  * labeled packets of at least one type); otherwise NetLabel is considered
  * be disabled.
  *
  */

Same thing, you need a description for the 'lsm' parameter in the comment header above.

net/netlabel/netlabel_kapi.c int netlbl_secattr_catmap_setrng(struct netlbl_lsm_secattr_catmap *catmap, · line 626

Quoted 6 lines
net/netlabel/netlabel_kapi.c +1 -4
-int netlbl_enabled(void)
+int netlbl_enabled(struct security_operations *lsm)
 {
-	/* At some point we probably want to expose this mechanism to the user
-	 * as well so that admins can toggle NetLabel regardless of the
-	 * configuration */

It really doesn't matter if you remove that comment or not, but I believe it still applies so long as we do the LSM check first.

Quoted 4 lines
net/netlabel/netlabel_kapi.c +2 -0
+	if (netlbl_active_lsm != lsm)
+		return 0;
 	return (atomic_read(&netlabel_mgmt_protocount) > 0);
 }

...

Quoted 56 lines
net/netlabel/netlabel_user.h +47 -0
index a6f1705..9990b24 100644
@@ -41,6 +41,65 @@
 
 /* NetLabel NETLINK helper functions */
 
+extern struct security_operations *netlbl_active_lsm;
+
+/**
+ * netlbl_secid_to_secctx - call the registered secid_to_secctx LSM hook
+ * @secid - The secid to convert
+ * @secdata - Where to put the result
+ * @seclen - Where to put the length of the result
+ *
+ * Returns: the result of calling the hook.
+ */
+static inline int netlbl_secid_to_secctx(u32 secid, char **secdata, u32
 *seclen) +{
+	if (netlbl_active_lsm == NULL)
+		return -EINVAL;
+	return netlbl_active_lsm->secid_to_secctx(secid, secdata, seclen);
+}
+
+/**
+ * netlbl_release_secctx - call the registered release_secctx LSM hook
+ * @secdata - The security context to release
+ * @seclen - The size of the context to release
+ *
+ */
+static inline void netlbl_release_secctx(char *secdata, u32 seclen)
+{
+	if (netlbl_active_lsm != NULL)
+		netlbl_active_lsm->release_secctx(secdata, seclen);
+}
+
+/**
+ * netlbl_secctx_to_secid - call the registered seccts_to_secid LSM hook
+ * @secdata - The security context
+ * @seclen - The size of the security context
+ * @secid - Where to put the result
+ *
+ * Returns: the result of calling the hook
+ */
+static inline int netlbl_secctx_to_secid(const char *secdata, u32 seclen,
+					 u32 *secid)
+{
+	if (netlbl_active_lsm == NULL) {
+		*secid = 0;
+		return -EINVAL;
+	}
+	return netlbl_active_lsm->secctx_to_secid(secdata, seclen, secid);
+}
+
+/**

net/netlabel/netlabel_user.h line 101

Quoted 10 lines
net/netlabel/netlabel_user.h +10 -0
+ * netlbl_task_getsecid - call the registered task_getsecid LSM hook
+ * @p - The task
+ * @secid - Where to put the secid
+ *
+ */
+static inline void netlbl_task_getsecid(struct task_struct *p, u32 *secid)
+{
+	if (netlbl_active_lsm)
+		netlbl_active_lsm->task_getsecid(p, secid);
+}

Any particular reason you put all these functions in 'netlabel_user.h'? I ask because this header is related to the NetLabel netlink interface, with some minor audit stuff tossed in for good measure; it really has nothing to do with the LSM secctx/secid stuff. I'd probably prefer these functions end up in their own header file for the sake of better organization, maybe 'netlabel_secid.h'?

Signature · 2 lines
paul moore
www.paul-moore.com
author maintainer
#20 lore raw

Re: [PATCH v13 5/9] LSM: Networking component isolation

Quoted 15 lines · Paul Moore
Quoted 12 lines · Casey Schaufler

Subject: [PATCH v13 5/9] LSM: Networking component isolation

The NetLabel, XFRM and secmark networking mechanisms are limited to providing security information managed by one LSM. These changes interface the single LSM networking components with the multiple LSM system. Each of the networking components will identify the security ops vector of the LSM that will use it. There are various wrapper functions provided to make this obvious and painless.

...

Quoted 11 lines

include/net/netlabel.h int netlbl_secattr_catmap_setrng(struct netlbl_lsm_secattr_catmap *catmap, · line 409

Quoted 10 lines
include/net/netlabel.h +0 -0
index 2c95d55..c0cf965 100644
@@ -406,7 +406,8 @@ int netlbl_secattr_catmap_setrng(struct

netlbl_lsm_secattr_catmap *catmap, /*
* LSM protocol operations (NetLabel LSM/kernel API) */

include/net/netlabel.h +1 -1
-int netlbl_enabled(void);
+int netlbl_register_lsm(struct security_operations *lsmops);

Nit picky, but I'd prefer "netlbl_lsm_register()".

Not a problem. I will conform to your conventions.

Quoted 15 lines
Quoted 5 lines
include/net/netlabel.h +1 -0
+int netlbl_enabled(struct security_operations *lsmops);
 int netlbl_sock_setattr(struct sock *sk,
 			u16 family,
 			const struct netlbl_lsm_secattr *secattr);

...

Quoted 8 lines
net/netlabel/netlabel_kapi.c +0 -0
index 7c94aed..2881d48 100644
@@ -607,23 +607,48 @@ int netlbl_secattr_catmap_setrng(struct

netlbl_lsm_secattr_catmap *catmap, * LSM Functions
*/

Quoted 12 lines

net/netlabel/netlabel_kapi.c int netlbl_secattr_catmap_setrng(struct netlbl_lsm_secattr_catmap *catmap, · line 620

Quoted 11 lines
net/netlabel/netlabel_kapi.c +11 -0
+struct security_operations *netlbl_active_lsm;
+/**
+ * netlbl_register_lsm - Reserve the NetLabel subsystem for an LSM
+ *
+ * Description:
+ * To avoid potential conflicting views between LSMs over
+ * what should go in the network label reserve the Netlabel
+ * mechanism for use by one LSM. netlbl_enabled will return
+ * false for all other LSMs.
+ *
+ */

You need a description for the 'lsm' parameter in the comment header above.

Thank you. I missed that.

Quoted 2 lines

Also, this is extremely nit picky but I'd like to see some vertical whitespace between the netlbl_active_lsm declaration and the function header.

White space is easy.

Quoted 23 lines
Quoted 23 lines
net/netlabel/netlabel_kapi.c +16 -2
+int netlbl_register_lsm(struct security_operations *lsm)
+{
+	if (lsm == NULL)
+		return -EINVAL;
+
+	if (netlbl_active_lsm == NULL)
+		netlbl_active_lsm = lsm;
+	else if (netlbl_active_lsm != lsm)
+		return -EBUSY;
+
+	printk(KERN_INFO "NetLabel: Registered LSM \"%s\".\n", lsm->name);
+	return 0;
+}
+
 /**
  * netlbl_enabled - Determine if the NetLabel subsystem is enabled
  *
  * Description:
  * The LSM can use this function to determine if it should use NetLabel
- * security attributes in it's enforcement mechanism.  Currently, NetLabel
- * considered to be enabled when it's configuration contains a valid
+ * security attributes in it's enforcement mechanism.  NetLabel
+ * considered to be enabled when the LSM making the call is registered
Quoted 8 lines
Quoted 6 lines

+ * the netlabel configuration contains a valid setup for
* at least one labeled protocol (i.e. NetLabel can understand incoming
* labeled packets of at least one type); otherwise NetLabel is considered
* be disabled.
*
*/

Same thing, you need a description for the 'lsm' parameter in the comment header above.

I'll add that.

Quoted 8 lines

net/netlabel/netlabel_kapi.c int netlbl_secattr_catmap_setrng(struct netlbl_lsm_secattr_catmap *catmap, · line 626

Quoted 6 lines
net/netlabel/netlabel_kapi.c +1 -4
-int netlbl_enabled(void)
+int netlbl_enabled(struct security_operations *lsm)
 {
-	/* At some point we probably want to expose this mechanism to the user
-	 * as well so that admins can toggle NetLabel regardless of the
-	 * configuration */

It really doesn't matter if you remove that comment or not, but I believe it still applies so long as we do the LSM check first.

OK. I'll leave it alone.

Quoted 70 lines
Quoted 4 lines
net/netlabel/netlabel_kapi.c +2 -0
+	if (netlbl_active_lsm != lsm)
+		return 0;
 	return (atomic_read(&netlabel_mgmt_protocount) > 0);
 }

...

Quoted 64 lines
net/netlabel/netlabel_user.h +55 -0
index a6f1705..9990b24 100644
@@ -41,6 +41,65 @@
 
 /* NetLabel NETLINK helper functions */
 
+extern struct security_operations *netlbl_active_lsm;
+
+/**
+ * netlbl_secid_to_secctx - call the registered secid_to_secctx LSM hook
+ * @secid - The secid to convert
+ * @secdata - Where to put the result
+ * @seclen - Where to put the length of the result
+ *
+ * Returns: the result of calling the hook.
+ */
+static inline int netlbl_secid_to_secctx(u32 secid, char **secdata, u32
 *seclen) +{
+	if (netlbl_active_lsm == NULL)
+		return -EINVAL;
+	return netlbl_active_lsm->secid_to_secctx(secid, secdata, seclen);
+}
+
+/**
+ * netlbl_release_secctx - call the registered release_secctx LSM hook
+ * @secdata - The security context to release
+ * @seclen - The size of the context to release
+ *
+ */
+static inline void netlbl_release_secctx(char *secdata, u32 seclen)
+{
+	if (netlbl_active_lsm != NULL)
+		netlbl_active_lsm->release_secctx(secdata, seclen);
+}
+
+/**
+ * netlbl_secctx_to_secid - call the registered seccts_to_secid LSM hook
+ * @secdata - The security context
+ * @seclen - The size of the security context
+ * @secid - Where to put the result
+ *
+ * Returns: the result of calling the hook
+ */
+static inline int netlbl_secctx_to_secid(const char *secdata, u32 seclen,
+					 u32 *secid)
+{
+	if (netlbl_active_lsm == NULL) {
+		*secid = 0;
+		return -EINVAL;
+	}
+	return netlbl_active_lsm->secctx_to_secid(secdata, seclen, secid);
+}
+
+/**
+ * netlbl_task_getsecid - call the registered task_getsecid LSM hook
+ * @p - The task
+ * @secid - Where to put the secid
+ *
+ */
+static inline void netlbl_task_getsecid(struct task_struct *p, u32 *secid)
+{
+	if (netlbl_active_lsm)
Quoted 8 lines

net/netlabel/netlabel_user.h line 101

Quoted 2 lines
net/netlabel/netlabel_user.h +2 -0
+		netlbl_active_lsm->task_getsecid(p, secid);
+}

Any particular reason you put all these functions in 'netlabel_user.h'? I ask because this header is related to the NetLabel netlink interface, with some minor audit stuff tossed in for good measure; it really has nothing to do with the LSM secctx/secid stuff. I'd probably prefer these functions end up in their own header file for the sake of better organization, maybe 'netlabel_secid.h'?

I can put it anywhere you like. I'd prefer netlabel_lsm.h to netlabel_secid.h, but if you have a strong preference I'll defer to your conventions.

Thank you.

maintainer
#21 lore raw

Re: [PATCH v13 5/9] LSM: Networking component isolation

Quoted 94 lines · Casey Schaufler
Quoted 85 lines · Paul Moore
Quoted 12 lines · Casey Schaufler

Subject: [PATCH v13 5/9] LSM: Networking component isolation

The NetLabel, XFRM and secmark networking mechanisms are limited to providing security information managed by one LSM. These changes interface the single LSM networking components with the multiple LSM system. Each of the networking components will identify the security ops vector of the LSM that will use it. There are various wrapper functions provided to make this obvious and painless.

...

Quoted 58 lines
net/netlabel/netlabel_user.h +48 -0
index a6f1705..9990b24 100644
@@ -41,6 +41,65 @@
 
 /* NetLabel NETLINK helper functions */
 
+extern struct security_operations *netlbl_active_lsm;
+
+/**
+ * netlbl_secid_to_secctx - call the registered secid_to_secctx LSM hook
+ * @secid - The secid to convert
+ * @secdata - Where to put the result
+ * @seclen - Where to put the length of the result
+ *
+ * Returns: the result of calling the hook.
+ */
+static inline int netlbl_secid_to_secctx(u32 secid, char **secdata, u32
 *seclen) +{
+	if (netlbl_active_lsm == NULL)
+		return -EINVAL;
+	return netlbl_active_lsm->secid_to_secctx(secid, secdata, seclen);
+}
+
+/**
+ * netlbl_release_secctx - call the registered release_secctx LSM hook
+ * @secdata - The security context to release
+ * @seclen - The size of the context to release
+ *
+ */
+static inline void netlbl_release_secctx(char *secdata, u32 seclen)
+{
+	if (netlbl_active_lsm != NULL)
+		netlbl_active_lsm->release_secctx(secdata, seclen);
+}
+
+/**
+ * netlbl_secctx_to_secid - call the registered seccts_to_secid LSM hook
+ * @secdata - The security context
+ * @seclen - The size of the security context
+ * @secid - Where to put the result
+ *
+ * Returns: the result of calling the hook
+ */
+static inline int netlbl_secctx_to_secid(const char *secdata, u32
 seclen,
+					 u32 *secid)
+{
+	if (netlbl_active_lsm == NULL) {
+		*secid = 0;
+		return -EINVAL;
+	}
+	return netlbl_active_lsm->secctx_to_secid(secdata, seclen, secid);
+}
+
+/**
+ * netlbl_task_getsecid - call the registered task_getsecid LSM hook

net/netlabel/netlabel_user.h line 103

Quoted 10 lines
net/netlabel/netlabel_user.h +9 -0
+ * @p - The task
+ * @secid - Where to put the secid
+ *
+ */
+static inline void netlbl_task_getsecid(struct task_struct *p, u32
 *secid)
+{
+	if (netlbl_active_lsm)
+		netlbl_active_lsm->task_getsecid(p, secid);
+}
Quoted 7 lines

Any particular reason you put all these functions in 'netlabel_user.h'? I ask because this header is related to the NetLabel netlink interface, with some minor audit stuff tossed in for good measure; it really has nothing to do with the LSM secctx/secid stuff. I'd probably prefer these functions end up in their own header file for the sake of better organization, maybe
'netlabel_secid.h'?

Quoted 3 lines

I can put it anywhere you like. I'd prefer netlabel_lsm.h to netlabel_secid.h, but if you have a strong preference I'll defer to your conventions.

That's fine too.

Thanks.

Signature · 2 lines
paul moore
www.paul-moore.com
author maintainer
#22 lore raw

PATCH v13 6/9 LSM: Additional interfaces in /proc/pid/attr

In reply to a message not in the archive

Subject: [PATCH v13 6/9] LSM: Additional interfaces in /proc/pid/attr

SELinux, Smack and AppArmor share the files to /proc/<pid>/attr. This is fine when only one LSM is allowed, but not so good when there is more than one of those LSMs active. For backward compatability the old interfaces are left as is. New interfaces specific to the LSMs have been added. There is also a new entry "context", which is the combined security context.

---
 fs/proc/base.c |   29 +++++++++++++++++++++++------
 1 file changed, 23 insertions(+), 6 deletions(-)
fs/proc/base.c +23 -6
index 69078c7..51435ba 100644
@@ -2217,12 +2217,29 @@ static const struct file_operations proc_pid_attr_operations = {
 };
 
 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("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),
+#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),
+#endif
+#ifdef CONFIG_SECURITY_SMACK
+	REG("smack.current",      S_IRUGO|S_IWUGO, proc_pid_attr_operations),
+#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),
+#endif
 };
 
 static int proc_attr_dir_readdir(struct file * filp,

--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.

author maintainer
#23 lore raw

PATCH v13 7/9 LSM: remove Yama special case stacking

In reply to a message not in the archive

Subject: [PATCH v13 7/9] LSM: remove Yama special case stacking

Remove the special case stacking for Yama.

---
 security/security.c      |   21 ---------------------
 security/yama/Kconfig    |    8 --------
 security/yama/yama_lsm.c |   19 -------------------
 3 files changed, 48 deletions(-)
security/security.c +0 -21
index d0b768c..67e435b 100644
@@ -138,23 +138,11 @@ int __init register_security(struct security_operations *ops)
 
 int security_ptrace_access_check(struct task_struct *child, unsigned int mode)
 {
-#ifdef CONFIG_SECURITY_YAMA_STACKED
-	int rc;
-	rc = yama_ptrace_access_check(child, mode);
-	if (rc)
-		return rc;
-#endif
 	return security_ops->ptrace_access_check(child, mode);
 }
 
 int security_ptrace_traceme(struct task_struct *parent)
 {
-#ifdef CONFIG_SECURITY_YAMA_STACKED
-	int rc;
-	rc = yama_ptrace_traceme(parent);
-	if (rc)
-		return rc;
-#endif
 	return security_ops->ptrace_traceme(parent);
 }
 
@@ -783,9 +771,6 @@ int security_task_create(unsigned long clone_flags)
 
 void security_task_free(struct task_struct *task)
 {
-#ifdef CONFIG_SECURITY_YAMA_STACKED
-	yama_task_free(task);
-#endif
 	security_ops->task_free(task);
 }
 
@@ -911,12 +896,6 @@ int security_task_wait(struct task_struct *p)
 int security_task_prctl(int option, unsigned long arg2, unsigned long arg3,
 			 unsigned long arg4, unsigned long arg5)
 {
-#ifdef CONFIG_SECURITY_YAMA_STACKED
-	int rc;
-	rc = yama_task_prctl(option, arg2, arg3, arg4, arg5);
-	if (rc != -ENOSYS)
-		return rc;
-#endif
 	return security_ops->task_prctl(option, arg2, arg3, arg4, arg5);
 }
 
security/yama/Kconfig +0 -8
index 20ef514..51d6709 100644
@@ -11,11 +11,3 @@ config SECURITY_YAMA
 	  Further information can be found in Documentation/security/Yama.txt.
 
 	  If you are unsure how to answer this question, answer N.
-
-config SECURITY_YAMA_STACKED
-	bool "Yama stacked with other LSMs"
-	depends on SECURITY_YAMA
-	default n
-	help
-	  When Yama is built into the kernel, force it to stack with the
-	  selected primary LSM.
security/yama/yama_lsm.c +0 -19
index 13c88fbc..63ad9bb 100644
@@ -364,16 +364,6 @@ int yama_ptrace_traceme(struct task_struct *parent)
 	return rc;
 }
 
-#ifndef CONFIG_SECURITY_YAMA_STACKED
-static struct security_operations yama_ops = {
-	.name =			"yama",
-
-	.ptrace_access_check =	yama_ptrace_access_check,
-	.ptrace_traceme =	yama_ptrace_traceme,
-	.task_prctl =		yama_task_prctl,
-	.task_free =		yama_task_free,
-};
-#endif
 
 #ifdef CONFIG_SYSCTL
 static int yama_dointvec_minmax(struct ctl_table *table, int write,
@@ -420,18 +410,9 @@ static struct ctl_table yama_sysctl_table[] = {
 
 static __init int yama_init(void)
 {
-#ifndef CONFIG_SECURITY_YAMA_STACKED
-	if (!security_module_enable(&yama_ops))
-		return 0;
-#endif
 
 	printk(KERN_INFO "Yama: becoming mindful.\n");
 
-#ifndef CONFIG_SECURITY_YAMA_STACKED
-	if (register_security(&yama_ops))
-		panic("Yama: kernel registration failed.\n");
-#endif
-
 #ifdef CONFIG_SYSCTL
 	if (!register_sysctl_paths(yama_sysctl_path, yama_sysctl_table))
 		panic("Yama: sysctl registration failed.\n");

--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.

#24 lore raw

Re: [PATCH v13 7/9] LSM: remove Yama special case stacking

Quoted 11 lines · Casey Schaufler

Subject: [PATCH v13 7/9] LSM: remove Yama special case stacking

Remove the special case stacking for Yama.

---
 security/security.c      |   21 ---------------------
 security/yama/Kconfig    |    8 --------
 security/yama/yama_lsm.c |   19 -------------------
 3 files changed, 48 deletions(-)

In the 8/9 patch, the Yama externs are removed from include/linux/security.h. That change should likely be moved to this one, since the calls to those are being removed from security/security.c in this patch:

Quoted 57 lines
security/security.c +0 -21
index d0b768c..67e435b 100644
@@ -138,23 +138,11 @@ int __init register_security(struct security_operations *ops)
 
 int security_ptrace_access_check(struct task_struct *child, unsigned int mode)
 {
-#ifdef CONFIG_SECURITY_YAMA_STACKED
-       int rc;
-       rc = yama_ptrace_access_check(child, mode);
-       if (rc)
-               return rc;
-#endif
        return security_ops->ptrace_access_check(child, mode);
 }
 
 int security_ptrace_traceme(struct task_struct *parent)
 {
-#ifdef CONFIG_SECURITY_YAMA_STACKED
-       int rc;
-       rc = yama_ptrace_traceme(parent);
-       if (rc)
-               return rc;
-#endif
        return security_ops->ptrace_traceme(parent);
 }
 
@@ -783,9 +771,6 @@ int security_task_create(unsigned long clone_flags)
 
 void security_task_free(struct task_struct *task)
 {
-#ifdef CONFIG_SECURITY_YAMA_STACKED
-       yama_task_free(task);
-#endif
        security_ops->task_free(task);
 }
 
@@ -911,12 +896,6 @@ int security_task_wait(struct task_struct *p)
 int security_task_prctl(int option, unsigned long arg2, unsigned long arg3,
                         unsigned long arg4, unsigned long arg5)
 {
-#ifdef CONFIG_SECURITY_YAMA_STACKED
-       int rc;
-       rc = yama_task_prctl(option, arg2, arg3, arg4, arg5);
-       if (rc != -ENOSYS)
-               return rc;
-#endif
        return security_ops->task_prctl(option, arg2, arg3, arg4, arg5);
 }
 
security/yama/Kconfig +0 -0
index 20ef514..51d6709 100644
@@ -11,11 +11,3 @@ config SECURITY_YAMA
          Further information can be found in Documentation/security/Yama.txt.

security/yama/Kconfig config SECURITY_YAMA · line 21

Quoted 10 lines
security/yama/Kconfig +0 -8
 
          If you are unsure how to answer this question, answer N.
-
-config SECURITY_YAMA_STACKED
-       bool "Yama stacked with other LSMs"
-       depends on SECURITY_YAMA
-       default n
-       help
-         When Yama is built into the kernel, force it to stack with the
-         selected primary LSM.

Patch 8/9 removes a blank line from this Kconfig. It should probably be moved to here.

Quoted 8 lines
security/yama/yama_lsm.c +0 -0
index 13c88fbc..63ad9bb 100644
@@ -364,16 +364,6 @@ int yama_ptrace_traceme(struct task_struct *parent)
        return rc;
 }
 

security/yama/yama_lsm.c int yama_ptrace_traceme(struct task_struct *parent) · line 376

Quoted 10 lines
security/yama/yama_lsm.c +0 -10
-#ifndef CONFIG_SECURITY_YAMA_STACKED
-static struct security_operations yama_ops = {
-       .name =                 "yama",
-
-       .ptrace_access_check =  yama_ptrace_access_check,
-       .ptrace_traceme =       yama_ptrace_traceme,
-       .task_prctl =           yama_task_prctl,
-       .task_free =            yama_task_free,
-};
-#endif

The yama_ops (and the calls to security_module_enable and register_security) shouldn't be removed (just the ifdefs). They're added back in 8/9, so I think they should just stay in place. (Or rather, they should stay in place in this patch, and 8/9 should only remove the register_security call, as done with the others.)

Quoted 12 lines
security/yama/yama_lsm.c +0 -4
 #ifdef CONFIG_SYSCTL
 static int yama_dointvec_minmax(struct ctl_table *table, int write,
@@ -420,18 +410,9 @@ static struct ctl_table yama_sysctl_table[] = {
 
 static __init int yama_init(void)
 {
-#ifndef CONFIG_SECURITY_YAMA_STACKED
-       if (!security_module_enable(&yama_ops))
-               return 0;
-#endif
 

security/yama/yama_lsm.c static struct ctl_table yama_sysctl_table[] = { · line 418

Quoted 10 lines
security/yama/yama_lsm.c +0 -5
        printk(KERN_INFO "Yama: becoming mindful.\n");
 
-#ifndef CONFIG_SECURITY_YAMA_STACKED
-       if (register_security(&yama_ops))
-               panic("Yama: kernel registration failed.\n");
-#endif
-
 #ifdef CONFIG_SYSCTL
        if (!register_sysctl_paths(yama_sysctl_path, yama_sysctl_table))
                panic("Yama: sysctl registration failed.\n");

Regardless: yay! I'm looking forward to this series landing. :)

-Kees

--
Kees Cook
Chrome OS Security

author maintainer
#25 lore raw

PATCH v13 8/9 LSM: Hook list management

In reply to a message not in the archive

Subject: [PATCH v13 8/9] LSM: Hook list management

Implement a list for each LSM hook. Execute all of the registered hooks in the specified order. Manage security blobs on behalf of the modules. Integrate with the NetLabel, xfrm and secmark networking components. Move the capablity module directly into the hook handlers. Provide securityfs interfaces to display which lsms are active and which is using the legacy interfaces in /proc/pid/attr. Bring all existing modules in line with the new world order.

---
 include/linux/lsm.h                                |   75 +-
 include/linux/security.h                           |  290 ++-
 include/net/xfrm.h                                 |    2 +-
 kernel/audit.c                                     |    6 +-
 .../netfilter/nf_conntrack_l3proto_ipv4_compat.c   |    2 +-
 net/netfilter/nf_conntrack_netlink.c               |   14 +-
 net/netfilter/nf_conntrack_standalone.c            |    3 +-
 security/Kconfig                                   |  176 +-
 security/apparmor/domain.c                         |   11 +-
 security/apparmor/lsm.c                            |   32 +-
 security/capability.c                              |    1 -
 security/commoncap.c                               |    6 -
 security/inode.c                                   |   79 +-
 security/security.c                                | 1975 ++++++++++++++++----
 security/selinux/hooks.c                           |   71 +-
 security/smack/smack_lsm.c                         |   50 +-
 security/smack/smackfs.c                           |    2 +-
 security/tomoyo/tomoyo.c                           |    8 +-
 security/yama/Kconfig                              |    1 +
 security/yama/yama_lsm.c                           |   34 +-
 20 files changed, 2233 insertions(+), 605 deletions(-)
include/linux/lsm.h +46 -29
index 7c93865..d8ec5a4 100644
@@ -10,11 +10,6 @@
  * Author:
  *	Casey Schaufler <[email protected]>
  *
- * Abstraction layer for LSM security blobs.
- * This is pointless by itself, but necessary for multiple concurrent
- * modules support. Multiple concurrent module support is also refered
- * to as module stacking.
- *
  */
 #ifndef _LINUX_LSM_H
 #define _LINUX_LSM_H
@@ -27,124 +22,146 @@
 #include <linux/security.h>
 
 /*
- * Trivial implementation for the one-LSM-at-a-time case
+ * Just a set of slots for each LSM to keep its blob in.
  */
-static inline void *lsm_get_blob(const void *bp, const int lsm)
+struct lsm_blob {
+	int	lsm_setcount;			/* Number of blobs set */
+	void	*lsm_blobs[COMPOSER_MAX];	/* LSM specific blobs */
+};
+
+static inline struct lsm_blob *lsm_alloc_blob(gfp_t gfp)
 {
-	return (void *)bp;
+	return kzalloc(sizeof(struct lsm_blob), gfp);
+}
+
+static inline void *lsm_get_blob(const struct lsm_blob *bp, const int lsm)
+{
+	if (bp == NULL)
+		return NULL;
+	return bp->lsm_blobs[lsm];
 }
 
-/*
- * Trivial implementation for the one-LSM-at-a-time case
- */
 static inline void lsm_set_blob(void **vpp, void *value, const int lsm)
 {
-	*vpp = value;
+	struct lsm_blob *bp = *vpp;
+
+	if (value == NULL && bp->lsm_blobs[lsm] != NULL)
+		bp->lsm_setcount--;
+	if (value != NULL && bp->lsm_blobs[lsm] == NULL)
+		bp->lsm_setcount++;
+
+	bp->lsm_blobs[lsm] = value;
 }
 
 static inline void *lsm_get_cred(const struct cred *cred,
 					const struct security_operations *sop)
 {
-	return lsm_get_blob(cred->security, 0);
+	return lsm_get_blob(cred->security, sop->order);
 }
 
 static inline void lsm_set_cred(struct cred *cred, void *value,
 					const struct security_operations *sop)
 {
-	lsm_set_blob(&cred->security, value, 0);
+	lsm_set_blob(&cred->security, value, sop->order);
 }
 
 static inline int lsm_set_init_cred(struct cred *cred, void *value,
 					const struct security_operations *sop)
 {
-	cred->security = value;
+	if (cred->security == NULL) {
+		cred->security = lsm_alloc_blob(GFP_KERNEL);
+		if (cred->security == NULL)
+			return -ENOMEM;
+	}
+
+	lsm_set_blob(&cred->security, value, sop->order);
 	return 0;
 }
 
 static inline void *lsm_get_file(const struct file *file,
 					const struct security_operations *sop)
 {
-	return lsm_get_blob(file->f_security, 0);
+	return lsm_get_blob(file->f_security, sop->order);
 }
 
 static inline void lsm_set_file(struct file *file, void *value,
 					const struct security_operations *sop)
 {
-	lsm_set_blob(&file->f_security, value, 0);
+	lsm_set_blob(&file->f_security, value, sop->order);
 }
 
 static inline void *lsm_get_inode(const struct inode *inode,
 					const struct security_operations *sop)
 {
-	return lsm_get_blob(inode->i_security, 0);
+	return lsm_get_blob(inode->i_security, sop->order);
 }
 
 static inline void lsm_set_inode(struct inode *inode, void *value,
 					const struct security_operations *sop)
 {
-	lsm_set_blob(&inode->i_security, value, 0);
+	lsm_set_blob(&inode->i_security, value, sop->order);
 }
 
 static inline void *lsm_get_super(const struct super_block *super,
 					const struct security_operations *sop)
 {
-	return lsm_get_blob(super->s_security, 0);
+	return lsm_get_blob(super->s_security, sop->order);
 }
 
 static inline void lsm_set_super(struct super_block *super, void *value,
 					const struct security_operations *sop)
 {
-	lsm_set_blob(&super->s_security, value, 0);
+	lsm_set_blob(&super->s_security, value, sop->order);
 }
 
 static inline void *lsm_get_ipc(const struct kern_ipc_perm *ipc,
 					const struct security_operations *sop)
 {
-	return lsm_get_blob(ipc->security, 0);
+	return lsm_get_blob(ipc->security, sop->order);
 }
 
 static inline void lsm_set_ipc(struct kern_ipc_perm *ipc, void *value,
 					const struct security_operations *sop)
 {
-	lsm_set_blob(&ipc->security, value, 0);
+	lsm_set_blob(&ipc->security, value, sop->order);
 }
 
 static inline void *lsm_get_msg(const struct msg_msg *msg,
 					const struct security_operations *sop)
 {
-	return lsm_get_blob(msg->security, 0);
+	return lsm_get_blob(msg->security, sop->order);
 }
 
 static inline void lsm_set_msg(struct msg_msg *msg, void *value,
 					const struct security_operations *sop)
 {
-	lsm_set_blob(&msg->security, value, 0);
+	lsm_set_blob(&msg->security, value, sop->order);
 }
 
 #ifdef CONFIG_KEYS
 static inline void *lsm_get_key(const struct key *key,
 					const struct security_operations *sop)
 {
-	return lsm_get_blob(key->security, 0);
+	return lsm_get_blob(key->security, sop->order);
 }
 
 static inline void lsm_set_key(struct key *key, void *value,
 					const struct security_operations *sop)
 {
-	lsm_set_blob(&key->security, value, 0);
+	lsm_set_blob(&key->security, value, sop->order);
 }
 #endif
 
 static inline void *lsm_get_sock(const struct sock *sock,
 					const struct security_operations *sop)
 {
-	return lsm_get_blob(sock->sk_security, 0);
+	return lsm_get_blob(sock->sk_security, sop->order);
 }
 
 static inline void lsm_set_sock(struct sock *sock, void *value,
 					const struct security_operations *sop)
 {
-	lsm_set_blob(&sock->sk_security, value, 0);
+	lsm_set_blob(&sock->sk_security, value, sop->order);
 }
 
 #endif /* ! _LINUX_LSM_H */
include/linux/security.h +234 -11

324 lines not on this page · raw message

						u32 seclen, u32 *secid)

{
- if (security_ops && security_ops->secctx_to_secid)
- return security_ops->secctx_to_secid(secdata, seclen, secid);
+ if (lsm_secmark_ops && lsm_secmark_ops->secctx_to_secid)
+ return lsm_secmark_ops->secctx_to_secid(secdata, seclen, secid);
*secid = 0;
return 0;
}
@@ -2837,11 +3060,13 @@ int security_xfrm_state_pol_flow_match(struct xfrm_state *x,
int security_xfrm_decode_session(struct sk_buff *skb, u32 *secid); void security_skb_classify_flow(struct sk_buff *skb, struct flowi *fl);

+extern struct security_operations *lsm_xfrm_ops;
+
static inline void security_xfrm_task_getsecid(struct task_struct *p,
u32 *secid)
{
- if (security_ops && security_ops->task_getsecid)
- security_ops->task_getsecid(p, secid);
+ if (lsm_xfrm_ops && lsm_xfrm_ops->task_getsecid)
+ lsm_xfrm_ops->task_getsecid(p, secid);
else
*secid = 0;
}
@@ -2849,8 +3074,8 @@ static inline void security_xfrm_task_getsecid(struct task_struct *p,
static inline int security_xfrm_secid_to_secctx(u32 secid, char **secdata,
u32 *seclen)
{
- if (security_ops && security_ops->secid_to_secctx)
- return security_ops->secid_to_secctx(secid, secdata, seclen);
+ if (lsm_xfrm_ops && lsm_xfrm_ops->secid_to_secctx)
+ return lsm_xfrm_ops->secid_to_secctx(secid, secdata, seclen);
return 0;
}

@@ -3134,36 +3359,5 @@ static inline void free_secdata(void *secdata)
{ }
#endif /* CONFIG_SECURITY */

-#ifdef CONFIG_SECURITY_YAMA
-extern int yama_ptrace_access_check(struct task_struct *child,
- unsigned int mode);
-extern int yama_ptrace_traceme(struct task_struct *parent); -extern void yama_task_free(struct task_struct *task);
-extern int yama_task_prctl(int option, unsigned long arg2, unsigned long arg3,
- unsigned long arg4, unsigned long arg5);
-#else
-static inline int yama_ptrace_access_check(struct task_struct *child,
- unsigned int mode)
-{
- return 0;
-}
-
-static inline int yama_ptrace_traceme(struct task_struct *parent) -{
- return 0;
-}
-
-static inline void yama_task_free(struct task_struct *task)
-{
-}
-
-static inline int yama_task_prctl(int option, unsigned long arg2,
- unsigned long arg3, unsigned long arg4,
- unsigned long arg5)
-{
- return -ENOSYS;
-}
-#endif /* CONFIG_SECURITY_YAMA */
-
#endif /* ! __LINUX_SECURITY_H */

include/net/xfrm.h +1 -1
index a9f22be..6dde1d4 100644
@@ -704,7 +704,7 @@ static inline void xfrm_audit_helper_usrinfo(kuid_t auid, u32 ses, u32 secid,
 	if (secid != 0 &&
 	    security_xfrm_secid_to_secctx(secid, &secctx, &secctx_len) == 0) {
 		audit_log_format(audit_buf, " subj=%s", secctx);
-		security_release_secctx(secctx, secctx_len, security_ops);
+		security_release_secctx(secctx, secctx_len, lsm_xfrm_ops);
 	} else
 		audit_log_task_context(audit_buf);
 }
kernel/audit.c +5 -1
index a01ab21..1cca29d 100644
@@ -1549,9 +1549,13 @@ void audit_log_secctx(struct audit_buffer *ab, u32 secid)
 	struct secids secids;
 	struct security_operations *sop;
 
+	if (!lsm_secmark_ops)
+		return;
+
 	memset(&secids, 0, sizeof(secids));
 
-	secids.si_lsm[0] = secid;
+	secids.si_lsm[lsm_secmark_ops->order] = secid;
+	secids.si_count = 1;
 
 	if (security_secid_to_secctx(&secids, &secctx, &len, &sop)) {
 		audit_panic("Cannot convert secid to context");
net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c +1 -1
index b42e160..03dd794 100644
@@ -103,7 +103,7 @@ static int ct_show_secctx(struct seq_file *s, const struct nf_conn *ct)
 
 	memset(&secid, 0, sizeof(secid));
 
-	secid.si_lsm[0] = ct->secmark;
+	secid.si_lsm[lsm_secmark_ops->order] = ct->secmark;
 	secid.si_count = 1;
 
 	ret = security_secid_to_secctx(&secid, &secctx, &len, &sop);
net/netfilter/nf_conntrack_netlink.c +12 -2
index cdcf9ab..7ebcbbf 100644
@@ -304,7 +304,12 @@ ctnetlink_dump_secctx(struct sk_buff *skb, const struct nf_conn *ct)
 	struct secids secid;
 	struct security_operations *sop;
 
-	secid.si_lsm[0] = ct->secmark;
+	memset(&secid, 0, sizeof(secid));
+
+	if (lsm_secmark_ops) {
+		secid.si_lsm[lsm_secmark_ops->order] = ct->secmark;
+		secid.si_count = 1;
+	}
 
 	ret = security_secid_to_secctx(&secid, &secctx, &len, &sop);
 	if (ret)
@@ -555,7 +560,12 @@ ctnetlink_secctx_size(const struct nf_conn *ct)
 	struct secids secid;
 	struct security_operations *sop;
 
-	secid.si_lsm[0] = ct->secmark;
+	memset(&secid, 0, sizeof(secid));
+
+	if (lsm_secmark_ops) {
+		secid.si_lsm[lsm_secmark_ops->order] = ct->secmark;
+		secid.si_count = 1;
+	}
 
 	ret = security_secid_to_secctx(&secid, NULL, &len, &sop);
 	if (ret)
net/netfilter/nf_conntrack_standalone.c +2 -1
index fc571d4..5f94265 100644
@@ -128,7 +128,8 @@ static int ct_show_secctx(struct seq_file *s, const struct nf_conn *ct)
 
 	memset(&secid, 0, sizeof(secid));
 
-	secid.si_lsm[0] = ct->secmark;
+	secid.si_lsm[lsm_secmark_ops->order] = ct->secmark;
+	secid.si_count = 1;
 
 	ret = security_secid_to_secctx(&secid, &secctx, &len, &sop);
 	if (ret)
security/Kconfig +149 -27

210 lines not on this page · raw message

security/apparmor/domain.c +2 -9
index 1614111..e67c88c 100644
@@ -353,9 +353,7 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
 		file_inode(bprm->file)->i_mode
 	};
 	const char *name = NULL, *target = NULL, *info = NULL;
-	int error = cap_bprm_set_creds(bprm);
-	if (error)
-		return error;
+	int error = 0;
 
 	if (bprm->cred_prepared)
 		return 0;
@@ -539,15 +537,10 @@ cleanup:
  */
 int apparmor_bprm_secureexec(struct linux_binprm *bprm)
 {
-	int ret = cap_bprm_secureexec(bprm);
-
 	/* the decision to use secure exec is computed in set_creds
 	 * and stored in bprm->unsafe.
 	 */
-	if (!ret && (bprm->unsafe & AA_SECURE_X_NEEDED))
-		ret = 1;
-
-	return ret;
+	return bprm->unsafe & AA_SECURE_X_NEEDED;
 }
 
 /**
security/apparmor/lsm.c +6 -26
index 8784681..6542339 100644
@@ -96,19 +96,11 @@ static void apparmor_cred_transfer(struct cred *new, const struct cred *old)
 static int apparmor_ptrace_access_check(struct task_struct *child,
 					unsigned int mode)
 {
-	int error = cap_ptrace_access_check(child, mode);
-	if (error)
-		return error;
-
 	return aa_ptrace(current, child, mode);
 }
 
 static int apparmor_ptrace_traceme(struct task_struct *parent)
 {
-	int error = cap_ptrace_traceme(parent);
-	if (error)
-		return error;
-
 	return aa_ptrace(parent, current, PTRACE_MODE_ATTACH);
 }
 
@@ -140,14 +132,11 @@ static int apparmor_capable(const struct cred *cred, struct user_namespace *ns,
 			    int cap, int audit)
 {
 	struct aa_profile *profile;
-	/* cap_capable returns 0 on success, else -EPERM */
-	int error = cap_capable(cred, ns, cap, audit);
-	if (!error) {
-		profile = aa_cred_profile(cred);
-		if (!unconfined(profile))
-			error = aa_capable(current, profile, cap, audit);
-	}
-	return error;
+
+	profile = aa_cred_profile(cred);
+	if (!unconfined(profile))
+		return aa_capable(current, profile, cap, audit);
+	return 0;
 }
 
 /**
@@ -897,7 +886,7 @@ static int __init apparmor_init(void)
 {
 	int error;
 
-	if (!apparmor_enabled || !security_module_enable(&apparmor_ops)) {
+	if (!apparmor_enabled || security_module_enable(&apparmor_ops)) {
 		aa_info_message("AppArmor disabled by boot time parameter");
 		apparmor_enabled = 0;
 		return 0;
@@ -915,12 +904,6 @@ static int __init apparmor_init(void)
 		goto register_security_out;
 	}
 
-	error = register_security(&apparmor_ops);
-	if (error) {
-		AA_ERROR("Unable to register AppArmor\n");
-		goto set_init_cxt_out;
-	}
-
 	/* Report that AppArmor successfully initialized */
 	apparmor_initialized = 1;
 	if (aa_g_profile_mode == APPARMOR_COMPLAIN)
@@ -932,9 +915,6 @@ static int __init apparmor_init(void)
 
 	return error;
 
-set_init_cxt_out:
-	aa_free_task_context(current->real_cred->security);
-
 register_security_out:
 	aa_free_root_ns();
 
security/capability.c +0 -1
index 08bca78..d7b2a38 100644
@@ -975,7 +975,6 @@ void __init security_fixup_ops(struct security_operations *ops)
 	set_to_cap_if_null(ops, file_free_security);
 	set_to_cap_if_null(ops, file_ioctl);
 	set_to_cap_if_null(ops, mmap_addr);
-	set_to_cap_if_null(ops, mmap_file);
 	set_to_cap_if_null(ops, file_mprotect);
 	set_to_cap_if_null(ops, file_lock);
 	set_to_cap_if_null(ops, file_fcntl);
security/commoncap.c +0 -6
index c44b6fe..3b12ab1 100644
@@ -988,9 +988,3 @@ int cap_mmap_addr(unsigned long addr)
 	}
 	return ret;
 }
-
-int cap_mmap_file(struct file *file, unsigned long reqprot,
-		  unsigned long prot, unsigned long flags)
-{
-	return 0;
-}
security/inode.c +77 -2

98 lines not on this page · raw message

security/security.c +1662 -313

2,013 lines not on this page · raw message

security/selinux/hooks.c +7 -64

71 lines not on this page · raw message

security/smack/smack_lsm.c +5 -45

50 lines not on this page · raw message

security/smack/smackfs.c +1 -1
index f51f98f..aefe8e7 100644

Lines of this file are not shown. View the raw message.

security/tomoyo/tomoyo.c +1 -7
index 2b4cade..bfe54d6 100644

Lines of this file are not shown. View the raw message.

security/yama/Kconfig +1 -0
index 51d6709..a99aa1d 100644

Lines of this file are not shown. View the raw message.

security/yama/yama_lsm.c +13 -21
index 63ad9bb..4958e68 100644

Lines of this file are not shown. View the raw message.

The rest of this diff is not shown. View the raw message.

--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.

Part of the diff is not shown here. View the raw message.

author maintainer
#26 lore raw

PATCH v13 9/9 LSM: Documentation and cleanup

In reply to a message not in the archive

Subject: [PATCH v13 9/9] LSM: Documentation and cleanup

Add a description of the ways secuirty modules work now. Remove security/capability.c as it is no longer used.

---
 Documentation/security/LSM.txt |   39 +-
 security/Makefile              |    3 +-
 security/capability.c          | 1104 ----------------------------------------
 3 files changed, 31 insertions(+), 1115 deletions(-)
Documentation/security/LSM.txt +30 -9
index c335a76..f979e00 100644
@@ -9,18 +9,39 @@ CONFIG_DEFAULT_SECURITY and can be overridden at boot-time via the
 "security=..." kernel command line argument, in the case where multiple
 LSMs were built into a given kernel.
 
+Both CONFIG_DEFAULT_SECURITY and the "security=" option take a comma
+separated list of LSM names. The LSM hooks are invoked in the order
+specified. All hooks provided are invoked regardless of the outcome
+of preceeding hooks. Hooks the return success or failure results
+return success if all of the LSM provided hooks succeed and the error
+code of the last failing hook on error.
+
+The /proc filesystem attribute interface supports files from a time
+when only one LSM could be used at a time. CONFIG_PRESENT_SECURITY
+defines which LSM uses these interfaces. There are also LSM identified
+interfaces which should be used in preference to the undifferentiated
+interfaces.
+
+The three networking mechanisms supporting LSM attributes are
+restricted to providing those attributes for a single LSM each.
+CONFIG_SECMARK_LSM specifies which LSM will provide hooks for the
+secmark mechanism. CONFIG_NETLABEL_LSM specifies which LSM hooks
+are used by NetLabel to provide IPv4 CIPSO headers. CONFIG_XFRM_LSM
+specifies the LSM providing xfrm hooks.
+
+The Linux capabilities system is used in conjunction with any LSMs.
+LSM hooks are called after the capability checks in most cases,
+but after in a small number of cases. All LSM hooks need to be aware
+of the potential interactions with the capability system. For more
+details on capabilities, see capabilities(7) in the Linux man-pages
+project.
+
 The primary users of the LSM interface are Mandatory Access Control
 (MAC) extensions which provide a comprehensive security policy. Examples
 include SELinux, Smack, Tomoyo, and AppArmor. In addition to the larger
-MAC extensions, other extensions can be built using the LSM to provide
-specific changes to system operation when these tweaks are not available
-in the core functionality of Linux itself.
-
-Without a specific LSM built into the kernel, the default LSM will be the
-Linux capabilities system. Most LSMs choose to extend the capabilities
-system, building their checks on top of the defined capability hooks.
-For more details on capabilities, see capabilities(7) in the Linux
-man-pages project.
+MAC extensions, other extensions such as Yama can be built using the LSM
+to provide specific changes to system operation when these tweaks are not
+available in the core functionality of Linux itself.
 
 Based on http://kerneltrap.org/Linux/Documenting_Security_Module_Intent,
 a new LSM is accepted into the kernel when its intent (a description of
security/Makefile +1 -2
index c26c81e..b1875b1 100644
@@ -14,9 +14,8 @@ obj-y					+= commoncap.o
 obj-$(CONFIG_MMU)			+= min_addr.o
 
 # Object file lists
-obj-$(CONFIG_SECURITY)			+= security.o capability.o
+obj-$(CONFIG_SECURITY)			+= security.o
 obj-$(CONFIG_SECURITYFS)		+= inode.o
-# Must precede capability.o in order to stack properly.
 obj-$(CONFIG_SECURITY_SELINUX)		+= selinux/built-in.o
 obj-$(CONFIG_SECURITY_SMACK)		+= smack/built-in.o
 obj-$(CONFIG_AUDIT)			+= lsm_audit.o
security/capability.c deleted +0 -1104

1,104 lines not on this page · raw message

--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.

reviewer
#27 lore raw

Re: [PATCH v13 9/9] LSM: Documentation and cleanup

Quoted 3 lines · Casey Schaufler

Subject: [PATCH v13 9/9] LSM: Documentation and cleanup

Add a description of the ways secuirty modules work now.

security

Quoted 15 lines

Remove security/capability.c as it is no longer used.

---
 Documentation/security/LSM.txt |   39 +-
 security/Makefile              |    3 +-
 security/capability.c          | 1104 ----------------------------------------
 3 files changed, 31 insertions(+), 1115 deletions(-)
Documentation/security/LSM.txt +0 -0
index c335a76..f979e00 100644

Documentation/security/LSM.txt CONFIG_DEFAULT_SECURITY and can be overridden at boot-time via the · line 15

Quoted 7 lines
Documentation/security/LSM.txt +4 -0
@@ -9,18 +9,39 @@ CONFIG_DEFAULT_SECURITY and can be overridden at boot-time via the
 "security=..." kernel command line argument, in the case where multiple
 LSMs were built into a given kernel.
 
+Both CONFIG_DEFAULT_SECURITY and the "security=" option take a comma
+separated list of LSM names. The LSM hooks are invoked in the order
+specified. All hooks provided are invoked regardless of the outcome
+of preceeding hooks. Hooks the return success or failure results

preceding . ^^^confusing sentence structure^^^

Quoted 8 lines
Documentation/security/LSM.txt +8 -0
+return success if all of the LSM provided hooks succeed and the error
+code of the last failing hook on error.
+
+The /proc filesystem attribute interface supports files from a time
+when only one LSM could be used at a time. CONFIG_PRESENT_SECURITY
+defines which LSM uses these interfaces. There are also LSM identified
+interfaces which should be used in preference to the undifferentiated
+interfaces.
Signature · 1 line
~Randy