Merge branch 'for-2.6.24' of master.kernel.org:/pub/scm/linux/kernel/git/jwboyer...
[sfrench/cifs-2.6.git] / kernel / audit.c
index eb0f9165b401bcf4375baf4b233ab6a1401b448d..f93c2713017da93b90e5e8d67d029c1b754ffaa0 100644 (file)
@@ -468,6 +468,21 @@ int audit_send_list(void *_dest)
        return 0;
 }
 
+#ifdef CONFIG_AUDIT_TREE
+static int prune_tree_thread(void *unused)
+{
+       mutex_lock(&audit_cmd_mutex);
+       audit_prune_trees();
+       mutex_unlock(&audit_cmd_mutex);
+       return 0;
+}
+
+void audit_schedule_prune(void)
+{
+       kthread_run(prune_tree_thread, NULL, "audit_prune_tree");
+}
+#endif
+
 struct sk_buff *audit_make_reply(int pid, int seq, int type, int done,
                                 int multi, void *payload, int size)
 {
@@ -540,6 +555,8 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type)
        case AUDIT_SIGNAL_INFO:
        case AUDIT_TTY_GET:
        case AUDIT_TTY_SET:
+       case AUDIT_TRIM:
+       case AUDIT_MAKE_EQUIV:
                if (security_netlink_recv(skb, CAP_AUDIT_CONTROL))
                        err = -EPERM;
                break;
