perf: Handle compat ioctl
[linux-3.10.git] / kernel / audit.c
index 8cc5803..4dd7529 100644 (file)
@@ -60,7 +60,7 @@
 #ifdef CONFIG_SECURITY
 #include <linux/security.h>
 #endif
-#include <linux/netlink.h>
+#include <net/netlink.h>
 #include <linux/freezer.h>
 #include <linux/tty.h>
 #include <linux/pid_namespace.h>
@@ -103,7 +103,8 @@ static int  audit_rate_limit;
 
 /* Number of outstanding audit_buffers allowed. */
 static int     audit_backlog_limit = 64;
-static int     audit_backlog_wait_time = 60 * HZ;
+#define AUDIT_BACKLOG_WAIT_TIME (60 * HZ)
+static int     audit_backlog_wait_time = AUDIT_BACKLOG_WAIT_TIME;
 static int     audit_backlog_wait_overflow = 0;
 
 /* The identity of the user shutting down the audit system. */
@@ -592,13 +593,13 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type)
        case AUDIT_TTY_SET:
        case AUDIT_TRIM:
        case AUDIT_MAKE_EQUIV:
-               if (!capable(CAP_AUDIT_CONTROL))
+               if (!netlink_capable(skb, CAP_AUDIT_CONTROL))
                        err = -EPERM;
                break;
        case AUDIT_USER:
        case AUDIT_FIRST_USER_MSG ... AUDIT_LAST_USER_MSG:
        case AUDIT_FIRST_USER_MSG2 ... AUDIT_LAST_USER_MSG2:
-               if (!capable(CAP_AUDIT_WRITE))
+               if (!netlink_capable(skb, CAP_AUDIT_WRITE))
                        err = -EPERM;
                break;
        default:  /* bad msg */
@@ -613,7 +614,7 @@ static int audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type)
        int rc = 0;
        uid_t uid = from_kuid(&init_user_ns, current_uid());
 
