Skip to contentSkip to conversation

LSM: Multiple concurrent LSMs

PATCH In review Casey Schaufler 5 participants 35 messages Jul 25, 2013 – Sep 6, 2013

Subsystems (23)
Networking Documentation VFS USB +19 more subsystems
lore
Share & tools
lore

Casey Schaufler

author maintainer
#0 lore raw

v14 cover LSM: Multiple concurrent LSMs

Subject: [PATCH v14 0/6] LSM: Multiple concurrent LSMs

Version 14 of this patchset is based on v3.10.
It required significant change from version 13 due to changes in the audit code. It came out cleaner, especially in the changes to NetLabel. This version supports all existing LSMs running together at the same time. The combinations tested most completely are:

apparmor,tomoyo,smack,yama - Ubuntu
apparmor,selinux,smack,yama - Fedora

I have been unable to figure out how to configure SELinux on Ubuntu and TOMOYO on Fedora. That's the only reason the list does not include all five LSMs at once. Combining LSMs that use networking is tricky, but can be done. There are changes coming from AppArmor that might make it even trickier, but that's a problem for the future.

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. All combinations of existing LSMs are supported.

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". The XFRM and secmark facilities appear unlikely to ever allow for more than the existing 32 bit values. The NetLabel scheme might possibly be used to represent more than one labeling scheme (CIPSO does allow for multiple tags) although there is no plan to do so at this time. The SO_PEERSEC scheme is capable of providing information from multiple LSMs. Auditing can deal with multiple secids.

The NetLabel, XFRM and secmark facilities are restricted to use by one LSM at a time. The SO_PEERSEC facility can provide information from multiple LSMs, but existing user space tools don't understand that. The default behavior is to assign each of these facilities to the first registered LSM that uses them. They can be configured for use by any of the LSMs that provide hooks for them. SO_PEERSEC can be configured to provide information from all of the LSMs that provide hooks.

The /proc/*/attr interfaces are given to one LSM. This can be done by setting CONFIG_SECURITY_PRESENT. Additional interfaces have been created in /proc/*/attr so that each LSM has its own named interfaces. The name of the presenting LSM can be read from /sys/kernel/security/present. The list of LSMs being used can be read from /sys/kernel/security/lsm.

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                     |   56 +-
 drivers/usb/core/devio.c                           |   13 +-
 fs/proc/base.c                                     |   36 +-
 fs/sysfs/dir.c                                     |    3 +-
 fs/sysfs/inode.c                                   |   12 +-
 fs/sysfs/sysfs.h                                   |    7 +-
 fs/xattr.c                                         |    8 +-
 include/linux/cred.h                               |    4 +-
 include/linux/lsm.h                                |  300 +++
 include/linux/lsm_audit.h                          |    9 +-
 include/linux/sched.h                              |    2 +-
 include/linux/security.h                           |  580 ++++--
 include/net/af_unix.h                              |    5 +-
 include/net/netlabel.h                             |   15 +-
 include/net/scm.h                                  |   11 +-
 include/net/xfrm.h                                 |    9 +-
 kernel/audit.c                                     |   55 +-
 kernel/audit.h                                     |    9 +-
 kernel/auditfilter.c                               |    4 +-
 kernel/auditsc.c                                   |   53 +-
 kernel/cred.c                                      |   17 +-
 kernel/signal.c                                    |    7 +-
 net/ipv4/cipso_ipv4.c                              |    9 +-
 net/ipv4/ip_sockglue.c                             |    8 +-
 .../netfilter/nf_conntrack_l3proto_ipv4_compat.c   |    8 +-
 net/netfilter/nf_conntrack_netlink.c               |   13 +-
 net/netfilter/nf_conntrack_standalone.c            |    8 +-
 net/netfilter/xt_SECMARK.c                         |   13 +-
 net/netlabel/netlabel_kapi.c                       |   47 +-
 net/netlabel/netlabel_unlabeled.c                  |   57 +-
 net/netlabel/netlabel_user.c                       |   10 +-
 net/netlabel/netlabel_user.h                       |    1 +
 net/unix/af_unix.c                                 |   14 +-
 net/xfrm/xfrm_user.c                               |   33 +-
 security/Kconfig                                   |  226 ++-
 security/Makefile                                  |    3 +-
 security/apparmor/context.c                        |   10 +-
 security/apparmor/domain.c                         |   12 +-
 security/apparmor/include/apparmor.h               |    3 +
 security/apparmor/include/context.h                |    9 +-
 security/apparmor/lsm.c                            |   64 +-
 security/capability.c                              | 1106 -----------
 security/commoncap.c                               |    6 -
 security/inode.c                                   |   77 +-
 security/integrity/ima/ima.h                       |    4 +-
 security/integrity/ima/ima_policy.c                |    6 +-
 security/security.c                                | 2082
+++++++++++++++++---
 security/selinux/hooks.c                           |  431 ++--
 security/selinux/include/objsec.h                  |    1 +
 security/selinux/include/xfrm.h                    |    2 +-
 security/selinux/netlabel.c                        |   46 +-
 security/selinux/selinuxfs.c                       |    7 +-
 security/selinux/ss/services.c                     |    5 +-
 security/selinux/xfrm.c                            |    9 +-
 security/smack/smack.h                             |    7 +-
 security/smack/smack_access.c                      |    2 +-
 security/smack/smack_lsm.c                         |  338 ++--
 security/smack/smackfs.c                           |   26 +-
 security/tomoyo/common.h                           |    6 +-
 security/tomoyo/domain.c                           |    2 +-
 security/tomoyo/securityfs_if.c                    |    7 +-
 security/tomoyo/tomoyo.c                           |   34 +-
 security/yama/Kconfig                              |    7 -
 security/yama/yama_lsm.c                           |   33 +-
 64 files changed, 3679 insertions(+), 2328 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.

author maintainer
#1 lore raw

PATCH v14 1/6 LSM: Security blob abstraction

Subject: [PATCH v14 1/6] LSM: Security blob abstraction

Create an abstracted interface for security blobs. Instead of directly accessing security blob pointers Use lsm_get and lsm_set functions that hide the actual mechanism used to maintain the security blobs. This affects most uses of inode->i_security, file->f_security, cred->security and similar fields in keys, sockets, superblocks, ipc and keys.

The use of a single 32 bit integer to refer to a security blob does not scale to the case where there may be more than one relevant security blob. Where it is possible to do so the use of secids (u32) has been replaced with a struct secids, which provides for multiple u32 values. There are components where u32 secids remain at the request of the maintainer of that component.

---
 drivers/usb/core/devio.c                           |   13 +-
 include/linux/cred.h                               |    4 +-
 include/linux/lsm.h                                |  177 +++++++++++
 include/linux/sched.h                              |    2 +-
 include/linux/security.h                           |   76 +++--
 include/net/af_unix.h                              |    2 +-
 include/net/netlabel.h                             |    5 +-
 include/net/scm.h                                  |    4 +-
 include/net/xfrm.h                                 |    5 +-
 kernel/audit.c                                     |   41 ++-
 kernel/audit.h                                     |    9 +-
 kernel/auditfilter.c                               |    4 +-
 kernel/auditsc.c                                   |   43 +--
 kernel/cred.c                                      |    6 +-
 kernel/signal.c                                    |    7 +-
 net/ipv4/cipso_ipv4.c                              |    8 +-
 net/ipv4/ip_sockglue.c                             |    5 +-
 .../netfilter/nf_conntrack_l3proto_ipv4_compat.c   |    5 +-
 net/netfilter/nf_conntrack_netlink.c               |    9 +-
 net/netfilter/nf_conntrack_standalone.c            |    5 +-
 net/netfilter/xt_SECMARK.c                         |    7 +-
 net/netlabel/netlabel_unlabeled.c                  |   32 +-
 net/netlabel/netlabel_user.c                       |    5 +-
 net/netlabel/netlabel_user.h                       |    1 +
 net/unix/af_unix.c                                 |    8 +-
 net/xfrm/xfrm_user.c                               |   33 +-
 security/apparmor/context.c                        |   10 +-
 security/apparmor/domain.c                         |    8 +-
 security/apparmor/include/apparmor.h               |    3 +
 security/apparmor/include/context.h                |    9 +-
 security/apparmor/lsm.c                            |   34 +-
 security/integrity/ima/ima.h                       |    4 +-
 security/integrity/ima/ima_policy.c                |    6 +-
 security/security.c                                |   69 ++--
 security/selinux/hooks.c                           |  333 +++++++++++---------
 security/selinux/include/objsec.h                  |    1 +
 security/selinux/include/xfrm.h                    |    2 +-
 security/selinux/netlabel.c                        |   13 +-
 security/selinux/selinuxfs.c                       |    7 +-
 security/selinux/ss/services.c                     |    5 +-
 security/selinux/xfrm.c                            |    9 +-
 security/smack/smack.h                             |    7 +-
 security/smack/smack_access.c                      |    2 +-
 security/smack/smack_lsm.c                         |  180 +++++------
 security/smack/smackfs.c                           |   16 +-
 security/tomoyo/common.h                           |    4 +-
 security/tomoyo/domain.c                           |    2 +-
 security/tomoyo/securityfs_if.c                    |    7 +-
 security/tomoyo/tomoyo.c                           |   23 +-
 49 files changed, 815 insertions(+), 455 deletions(-)
drivers/usb/core/devio.c +8 -5
index c88c4fb..ab26dc4 100644
@@ -47,6 +47,7 @@
 #include <linux/cdev.h>
 #include <linux/notifier.h>
 #include <linux/security.h>
+#include <linux/lsm.h>
 #include <linux/user_namespace.h>
 #include <linux/scatterlist.h>
 #include <asm/uaccess.h>
@@ -75,7 +76,7 @@ struct dev_state {
 	const struct cred *cred;
 	void __user *disccontext;
 	unsigned long ifclaimed;
-	u32 secid;
+	struct secids secid;
 	u32 disabled_bulk_eps;
 };
 
@@ -91,7 +92,7 @@ struct async {
 	struct urb *urb;
 	unsigned int mem_usage;
 	int status;
-	u32 secid;
+	struct secids secid;
 	u8 bulk_addr;
 	u8 bulk_status;
 };
@@ -492,10 +493,11 @@ static void async_completed(struct urb *urb)
 	struct dev_state *ps = as->ps;
 	struct siginfo sinfo;
 	struct pid *pid = NULL;
-	u32 secid = 0;
+	struct secids secid;
 	const struct cred *cred = NULL;
 	int signr;
 
+	lsm_init_secid(&secid, 0, 0);
 	spin_lock(&ps->lock);
 	list_move_tail(&as->asynclist, &ps->async_completed);
 	as->status = urb->status;
@@ -521,7 +523,8 @@ 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,
+					&secid);
 		put_pid(pid);
 		put_cred(cred);
 	}
@@ -2217,7 +2220,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, &ps->secid);
 		}
 	}
 }
include/linux/cred.h +2 -2
index 04421e8..fb0f399 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);
@@ -338,7 +339,6 @@ static inline void put_cred(const struct cred *_cred)
 #define current_fsgid() 	(current_cred_xxx(fsgid))
 #define current_cap()		(current_cred_xxx(cap_effective))
 #define current_user()		(current_cred_xxx(user))
-#define current_security()	(current_cred_xxx(security))
 
 extern struct user_namespace init_user_ns;
 #ifdef CONFIG_USER_NS
include/linux/lsm.h new file +177 -0

177 lines not on this page · raw message

include/linux/sched.h +1 -1
index 178a8d9..857d988 100644
@@ -2010,7 +2010,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 *, struct secids *);
 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 +50 -26

210 lines not on this page · raw message

include/net/af_unix.h +1 -1
index dbdfd2b..32b53b7 100644
@@ -33,7 +33,7 @@ struct unix_skb_parms {
 	kgid_t			gid;
 	struct scm_fp_list	*fp;		/* Passed files		*/
 #ifdef CONFIG_SECURITY_NETWORK
-	u32			secid;		/* Security ID		*/
+	struct secids		secid;		/* Security ID		*/
 #endif
 };
 
include/net/netlabel.h +3 -2
index 2c95d55..e84fbb5 100644
@@ -36,6 +36,7 @@
 #include <linux/skbuff.h>
 #include <linux/in.h>
 #include <linux/in6.h>
+#include <linux/lsm.h>
 #include <net/netlink.h>
 #include <net/request_sock.h>
 #include <linux/atomic.h>
@@ -109,7 +110,7 @@ struct cipso_v4_doi;
 
 /* NetLabel audit information */
 struct netlbl_audit {
-	u32 secid;
+	struct secids secid;
 	kuid_t loginuid;
 	u32 sessionid;
 };
@@ -213,7 +214,7 @@ struct netlbl_lsm_secattr {
 			struct netlbl_lsm_secattr_catmap *cat;
 			u32 lvl;
 		} mls;
-		u32 secid;
+		struct secids secid;
 	} attr;
 };
 
include/net/scm.h +2 -2
index 8de2d37..349ec25 100644
@@ -29,7 +29,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
 };
 
@@ -93,7 +93,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 94ce082..d8ac020 100644
@@ -13,6 +13,7 @@
 #include <linux/mutex.h>
 #include <linux/audit.h>
 #include <linux/slab.h>
+#include <linux/lsm.h>
 
 #include <net/sock.h>
 #include <net/dst.h>