@@ -664,11 +681,11 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                                if (sid) {
                                        if (selinux_sid_to_string(
                                                        sid, &ctx, &len)) {
-                                               audit_log_format(ab, 
+                                               audit_log_format(ab,
                                                        " ssid=%u", sid);
                                                /* Maybe call audit_panic? */
                                        } else
-                                               audit_log_format(ab, 
+                                               audit_log_format(ab,
                                                        " subj=%s", ctx);
                                        kfree(ctx);
                                }
@@ -756,6 +773,76 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                                           uid, seq, data, nlmsg_len(nlh),
                                           loginuid, sid);
                break;
+       case AUDIT_TRIM:
+               audit_trim_trees();
+               ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
+               if (!ab)
+                       break;
+               audit_log_format(ab, "auid=%u", loginuid);
+               if (sid) {
+                       u32 len;
+                       ctx = NULL;
+                       if (selinux_sid_to_string(sid, &ctx, &len))
+                               audit_log_format(ab, " ssid=%u", sid);
+                       else
+                               audit_log_format(ab, " subj=%s", ctx);
+                       kfree(ctx);
+               }
+               audit_log_format(ab, " op=trim res=1");
+               audit_log_end(ab);
+               break;
+       case AUDIT_MAKE_EQUIV: {
+               void *bufp = data;
+               u32 sizes[2];
+               size_t len = nlmsg_len(nlh);
+               char *old, *new;
+
+               err = -EINVAL;
+               if (len < 2 * sizeof(u32))
+                       break;
+               memcpy(sizes, bufp, 2 * sizeof(u32));
+               bufp += 2 * sizeof(u32);
+               len -= 2 * sizeof(u32);
+               old = audit_unpack_string(&bufp, &len, sizes[0]);
+               if (IS_ERR(old)) {
+                       err = PTR_ERR(old);
+                       break;
+               }
+               new = audit_unpack_string(&bufp, &len, sizes[1]);
+               if (IS_ERR(new)) {
+                       err = PTR_ERR(new);
+                       kfree(old);
+                       break;
+               }
+               /* OK, here comes... */
+               err = audit_tag_tree(old, new);
+
+               ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
+               if (!ab) {
+                       kfree(old);
+                       kfree(new);
+                       break;
+               }
+               audit_log_format(ab, "auid=%u", loginuid);
+               if (sid) {
+                       u32 len;
+                       ctx = NULL;
+                       if (selinux_sid_to_string(sid, &ctx, &len))
+                               audit_log_format(ab, " ssid=%u", sid);
+                       else
+                               audit_log_format(ab, " subj=%s", ctx);
+                       kfree(ctx);
+               }
+               audit_log_format(ab, " op=make_equiv old=");
+               audit_log_untrustedstring(ab, old);
+               audit_log_format(ab, " new=");
+               audit_log_untrustedstring(ab, new);
+               audit_log_format(ab, " res=%d", !err);
+               audit_log_end(ab);
+               kfree(old);
+               kfree(new);
+               break;
+       }
        case AUDIT_SIGNAL_INFO:
                err = selinux_sid_to_string(audit_sig_sid, &ctx, &len);
                if (err)
@@ -769,7 +856,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                sig_data->pid = audit_sig_pid;
                memcpy(sig_data->ctx, ctx, len);
                kfree(ctx);
-               audit_send_reply(NETLINK_CB(skb).pid, seq, AUDIT_SIGNAL_INFO, 
+               audit_send_reply(NETLINK_CB(skb).pid, seq, AUDIT_SIGNAL_INFO,
                                0, 0, sig_data, sizeof(*sig_data) + len);
                kfree(sig_data);
                break;
@@ -847,18 +934,10 @@ static void audit_receive_skb(struct sk_buff *skb)
 }
 
 /* Receive messages from netlink socket. */
-static void audit_receive(struct sock *sk, int length)
+static void audit_receive(struct sk_buff  *skb)
 {
-       struct sk_buff  *skb;
-       unsigned int qlen;
-
        mutex_lock(&audit_cmd_mutex);
-
-       for (qlen = skb_queue_len(&sk->sk_receive_queue); qlen; qlen--) {
-               skb = skb_dequeue(&sk->sk_receive_queue);
-               audit_receive_skb(skb);
-               kfree_skb(skb);
-       }
+       audit_receive_skb(skb);
        mutex_unlock(&audit_cmd_mutex);
 }
 
@@ -876,8 +955,8 @@ static int __init audit_init(void)
 
        printk(KERN_INFO "audit: initializing netlink socket (%s)\n",
               audit_default ? "enabled" : "disabled");
-       audit_sock = netlink_kernel_create(NETLINK_AUDIT, 0, audit_receive,
-                                          NULL, THIS_MODULE);
+       audit_sock = netlink_kernel_create(&init_net, NETLINK_AUDIT, 0,
+                                          audit_receive, NULL, THIS_MODULE);
        if (!audit_sock)
                audit_panic("cannot initialize netlink socket");
        else
@@ -1013,7 +1092,7 @@ unsigned int audit_serial(void)
        return ret;
 }
 
-static inline void audit_get_stamp(struct audit_context *ctx, 
+static inline void audit_get_stamp(struct audit_context *ctx,
                                   struct timespec *t, unsigned int *serial)
 {
        if (ctx)
@@ -1064,7 +1143,7 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask,
        if (gfp_mask & __GFP_WAIT)
                reserve = 0;
        else
-               reserve = 5; /* Allow atomic callers to go up to five 
+               reserve = 5; /* Allow atomic callers to go up to five
                                entries over the normal backlog limit */
 
        while (audit_backlog_limit
@@ -1327,7 +1406,7 @@ void audit_log_d_path(struct audit_buffer *ab, const char *prefix,
        if (IS_ERR(p)) { /* Should never happen since we send PATH_MAX */
                /* FIXME: can we save some information here? */
                audit_log_format(ab, "<too long>");
-       } else 
+       } else
                audit_log_untrustedstring(ab, p);
        kfree(path);
 }
@@ -1373,7 +1452,7 @@ void audit_log_end(struct audit_buffer *ab)
  * audit_log_vformat, and audit_log_end.  It may be called
  * in any context.
  */
-void audit_log(struct audit_context *ctx, gfp_t gfp_mask, int type, 
+void audit_log(struct audit_context *ctx, gfp_t gfp_mask, int type,
               const char *fmt, ...)
 {
        struct audit_buffer *ab;