Skip to contentSkip to conversation

V3 Remove SELinux dependencies from linux-audit via LSM

RFC PATCH New Casey Schaufler 1 participant 1 message Aug 31, 2007

Subsystems (4)
lore
Share & tools
lore
#0 lore raw

RFC PATCH 1/1 V3 Remove SELinux dependencies from linux-audit via LSM

From: Casey Schaufler <[email protected]>

This patch interposes LSM interfaces between the audit system and SELinux. This helps make SELinux a cleaner LSM and clarifies the interfaces provided by the audit system. The audit system no longer requires SELinux functions or data structures, making it available for use by other LSMs.

The audit system interfaces should now be useful to any LSM that can provide secids and text string representations that match them. The audit system uses secids only to map to those strings and treats them as opaque data otherwise. Audit rule information that is specific to an LSM is maintained through a void *.

The SELinux code uses LSM interfaces to access the audit system, with the exception of audit_rule_update_callout(), which is intended to be called at the descretion of an LSM to update the LSM specific rules.

The LSM interface includes six new entries, four for audit and two that supply secids from the LSM to networking and audit subsystems. Also, there were several cases where SELinux code was being called where LSM interfaces were more appropriate. These uses have been repaired and the SELinux interfaces are no longer exported.

These changes expose the secid as an LSM interface. SELinux already uses secids. Other LSMs that expect to interface with audit, xfrm, and USB will have to support the notion of secids. Smack has been adjusted to support this scheme.

This patch is relative to 2.6.23-rc4. It will not apply to 2.6.22.

---

I have approached the elimination of secids from three different directions and while I would accept the changes required I would not expect all parties to buy into them because of the code disruption. The approach I am putting forward has the advantage of directly addressing the issue at hand, which is to make it possible for an LSM that is not SELinux to use the audit system. As I've suggested elsewhere, maybe cleaning up the LSM interface is a task for Linux 3.0.

 include/linux/audit.h               |   55 +++++++++-
 include/linux/security.h            |  113 +++++++++++++++++++++
 include/linux/selinux.h             |  138 --------------------------
 kernel/audit.c                      |   43 +++-----
 kernel/audit.h                      |   41 -------
 kernel/auditfilter.c                |   70 ++++---------
 kernel/auditsc.c                    |   45 ++++----
 net/netlink/af_netlink.c            |    3 
 security/selinux/exports.c          |   42 -------
 security/selinux/hooks.c            |   51 +++++++++
 security/selinux/include/security.h |   38 +++++++
 security/selinux/ss/services.c      |   19 +--
 12 files changed, 323 insertions(+), 335 deletions(-)
include/linux/audit.h +49 -6
diff -uprN -X linux-2.6.23-rc4-base/Documentation/dontdiff linux-2.6.23-rc4-base/include/linux/audit.h linux-2.6.23-rc4-audit/include/linux/audit.h
@@ -333,20 +333,63 @@ struct audit_rule {		/* for AUDIT_LIST, 
 #ifdef __KERNEL__
 #include <linux/sched.h>
 
-struct audit_sig_info {
-	uid_t		uid;
-	pid_t		pid;
-	char		ctx[0];
-};
-
 struct audit_buffer;
 struct audit_context;
+struct audit_parent;
 struct inode;
 struct netlink_skb_parms;
 struct linux_binprm;
 struct mq_attr;
 struct mqstat;
 
+struct audit_sig_info {
+	uid_t		uid;
+	pid_t		pid;
+	char		ctx[0];
+};
+
+struct audit_watch {
+	atomic_t		count;	/* reference count */
+	char			*path;	/* insertion path */
+	dev_t			dev;	/* associated superblock device */
+	unsigned long		ino;	/* associated inode number */
+	struct audit_parent	*parent; /* associated parent */
+	struct list_head	wlist;	/* entry in parent->watches list */
+	struct list_head	rules;	/* associated rules */
+};
+
+struct audit_field {
+	u32	type;
+	u32	val;
+	u32	op;
+	char	*se_str;
+	void	*se_rule;
+};
+
+struct audit_krule {
+	int			vers_ops;
+	u32			flags;
+	u32			listnr;
+	u32			action;
+	u32			mask[AUDIT_BITMASK_SIZE];
+	u32			buflen; /* for data alloc on list rules */
+	u32			field_count;
+	char			*filterkey; /* ties events to rules */
+	struct audit_field	*fields;
+	struct audit_field	*arch_f; /* quick access to arch field */
+	struct audit_field	*inode_f; /* quick access to an inode field */
+	struct audit_watch	*watch;	/* associated watch */
+	struct list_head	rlist;	/* entry in audit_watch.rules list */
+};
+
+struct audit_entry {
+	struct list_head	list;
+	struct rcu_head		rcu;
+	struct audit_krule	rule;
+};
+
+extern int audit_rule_update_callout(void);
+
 #define AUDITSC_INVALID 0
 #define AUDITSC_SUCCESS 1
 #define AUDITSC_FAILURE 2
include/linux/security.h +113 -0

149 lines not on this page · raw message

include/linux/selinux.h +0 -138

153 lines not on this page · raw message

kernel/audit.c +19 -24

158 lines not on this page · raw message

kernel/auditfilter.c +22 -48

155 lines not on this page · raw message

kernel/audit.h +0 -41

53 lines not on this page · raw message

kernel/auditsc.c +22 -23

168 lines not on this page · raw message

