X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=kernel%2Faudit.c;h=f93c2713017da93b90e5e8d67d029c1b754ffaa0;hb=54561783ee99d73a086f3abbda3e44f87f6bf65b;hp=2924251a6547bebb25d952dc64ea5590848b1bce;hpb=408af0dab78ef4145203b849d6bfd3195f6e3ec9;p=linux-2.6 diff --git a/kernel/audit.c b/kernel/audit.c index 2924251a65..f93c271301 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -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, ""); - } 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;