[Bluetooth] Retrieve L2CAP features mask on connection setup
[pandora-kernel.git] / kernel / audit.c
index 2924251..f93c271 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;
@@ -1005,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)
@@ -1056,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
@@ -1319,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);
 }
@@ -1365,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;