diff options
-rw-r--r-- | include/uapi/linux/audit.h | 8 | ||||
-rw-r--r-- | kernel/audit.c | 51 |
2 files changed, 55 insertions, 4 deletions
diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h index 11917f747cb4..dfa4c860ccef 100644 --- a/include/uapi/linux/audit.h +++ b/include/uapi/linux/audit.h | |||
@@ -373,6 +373,14 @@ enum { | |||
373 | */ | 373 | */ |
374 | #define AUDIT_MESSAGE_TEXT_MAX 8560 | 374 | #define AUDIT_MESSAGE_TEXT_MAX 8560 |
375 | 375 | ||
376 | /* Multicast Netlink socket groups (default up to 32) */ | ||
377 | enum audit_nlgrps { | ||
378 | AUDIT_NLGRP_NONE, /* Group 0 not used */ | ||
379 | AUDIT_NLGRP_READLOG, /* "best effort" read only socket */ | ||
380 | __AUDIT_NLGRP_MAX | ||
381 | }; | ||
382 | #define AUDIT_NLGRP_MAX (__AUDIT_NLGRP_MAX - 1) | ||
383 | |||
376 | struct audit_status { | 384 | struct audit_status { |
377 | __u32 mask; /* Bit mask for valid entries */ | 385 | __u32 mask; /* Bit mask for valid entries */ |
378 | __u32 enabled; /* 1 = enabled, 0 = disabled */ | 386 | __u32 enabled; /* 1 = enabled, 0 = disabled */ |
diff --git a/kernel/audit.c b/kernel/audit.c index 223cb746f141..d272cc11dff4 100644 --- a/kernel/audit.c +++ b/kernel/audit.c | |||
@@ -424,6 +424,35 @@ static void kauditd_send_skb(struct sk_buff *skb) | |||
424 | } | 424 | } |
425 | 425 | ||
426 | /* | 426 | /* |
427 | * kauditd_send_multicast_skb - send the skb to multicast userspace listeners | ||
428 | * | ||
429 | * This function doesn't consume an skb as might be expected since it has to | ||
430 | * copy it anyways. | ||
431 | */ | ||
432 | static void kauditd_send_multicast_skb(struct sk_buff *skb) | ||
433 | { | ||
434 | struct sk_buff *copy; | ||
435 | struct audit_net *aunet = net_generic(&init_net, audit_net_id); | ||
436 | struct sock *sock = aunet->nlsk; | ||
437 | |||
438 | /* | ||
439 | * The seemingly wasteful skb_copy() rather than bumping the refcount | ||
440 | * using skb_get() is necessary because non-standard mods are made to | ||
441 | * the skb by the original kaudit unicast socket send routine. The | ||
442 | * existing auditd daemon assumes this breakage. Fixing this would | ||
443 | * require co-ordinating a change in the established protocol between | ||
444 | * the kaudit kernel subsystem and the auditd userspace code. There is | ||
445 | * no reason for new multicast clients to continue with this | ||
446 | * non-compliance. | ||
447 | */ | ||
448 | copy = skb_copy(skb, GFP_KERNEL); | ||
449 | if (!copy) | ||
450 | return; | ||
451 | |||
452 | nlmsg_multicast(sock, copy, 0, AUDIT_NLGRP_READLOG, GFP_KERNEL); | ||
453 | } | ||
454 | |||
455 | /* | ||
427 | * flush_hold_queue - empty the hold queue if auditd appears | 456 | * flush_hold_queue - empty the hold queue if auditd appears |
428 | * | 457 | * |
429 | * If auditd just started, drain the queue of messages already | 458 | * If auditd just started, drain the queue of messages already |
@@ -1090,6 +1119,8 @@ static int __net_init audit_net_init(struct net *net) | |||
1090 | struct netlink_kernel_cfg cfg = { | 1119 | struct netlink_kernel_cfg cfg = { |
1091 | .input = audit_receive, | 1120 | .input = audit_receive, |
1092 | .bind = audit_bind, | 1121 | .bind = audit_bind, |
1122 | .flags = NL_CFG_F_NONROOT_RECV, | ||
1123 | .groups = AUDIT_NLGRP_MAX, | ||
1093 | }; | 1124 | }; |
1094 | 1125 | ||
1095 | struct audit_net *aunet = net_generic(net, audit_net_id); | 1126 | struct audit_net *aunet = net_generic(net, audit_net_id); |
@@ -1911,10 +1942,10 @@ out: | |||
1911 | * audit_log_end - end one audit record | 1942 | * audit_log_end - end one audit record |
1912 | * @ab: the audit_buffer | 1943 | * @ab: the audit_buffer |
1913 | * | 1944 | * |
1914 | * The netlink_* functions cannot be called inside an irq context, so | 1945 | * netlink_unicast() cannot be called inside an irq context because it blocks |
1915 | * the audit buffer is placed on a queue and a tasklet is scheduled to | 1946 | * (last arg, flags, is not set to MSG_DONTWAIT), so the audit buffer is placed |
1916 | * remove them from the queue outside the irq context. May be called in | 1947 | * on a queue and a tasklet is scheduled to remove them from the queue outside |
1917 | * any context. | 1948 | * the irq context. May be called in any context. |
1918 | */ | 1949 | */ |
1919 | void audit_log_end(struct audit_buffer *ab) | 1950 | void audit_log_end(struct audit_buffer *ab) |
1920 | { | 1951 | { |
@@ -1924,6 +1955,18 @@ void audit_log_end(struct audit_buffer *ab) | |||
1924 | audit_log_lost("rate limit exceeded"); | 1955 | audit_log_lost("rate limit exceeded"); |
1925 | } else { | 1956 | } else { |
1926 | struct nlmsghdr *nlh = nlmsg_hdr(ab->skb); | 1957 | struct nlmsghdr *nlh = nlmsg_hdr(ab->skb); |
1958 | |||
1959 | kauditd_send_multicast_skb(ab->skb); | ||
1960 | |||
1961 | /* | ||
1962 | * The original kaudit unicast socket sends up messages with | ||
1963 | * nlmsg_len set to the payload length rather than the entire | ||
1964 | * message length. This breaks the standard set by netlink. | ||
1965 | * The existing auditd daemon assumes this breakage. Fixing | ||
1966 | * this would require co-ordinating a change in the established | ||
1967 | * protocol between the kaudit kernel subsystem and the auditd | ||
1968 | * userspace code. | ||
1969 | */ | ||
1927 | nlh->nlmsg_len = ab->skb->len - NLMSG_HDRLEN; | 1970 | nlh->nlmsg_len = ab->skb->len - NLMSG_HDRLEN; |
1928 | 1971 | ||
1929 | if (audit_pid) { | 1972 | if (audit_pid) { |