-       if (!audit_enabled) {
+       if (!audit_enabled && msg_type != AUDIT_USER_AVC) {
                *ab = NULL;
                return rc;
        }
@@ -644,11 +645,22 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
        if (err)
                return err;
 
+       /* As soon as there's any sign of userspace auditd,
+        * start kauditd to talk to it */
+       if (!kauditd_task) {
+               kauditd_task = kthread_run(kauditd_thread, NULL, "kauditd");
+               if (IS_ERR(kauditd_task)) {
+                       err = PTR_ERR(kauditd_task);
+                       kauditd_task = NULL;
+                       return err;
+               }
+       }
        seq  = nlh->nlmsg_seq;
        data = nlmsg_data(nlh);
 
        switch (msg_type) {
        case AUDIT_GET:
+               status_set.mask          = 0;
                status_set.enabled       = audit_enabled;
                status_set.failure       = audit_failure;
                status_set.pid           = audit_pid;
@@ -660,7 +672,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                                 &status_set, sizeof(status_set));
                break;
        case AUDIT_SET:
-               if (nlh->nlmsg_len < sizeof(struct audit_status))
+               if (nlmsg_len(nlh) < sizeof(struct audit_status))
                        return -EINVAL;
                status_get   = (struct audit_status *)data;
                if (status_get->mask & AUDIT_STATUS_ENABLED) {
@@ -822,7 +834,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 
                memset(&s, 0, sizeof(s));
                /* guard against past and future API changes */
-               memcpy(&s, data, min(sizeof(s), (size_t)nlh->nlmsg_len));
+               memcpy(&s, data, min_t(size_t, sizeof(s), nlmsg_len(nlh)));
                if ((s.enabled != 0 && s.enabled != 1) ||
                    (s.log_passwd != 0 && s.log_passwd != 1))
                        return -EINVAL;
@@ -849,7 +861,7 @@ static void audit_receive_skb(struct sk_buff *skb)
 {
        struct nlmsghdr *nlh;
        /*
-        * len MUST be signed for NLMSG_NEXT to be able to dec it below 0
+        * len MUST be signed for nlmsg_next to be able to dec it below 0
         * if the nlmsg_len was not aligned
         */
        int len;
@@ -858,13 +870,13 @@ static void audit_receive_skb(struct sk_buff *skb)
        nlh = nlmsg_hdr(skb);
        len = skb->len;
 
-       while (NLMSG_OK(nlh, len)) {
+       while (nlmsg_ok(nlh, len)) {
                err = audit_receive_msg(skb, nlh);
                /* if err or if this message says it wants a response */
                if (err || (nlh->nlmsg_flags & NLM_F_ACK))
                        netlink_ack(skb, nlh, err);
 
-               nlh = NLMSG_NEXT(nlh, len);
+               nlh = nlmsg_next(nlh, &len);
        }
 }
 
@@ -895,10 +907,6 @@ static int __init audit_init(void)
        else
                audit_sock->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT;
 
-       kauditd_task = kthread_run(kauditd_thread, NULL, "kauditd");
-       if (IS_ERR(kauditd_task))
-               return PTR_ERR(kauditd_task);
-
        skb_queue_head_init(&audit_skb_queue);
        skb_queue_head_init(&audit_skb_hold_queue);
        audit_initialized = AUDIT_INITIALIZED;
@@ -1050,7 +1058,7 @@ static inline void audit_get_stamp(struct audit_context *ctx,
 static void wait_for_auditd(unsigned long sleep_time)
 {
        DECLARE_WAITQUEUE(wait, current);
-       set_current_state(TASK_INTERRUPTIBLE);
+       set_current_state(TASK_UNINTERRUPTIBLE);
        add_wait_queue(&audit_backlog_wait, &wait);
 
        if (audit_backlog_limit &&
@@ -1111,9 +1119,10 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask,
 
                        sleep_time = timeout_start + audit_backlog_wait_time -
                                        jiffies;
-                       if ((long)sleep_time > 0)
+                       if ((long)sleep_time > 0) {
                                wait_for_auditd(sleep_time);
-                       continue;
+                               continue;
+                       }
                }
                if (audit_rate_check() && printk_ratelimit())
                        printk(KERN_WARNING
@@ -1127,6 +1136,8 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask,
                return NULL;
        }
 
+       audit_backlog_wait_time = AUDIT_BACKLOG_WAIT_TIME;
+
        ab = audit_buffer_alloc(ctx, gfp_mask, type);
        if (!ab) {
                audit_log_lost("out of memory in audit_log_start");
@@ -1382,7 +1393,7 @@ void audit_log_session_info(struct audit_buffer *ab)
        u32 sessionid = audit_get_sessionid(current);
        uid_t auid = from_kuid(&init_user_ns, audit_get_loginuid(current));
 
-       audit_log_format(ab, "auid=%u ses=%u\n", auid, sessionid);
+       audit_log_format(ab, " auid=%u ses=%u\n", auid, sessionid);
 }
 
 void audit_log_key(struct audit_buffer *ab, char *key)
@@ -1401,7 +1412,7 @@ void audit_log_cap(struct audit_buffer *ab, char *prefix, kernel_cap_t *cap)
        audit_log_format(ab, " %s=", prefix);
        CAP_FOR_EACH_U32(i) {
                audit_log_format(ab, "%08x",
-                                cap->cap[(_KERNEL_CAPABILITY_U32S-1) - i]);
+                                cap->cap[CAP_LAST_U32 - i]);
        }
 }
 
@@ -1529,6 +1540,26 @@ void audit_log_name(struct audit_context *context, struct audit_names *n,
                }
        }
 
+       /* log the audit_names record type */
+       audit_log_format(ab, " nametype=");
+       switch(n->type) {
+       case AUDIT_TYPE_NORMAL:
+               audit_log_format(ab, "NORMAL");
+               break;
+       case AUDIT_TYPE_PARENT:
+               audit_log_format(ab, "PARENT");
+               break;
+       case AUDIT_TYPE_CHILD_DELETE:
+               audit_log_format(ab, "DELETE");
+               break;
+       case AUDIT_TYPE_CHILD_CREATE:
+               audit_log_format(ab, "CREATE");
+               break;
+       default:
+               audit_log_format(ab, "UNKNOWN");
+               break;
+       }
+
        audit_log_fcaps(ab, n);
        audit_log_end(ab);
 }
@@ -1661,7 +1692,7 @@ void audit_log_end(struct audit_buffer *ab)
                audit_log_lost("rate limit exceeded");
        } else {
                struct nlmsghdr *nlh = nlmsg_hdr(ab->skb);
-               nlh->nlmsg_len = ab->skb->len - NLMSG_SPACE(0);
+               nlh->nlmsg_len = ab->skb->len - NLMSG_HDRLEN;
 
                if (audit_pid) {
                        skb_queue_tail(&audit_skb_queue, ab->skb);