[Date Prev][Date Next] [Thread Prev][Thread Next]
[Thread Index]
[Date Index]
[Author Index]
Re: Two netlink patches
- From: Serge Hallyn <serue us ibm com>
- To: Stephen Smalley <sds epoch ncsc mil>
- Cc: Linux Audit Discussion <linux-audit redhat com>
- Subject: Re: Two netlink patches
- Date: Thu, 16 Dec 2004 10:55:29 -0600
Well, the attached (compiled, but untested) patch does move the code
into audit.c the way Chris wanted, adding only one line to
dummy_netlink_send and cap_netlink_send. But it also would require some
changes to SELinux, I assume, to at least handle the new CAP_AUDIT bit.
By extending the NETLINK_CREDS(skb), I assume you mean adding a void
*security? Perhaps that's actually the cleaner way to go, if only
because it lets the actual receiving subsystem perform the check, rather
than netlink. That's the part I don't like about my patch. While in
this case it's just audit, that may change, and soon
security_netlink_send becomes a central location for checks for all
sorts of protocols...
So does extending NETLINK_CREDS seem (politically) feasible? Or does
the attached patch seem acceptable?
-serge
On Thu, 2004-12-16 at 10:29 -0500, Stephen Smalley wrote:
> On Thu, 2004-12-16 at 11:25, Serge Hallyn wrote:
> > Hi,
> >
> > I believe a single CAP_AUDIT_CONTROL bit should suffice for defining an
> > MRMLOSPP-compliant audit role. I will send out a new patch asap which
> > also nixes cap_netlink_audit_send and just leaves the code in dummy.
> >
> > Does this seem sufficient? Or do you (Chris) object to having this test
> > in the netlink send codepath? As far as I can see, the only legitimate
> > alternative would be to in fact move audit control to a different
> > (pseudo-fs?) interface.
>
> For just a capability check, you can check on the receive path based on
> NETLINK_CREDS(skb)->eff_cap, as long as the security modules set all of
> the capability bits in that field properly (commoncap already does so,
> and SELinux and dummy could easily be changed to do so). In contrast,
> we don't have that option for SELinux permissions, because we don't have
> any way to convey either the sender security context or the computed
> permissions in NETLINK_CREDS without extending that structure.
>
--
Serge Hallyn <serue us ibm com>
Index: linux-2.6.9/include/linux/audit.h
===================================================================
--- linux-2.6.9.orig/include/linux/audit.h 2004-12-15 17:42:23.000000000 -0600
+++ linux-2.6.9/include/linux/audit.h 2004-12-16 10:44:24.000000000 -0600
@@ -193,6 +193,8 @@ extern void audit_send_reply(int pi
int done, int multi,
void *payload, int size);
extern void audit_log_lost(const char *message);
+struct sk_buff;
+extern int audit_netlink_ok(struct sk_buff *skb);
#else
#define audit_log(t,f,...) do { ; } while (0)
#define audit_log_start(t) ({ NULL; })
@@ -206,6 +208,7 @@ extern void audit_log_lost(const ch
#define audit_set_backlog_limit(l) do { ; } while (0)
#define audit_set_enabled(s) do { ; } while (0)
#define audit_set_failure(s) do { ; } while (0)
+#define audit_netlink_ok(n) do { 0; } while (0)
#endif
#endif
#endif
Index: linux-2.6.9/include/linux/capability.h
===================================================================
--- linux-2.6.9.orig/include/linux/capability.h 2004-12-16 10:27:20.000000000 -0600
+++ linux-2.6.9/include/linux/capability.h 2004-12-16 10:27:32.000000000 -0600
@@ -284,6 +284,10 @@ typedef __u32 kernel_cap_t;
#define CAP_LEASE 28
+/* Allow control of audit subsystem */
+
+#define CAP_AUDIT 29
+
#ifdef __KERNEL__
/*
* Bounding set
Index: linux-2.6.9/include/linux/netlink.h
===================================================================
--- linux-2.6.9.orig/include/linux/netlink.h 2004-12-02 16:08:23.000000000 -0600
+++ linux-2.6.9/include/linux/netlink.h 2004-12-02 16:14:17.000000000 -0600
@@ -120,6 +120,7 @@ extern int netlink_attach(int unit, int
extern void netlink_detach(int unit);
extern int netlink_post(int unit, struct sk_buff *skb);
extern struct sock *netlink_kernel_create(int unit, void (*input)(struct sock *sk, int len));
+extern int netlink_get_msgtype(struct sk_buff *skb);
extern void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err);
extern int netlink_unicast(struct sock *ssk, struct sk_buff *skb, __u32 pid, int nonblock);
extern int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, __u32 pid,
Index: linux-2.6.9/kernel/audit.c
===================================================================
--- linux-2.6.9.orig/kernel/audit.c 2004-12-02 16:02:22.000000000 -0600
+++ linux-2.6.9/kernel/audit.c 2004-12-16 10:46:25.000000000 -0600
@@ -327,8 +327,8 @@ static int audit_receive_msg(struct sk_b
&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 +364,8 @@ static int audit_receive_msg(struct sk_b
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 +384,12 @@ static int audit_receive_msg(struct sk_b
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);
@@ -810,3 +813,38 @@ void audit_log(struct audit_context *ctx
audit_log_end(ab);
}
}
+
+int audit_netlink_ok(struct sk_buff *skb)
+{
+ int err = 0;
+ int msgtype;
+
+ if (!skb || !skb->sk || skb->sk->sk_protocol != NETLINK_AUDIT)
+ goto out;
+
+ msgtype = netlink_get_msgtype(skb);
+
+ switch(msgtype) {
+ case 0: /* not an audit msg */
+
+ case AUDIT_GET:
+ case AUDIT_LIST:
+ break;
+
+ case AUDIT_SET:
+ case AUDIT_USER:
+ case AUDIT_LOGIN:
+
+ case AUDIT_ADD:
+ case AUDIT_DEL:
+ if (!capable(CAP_AUDIT))
+ err = -EPERM;
+ break;
+
+ default: /* permission denied: bad msg */
+ err = -EINVAL;
+ }
+
+out:
+ return err;
+}
Index: linux-2.6.9/kernel/auditsc.c
===================================================================
--- linux-2.6.9.orig/kernel/auditsc.c 2004-12-02 16:02:22.000000000 -0600
+++ linux-2.6.9/kernel/auditsc.c 2004-12-15 15:27:16.000000000 -0600
@@ -250,8 +250,6 @@ 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;
if (!(entry = kmalloc(sizeof(*entry), GFP_KERNEL)))
return -ENOMEM;
if (audit_copy_rule(&entry->rule, data)) {
Index: linux-2.6.9/net/netlink/af_netlink.c
===================================================================
--- linux-2.6.9.orig/net/netlink/af_netlink.c 2004-12-02 16:09:27.000000000 -0600
+++ linux-2.6.9/net/netlink/af_netlink.c 2004-12-03 08:52:19.000000000 -0600
@@ -518,6 +518,18 @@ static int netlink_connect(struct socket
return err;
}
+int netlink_get_msgtype(struct sk_buff *skb)
+{
+ struct nlmsghdr *nlh = (struct nlmsghdr *)skb->data;
+
+ if (skb->len < NLMSG_SPACE(0))
+ return -EINVAL;
+
+ if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len)
+ return -EINVAL;
+ return nlh->nlmsg_type;
+}
+
static int netlink_getname(struct socket *sock, struct sockaddr *addr, int *addr_len, int peer)
{
struct sock *sk = sock->sk;
@@ -1511,6 +1523,7 @@ MODULE_LICENSE("GPL");
MODULE_ALIAS_NETPROTO(PF_NETLINK);
+EXPORT_SYMBOL(netlink_get_msgtype);
EXPORT_SYMBOL(netlink_ack);
EXPORT_SYMBOL(netlink_broadcast);
EXPORT_SYMBOL(netlink_dump_start);
Index: linux-2.6.9/security/commoncap.c
===================================================================
--- linux-2.6.9.orig/security/commoncap.c 2004-12-02 16:08:24.000000000 -0600
+++ linux-2.6.9/security/commoncap.c 2004-12-16 10:39:45.000000000 -0600
@@ -23,11 +23,13 @@
#include <linux/ptrace.h>
#include <linux/xattr.h>
#include <linux/hugetlb.h>
+#include <net/sock.h>
+#include <linux/audit.h>
int cap_netlink_send(struct sock *sk, struct sk_buff *skb)
{
NETLINK_CB(skb).eff_cap = current->cap_effective;
- return 0;
+ return audit_netlink_ok(skb);
}
EXPORT_SYMBOL(cap_netlink_send);
Index: linux-2.6.9/security/dummy.c
===================================================================
--- linux-2.6.9.orig/security/dummy.c 2004-12-02 16:08:24.000000000 -0600
+++ linux-2.6.9/security/dummy.c 2004-12-16 10:40:57.000000000 -0600
@@ -732,7 +732,7 @@ static int dummy_netlink_send (struct so
cap_raise (NETLINK_CB (skb).eff_cap, CAP_NET_ADMIN);
else
NETLINK_CB (skb).eff_cap = 0;
- return 0;
+ return audit_netlink_ok(skb);
}
static int dummy_netlink_recv (struct sk_buff *skb)
[Date Prev][Date Next] [Thread Prev][Thread Next]
[Thread Index]
[Date Index]
[Author Index]