summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorSerge Hallyn <hallyn@cs.wm.edu>2005-01-20 15:51:22 -0800
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-01-20 15:51:22 -0800
commitf2840fccfd30c7776d1b9bc877d3693bce2429be (patch)
tree5a3ece61aa18517202a8400912f67d7ce6e5882a /kernel
parentfe00c037355a517b69608371479add1b68043127 (diff)
[PATCH] Fix audit control message checks
The audit control messages are sent over netlink. Permission checks are done on the process receiving the message, which may not be the same as the process sending the message. This patch switches the netlink_send security hooks to calculate the effective capabilities based on the sender. Then audit_receive_msg performs capability checks based on that. It also introduces the CAP_AUDIT_WRITE and CAP_AUDIT_CONTROL capabilities, and replaces the previous CAP_SYS_ADMIN checks in audit code with the appropriate checks. - Simplified dummy_netlink_send given that dummy now keeps track of capabilities. - Many fixes based on feedback from <linux-audit@redhat.com> list. - Removed the netlink_msg_type helper function. - Switch to using CAP_AUDIT_WRITE and CAP_AUDIT_CONTROL. Signed-off-by: Serge Hallyn <serue@us.ibm.com> Signed-off-by: Stephen Smalley <sds@epoch.ncsc.mil> Signed-off-by: Chris Wright <chrisw@osdl.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/audit.c51
-rw-r--r--kernel/auditsc.c2
2 files changed, 44 insertions, 9 deletions
diff --git a/kernel/audit.c b/kernel/audit.c
index e21f947bacf2..5deb43753406 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -300,21 +300,55 @@ nlmsg_failure: /* Used by NLMSG_PUT */
kfree_skb(skb);
}
+/*
+ * Check for appropriate CAP_AUDIT_ capabilities on incoming audit
+ * control messages.
+ */
+static int audit_netlink_ok(kernel_cap_t eff_cap, u16 msg_type)
+{
+ int err = 0;
+
+ switch (msg_type) {
+ case AUDIT_GET:
+ case AUDIT_LIST:
+ case AUDIT_SET:
+ case AUDIT_LOGIN:
+ case AUDIT_ADD:
+ case AUDIT_DEL:
+ if (!cap_raised(eff_cap, CAP_AUDIT_CONTROL))
+ err = -EPERM;
+ break;
+ case AUDIT_USER:
+ if (!cap_raised(eff_cap, CAP_AUDIT_WRITE))
+ err = -EPERM;
+ break;
+ default: /* bad msg */
+ err = -EINVAL;
+ }
+
+ return err;
+}
+
static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
{
u32 uid, pid, seq;
void *data;
struct audit_status *status_get, status_set;
struct audit_login *login;
- int err = 0;
+ int err;
struct audit_buffer *ab;
+ u16 msg_type = nlh->nlmsg_type;
+
+ err = audit_netlink_ok(NETLINK_CB(skb).eff_cap, msg_type);
+ if (err)
+ return err;
pid = NETLINK_CREDS(skb)->pid;
uid = NETLINK_CREDS(skb)->uid;
seq = nlh->nlmsg_seq;
data = NLMSG_DATA(nlh);
- switch (nlh->nlmsg_type) {
+ switch (msg_type) {
case AUDIT_GET:
status_set.enabled = audit_enabled;
status_set.failure = audit_failure;
@@ -327,8 +361,8 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
&status_set, sizeof(status_set));
break;
case AUDIT_SET:
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
+ if (nlh->nlmsg_len < sizeof(struct audit_status))
+ return -EINVAL;
status_get = (struct audit_status *)data;
if (status_get->mask & AUDIT_STATUS_ENABLED) {
err = audit_set_enabled(status_get->enabled);
@@ -364,8 +398,8 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
audit_log_end(ab);
break;
case AUDIT_LOGIN:
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
+ if (nlh->nlmsg_len < sizeof(struct audit_login))
+ return -EINVAL;
login = (struct audit_login *)data;
ab = audit_log_start(NULL);
if (ab) {
@@ -384,9 +418,12 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
login->loginuid);
#endif
break;
- case AUDIT_LIST:
case AUDIT_ADD:
case AUDIT_DEL:
+ if (nlh->nlmsg_len < sizeof(struct audit_rule))
+ return -EINVAL;
+ /* fallthrough */
+ case AUDIT_LIST:
#ifdef CONFIG_AUDITSYSCALL
err = audit_receive_filter(nlh->nlmsg_type, pid, uid, seq,
data);
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index aa617bbe49b0..5efa31c1dc83 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -250,8 +250,6 @@ int audit_receive_filter(int type, int pid, int uid, int seq, void *data)
audit_send_reply(pid, seq, AUDIT_LIST, 1, 1, NULL, 0);
break;
case AUDIT_ADD:
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
if (!(entry = kmalloc(sizeof(*entry), GFP_KERNEL)))
return -ENOMEM;
if (audit_copy_rule(&entry->rule, data)) {