@@ -699,11 +700,13 @@ static inline void xfrm_audit_helper_usrinfo(kuid_t auid, u32 ses, u32 secid,
 {
 	char *secctx;
 	u32 secctx_len;
+	struct secids secids;
 
 	audit_log_format(audit_buf, " auid=%u ses=%u",
 			 from_kuid(&init_user_ns, auid), ses);
+	lsm_init_secid(&secids, secid, 0);
 	if (secid != 0 &&
-	    security_secid_to_secctx(secid, &secctx, &secctx_len) == 0) {
+	    security_secid_to_secctx(&secids, &secctx, &secctx_len) == 0) {
 		audit_log_format(audit_buf, " subj=%s", secctx);
 		security_release_secctx(secctx, secctx_len);
 	} else
kernel/audit.c +24 -17

103 lines not on this page · raw message

kernel/audit.h +5 -4
index 1c95131..fcc5bb4 100644
@@ -22,6 +22,7 @@
 #include <linux/fs.h>
 #include <linux/audit.h>
 #include <linux/skbuff.h>
+#include <linux/lsm.h>
 #include <uapi/linux/mqueue.h>
 
 /* 0 = no checking
@@ -93,7 +94,7 @@ struct audit_names {
 	kuid_t			uid;
 	kgid_t			gid;
 	dev_t			rdev;
-	u32			osid;
+	struct secids		osid;
 	struct audit_cap_data	fcap;
 	unsigned int		fcap_ver;
 	unsigned char		type;		/* record type */
@@ -145,7 +146,7 @@ struct audit_context {
 	kuid_t		    target_auid;
 	kuid_t		    target_uid;
 	unsigned int	    target_sessionid;
-	u32		    target_sid;
+	struct secids	    target_sid;
 	char		    target_comm[TASK_COMM_LEN];
 
 	struct audit_tree_refs *trees, *first_trees;
@@ -162,7 +163,7 @@ struct audit_context {
 			kuid_t			uid;
 			kgid_t			gid;
 			umode_t			mode;
-			u32			osid;
+			struct secids		osid;
 			int			has_perm;
 			uid_t			perm_uid;
 			gid_t			perm_gid;
@@ -303,7 +304,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 +2 -2
index 6bd4a90..701d308 100644
@@ -1216,7 +1216,7 @@ static int audit_filter_user_rules(struct audit_krule *rule, int type,
 	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:
@@ -1246,7 +1246,7 @@ static int audit_filter_user_rules(struct audit_krule *rule, int type,
 		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 +25 -18

125 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);
 
kernel/signal.c +5 -2
index 113411b..ce19c78 100644
@@ -19,6 +19,7 @@
 #include <linux/binfmts.h>
 #include <linux/coredump.h>
 #include <linux/security.h>
+#include <linux/lsm.h>
 #include <linux/syscalls.h>
 #include <linux/ptrace.h>
 #include <linux/signal.h>
@@ -789,6 +790,7 @@ static int check_kill_permission(int sig, struct siginfo *info,
 {
 	struct pid *sid;
 	int error;
+	struct secids secid;
 
 	if (!valid_signal(sig))
 		return -EINVAL;
@@ -816,7 +818,8 @@ static int check_kill_permission(int sig, struct siginfo *info,
 		}
 	}
 
-	return security_task_kill(t, info, sig, 0);
+	lsm_init_secid(&secid, 0, 0);
+	return security_task_kill(t, info, sig, &secid);
 }
 
 /**
@@ -1390,7 +1393,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, struct secids *secid)
 {
 	int ret = -EINVAL;
 	struct task_struct *p;
net/ipv4/cipso_ipv4.c +6 -2
index 667c1d4..1b47808 100644
@@ -45,6 +45,7 @@
 #include <linux/jhash.h>
 #include <linux/audit.h>
 #include <linux/slab.h>
+#include <linux/lsm.h>
 #include <net/ip.h>
 #include <net/icmp.h>
 #include <net/tcp.h>
@@ -1569,7 +1570,7 @@ static int cipso_v4_gentag_loc(const struct cipso_v4_doi *doi_def,
 
 	buffer[0] = CIPSO_V4_TAG_LOCAL;
 	buffer[1] = CIPSO_V4_TAG_LOC_BLEN;
-	*(u32 *)&buffer[2] = secattr->attr.secid;
+	*(u32 *)&buffer[2] = lsm_get_secid(&secattr->attr.secid, 0);
 
 	return CIPSO_V4_TAG_LOC_BLEN;
 }
@@ -1589,7 +1590,10 @@ static int cipso_v4_parsetag_loc(const struct cipso_v4_doi *doi_def,
 				 const unsigned char *tag,
 				 struct netlbl_lsm_secattr *secattr)
 {
-	secattr->attr.secid = *(u32 *)&tag[2];
+	u32 secid;
+
+	secid = *(u32 *)&tag[2];
+	lsm_init_secid(&secattr->attr.secid, secid, 0);
 	secattr->flags |= NETLBL_SECATTR_SECID;
 
 	return 0;
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 +4 -1
index 4c48e43..f7704fe 100644
@@ -13,6 +13,7 @@
 #include <linux/seq_file.h>
 #include <linux/percpu.h>
 #include <linux/security.h>
+#include <linux/lsm.h>
 #include <net/net_namespace.h>
 
 #include <linux/netfilter.h>
@@ -99,8 +100,10 @@ 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);
+	lsm_init_secid(&secid, ct->secmark, 0);
+	ret = security_secid_to_secctx(&secid, &secctx, &len);
 	if (ret)
 		return 0;
 
net/netfilter/nf_conntrack_netlink.c +7 -2
index ecf065f..d45138e 100644
@@ -23,6 +23,7 @@
 #include <linux/types.h>
 #include <linux/timer.h>
 #include <linux/security.h>
+#include <linux/lsm.h>
 #include <linux/skbuff.h>
 #include <linux/errno.h>
 #include <linux/netlink.h>
@@ -301,8 +302,10 @@ 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);
+	lsm_init_secid(&secid, ct->secmark, 0);
+	ret = security_secid_to_secctx(&secid, &secctx, &len);
 	if (ret)
 		return 0;
 
@@ -548,8 +551,10 @@ ctnetlink_secctx_size(const struct nf_conn *ct)
 {
 #ifdef CONFIG_NF_CONNTRACK_SECMARK
 	int len, ret;
+	struct secids secid;
 
-	ret = security_secid_to_secctx(ct->secmark, NULL, &len);
+	lsm_init_secid(&secid, ct->secmark, 0);
+	ret = security_secid_to_secctx(&secid, NULL, &len);
 	if (ret)
 		return 0;
 
net/netfilter/nf_conntrack_standalone.c +4 -1
index bd700b4..831116a 100644
@@ -17,6 +17,7 @@
 #include <linux/percpu.h>
 #include <linux/netdevice.h>
 #include <linux/security.h>
+#include <linux/lsm.h>
 #include <net/net_namespace.h>
 #ifdef CONFIG_SYSCTL
 #include <linux/sysctl.h>
@@ -124,8 +125,10 @@ 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);
+	lsm_init_secid(&secid, ct->secmark, 0);
+	ret = security_secid_to_secctx(&secid, &secctx, &len);
 	if (ret)
 		return 0;
 
net/netfilter/xt_SECMARK.c +5 -2
index 9faf5e0..823ed01 100644
@@ -15,6 +15,7 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 #include <linux/module.h>
 #include <linux/security.h>
+#include <linux/lsm.h>
 #include <linux/skbuff.h>
 #include <linux/netfilter/x_tables.h>
 #include <linux/netfilter/xt_SECMARK.h>
@@ -52,24 +53,26 @@ 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;
 
 	err = security_secctx_to_secid(info->secctx, strlen(info->secctx),
-				       &info->secid);
+				       &secid);
 	if (err) {
 		if (err == -EINVAL)
 			pr_info("invalid security context \'%s\'\n", info->secctx);
 		return err;
 	}
 
+	info->secid = lsm_get_secid(&secid, 0);
 	if (!info->secid) {
 		pr_info("unable to map security context \'%s\'\n", info->secctx);
 		return -ENOENT;
 	}
 
-	err = security_secmark_relabel_packet(info->secid);
+	err = security_secmark_relabel_packet(&secid);
 	if (err) {
 		pr_info("unable to obtain relabeling permission\n");
 		return err;
net/netlabel/netlabel_unlabeled.c +18 -14
index 8a6c6ea..cd1e571 100644
@@ -81,7 +81,7 @@ struct netlbl_unlhsh_tbl {
 #define netlbl_unlhsh_addr4_entry(iter) \
 	container_of(iter, struct netlbl_unlhsh_addr4, list)
 struct netlbl_unlhsh_addr4 {
-	u32 secid;
+	struct secids secid;
 
 	struct netlbl_af4list list;
 	struct rcu_head rcu;
@@ -89,7 +89,7 @@ struct netlbl_unlhsh_addr4 {
 #define netlbl_unlhsh_addr6_entry(iter) \
 	container_of(iter, struct netlbl_unlhsh_addr6, list)
 struct netlbl_unlhsh_addr6 {
-	u32 secid;
+	struct secids secid;
 
 	struct netlbl_af6list list;
 	struct rcu_head rcu;
@@ -263,7 +263,7 @@ static int netlbl_unlhsh_add_addr4(struct netlbl_unlhsh_iface *iface,
 	entry->list.addr = addr->s_addr & mask->s_addr;
 	entry->list.mask = mask->s_addr;
 	entry->list.valid = 1;
-	entry->secid = secid;
+	lsm_init_secid(&entry->secid, secid, 0);
 
 	spin_lock(&netlbl_unlhsh_lock);
 	ret_val = netlbl_af4list_add(&entry->list, &iface->addr4_list);
@@ -307,7 +307,7 @@ static int netlbl_unlhsh_add_addr6(struct netlbl_unlhsh_iface *iface,
 	entry->list.addr.s6_addr32[3] &= mask->s6_addr32[3];
 	entry->list.mask = *mask;
 	entry->list.valid = 1;
-	entry->secid = secid;
+	lsm_init_secid(&entry->secid, secid, 0);
 
 	spin_lock(&netlbl_unlhsh_lock);
 	ret_val = netlbl_af6list_add(&entry->list, &iface->addr6_list);
@@ -394,6 +394,7 @@ int netlbl_unlhsh_add(struct net *net,
 	struct net_device *dev;
 	struct netlbl_unlhsh_iface *iface;
 	struct audit_buffer *audit_buf = NULL;
+	struct secids secids;
 	char *secctx = NULL;
 	u32 secctx_len;
 
@@ -458,7 +459,8 @@ int netlbl_unlhsh_add(struct net *net,
 unlhsh_add_return:
 	rcu_read_unlock();
 	if (audit_buf != NULL) {
-		if (security_secid_to_secctx(secid,
+		lsm_init_secid(&secids, secid, 0);
+		if (security_secid_to_secctx(&secids,
 					     &secctx,
 					     &secctx_len) == 0) {
 			audit_log_format(audit_buf, " sec_obj=%s", secctx);
@@ -515,7 +517,7 @@ static int netlbl_unlhsh_remove_addr4(struct net *net,
 		if (dev != NULL)
 			dev_put(dev);
 		if (entry != NULL &&
-		    security_secid_to_secctx(entry->secid,
+		    security_secid_to_secctx(&entry->secid,
 					     &secctx, &secctx_len) == 0) {
 			audit_log_format(audit_buf, " sec_obj=%s", secctx);
 			security_release_secctx(secctx, secctx_len);
@@ -576,7 +578,7 @@ static int netlbl_unlhsh_remove_addr6(struct net *net,
 		if (dev != NULL)
 			dev_put(dev);
 		if (entry != NULL &&
-		    security_secid_to_secctx(entry->secid,
+		    security_secid_to_secctx(&entry->secid,
 					     &secctx, &secctx_len) == 0) {
 			audit_log_format(audit_buf, " sec_obj=%s", secctx);
 			security_release_secctx(secctx, secctx_len);
@@ -902,7 +904,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 +933,8 @@ 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,
+				 lsm_get_secid(&secid, 0),
 				 &audit_info);
 }
 
@@ -953,7 +956,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 +983,8 @@ 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,
+				 lsm_get_secid(&secid, 0),
 				 &audit_info);
 }
 
@@ -1092,7 +1096,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 +1138,7 @@ static int netlbl_unlabel_staticlist_gen(u32 cmd,
 		if (ret_val != 0)
 			goto list_cb_failure;
 
-		secid = addr4->secid;
+		secid = &addr4->secid;
 	} else {
 		ret_val = nla_put(cb_arg->skb,
 				  NLBL_UNLABEL_A_IPV6ADDR,
@@ -1150,7 +1154,7 @@ static int netlbl_unlabel_staticlist_gen(u32 cmd,
 		if (ret_val != 0)
 			goto list_cb_failure;
 
-		secid = addr6->secid;
+		secid = &addr6->secid;
 	}
 
 	ret_val = security_secid_to_secctx(secid, &secctx, &secctx_len);
net/netlabel/netlabel_user.c +3 -2
index 9650c4a..898153c 100644
@@ -35,6 +35,7 @@
 #include <linux/audit.h>
 #include <linux/tty.h>
 #include <linux/security.h>
+#include <linux/lsm.h>
 #include <linux/gfp.h>
 #include <net/sock.h>
 #include <net/netlink.h>
@@ -112,8 +113,8 @@ struct audit_buffer *netlbl_audit_start_common(int type,
 			 from_kuid(&init_user_ns, audit_info->loginuid),
 			 audit_info->sessionid);
 
-	if (audit_info->secid != 0 &&
-	    security_secid_to_secctx(audit_info->secid,
+	if (!lsm_zero_secid(&audit_info->secid) &&
+	    security_secid_to_secctx(&audit_info->secid,
 				     &secctx,
 				     &secctx_len) == 0) {
 		audit_log_format(audit_buf, " subj=%s", secctx);
net/netlabel/netlabel_user.h +1 -0
index 8196978..f23656b 100644
@@ -35,6 +35,7 @@
 #include <linux/skbuff.h>
 #include <linux/capability.h>
 #include <linux/audit.h>
+#include <linux/lsm.h>
 #include <net/netlink.h>
 #include <net/genetlink.h>
 #include <net/netlabel.h>
net/unix/af_unix.c +6 -2
index 826e099..964bbe3 100644
@@ -137,12 +137,16 @@ static struct hlist_head *unix_sockets_unbound(void *addr)
 #ifdef CONFIG_SECURITY_NETWORK
 static void unix_get_secdata(struct scm_cookie *scm, struct sk_buff *skb)
 {
-	memcpy(UNIXSID(skb), &scm->secid, sizeof(u32));
+	struct secids *skb_secid = UNIXSID(skb);
+
+	*skb_secid = scm->secid;
 }
 
 static inline void unix_set_secdata(struct scm_cookie *scm, struct sk_buff *skb)
 {
-	scm->secid = *UNIXSID(skb);
+	struct secids *skb_secid = UNIXSID(skb);
+
+	scm->secid = *skb_secid;
 }
 #else
 static inline void unix_get_secdata(struct scm_cookie *scm, struct sk_buff *skb)
net/xfrm/xfrm_user.c +25 -8
index 3f565e4..85f6bca 100644
@@ -23,6 +23,7 @@
 #include <linux/ipsec.h>
 #include <linux/init.h>
 #include <linux/security.h>
+#include <linux/lsm.h>
 #include <net/sock.h>
 #include <net/xfrm.h>
 #include <net/netlink.h>
@@ -601,6 +602,7 @@ static int xfrm_add_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
 	kuid_t loginuid = audit_get_loginuid(current);
 	u32 sessionid = audit_get_sessionid(current);
 	u32 sid;
+	struct secids sids;
 
 	err = verify_newsa_info(p, attrs);
 	if (err)
@@ -616,7 +618,8 @@ static int xfrm_add_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
 	else
 		err = xfrm_state_update(x);
 
-	security_task_getsecid(current, &sid);
+	security_task_getsecid(current, &sids);
+	sid = lsm_get_secid(&sids, 0);
 	xfrm_audit_state_add(x, err ? 0 : 1, loginuid, sessionid, sid);
 
 	if (err < 0) {
@@ -680,6 +683,7 @@ static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
 	kuid_t loginuid = audit_get_loginuid(current);
 	u32 sessionid = audit_get_sessionid(current);
 	u32 sid;
+	struct secids sids;
 
 	x = xfrm_user_state_lookup(net, p, attrs, &err);
 	if (x == NULL)
@@ -704,7 +708,8 @@ static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
 	km_state_notify(x, &c);
 
 out:
-	security_task_getsecid(current, &sid);
+	security_task_getsecid(current, &sids);
+	sid = lsm_get_secid(&sids, 0);
 	xfrm_audit_state_delete(x, err ? 0 : 1, loginuid, sessionid, sid);
 	xfrm_state_put(x);
 	return err;
@@ -1406,6 +1411,7 @@ static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
 	kuid_t loginuid = audit_get_loginuid(current);
 	u32 sessionid = audit_get_sessionid(current);
 	u32 sid;
+	struct secids sids;
 
 	err = verify_newpolicy_info(p);
 	if (err)
@@ -1424,7 +1430,8 @@ static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
 	 * a type XFRM_MSG_UPDPOLICY - JHS */
 	excl = nlh->nlmsg_type == XFRM_MSG_NEWPOLICY;
 	err = xfrm_policy_insert(p->dir, xp, excl);
-	security_task_getsecid(current, &sid);
+	security_task_getsecid(current, &sids);
+	sid = lsm_get_secid(&sids, 0);
 	xfrm_audit_policy_add(xp, err ? 0 : 1, loginuid, sessionid, sid);
 
 	if (err) {
@@ -1664,8 +1671,10 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
 		kuid_t loginuid = audit_get_loginuid(current);
 		u32 sessionid = audit_get_sessionid(current);
 		u32 sid;
+		struct secids sids;
 
-		security_task_getsecid(current, &sid);
+		security_task_getsecid(current, &sids);
+		sid = lsm_get_secid(&sids, 0);
 		xfrm_audit_policy_delete(xp, err ? 0 : 1, loginuid, sessionid,
 					 sid);
 
@@ -1693,11 +1702,13 @@ static int xfrm_flush_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
 	struct km_event c;
 	struct xfrm_usersa_flush *p = nlmsg_data(nlh);
 	struct xfrm_audit audit_info;
+	struct secids secid;
 	int err;
 
 	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 = lsm_get_secid(&secid, 0);
 	err = xfrm_state_flush(net, p->proto, &audit_info);
 	if (err) {
 		if (err == -ESRCH) /* empty table */
@@ -1883,6 +1894,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)
@@ -1890,7 +1902,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 = lsm_get_secid(&secid, 0);
 	err = xfrm_policy_flush(net, type, &audit_info);
 	if (err) {
 		if (err == -ESRCH) /* empty table */
@@ -1960,8 +1973,10 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
 		kuid_t loginuid = audit_get_loginuid(current);
 		u32 sessionid = audit_get_sessionid(current);
 		u32 sid;
+		struct secids sids;
 
-		security_task_getsecid(current, &sid);
+		security_task_getsecid(current, &sids);
+		sid = lsm_get_secid(&sids, 0);
 		xfrm_policy_delete(xp, p->dir);
 		xfrm_audit_policy_delete(xp, 1, loginuid, sessionid, sid);
 
@@ -2003,8 +2018,10 @@ static int xfrm_add_sa_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
 		kuid_t loginuid = audit_get_loginuid(current);
 		u32 sessionid = audit_get_sessionid(current);
 		u32 sid;
+		struct secids sids;
 
-		security_task_getsecid(current, &sid);
+		security_task_getsecid(current, &sids);
+		sid = lsm_get_secid(&sids, 0);
 		__xfrm_state_delete(x);
 		xfrm_audit_state_delete(x, 1, loginuid, sessionid, sid);
 	}
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/apparmor.h +3 -0
index 40aedd9..e94439a 100644
@@ -61,6 +61,9 @@ extern unsigned int aa_g_path_max;
 /* Flag indicating whether initialization completed */
 extern int apparmor_initialized __initdata;
 
+extern struct security_operations apparmor_ops;
+
+
 /* fn's in lib */
 char *aa_split_fqname(char *args, char **ns_name);
 void aa_info_message(const char *str);
security/apparmor/include/context.h +6 -3
index a9cbee4..d844ae0 100644
@@ -18,6 +18,7 @@
 #include <linux/cred.h>
 #include <linux/slab.h>
 #include <linux/sched.h>
+#include <linux/lsm.h>
 
 #include "policy.h"
 
@@ -89,7 +90,8 @@ 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 =
+		lsm_get_cred(__task_cred(task), &apparmor_ops);
 
 	BUG_ON(!cxt || !cxt->profile);
 	if (unconfined(aa_newest_version(cxt->profile)))
@@ -108,7 +110,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,7 +138,8 @@ 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 =
+		lsm_get_cred(current_cred(), &apparmor_ops);
 	struct aa_profile *profile;
 	BUG_ON(!cxt || !cxt->profile);
 
security/apparmor/lsm.c +17 -17
index b21830e..64557a0 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,14 @@ 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);
 
 	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 +472,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 +510,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 +614,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,
@@ -886,7 +886,7 @@ static int __init set_init_cxt(void)
 		return -ENOMEM;
 
 	cxt->profile = aa_get_profile(root_ns->unconfined);
-	cred->security = cxt;
+	lsm_set_cred(cred, cxt, &apparmor_ops);
 
 	return 0;
 }
@@ -931,7 +931,7 @@ static int __init apparmor_init(void)
 	return error;
 
 set_init_cxt_out:
-	aa_free_task_context(current->real_cred->security);
+	aa_free_task_context(lsm_get_cred(current->real_cred, &apparmor_ops));
 
 register_security_out:
 	aa_free_root_ns();
security/integrity/ima/ima.h +2 -2
index a41c9c1..b922449 100644
@@ -192,8 +192,8 @@ static inline int security_filter_rule_init(u32 field, u32 op, char *rulestr,
 	return -EINVAL;
 }
 
-static inline int security_filter_rule_match(u32 secid, u32 field, u32 op,
-					     void *lsmrule,
+static inline int security_filter_rule_match(struct secids *secid, u32 field,
+					     u32 op, void *lsmrule,
 					     struct audit_context *actx)
 {
 	return -EINVAL;
security/integrity/ima/ima_policy.c +3 -3
index 399433a..a0a4e90 100644
@@ -184,7 +184,7 @@ 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 osid, sid;
 		int retried = 0;
 
 		if (!rule->lsm[i].rule)
@@ -195,7 +195,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 +205,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 +47 -22

148 lines not on this page · raw message

security/selinux/hooks.c +188 -145

1,009 lines not on this page · raw message

security/selinux/include/objsec.h +1 -0
index aa47bca..9628bcb 100644
@@ -119,5 +119,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..63154c6 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 +4 -3
index ff42773..bac7874 100644
@@ -23,6 +23,7 @@
 #include <linux/init.h>
 #include <linux/string.h>
 #include <linux/security.h>
+#include <linux/lsm.h>
 #include <linux/major.h>
 #include <linux/seq_file.h>
 #include <linux/percpu.h>
@@ -83,7 +84,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 +1263,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 +1828,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/ss/services.c +3 -2
index b4feecc..71b0939 100644
@@ -48,6 +48,7 @@
 #include <linux/in.h>
 #include <linux/sched.h>
 #include <linux/audit.h>
+#include <linux/lsm.h>
 #include <linux/mutex.h>
 #include <linux/selinux.h>
 #include <linux/flex_array.h>
@@ -3129,7 +3130,7 @@ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
 	if (secattr->flags & NETLBL_SECATTR_CACHE)
 		*sid = *(u32 *)secattr->cache->data;
 	else if (secattr->flags & NETLBL_SECATTR_SECID)
-		*sid = secattr->attr.secid;
+		*sid = lsm_get_secid(&secattr->attr.secid, 0);
 	else if (secattr->flags & NETLBL_SECATTR_MLS_LVL) {
 		rc = -EIDRM;
 		ctx = sidtab_search(&sidtab, SECINITSID_NETMSG);
@@ -3204,7 +3205,7 @@ int security_netlbl_sid_to_secattr(u32 sid, struct netlbl_lsm_secattr *secattr)
 	if (secattr->domain == NULL)
 		goto out;
 
-	secattr->attr.secid = sid;
+	lsm_set_secid(&secattr->attr.secid, sid, 0);
 	secattr->flags |= NETLBL_SECATTR_DOMAIN_CPY | NETLBL_SECATTR_SECID;
 	mls_export_netlbl_lvl(ctx, secattr);
 	rc = mls_export_netlbl_cat(ctx, secattr);
security/selinux/xfrm.c +6 -3
index d030818..25fb459 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;
@@ -336,7 +337,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);
 
 	if (!ctx)
 		return 0;
@@ -377,7 +379,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;
 
 	if (!ctx)
security/smack/smack.h +4 -3
index 8ad3095..83997ba 100644
@@ -16,6 +16,7 @@
 #include <linux/capability.h>
 #include <linux/spinlock.h>
 #include <linux/security.h>
+#include <linux/lsm.h>
 #include <linux/in.h>
 #include <net/netlabel.h>
 #include <linux/list.h>
@@ -240,7 +241,7 @@ extern struct security_operations smack_ops;
  */
 static inline int smk_inode_transmutable(const 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;
 }
 
@@ -249,7 +250,7 @@ static inline int smk_inode_transmutable(const struct inode *isp)
  */
 static inline char *smk_of_inode(const struct inode *isp)
 {
-	struct inode_smack *sip = isp->i_security;
+	struct inode_smack *sip = lsm_get_inode(isp, &smack_ops);
 	return sip->smk_inode;
 }
 
@@ -274,7 +275,7 @@ static inline char *smk_of_forked(const struct task_smack *tsp)
  */
 static inline char *smk_of_current(void)
 {
-	return smk_of_task(current_security());
+	return smk_of_task(lsm_get_cred(current_cred(), &smack_ops));
 }
 
 /*
security/smack/smack_access.c +1 -1
index 2e397a8..360a56c 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 +91 -89

100 lines not on this page · raw message

security/smack/smackfs.c +8 -8
index 53a08b8..af7629c 100644

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

security/tomoyo/common.h +3 -1
index b897d48..9285c23 100644

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

security/tomoyo/domain.c +1 -1
index 3865145..e90482a 100644

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

security/tomoyo/securityfs_if.c +4 -3
index 179a955..c7afa26 100644

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

security/tomoyo/tomoyo.c +12 -11
index f0b756e..624d8f2 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
#4 lore raw

PATCH v14 2/6 LSM: Move the capability LSM into the hook handlers

In reply to Casey Schaufler

Subject: [PATCH v14 2/6] LSM: Move the capability LSM into the hook handlers

Move the capability module hooks out of thier own module and into security.c. Pull the calls out of the LSMs as well, as the call is getting already getting done. It turns out that in all but a few cases the LSMs that provide those hooks call the capability function themselves.

When a secctx is generated it may be done for a specific LSM or for a collection of LSMs. In the former case the LSM's free function will be required to release the memory involved, while in the latter case the lsm infrastructure's free code needs to be called. The context generation has to note which LSM created a context, or if it was done for a set.

---
 fs/sysfs/dir.c                                     |    3 +-
 fs/sysfs/inode.c                                   |   12 ++-
 fs/sysfs/sysfs.h                                   |    7 +-
 fs/xattr.c                                         |    8 +-
 include/linux/lsm.h                                |   46 +++++++++
 include/linux/security.h                           |   40 +++++---
 include/net/scm.h                                  |    9 +-
 include/net/xfrm.h                                 |    6 +-
 kernel/audit.c                                     |   22 +++--
 kernel/auditsc.c                                   |   10 +-
 kernel/cred.c                                      |   11 ++-
 net/ipv4/cipso_ipv4.c                              |    3 +-
 net/ipv4/ip_sockglue.c                             |    5 +-
 .../netfilter/nf_conntrack_l3proto_ipv4_compat.c   |    5 +-
 net/netfilter/nf_conntrack_netlink.c               |    8 +-
 net/netfilter/nf_conntrack_standalone.c            |    5 +-
 net/netfilter/xt_SECMARK.c                         |    4 +-
 net/netlabel/netlabel_unlabeled.c                  |   28 +++---
 net/netlabel/netlabel_user.c                       |    5 +-
 net/xfrm/xfrm_user.c                               |   16 +--
 security/apparmor/domain.c                         |   13 +--
 security/apparmor/lsm.c                            |   22 +----
 security/security.c                                |  104 +++++++++++++++++---
 security/selinux/hooks.c                           |   73 +-------------
 security/selinux/ss/services.c                     |    4 +-
 security/smack/smack_lsm.c                         |   45 ++-------
 security/tomoyo/common.h                           |    2 +-
 security/tomoyo/tomoyo.c                           |    6 --
 security/yama/yama_lsm.c                           |   24 +----
 29 files changed, 296 insertions(+), 250 deletions(-)
fs/sysfs/dir.c +2 -1
index e8e0e71..62937d1 100644
@@ -278,7 +278,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 +8 -4
index 0ce3ccf..677f37c 100644
@@ -130,7 +130,9 @@ out:
 	return error;
 }
 
-static int sysfs_sd_setsecdata(struct sysfs_dirent *sd, void **secdata, u32 *secdata_len)
+static int sysfs_sd_setsecdata(struct sysfs_dirent *sd, void **secdata,
+				u32 *secdata_len,
+				struct security_operations *sop)
 {
 	struct sysfs_inode_attrs *iattrs;
 	void *old_secdata;
@@ -148,6 +150,7 @@ static int sysfs_sd_setsecdata(struct sysfs_dirent *sd, void **secdata, u32 *sec
 
 	iattrs->ia_secdata = *secdata;
 	iattrs->ia_secdata_len = *secdata_len;
+	iattrs->ia_sop = sop;
 
 	*secdata = old_secdata;
 	*secdata_len = old_secdata_len;
@@ -161,6 +164,7 @@ int sysfs_setxattr(struct dentry *dentry, const char *name, const void *value,
 	void *secdata;
 	int error;
 	u32 secdata_len = 0;
+	struct security_operations *sop;
 
 	if (!sd)
 		return -EINVAL;
@@ -172,16 +176,16 @@ 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;
 
 		mutex_lock(&sysfs_mutex);
-		error = sysfs_sd_setsecdata(sd, &secdata, &secdata_len);
+		error = sysfs_sd_setsecdata(sd, &secdata, &secdata_len, sop);
 		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..9def633 100644
@@ -148,13 +148,15 @@ xattr_getsecurity(struct inode *inode, const char *name, void *value,
 {
 	void *buffer = NULL;
 	ssize_t len;
+	struct security_operations *sop;
 
 	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/lsm.h +46 -0

56 lines not on this page · raw message

include/linux/security.h +28 -12
index e02cad4..870e264 100644
@@ -1773,7 +1773,9 @@ 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 **sop);
 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);
@@ -1850,15 +1852,22 @@ 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);
+			     struct secids *secid,
+			     struct security_operations *secops);
+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_operations {
+};
+
 struct security_mnt_opts {
 };
 
@@ -2184,7 +2193,10 @@ 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 **sop)
 {
 	return -EOPNOTSUPP;
 }
@@ -2539,19 +2551,21 @@ static inline int security_netlink_send(struct sock *sk, struct sk_buff *skb)
 }
 
 static inline int security_secid_to_secctx(struct secids *secid,
-						char **secdata, u32 *seclen)
+					   char **secdata, u32 *seclen,
+					   struct security_operations **secops)
 {
 	return -EOPNOTSUPP;
 }
 
-static inline int security_secctx_to_secid(const char *secdata,
-					   u32 seclen,
-					   struct secids *secid)
+static inline int security_secctx_to_secid(const char *secdata, u32 seclen,
+					   struct secids *secid,
+				           struct security_operations *secops)
 {
 	return -EOPNOTSUPP;
 }
 
-static inline void security_release_secctx(char *secdata, u32 seclen)
+static inline void security_release_secctx(char *secdata, u32 seclen,
+					   struct security_operations *secops)
 {
 }
 
@@ -2563,7 +2577,9 @@ 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 +6 -3
index 349ec25..5279fb1 100644
@@ -91,13 +91,16 @@ static inline void scm_passec(struct socket *sock, struct msghdr *msg, struct sc
 	char *secdata;
 	u32 seclen;
 	int err;
+	struct security_operations *sop;
 
 	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);
+			put_cmsg(msg, SOL_SOCKET, SCM_SECURITY, seclen,
+					secdata);
+			security_release_secctx(secdata, seclen, sop);
 		}
 	}
 }
include/net/xfrm.h +4 -2
index d8ac020..49824d5 100644
@@ -701,14 +701,16 @@ static inline void xfrm_audit_helper_usrinfo(kuid_t auid, u32 ses, u32 secid,
 	char *secctx;
 	u32 secctx_len;
 	struct secids secids;
+	struct security_operations *sop;
 
 	audit_log_format(audit_buf, " auid=%u ses=%u",
 			 from_kuid(&init_user_ns, auid), ses);
 	lsm_init_secid(&secids, secid, 0);
 	if (secid != 0 &&
-	    security_secid_to_secctx(&secids, &secctx, &secctx_len) == 0) {
+	    security_secid_to_secctx(&secids, &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 -9
index d49f7ab..3d55ca0 100644
@@ -640,6 +640,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 	struct audit_sig_info   *sig_data;
 	char			*ctx = NULL;
 	u32			len;
+	struct security_operations *sop;
 
 	err = audit_netlink_ok(skb, msg_type);
 	if (err)
@@ -795,21 +796,21 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 		len = 0;
 		if (!lsm_zero_secid(&audit_sig_sid)) {
 			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 (!lsm_zero_secid(&audit_sig_sid))
-				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 (!lsm_zero_secid(&audit_sig_sid)) {
 			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);
@@ -1480,6 +1481,7 @@ void audit_copy_inode(struct audit_names *name, const struct dentry *dentry,
 void audit_log_name(struct audit_context *context, struct audit_names *n,
 		    struct path *path, 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)
@@ -1526,13 +1528,13 @@ void audit_log_name(struct audit_context *context, struct audit_names *n,
 	if (!lsm_zero_secid(&n->osid)) {
 		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);
 			if (call_panic)
 				*call_panic = 2;
 		} else {
 			audit_log_format(ab, " obj=%s", ctx);
-			security_release_secctx(ctx, len);
+			security_release_secctx(ctx, len, sop);
 		}
 	}
 
@@ -1546,12 +1548,13 @@ int 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 (lsm_zero_secid(&sid))
 		return 0;
 
-	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;
@@ -1559,7 +1562,7 @@ int 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 0;
 
 error_path:
@@ -1728,13 +1731,14 @@ void audit_log_secctx(struct audit_buffer *ab, u32 secid)
 	u32 len;
 	char *secctx;
 	struct secids secids;
+	struct security_operations *sop;
 
 	lsm_init_secid(&secids, secid, 0);
-	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/auditsc.c +6 -4
index 5a6478a..0bab5c5 100644
@@ -984,6 +984,7 @@ static int audit_log_pid_context(struct audit_context *context, pid_t pid,
 	char *ctx = NULL;
 	u32 len;
 	int rc = 0;
+	struct security_operations *sop;
 
 	ab = audit_log_start(context, GFP_KERNEL, AUDIT_OBJ_PID);
 	if (!ab)
@@ -993,12 +994,12 @@ static int audit_log_pid_context(struct audit_context *context, pid_t pid,
 			 from_kuid(&init_user_ns, auid),
 			 from_kuid(&init_user_ns, uid), sessionid);
 	if (!lsm_zero_secid(sid)) {
-		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=");
@@ -1220,12 +1221,13 @@ static void show_special(struct audit_context *context, int *call_panic)
 		if (!lsm_zero_secid(osid)) {
 			char *ctx = NULL;
 			u32 len;
-			if (security_secid_to_secctx(osid, &ctx, &len)) {
+			struct security_operations *sop;
+			if (security_secid_to_secctx(osid, &ctx, &len, &sop)) {
 				audit_log_format(ab, " osc=%u", osid->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) {
kernel/cred.c +8 -3
index c94a3ff..7a88548 100644
@@ -653,16 +653,21 @@ EXPORT_SYMBOL(set_security_override);
  * @secctx: The LSM security context to generate the security ID from.
  *
  * 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.  The
- * security ID is specified in string form as a security context to be
+ * security is overridden when an alternative set of credentials is used.
+ * The security ID is specified in string form as a security context to be
  * interpreted by the LSM.
+ *
+ * The last parameter to security_secctx_to_secid() indicates which
+ * LSM should interpret the context string. NULL means that the LSM
+ * infrastructure may have to figure out for itself which LSM or set
+ * of LSMs should get called.
  */
 int set_security_override_from_ctx(struct cred *new, const char *secctx)
 {
 	struct secids secid;
 	int ret;
 
-	ret = security_secctx_to_secid(secctx, strlen(secctx), &secid);
+	ret = security_secctx_to_secid(secctx, strlen(secctx), &secid, NULL);
 	if (ret < 0)
 		return ret;
 
net/ipv4/cipso_ipv4.c +2 -1
index 1b47808..00a2b2b 100644
@@ -1570,7 +1570,8 @@ static int cipso_v4_gentag_loc(const struct cipso_v4_doi *doi_def,
 
 	buffer[0] = CIPSO_V4_TAG_LOCAL;
 	buffer[1] = CIPSO_V4_TAG_LOC_BLEN;
-	*(u32 *)&buffer[2] = lsm_get_secid(&secattr->attr.secid, 0);
+	*(u32 *)&buffer[2] = lsm_get_secid(&secattr->attr.secid,
+						lsm_netlbl_order());
 
 	return CIPSO_V4_TAG_LOC_BLEN;
 }
net/ipv4/ip_sockglue.c +3 -2
index a55f8c0..3986a24 100644
@@ -111,17 +111,18 @@ static void ip_cmsg_recv_security(struct msghdr *msg, struct sk_buff *skb)
 	u32 seclen;
 	struct secids secid;
 	int err;
+	struct security_operations *sop;
 
 	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/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c +3 -2
index f7704fe..8f73bfb 100644
@@ -101,15 +101,16 @@ 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;
 
 	lsm_init_secid(&secid, ct->secmark, 0);
-	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/netfilter/nf_conntrack_netlink.c +5 -3
index d45138e..e240d22 100644
@@ -303,9 +303,10 @@ ctnetlink_dump_secctx(struct sk_buff *skb, const struct nf_conn *ct)
 	int len, ret;
 	char *secctx;
 	struct secids secid;
+	struct security_operations *sop;
 
 	lsm_init_secid(&secid, ct->secmark, 0);
-	ret = security_secid_to_secctx(&secid, &secctx, &len);
+	ret = security_secid_to_secctx(&secid, &secctx, &len, &sop);
 	if (ret)
 		return 0;
 
@@ -320,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
@@ -552,9 +553,10 @@ ctnetlink_secctx_size(const struct nf_conn *ct)
 #ifdef CONFIG_NF_CONNTRACK_SECMARK
 	int len, ret;
 	struct secids secid;
+	struct security_operations *sop;
 
 	lsm_init_secid(&secid, ct->secmark, 0);
-	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 831116a..8b19091 100644
@@ -126,15 +126,16 @@ 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;
 
 	lsm_init_secid(&secid, ct->secmark, 0);
-	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/netfilter/xt_SECMARK.c +2 -2
index 823ed01..9887626 100644
@@ -59,14 +59,14 @@ static int checkentry_lsm(struct xt_secmark_target_info *info)
 	info->secid = 0;
 
 	err = security_secctx_to_secid(info->secctx, strlen(info->secctx),
-				       &secid);
+				       &secid, lsm_secmark_ops());
 	if (err) {
 		if (err == -EINVAL)
 			pr_info("invalid security context \'%s\'\n", info->secctx);
 		return err;
 	}
 
-	info->secid = lsm_get_secid(&secid, 0);
+	info->secid = lsm_get_secid(&secid, lsm_secmark_order());
 	if (!info->secid) {
 		pr_info("unable to map security context \'%s\'\n", info->secctx);
 		return -ENOENT;
net/netlabel/netlabel_unlabeled.c +16 -12
index cd1e571..3e9064a 100644
@@ -397,6 +397,7 @@ int netlbl_unlhsh_add(struct net *net,
 	struct secids secids;
 	char *secctx = NULL;
 	u32 secctx_len;
+	struct security_operations *sop;
 
 	if (addr_len != sizeof(struct in_addr) &&
 	    addr_len != sizeof(struct in6_addr))
@@ -462,9 +463,9 @@ unlhsh_add_return:
 		lsm_init_secid(&secids, secid, 0);
 		if (security_secid_to_secctx(&secids,
 					     &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);
@@ -497,6 +498,7 @@ static int netlbl_unlhsh_remove_addr4(struct net *net,
 	struct net_device *dev;
 	char *secctx;
 	u32 secctx_len;
+	struct security_operations *sop;
 
 	spin_lock(&netlbl_unlhsh_lock);
 	list_entry = netlbl_af4list_remove(addr->s_addr, mask->s_addr,
@@ -518,9 +520,9 @@ static int netlbl_unlhsh_remove_addr4(struct net *net,
 			dev_put(dev);
 		if (entry != NULL &&
 		    security_secid_to_secctx(&entry->secid,
-					     &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);
@@ -559,6 +561,7 @@ static int netlbl_unlhsh_remove_addr6(struct net *net,
 	struct net_device *dev;
 	char *secctx;
 	u32 secctx_len;
+	struct security_operations *sop;
 
 	spin_lock(&netlbl_unlhsh_lock);
 	list_entry = netlbl_af6list_remove(addr, mask, &iface->addr6_list);
@@ -579,9 +582,9 @@ static int netlbl_unlhsh_remove_addr6(struct net *net,
 			dev_put(dev);
 		if (entry != NULL &&
 		    security_secid_to_secctx(&entry->secid,
-					     &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);
@@ -928,13 +931,13 @@ static int netlbl_unlabel_staticadd(struct sk_buff *skb,
 	ret_val = security_secctx_to_secid(
 		                  nla_data(info->attrs[NLBL_UNLABEL_A_SECCTX]),
 				  nla_len(info->attrs[NLBL_UNLABEL_A_SECCTX]),
-				  &secid);
+				  &secid, lsm_netlbl_ops());
 	if (ret_val != 0)
 		return ret_val;
 
 	return netlbl_unlhsh_add(&init_net,
 				 dev_name, addr, mask, addr_len,
-				 lsm_get_secid(&secid, 0),
+				 lsm_get_secid(&secid, lsm_netlbl_order()),
 				 &audit_info);
 }
 
@@ -978,13 +981,13 @@ static int netlbl_unlabel_staticadddef(struct sk_buff *skb,
 	ret_val = security_secctx_to_secid(
 		                  nla_data(info->attrs[NLBL_UNLABEL_A_SECCTX]),
 				  nla_len(info->attrs[NLBL_UNLABEL_A_SECCTX]),
-				  &secid);
+				  &secid, lsm_netlbl_ops());
 	if (ret_val != 0)
 		return ret_val;
 
 	return netlbl_unlhsh_add(&init_net,
 				 NULL, addr, mask, addr_len,
-				 lsm_get_secid(&secid, 0),
+				 lsm_get_secid(&secid, lsm_netlbl_order()),
 				 &audit_info);
 }
 
@@ -1099,6 +1102,7 @@ static int netlbl_unlabel_staticlist_gen(u32 cmd,
 	struct secids *secid;
 	char *secctx;
 	u32 secctx_len;
+	struct security_operations *sop;
 
 	data = genlmsg_put(cb_arg->skb, NETLINK_CB(cb_arg->nl_cb->skb).portid,
 			   cb_arg->seq, &netlbl_unlabel_gnl_family,
@@ -1157,14 +1161,14 @@ static int netlbl_unlabel_staticlist_gen(u32 cmd,
 		secid = &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 898153c..556f695 100644
@@ -101,6 +101,7 @@ struct audit_buffer *netlbl_audit_start_common(int type,
 	struct audit_buffer *audit_buf;
 	char *secctx;
 	u32 secctx_len;
+	struct security_operations *sop;
 
 	if (audit_enabled == 0)
 		return NULL;
@@ -116,9 +117,9 @@ struct audit_buffer *netlbl_audit_start_common(int type,
 	if (!lsm_zero_secid(&audit_info->secid) &&
 	    security_secid_to_secctx(&audit_info->secid,
 				     &secctx,
-				     &secctx_len) == 0) {
+				     &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;
net/xfrm/xfrm_user.c +8 -8
index 85f6bca..bacf995 100644
@@ -619,7 +619,7 @@ static int xfrm_add_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
 		err = xfrm_state_update(x);
 
 	security_task_getsecid(current, &sids);
-	sid = lsm_get_secid(&sids, 0);
+	sid = lsm_get_secid(&sids, lsm_xfrm_order());
 	xfrm_audit_state_add(x, err ? 0 : 1, loginuid, sessionid, sid);
 
 	if (err < 0) {
@@ -709,7 +709,7 @@ static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
 
 out:
 	security_task_getsecid(current, &sids);
-	sid = lsm_get_secid(&sids, 0);
+	sid = lsm_get_secid(&sids, lsm_xfrm_order());
 	xfrm_audit_state_delete(x, err ? 0 : 1, loginuid, sessionid, sid);
 	xfrm_state_put(x);
 	return err;
@@ -1431,7 +1431,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, &sids);
-	sid = lsm_get_secid(&sids, 0);
+	sid = lsm_get_secid(&sids, lsm_xfrm_order());
 	xfrm_audit_policy_add(xp, err ? 0 : 1, loginuid, sessionid, sid);
 
 	if (err) {
@@ -1674,7 +1674,7 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
 		struct secids sids;
 
 		security_task_getsecid(current, &sids);
-		sid = lsm_get_secid(&sids, 0);
+		sid = lsm_get_secid(&sids, lsm_xfrm_order());
 		xfrm_audit_policy_delete(xp, err ? 0 : 1, loginuid, sessionid,
 					 sid);
 
@@ -1708,7 +1708,7 @@ static int xfrm_flush_sa(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, &secid);
-	audit_info.secid = lsm_get_secid(&secid, 0);
+	audit_info.secid = lsm_get_secid(&secid, lsm_xfrm_order());
 	err = xfrm_state_flush(net, p->proto, &audit_info);
 	if (err) {
 		if (err == -ESRCH) /* empty table */
@@ -1903,7 +1903,7 @@ 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, &secid);
-	audit_info.secid = lsm_get_secid(&secid, 0);
+	audit_info.secid = lsm_get_secid(&secid, lsm_xfrm_order());
 	err = xfrm_policy_flush(net, type, &audit_info);
 	if (err) {
 		if (err == -ESRCH) /* empty table */
@@ -1976,7 +1976,7 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
 		struct secids sids;
 
 		security_task_getsecid(current, &sids);
-		sid = lsm_get_secid(&sids, 0);
+		sid = lsm_get_secid(&sids, lsm_xfrm_order());
 		xfrm_policy_delete(xp, p->dir);
 		xfrm_audit_policy_delete(xp, 1, loginuid, sessionid, sid);
 
@@ -2021,7 +2021,7 @@ static int xfrm_add_sa_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
 		struct secids sids;
 
 		security_task_getsecid(current, &sids);
-		sid = lsm_get_secid(&sids, 0);
+		sid = lsm_get_secid(&sids, lsm_xfrm_order());
 		__xfrm_state_delete(x);
 		xfrm_audit_state_delete(x, 1, loginuid, sessionid, sid);
 	}
security/apparmor/domain.c +4 -9
index 1614111..2286daa 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;
 
 	if (bprm->cred_prepared)
 		return 0;
@@ -539,15 +537,12 @@ 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;
+	if (bprm->unsafe & AA_SECURE_X_NEEDED)
+		return 1;
+	return 0;
 }
 
 /**
security/apparmor/lsm.c +5 -17
index 64557a0..c9c463b 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);
 }
 
@@ -139,15 +131,11 @@ static int apparmor_capget(struct task_struct *target, kernel_cap_t *effective,
 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;
+	struct aa_profile *profile = aa_cred_profile(cred);
+
+	if (!unconfined(profile))
+		return aa_capable(current, profile, cap, audit);
+	return 0;
 }
 
 /**
security/security.c +93 -11

249 lines not on this page · raw message

security/selinux/hooks.c +5 -68

147 lines not on this page · raw message

security/selinux/ss/services.c +2 -2
index 71b0939..f7de6bb 100644
@@ -3130,7 +3130,7 @@ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
 	if (secattr->flags & NETLBL_SECATTR_CACHE)
 		*sid = *(u32 *)secattr->cache->data;
 	else if (secattr->flags & NETLBL_SECATTR_SECID)
-		*sid = lsm_get_secid(&secattr->attr.secid, 0);
+		*sid = lsm_get_secid(&secattr->attr.secid, lsm_netlbl_order());
 	else if (secattr->flags & NETLBL_SECATTR_MLS_LVL) {
 		rc = -EIDRM;
 		ctx = sidtab_search(&sidtab, SECINITSID_NETMSG);
@@ -3205,7 +3205,7 @@ int security_netlbl_sid_to_secattr(u32 sid, struct netlbl_lsm_secattr *secattr)
 	if (secattr->domain == NULL)
 		goto out;
 
-	lsm_set_secid(&secattr->attr.secid, sid, 0);
+	lsm_set_secid(&secattr->attr.secid, sid, lsm_netlbl_order());
 	secattr->flags |= NETLBL_SECATTR_DOMAIN_CPY | NETLBL_SECATTR_SECID;
 	mls_export_netlbl_lvl(ctx, secattr);
 	rc = mls_export_netlbl_cat(ctx, secattr);
security/smack/smack_lsm.c +8 -37

94 lines not on this page · raw message

security/tomoyo/common.h +1 -1
index 9285c23..a2906d3 100644
@@ -1217,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_ops);
 }
 
 /**
security/tomoyo/tomoyo.c +0 -6
index 624d8f2..5b410b3 100644
@@ -72,12 +72,6 @@ static void tomoyo_cred_free(struct cred *cred)
  */
 static int tomoyo_bprm_set_creds(struct linux_binprm *bprm)
 {
-	int rc;
-
-	rc = cap_bprm_set_creds(bprm);
-	if (rc)
-		return rc;
-
 	/*
 	 * Do only if this function is called for the first time of an execve
 	 * operation.
security/yama/yama_lsm.c +3 -21
index 13c88fbc..cf57c7f 100644
@@ -154,13 +154,9 @@ void yama_task_free(struct task_struct *task)
 int yama_task_prctl(int option, unsigned long arg2, unsigned long arg3,
 			   unsigned long arg4, unsigned long arg5)
 {
-	int rc;
+	int rc = 0;
 	struct task_struct *myself = current;
 
-	rc = cap_task_prctl(option, arg2, arg3, arg4, arg5);
-	if (rc != -ENOSYS)
-		return rc;
-
 	switch (option) {
 	case PR_SET_PTRACER:
 		/* Since a thread can call prctl(), find the group leader
@@ -282,14 +278,7 @@ static int ptracer_exception_found(struct task_struct *tracer,
 int yama_ptrace_access_check(struct task_struct *child,
 				    unsigned int mode)
 {
-	int rc;
-
-	/* If standard caps disallows it, so does Yama.  We should
-	 * only tighten restrictions further.
-	 */
-	rc = cap_ptrace_access_check(child, mode);
-	if (rc)
-		return rc;
+	int rc = 0;
 
 	/* require ptrace target be a child of ptracer on attach */
 	if (mode == PTRACE_MODE_ATTACH) {
@@ -335,14 +324,7 @@ int yama_ptrace_access_check(struct task_struct *child,
  */
 int yama_ptrace_traceme(struct task_struct *parent)
 {
-	int rc;
-
-	/* If standard caps disallows it, so does Yama.  We should
-	 * only tighten restrictions further.
-	 */
-	rc = cap_ptrace_traceme(parent);
-	if (rc)
-		return rc;
+	int rc = 0;
 
 	/* Only disallow PTRACE_TRACEME on more aggressive settings. */
 	switch (ptrace_scope) {

--
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 v14 4/6 LSM: List based multiple LSM hooks

In reply to Casey Schaufler

Subject: [PATCH v14 4/6] LSM: List based multiple LSM hooks

Change the basic hook logic to call all available LSM versions of a particular hook. If the hook returns a value return the last error code encountered, or success. If the hook does not return a value just call them all. There are special cases that violate this scheme, and they are handled individually. Except in rare occasions the existing security modules get the same arguments as they did before.

Introduce vectored security blobs. Security blobs are handled by allocating a master blob that contains the blob pointers provided by the individual LSMs. These master blobs are managed in the lsm infrastructure.

Restructure the interpretation of the security= boot option and CONFIG_SECURITY_DEFAULT to allow an ordered list of security modules. Provide configuration options for the features that don't combine well, NetLabel, xfrm, secmark and SO_PEERSEC.

Remove special case Yama stacking.
Remove the register_security interface and do all of the work of registering an LSM in security_module_enable instead.
Put the security_module_disable interface (formerly reset_security_ops) under ifdef. Make it general on the off chance another LSM may want to use it in the future.

---
 fs/proc/base.c               |    8 +-
 include/linux/lsm.h          |  101 ++-
 include/linux/security.h     |  427 ++++++---
 include/net/af_unix.h        |    5 +-
 kernel/audit.c               |    2 +-
 kernel/auditsc.c             |    2 +-
 net/netfilter/xt_SECMARK.c   |    6 +-
 net/netlabel/netlabel_user.c |    2 +-
 net/unix/af_unix.c           |   14 +-
 security/Kconfig             |  194 ++++-
 security/Makefile            |    2 +-
 security/apparmor/domain.c   |    9 +-
 security/apparmor/lsm.c      |    9 -
 security/commoncap.c         |    6 -
 security/inode.c             |   12 +-
 security/security.c          | 1979 ++++++++++++++++++++++++++++++++++--------
 security/selinux/hooks.c     |   53 +-
 security/selinux/netlabel.c  |   29 +-
 security/smack/smack_lsm.c   |   48 +-
 security/tomoyo/tomoyo.c     |    9 +-
 security/yama/Kconfig        |    7 -
 security/yama/yama_lsm.c     |    9 -
 22 files changed, 2290 insertions(+), 643 deletions(-)
fs/proc/base.c +4 -4
index 3018f3d..941fe83 100644
@@ -131,11 +131,11 @@ struct pid_entry {
 #define REG(NAME, MODE, fops)				\
 	NOD(NAME, (S_IFREG|(MODE)), NULL, &fops, {})
 #define INF(NAME, MODE, read)				\
-	NOD(NAME, (S_IFREG|(MODE)), 			\
+	NOD(NAME, (S_IFREG|(MODE)),			\
 		NULL, &proc_info_file_operations,	\
 		{ .proc_read = read } )
 #define ONE(NAME, MODE, show)				\
-	NOD(NAME, (S_IFREG|(MODE)), 			\
+	NOD(NAME, (S_IFREG|(MODE)),			\
 		NULL, &proc_single_file_operations,	\
 		{ .proc_show = show } )
 
@@ -210,7 +210,7 @@ static int proc_pid_cmdline(struct task_struct *task, char * buffer)
 	if (!mm->arg_end)
 		goto out_mm;	/* Shh! No looking before we're done */
 
- 	len = mm->arg_end - mm->arg_start;
+	len = mm->arg_end - mm->arg_start;
  
 	if (len > PAGE_SIZE)
 		len = PAGE_SIZE;
@@ -2369,7 +2369,7 @@ static const struct pid_entry attr_dir_stuff[] = {
 	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
+#ifdef CONFIG_SECURITY_SMACK
 	REG("smack.current",      S_IRUGO|S_IWUGO, proc_pid_attr_operations),
 #endif
 #ifdef CONFIG_SECURITY_APPARMOR
include/linux/lsm.h +62 -39

226 lines not on this page · raw message

include/linux/security.h +324 -103

729 lines not on this page · raw message

include/net/af_unix.h +2 -3
index 32b53b7..16f1d2a 100644
@@ -33,12 +33,11 @@ struct unix_skb_parms {
 	kgid_t			gid;
 	struct scm_fp_list	*fp;		/* Passed files		*/
 #ifdef CONFIG_SECURITY_NETWORK
-	struct secids		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 UNIXCB(skb)	(*(struct unix_skb_parms *)&((skb)->cb))
 
 #define unix_state_lock(s)	spin_lock(&unix_sk(s)->lock)
 #define unix_state_unlock(s)	spin_unlock(&unix_sk(s)->lock)
kernel/audit.c +1 -1
index 00f3d36..8bbfbf2 100644
@@ -1529,7 +1529,7 @@ void audit_log_name(struct audit_context *context, struct audit_names *n,
 		char *ctx = NULL;
 		u32 len;
 		if (security_secid_to_secctx(&n->osid, &ctx, &len, &sop)) {
-			audit_log_format(ab, " osid=%u", n->osid.si_count);
+			audit_log_format(ab, " osid=%u", 0);
 			if (call_panic)
 				*call_panic = 2;
 		} else {
kernel/auditsc.c +1 -1
index a1620f5..2932ac5 100644
@@ -1223,7 +1223,7 @@ static void show_special(struct audit_context *context, int *call_panic)
 			u32 len;
 			struct security_operations *sop;
 			if (security_secid_to_secctx(osid, &ctx, &len, &sop)) {
-				audit_log_format(ab, " osc=%u", osid->si_count);
+				audit_log_format(ab, " osc=%u", 0);
 				*call_panic = 1;
 			} else {
 				audit_log_format(ab, " obj=%s", ctx);
net/netfilter/xt_SECMARK.c +4 -2
index 9887626..1264079 100644
@@ -62,13 +62,15 @@ static int checkentry_lsm(struct xt_secmark_target_info *info)
 				       &secid, lsm_secmark_ops());
 	if (err) {
 		if (err == -EINVAL)
-			pr_info("invalid security context \'%s\'\n", info->secctx);
+			pr_info("invalid security context \'%s\'\n",
+					info->secctx);
 		return err;
 	}
 
 	info->secid = lsm_get_secid(&secid, lsm_secmark_order());
 	if (!info->secid) {
-		pr_info("unable to map security context \'%s\'\n", info->secctx);
+		pr_info("unable to map security context \'%s\'\n",
+				info->secctx);
 		return -ENOENT;
 	}
 
net/netlabel/netlabel_user.c +1 -1
index 556f695..20e3e0d 100644
@@ -114,7 +114,7 @@ struct audit_buffer *netlbl_audit_start_common(int type,
 			 from_kuid(&init_user_ns, audit_info->loginuid),
 			 audit_info->sessionid);
 
-	if (!lsm_zero_secid(&audit_info->secid) &&
+	if (lsm_get_secid(&audit_info->secid, lsm_netlbl_order()) &&
 	    security_secid_to_secctx(&audit_info->secid,
 				     &secctx,
 				     &secctx_len, &sop) == 0) {
net/unix/af_unix.c +10 -4
index 964bbe3..56cd1d4 100644
@@ -137,16 +137,22 @@ static struct hlist_head *unix_sockets_unbound(void *addr)
 #ifdef CONFIG_SECURITY_NETWORK
 static void unix_get_secdata(struct scm_cookie *scm, struct sk_buff *skb)
 {
-	struct secids *skb_secid = UNIXSID(skb);
+	struct secids *sip = kzalloc(sizeof(*sip), GFP_KERNEL);
 
-	*skb_secid = scm->secid;
+	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)
 {
-	struct secids *skb_secid = UNIXSID(skb);
+	struct secids *sip = UNIXCB(skb).secid;
 
-	scm->secid = *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)
security/Kconfig +167 -27

228 lines not on this page · raw message

security/Makefile +1 -1
index c26c81e..0370e41 100644
@@ -14,8 +14,8 @@ obj-y					+= commoncap.o
 obj-$(CONFIG_MMU)			+= min_addr.o
 
 # Object file lists
-obj-$(CONFIG_SECURITY)			+= security.o capability.o
 obj-$(CONFIG_SECURITYFS)		+= inode.o
+obj-$(CONFIG_SECURITY)			+= security.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
security/apparmor/domain.c +6 -3
index 2286daa..cce4dbe 100644
@@ -537,12 +537,15 @@ 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 (bprm->unsafe & AA_SECURE_X_NEEDED)
-		return 1;
-	return 0;
+	if (!ret && (bprm->unsafe & AA_SECURE_X_NEEDED))
+		ret = 1;
+
+	return ret;
 }
 
 /**
security/apparmor/lsm.c +0 -9
index 709b2d7..78b271a 100644
@@ -902,12 +902,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)
@@ -919,9 +913,6 @@ static int __init apparmor_init(void)
 
 	return error;
 
-set_init_cxt_out:
-	aa_free_task_context(lsm_get_cred(current->real_cred, &apparmor_ops));
-
 register_security_out:
 	aa_free_root_ns();
 
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 +8 -4
index 27157b4..36c3487 100644
@@ -225,15 +225,19 @@ static ssize_t lsm_read(struct file *filp, char __user *buf, size_t count,
 	char *data;
 	int len;
 
-	data = kzalloc(SECURITY_NAME_MAX + 1, GFP_KERNEL);
+	data = kzalloc(LSM_NAMES_MAX + 1, GFP_KERNEL);
 	if (data == NULL)
 		return -ENOMEM;
 
-	strcat(data, sop->name);
-	strcat(data, "\n");
+	list_for_each_entry(sop, &lsm_hooks[lsm_name], list[lsm_name]) {
+		strcat(data, sop->name);
+		strcat(data, ",");
+	}
 	len = strlen(data);
+	if (len > 1)
+		data[len-1] = '\n';
 
-	len = simple_read_from_buffer(buf, count, ppos, data, len + 1);
+	len = simple_read_from_buffer(buf, count, ppos, data, len);
 	kfree(data);
 
 	return len;
security/security.c +1612 -367

1,627 lines not on this page · raw message

security/selinux/hooks.c +30 -23

53 lines not on this page · raw message

security/selinux/netlabel.c +25 -4
index 43504ea..162d95f 100644

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

security/smack/smack_lsm.c +27 -21

48 lines not on this page · raw message

security/tomoyo/tomoyo.c +5 -4
index 5b410b3..2525599 100644

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

security/yama/Kconfig +0 -7
index 20ef514..a99aa1d 100644

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

security/yama/yama_lsm.c +0 -9
index cf57c7f..78d7f45 100644

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

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

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

author maintainer
#18 lore raw

PATCH v14 5/6 LSM: SO_PEERSEC configuration options

In reply to Casey Schaufler

Subject: [PATCH v14 5/6] LSM: SO_PEERSEC configuration options

Refine the handling of SO_PEERSEC to enable legacy user space runtimes, Fedora in particular, when running with multiple LSMs that are capable of providing information using getsockopt(). This introduces an additional configuration option, and requires that the default be the legacy behavior.

---
 include/linux/lsm.h                                |   15 +++++
 include/linux/lsm_audit.h                          |    9 +--
 include/linux/security.h                           |    7 +-
 include/net/scm.h                                  |    2 +-
 include/net/xfrm.h                                 |    2 +-
 kernel/audit.c                                     |    8 +--
 kernel/auditsc.c                                   |    4 +-
 net/ipv4/ip_sockglue.c                             |    2 +-
 .../netfilter/nf_conntrack_l3proto_ipv4_compat.c   |    2 +-
 net/netfilter/nf_conntrack_netlink.c               |    4 +-
 net/netfilter/nf_conntrack_standalone.c            |    2 +-
 net/netlabel/netlabel_unlabeled.c                  |    8 +--
 net/netlabel/netlabel_user.c                       |    2 +-
 security/Kconfig                                   |   52 ++++++++++++---
 security/security.c                                |   70 ++++++++++----------
 security/selinux/hooks.c                           |    2 +-
 security/smack/smack_lsm.c                         |    2 +-
 17 files changed, 120 insertions(+), 73 deletions(-)
include/linux/lsm.h +15 -0
index 87736ba..9d39526 100644
@@ -263,6 +263,16 @@ static inline int lsm_secmark_order(void)
 }
 #endif /* CONFIG_NETWORK_SECMARK */
 
+static inline int lsm_peersec_order(void)
+{
+	return peersec_ops->order;
+}
+
+static inline struct security_operations *lsm_peersec_ops(void)
+{
+	return peersec_ops;
+}
+
 #else /* CONFIG_SECURITY */
 
 static inline int lsm_xfrm_order(void)
@@ -280,6 +290,11 @@ static inline struct security_operations *lsm_secmark_ops(void)
 	return NULL;
 }
 
+static inline struct security_operations *lsm_peersec_ops(void)
+{
+	return NULL;
+}
+
 #endif /* CONFIG_SECURITY */
 
 #endif /* ! _LINUX_LSM_H */
include/linux/lsm_audit.h +3 -6
index 1cc89e9..a575258 100644
@@ -69,18 +69,15 @@ struct common_audit_data {
 #endif
 		char *kmod_name;
 	} u;
-	/* this union contains LSM specific data */
-	union {
 #ifdef CONFIG_SECURITY_SMACK
-		struct smack_audit_data *smack_audit_data;
+	struct smack_audit_data *smack_audit_data;
 #endif
 #ifdef CONFIG_SECURITY_SELINUX
-		struct selinux_audit_data *selinux_audit_data;
+	struct selinux_audit_data *selinux_audit_data;
 #endif
 #ifdef CONFIG_SECURITY_APPARMOR
-		struct apparmor_audit_data *apparmor_audit_data;
+	struct apparmor_audit_data *apparmor_audit_data;
 #endif
-	}; /* per LSM data pointer union */
 };
 
 #define v4info fam.v4
include/linux/security.h +6 -1
index f63edec..3ec3489 100644
@@ -57,7 +57,11 @@ struct mm_struct;
 #define SECURITY_NAME_MAX	10
 
 /* Maximum number of LSMs that can be used at a time.  */
+#ifdef CONFIG_SECURITY
 #define LSM_SLOTS	CONFIG_SECURITY_LSM_MAX
+#else
+#define LSM_SLOTS	1
+#endif
 #define LSM_NAMES_MAX	((SECURITY_NAME_MAX + 1) * LSM_SLOTS)
 
 /* If capable should audit the security request */
@@ -152,7 +156,7 @@ struct request_sock;
 #define LSM_FEATURE_NETLABEL	0x02
 #define LSM_FEATURE_XFRM	0x04
 #define LSM_FEATURE_SECMARK	0x08
-#define LSM_FEATURE_SECIDS	0x10
+#define LSM_FEATURE_PEERSEC	0x10
 
 #ifdef CONFIG_MMU
 extern int mmap_min_addr_handler(struct ctl_table *table, int write,
@@ -1938,6 +1942,7 @@ extern void __init security_fixup_ops(struct security_operations *ops);
 #ifdef CONFIG_SECURITY_SELINUX_DISABLE
 extern void security_module_disable(struct security_operations *ops);
 #endif /* CONFIG_SECURITY_SELINUX_DISABLE */
+extern struct security_operations *peersec_ops;
 
 /* Security operations */
 int security_ptrace_access_check(struct task_struct *child, unsigned int mode);
include/net/scm.h +1 -1
index 5279fb1..f30fa64 100644
@@ -91,7 +91,7 @@ static inline void scm_passec(struct socket *sock, struct msghdr *msg, struct sc
 	char *secdata;
 	u32 seclen;
 	int err;
-	struct security_operations *sop;
+	struct security_operations *sop = peersec_ops;
 
 	if (test_bit(SOCK_PASSSEC, &sock->flags)) {
 		err = security_secid_to_secctx(&scm->secid, &secdata,
include/net/xfrm.h +1 -1
index b4d4231..7301859 100644
@@ -701,7 +701,7 @@ static inline void xfrm_audit_helper_usrinfo(kuid_t auid, u32 ses, u32 secid,
 	char *secctx;
 	u32 secctx_len;
 	struct secids secids;
-	struct security_operations *sop;
+	struct security_operations *sop = lsm_peersec_ops();
 
 	audit_log_format(audit_buf, " auid=%u ses=%u",
 			 from_kuid(&init_user_ns, auid), ses);
kernel/audit.c +4 -4
index 8bbfbf2..1b82d15 100644
@@ -640,7 +640,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 	struct audit_sig_info   *sig_data;
 	char			*ctx = NULL;
 	u32			len;
-	struct security_operations *sop;
+	struct security_operations *sop = NULL;
 
 	err = audit_netlink_ok(skb, msg_type);
 	if (err)
@@ -1481,7 +1481,7 @@ void audit_copy_inode(struct audit_names *name, const struct dentry *dentry,
 void audit_log_name(struct audit_context *context, struct audit_names *n,
 		    struct path *path, int record_num, int *call_panic)
 {
-	struct security_operations *sop;
+	struct security_operations *sop = NULL;
 	struct audit_buffer *ab;
 	ab = audit_log_start(context, GFP_KERNEL, AUDIT_PATH);
 	if (!ab)
@@ -1548,7 +1548,7 @@ int audit_log_task_context(struct audit_buffer *ab)
 	unsigned len;
 	int error;
 	struct secids sid;
-	struct security_operations *sop;
+	struct security_operations *sop = NULL;
 
 	security_task_getsecid(current, &sid);
 	if (lsm_zero_secid(&sid))
@@ -1731,7 +1731,7 @@ void audit_log_secctx(struct audit_buffer *ab, u32 secid)
 	u32 len;
 	char *secctx;
 	struct secids secids;
-	struct security_operations *sop;
+	struct security_operations *sop = lsm_secmark_ops();
 
 	lsm_init_secid(&secids, secid, lsm_secmark_order());
 	if (security_secid_to_secctx(&secids, &secctx, &len, &sop)) {
kernel/auditsc.c +2 -2
index 2932ac5..db0feec 100644
@@ -984,7 +984,7 @@ static int audit_log_pid_context(struct audit_context *context, pid_t pid,
 	char *ctx = NULL;
 	u32 len;
 	int rc = 0;
-	struct security_operations *sop;
+	struct security_operations *sop = NULL;
 
 	ab = audit_log_start(context, GFP_KERNEL, AUDIT_OBJ_PID);
 	if (!ab)
@@ -1221,7 +1221,7 @@ static void show_special(struct audit_context *context, int *call_panic)
 		if (!lsm_zero_secid(osid)) {
 			char *ctx = NULL;
 			u32 len;
-			struct security_operations *sop;
+			struct security_operations *sop = NULL;
 			if (security_secid_to_secctx(osid, &ctx, &len, &sop)) {
 				audit_log_format(ab, " osc=%u", 0);
 				*call_panic = 1;
net/ipv4/ip_sockglue.c +1 -1
index 3986a24..b1dcd34 100644
@@ -111,7 +111,7 @@ static void ip_cmsg_recv_security(struct msghdr *msg, struct sk_buff *skb)
 	u32 seclen;
 	struct secids secid;
 	int err;
-	struct security_operations *sop;
+	struct security_operations *sop = lsm_peersec_ops();
 
 	err = security_socket_getpeersec_dgram(NULL, skb, &secid);
 	if (err)
net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c +1 -1
index 8ce7e3d..881b4fa 100644
@@ -101,7 +101,7 @@ 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;
+	struct security_operations *sop = lsm_secmark_ops();
 
 	lsm_init_secid(&secid, ct->secmark, lsm_secmark_order());
 	ret = security_secid_to_secctx(&secid, &secctx, &len, &sop);
net/netfilter/nf_conntrack_netlink.c +2 -2
index b167205..34c809e 100644
@@ -303,7 +303,7 @@ ctnetlink_dump_secctx(struct sk_buff *skb, const struct nf_conn *ct)
 	int len, ret;
 	char *secctx;
 	struct secids secid;
-	struct security_operations *sop;
+	struct security_operations *sop = lsm_secmark_ops();
 
 	lsm_init_secid(&secid, ct->secmark, lsm_secmark_order());
 	ret = security_secid_to_secctx(&secid, &secctx, &len, &sop);
@@ -553,7 +553,7 @@ ctnetlink_secctx_size(const struct nf_conn *ct)
 #ifdef CONFIG_NF_CONNTRACK_SECMARK
 	int len, ret;
 	struct secids secid;
-	struct security_operations *sop;
+	struct security_operations *sop = lsm_secmark_ops();
 
 	lsm_init_secid(&secid, ct->secmark, lsm_secmark_order());
 	ret = security_secid_to_secctx(&secid, NULL, &len, &sop);
net/netfilter/nf_conntrack_standalone.c +1 -1
index e04dfb0..cbe5c1b 100644
@@ -126,7 +126,7 @@ 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;
+	struct security_operations *sop = lsm_secmark_ops();
 
 	lsm_init_secid(&secid, ct->secmark, lsm_secmark_order());
 	ret = security_secid_to_secctx(&secid, &secctx, &len, &sop);
net/netlabel/netlabel_unlabeled.c +4 -4
index be4e083..31211c9 100644
@@ -397,7 +397,7 @@ int netlbl_unlhsh_add(struct net *net,
 	struct secids secids;
 	char *secctx = NULL;
 	u32 secctx_len;
-	struct security_operations *sop;
+	struct security_operations *sop = lsm_netlbl_ops();
 
 	if (addr_len != sizeof(struct in_addr) &&
 	    addr_len != sizeof(struct in6_addr))
@@ -498,7 +498,7 @@ static int netlbl_unlhsh_remove_addr4(struct net *net,
 	struct net_device *dev;
 	char *secctx;
 	u32 secctx_len;
-	struct security_operations *sop;
+	struct security_operations *sop = lsm_netlbl_ops();
 
 	spin_lock(&netlbl_unlhsh_lock);
 	list_entry = netlbl_af4list_remove(addr->s_addr, mask->s_addr,
@@ -561,7 +561,7 @@ static int netlbl_unlhsh_remove_addr6(struct net *net,
 	struct net_device *dev;
 	char *secctx;
 	u32 secctx_len;
-	struct security_operations *sop;
+	struct security_operations *sop = lsm_netlbl_ops();
 
 	spin_lock(&netlbl_unlhsh_lock);
 	list_entry = netlbl_af6list_remove(addr, mask, &iface->addr6_list);
@@ -1102,7 +1102,7 @@ static int netlbl_unlabel_staticlist_gen(u32 cmd,
 	const struct secids *secid;
 	char *secctx;
 	u32 secctx_len;
-	struct security_operations *sop;
+	struct security_operations *sop = lsm_netlbl_ops();
 
 	data = genlmsg_put(cb_arg->skb, NETLINK_CB(cb_arg->nl_cb->skb).portid,
 			   cb_arg->seq, &netlbl_unlabel_gnl_family,
net/netlabel/netlabel_user.c +1 -1
index 20e3e0d..53b38ce 100644
@@ -101,7 +101,7 @@ struct audit_buffer *netlbl_audit_start_common(int type,
 	struct audit_buffer *audit_buf;
 	char *secctx;
 	u32 secctx_len;
-	struct security_operations *sop;
+	struct security_operations *sop = lsm_netlbl_ops();
 
 	if (audit_enabled == 0)
 		return NULL;
security/Kconfig +42 -10

59 lines not on this page · raw message

security/security.c +34 -36

143 lines not on this page · raw message

security/selinux/hooks.c +1 -1
index a5d73f1..aa3c024 100644
@@ -5526,7 +5526,7 @@ struct security_operations selinux_ops = {
 					LSM_FEATURE_NETLABEL |
 					LSM_FEATURE_XFRM |
 					LSM_FEATURE_SECMARK |
-					LSM_FEATURE_SECIDS,
+					LSM_FEATURE_PEERSEC,
 
 	.ptrace_access_check =		selinux_ptrace_access_check,
 	.ptrace_traceme =		selinux_ptrace_traceme,
security/smack/smack_lsm.c +1 -1
index 22c0041..d96e0b3 100644
@@ -3386,7 +3386,7 @@ struct security_operations smack_ops = {
 	.name =				"smack",
 	.features =			LSM_FEATURE_PRESENT |
 					LSM_FEATURE_NETLABEL |
-					LSM_FEATURE_SECIDS,
+					LSM_FEATURE_PEERSEC,
 
 	.ptrace_access_check =		smack_ptrace_access_check,
 	.ptrace_traceme =		smack_ptrace_traceme,

--
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
#22 lore raw

PATCH v14 6/6 LSM: Multiple LSM Documentation and cleanup

In reply to Casey Schaufler

Subject: [PATCH v14 6/6] LSM: Multiple LSM Documentation and cleanup

Add documentation and remove the obsolete capability LSM. Clean up some comments in security.h

---
 Documentation/security/LSM.txt |   56 +-
 include/linux/security.h       |   48 +-
 security/Makefile              |    1 -
 security/capability.c          | 1106 ----------------------------------------
 4 files changed, 77 insertions(+), 1134 deletions(-)
Documentation/security/LSM.txt +46 -10
index c335a76..69cf466 100644
@@ -7,20 +7,56 @@ various security checks to be hooked by new kernel extensions. The name
 loadable kernel modules. Instead, they are selectable at build-time via
 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.
+LSMs were built into a given kernel. The names of the active LSMs
+can be read from /sys/kernel/security/lsm.
+
+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 preceding hooks. Hooks that 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.
+
+Information from an LSM can come in one of two forms. The raw data
+used by the LSM is typically the preferred form. SELinux contexts and
+Smack labels are examples of raw LSM data. If the data from multiple
+LSMs is presented together it will be in the form:
+
+	lsmname='value'[lsmname='value']...
+
+Interfaces that accept LSM data as input accept this format as well,
+passing only the relevant portion of the data to each LSM.
+
+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. The name of this LSM can be
+read from /sys/kernel/security/present. There are also LSM identified
+interfaces which should be used in preference to the undifferentiated
+interfaces. The attribute interface "context" always provides the
+data from all LSMs that maintain it in the lsmname='value' format.
+
+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. CONFIG_PEERSEC_LSM allows
+for either a specific LSM to provide data with SO_PEERSEC or for
+all LSMs that provide data to do so.
+
+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
include/linux/security.h +31 -17

143 lines not on this page · raw message

security/Makefile +0 -1
index 0370e41..cf62a69 100644
@@ -9,7 +9,6 @@ subdir-$(CONFIG_SECURITY_TOMOYO)        += tomoyo
 subdir-$(CONFIG_SECURITY_APPARMOR)	+= apparmor
 subdir-$(CONFIG_SECURITY_YAMA)		+= yama
 
-# always enable default capabilities
 obj-y					+= commoncap.o
 obj-$(CONFIG_MMU)			+= min_addr.o
 
security/capability.c deleted +0 -1106

1,106 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
#5 lore raw

PATCH v14 3/6 LSM: Explicit individual LSM associations

In reply to Casey Schaufler

Subject: [PATCH v14 3/6] LSM: Explicit individual LSM associations

Expand the /proc/.../attr interface set to help include LSM specific entries as well as the traditional shared "current", "prev" and "exec" entries. Each LSM that uses one of the traditional interfaces gets it's own interface prefixed with the LSM name for the ones it cares about. Thus, we have "smack.current", "selinux.current" and "apparmor.current" in addition to "current".

Add two new interfaces under /sys/kernel/security. The lsm interface displays the comma seperated list of active LSMs. The present interface displays the name of the LSM providing the traditional /proc/.../attr interfaces. User space code should no longer have to grub around in odd places to determine what LSM is being used and thus what data is available to it.

Introduce feature specific security operation vectors for NetLabel, XFRM, secmark and presentation in the traditional /proc/.../attr interfaces. This allows proper handling of secids.

Add NetLabel interfaces that allow an LSM to request ownership of the NetLabel subsystem and to determine whether or not it has that ownership. These interfaces are intended to allow a future in which NetLabel can support multiple LSMs at the same time, although they do not do so now.

---
 drivers/usb/core/devio.c                           |    2 +-
 fs/proc/base.c                                     |   30 ++++-
 include/linux/lsm.h                                |   57 ++++++++--
 include/linux/security.h                           |   14 +++
 include/net/netlabel.h                             |   10 +-
 include/net/xfrm.h                                 |    2 +-
 kernel/audit.c                                     |    2 +-
 kernel/auditsc.c                                   |    2 +-
 kernel/signal.c                                    |    2 +-
 net/ipv4/cipso_ipv4.c                              |    2 +-
 .../netfilter/nf_conntrack_l3proto_ipv4_compat.c   |    2 +-
 net/netfilter/nf_conntrack_netlink.c               |    4 +-
 net/netfilter/nf_conntrack_standalone.c            |    2 +-
 net/netlabel/netlabel_kapi.c                       |   47 +++++++-
 net/netlabel/netlabel_unlabeled.c                  |   11 +-
 security/apparmor/lsm.c                            |    1 +
 security/inode.c                                   |   73 +++++++++++-
 security/security.c                                |  116 ++++++++++++++++++--
 security/selinux/hooks.c                           |   12 +-
 security/selinux/netlabel.c                        |    4 +-
 security/smack/smack_lsm.c                         |   91 ++++++++-------
 security/smack/smackfs.c                           |   12 +-
 22 files changed, 403 insertions(+), 95 deletions(-)
drivers/usb/core/devio.c +1 -1
index ab26dc4..f79c733 100644
@@ -497,7 +497,7 @@ static void async_completed(struct urb *urb)
 	const struct cred *cred = NULL;
 	int signr;
 
-	lsm_init_secid(&secid, 0, 0);
+	lsm_init_secid(&secid, 0, -1);
 	spin_lock(&ps->lock);
 	list_move_tail(&as->asynclist, &ps->async_completed);
 	as->status = urb->status;
fs/proc/base.c +24 -6
index c3834da..3018f3d 100644
@@ -2354,12 +2354,30 @@ 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,
include/linux/lsm.h +48 -9

102 lines not on this page · raw message

include/linux/security.h +14 -0
index 870e264..2041cda 100644
@@ -151,6 +151,12 @@ struct request_sock;
 #define LSM_UNSAFE_PTRACE_CAP	4
 #define LSM_UNSAFE_NO_NEW_PRIVS	8
 
+/* Unstackable features */
+#define LSM_FEATURE_PRESENT	0x1
+#define LSM_FEATURE_NETLABEL	0x2
+#define LSM_FEATURE_XFRM	0x4
+#define LSM_FEATURE_SECMARK	0x8
+
 #ifdef CONFIG_MMU
 extern int mmap_min_addr_handler(struct ctl_table *table, int write,
 				 void __user *buffer, size_t *lenp, loff_t *ppos);
@@ -202,6 +208,12 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
  * @name:
  *	A string that acts as a unique identifier for the LSM with max number
  *	of characters = SECURITY_NAME_MAX.
+ * @order:
+ *     The numeric order in which this LSM will be invoked.
+ *     Set during LSM initialization. Used to identify
+ *     which security blob to use when there is more than one LSM.
+ * @features:
+ *     Indicates which of the unshared facilities this LSM supports.
  *
  * Security hooks for program execution operations.
  *
@@ -1411,6 +1423,8 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
  */
 struct security_operations {
 	char name[SECURITY_NAME_MAX + 1];
+	int order;
+	int features;
 
 	int (*ptrace_access_check) (struct task_struct *child, unsigned int mode);
 	int (*ptrace_traceme) (struct task_struct *parent);
include/net/netlabel.h +8 -2
index e84fbb5..791cd89 100644
@@ -407,7 +407,9 @@ int netlbl_secattr_catmap_setrng(struct netlbl_lsm_secattr_catmap *catmap,
 /*
  * LSM protocol operations (NetLabel LSM/kernel API)
  */
-int netlbl_enabled(void);
+int netlbl_enabled(struct security_operations *lsm);
+int netlbl_lsm_owner(struct security_operations *lsm);
+int netlbl_lsm_register(struct security_operations *lsm);
 int netlbl_sock_setattr(struct sock *sk,
 			u16 family,
 			const struct netlbl_lsm_secattr *secattr);
@@ -521,7 +523,11 @@ static inline int netlbl_secattr_catmap_setrng(
 {
 	return 0;
 }
-static inline int netlbl_enabled(void)
+static inline int netlbl_lsm_register(struct security_operations *lsm)
+{
+	return 0;
+}
+static inline int netlbl_enabled(struct security_operations *lsm)
 {
 	return 0;
 }
include/net/xfrm.h +1 -1
index 49824d5..b4d4231 100644
@@ -705,7 +705,7 @@ static inline void xfrm_audit_helper_usrinfo(kuid_t auid, u32 ses, u32 secid,
 
 	audit_log_format(audit_buf, " auid=%u ses=%u",
 			 from_kuid(&init_user_ns, auid), ses);
-	lsm_init_secid(&secids, secid, 0);
+	lsm_init_secid(&secids, secid, lsm_xfrm_order());
 	if (secid != 0 &&
 	    security_secid_to_secctx(&secids, &secctx, &secctx_len,
 					&sop) == 0) {
kernel/audit.c +1 -1
index 3d55ca0..00f3d36 100644
@@ -1733,7 +1733,7 @@ void audit_log_secctx(struct audit_buffer *ab, u32 secid)
 	struct secids secids;
 	struct security_operations *sop;
 
-	lsm_init_secid(&secids, secid, 0);
+	lsm_init_secid(&secids, secid, lsm_secmark_order());
 	if (security_secid_to_secctx(&secids, &secctx, &len, &sop)) {
 		audit_panic("Cannot convert secid to context");
 	} else {
kernel/auditsc.c +1 -1
index 0bab5c5..a1620f5 100644
@@ -1542,7 +1542,7 @@ void __audit_syscall_exit(int success, long return_code)
 	context->aux = NULL;
 	context->aux_pids = NULL;
 	context->target_pid = 0;
-	lsm_init_secid(&context->target_sid, 0, 0);
+	lsm_init_secid(&context->target_sid, 0, -1);
 	context->sockaddr_len = 0;
 	context->type = 0;
 	context->fds[0] = -1;
kernel/signal.c +1 -1
index ce19c78..6d3da58 100644
@@ -818,7 +818,7 @@ static int check_kill_permission(int sig, struct siginfo *info,
 		}
 	}
 
-	lsm_init_secid(&secid, 0, 0);
+	lsm_init_secid(&secid, 0, -1);
 	return security_task_kill(t, info, sig, &secid);
 }
 
net/ipv4/cipso_ipv4.c +1 -1
index 00a2b2b..5ca352b 100644
@@ -1594,7 +1594,7 @@ static int cipso_v4_parsetag_loc(const struct cipso_v4_doi *doi_def,
 	u32 secid;
 
 	secid = *(u32 *)&tag[2];
-	lsm_init_secid(&secattr->attr.secid, secid, 0);
+	lsm_init_secid(&secattr->attr.secid, secid, lsm_netlbl_order());
 	secattr->flags |= NETLBL_SECATTR_SECID;
 
 	return 0;
net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c +1 -1
index 8f73bfb..8ce7e3d 100644
@@ -103,7 +103,7 @@ static int ct_show_secctx(struct seq_file *s, const struct nf_conn *ct)
 	struct secids secid;
 	struct security_operations *sop;
 
-	lsm_init_secid(&secid, ct->secmark, 0);
+	lsm_init_secid(&secid, ct->secmark, lsm_secmark_order());
 	ret = security_secid_to_secctx(&secid, &secctx, &len, &sop);
 	if (ret)
 		return 0;
net/netfilter/nf_conntrack_netlink.c +2 -2
index e240d22..b167205 100644
@@ -305,7 +305,7 @@ ctnetlink_dump_secctx(struct sk_buff *skb, const struct nf_conn *ct)
 	struct secids secid;
 	struct security_operations *sop;
 
-	lsm_init_secid(&secid, ct->secmark, 0);
+	lsm_init_secid(&secid, ct->secmark, lsm_secmark_order());
 	ret = security_secid_to_secctx(&secid, &secctx, &len, &sop);
 	if (ret)
 		return 0;
@@ -555,7 +555,7 @@ ctnetlink_secctx_size(const struct nf_conn *ct)
 	struct secids secid;
 	struct security_operations *sop;
 
-	lsm_init_secid(&secid, ct->secmark, 0);
+	lsm_init_secid(&secid, ct->secmark, lsm_secmark_order());
 	ret = security_secid_to_secctx(&secid, NULL, &len, &sop);
 	if (ret)
 		return 0;
net/netfilter/nf_conntrack_standalone.c +1 -1
index 8b19091..e04dfb0 100644
@@ -128,7 +128,7 @@ static int ct_show_secctx(struct seq_file *s, const struct nf_conn *ct)
 	struct secids secid;
 	struct security_operations *sop;
 
-	lsm_init_secid(&secid, ct->secmark, 0);
+	lsm_init_secid(&secid, ct->secmark, lsm_secmark_order());
 	ret = security_secid_to_secctx(&secid, &secctx, &len, &sop);
 	if (ret)
 		return 0;
net/netlabel/netlabel_kapi.c +46 -1

60 lines not on this page · raw message

net/netlabel/netlabel_unlabeled.c +6 -5
index 3e9064a..be4e083 100644
@@ -263,7 +263,7 @@ static int netlbl_unlhsh_add_addr4(struct netlbl_unlhsh_iface *iface,
 	entry->list.addr = addr->s_addr & mask->s_addr;
 	entry->list.mask = mask->s_addr;
 	entry->list.valid = 1;
-	lsm_init_secid(&entry->secid, secid, 0);
+	lsm_init_secid(&entry->secid, secid, lsm_netlbl_order());
 
 	spin_lock(&netlbl_unlhsh_lock);
 	ret_val = netlbl_af4list_add(&entry->list, &iface->addr4_list);
@@ -307,7 +307,7 @@ static int netlbl_unlhsh_add_addr6(struct netlbl_unlhsh_iface *iface,
 	entry->list.addr.s6_addr32[3] &= mask->s6_addr32[3];
 	entry->list.mask = *mask;
 	entry->list.valid = 1;
-	lsm_init_secid(&entry->secid, secid, 0);
+	lsm_init_secid(&entry->secid, secid, lsm_netlbl_order());
 
 	spin_lock(&netlbl_unlhsh_lock);
 	ret_val = netlbl_af6list_add(&entry->list, &iface->addr6_list);
@@ -460,7 +460,7 @@ int netlbl_unlhsh_add(struct net *net,
 unlhsh_add_return:
 	rcu_read_unlock();
 	if (audit_buf != NULL) {
-		lsm_init_secid(&secids, secid, 0);
+		lsm_init_secid(&secids, secid, lsm_netlbl_order());
 		if (security_secid_to_secctx(&secids,
 					     &secctx,
 					     &secctx_len, &sop) == 0) {
@@ -1099,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;
-	struct secids *secid;
+	const struct secids *secid;
 	char *secctx;
 	u32 secctx_len;
 	struct security_operations *sop;
@@ -1161,7 +1161,8 @@ static int netlbl_unlabel_staticlist_gen(u32 cmd,
 		secid = &addr6->secid;
 	}
 
-	ret_val = security_secid_to_secctx(secid, &secctx, &secctx_len, &sop);
+	ret_val = security_secid_to_secctx((struct secids *)secid, &secctx,
+						&secctx_len, &sop);
 	if (ret_val != 0)
 		goto list_cb_failure;
 	ret_val = nla_put(cb_arg->skb,
security/apparmor/lsm.c +1 -0
index c9c463b..709b2d7 100644
@@ -604,6 +604,7 @@ static int apparmor_task_setrlimit(struct task_struct *task,
 
 struct security_operations apparmor_ops = {
 	.name =				"apparmor",
+	.features =			LSM_FEATURE_PRESENT,
 
 	.ptrace_access_check =		apparmor_ptrace_access_check,
 	.ptrace_traceme =		apparmor_ptrace_traceme,
security/inode.c +71 -2

92 lines not on this page · raw message

security/security.c +107 -9

192 lines not on this page · raw message

security/selinux/hooks.c +8 -4
index 42b4bbb..71f14bf 100644
@@ -4159,7 +4159,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;
 
@@ -4542,7 +4542,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;
@@ -4607,7 +4607,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
@@ -4696,7 +4696,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;
 
@@ -5511,6 +5511,10 @@ static int selinux_key_getsecurity(struct key *key, char **_buffer)
 
 struct security_operations selinux_ops = {
 	.name =				"selinux",
+	.features =			LSM_FEATURE_PRESENT |
+					LSM_FEATURE_NETLABEL |
+					LSM_FEATURE_XFRM |
+					LSM_FEATURE_SECMARK,
 
 	.ptrace_access_check =		selinux_ptrace_access_check,
 	.ptrace_traceme =		selinux_ptrace_traceme,
security/selinux/netlabel.c +2 -2
index 63154c6..43504ea 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 +52 -39

147 lines not on this page · raw message

security/smack/smackfs.c +6 -6
index af7629c..650a0f3 100644
@@ -165,7 +165,8 @@ static void smk_netlabel_audit_set(struct netlbl_audit *nap)
 {
 	nap->loginuid = audit_get_loginuid(current);
 	nap->sessionid = audit_get_sessionid(current);
-	lsm_init_secid(&nap->secid, smack_to_secid(smk_of_current()), 0);
+	lsm_init_secid(&nap->secid, smack_to_secid(smk_of_current()),
+			lsm_netlbl_order());
 }
 
 /*
@@ -1236,12 +1237,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;
@@ -1250,12 +1251,11 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
 	} else {
 		/* we delete the unlabeled entry, only if the previous label
 		 * wasn't the special CIPSO option */
-		if (skp->smk_label != smack_cipso_option)
+		if (skp->smk_label != smack_cipso_option &&
+		    netlbl_lsm_owner(&smack_ops))
 			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;
 	}
 
@@ -1264,7 +1264,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 && netlbl_lsm_owner(&smack_ops))
 		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.

reviewer
#23 lore raw

Re: [PATCH v14 6/6] LSM: Multiple LSM Documentation and cleanup

In reply to Casey Schaufler
Quoted 29 lines · Casey Schaufler

Subject: [PATCH v14 6/6] LSM: Multiple LSM Documentation and cleanup

Add documentation and remove the obsolete capability LSM. Clean up some comments in security.h

---
 Documentation/security/LSM.txt |   56 +-
 include/linux/security.h       |   48 +-
 security/Makefile              |    1 -
 security/capability.c          | 1106 ----------------------------------------
 4 files changed, 77 insertions(+), 1134 deletions(-)
Documentation/security/LSM.txt +6 -1
index c335a76..69cf466 100644
@@ -7,20 +7,56 @@ various security checks to be hooked by new kernel extensions. The name
 loadable kernel modules. Instead, they are selectable at build-time via
 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.
+LSMs were built into a given kernel. The names of the active LSMs
+can be read from /sys/kernel/security/lsm.
+
+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

Documentation/security/LSM.txt various security checks to be hooked by new kernel extensions. The name · line 25

Quoted 10 lines
Documentation/security/LSM.txt +10 -0
+of preceding hooks. Hooks that 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.
+
+Information from an LSM can come in one of two forms. The raw data
+used by the LSM is typically the preferred form. SELinux contexts and
+Smack labels are examples of raw LSM data. If the data from multiple
+LSMs is presented together it will be in the form:
+
+	lsmname='value'[lsmname='value']...

no commas? just (made up example):

smack='label'selinux='notstrict'

Quoted 13 lines
Documentation/security/LSM.txt +13 -0
+
+Interfaces that accept LSM data as input accept this format as well,
+passing only the relevant portion of the data to each LSM.
+
+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. The name of this LSM can be
+read from /sys/kernel/security/present. There are also LSM identified
+interfaces which should be used in preference to the undifferentiated
+interfaces. The attribute interface "context" always provides the
+data from all LSMs that maintain it in the lsmname='value' format.
+
+The three networking mechanisms supporting LSM attributes are

Documentation/security/LSM.txt various security checks to be hooked by new kernel extensions. The name · line 48

Quoted 10 lines
Documentation/security/LSM.txt +10 -0
+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. CONFIG_PEERSEC_LSM allows
+for either a specific LSM to provide data with SO_PEERSEC or for
+all LSMs that provide data to do so.
+
+The Linux capabilities system is used in conjunction with any LSMs.
+LSM hooks are called after the capability checks in most cases,
                        ^^^^^

Documentation/security/LSM.txt various security checks to be hooked by new kernel extensions. The name · line 49

Quoted 1 line
Documentation/security/LSM.txt +1 -0
+but after in a small number of cases. All LSM hooks need to be aware

^^^^^

one of these 'after's should be 'before' ??

Quoted 22 lines
Documentation/security/LSM.txt +6 -9
+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
Signature · 1 line
~Randy
author maintainer
#24 lore raw

Re: [PATCH v14 6/6] LSM: Multiple LSM Documentation and cleanup

Quoted 42 lines · Randy Dunlap
Quoted 29 lines · Casey Schaufler

Subject: [PATCH v14 6/6] LSM: Multiple LSM Documentation and cleanup

Add documentation and remove the obsolete capability LSM. Clean up some comments in security.h

---
 Documentation/security/LSM.txt |   56 +-
 include/linux/security.h       |   48 +-
 security/Makefile              |    1 -
 security/capability.c          | 1106 ----------------------------------------
 4 files changed, 77 insertions(+), 1134 deletions(-)
Documentation/security/LSM.txt +6 -1
index c335a76..69cf466 100644
@@ -7,20 +7,56 @@ various security checks to be hooked by new kernel extensions. The name
 loadable kernel modules. Instead, they are selectable at build-time via
 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.
+LSMs were built into a given kernel. The names of the active LSMs
+can be read from /sys/kernel/security/lsm.
+
+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

Documentation/security/LSM.txt various security checks to be hooked by new kernel extensions. The name · line 25

Quoted 10 lines
Documentation/security/LSM.txt +10 -0
+of preceding hooks. Hooks that 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.
+
+Information from an LSM can come in one of two forms. The raw data
+used by the LSM is typically the preferred form. SELinux contexts and
+Smack labels are examples of raw LSM data. If the data from multiple
+LSMs is presented together it will be in the form:
+
+	lsmname='value'[lsmname='value']...

no commas? just (made up example):

Quoted 1 line

smack='label'selinux='notstrict'

That's correct. No commas. Because all values are quoted commas are unnecessary. If I want the SELinux portion of a context I can call

	sscanf(source, "selinux='%[^']'", result);

and comma separation helps not a bit.

Quoted 24 lines
Quoted 13 lines
Documentation/security/LSM.txt +13 -0
+
+Interfaces that accept LSM data as input accept this format as well,
+passing only the relevant portion of the data to each LSM.
+
+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. The name of this LSM can be
+read from /sys/kernel/security/present. There are also LSM identified
+interfaces which should be used in preference to the undifferentiated
+interfaces. The attribute interface "context" always provides the
+data from all LSMs that maintain it in the lsmname='value' format.
+
+The three networking mechanisms supporting LSM attributes are

Documentation/security/LSM.txt various security checks to be hooked by new kernel extensions. The name · line 48

Quoted 10 lines
Documentation/security/LSM.txt +10 -0
+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. CONFIG_PEERSEC_LSM allows
+for either a specific LSM to provide data with SO_PEERSEC or for
+all LSMs that provide data to do so.
+
+The Linux capabilities system is used in conjunction with any LSMs.
+LSM hooks are called after the capability checks in most cases,
                        ^^^^^
Quoted 4 lines

Documentation/security/LSM.txt various security checks to be hooked by new kernel extensions. The name · line 49

Quoted 1 line
Documentation/security/LSM.txt +1 -0
+but after in a small number of cases. All LSM hooks need to be aware

^^^^^

one of these 'after's should be 'before' ??

Yup. The latter should in fact be "before".

Quoted 23 lines
Quoted 23 lines
Documentation/security/LSM.txt +6 -9
+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
#6 lore raw

Re: [PATCH v14 3/6] LSM: Explicit individual LSM associations

In reply to Casey Schaufler
Quoted 104 lines · Casey Schaufler

Subject: [PATCH v14 3/6] LSM: Explicit individual LSM associations [...]
Introduce feature specific security operation vectors for NetLabel, XFRM, secmark and presentation in the traditional /proc/.../attr interfaces. This allows proper handling of secids.
[...]

include/linux/lsm.h +43 -9
@@ -164,9 +164,18 @@ static inline void lsm_init_secid(struct secids *secid, u32 lsecid, int order)
 {
        memset(secid, 0, sizeof(*secid));
 
-       if (lsecid != 0)
+       if (lsecid == 0)
+               return;
+       /*
+        * An order of -1 means set it for all LSMs.
+        */
+       if (order < 0) {
+               secid->si_lsm[0] = lsecid;
+               secid->si_count++;
+       } else {
+               secid->si_lsm[order] = lsecid;
                secid->si_count = 1;
-       secid->si_lsm[order] = lsecid;
+       }
 }
 
 static inline int lsm_zero_secid(struct secids *secid)
@@ -178,39 +187,64 @@ static inline int lsm_zero_secid(struct secids *secid)
 
 #ifdef CONFIG_SECURITY
 
+extern struct security_operations *present_ops;
 static inline struct security_operations *lsm_present_ops(void)
 {
-       return security_ops;
+       return present_ops;
 }
 
 static inline int lsm_present_order(void)
 {
-       return 0;
+       return present_ops->order;
 }
 
+#ifdef CONFIG_NETLABEL
+extern struct security_operations *netlbl_ops;
+
 static inline struct security_operations *lsm_netlbl_ops(void)
 {
-       return security_ops;
+       return netlbl_ops;
 }
 
 static inline int lsm_netlbl_order(void)
 {
-       return 0;
+       return netlbl_ops->order;
 }
+#endif /* CONFIG_NETLABEL */
+
+#ifdef CONFIG_SECURITY_NETWORK_XFRM
+extern struct security_operations *xfrm_ops;
 
 static inline struct security_operations *lsm_xfrm_ops(void)
 {
-       return security_ops;
+       return xfrm_ops;
 }
 
 static inline int lsm_xfrm_order(void)
 {
-       return 0;
+       return xfrm_ops->order;
 }
+#endif /* CONFIG_SECURITY_NETWORK_XFRM */
+
+#ifdef CONFIG_NETWORK_SECMARK
+extern struct security_operations *secmark_ops;
 
 static inline struct security_operations *lsm_secmark_ops(void)
 {
-       return security_ops;
+       return secmark_ops;
+}
+
+static inline int lsm_secmark_order(void)
+{
+       return secmark_ops->order;
+}
+#endif /* CONFIG_NETWORK_SECMARK */
+
+#else /* CONFIG_SECURITY */
+
+static inline int lsm_xfrm_order(void)
+{
+       return 0;
 }
 
 static inline int lsm_secmark_order(void)
@@ -218,6 +252,11 @@ static inline int lsm_secmark_order(void)
        return 0;

include/linux/lsm.h static inline int lsm_secmark_order(void) · line 262

Quoted 10 lines
include/linux/lsm.h +5 -0
 }
 
+static inline struct security_operations *lsm_secmark_ops(void)
+{
+       return NULL;
+}
+
 #endif /* CONFIG_SECURITY */
 
 #endif /* ! _LINUX_LSM_H */

Something went wrong here with the #ifdef/#else stuff here. I built without CONFIG_SECURITY_NETWORK_XFRM and it fails, missing lsm_xfrm_order().

If I added an #else to the CONFIG_SECURITY_NETWORK_XFRM check and made lsm_xfrm_order() return 0 there too, it built fine.

-Kees

Signature · 2 lines
Kees Cook
Chrome OS Security
#2 lore raw

Re: [PATCH v14 1/6] LSM: Security blob abstraction

In reply to Casey Schaufler
Quoted 10 lines · Casey Schaufler

Subject: [PATCH v14 1/6] LSM: Security blob abstraction

Create an abstracted interface for security blobs. Instead of directly accessing security blob pointers Use lsm_get and lsm_set functions that hide the actual mechanism used to maintain the security blobs. This affects most uses of inode->i_security, file->f_security, cred->security and similar fields in keys, sockets, superblocks, ipc and keys.

Quoted 7 lines

The use of a single 32 bit integer to refer to a security blob does not scale to the case where there may be more than one relevant security blob. Where it is possible to do so the use of secids (u32) has been replaced with a struct secids, which provides for multiple u32 values. There are components where u32 secids remain at the request of the maintainer of that component.

If I boot with "security=apparmor", lsm_set_blob ends up with a NULL "bp" and Oopses the kernel. Still happens with "security=yama,apparmor". As soon as I add smack anywhere in the list, everything is fine. It seems like the AppArmor init needs to be changed to:

security/apparmor/lsm.c +3 -3
index 78b271a..512f430 100644
@@ -875,9 +875,9 @@ static int __init set_init_cxt(void)
                return -ENOMEM;
 
        cxt->profile = aa_get_profile(root_ns->unconfined);
-       lsm_set_cred(cred, cxt, &apparmor_ops);
-
-       return 0;
+       printk(KERN_INFO "AA: cred:%p cxt:%p &apparmor_ops:%p\n",
+               cred, cxt, &apparmor_ops);
+       return lsm_set_init_cred(cred, cxt, &apparmor_ops);
 }
 
 static int __init apparmor_init(void)

Or maybe it still needs lsm_set_cred, but an earlier lsm_set_init_cred? It's not clear to me yet.

-Kees

Signature · 2 lines
Kees Cook
Chrome OS Security
author maintainer
#7 lore raw

Re: [PATCH v14 3/6] LSM: Explicit individual LSM associations

In reply to Kees Cook
Quoted 115 lines · Kees Cook
Quoted 113 lines · Casey Schaufler

Subject: [PATCH v14 3/6] LSM: Explicit individual LSM associations [...]
Introduce feature specific security operation vectors for NetLabel, XFRM, secmark and presentation in the traditional /proc/.../attr interfaces. This allows proper handling of secids.
[...]

include/linux/lsm.h +48 -9
@@ -164,9 +164,18 @@ static inline void lsm_init_secid(struct secids *secid, u32 lsecid, int order)
 {
        memset(secid, 0, sizeof(*secid));
 
-       if (lsecid != 0)
+       if (lsecid == 0)
+               return;
+       /*
+        * An order of -1 means set it for all LSMs.
+        */
+       if (order < 0) {
+               secid->si_lsm[0] = lsecid;
+               secid->si_count++;
+       } else {
+               secid->si_lsm[order] = lsecid;
                secid->si_count = 1;
-       secid->si_lsm[order] = lsecid;
+       }
 }
 
 static inline int lsm_zero_secid(struct secids *secid)
@@ -178,39 +187,64 @@ static inline int lsm_zero_secid(struct secids *secid)
 
 #ifdef CONFIG_SECURITY
 
+extern struct security_operations *present_ops;
 static inline struct security_operations *lsm_present_ops(void)
 {
-       return security_ops;
+       return present_ops;
 }
 
 static inline int lsm_present_order(void)
 {
-       return 0;
+       return present_ops->order;
 }
 
+#ifdef CONFIG_NETLABEL
+extern struct security_operations *netlbl_ops;
+
 static inline struct security_operations *lsm_netlbl_ops(void)
 {
-       return security_ops;
+       return netlbl_ops;
 }
 
 static inline int lsm_netlbl_order(void)
 {
-       return 0;
+       return netlbl_ops->order;
 }
+#endif /* CONFIG_NETLABEL */
+
+#ifdef CONFIG_SECURITY_NETWORK_XFRM
+extern struct security_operations *xfrm_ops;
 
 static inline struct security_operations *lsm_xfrm_ops(void)
 {
-       return security_ops;
+       return xfrm_ops;
 }
 
 static inline int lsm_xfrm_order(void)
 {
-       return 0;
+       return xfrm_ops->order;
 }
+#endif /* CONFIG_SECURITY_NETWORK_XFRM */
+
+#ifdef CONFIG_NETWORK_SECMARK
+extern struct security_operations *secmark_ops;
 
 static inline struct security_operations *lsm_secmark_ops(void)
 {
-       return security_ops;
+       return secmark_ops;
+}
+
+static inline int lsm_secmark_order(void)
+{
+       return secmark_ops->order;
+}
+#endif /* CONFIG_NETWORK_SECMARK */
+
+#else /* CONFIG_SECURITY */
+
+static inline int lsm_xfrm_order(void)
+{
+       return 0;
 }
 
 static inline int lsm_secmark_order(void)
@@ -218,6 +252,11 @@ static inline int lsm_secmark_order(void)
        return 0;
 }
 
+static inline struct security_operations *lsm_secmark_ops(void)
+{
+       return NULL;
+}
+
 #endif /* CONFIG_SECURITY */
 
Quoted 7 lines

include/linux/lsm.h static inline int lsm_secmark_order(void) · line 262

Quoted 1 line
include/linux/lsm.h +0 -0
 #endif /* ! _LINUX_LSM_H */

Something went wrong here with the #ifdef/#else stuff here. I built without CONFIG_SECURITY_NETWORK_XFRM and it fails, missing lsm_xfrm_order().

If I added an #else to the CONFIG_SECURITY_NETWORK_XFRM check and made lsm_xfrm_order() return 0 there too, it built fine.

Yup, I missed that configuration iteration at the end. I've incorporated a fix.

Quoted 3 lines

-Kees

author maintainer
#3 lore raw

Re: [PATCH v14 1/6] LSM: Security blob abstraction

In reply to Kees Cook
Quoted 30 lines · Kees Cook
Quoted 10 lines · Casey Schaufler

Subject: [PATCH v14 1/6] LSM: Security blob abstraction

Create an abstracted interface for security blobs. Instead of directly accessing security blob pointers Use lsm_get and lsm_set functions that hide the actual mechanism used to maintain the security blobs. This affects most uses of inode->i_security, file->f_security, cred->security and similar fields in keys, sockets, superblocks, ipc and keys.

Quoted 7 lines

The use of a single 32 bit integer to refer to a security blob does not scale to the case where there may be more than one relevant security blob. Where it is possible to do so the use of secids (u32) has been replaced with a struct secids, which provides for multiple u32 values. There are components where u32 secids remain at the request of the maintainer of that component.

If I boot with "security=apparmor", lsm_set_blob ends up with a NULL "bp" and Oopses the kernel. Still happens with "security=yama,apparmor". As soon as I add smack anywhere in the list, everything is fine. It seems like the AppArmor init needs to be changed to:

security/apparmor/lsm.c +0 -0
index 78b271a..512f430 100644

security/apparmor/lsm.c static int __init set_init_cxt(void) · line 880

Quoted 9 lines
security/apparmor/lsm.c +3 -3
@@ -875,9 +875,9 @@ static int __init set_init_cxt(void)
                return -ENOMEM;
 
        cxt->profile = aa_get_profile(root_ns->unconfined);
-       lsm_set_cred(cred, cxt, &apparmor_ops);
-
-       return 0;
+       printk(KERN_INFO "AA: cred:%p cxt:%p &apparmor_ops:%p\n",
+               cred, cxt, &apparmor_ops);
+       return lsm_set_init_cred(cred, cxt, &apparmor_ops);

I've incorporated this fix (without the printk) and she looks good.

Quoted 9 lines
security/apparmor/lsm.c +0 -0
 }
 
 static int __init apparmor_init(void)

Or maybe it still needs lsm_set_cred, but an earlier lsm_set_init_cred? It's not clear to me yet.

-Kees

maintainer
#19 lore raw

Re: [PATCH v14 5/6] LSM: SO_PEERSEC configuration options

In reply to Casey Schaufler
Quoted 9 lines · Casey Schaufler

Subject: [PATCH v14 5/6] LSM: SO_PEERSEC configuration options

Refine the handling of SO_PEERSEC to enable legacy user space runtimes, Fedora in particular, when running with multiple LSMs that are capable of providing information using getsockopt(). This introduces an additional configuration option, and requires that the default be the legacy behavior.

...

Quoted 18 lines
security/Kconfig +5 -6
@@ -157,17 +157,49 @@ config SECMARK_LSM
 	help
 	  The name of the LSM to use with the networking secmark
 
-config SECURITY_PLAIN_CONTEXT
-	bool "Backward compatable contexts without lsm='value' formatting"
-	depends on SECURITY_SELINUX || SECURITY_SMACK
-	default y
+choice
+	depends on SECURITY && (SECURITY_SELINUX || SECURITY_SMACK)
+	prompt "Peersec LSM"
+	default PEERSEC_SECURITY_FIRST
+
 	help
-	  Without this value set security context strings will
-	  include the name of the lsm with which they are associated

security/Kconfig config SECMARK_LSM · line 171

Quoted 10 lines
security/Kconfig +6 -4
-	  even if there is only one LSM that uses security contexts.
-	  This matches the way contexts were handled before it was
-	  possible to have multiple concurrent security modules.
-	  If you are unsure how to answer this question, answer Y.
+	  Select the security module that will send attribute
+	  information in IP header options.
+	  Most SELinux configurations do not take advantage
+	  of Netlabel, while all Smack configurations do. Unless
+	  there is a need to do otherwise chose Smack in preference
+	  to SELinux.

I'm not hugely in love with the help text; the first sentence seems to be all that is needed, the second seems unnecessary and not exactly fair to the LSMs.

Quoted 33 lines
security/Kconfig +30 -0
+	config PEERSEC_SECURITY_FIRST
+		bool "First LSM providing for SO_PEERSEC"
+		help
+		  Provide the first available LSM's information with SO_PEERSEC
+
+	config PEERSEC_SECURITY_ALL
+		bool "Use lsm='value'lsm='value' format"
+		help
+		  Provide all available security information in SO_PEERSEC
+
+	config PEERSEC_SECURITY_SELINUX
+		bool "SELinux" if SECURITY_SELINUX=y
+		help
+		  Provide SELinux context with SO_PEERSEC
+
+	config PEERSEC_SECURITY_SMACK
+		bool "Smack" if SECURITY_SMACK=y
+		help
+		  Provide Smack labels with SO_PEERSEC
+
+endchoice
+
+config PEERSEC_LSM
+	string
+	default "smack" if PEERSEC_SECURITY_SMACK
+	default "selinux" if PEERSEC_SECURITY_SELINUX
+	default "(all)" if PEERSEC_SECURITY_ALL
+	default "(first)"
+	help
+	  The name of the LSM to use with Netlabel
 
 config SECURITY_PATH
 	bool "Security hooks for pathname based access control"
Signature · 2 lines
paul moore
www.paul-moore.com
maintainer
#8 lore raw

Re: [PATCH v14 3/6] LSM: Explicit individual LSM associations

In reply to Casey Schaufler
Quoted 18 lines · Casey Schaufler

Subject: [PATCH v14 3/6] LSM: Explicit individual LSM associations

Expand the /proc/.../attr interface set to help include LSM specific entries as well as the traditional shared "current", "prev" and "exec" entries. Each LSM that uses one of the traditional interfaces gets it's own interface prefixed with the LSM name for the ones it cares about. Thus, we have "smack.current", "selinux.current" and "apparmor.current" in addition to "current".

Add two new interfaces under /sys/kernel/security. The lsm interface displays the comma seperated list of active LSMs. The present interface displays the name of the LSM providing the traditional /proc/.../attr interfaces. User space code should no longer have to grub around in odd places to determine what LSM is being used and thus what data is available to it.

Quoted 4 lines

Introduce feature specific security operation vectors for NetLabel, XFRM, secmark and presentation in the traditional /proc/.../attr interfaces. This allows proper handling of secids.

Maybe I missed something, can you elaborate on this, perhaps even provide an example for us simple minded folk?

Quoted 8 lines

Add NetLabel interfaces that allow an LSM to request ownership of the NetLabel subsystem and to determine whether or not it has that ownership. These interfaces are intended to allow a future in which NetLabel can support multiple LSMs at the same time, although they do not do so now.

...

Quoted 16 lines
include/net/netlabel.h +0 -0
@@ -407,7 +407,9 @@ int netlbl_secattr_catmap_setrng(struct

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

include/net/netlabel.h +3 -1
-int netlbl_enabled(void);
+int netlbl_enabled(struct security_operations *lsm);
+int netlbl_lsm_owner(struct security_operations *lsm);
+int netlbl_lsm_register(struct security_operations *lsm);
 int netlbl_sock_setattr(struct sock *sk,
 			u16 family,
 			const struct netlbl_lsm_secattr *secattr);
@@ -521,7 +523,11 @@ static inline int netlbl_secattr_catmap_setrng(
 {
 	return 0;

include/net/netlabel.h static inline int netlbl_secattr_catmap_setrng( · line 533

Quoted 10 lines
include/net/netlabel.h +5 -1
 }
-static inline int netlbl_enabled(void)
+static inline int netlbl_lsm_register(struct security_operations *lsm)
+{
+	return 0;
+}
+static inline int netlbl_enabled(struct security_operations *lsm)
 {
 	return 0;
 }

Is it worth including a static inline for netlabel_lsm_owner() for the sake of completeness? I haven't looked closely enough yet to know if it is strictly necessary or not.

net/ipv4/cipso_ipv4.c static int cipso_v4_parsetag_loc(const struct · line 1598

Quoted 11 lines
net/ipv4/cipso_ipv4.c +1 -1
index 00a2b2b..5ca352b 100644
@@ -1594,7 +1594,7 @@ static int cipso_v4_parsetag_loc(const struct
 cipso_v4_doi *doi_def, u32 secid;
 
 	secid = *(u32 *)&tag[2];
-	lsm_init_secid(&secattr->attr.secid, secid, 0);
+	lsm_init_secid(&secattr->attr.secid, secid, lsm_netlbl_order());
 	secattr->flags |= NETLBL_SECATTR_SECID;

I still need to wrap my head around all the changes, but I *think* this change may not be necessary since NetLabel isn't multi-LSM aware at the moment. If this change is necessary, then there are likely other changes that need to be made as well, the NetLabel LSM cache would be my main concern.

Quoted 56 lines
net/netlabel/netlabel_kapi.c +0 -0
index 7c94aed..bd5fee6 100644
@@ -608,6 +608,47 @@ int netlbl_secattr_catmap_setrng(struct

netlbl_lsm_secattr_catmap *catmap, */

/**
+ * netlbl_lsm_register - Reserve the NetLabel subsystem for an LSM
+ * @lsm: the security module making the request
+ *
+ * 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.
+ *
+ */

net/netlabel/netlabel_kapi.c +16 -0
+int netlbl_lsm_register(struct security_operations *lsm)
+{
+	if (lsm == NULL)
+		return -EINVAL;
+
+	if (lsm_netlbl_ops() == NULL)
+		netlbl_ops = lsm;
+	else if (lsm_netlbl_ops() != lsm)
+		return -EBUSY;
+
+	printk(KERN_INFO "NetLabel: Registered LSM \"%s\".\n", lsm->name);
+	return 0;
+}
+
+/**
+ * netlbl_lsm_owner - Report if the NetLabel subsystem is registered for an

LSM + * @lsm: the security module making the request
+ *
+ * Description:
+ * Report whether the LSM passed is the LSM registered for NetLabel
+ *
+ * Returns 1 if this is the registered NetLabel LSM, 0 otherwise
+ */

net/netlabel/netlabel_kapi.c +8 -0
+int netlbl_lsm_owner(struct security_operations *lsm)
+{
+	if (lsm_netlbl_ops() == lsm)
+		return 1;
+	return 0;
+}
+
+/**
  * netlbl_enabled - Determine if the NetLabel subsystem is enabled
  *
  * Description:
@@ -619,8 +660,12 @@ int netlbl_secattr_catmap_setrng(struct

netlbl_lsm_secattr_catmap *catmap, * be disabled.
*
*/

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

Quoted 7 lines
net/netlabel/netlabel_kapi.c +5 -1
-int netlbl_enabled(void)
+int netlbl_enabled(struct security_operations *lsm)
 {
+	if (lsm_netlbl_ops() == NULL)
+		return 0;
+	if (lsm_netlbl_ops() != lsm)
+		return 0;

How about some simplification in the above?

	struct security_operations *sops = lsm_netlbl_ops();

	if (sops == NULL || sops != lsm)
		return 0;
Quoted 3 lines
net/netlabel/netlabel_kapi.c +0 -0
 	/* 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 */

...

net/netlabel/netlabel_unlabeled.c static int netlbl_unlhsh_add_addr4(struct · line 266

Quoted 10 lines
(quoted diff) +0 -0

b/net/netlabel/netlabel_unlabeled.c index 3e9064a..be4e083 100644

net/netlabel/netlabel_unlabeled.c +1 -1
@@ -263,7 +263,7 @@ static int netlbl_unlhsh_add_addr4(struct
 netlbl_unlhsh_iface *iface, entry->list.addr = addr->s_addr & mask->s_addr;
 	entry->list.mask = mask->s_addr;
 	entry->list.valid = 1;
-	lsm_init_secid(&entry->secid, secid, 0);
+	lsm_init_secid(&entry->secid, secid, lsm_netlbl_order());

See my above comments in the CIPSO code.

net/netlabel/netlabel_unlabeled.c static int netlbl_unlhsh_add_addr6(struct netlbl_unlhsh_iface *iface, · line 310

Quoted 9 lines
net/netlabel/netlabel_unlabeled.c +0 -0
 	spin_lock(&netlbl_unlhsh_lock);
 	ret_val = netlbl_af4list_add(&entry->list, &iface->addr4_list);
@@ -307,7 +307,7 @@ static int netlbl_unlhsh_add_addr6(struct

netlbl_unlhsh_iface *iface, entry->list.addr.s6_addr32[3] &= mask->s6_addr32[3];

net/netlabel/netlabel_unlabeled.c +1 -1
 	entry->list.mask = *mask;
 	entry->list.valid = 1;
-	lsm_init_secid(&entry->secid, secid, 0);
+	lsm_init_secid(&entry->secid, secid, lsm_netlbl_order());

Same. You get the idea ...

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

Re: [PATCH v14 5/6] LSM: SO_PEERSEC configuration options

In reply to Paul Moore
Quoted 34 lines · Paul Moore
Quoted 9 lines · Casey Schaufler

Subject: [PATCH v14 5/6] LSM: SO_PEERSEC configuration options

Refine the handling of SO_PEERSEC to enable legacy user space runtimes, Fedora in particular, when running with multiple LSMs that are capable of providing information using getsockopt(). This introduces an additional configuration option, and requires that the default be the legacy behavior.

...

Quoted 22 lines
security/Kconfig +5 -10
@@ -157,17 +157,49 @@ config SECMARK_LSM
 	help
 	  The name of the LSM to use with the networking secmark
 
-config SECURITY_PLAIN_CONTEXT
-	bool "Backward compatable contexts without lsm='value' formatting"
-	depends on SECURITY_SELINUX || SECURITY_SMACK
-	default y
+choice
+	depends on SECURITY && (SECURITY_SELINUX || SECURITY_SMACK)
+	prompt "Peersec LSM"
+	default PEERSEC_SECURITY_FIRST
+
 	help
-	  Without this value set security context strings will
-	  include the name of the lsm with which they are associated
-	  even if there is only one LSM that uses security contexts.
-	  This matches the way contexts were handled before it was
-	  possible to have multiple concurrent security modules.
-	  If you are unsure how to answer this question, answer Y.
Quoted 8 lines

security/Kconfig config SECMARK_LSM · line 171

Quoted 6 lines
security/Kconfig +6 -0
+	  Select the security module that will send attribute
+	  information in IP header options.
+	  Most SELinux configurations do not take advantage
+	  of Netlabel, while all Smack configurations do. Unless
+	  there is a need to do otherwise chose Smack in preference
+	  to SELinux.

I'm not hugely in love with the help text; the first sentence seems to be all that is needed, the second seems unnecessary and not exactly fair to the LSMs.

I can take out the "friendly advice". What it really should say is more on the lines of:

If you have gotten to the point where you have to make this decision you should probably call it a work day, go home, have a nice drink and spend some time with a loved one. In the morning take a good hard look at your network configuration. You may end up with a different security policies being enforced with IPv4 and IPv6 communications.

Quoted 32 lines
Quoted 32 lines
security/Kconfig +30 -0
+	config PEERSEC_SECURITY_FIRST
+		bool "First LSM providing for SO_PEERSEC"
+		help
+		  Provide the first available LSM's information with SO_PEERSEC
+
+	config PEERSEC_SECURITY_ALL
+		bool "Use lsm='value'lsm='value' format"
+		help
+		  Provide all available security information in SO_PEERSEC
+
+	config PEERSEC_SECURITY_SELINUX
+		bool "SELinux" if SECURITY_SELINUX=y
+		help
+		  Provide SELinux context with SO_PEERSEC
+
+	config PEERSEC_SECURITY_SMACK
+		bool "Smack" if SECURITY_SMACK=y
+		help
+		  Provide Smack labels with SO_PEERSEC
+
+endchoice
+
+config PEERSEC_LSM
+	string
+	default "smack" if PEERSEC_SECURITY_SMACK
+	default "selinux" if PEERSEC_SECURITY_SELINUX
+	default "(all)" if PEERSEC_SECURITY_ALL
+	default "(first)"
+	help
+	  The name of the LSM to use with Netlabel
 
Quoted 2 lines

security/Kconfig config SECMARK_LSM · line 205

Quoted 2 lines
security/Kconfig +0 -0
 config SECURITY_PATH
 	bool "Security hooks for pathname based access control"

--
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
#9 lore raw

Re: [PATCH v14 3/6] LSM: Explicit individual LSM associations

In reply to Paul Moore
Quoted 19 lines · Paul Moore
Quoted 18 lines · Casey Schaufler

Subject: [PATCH v14 3/6] LSM: Explicit individual LSM associations

Expand the /proc/.../attr interface set to help include LSM specific entries as well as the traditional shared "current", "prev" and "exec" entries. Each LSM that uses one of the traditional interfaces gets it's own interface prefixed with the LSM name for the ones it cares about. Thus, we have "smack.current", "selinux.current" and "apparmor.current" in addition to "current".

Add two new interfaces under /sys/kernel/security. The lsm interface displays the comma seperated list of active LSMs. The present interface displays the name of the LSM providing the traditional /proc/.../attr interfaces. User space code should no longer have to grub around in odd places to determine what LSM is being used and thus what data is available to it.

Quoted 6 lines
Quoted 4 lines

Introduce feature specific security operation vectors for NetLabel, XFRM, secmark and presentation in the traditional /proc/.../attr interfaces. This allows proper handling of secids.

Maybe I missed something, can you elaborate on this, perhaps even provide an example for us simple minded folk?

There are a set of facilities that (currently, at least) can't be shared by multiple LSMs for one reason or another. XFRM and secmark have pretty well been declared as hopeless for expansion due to the sk_buff "32 bits is all you're ever going to get now shut up and go away" stance taken by certain networking maintainers. NetLabel might possibly be made to support multiple CIPSO tag types and while I don't think that it makes sense to put much effort into doing so, if there is a coin flip choice it should go in the direction of allowing it. The presentation facility is there to address the "current" interface in /proc, where backward compatibility is necessary.

Audit, on the other hand, uses secids but is capable of dealing with multiple LSMs, provided it can identify which LSM goes with which secid.

The most general case (audit) needs to keep a secid for each LSM. This is easy enough to do. The networking facilities (XFRM, secmark and NetLabel) always want to deal with exactly one, although as I mentioned previously, NetLabel could conceivably be multiple LSM aware someday. When audit and XFRM interact there needs to be a way to identify which of the secids audit is going to use is the one XFRM cares about.

There are two ways to do this. One is to identify the security_operations structure associated with the LSM or to identify the slot in the secids structure that holds that LSM's secid. The security_operations structure contains the information about the slot in the secids structure. The most general way to identify the information about these special cases is to identify the security_operations that go with them.

I hope that is helpful. I fear that I may not be getting the core concept across. The idea is to make it easier to deal with the special interfaces in the general cases.

Quoted 31 lines
Quoted 8 lines

Add NetLabel interfaces that allow an LSM to request ownership of the NetLabel subsystem and to determine whether or not it has that ownership. These interfaces are intended to allow a future in which NetLabel can support multiple LSMs at the same time, although they do not do so now.

...

Quoted 21 lines
include/net/netlabel.h +0 -0
@@ -407,7 +407,9 @@ int netlbl_secattr_catmap_setrng(struct

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

include/net/netlabel.h +6 -2
-int netlbl_enabled(void);
+int netlbl_enabled(struct security_operations *lsm);
+int netlbl_lsm_owner(struct security_operations *lsm);
+int netlbl_lsm_register(struct security_operations *lsm);
 int netlbl_sock_setattr(struct sock *sk,
 			u16 family,
 			const struct netlbl_lsm_secattr *secattr);
@@ -521,7 +523,11 @@ static inline int netlbl_secattr_catmap_setrng(
 {
 	return 0;
 }
-static inline int netlbl_enabled(void)
+static inline int netlbl_lsm_register(struct security_operations *lsm)
+{
+	return 0;
Quoted 8 lines

include/net/netlabel.h static inline int netlbl_secattr_catmap_setrng( · line 533

Quoted 5 lines
include/net/netlabel.h +2 -0
+}
+static inline int netlbl_enabled(struct security_operations *lsm)
 {
 	return 0;
 }

Is it worth including a static inline for netlabel_lsm_owner() for the sake of completeness? I haven't looked closely enough yet to know if it is strictly necessary or not.

I don't think it ever comes up, which would imply we don't need netlbl_enabled(), either.

Quoted 7 lines
Quoted 7 lines
net/ipv4/cipso_ipv4.c +0 -0
index 00a2b2b..5ca352b 100644
@@ -1594,7 +1594,7 @@ static int cipso_v4_parsetag_loc(const struct
 cipso_v4_doi *doi_def, u32 secid;
 
Quoted 8 lines

net/ipv4/cipso_ipv4.c static int cipso_v4_parsetag_loc(const struct cipso_v4_doi *doi_def, · line 1598

Quoted 4 lines
net/ipv4/cipso_ipv4.c +1 -1
 	secid = *(u32 *)&tag[2];
-	lsm_init_secid(&secattr->attr.secid, secid, 0);
+	lsm_init_secid(&secattr->attr.secid, secid, lsm_netlbl_order());
 	secattr->flags |= NETLBL_SECATTR_SECID;

I still need to wrap my head around all the changes, but I *think* this change may not be necessary since NetLabel isn't multi-LSM aware at the moment. If this change is necessary, then there are likely other changes that need to be made as well, the NetLabel LSM cache would be my main concern.

Using the NetLabel secid slot is necessary because when we get into the auditing code the secid needs to be in the right place to associate it with the right LSM.

Quoted 65 lines
Quoted 56 lines
net/netlabel/netlabel_kapi.c +0 -0
index 7c94aed..bd5fee6 100644
@@ -608,6 +608,47 @@ int netlbl_secattr_catmap_setrng(struct

netlbl_lsm_secattr_catmap *catmap, */

/**
+ * netlbl_lsm_register - Reserve the NetLabel subsystem for an LSM
+ * @lsm: the security module making the request
+ *
+ * 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.
+ *
+ */

net/netlabel/netlabel_kapi.c +16 -0
+int netlbl_lsm_register(struct security_operations *lsm)
+{
+	if (lsm == NULL)
+		return -EINVAL;
+
+	if (lsm_netlbl_ops() == NULL)
+		netlbl_ops = lsm;
+	else if (lsm_netlbl_ops() != lsm)
+		return -EBUSY;
+
+	printk(KERN_INFO "NetLabel: Registered LSM \"%s\".\n", lsm->name);
+	return 0;
+}
+
+/**
+ * netlbl_lsm_owner - Report if the NetLabel subsystem is registered for an

LSM + * @lsm: the security module making the request
+ *
+ * Description:
+ * Report whether the LSM passed is the LSM registered for NetLabel
+ *
+ * Returns 1 if this is the registered NetLabel LSM, 0 otherwise
+ */

net/netlabel/netlabel_kapi.c +8 -0
+int netlbl_lsm_owner(struct security_operations *lsm)
+{
+	if (lsm_netlbl_ops() == lsm)
+		return 1;
+	return 0;
+}
+
+/**
  * netlbl_enabled - Determine if the NetLabel subsystem is enabled
  *
  * Description:
@@ -619,8 +660,12 @@ int netlbl_secattr_catmap_setrng(struct

netlbl_lsm_secattr_catmap *catmap, * be disabled.
*
*/

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

Quoted 7 lines
net/netlabel/netlabel_kapi.c +5 -1
-int netlbl_enabled(void)
+int netlbl_enabled(struct security_operations *lsm)
 {
+	if (lsm_netlbl_ops() == NULL)
+		return 0;
+	if (lsm_netlbl_ops() != lsm)
+		return 0;

How about some simplification in the above?

Quoted 4 lines
	struct security_operations *sops = lsm_netlbl_ops();

	if (sops == NULL || sops != lsm)
		return 0;

Sure.

Quoted 17 lines
Quoted 3 lines
net/netlabel/netlabel_kapi.c +0 -0
 	/* 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 */

...

net/netlabel/netlabel_unlabeled.c static int netlbl_unlhsh_add_addr4(struct · line 266

Quoted 10 lines
(quoted diff) +0 -0

b/net/netlabel/netlabel_unlabeled.c index 3e9064a..be4e083 100644

net/netlabel/netlabel_unlabeled.c +1 -1
@@ -263,7 +263,7 @@ static int netlbl_unlhsh_add_addr4(struct
 netlbl_unlhsh_iface *iface, entry->list.addr = addr->s_addr & mask->s_addr;
 	entry->list.mask = mask->s_addr;
 	entry->list.valid = 1;
-	lsm_init_secid(&entry->secid, secid, 0);
+	lsm_init_secid(&entry->secid, secid, lsm_netlbl_order());

See my above comments in the CIPSO code.

Quoted 11 lines

net/netlabel/netlabel_unlabeled.c static int netlbl_unlhsh_add_addr6(struct netlbl_unlhsh_iface *iface, · line 310

Quoted 9 lines
net/netlabel/netlabel_unlabeled.c +0 -0
 	spin_lock(&netlbl_unlhsh_lock);
 	ret_val = netlbl_af4list_add(&entry->list, &iface->addr4_list);
@@ -307,7 +307,7 @@ static int netlbl_unlhsh_add_addr6(struct

netlbl_unlhsh_iface *iface, entry->list.addr.s6_addr32[3] &= mask->s6_addr32[3];

net/netlabel/netlabel_unlabeled.c +1 -1
 	entry->list.mask = *mask;
 	entry->list.valid = 1;
-	lsm_init_secid(&entry->secid, secid, 0);
+	lsm_init_secid(&entry->secid, secid, lsm_netlbl_order());

Same. You get the idea ...

--
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
#21 lore raw

Re: [PATCH v14 5/6] LSM: SO_PEERSEC configuration options

In reply to Casey Schaufler
Quoted 54 lines · Casey Schaufler
Quoted 33 lines · Paul Moore
Quoted 9 lines · Casey Schaufler

Subject: [PATCH v14 5/6] LSM: SO_PEERSEC configuration options

Refine the handling of SO_PEERSEC to enable legacy user space runtimes, Fedora in particular, when running with multiple LSMs that are capable of providing information using getsockopt(). This introduces an additional configuration option, and requires that the default be the legacy behavior.

...

Quoted 20 lines
security/Kconfig +5 -4
@@ -157,17 +157,49 @@ config SECMARK_LSM
 
 	help
 
 	  The name of the LSM to use with the networking secmark
 
-config SECURITY_PLAIN_CONTEXT
-	bool "Backward compatable contexts without lsm='value' formatting"
-	depends on SECURITY_SELINUX || SECURITY_SMACK
-	default y
+choice
+	depends on SECURITY && (SECURITY_SELINUX || SECURITY_SMACK)
+	prompt "Peersec LSM"
+	default PEERSEC_SECURITY_FIRST
+
 
 	help
 
Quoted 16 lines

security/Kconfig config SECMARK_LSM · line 171

Quoted 12 lines
security/Kconfig +6 -6
-	  Without this value set security context strings will
-	  include the name of the lsm with which they are associated
-	  even if there is only one LSM that uses security contexts.
-	  This matches the way contexts were handled before it was
-	  possible to have multiple concurrent security modules.
-	  If you are unsure how to answer this question, answer Y.
+	  Select the security module that will send attribute
+	  information in IP header options.
+	  Most SELinux configurations do not take advantage
+	  of Netlabel, while all Smack configurations do. Unless
+	  there is a need to do otherwise chose Smack in preference
+	  to SELinux.

I'm not hugely in love with the help text; the first sentence seems to be all that is needed, the second seems unnecessary and not exactly fair to the LSMs.

I can take out the "friendly advice". What it really should say is more on the lines of:

Quoted 6 lines

If you have gotten to the point where you have to make this decision you should probably call it a work day, go home, have a nice drink and spend some time with a loved one. In the morning take a good hard look at your network configuration. You may end up with a different security policies being enforced with IPv4 and IPv6 communications.

Perfect ;)

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

Re: [PATCH v14 3/6] LSM: Explicit individual LSM associations

In reply to Casey Schaufler
Quoted 25 lines · Casey Schaufler
Quoted 24 lines · Paul Moore
Quoted 22 lines · Casey Schaufler

Subject: [PATCH v14 3/6] LSM: Explicit individual LSM associations

Expand the /proc/.../attr interface set to help include LSM specific entries as well as the traditional shared "current", "prev" and "exec" entries. Each LSM that uses one of the traditional interfaces gets it's own interface prefixed with the LSM name for the ones it cares about. Thus, we have "smack.current", "selinux.current" and "apparmor.current" in addition to "current".

Add two new interfaces under /sys/kernel/security. The lsm interface displays the comma seperated list of active LSMs. The present interface displays the name of the LSM providing the traditional /proc/.../attr interfaces. User space code should no longer have to grub around in odd places to determine what LSM is being used and thus what data is available to it.

Introduce feature specific security operation vectors for NetLabel, XFRM, secmark and presentation in the traditional /proc/.../attr interfaces. This allows proper handling of secids.

Quoted 5 lines
Quoted 2 lines

Maybe I missed something, can you elaborate on this, perhaps even provide an example for us simple minded folk?

There are a set of facilities that (currently, at least) can't be shared by multiple LSMs ...

I should have been more specific.

Thanks for the explanation, but that I understand the problems of stacking LSM/secids, we've had that conversation a few times now. The explanation I was hoping for had to do with this sentence:

"Introduce feature specific security operation vectors for
NetLabel, XFRM, secmark and presentation in the traditional /proc/.../attr interfaces."

Can you explain this a bit more? When I looked at the patch - and maybe I'm missing something - I didn't see anything in /proc that dealt with NetLabel, XFRM, and/or Secmark.

Quoted 48 lines
Quoted 48 lines
Quoted 8 lines

Add NetLabel interfaces that allow an LSM to request ownership of the NetLabel subsystem and to determine whether or not it has that ownership. These interfaces are intended to allow a future in which NetLabel can support multiple LSMs at the same time, although they do not do so now.

...

Quoted 37 lines
include/net/netlabel.h +0 -0
@@ -407,7 +407,9 @@ int netlbl_secattr_catmap_setrng(struct

netlbl_lsm_secattr_catmap *catmap, /*

* LSM protocol operations (NetLabel LSM/kernel API) */

include/net/netlabel.h +8 -2
-int netlbl_enabled(void);
+int netlbl_enabled(struct security_operations *lsm);
+int netlbl_lsm_owner(struct security_operations *lsm);
+int netlbl_lsm_register(struct security_operations *lsm);
 
 int netlbl_sock_setattr(struct sock *sk,
 
 			u16 family,
 			const struct netlbl_lsm_secattr *secattr);
@@ -521,7 +523,11 @@ static inline int netlbl_secattr_catmap_setrng(
 
 {
 
 	return 0;
 
 }
 
-static inline int netlbl_enabled(void)
+static inline int netlbl_lsm_register(struct security_operations *lsm)
+{
+	return 0;
+}
+static inline int netlbl_enabled(struct security_operations *lsm)
 
 {
 
 	return 0;
Quoted 8 lines
Quoted 5 lines
Quoted 1 line

}

Is it worth including a static inline for netlabel_lsm_owner() for the sake of completeness? I haven't looked closely enough yet to know if it is strictly necessary or not.

I don't think it ever comes up, which would imply we don't need netlbl_enabled(), either.

Probably not, but I like the safety of having it defined. I guess that is why I would prefer having netlabel_lsm_owner() defined here as well.

Quoted 20 lines
Quoted 12 lines
Quoted 12 lines
net/ipv4/cipso_ipv4.c +1 -1
index 00a2b2b..5ca352b 100644
@@ -1594,7 +1594,7 @@ static int cipso_v4_parsetag_loc(const struct
 cipso_v4_doi *doi_def, u32 secid;
 
 	secid = *(u32 *)&tag[2];
 
-	lsm_init_secid(&secattr->attr.secid, secid, 0);
+	lsm_init_secid(&secattr->attr.secid, secid, lsm_netlbl_order());
 
Quoted 7 lines

net/ipv4/cipso_ipv4.c static int cipso_v4_parsetag_loc(const struct cipso_v4_doi *doi_def, · line 1598

Quoted 1 line
net/ipv4/cipso_ipv4.c +0 -0
 	secattr->flags |= NETLBL_SECATTR_SECID;

I still need to wrap my head around all the changes, but I *think* this change may not be necessary since NetLabel isn't multi-LSM aware at the moment. If this change is necessary, then there are likely other changes that need to be made as well, the NetLabel LSM cache would be my main concern.

Quoted 3 lines

Using the NetLabel secid slot is necessary because when we get into the auditing code the secid needs to be in the right place to associate it with the right LSM.

Fair enough.

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

Re: [PATCH v14 3/6] LSM: Explicit individual LSM associations

Quoted 35 lines · Paul Moore
Quoted 20 lines · Casey Schaufler
Quoted 19 lines · Paul Moore
Quoted 18 lines · Casey Schaufler

Subject: [PATCH v14 3/6] LSM: Explicit individual LSM associations

Expand the /proc/.../attr interface set to help include LSM specific entries as well as the traditional shared "current", "prev" and "exec" entries. Each LSM that uses one of the traditional interfaces gets it's own interface prefixed with the LSM name for the ones it cares about. Thus, we have "smack.current", "selinux.current" and "apparmor.current" in addition to "current".

Add two new interfaces under /sys/kernel/security. The lsm interface displays the comma seperated list of active LSMs. The present interface displays the name of the LSM providing the traditional /proc/.../attr interfaces. User space code should no longer have to grub around in odd places to determine what LSM is being used and thus what data is available to it.

Quoted 8 lines
Quoted 6 lines
Quoted 4 lines

Introduce feature specific security operation vectors for NetLabel, XFRM, secmark and presentation in the traditional /proc/.../attr interfaces. This allows proper handling of secids.

Maybe I missed something, can you elaborate on this, perhaps even provide an example for us simple minded folk?

There are a set of facilities that (currently, at least) can't be shared by multiple LSMs ...

I should have been more specific.

Thanks for the explanation, but that I understand the problems of stacking LSM/secids, we've had that conversation a few times now. The explanation I was hoping for had to do with this sentence:

Quoted 7 lines

"Introduce feature specific security operation vectors for
NetLabel, XFRM, secmark and presentation in the traditional /proc/.../attr interfaces."

Can you explain this a bit more? When I looked at the patch - and maybe I'm missing something - I didn't see anything in /proc that dealt with NetLabel, XFRM, and/or Secmark.

Just so. I have failed to communicate clearly.

"Each feature that requires support by a single, selected LSM
is identified by a global pointer to that LSM's security_operations structure."

NetLabel, XFRM and secmark are networking interfaces that can send the security information from a single LSM along with the packets of data.

/proc/.../attr/current and SO_PEERSEC are interfaces that could send information from multiple LSMs, but in most cases you have to choose one LSM to placate your user space tools.

In all of these cases it is necessary to identify the LSM to use. Even though the end use is quite different the mechanism to support the identification is the same.

Quoted 48 lines
Quoted 48 lines
Quoted 48 lines
Quoted 9 lines

Add NetLabel interfaces that allow an LSM to request ownership of the NetLabel subsystem and to determine whether or not it has that ownership. These interfaces are intended to allow a future in which NetLabel can support multiple LSMs at the same time, although they do not do so now.

...

Quoted 37 lines
include/net/netlabel.h +0 -0
@@ -407,7 +407,9 @@ int netlbl_secattr_catmap_setrng(struct

netlbl_lsm_secattr_catmap *catmap, /*

* LSM protocol operations (NetLabel LSM/kernel API) */

include/net/netlabel.h +8 -2
-int netlbl_enabled(void);
+int netlbl_enabled(struct security_operations *lsm);
+int netlbl_lsm_owner(struct security_operations *lsm);
+int netlbl_lsm_register(struct security_operations *lsm);
 
 int netlbl_sock_setattr(struct sock *sk,
 
 			u16 family,
 			const struct netlbl_lsm_secattr *secattr);
@@ -521,7 +523,11 @@ static inline int netlbl_secattr_catmap_setrng(
 
 {
 
 	return 0;
 
 }
 
-static inline int netlbl_enabled(void)
+static inline int netlbl_lsm_register(struct security_operations *lsm)
+{
+	return 0;
+}
+static inline int netlbl_enabled(struct security_operations *lsm)
 
 {
 
 	return 0;
Quoted 8 lines
Quoted 6 lines
Quoted 4 lines
Quoted 1 line

}

Is it worth including a static inline for netlabel_lsm_owner() for the sake of completeness? I haven't looked closely enough yet to know if it is strictly necessary or not.

I don't think it ever comes up, which would imply we don't need netlbl_enabled(), either.

Probably not, but I like the safety of having it defined. I guess that is why I would prefer having netlabel_lsm_owner() defined here as well.

Not a problem. I'll add it.

Quoted 18 lines
Quoted 18 lines
Quoted 18 lines

net/ipv4/cipso_ipv4.c static int cipso_v4_parsetag_loc(const struct · line 1600

Quoted 13 lines
net/ipv4/cipso_ipv4.c +1 -1
index 00a2b2b..5ca352b 100644
@@ -1594,7 +1594,7 @@ static int cipso_v4_parsetag_loc(const struct
 cipso_v4_doi *doi_def, u32 secid;
 
 	secid = *(u32 *)&tag[2];
 
-	lsm_init_secid(&secattr->attr.secid, secid, 0);
+	lsm_init_secid(&secattr->attr.secid, secid, lsm_netlbl_order());
 
 	secattr->flags |= NETLBL_SECATTR_SECID;

I still need to wrap my head around all the changes, but I *think* this change may not be necessary since NetLabel isn't multi-LSM aware at the moment. If this change is necessary, then there are likely other changes that need to be made as well, the NetLabel LSM cache would be my main concern.

Quoted 5 lines
Quoted 3 lines

Using the NetLabel secid slot is necessary because when we get into the auditing code the secid needs to be in the right place to associate it with the right LSM.

Fair enough.

--
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.

#25 lore raw
In reply to Casey Schaufler
Quoted 9 lines · Casey Schaufler

Subject: [PATCH v14 0/6] LSM: Multiple concurrent LSMs

Version 14 of this patchset is based on v3.10.
It required significant change from version 13 due to changes in the audit code. It came out cleaner, especially in the changes to NetLabel. This version supports all existing LSMs running together at the same time. The combinations tested most completely are:

Quoted 3 lines

apparmor,tomoyo,smack,yama - Ubuntu
apparmor,selinux,smack,yama - Fedora

Does this change the way one would develop a new LSM module? I presume it does not

Quoted 13 lines

I have been unable to figure out how to configure SELinux on Ubuntu and TOMOYO on Fedora. That's the only reason the list does not include all five LSMs at once. Combining LSMs that use networking is tricky, but can be done. There are changes coming from AppArmor that might make it even trickier, but that's a problem for the future.

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. All combinations of existing LSMs are supported.

Quoted 7 lines

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.

This is an important design trade-off. From my perspective I think you might want to revisit this, today it sounds like effective security == all hooks process and allow the operation. In this world a lack of proper policy/setting can make hooks fail. I've not yet looked at the code, but you might want to revisit this.

Quoted 41 lines

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". The XFRM and secmark facilities appear unlikely to ever allow for more than the existing 32 bit values. The NetLabel scheme might possibly be used to represent more than one labeling scheme (CIPSO does allow for multiple tags) although there is no plan to do so at this time. The SO_PEERSEC scheme is capable of providing information from multiple LSMs. Auditing can deal with multiple secids.

The NetLabel, XFRM and secmark facilities are restricted to use by one LSM at a time. The SO_PEERSEC facility can provide information from multiple LSMs, but existing user space tools don't understand that. The default behavior is to assign each of these facilities to the first registered LSM that uses them. They can be configured for use by any of the LSMs that provide hooks for them. SO_PEERSEC can be configured to provide information from all of the LSMs that provide hooks.

The /proc/*/attr interfaces are given to one LSM. This can be done by setting CONFIG_SECURITY_PRESENT. Additional interfaces have been created in /proc/*/attr so that each LSM has its own named interfaces. The name of the presenting LSM can be read from /sys/kernel/security/present. The list of LSMs being used can be read from /sys/kernel/security/lsm.

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:

Quoted 8 lines
    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.

Balbir Singh

author maintainer
#26 lore raw
Quoted 11 lines · Balbir Singh
Quoted 9 lines · Casey Schaufler

Subject: [PATCH v14 0/6] LSM: Multiple concurrent LSMs

Version 14 of this patchset is based on v3.10.
It required significant change from version 13 due to changes in the audit code. It came out cleaner, especially in the changes to NetLabel. This version supports all existing LSMs running together at the same time. The combinations tested most completely are:

Quoted 5 lines
Quoted 3 lines

apparmor,tomoyo,smack,yama - Ubuntu
apparmor,selinux,smack,yama - Fedora

Does this change the way one would develop a new LSM module? I presume it does not

The change that LSM developers need to be aware of is the security blob abstraction. Instead of using cred->security, inode->i_security and the like the code needs to use lsm_get_cred() and lsm_set_cred() and similar functions.

Quoted 20 lines
Quoted 13 lines

I have been unable to figure out how to configure SELinux on Ubuntu and TOMOYO on Fedora. That's the only reason the list does not include all five LSMs at once. Combining LSMs that use networking is tricky, but can be done. There are changes coming from AppArmor that might make it even trickier, but that's a problem for the future.

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. All combinations of existing LSMs are supported.

Quoted 7 lines

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

This is an important design trade-off. From my perspective I think you might want to revisit this, today it sounds like effective security == all hooks process and allow the operation. In this world a lack of proper policy/setting can make hooks fail. I've not yet looked at the code, but you might want to revisit this.

The result of an LSM hook will be failure if any of the LSMs indicates failure. The key here is that all of the LSM hooks get called even if it's known that the overall result is failure. This is done because many LSM hooks maintain internal state and shortcutting can disrupt that.

Quoted 48 lines
Quoted 48 lines

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". The XFRM and secmark facilities appear unlikely to ever allow for more than the existing 32 bit values. The NetLabel scheme might possibly be used to represent more than one labeling scheme (CIPSO does allow for multiple tags) although there is no plan to do so at this time. The SO_PEERSEC scheme is capable of providing information from multiple LSMs. Auditing can deal with multiple secids.

The NetLabel, XFRM and secmark facilities are restricted to use by one LSM at a time. The SO_PEERSEC facility can provide information from multiple LSMs, but existing user space tools don't understand that. The default behavior is to assign each of these facilities to the first registered LSM that uses them. They can be configured for use by any of the LSMs that provide hooks for them. SO_PEERSEC can be configured to provide information from all of the LSMs that provide hooks.

The /proc/*/attr interfaces are given to one LSM. This can be done by setting CONFIG_SECURITY_PRESENT. Additional interfaces have been created in /proc/*/attr so that each LSM has its own named interfaces. The name of the presenting LSM can be read from /sys/kernel/security/present. The list of LSMs being used can be read from /sys/kernel/security/lsm.

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.

Quoted 8 lines
Quoted 1 line

Balbir Singh
--
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
#12 lore raw

Re: [PATCH v14 3/6] LSM: Explicit individual LSM associations

In reply to Casey Schaufler
Quoted 57 lines · Casey Schaufler
Quoted 38 lines · Paul Moore
Quoted 25 lines · Casey Schaufler
Quoted 24 lines · Paul Moore
Quoted 22 lines · Casey Schaufler

Subject: [PATCH v14 3/6] LSM: Explicit individual LSM associations

Expand the /proc/.../attr interface set to help include LSM specific entries as well as the traditional shared "current", "prev" and "exec" entries. Each LSM that uses one of the traditional interfaces gets it's own interface prefixed with the LSM name for the ones it cares about. Thus, we have "smack.current", "selinux.current" and "apparmor.current" in addition to "current".

Add two new interfaces under /sys/kernel/security. The lsm interface displays the comma seperated list of active LSMs. The present interface displays the name of the LSM providing the traditional /proc/.../attr interfaces. User space code should no longer have to grub around in odd places to determine what LSM is being used and thus what data is available to it.

Introduce feature specific security operation vectors for NetLabel, XFRM, secmark and presentation in the traditional /proc/.../attr interfaces. This allows proper handling of secids.

Quoted 5 lines
Quoted 2 lines

Maybe I missed something, can you elaborate on this, perhaps even provide an example for us simple minded folk?

There are a set of facilities that (currently, at least) can't be shared by multiple LSMs ...

I should have been more specific.

Thanks for the explanation, but that I understand the problems of stacking LSM/secids, we've had that conversation a few times now. The explanation I was hoping for had to do with this sentence:

Quoted 7 lines

"Introduce feature specific security operation vectors for
NetLabel, XFRM, secmark and presentation in the traditional /proc/.../attr interfaces."

Can you explain this a bit more? When I looked at the patch - and maybe I'm missing something - I didn't see anything in /proc that dealt with NetLabel, XFRM, and/or Secmark.

Just so. I have failed to communicate clearly.

"Each feature that requires support by a single, selected LSM
is identified by a global pointer to that LSM's security_operations structure."

NetLabel, XFRM and secmark are networking interfaces that can send the security information from a single LSM along with the packets of data.

Quoted 7 lines

/proc/.../attr/current and SO_PEERSEC are interfaces that could send information from multiple LSMs, but in most cases you have to choose one LSM to placate your user space tools.

In all of these cases it is necessary to identify the LSM to use. Even though the end use is quite different the mechanism to support the identification is the same.

Okay, so if I understand everything correctly, there are no new entries in /proc relating specifically to NetLabel, XFRM, or Secmark; although there are new LSM specific entries for the general /proc entries that exist now. Yes?

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

Re: [PATCH v14 3/6] LSM: Explicit individual LSM associations

Quoted 58 lines · Paul Moore
Quoted 57 lines · Casey Schaufler
Quoted 35 lines · Paul Moore
Quoted 20 lines · Casey Schaufler
Quoted 19 lines · Paul Moore
Quoted 18 lines · Casey Schaufler

Subject: [PATCH v14 3/6] LSM: Explicit individual LSM associations

Expand the /proc/.../attr interface set to help include LSM specific entries as well as the traditional shared "current", "prev" and "exec" entries. Each LSM that uses one of the traditional interfaces gets it's own interface prefixed with the LSM name for the ones it cares about. Thus, we have "smack.current", "selinux.current" and "apparmor.current" in addition to "current".

Add two new interfaces under /sys/kernel/security. The lsm interface displays the comma seperated list of active LSMs. The present interface displays the name of the LSM providing the traditional /proc/.../attr interfaces. User space code should no longer have to grub around in odd places to determine what LSM is being used and thus what data is available to it.

Quoted 8 lines
Quoted 6 lines
Quoted 4 lines

Introduce feature specific security operation vectors for NetLabel, XFRM, secmark and presentation in the traditional /proc/.../attr interfaces. This allows proper handling of secids.

Maybe I missed something, can you elaborate on this, perhaps even provide an example for us simple minded folk?

There are a set of facilities that (currently, at least) can't be shared by multiple LSMs ...

I should have been more specific.

Thanks for the explanation, but that I understand the problems of stacking LSM/secids, we've had that conversation a few times now. The explanation I was hoping for had to do with this sentence:

Quoted 7 lines

"Introduce feature specific security operation vectors for
NetLabel, XFRM, secmark and presentation in the traditional /proc/.../attr interfaces."

Can you explain this a bit more? When I looked at the patch - and maybe I'm missing something - I didn't see anything in /proc that dealt with NetLabel, XFRM, and/or Secmark.

Just so. I have failed to communicate clearly.

"Each feature that requires support by a single, selected LSM
is identified by a global pointer to that LSM's security_operations structure."

NetLabel, XFRM and secmark are networking interfaces that can send the security information from a single LSM along with the packets of data.

/proc/.../attr/current and SO_PEERSEC are interfaces that could send information from multiple LSMs, but in most cases you have to choose one LSM to placate your user space tools.

Quoted 6 lines
Quoted 3 lines

In all of these cases it is necessary to identify the LSM to use. Even though the end use is quite different the mechanism to support the identification is the same.

Okay, so if I understand everything correctly, there are no new entries in /proc relating specifically to NetLabel, XFRM, or Secmark; although there are new LSM specific entries for the general /proc entries that exist now. Yes?

That's correct.

There is /sys/kernel/security/present, which tells you which LSM is going to show up in /proc/.../attr/current.

Should we have /sys/kernel/security/XFRM, /sys/kernel/security/secmark, /sys/kernel/security/NetLabel and /sys/kernel/security/SO_PEERCRED?

maintainer
#14 lore raw

Re: [PATCH v14 3/6] LSM: Explicit individual LSM associations

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

Okay, so if I understand everything correctly, there are no new entries in /proc relating specifically to NetLabel, XFRM, or Secmark; although there are new LSM specific entries for the general /proc entries that exist now. Yes?

Quoted 7 lines

That's correct.

There is /sys/kernel/security/present, which tells you which LSM is going to show up in /proc/.../attr/current.

Should we have /sys/kernel/security/XFRM, /sys/kernel/security/secmark, /sys/kernel/security/NetLabel and /sys/kernel/security/SO_PEERCRED?

Maybe.

While they might be helpful, I'm not 100% certain they are needed and further I'm not sure they are the "right" solution at this point. Any thoughts, both for and against, are welcome.

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

Re: [PATCH v14 3/6] LSM: Explicit individual LSM associations

Quoted 11 lines · Paul Moore
Quoted 10 lines · Casey Schaufler
Quoted 4 lines · Paul Moore

Okay, so if I understand everything correctly, there are no new entries in /proc relating specifically to NetLabel, XFRM, or Secmark; although there are new LSM specific entries for the general /proc entries that exist now. Yes?

That's correct.

There is /sys/kernel/security/present, which tells you which LSM is going to show up in /proc/.../attr/current.

Quoted 8 lines
Quoted 2 lines

Should we have /sys/kernel/security/XFRM, /sys/kernel/security/secmark, /sys/kernel/security/NetLabel and /sys/kernel/security/SO_PEERCRED?

Maybe.

While they might be helpful, I'm not 100% certain they are needed and further I'm not sure they are the "right" solution at this point. Any thoughts, both for and against, are welcome.

What might be a more correct solution? Assuming, of course, that there's a real problem.

--
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
#16 lore raw

Re: [PATCH v14 3/6] LSM: Explicit individual LSM associations

Quoted 18 lines · Casey Schaufler
Quoted 17 lines · Paul Moore
Quoted 15 lines · Casey Schaufler
Quoted 6 lines · Paul Moore

Okay, so if I understand everything correctly, there are no new entries in
/proc relating specifically to NetLabel, XFRM, or Secmark; although there
are new LSM specific entries for the general /proc entries that exist now. Yes?

That's correct.

There is /sys/kernel/security/present, which tells you which LSM is going to show up in /proc/.../attr/current.

Should we have /sys/kernel/security/XFRM, /sys/kernel/security/secmark, /sys/kernel/security/NetLabel and /sys/kernel/security/SO_PEERCRED?

Quoted 8 lines
Quoted 5 lines

Maybe.

While they might be helpful, I'm not 100% certain they are needed and further I'm not sure they are the "right" solution at this point. Any thoughts, both for and against, are welcome.

What might be a more correct solution? Assuming, of course, that there's a real problem.

Well, like I said, I'm not sure they are needed in the first place, in other words, I'm not sure there is a problem. As for the correct solution, I think we need to understand the problem, if there is one, before we can understand the solution.

How is that for an answer? :)

In short, I think we are best leaving them out until something comes along which requires that we add the /proc entries.

Signature · 2 lines
paul moore
www.paul-moore.com
#27 lore raw
In reply to Casey Schaufler
Quoted 15 lines · Casey Schaufler
Quoted 14 lines · Balbir Singh
Quoted 12 lines · Casey Schaufler

Subject: [PATCH v14 0/6] LSM: Multiple concurrent LSMs

Version 14 of this patchset is based on v3.10.
It required significant change from version 13 due to changes in the audit code. It came out cleaner, especially in the changes to NetLabel. This version supports all existing LSMs running together at the same time. The combinations tested most completely are:

apparmor,tomoyo,smack,yama - Ubuntu
apparmor,selinux,smack,yama - Fedora

Quoted 8 lines
Quoted 2 lines

Does this change the way one would develop a new LSM module? I presume it does not

The change that LSM developers need to be aware of is the security blob abstraction. Instead of using cred->security, inode->i_security and the like the code needs to use lsm_get_cred() and lsm_set_cred() and similar functions.

OK

Quoted 26 lines
Quoted 20 lines
Quoted 13 lines

I have been unable to figure out how to configure SELinux on Ubuntu and TOMOYO on Fedora. That's the only reason the list does not include all five LSMs at once. Combining LSMs that use networking is tricky, but can be done. There are changes coming from AppArmor that might make it even trickier, but that's a problem for the future.

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. All combinations of existing LSMs are supported.

Quoted 7 lines

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

This is an important design trade-off. From my perspective I think you might want to revisit this, today it sounds like effective security == all hooks process and allow the operation. In this world a lack of proper policy/setting can make hooks fail. I've not yet looked at the code, but you might want to revisit this.

Quoted 6 lines

The result of an LSM hook will be failure if any of the LSMs indicates failure. The key here is that all of the LSM hooks get called even if it's known that the overall result is failure. This is done because many LSM hooks maintain internal state and shortcutting can disrupt that.

Thanks for clarifying

Balbir

#28 lore raw
In reply to Casey Schaufler
Quoted 4 lines · Casey Schaufler

The /proc/*/attr interfaces are given to one LSM. This can be done by setting CONFIG_SECURITY_PRESENT. Additional interfaces have been created in /proc/*/attr so that each LSM has its own named interfaces. The name of the presenting LSM can be read from

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

-Kees

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

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

---
 fs/proc/base.c           |   95 ++++++++++++++++++++++++++++++++++++----------
 fs/proc/internal.h       |    1 +
 include/linux/security.h |   11 +++---
 security/security.c      |   67 ++++++++++++++------------------
 4 files changed, 112 insertions(+), 62 deletions(-)
fs/proc/base.c +76 -19
index 941fe83..4c80ffd 100644
@@ -138,6 +138,10 @@ struct pid_entry {
 	NOD(NAME, (S_IFREG|(MODE)),			\
 		NULL, &proc_single_file_operations,	\
 		{ .proc_show = show } )
+#define ATTR(LSM, NAME, MODE)				\
+	NOD(NAME, (S_IFREG|(MODE)),			\
+		NULL, &proc_pid_attr_operations,	\
+		{ .lsm = LSM } )
 
 /*
  * Count the number of hardlinks for the pid_entry table, excluding the .
@@ -2292,7 +2296,7 @@ static ssize_t proc_pid_attr_read(struct file * file, char __user * buf,
 	if (!task)
 		return -ESRCH;
 
-	length = security_getprocattr(task,
+	length = security_getprocattr(task, PROC_I(inode)->op.lsm,
 				      (char*)file->f_path.dentry->d_name.name,
 				      &p);
 	put_task_struct(task);
@@ -2335,7 +2339,7 @@ static ssize_t proc_pid_attr_write(struct file * file, const char __user * buf,
 	if (length < 0)
 		goto out_free;
 
-	length = security_setprocattr(task,
+	length = security_setprocattr(task, PROC_I(inode)->op.lsm,
 				      (char*)file->f_path.dentry->d_name.name,
 				      (void*)page, count);
 	mutex_unlock(&task->signal->cred_guard_mutex);
@@ -2353,29 +2357,82 @@ static const struct file_operations proc_pid_attr_operations = {
 	.llseek		= generic_file_llseek,
 };
 
+#define LSM_DIR_OPS(LSM) \
+static int proc_##LSM##_attr_dir_readdir(struct file * filp, \
+			     void * dirent, filldir_t filldir) \
+{ \
+	return proc_pident_readdir(filp, dirent, filldir, \
+				   LSM##_attr_dir_stuff, \
+				   ARRAY_SIZE(LSM##_attr_dir_stuff)); \
+} \
+\
+static const struct file_operations proc_##LSM##_attr_dir_ops = { \
+	.read		= generic_read_dir, \
+	.readdir	= proc_##LSM##_attr_dir_readdir, \
+	.llseek		= default_llseek, \
+}; \
+\
+static struct dentry *proc_##LSM##_attr_dir_lookup(struct inode *dir, \
+				struct dentry *dentry, unsigned int flags) \
+{ \
+	return proc_pident_lookup(dir, dentry, \
+				  LSM##_attr_dir_stuff, \
+				  ARRAY_SIZE(LSM##_attr_dir_stuff)); \
+} \
+\
+static const struct inode_operations proc_##LSM##_attr_dir_inode_ops = { \
+	.lookup		= proc_##LSM##_attr_dir_lookup, \
+	.getattr	= pid_getattr, \
+	.setattr	= proc_setattr, \
+};
+
+#ifdef CONFIG_SECURITY_SELINUX
+static const struct pid_entry selinux_attr_dir_stuff[] = {
+	ATTR("selinux", "current",	S_IRUGO|S_IWUGO),
+	ATTR("selinux", "prev",		S_IRUGO),
+	ATTR("selinux", "exec",		S_IRUGO|S_IWUGO),
+	ATTR("selinux", "fscreate",	S_IRUGO|S_IWUGO),
+	ATTR("selinux", "keycreate",	S_IRUGO|S_IWUGO),
+	ATTR("selinux", "sockcreate",	S_IRUGO|S_IWUGO),
+};
+LSM_DIR_OPS(selinux);
+#endif
+
+#ifdef CONFIG_SECURITY_SMACK
+static const struct pid_entry smack_attr_dir_stuff[] = {
+	ATTR("smack", "current",	S_IRUGO|S_IWUGO),
+};
+LSM_DIR_OPS(smack);
+#endif
+
+#ifdef CONFIG_SECURITY_APPARMOR
+static const struct pid_entry apparmor_attr_dir_stuff[] = {
+	ATTR("apparmor", "current",	S_IRUGO|S_IWUGO),
+	ATTR("apparmor", "prev",	S_IRUGO),
+	ATTR("apparmor", "exec",	S_IRUGO|S_IWUGO),
+};
+LSM_DIR_OPS(apparmor);
+#endif
+
 static const struct pid_entry attr_dir_stuff[] = {
-	REG("current",            S_IRUGO|S_IWUGO, proc_pid_attr_operations),
-	REG("prev",               S_IRUGO,	   proc_pid_attr_operations),
-	REG("exec",               S_IRUGO|S_IWUGO, proc_pid_attr_operations),
-	REG("fscreate",           S_IRUGO|S_IWUGO, proc_pid_attr_operations),
-	REG("keycreate",          S_IRUGO|S_IWUGO, proc_pid_attr_operations),
-	REG("sockcreate",         S_IRUGO|S_IWUGO, proc_pid_attr_operations),
-	REG("context",            S_IRUGO|S_IWUGO, proc_pid_attr_operations),
+	ATTR(NULL, "current",		S_IRUGO|S_IWUGO),
+	ATTR(NULL, "prev",		S_IRUGO),
+	ATTR(NULL, "exec",		S_IRUGO|S_IWUGO),
+	ATTR(NULL, "fscreate",		S_IRUGO|S_IWUGO),
+	ATTR(NULL, "keycreate",		S_IRUGO|S_IWUGO),
+	ATTR(NULL, "sockcreate",	S_IRUGO|S_IWUGO),
+	ATTR(NULL, "context",		S_IRUGO|S_IWUGO),
 #ifdef CONFIG_SECURITY_SELINUX
-	REG("selinux.current",    S_IRUGO|S_IWUGO, proc_pid_attr_operations),
-	REG("selinux.prev",       S_IRUGO,         proc_pid_attr_operations),
-	REG("selinux.exec",       S_IRUGO|S_IWUGO, proc_pid_attr_operations),
-	REG("selinux.fscreate",   S_IRUGO|S_IWUGO, proc_pid_attr_operations),
-	REG("selinux.keycreate",  S_IRUGO|S_IWUGO, proc_pid_attr_operations),
-	REG("selinux.sockcreate", S_IRUGO|S_IWUGO, proc_pid_attr_operations),
+	DIR("selinux",			S_IRUGO|S_IXUGO,
+	    proc_selinux_attr_dir_inode_ops, proc_selinux_attr_dir_ops),
 #endif
 #ifdef CONFIG_SECURITY_SMACK
-	REG("smack.current",      S_IRUGO|S_IWUGO, proc_pid_attr_operations),
+	DIR("smack",			S_IRUGO|S_IXUGO,
+	    proc_smack_attr_dir_inode_ops, proc_smack_attr_dir_ops),
 #endif
 #ifdef CONFIG_SECURITY_APPARMOR
-	REG("apparmor.current",   S_IRUGO|S_IWUGO, proc_pid_attr_operations),
-	REG("apparmor.prev",      S_IRUGO,         proc_pid_attr_operations),
-	REG("apparmor.exec",      S_IRUGO|S_IWUGO, proc_pid_attr_operations),
+	DIR("apparmor",			S_IRUGO|S_IXUGO,
+	    proc_apparmor_attr_dir_inode_ops, proc_apparmor_attr_dir_ops),
 #endif
 
 };
fs/proc/internal.h +1 -0
index d600fb0..795f649 100644
@@ -56,6 +56,7 @@ union proc_op {
 	int (*proc_show)(struct seq_file *m,
 		struct pid_namespace *ns, struct pid *pid,
 		struct task_struct *task);
+	const char *lsm;
 };
 
 struct proc_inode {
include/linux/security.h +6 -5
index d60e21c..fa89618 100644
@@ -2115,9 +2115,10 @@ int security_sem_semctl(struct sem_array *sma, int cmd);
 int security_sem_semop(struct sem_array *sma, struct sembuf *sops,
 			unsigned nsops, int alter);
 void security_d_instantiate(struct dentry *dentry, struct inode *inode);
-int security_getprocattr(struct task_struct *p, char *name, char **value);
-int security_setprocattr(struct task_struct *p, char *name, void *value,
-			 size_t size);
+int security_getprocattr(struct task_struct *p, const char *lsm, char *name,
+                         char **value);
+int security_setprocattr(struct task_struct *p, const char *lsm, char *name,
+                         void *value, size_t size);
 int security_netlink_send(struct sock *sk, struct sk_buff *skb);
 int security_secid_to_secctx(struct secids *secid, char **secdata, u32 *seclen,
 			     struct security_operations **secops);
@@ -2801,8 +2802,8 @@ static inline void security_d_instantiate(struct dentry *dentry,
 					  struct inode *inode)
 { }
 
-static inline int security_getprocattr(struct task_struct *p, char *name,
-				       char **value)
+static inline int security_getprocattr(struct task_struct *p, char *lsm,
+                       char *name, char **value)
 {
 	return -EINVAL;
 }
security/security.c +29 -38

103 lines not on this page · raw message

Signature · 6 lines
1.7.9.5


-- 
Kees Cook
Chrome OS Security
author maintainer
#29 lore raw
Quoted 11 lines · Kees Cook
Quoted 4 lines · Casey Schaufler

The /proc/*/attr interfaces are given to one LSM. This can be done by setting CONFIG_SECURITY_PRESENT. Additional interfaces have been created in /proc/*/attr so that each LSM has its own named interfaces. The name of the presenting LSM can be read from

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

I will confess that the reason I went with <lsm>.current instead of <lsm>/current was that the former was easier to implement.

Quoted 72 lines

-Kees

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

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

---
 fs/proc/base.c           |   95 ++++++++++++++++++++++++++++++++++++----------
 fs/proc/internal.h       |    1 +
 include/linux/security.h |   11 +++---
 security/security.c      |   67 ++++++++++++++------------------
 4 files changed, 112 insertions(+), 62 deletions(-)
fs/proc/base.c +24 -2
index 941fe83..4c80ffd 100644
@@ -138,6 +138,10 @@ struct pid_entry {
 	NOD(NAME, (S_IFREG|(MODE)),			\
 		NULL, &proc_single_file_operations,	\
 		{ .proc_show = show } )
+#define ATTR(LSM, NAME, MODE)				\
+	NOD(NAME, (S_IFREG|(MODE)),			\
+		NULL, &proc_pid_attr_operations,	\
+		{ .lsm = LSM } )
 
 /*
  * Count the number of hardlinks for the pid_entry table, excluding the .
@@ -2292,7 +2296,7 @@ static ssize_t proc_pid_attr_read(struct file * file, char __user * buf,
 	if (!task)
 		return -ESRCH;
 
-	length = security_getprocattr(task,
+	length = security_getprocattr(task, PROC_I(inode)->op.lsm,
 				      (char*)file->f_path.dentry->d_name.name,
 				      &p);
 	put_task_struct(task);
@@ -2335,7 +2339,7 @@ static ssize_t proc_pid_attr_write(struct file * file, const char __user * buf,
 	if (length < 0)
 		goto out_free;
 
-	length = security_setprocattr(task,
+	length = security_setprocattr(task, PROC_I(inode)->op.lsm,
 				      (char*)file->f_path.dentry->d_name.name,
 				      (void*)page, count);
 	mutex_unlock(&task->signal->cred_guard_mutex);
@@ -2353,29 +2357,82 @@ static const struct file_operations proc_pid_attr_operations = {
 	.llseek		= generic_file_llseek,
 };
 
+#define LSM_DIR_OPS(LSM) \
+static int proc_##LSM##_attr_dir_readdir(struct file * filp, \
+			     void * dirent, filldir_t filldir) \
+{ \
+	return proc_pident_readdir(filp, dirent, filldir, \
+				   LSM##_attr_dir_stuff, \
+				   ARRAY_SIZE(LSM##_attr_dir_stuff)); \
+} \
+\
+static const struct file_operations proc_##LSM##_attr_dir_ops = { \
+	.read		= generic_read_dir, \
+	.readdir	= proc_##LSM##_attr_dir_readdir, \
+	.llseek		= default_llseek, \
+}; \
+\
+static struct dentry *proc_##LSM##_attr_dir_lookup(struct inode *dir, \
+				struct dentry *dentry, unsigned int flags) \
+{ \

fs/proc/base.c static const struct file_operations proc_pid_attr_operations = { · line 2387

Quoted 10 lines
fs/proc/base.c +10 -0
+	return proc_pident_lookup(dir, dentry, \
+				  LSM##_attr_dir_stuff, \
+				  ARRAY_SIZE(LSM##_attr_dir_stuff)); \
+} \
+\
+static const struct inode_operations proc_##LSM##_attr_dir_inode_ops = { \
+	.lookup		= proc_##LSM##_attr_dir_lookup, \
+	.getattr	= pid_getattr, \
+	.setattr	= proc_setattr, \
+};

That's one hell of a macro you got there, Kees. I'm not saying it's bad, but it is quite the mouthful.

Quoted 19 lines
fs/proc/base.c +19 -0
+
+#ifdef CONFIG_SECURITY_SELINUX
+static const struct pid_entry selinux_attr_dir_stuff[] = {
+	ATTR("selinux", "current",	S_IRUGO|S_IWUGO),
+	ATTR("selinux", "prev",		S_IRUGO),
+	ATTR("selinux", "exec",		S_IRUGO|S_IWUGO),
+	ATTR("selinux", "fscreate",	S_IRUGO|S_IWUGO),
+	ATTR("selinux", "keycreate",	S_IRUGO|S_IWUGO),
+	ATTR("selinux", "sockcreate",	S_IRUGO|S_IWUGO),
+};
+LSM_DIR_OPS(selinux);
+#endif
+
+#ifdef CONFIG_SECURITY_SMACK
+static const struct pid_entry smack_attr_dir_stuff[] = {
+	ATTR("smack", "current",	S_IRUGO|S_IWUGO),
+};
+LSM_DIR_OPS(smack);
+#endif

fs/proc/base.c static const struct file_operations proc_pid_attr_operations = { · line 2416

Quoted 10 lines
fs/proc/base.c +10 -0
+
+#ifdef CONFIG_SECURITY_APPARMOR
+static const struct pid_entry apparmor_attr_dir_stuff[] = {
+	ATTR("apparmor", "current",	S_IRUGO|S_IWUGO),
+	ATTR("apparmor", "prev",	S_IRUGO),
+	ATTR("apparmor", "exec",	S_IRUGO|S_IWUGO),
+};
+LSM_DIR_OPS(apparmor);
+#endif
+

%s/dir_stuff/dir_entries/g
It doesn't have to be "entries", but "stuff" is horribly non-descriptive.

Quoted 162 lines
fs/proc/base.c +13 -17
 static const struct pid_entry attr_dir_stuff[] = {
-	REG("current",            S_IRUGO|S_IWUGO, proc_pid_attr_operations),
-	REG("prev",               S_IRUGO,	   proc_pid_attr_operations),
-	REG("exec",               S_IRUGO|S_IWUGO, proc_pid_attr_operations),
-	REG("fscreate",           S_IRUGO|S_IWUGO, proc_pid_attr_operations),
-	REG("keycreate",          S_IRUGO|S_IWUGO, proc_pid_attr_operations),
-	REG("sockcreate",         S_IRUGO|S_IWUGO, proc_pid_attr_operations),
-	REG("context",            S_IRUGO|S_IWUGO, proc_pid_attr_operations),
+	ATTR(NULL, "current",		S_IRUGO|S_IWUGO),
+	ATTR(NULL, "prev",		S_IRUGO),
+	ATTR(NULL, "exec",		S_IRUGO|S_IWUGO),
+	ATTR(NULL, "fscreate",		S_IRUGO|S_IWUGO),
+	ATTR(NULL, "keycreate",		S_IRUGO|S_IWUGO),
+	ATTR(NULL, "sockcreate",	S_IRUGO|S_IWUGO),
+	ATTR(NULL, "context",		S_IRUGO|S_IWUGO),
 #ifdef CONFIG_SECURITY_SELINUX
-	REG("selinux.current",    S_IRUGO|S_IWUGO, proc_pid_attr_operations),
-	REG("selinux.prev",       S_IRUGO,         proc_pid_attr_operations),
-	REG("selinux.exec",       S_IRUGO|S_IWUGO, proc_pid_attr_operations),
-	REG("selinux.fscreate",   S_IRUGO|S_IWUGO, proc_pid_attr_operations),
-	REG("selinux.keycreate",  S_IRUGO|S_IWUGO, proc_pid_attr_operations),
-	REG("selinux.sockcreate", S_IRUGO|S_IWUGO, proc_pid_attr_operations),
+	DIR("selinux",			S_IRUGO|S_IXUGO,
+	    proc_selinux_attr_dir_inode_ops, proc_selinux_attr_dir_ops),
 #endif
 #ifdef CONFIG_SECURITY_SMACK
-	REG("smack.current",      S_IRUGO|S_IWUGO, proc_pid_attr_operations),
+	DIR("smack",			S_IRUGO|S_IXUGO,
+	    proc_smack_attr_dir_inode_ops, proc_smack_attr_dir_ops),
 #endif
 #ifdef CONFIG_SECURITY_APPARMOR
-	REG("apparmor.current",   S_IRUGO|S_IWUGO, proc_pid_attr_operations),
-	REG("apparmor.prev",      S_IRUGO,         proc_pid_attr_operations),
-	REG("apparmor.exec",      S_IRUGO|S_IWUGO, proc_pid_attr_operations),
+	DIR("apparmor",			S_IRUGO|S_IXUGO,
+	    proc_apparmor_attr_dir_inode_ops, proc_apparmor_attr_dir_ops),
 #endif
 
 };
fs/proc/internal.h +1 -0
index d600fb0..795f649 100644
@@ -56,6 +56,7 @@ union proc_op {
 	int (*proc_show)(struct seq_file *m,
 		struct pid_namespace *ns, struct pid *pid,
 		struct task_struct *task);
+	const char *lsm;
 };
 
 struct proc_inode {
include/linux/security.h +6 -5
index d60e21c..fa89618 100644
@@ -2115,9 +2115,10 @@ int security_sem_semctl(struct sem_array *sma, int cmd);
 int security_sem_semop(struct sem_array *sma, struct sembuf *sops,
 			unsigned nsops, int alter);
 void security_d_instantiate(struct dentry *dentry, struct inode *inode);
-int security_getprocattr(struct task_struct *p, char *name, char **value);
-int security_setprocattr(struct task_struct *p, char *name, void *value,
-			 size_t size);
+int security_getprocattr(struct task_struct *p, const char *lsm, char *name,
+                         char **value);
+int security_setprocattr(struct task_struct *p, const char *lsm, char *name,
+                         void *value, size_t size);
 int security_netlink_send(struct sock *sk, struct sk_buff *skb);
 int security_secid_to_secctx(struct secids *secid, char **secdata, u32 *seclen,
 			     struct security_operations **secops);
@@ -2801,8 +2802,8 @@ static inline void security_d_instantiate(struct dentry *dentry,
 					  struct inode *inode)
 { }
 
-static inline int security_getprocattr(struct task_struct *p, char *name,
-				       char **value)
+static inline int security_getprocattr(struct task_struct *p, char *lsm,
+                       char *name, char **value)
 {
 	return -EINVAL;
 }
security/security.c +21 -27
index 119a377..499af30 100644
@@ -1897,74 +1897,65 @@ void security_d_instantiate(struct dentry *dentry, struct inode *inode)
 }
 EXPORT_SYMBOL(security_d_instantiate);
 
-int security_getprocattr(struct task_struct *p, char *name, char **value)
+int security_getprocattr(struct task_struct *p, const char *lsm, char *name,
+			 char **value)
 {
 	struct security_operations *sop = NULL;
 	struct secids secid;
-	char *lsm;
-	int lsmlen;
 	int ret;
 
 	/*
-	 * Names will either be in the legacy form containing
-	 * no periods (".") or they will be the LSM name followed
-	 * by the legacy suffix. "current" or "selinux.current"
-	 * The exception is "context", which gets all of the LSMs.
-	 *
-	 * Legacy names are handled by the presenting LSM.
-	 * Suffixed names are handled by the named LSM.
+	 * Target LSM will be either NULL or looked up by name. Names with
+	 * a NULL LSM (legacy) are handled by the presenting LSM. The
+	 * exception is "context", which gets all of the LSMs.
 	 */
 	if (strcmp(name, "context") == 0) {
+		char *lsmname;
+		int lsmlen;
+
 		security_task_getsecid(p, &secid);
-		ret = security_secid_to_secctx(&secid, &lsm, &lsmlen, &sop);
+		ret = security_secid_to_secctx(&secid, &lsmname, &lsmlen, &sop);
 		if (ret == 0) {
-			*value = kstrdup(lsm, GFP_KERNEL);
+			*value = kstrdup(lsmname, GFP_KERNEL);
 			if (*value == NULL)
 				ret = -ENOMEM;
 			else
 				ret = strlen(*value);
-			security_release_secctx(lsm, lsmlen, sop);
+			security_release_secctx(lsmname, lsmlen, sop);
 		}
 		return ret;
 	}
 
-	if (present_ops && !strchr(name, '.'))
-		return present_getprocattr(p, name, value);
-
-	for_each_hook(sop, getprocattr) {
-		lsm = sop->name;
-		lsmlen = strlen(lsm);
-		if (!strncmp(name, lsm, lsmlen) && name[lsmlen] == '.')
-			return sop->getprocattr(p, name + lsmlen + 1, value);
+	if (!lsm) {
+		if (present_ops)
+			return present_getprocattr(p, name, value);
+	} else {
+		for_each_hook(sop, getprocattr) {
+			if (!strcmp(lsm, sop->name))
+				return sop->getprocattr(p, name, value);
+		}
 	}
 	return -EINVAL;
 }
 
-int security_setprocattr(struct task_struct *p, char *name, void *value,
-			 size_t size)
+int security_setprocattr(struct task_struct *p, const char *lsm, char *name,
+			 void *value, size_t size)
 {
 	struct security_operations *sop;
-	char *lsm;
-	int lsmlen;
 
 	/*
-	 * Names will either be in the legacy form containing
-	 * no periods (".") or they will be the LSM name followed

security/security.c void security_d_instantiate(struct dentry *dentry, struct inode *inode) · line 1951

Quoted 10 lines
security/security.c +2 -5
-	 * by the legacy suffix.
-	 * "current" or "selinux.current"
-	 *
-	 * Legacy names are handled by the presenting LSM.
-	 * Suffixed names are handled by the named LSM.
+	 * Target LSM will be either NULL or looked up by name. Names with
+	 * a NULL LSM (legacy) are handled by the presenting LSM. The
 	 */
 	if (present_ops && !strchr(name, '.'))
 		return present_setprocattr(p, name, value, size);

We'll want to loose the preceding two lines, and add some later.

security/security.c void security_d_instantiate(struct dentry *dentry, struct inode *inode)

Quoted 13 lines
security/security.c +6 -7
-	for_each_hook(sop, setprocattr) {
-		lsm = sop->name;
-		lsmlen = strlen(lsm);
-		if (!strncmp(name, lsm, lsmlen) && name[lsmlen] == '.')
-			return sop->setprocattr(p, name + lsmlen + 1, value,
-						size);
+	if (lsm) {
+		for_each_hook(sop, setprocattr) {
+			if (!strcmp(lsm, sop->name))
+				return sop->setprocattr(p, name, value,
+							size);
+		}
-	}
  +	} else if (present_ops)
  +		return present_setprocattr(p, name, value, size);
Quoted 2 lines
security/security.c +0 -0
 	return -EINVAL;
 }
#30 lore raw
Quoted 13 lines · Casey Schaufler
Quoted 11 lines · Kees Cook
Quoted 4 lines · Casey Schaufler

The /proc/*/attr interfaces are given to one LSM. This can be done by setting CONFIG_SECURITY_PRESENT. Additional interfaces have been created in /proc/*/attr so that each LSM has its own named interfaces. The name of the presenting LSM can be read from

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

Quoted 2 lines

I will confess that the reason I went with <lsm>.current instead of <lsm>/current was that the former was easier to implement.

Yeah, that's totally fine. It wasn't very obvious (to me) how to implement this initially, so no problem at all. I'm glad there was something more than bug fixes I could contribute to this series. :)

Quoted 78 lines
Quoted 78 lines

-Kees

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

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

---
 fs/proc/base.c           |   95 ++++++++++++++++++++++++++++++++++++----------
 fs/proc/internal.h       |    1 +
 include/linux/security.h |   11 +++---
 security/security.c      |   67 ++++++++++++++------------------
 4 files changed, 112 insertions(+), 62 deletions(-)
fs/proc/base.c +29 -2
index 941fe83..4c80ffd 100644
@@ -138,6 +138,10 @@ struct pid_entry {
      NOD(NAME, (S_IFREG|(MODE)),                     \
              NULL, &proc_single_file_operations,     \
              { .proc_show = show } )
+#define ATTR(LSM, NAME, MODE)                                \
+     NOD(NAME, (S_IFREG|(MODE)),                     \
+             NULL, &proc_pid_attr_operations,        \
+             { .lsm = LSM } )
 
 /*
  * Count the number of hardlinks for the pid_entry table, excluding the .
@@ -2292,7 +2296,7 @@ static ssize_t proc_pid_attr_read(struct file * file, char __user * buf,
      if (!task)
              return -ESRCH;
 
-     length = security_getprocattr(task,
+     length = security_getprocattr(task, PROC_I(inode)->op.lsm,
                                    (char*)file->f_path.dentry->d_name.name,
                                    &p);
      put_task_struct(task);
@@ -2335,7 +2339,7 @@ static ssize_t proc_pid_attr_write(struct file * file, const char __user * buf,
      if (length < 0)
              goto out_free;
 
-     length = security_setprocattr(task,
+     length = security_setprocattr(task, PROC_I(inode)->op.lsm,
                                    (char*)file->f_path.dentry->d_name.name,
                                    (void*)page, count);
      mutex_unlock(&task->signal->cred_guard_mutex);
@@ -2353,29 +2357,82 @@ static const struct file_operations proc_pid_attr_operations = {
      .llseek         = generic_file_llseek,
 };
 
+#define LSM_DIR_OPS(LSM) \
+static int proc_##LSM##_attr_dir_readdir(struct file * filp, \
+                          void * dirent, filldir_t filldir) \
+{ \
+     return proc_pident_readdir(filp, dirent, filldir, \
+                                LSM##_attr_dir_stuff, \
+                                ARRAY_SIZE(LSM##_attr_dir_stuff)); \
+} \
+\
+static const struct file_operations proc_##LSM##_attr_dir_ops = { \
+     .read           = generic_read_dir, \
+     .readdir        = proc_##LSM##_attr_dir_readdir, \
+     .llseek         = default_llseek, \
+}; \
+\
+static struct dentry *proc_##LSM##_attr_dir_lookup(struct inode *dir, \
+                             struct dentry *dentry, unsigned int flags) \
+{ \
+     return proc_pident_lookup(dir, dentry, \
+                               LSM##_attr_dir_stuff, \
+                               ARRAY_SIZE(LSM##_attr_dir_stuff)); \
+} \
+\
Quoted 8 lines

fs/proc/base.c static const struct file_operations proc_pid_attr_operations = { · line 2387

Quoted 5 lines
fs/proc/base.c +5 -0
+static const struct inode_operations proc_##LSM##_attr_dir_inode_ops = { \
+     .lookup         = proc_##LSM##_attr_dir_lookup, \
+     .getattr        = pid_getattr, \
+     .setattr        = proc_setattr, \
+};

That's one hell of a macro you got there, Kees. I'm not saying it's bad, but it is quite the mouthful.

Heh, yeah. And this is the reduced version! I haven't found a good way to make this smaller yet.

Quoted 24 lines
Quoted 24 lines
fs/proc/base.c +24 -0
+
+#ifdef CONFIG_SECURITY_SELINUX
+static const struct pid_entry selinux_attr_dir_stuff[] = {
+     ATTR("selinux", "current",      S_IRUGO|S_IWUGO),
+     ATTR("selinux", "prev",         S_IRUGO),
+     ATTR("selinux", "exec",         S_IRUGO|S_IWUGO),
+     ATTR("selinux", "fscreate",     S_IRUGO|S_IWUGO),
+     ATTR("selinux", "keycreate",    S_IRUGO|S_IWUGO),
+     ATTR("selinux", "sockcreate",   S_IRUGO|S_IWUGO),
+};
+LSM_DIR_OPS(selinux);
+#endif
+
+#ifdef CONFIG_SECURITY_SMACK
+static const struct pid_entry smack_attr_dir_stuff[] = {
+     ATTR("smack", "current",        S_IRUGO|S_IWUGO),
+};
+LSM_DIR_OPS(smack);
+#endif
+
+#ifdef CONFIG_SECURITY_APPARMOR
+static const struct pid_entry apparmor_attr_dir_stuff[] = {
+     ATTR("apparmor", "current",     S_IRUGO|S_IWUGO),
+     ATTR("apparmor", "prev",        S_IRUGO),
Quoted 8 lines

fs/proc/base.c static const struct file_operations proc_pid_attr_operations = { · line 2416

Quoted 5 lines
fs/proc/base.c +5 -0
+     ATTR("apparmor", "exec",        S_IRUGO|S_IWUGO),
+};
+LSM_DIR_OPS(apparmor);
+#endif
+

%s/dir_stuff/dir_entries/g
It doesn't have to be "entries", but "stuff" is horribly non-descriptive.

Using "entries" is fine by me. I was modeling it entirely after the existing code (see "attr_dir_stuff" below).

Quoted 192 lines
Quoted 164 lines
fs/proc/base.c +13 -17
 static const struct pid_entry attr_dir_stuff[] = {
-     REG("current",            S_IRUGO|S_IWUGO, proc_pid_attr_operations),
-     REG("prev",               S_IRUGO,         proc_pid_attr_operations),
-     REG("exec",               S_IRUGO|S_IWUGO, proc_pid_attr_operations),
-     REG("fscreate",           S_IRUGO|S_IWUGO, proc_pid_attr_operations),
-     REG("keycreate",          S_IRUGO|S_IWUGO, proc_pid_attr_operations),
-     REG("sockcreate",         S_IRUGO|S_IWUGO, proc_pid_attr_operations),
-     REG("context",            S_IRUGO|S_IWUGO, proc_pid_attr_operations),
+     ATTR(NULL, "current",           S_IRUGO|S_IWUGO),
+     ATTR(NULL, "prev",              S_IRUGO),
+     ATTR(NULL, "exec",              S_IRUGO|S_IWUGO),
+     ATTR(NULL, "fscreate",          S_IRUGO|S_IWUGO),
+     ATTR(NULL, "keycreate",         S_IRUGO|S_IWUGO),
+     ATTR(NULL, "sockcreate",        S_IRUGO|S_IWUGO),
+     ATTR(NULL, "context",           S_IRUGO|S_IWUGO),
 #ifdef CONFIG_SECURITY_SELINUX
-     REG("selinux.current",    S_IRUGO|S_IWUGO, proc_pid_attr_operations),
-     REG("selinux.prev",       S_IRUGO,         proc_pid_attr_operations),
-     REG("selinux.exec",       S_IRUGO|S_IWUGO, proc_pid_attr_operations),
-     REG("selinux.fscreate",   S_IRUGO|S_IWUGO, proc_pid_attr_operations),
-     REG("selinux.keycreate",  S_IRUGO|S_IWUGO, proc_pid_attr_operations),
-     REG("selinux.sockcreate", S_IRUGO|S_IWUGO, proc_pid_attr_operations),
+     DIR("selinux",                  S_IRUGO|S_IXUGO,
+         proc_selinux_attr_dir_inode_ops, proc_selinux_attr_dir_ops),
 #endif
 #ifdef CONFIG_SECURITY_SMACK
-     REG("smack.current",      S_IRUGO|S_IWUGO, proc_pid_attr_operations),
+     DIR("smack",                    S_IRUGO|S_IXUGO,
+         proc_smack_attr_dir_inode_ops, proc_smack_attr_dir_ops),
 #endif
 #ifdef CONFIG_SECURITY_APPARMOR
-     REG("apparmor.current",   S_IRUGO|S_IWUGO, proc_pid_attr_operations),
-     REG("apparmor.prev",      S_IRUGO,         proc_pid_attr_operations),
-     REG("apparmor.exec",      S_IRUGO|S_IWUGO, proc_pid_attr_operations),
+     DIR("apparmor",                 S_IRUGO|S_IXUGO,
+         proc_apparmor_attr_dir_inode_ops, proc_apparmor_attr_dir_ops),
 #endif
 
 };
fs/proc/internal.h +1 -0
index d600fb0..795f649 100644
@@ -56,6 +56,7 @@ union proc_op {
      int (*proc_show)(struct seq_file *m,
              struct pid_namespace *ns, struct pid *pid,
              struct task_struct *task);
+     const char *lsm;
 };
 
 struct proc_inode {
include/linux/security.h +6 -5
index d60e21c..fa89618 100644
@@ -2115,9 +2115,10 @@ int security_sem_semctl(struct sem_array *sma, int cmd);
 int security_sem_semop(struct sem_array *sma, struct sembuf *sops,
                      unsigned nsops, int alter);
 void security_d_instantiate(struct dentry *dentry, struct inode *inode);
-int security_getprocattr(struct task_struct *p, char *name, char **value);
-int security_setprocattr(struct task_struct *p, char *name, void *value,
-                      size_t size);
+int security_getprocattr(struct task_struct *p, const char *lsm, char *name,
+                         char **value);
+int security_setprocattr(struct task_struct *p, const char *lsm, char *name,
+                         void *value, size_t size);
 int security_netlink_send(struct sock *sk, struct sk_buff *skb);
 int security_secid_to_secctx(struct secids *secid, char **secdata, u32 *seclen,
                           struct security_operations **secops);
@@ -2801,8 +2802,8 @@ static inline void security_d_instantiate(struct dentry *dentry,
                                        struct inode *inode)
 { }
 
-static inline int security_getprocattr(struct task_struct *p, char *name,
-                                    char **value)
+static inline int security_getprocattr(struct task_struct *p, char *lsm,
+                       char *name, char **value)
 {
      return -EINVAL;
 }
security/security.c +21 -27
index 119a377..499af30 100644
@@ -1897,74 +1897,65 @@ void security_d_instantiate(struct dentry *dentry, struct inode *inode)
 }
 EXPORT_SYMBOL(security_d_instantiate);
 
-int security_getprocattr(struct task_struct *p, char *name, char **value)
+int security_getprocattr(struct task_struct *p, const char *lsm, char *name,
+                      char **value)
 {
      struct security_operations *sop = NULL;
      struct secids secid;
-     char *lsm;
-     int lsmlen;
      int ret;
 
      /*
-      * Names will either be in the legacy form containing
-      * no periods (".") or they will be the LSM name followed
-      * by the legacy suffix. "current" or "selinux.current"
-      * The exception is "context", which gets all of the LSMs.
-      *
-      * Legacy names are handled by the presenting LSM.
-      * Suffixed names are handled by the named LSM.
+      * Target LSM will be either NULL or looked up by name. Names with
+      * a NULL LSM (legacy) are handled by the presenting LSM. The
+      * exception is "context", which gets all of the LSMs.
       */
      if (strcmp(name, "context") == 0) {
+             char *lsmname;
+             int lsmlen;
+
              security_task_getsecid(p, &secid);
-             ret = security_secid_to_secctx(&secid, &lsm, &lsmlen, &sop);
+             ret = security_secid_to_secctx(&secid, &lsmname, &lsmlen, &sop);
              if (ret == 0) {
-                     *value = kstrdup(lsm, GFP_KERNEL);
+                     *value = kstrdup(lsmname, GFP_KERNEL);
                      if (*value == NULL)
                              ret = -ENOMEM;
                      else
                              ret = strlen(*value);
-                     security_release_secctx(lsm, lsmlen, sop);
+                     security_release_secctx(lsmname, lsmlen, sop);
              }
              return ret;
      }
 
-     if (present_ops && !strchr(name, '.'))
-             return present_getprocattr(p, name, value);
-
-     for_each_hook(sop, getprocattr) {
-             lsm = sop->name;
-             lsmlen = strlen(lsm);
-             if (!strncmp(name, lsm, lsmlen) && name[lsmlen] == '.')
-                     return sop->getprocattr(p, name + lsmlen + 1, value);
+     if (!lsm) {
+             if (present_ops)
+                     return present_getprocattr(p, name, value);
+     } else {
+             for_each_hook(sop, getprocattr) {
+                     if (!strcmp(lsm, sop->name))
+                             return sop->getprocattr(p, name, value);
+             }
      }
      return -EINVAL;
 }
 
-int security_setprocattr(struct task_struct *p, char *name, void *value,
-                      size_t size)
+int security_setprocattr(struct task_struct *p, const char *lsm, char *name,
+                      void *value, size_t size)
 {
      struct security_operations *sop;
-     char *lsm;
-     int lsmlen;
 
      /*
-      * Names will either be in the legacy form containing
-      * no periods (".") or they will be the LSM name followed

security/security.c void security_d_instantiate(struct dentry *dentry, struct inode *inode) · line 1951

Quoted 10 lines
security/security.c +2 -5
-      * by the legacy suffix.
-      * "current" or "selinux.current"
-      *
-      * Legacy names are handled by the presenting LSM.
-      * Suffixed names are handled by the named LSM.
+      * Target LSM will be either NULL or looked up by name. Names with
+      * a NULL LSM (legacy) are handled by the presenting LSM. The
       */
      if (present_ops && !strchr(name, '.'))
              return present_setprocattr(p, name, value, size);

We'll want to loose the preceding two lines, and add some later.

security/security.c void security_d_instantiate(struct dentry *dentry, struct inode *inode)

Quoted 13 lines
security/security.c +6 -7
-     for_each_hook(sop, setprocattr) {
-             lsm = sop->name;
-             lsmlen = strlen(lsm);
-             if (!strncmp(name, lsm, lsmlen) && name[lsmlen] == '.')
-                     return sop->setprocattr(p, name + lsmlen + 1, value,
-                                             size);
+     if (lsm) {
+             for_each_hook(sop, setprocattr) {
+                     if (!strcmp(lsm, sop->name))
+                             return sop->setprocattr(p, name, value,
+                                                     size);
+             }
-     }
Quoted 2 lines

+ } else if (present_ops)
+ return present_setprocattr(p, name, value, size);

Ah yes, this is better. Great!

-Kees

Quoted 4 lines
Quoted 3 lines
security/security.c +0 -0
      return -EINVAL;
 }
Signature · 2 lines
Kees Cook
Chrome OS Security
author maintainer
#31 lore raw
Quoted 13 lines · Kees Cook
Quoted 12 lines · Casey Schaufler
Quoted 11 lines · Kees Cook
Quoted 4 lines · Casey Schaufler

The /proc/*/attr interfaces are given to one LSM. This can be done by setting CONFIG_SECURITY_PRESENT. Additional interfaces have been created in /proc/*/attr so that each LSM has its own named interfaces. The name of the presenting LSM can be read from

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

Quoted 5 lines
Quoted 2 lines

I will confess that the reason I went with <lsm>.current instead of <lsm>/current was that the former was easier to implement.

Yeah, that's totally fine. It wasn't very obvious (to me) how to implement this initially, so no problem at all. I'm glad there was something more than bug fixes I could contribute to this series. :)

Oh dear. I'm rebasing for 3.12 and the macros don't generate compiling code any longer. It seems that, among other things, readdir is no longer a member of file_operations.

Quoted 319 lines
Quoted 77 lines
Quoted 77 lines

-Kees

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

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

---
 fs/proc/base.c           |   95 ++++++++++++++++++++++++++++++++++++----------
 fs/proc/internal.h       |    1 +
 include/linux/security.h |   11 +++---
 security/security.c      |   67 ++++++++++++++------------------
 4 files changed, 112 insertions(+), 62 deletions(-)
fs/proc/base.c +28 -2
index 941fe83..4c80ffd 100644
@@ -138,6 +138,10 @@ struct pid_entry {
      NOD(NAME, (S_IFREG|(MODE)),                     \
              NULL, &proc_single_file_operations,     \
              { .proc_show = show } )
+#define ATTR(LSM, NAME, MODE)                                \
+     NOD(NAME, (S_IFREG|(MODE)),                     \
+             NULL, &proc_pid_attr_operations,        \
+             { .lsm = LSM } )
 
 /*
  * Count the number of hardlinks for the pid_entry table, excluding the .
@@ -2292,7 +2296,7 @@ static ssize_t proc_pid_attr_read(struct file * file, char __user * buf,
      if (!task)
              return -ESRCH;
 
-     length = security_getprocattr(task,
+     length = security_getprocattr(task, PROC_I(inode)->op.lsm,
                                    (char*)file->f_path.dentry->d_name.name,
                                    &p);
      put_task_struct(task);
@@ -2335,7 +2339,7 @@ static ssize_t proc_pid_attr_write(struct file * file, const char __user * buf,
      if (length < 0)
              goto out_free;
 
-     length = security_setprocattr(task,
+     length = security_setprocattr(task, PROC_I(inode)->op.lsm,
                                    (char*)file->f_path.dentry->d_name.name,
                                    (void*)page, count);
      mutex_unlock(&task->signal->cred_guard_mutex);
@@ -2353,29 +2357,82 @@ static const struct file_operations proc_pid_attr_operations = {
      .llseek         = generic_file_llseek,
 };
 
+#define LSM_DIR_OPS(LSM) \
+static int proc_##LSM##_attr_dir_readdir(struct file * filp, \
+                          void * dirent, filldir_t filldir) \
+{ \
+     return proc_pident_readdir(filp, dirent, filldir, \
+                                LSM##_attr_dir_stuff, \
+                                ARRAY_SIZE(LSM##_attr_dir_stuff)); \
+} \
+\
+static const struct file_operations proc_##LSM##_attr_dir_ops = { \
+     .read           = generic_read_dir, \
+     .readdir        = proc_##LSM##_attr_dir_readdir, \
+     .llseek         = default_llseek, \
+}; \
+\
+static struct dentry *proc_##LSM##_attr_dir_lookup(struct inode *dir, \
+                             struct dentry *dentry, unsigned int flags) \
+{ \
+     return proc_pident_lookup(dir, dentry, \
+                               LSM##_attr_dir_stuff, \
+                               ARRAY_SIZE(LSM##_attr_dir_stuff)); \
+} \
Quoted 8 lines

fs/proc/base.c static const struct file_operations proc_pid_attr_operations = { · line 2387

Quoted 6 lines
fs/proc/base.c +6 -0
+\
+static const struct inode_operations proc_##LSM##_attr_dir_inode_ops = { \
+     .lookup         = proc_##LSM##_attr_dir_lookup, \
+     .getattr        = pid_getattr, \
+     .setattr        = proc_setattr, \
+};

That's one hell of a macro you got there, Kees. I'm not saying it's bad, but it is quite the mouthful.

Heh, yeah. And this is the reduced version! I haven't found a good way to make this smaller yet.

Quoted 23 lines
Quoted 23 lines
fs/proc/base.c +23 -0
+
+#ifdef CONFIG_SECURITY_SELINUX
+static const struct pid_entry selinux_attr_dir_stuff[] = {
+     ATTR("selinux", "current",      S_IRUGO|S_IWUGO),
+     ATTR("selinux", "prev",         S_IRUGO),
+     ATTR("selinux", "exec",         S_IRUGO|S_IWUGO),
+     ATTR("selinux", "fscreate",     S_IRUGO|S_IWUGO),
+     ATTR("selinux", "keycreate",    S_IRUGO|S_IWUGO),
+     ATTR("selinux", "sockcreate",   S_IRUGO|S_IWUGO),
+};
+LSM_DIR_OPS(selinux);
+#endif
+
+#ifdef CONFIG_SECURITY_SMACK
+static const struct pid_entry smack_attr_dir_stuff[] = {
+     ATTR("smack", "current",        S_IRUGO|S_IWUGO),
+};
+LSM_DIR_OPS(smack);
+#endif
+
+#ifdef CONFIG_SECURITY_APPARMOR
+static const struct pid_entry apparmor_attr_dir_stuff[] = {
+     ATTR("apparmor", "current",     S_IRUGO|S_IWUGO),
Quoted 8 lines

fs/proc/base.c static const struct file_operations proc_pid_attr_operations = { · line 2416

Quoted 6 lines
fs/proc/base.c +6 -0
+     ATTR("apparmor", "prev",        S_IRUGO),
+     ATTR("apparmor", "exec",        S_IRUGO|S_IWUGO),
+};
+LSM_DIR_OPS(apparmor);
+#endif
+

%s/dir_stuff/dir_entries/g
It doesn't have to be "entries", but "stuff" is horribly non-descriptive.

Using "entries" is fine by me. I was modeling it entirely after the existing code (see "attr_dir_stuff" below).

Quoted 189 lines
Quoted 163 lines
fs/proc/base.c +13 -17
 static const struct pid_entry attr_dir_stuff[] = {
-     REG("current",            S_IRUGO|S_IWUGO, proc_pid_attr_operations),
-     REG("prev",               S_IRUGO,         proc_pid_attr_operations),
-     REG("exec",               S_IRUGO|S_IWUGO, proc_pid_attr_operations),
-     REG("fscreate",           S_IRUGO|S_IWUGO, proc_pid_attr_operations),
-     REG("keycreate",          S_IRUGO|S_IWUGO, proc_pid_attr_operations),
-     REG("sockcreate",         S_IRUGO|S_IWUGO, proc_pid_attr_operations),
-     REG("context",            S_IRUGO|S_IWUGO, proc_pid_attr_operations),
+     ATTR(NULL, "current",           S_IRUGO|S_IWUGO),
+     ATTR(NULL, "prev",              S_IRUGO),
+     ATTR(NULL, "exec",              S_IRUGO|S_IWUGO),
+     ATTR(NULL, "fscreate",          S_IRUGO|S_IWUGO),
+     ATTR(NULL, "keycreate",         S_IRUGO|S_IWUGO),
+     ATTR(NULL, "sockcreate",        S_IRUGO|S_IWUGO),
+     ATTR(NULL, "context",           S_IRUGO|S_IWUGO),
 #ifdef CONFIG_SECURITY_SELINUX
-     REG("selinux.current",    S_IRUGO|S_IWUGO, proc_pid_attr_operations),
-     REG("selinux.prev",       S_IRUGO,         proc_pid_attr_operations),
-     REG("selinux.exec",       S_IRUGO|S_IWUGO, proc_pid_attr_operations),
-     REG("selinux.fscreate",   S_IRUGO|S_IWUGO, proc_pid_attr_operations),
-     REG("selinux.keycreate",  S_IRUGO|S_IWUGO, proc_pid_attr_operations),
-     REG("selinux.sockcreate", S_IRUGO|S_IWUGO, proc_pid_attr_operations),
+     DIR("selinux",                  S_IRUGO|S_IXUGO,
+         proc_selinux_attr_dir_inode_ops, proc_selinux_attr_dir_ops),
 #endif
 #ifdef CONFIG_SECURITY_SMACK
-     REG("smack.current",      S_IRUGO|S_IWUGO, proc_pid_attr_operations),
+     DIR("smack",                    S_IRUGO|S_IXUGO,
+         proc_smack_attr_dir_inode_ops, proc_smack_attr_dir_ops),
 #endif
 #ifdef CONFIG_SECURITY_APPARMOR
-     REG("apparmor.current",   S_IRUGO|S_IWUGO, proc_pid_attr_operations),
-     REG("apparmor.prev",      S_IRUGO,         proc_pid_attr_operations),
-     REG("apparmor.exec",      S_IRUGO|S_IWUGO, proc_pid_attr_operations),
+     DIR("apparmor",                 S_IRUGO|S_IXUGO,
+         proc_apparmor_attr_dir_inode_ops, proc_apparmor_attr_dir_ops),
 #endif
 
 };
fs/proc/internal.h +1 -0
index d600fb0..795f649 100644
@@ -56,6 +56,7 @@ union proc_op {
      int (*proc_show)(struct seq_file *m,
              struct pid_namespace *ns, struct pid *pid,
              struct task_struct *task);
+     const char *lsm;
 };
 
 struct proc_inode {
include/linux/security.h +6 -5
index d60e21c..fa89618 100644
@@ -2115,9 +2115,10 @@ int security_sem_semctl(struct sem_array *sma, int cmd);
 int security_sem_semop(struct sem_array *sma, struct sembuf *sops,
                      unsigned nsops, int alter);
 void security_d_instantiate(struct dentry *dentry, struct inode *inode);
-int security_getprocattr(struct task_struct *p, char *name, char **value);
-int security_setprocattr(struct task_struct *p, char *name, void *value,
-                      size_t size);
+int security_getprocattr(struct task_struct *p, const char *lsm, char *name,
+                         char **value);
+int security_setprocattr(struct task_struct *p, const char *lsm, char *name,
+                         void *value, size_t size);
 int security_netlink_send(struct sock *sk, struct sk_buff *skb);
 int security_secid_to_secctx(struct secids *secid, char **secdata, u32 *seclen,
                           struct security_operations **secops);
@@ -2801,8 +2802,8 @@ static inline void security_d_instantiate(struct dentry *dentry,
                                        struct inode *inode)
 { }
 
-static inline int security_getprocattr(struct task_struct *p, char *name,
-                                    char **value)
+static inline int security_getprocattr(struct task_struct *p, char *lsm,
+                       char *name, char **value)
 {
      return -EINVAL;
 }
security/security.c +21 -27
index 119a377..499af30 100644
@@ -1897,74 +1897,65 @@ void security_d_instantiate(struct dentry *dentry, struct inode *inode)
 }
 EXPORT_SYMBOL(security_d_instantiate);
 
-int security_getprocattr(struct task_struct *p, char *name, char **value)
+int security_getprocattr(struct task_struct *p, const char *lsm, char *name,
+                      char **value)
 {
      struct security_operations *sop = NULL;
      struct secids secid;
-     char *lsm;
-     int lsmlen;
      int ret;
 
      /*
-      * Names will either be in the legacy form containing
-      * no periods (".") or they will be the LSM name followed
-      * by the legacy suffix. "current" or "selinux.current"
-      * The exception is "context", which gets all of the LSMs.
-      *
-      * Legacy names are handled by the presenting LSM.
-      * Suffixed names are handled by the named LSM.
+      * Target LSM will be either NULL or looked up by name. Names with
+      * a NULL LSM (legacy) are handled by the presenting LSM. The
+      * exception is "context", which gets all of the LSMs.
       */
      if (strcmp(name, "context") == 0) {
+             char *lsmname;
+             int lsmlen;
+
              security_task_getsecid(p, &secid);
-             ret = security_secid_to_secctx(&secid, &lsm, &lsmlen, &sop);
+             ret = security_secid_to_secctx(&secid, &lsmname, &lsmlen, &sop);
              if (ret == 0) {
-                     *value = kstrdup(lsm, GFP_KERNEL);
+                     *value = kstrdup(lsmname, GFP_KERNEL);
                      if (*value == NULL)
                              ret = -ENOMEM;
                      else
                              ret = strlen(*value);
-                     security_release_secctx(lsm, lsmlen, sop);
+                     security_release_secctx(lsmname, lsmlen, sop);
              }
              return ret;
      }
 
-     if (present_ops && !strchr(name, '.'))
-             return present_getprocattr(p, name, value);
-
-     for_each_hook(sop, getprocattr) {
-             lsm = sop->name;
-             lsmlen = strlen(lsm);
-             if (!strncmp(name, lsm, lsmlen) && name[lsmlen] == '.')
-                     return sop->getprocattr(p, name + lsmlen + 1, value);
+     if (!lsm) {
+             if (present_ops)
+                     return present_getprocattr(p, name, value);
+     } else {
+             for_each_hook(sop, getprocattr) {
+                     if (!strcmp(lsm, sop->name))
+                             return sop->getprocattr(p, name, value);
+             }
      }
      return -EINVAL;
 }
 
-int security_setprocattr(struct task_struct *p, char *name, void *value,
-                      size_t size)
+int security_setprocattr(struct task_struct *p, const char *lsm, char *name,
+                      void *value, size_t size)
 {
      struct security_operations *sop;
-     char *lsm;
-     int lsmlen;
 
      /*
-      * Names will either be in the legacy form containing
-      * no periods (".") or they will be the LSM name followed

security/security.c void security_d_instantiate(struct dentry *dentry, struct inode *inode) · line 1951

Quoted 10 lines
security/security.c +2 -5
-      * by the legacy suffix.
-      * "current" or "selinux.current"
-      *
-      * Legacy names are handled by the presenting LSM.
-      * Suffixed names are handled by the named LSM.
+      * Target LSM will be either NULL or looked up by name. Names with
+      * a NULL LSM (legacy) are handled by the presenting LSM. The
       */
      if (present_ops && !strchr(name, '.'))
              return present_setprocattr(p, name, value, size);

We'll want to loose the preceding two lines, and add some later.

security/security.c void security_d_instantiate(struct dentry *dentry, struct inode *inode)

Quoted 13 lines
security/security.c +6 -7
-     for_each_hook(sop, setprocattr) {
-             lsm = sop->name;
-             lsmlen = strlen(lsm);
-             if (!strncmp(name, lsm, lsmlen) && name[lsmlen] == '.')
-                     return sop->setprocattr(p, name + lsmlen + 1, value,
-                                             size);
+     if (lsm) {
+             for_each_hook(sop, setprocattr) {
+                     if (!strcmp(lsm, sop->name))
+                             return sop->setprocattr(p, name, value,
+                                                     size);
+             }
-     }
Quoted 2 lines

+ } else if (present_ops)
+ return present_setprocattr(p, name, value, size);

Ah yes, this is better. Great!

-Kees

Quoted 2 lines
Quoted 2 lines
security/security.c +0 -0
      return -EINVAL;
 }
#32 lore raw
Quoted 16 lines · Casey Schaufler
Quoted 15 lines · Kees Cook
Quoted 14 lines · Casey Schaufler
Quoted 11 lines · Kees Cook
Quoted 4 lines · Casey Schaufler

The /proc/*/attr interfaces are given to one LSM. This can be done by setting CONFIG_SECURITY_PRESENT. Additional interfaces have been created in /proc/*/attr so that each LSM has its own named interfaces. The name of the presenting LSM can be read from

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

I will confess that the reason I went with <lsm>.current instead of <lsm>/current was that the former was easier to implement.

Quoted 7 lines
Quoted 3 lines

Yeah, that's totally fine. It wasn't very obvious (to me) how to implement this initially, so no problem at all. I'm glad there was something more than bug fixes I could contribute to this series. :)

Oh dear. I'm rebasing for 3.12 and the macros don't generate compiling code any longer. It seems that, among other things, readdir is no longer a member of file_operations.

Agh. I will take a look.

-Kees

Signature · 2 lines
Kees Cook
Chrome OS Security
#33 lore raw
In reply to Casey Schaufler
Quoted 16 lines · Casey Schaufler
Quoted 15 lines · Kees Cook
Quoted 14 lines · Casey Schaufler
Quoted 11 lines · Kees Cook
Quoted 4 lines · Casey Schaufler

The /proc/*/attr interfaces are given to one LSM. This can be done by setting CONFIG_SECURITY_PRESENT. Additional interfaces have been created in /proc/*/attr so that each LSM has its own named interfaces. The name of the presenting LSM can be read from

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

I will confess that the reason I went with <lsm>.current instead of <lsm>/current was that the former was easier to implement.

Quoted 7 lines
Quoted 3 lines

Yeah, that's totally fine. It wasn't very obvious (to me) how to implement this initially, so no problem at all. I'm glad there was something more than bug fixes I could contribute to this series. :)

Oh dear. I'm rebasing for 3.12 and the macros don't generate compiling code any longer. It seems that, among other things, readdir is no longer a member of file_operations.

Looks like f0c3b5093addc8bfe9fe3a5b01acb7ec7969eafa is what touched fs/proc/base.c and it should just need a few tweaks from "readdir" becoming "iterate", and the prototype changing.

So it should just require bump the macros a little. Let's see if gmail eats my paste...

fs/proc/base.c +4 -4
index 4c80ffd..f670349 100644
@@ -2358,17 +2358,17 @@ static const struct file_operations proc_pid_attr_operat
 };
 
 #define LSM_DIR_OPS(LSM) \
-static int proc_##LSM##_attr_dir_readdir(struct file * filp, \
-                            void * dirent, filldir_t filldir) \
+static int proc_##LSM##_attr_dir_iterate(struct file * filp, \
+                            struct dir_context *ctx) \
 { \
-       return proc_pident_readdir(filp, dirent, filldir, \
+       return proc_pident_readdir(filp, ctx, \
                                   LSM##_attr_dir_stuff, \
                                   ARRAY_SIZE(LSM##_attr_dir_stuff)); \
 } \
 \
 static const struct file_operations proc_##LSM##_attr_dir_ops = { \
        .read           = generic_read_dir, \
-       .readdir        = proc_##LSM##_attr_dir_readdir, \
+       .iterate        = proc_##LSM##_attr_dir_iterate, \
        .llseek         = default_llseek, \
 }; \
 \

Do you have the rest of the series already ported to 3.12?

-Kees

Signature · 2 lines
Kees Cook
Chrome OS Security
author maintainer
#34 lore raw
Quoted 58 lines · Kees Cook
Quoted 14 lines · Casey Schaufler
Quoted 13 lines · Kees Cook
Quoted 12 lines · Casey Schaufler
Quoted 11 lines · Kees Cook
Quoted 4 lines · Casey Schaufler

The /proc/*/attr interfaces are given to one LSM. This can be done by setting CONFIG_SECURITY_PRESENT. Additional interfaces have been created in /proc/*/attr so that each LSM has its own named interfaces. The name of the presenting LSM can be read from

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

Quoted 8 lines
Quoted 5 lines
Quoted 2 lines

I will confess that the reason I went with <lsm>.current instead of <lsm>/current was that the former was easier to implement.

Yeah, that's totally fine. It wasn't very obvious (to me) how to implement this initially, so no problem at all. I'm glad there was something more than bug fixes I could contribute to this series. :)

Oh dear. I'm rebasing for 3.12 and the macros don't generate compiling code any longer. It seems that, among other things, readdir is no longer a member of file_operations.

Looks like f0c3b5093addc8bfe9fe3a5b01acb7ec7969eafa is what touched fs/proc/base.c and it should just need a few tweaks from "readdir" becoming "iterate", and the prototype changing.

So it should just require bump the macros a little. Let's see if gmail eats my paste...

fs/proc/base.c +4 -4
index 4c80ffd..f670349 100644
@@ -2358,17 +2358,17 @@ static const struct file_operations proc_pid_attr_operat
 };
 
 #define LSM_DIR_OPS(LSM) \
-static int proc_##LSM##_attr_dir_readdir(struct file * filp, \
-                            void * dirent, filldir_t filldir) \
+static int proc_##LSM##_attr_dir_iterate(struct file * filp, \
+                            struct dir_context *ctx) \
 { \
-       return proc_pident_readdir(filp, dirent, filldir, \
+       return proc_pident_readdir(filp, ctx, \
                                   LSM##_attr_dir_stuff, \
                                   ARRAY_SIZE(LSM##_attr_dir_stuff)); \
 } \
 \
 static const struct file_operations proc_##LSM##_attr_dir_ops = { \
        .read           = generic_read_dir, \
-       .readdir        = proc_##LSM##_attr_dir_readdir, \
+       .iterate        = proc_##LSM##_attr_dir_iterate, \
        .llseek         = default_llseek, \
 }; \
 \
Quoted 4 lines

Do you have the rest of the series already ported to 3.12?

-Kees

Yes, but I did it last week before my holiday started, and have not updated since. I will become active again upon my return. I hope to have the 3.12 version posted before the Security Summit.

--
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.