net/netlink/af_netlink.c +1 -2
diff -uprN -X linux-2.6.23-rc4-base/Documentation/dontdiff linux-2.6.23-rc4-base/net/netlink/af_netlink.c linux-2.6.23-rc4-audit/net/netlink/af_netlink.c
@@ -54,7 +54,6 @@
 #include <linux/mm.h>
 #include <linux/types.h>
 #include <linux/audit.h>
-#include <linux/selinux.h>
 #include <linux/mutex.h>
 
 #include <net/sock.h>
@@ -1190,7 +1189,7 @@ static int netlink_sendmsg(struct kiocb 
 	NETLINK_CB(skb).pid	= nlk->pid;
 	NETLINK_CB(skb).dst_group = dst_group;
 	NETLINK_CB(skb).loginuid = audit_get_loginuid(current->audit_context);
-	selinux_get_task_sid(current, &(NETLINK_CB(skb).sid));
+	security_task_getsecid(current, &(NETLINK_CB(skb).sid));
 	memcpy(NETLINK_CREDS(skb), &siocb->scm->creds, sizeof(struct ucred));
 
 	/* What can I do? Netlink is asynchronous, so that
security/selinux/exports.c +0 -42

48 lines not on this page · raw message

security/selinux/hooks.c +51 -0

81 lines not on this page · raw message

security/selinux/include/security.h +38 -0
diff -uprN -X linux-2.6.23-rc4-base/Documentation/dontdiff linux-2.6.23-rc4-base/security/selinux/include/security.h linux-2.6.23-rc4-audit/security/selinux/include/security.h
@@ -129,5 +129,43 @@ static inline int security_netlbl_sid_to
 
 const char *security_get_initial_sid_context(u32 sid);
 
+/**
+ *      selinux_audit_rule_init - alloc/init an selinux audit rule structure.
+ *      @field: the field this rule refers to
+ *      @op: the operater the rule uses
+ *      @rulestr: the text "target" of the rule
+ *      @vpp: pointer to the new rule structure returned via this
+ *
+ *      Returns 0 if successful, -errno if not.  On success, the rule structure
+ *      will be allocated internally.  The caller must free this structure with
+ *      selinux_audit_rule_free() after use.
+ */
+int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vpp);
+
+/**
+ *      selinux_audit_rule_free - free an selinux audit rule structure.
+ *      @vp: pointer to the audit rule to be freed
+ *
+ *      This will free all memory associated with the given rule.
+ *      If @rule is NULL, no operation is performed.
+ */
+void selinux_audit_rule_free(void *vp);
+
+struct audit_context;
+/**
+ *      selinux_audit_rule_match - determine if a context ID matches a rule.
+ *      @sid: the context ID to check
+ *      @field: the field this rule refers to
+ *      @op: the operater the rule uses
+ *      @vp: pointer to the audit rule to check against
+ *      @actx: the audit context (can be NULL) associated with the check
+ *
+ *      Returns 1 if the context id matches the rule, 0 if it does not, and
+ *      -errno on failure.
+ */
+int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vp,
+                             struct audit_context *actx);
+
+
 #endif /* _SELINUX_SECURITY_H_ */
 
security/selinux/ss/services.c +8 -11
diff -uprN -X linux-2.6.23-rc4-base/Documentation/dontdiff linux-2.6.23-rc4-base/security/selinux/ss/services.c linux-2.6.23-rc4-audit/security/selinux/ss/services.c
@@ -2107,17 +2107,19 @@ struct selinux_audit_rule {
 	struct context au_ctxt;
 };
 
-void selinux_audit_rule_free(struct selinux_audit_rule *rule)
+void selinux_audit_rule_free(void *vp)
 {
+	struct selinux_audit_rule *rule = (struct selinux_audit_rule*)vp;
+
 	if (rule) {
 		context_destroy(&rule->au_ctxt);
 		kfree(rule);
 	}
 }
 
-int selinux_audit_rule_init(u32 field, u32 op, char *rulestr,
-                            struct selinux_audit_rule **rule)
+int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vpp)
 {
+	struct selinux_audit_rule **rule = (struct selinux_audit_rule**)vpp;
 	struct selinux_audit_rule *tmprule;
 	struct role_datum *roledatum;
 	struct type_datum *typedatum;
@@ -2208,10 +2210,10 @@ int selinux_audit_rule_init(u32 field, u
 	return rc;
 }
 
-int selinux_audit_rule_match(u32 sid, u32 field, u32 op,
-                             struct selinux_audit_rule *rule,
+int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vp,
                              struct audit_context *actx)
 {
+	struct selinux_audit_rule *rule = (struct selinux_audit_rule*)vp;
 	struct context *ctxt;
 	struct mls_level *level;
 	int match = 0;
@@ -2320,7 +2322,7 @@ out:
 	return match;
 }
 
-static int (*aurule_callback)(void) = NULL;
+static int (*aurule_callback)(void) = audit_rule_update_callout;
 
 static int aurule_avc_callback(u32 event, u32 ssid, u32 tsid,
                                u16 class, u32 perms, u32 *retained)
@@ -2345,11 +2347,6 @@ static int __init aurule_init(void)
 }
 __initcall(aurule_init);
 
-void selinux_audit_set_callback(int (*callback)(void))
-{
-	aurule_callback = callback;
-}
-
 #ifdef CONFIG_NETLABEL
 /*
  * NetLabel cache structure