----- Forwarded message from Serge Hallyn <serue(a)us.ibm.com> -----
From: Serge Hallyn <serue(a)us.ibm.com>
To: LSM <linux-security-module(a)wirex.com>
Message-Id: <1095256778.5294.17.camel(a)serge.austin.ibm.com>
X-Mailer: Ximian Evolution 1.4.5
Date: Wed, 15 Sep 2004 08:59:38 -0500
Cc:
Subject: [PATCH] LSM hooks for audit
Hi,
Attached is a patch which provides LSM controls over actions related to
the new audit framework. As a specific example, we might like to have
an "audit role", enabled by selinux or some other LSM, which would be
the only role allowed to add or delete filter rules.
What do people think about adding these hooks, both in general and these
hooks specifically?
thanks,
-serge
--
=======================================================
Serge Hallyn
Security Software Engineer, IBM Linux Technology Center
serue(a)us.ibm.com
diff -pNru /home/hallyn/kernels/linux-2.6.8.1/include/linux/security.h
linux-2.6.8.1/include/linux/security.h
--- /home/hallyn/kernels/linux-2.6.8.1/include/linux/security.h 2004-08-14
05:55:48.000000000 -0500
+++ linux-2.6.8.1/include/linux/security.h 2004-09-09 11:27:25.661860264 -0500
@@ -1012,6 +1012,22 @@ struct swap_info_struct;
* remove a stacked module.
* @name contains the name of the security module being unstacked.
* @ops contains a pointer to the struct security_operations of the module to unstack.
+ * @audit_set:
+ * set login parameters
+ * @mask: list of what is being set, out of
+ * AUDIT_STATUS_ENABLED
+ * AUDIT_STATUS_FAILURE
+ * AUDIT_STATUS_PID
+ * AUDIT_STATUS_RATE_LIMIT
+ * AUDIT_STATUS_BACKLOG_LIMIT
+ * @audit_login:
+ * create a login audit record
+ * @audit_listfilter:
+ * list the syscall audit rules
+ * @audit_listadd:
+ * add a syscall audit rule
+ * @audit_listdel:
+ * delete a syscall audit rule
*
* This is the main security structure.
*/
@@ -1228,6 +1244,12 @@ struct security_operations {
int (*sk_alloc_security) (struct sock *sk, int family, int priority);
void (*sk_free_security) (struct sock *sk);
#endif /* CONFIG_SECURITY_NETWORK */
+
+ int (*audit_set) (u32 mask);
+ int (*audit_login) (void);
+ int (*audit_listfilter) (void);
+ int (*audit_listadd) (void);
+ int (*audit_listdel) (void);
};
/* global variables */
@@ -1876,6 +1898,31 @@ static inline int security_setprocattr(s
return security_ops->setprocattr(p, name, value, size);
}
+static inline int security_audit_set (u32 mask)
+{
+ return security_ops->audit_set(mask);
+}
+
+static inline int security_audit_login (void)
+{
+ return security_ops->audit_login();
+}
+
+static inline int security_audit_listfilter (void)
+{
+ return security_ops->audit_listfilter();
+}
+
+static inline int security_audit_listadd (void)
+{
+ return security_ops->audit_listadd();
+}
+
+static inline int security_audit_listdel (void)
+{
+ return security_ops->audit_listdel();
+}
+
static inline int security_netlink_send(struct sock *sk, struct sk_buff * skb)
{
return security_ops->netlink_send(sk, skb);
@@ -2499,6 +2546,31 @@ static inline int security_setprocattr(s
return -EINVAL;
}
+int security_audit_set (u32 mask)
+{
+ return 0;
+}
+
+int security_audit_login (void)
+{
+ return 0;
+}
+
+int security_audit_listfilter (void)
+{
+ return 0;
+}
+
+int security_audit_listadd (void)
+{
+ return 0;
+}
+
+int security_audit_listdel (void)
+{
+ return 0;
+}
+
/*
* The netlink capability defaults need to be used inline by default
* (rather than hooking into the capability module) to reduce overhead
diff -pNru /home/hallyn/kernels/linux-2.6.8.1/kernel/audit.c linux-2.6.8.1/kernel/audit.c
--- /home/hallyn/kernels/linux-2.6.8.1/kernel/audit.c 2004-08-14 05:56:24.000000000 -0500
+++ linux-2.6.8.1/kernel/audit.c 2004-09-09 10:51:18.636298224 -0500
@@ -327,8 +327,9 @@ static int audit_receive_msg(struct sk_b
&status_set, sizeof(status_set));
break;
case AUDIT_SET:
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
+ err = security_audit_set(status_get->mask);
+ if (err)
+ return err;
status_get = (struct audit_status *)data;
if (status_get->mask & AUDIT_STATUS_ENABLED) {
err = audit_set_enabled(status_get->enabled);
@@ -364,8 +365,9 @@ static int audit_receive_msg(struct sk_b
audit_log_end(ab);
break;
case AUDIT_LOGIN:
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
+ err = security_audit_login();
+ if (err)
+ return err;
login = (struct audit_login *)data;
ab = audit_log_start(NULL);
if (ab) {
diff -pNru /home/hallyn/kernels/linux-2.6.8.1/kernel/auditsc.c
linux-2.6.8.1/kernel/auditsc.c
--- /home/hallyn/kernels/linux-2.6.8.1/kernel/auditsc.c 2004-08-14 05:55:48.000000000
-0500
+++ linux-2.6.8.1/kernel/auditsc.c 2004-09-09 11:37:43.176983696 -0500
@@ -34,6 +34,7 @@
#include <asm/types.h>
#include <linux/mm.h>
#include <linux/module.h>
+#include <linux/security.h>
#include <linux/audit.h>
#include <linux/personality.h>
@@ -238,6 +239,9 @@ int audit_receive_filter(int type, int p
case AUDIT_LIST:
/* The *_rcu iterators not needed here because we are
always called with audit_netlink_sem held. */
+ err = security_audit_listfilter();
+ if (err)
+ return err;
list_for_each_entry(entry, &audit_tsklist, list)
audit_send_reply(pid, seq, AUDIT_LIST, 0, 1,
&entry->rule, sizeof(entry->rule));
@@ -250,8 +254,9 @@ int audit_receive_filter(int type, int p
audit_send_reply(pid, seq, AUDIT_LIST, 1, 1, NULL, 0);
break;
case AUDIT_ADD:
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
+ err = security_audit_listadd();
+ if (err)
+ return err;
if (!(entry = kmalloc(sizeof(*entry), GFP_KERNEL)))
return -ENOMEM;
if (audit_copy_rule(&entry->rule, data)) {
@@ -267,6 +272,9 @@ int audit_receive_filter(int type, int p
err = audit_add_rule(entry, &audit_extlist);
break;
case AUDIT_DEL:
+ err = security_audit_listdel();
+ if (err)
+ return err;
flags =((struct audit_rule *)data)->flags;
if (!err && (flags & AUDIT_PER_TASK))
err = audit_del_rule(data, &audit_tsklist);
diff -pNru /home/hallyn/kernels/linux-2.6.8.1/security/dummy.c
linux-2.6.8.1/security/dummy.c
--- /home/hallyn/kernels/linux-2.6.8.1/security/dummy.c 2004-08-14 05:54:51.000000000
-0500
+++ linux-2.6.8.1/security/dummy.c 2004-09-09 11:00:40.591867992 -0500
@@ -873,6 +873,34 @@ static int dummy_setprocattr(struct task
return -EINVAL;
}
+static int dummy_audit_set(u32 mask)
+{
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+}
+
+static int dummy_audit_login(void)
+{
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+}
+
+static int dummy_audit_listfilter(void)
+{
+ return 0;
+}
+
+static int dummy_audit_listadd(void)
+{
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+}
+
+static int dummy_audit_listdel(void)
+{
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+}
struct security_operations dummy_security_ops;
@@ -1005,6 +1033,11 @@ void security_fixup_ops (struct security
set_to_dummy_if_null(ops, d_instantiate);
set_to_dummy_if_null(ops, getprocattr);
set_to_dummy_if_null(ops, setprocattr);
+ set_to_dummy_if_null(ops, audit_set);
+ set_to_dummy_if_null(ops, audit_login);
+ set_to_dummy_if_null(ops, audit_listfilter);
+ set_to_dummy_if_null(ops, audit_listadd);
+ set_to_dummy_if_null(ops, audit_listdel);
#ifdef CONFIG_SECURITY_NETWORK
set_to_dummy_if_null(ops, unix_stream_connect);
set_to_dummy_if_null(ops, unix_may_send);
----- End forwarded message -----