aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/audit.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2007-07-22 08:04:18 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2007-10-21 02:37:45 -0400
commit74c3cbe33bc077ac1159cadfea608b501e100344 (patch)
tree4c4023caa4e15d19780255fa5880df3d36eb292c /kernel/audit.c
parent455434d450a358ac5bcf3fc58f8913d13c544622 (diff)
[PATCH] audit: watching subtrees
New kind of audit rule predicates: "object is visible in given subtree". The part that can be sanely implemented, that is. Limitations: * if you have hardlink from outside of tree, you'd better watch it too (or just watch the object itself, obviously) * if you mount something under a watched tree, tell audit that new chunk should be added to watched subtrees * if you umount something in a watched tree and it's still mounted elsewhere, you will get matches on events happening there. New command tells audit to recalculate the trees, trimming such sources of false positives. Note that it's _not_ about path - if something mounted in several places (multiple mount, bindings, different namespaces, etc.), the match does _not_ depend on which one we are using for access. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'kernel/audit.c')
-rw-r--r--kernel/audit.c87
1 files changed, 87 insertions, 0 deletions
diff --git a/kernel/audit.c b/kernel/audit.c
index 6977ea57a7e2..f93c2713017d 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -468,6 +468,21 @@ int audit_send_list(void *_dest)
468 return 0; 468 return 0;
469} 469}
470 470
471#ifdef CONFIG_AUDIT_TREE
472static int prune_tree_thread(void *unused)
473{
474 mutex_lock(&audit_cmd_mutex);
475 audit_prune_trees();
476 mutex_unlock(&audit_cmd_mutex);
477 return 0;
478}
479
480void audit_schedule_prune(void)
481{
482 kthread_run(prune_tree_thread, NULL, "audit_prune_tree");
483}
484#endif
485
471struct sk_buff *audit_make_reply(int pid, int seq, int type, int done, 486struct sk_buff *audit_make_reply(int pid, int seq, int type, int done,
472 int multi, void *payload, int size) 487 int multi, void *payload, int size)
473{ 488{
@@ -540,6 +555,8 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type)
540 case AUDIT_SIGNAL_INFO: 555 case AUDIT_SIGNAL_INFO:
541 case AUDIT_TTY_GET: 556 case AUDIT_TTY_GET:
542 case AUDIT_TTY_SET: 557 case AUDIT_TTY_SET:
558 case AUDIT_TRIM:
559 case AUDIT_MAKE_EQUIV:
543 if (security_netlink_recv(skb, CAP_AUDIT_CONTROL)) 560 if (security_netlink_recv(skb, CAP_AUDIT_CONTROL))
544 err = -EPERM; 561 err = -EPERM;
545 break; 562 break;
@@ -756,6 +773,76 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
756 uid, seq, data, nlmsg_len(nlh), 773 uid, seq, data, nlmsg_len(nlh),
757 loginuid, sid); 774 loginuid, sid);
758 break; 775 break;
776 case AUDIT_TRIM:
777 audit_trim_trees();
778 ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
779 if (!ab)
780 break;
781 audit_log_format(ab, "auid=%u", loginuid);
782 if (sid) {
783 u32 len;
784 ctx = NULL;
785 if (selinux_sid_to_string(sid, &ctx, &len))
786 audit_log_format(ab, " ssid=%u", sid);
787 else
788 audit_log_format(ab, " subj=%s", ctx);
789 kfree(ctx);
790 }
791 audit_log_format(ab, " op=trim res=1");
792 audit_log_end(ab);
793 break;
794 case AUDIT_MAKE_EQUIV: {
795 void *bufp = data;
796 u32 sizes[2];
797 size_t len = nlmsg_len(nlh);
798 char *old, *new;
799
800 err = -EINVAL;
801 if (len < 2 * sizeof(u32))
802 break;
803 memcpy(sizes, bufp, 2 * sizeof(u32));
804 bufp += 2 * sizeof(u32);
805 len -= 2 * sizeof(u32);
806 old = audit_unpack_string(&bufp, &len, sizes[0]);
807 if (IS_ERR(old)) {
808 err = PTR_ERR(old);
809 break;
810 }
811 new = audit_unpack_string(&bufp, &len, sizes[1]);
812 if (IS_ERR(new)) {
813 err = PTR_ERR(new);
814 kfree(old);
815 break;
816 }
817 /* OK, here comes... */
818 err = audit_tag_tree(old, new);
819
820 ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
821 if (!ab) {
822 kfree(old);
823 kfree(new);
824 break;
825 }
826 audit_log_format(ab, "auid=%u", loginuid);
827 if (sid) {
828 u32 len;
829 ctx = NULL;
830 if (selinux_sid_to_string(sid, &ctx, &len))
831 audit_log_format(ab, " ssid=%u", sid);
832 else
833 audit_log_format(ab, " subj=%s", ctx);
834 kfree(ctx);
835 }
836 audit_log_format(ab, " op=make_equiv old=");
837 audit_log_untrustedstring(ab, old);
838 audit_log_format(ab, " new=");
839 audit_log_untrustedstring(ab, new);
840 audit_log_format(ab, " res=%d", !err);
841 audit_log_end(ab);
842 kfree(old);
843 kfree(new);
844 break;
845 }
759 case AUDIT_SIGNAL_INFO: 846 case AUDIT_SIGNAL_INFO:
760 err = selinux_sid_to_string(audit_sig_sid, &ctx, &len); 847 err = selinux_sid_to_string(audit_sig_sid, &ctx, &len);
761 if (err) 848 if (err)