diff options
-rw-r--r-- | kernel/audit.c | 47 | ||||
-rw-r--r-- | kernel/audit.h | 3 | ||||
-rw-r--r-- | kernel/audit_tree.c | 88 | ||||
-rw-r--r-- | kernel/auditsc.c | 9 |
4 files changed, 94 insertions, 53 deletions
diff --git a/kernel/audit.c b/kernel/audit.c index 72ab759a0b43..ab5745ddf962 100644 --- a/kernel/audit.c +++ b/kernel/audit.c | |||
@@ -43,6 +43,7 @@ | |||
43 | 43 | ||
44 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | 44 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
45 | 45 | ||
46 | #include <linux/file.h> | ||
46 | #include <linux/init.h> | 47 | #include <linux/init.h> |
47 | #include <linux/types.h> | 48 | #include <linux/types.h> |
48 | #include <linux/atomic.h> | 49 | #include <linux/atomic.h> |
@@ -107,6 +108,7 @@ static u32 audit_rate_limit; | |||
107 | * When set to zero, this means unlimited. */ | 108 | * When set to zero, this means unlimited. */ |
108 | static u32 audit_backlog_limit = 64; | 109 | static u32 audit_backlog_limit = 64; |
109 | #define AUDIT_BACKLOG_WAIT_TIME (60 * HZ) | 110 | #define AUDIT_BACKLOG_WAIT_TIME (60 * HZ) |
111 | static u32 audit_backlog_wait_time_master = AUDIT_BACKLOG_WAIT_TIME; | ||
110 | static u32 audit_backlog_wait_time = AUDIT_BACKLOG_WAIT_TIME; | 112 | static u32 audit_backlog_wait_time = AUDIT_BACKLOG_WAIT_TIME; |
111 | static u32 audit_backlog_wait_overflow = 0; | 113 | static u32 audit_backlog_wait_overflow = 0; |
112 | 114 | ||
@@ -338,13 +340,13 @@ static int audit_set_backlog_limit(u32 limit) | |||
338 | static int audit_set_backlog_wait_time(u32 timeout) | 340 | static int audit_set_backlog_wait_time(u32 timeout) |
339 | { | 341 | { |
340 | return audit_do_config_change("audit_backlog_wait_time", | 342 | return audit_do_config_change("audit_backlog_wait_time", |
341 | &audit_backlog_wait_time, timeout); | 343 | &audit_backlog_wait_time_master, timeout); |
342 | } | 344 | } |
343 | 345 | ||
344 | static int audit_set_enabled(u32 state) | 346 | static int audit_set_enabled(u32 state) |
345 | { | 347 | { |
346 | int rc; | 348 | int rc; |
347 | if (state < AUDIT_OFF || state > AUDIT_LOCKED) | 349 | if (state > AUDIT_LOCKED) |
348 | return -EINVAL; | 350 | return -EINVAL; |
349 | 351 | ||
350 | rc = audit_do_config_change("audit_enabled", &audit_enabled, state); | 352 | rc = audit_do_config_change("audit_enabled", &audit_enabled, state); |
@@ -663,7 +665,7 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type) | |||
663 | case AUDIT_MAKE_EQUIV: | 665 | case AUDIT_MAKE_EQUIV: |
664 | /* Only support auditd and auditctl in initial pid namespace | 666 | /* Only support auditd and auditctl in initial pid namespace |
665 | * for now. */ | 667 | * for now. */ |
666 | if ((task_active_pid_ns(current) != &init_pid_ns)) | 668 | if (task_active_pid_ns(current) != &init_pid_ns) |
667 | return -EPERM; | 669 | return -EPERM; |
668 | 670 | ||
669 | if (!netlink_capable(skb, CAP_AUDIT_CONTROL)) | 671 | if (!netlink_capable(skb, CAP_AUDIT_CONTROL)) |
@@ -834,7 +836,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
834 | s.lost = atomic_read(&audit_lost); | 836 | s.lost = atomic_read(&audit_lost); |
835 | s.backlog = skb_queue_len(&audit_skb_queue); | 837 | s.backlog = skb_queue_len(&audit_skb_queue); |
836 | s.feature_bitmap = AUDIT_FEATURE_BITMAP_ALL; | 838 | s.feature_bitmap = AUDIT_FEATURE_BITMAP_ALL; |
837 | s.backlog_wait_time = audit_backlog_wait_time; | 839 | s.backlog_wait_time = audit_backlog_wait_time_master; |
838 | audit_send_reply(skb, seq, AUDIT_GET, 0, 0, &s, sizeof(s)); | 840 | audit_send_reply(skb, seq, AUDIT_GET, 0, 0, &s, sizeof(s)); |
839 | break; | 841 | break; |
840 | } | 842 | } |
@@ -877,8 +879,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
877 | if (s.mask & AUDIT_STATUS_BACKLOG_WAIT_TIME) { | 879 | if (s.mask & AUDIT_STATUS_BACKLOG_WAIT_TIME) { |
878 | if (sizeof(s) > (size_t)nlh->nlmsg_len) | 880 | if (sizeof(s) > (size_t)nlh->nlmsg_len) |
879 | return -EINVAL; | 881 | return -EINVAL; |
880 | if (s.backlog_wait_time < 0 || | 882 | if (s.backlog_wait_time > 10*AUDIT_BACKLOG_WAIT_TIME) |
881 | s.backlog_wait_time > 10*AUDIT_BACKLOG_WAIT_TIME) | ||
882 | return -EINVAL; | 883 | return -EINVAL; |
883 | err = audit_set_backlog_wait_time(s.backlog_wait_time); | 884 | err = audit_set_backlog_wait_time(s.backlog_wait_time); |
884 | if (err < 0) | 885 | if (err < 0) |
@@ -1385,7 +1386,8 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask, | |||
1385 | return NULL; | 1386 | return NULL; |
1386 | } | 1387 | } |
1387 | 1388 | ||
1388 | audit_backlog_wait_time = AUDIT_BACKLOG_WAIT_TIME; | 1389 | if (!reserve) |
1390 | audit_backlog_wait_time = audit_backlog_wait_time_master; | ||
1389 | 1391 | ||
1390 | ab = audit_buffer_alloc(ctx, gfp_mask, type); | 1392 | ab = audit_buffer_alloc(ctx, gfp_mask, type); |
1391 | if (!ab) { | 1393 | if (!ab) { |
@@ -1759,7 +1761,7 @@ void audit_log_name(struct audit_context *context, struct audit_names *n, | |||
1759 | } else | 1761 | } else |
1760 | audit_log_format(ab, " name=(null)"); | 1762 | audit_log_format(ab, " name=(null)"); |
1761 | 1763 | ||
1762 | if (n->ino != (unsigned long)-1) { | 1764 | if (n->ino != (unsigned long)-1) |
1763 | audit_log_format(ab, " inode=%lu" | 1765 | audit_log_format(ab, " inode=%lu" |
1764 | " dev=%02x:%02x mode=%#ho" | 1766 | " dev=%02x:%02x mode=%#ho" |
1765 | " ouid=%u ogid=%u rdev=%02x:%02x", | 1767 | " ouid=%u ogid=%u rdev=%02x:%02x", |
@@ -1771,7 +1773,6 @@ void audit_log_name(struct audit_context *context, struct audit_names *n, | |||
1771 | from_kgid(&init_user_ns, n->gid), | 1773 | from_kgid(&init_user_ns, n->gid), |
1772 | MAJOR(n->rdev), | 1774 | MAJOR(n->rdev), |
1773 | MINOR(n->rdev)); | 1775 | MINOR(n->rdev)); |
1774 | } | ||
1775 | if (n->osid != 0) { | 1776 | if (n->osid != 0) { |
1776 | char *ctx = NULL; | 1777 | char *ctx = NULL; |
1777 | u32 len; | 1778 | u32 len; |
@@ -1838,11 +1839,29 @@ error_path: | |||
1838 | } | 1839 | } |
1839 | EXPORT_SYMBOL(audit_log_task_context); | 1840 | EXPORT_SYMBOL(audit_log_task_context); |
1840 | 1841 | ||
1842 | void audit_log_d_path_exe(struct audit_buffer *ab, | ||
1843 | struct mm_struct *mm) | ||
1844 | { | ||
1845 | struct file *exe_file; | ||
1846 | |||
1847 | if (!mm) | ||
1848 | goto out_null; | ||
1849 | |||
1850 | exe_file = get_mm_exe_file(mm); | ||
1851 | if (!exe_file) | ||
1852 | goto out_null; | ||
1853 | |||
1854 | audit_log_d_path(ab, " exe=", &exe_file->f_path); | ||
1855 | fput(exe_file); | ||
1856 | return; | ||
1857 | out_null: | ||
1858 | audit_log_format(ab, " exe=(null)"); | ||
1859 | } | ||
1860 | |||
1841 | void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk) | 1861 | void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk) |
1842 | { | 1862 | { |
1843 | const struct cred *cred; | 1863 | const struct cred *cred; |
1844 | char comm[sizeof(tsk->comm)]; | 1864 | char comm[sizeof(tsk->comm)]; |
1845 | struct mm_struct *mm = tsk->mm; | ||
1846 | char *tty; | 1865 | char *tty; |
1847 | 1866 | ||
1848 | if (!ab) | 1867 | if (!ab) |
@@ -1878,13 +1897,7 @@ void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk) | |||
1878 | audit_log_format(ab, " comm="); | 1897 | audit_log_format(ab, " comm="); |
1879 | audit_log_untrustedstring(ab, get_task_comm(comm, tsk)); | 1898 | audit_log_untrustedstring(ab, get_task_comm(comm, tsk)); |
1880 | 1899 | ||
1881 | if (mm) { | 1900 | audit_log_d_path_exe(ab, tsk->mm); |
1882 | down_read(&mm->mmap_sem); | ||
1883 | if (mm->exe_file) | ||
1884 | audit_log_d_path(ab, " exe=", &mm->exe_file->f_path); | ||
1885 | up_read(&mm->mmap_sem); | ||
1886 | } else | ||
1887 | audit_log_format(ab, " exe=(null)"); | ||
1888 | audit_log_task_context(ab); | 1901 | audit_log_task_context(ab); |
1889 | } | 1902 | } |
1890 | EXPORT_SYMBOL(audit_log_task_info); | 1903 | EXPORT_SYMBOL(audit_log_task_info); |
diff --git a/kernel/audit.h b/kernel/audit.h index 1caa0d345d90..d641f9bb3ed0 100644 --- a/kernel/audit.h +++ b/kernel/audit.h | |||
@@ -257,6 +257,9 @@ extern struct list_head audit_filter_list[]; | |||
257 | 257 | ||
258 | extern struct audit_entry *audit_dupe_rule(struct audit_krule *old); | 258 | extern struct audit_entry *audit_dupe_rule(struct audit_krule *old); |
259 | 259 | ||
260 | extern void audit_log_d_path_exe(struct audit_buffer *ab, | ||
261 | struct mm_struct *mm); | ||
262 | |||
260 | /* audit watch functions */ | 263 | /* audit watch functions */ |
261 | #ifdef CONFIG_AUDIT_WATCH | 264 | #ifdef CONFIG_AUDIT_WATCH |
262 | extern void audit_put_watch(struct audit_watch *watch); | 265 | extern void audit_put_watch(struct audit_watch *watch); |
diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c index 2e0c97427b33..71fd1f289885 100644 --- a/kernel/audit_tree.c +++ b/kernel/audit_tree.c | |||
@@ -37,6 +37,7 @@ struct audit_chunk { | |||
37 | 37 | ||
38 | static LIST_HEAD(tree_list); | 38 | static LIST_HEAD(tree_list); |
39 | static LIST_HEAD(prune_list); | 39 | static LIST_HEAD(prune_list); |
40 | static struct task_struct *prune_thread; | ||
40 | 41 | ||
41 | /* | 42 | /* |
42 | * One struct chunk is attached to each inode of interest. | 43 | * One struct chunk is attached to each inode of interest. |
@@ -651,6 +652,57 @@ static int tag_mount(struct vfsmount *mnt, void *arg) | |||
651 | return tag_chunk(mnt->mnt_root->d_inode, arg); | 652 | return tag_chunk(mnt->mnt_root->d_inode, arg); |
652 | } | 653 | } |
653 | 654 | ||
655 | /* | ||
656 | * That gets run when evict_chunk() ends up needing to kill audit_tree. | ||
657 | * Runs from a separate thread. | ||
658 | */ | ||
659 | static int prune_tree_thread(void *unused) | ||
660 | { | ||
661 | for (;;) { | ||
662 | set_current_state(TASK_INTERRUPTIBLE); | ||
663 | if (list_empty(&prune_list)) | ||
664 | schedule(); | ||
665 | __set_current_state(TASK_RUNNING); | ||
666 | |||
667 | mutex_lock(&audit_cmd_mutex); | ||
668 | mutex_lock(&audit_filter_mutex); | ||
669 | |||
670 | while (!list_empty(&prune_list)) { | ||
671 | struct audit_tree *victim; | ||
672 | |||
673 | victim = list_entry(prune_list.next, | ||
674 | struct audit_tree, list); | ||
675 | list_del_init(&victim->list); | ||
676 | |||
677 | mutex_unlock(&audit_filter_mutex); | ||
678 | |||
679 | prune_one(victim); | ||
680 | |||
681 | mutex_lock(&audit_filter_mutex); | ||
682 | } | ||
683 | |||
684 | mutex_unlock(&audit_filter_mutex); | ||
685 | mutex_unlock(&audit_cmd_mutex); | ||
686 | } | ||
687 | return 0; | ||
688 | } | ||
689 | |||
690 | static int audit_launch_prune(void) | ||
691 | { | ||
692 | if (prune_thread) | ||
693 | return 0; | ||
694 | prune_thread = kthread_create(prune_tree_thread, NULL, | ||
695 | "audit_prune_tree"); | ||
696 | if (IS_ERR(prune_thread)) { | ||
697 | pr_err("cannot start thread audit_prune_tree"); | ||
698 | prune_thread = NULL; | ||
699 | return -ENOMEM; | ||
700 | } else { | ||
701 | wake_up_process(prune_thread); | ||
702 | return 0; | ||
703 | } | ||
704 | } | ||
705 | |||
654 | /* called with audit_filter_mutex */ | 706 | /* called with audit_filter_mutex */ |
655 | int audit_add_tree_rule(struct audit_krule *rule) | 707 | int audit_add_tree_rule(struct audit_krule *rule) |
656 | { | 708 | { |
@@ -674,6 +726,12 @@ int audit_add_tree_rule(struct audit_krule *rule) | |||
674 | /* do not set rule->tree yet */ | 726 | /* do not set rule->tree yet */ |
675 | mutex_unlock(&audit_filter_mutex); | 727 | mutex_unlock(&audit_filter_mutex); |
676 | 728 | ||
729 | if (unlikely(!prune_thread)) { | ||
730 | err = audit_launch_prune(); | ||
731 | if (err) | ||
732 | goto Err; | ||
733 | } | ||
734 | |||
677 | err = kern_path(tree->pathname, 0, &path); | 735 | err = kern_path(tree->pathname, 0, &path); |
678 | if (err) | 736 | if (err) |
679 | goto Err; | 737 | goto Err; |
@@ -811,36 +869,10 @@ int audit_tag_tree(char *old, char *new) | |||
811 | return failed; | 869 | return failed; |
812 | } | 870 | } |
813 | 871 | ||
814 | /* | ||
815 | * That gets run when evict_chunk() ends up needing to kill audit_tree. | ||
816 | * Runs from a separate thread. | ||
817 | */ | ||
818 | static int prune_tree_thread(void *unused) | ||
819 | { | ||
820 | mutex_lock(&audit_cmd_mutex); | ||
821 | mutex_lock(&audit_filter_mutex); | ||
822 | |||
823 | while (!list_empty(&prune_list)) { | ||
824 | struct audit_tree *victim; | ||
825 | |||
826 | victim = list_entry(prune_list.next, struct audit_tree, list); | ||
827 | list_del_init(&victim->list); | ||
828 | |||
829 | mutex_unlock(&audit_filter_mutex); | ||
830 | |||
831 | prune_one(victim); | ||
832 | |||
833 | mutex_lock(&audit_filter_mutex); | ||
834 | } | ||
835 | |||
836 | mutex_unlock(&audit_filter_mutex); | ||
837 | mutex_unlock(&audit_cmd_mutex); | ||
838 | return 0; | ||
839 | } | ||
840 | 872 | ||
841 | static void audit_schedule_prune(void) | 873 | static void audit_schedule_prune(void) |
842 | { | 874 | { |
843 | kthread_run(prune_tree_thread, NULL, "audit_prune_tree"); | 875 | wake_up_process(prune_thread); |
844 | } | 876 | } |
845 | 877 | ||
846 | /* | 878 | /* |
@@ -907,9 +939,9 @@ static void evict_chunk(struct audit_chunk *chunk) | |||
907 | for (n = 0; n < chunk->count; n++) | 939 | for (n = 0; n < chunk->count; n++) |
908 | list_del_init(&chunk->owners[n].list); | 940 | list_del_init(&chunk->owners[n].list); |
909 | spin_unlock(&hash_lock); | 941 | spin_unlock(&hash_lock); |
942 | mutex_unlock(&audit_filter_mutex); | ||
910 | if (need_prune) | 943 | if (need_prune) |
911 | audit_schedule_prune(); | 944 | audit_schedule_prune(); |
912 | mutex_unlock(&audit_filter_mutex); | ||
913 | } | 945 | } |
914 | 946 | ||
915 | static int audit_tree_handle_event(struct fsnotify_group *group, | 947 | static int audit_tree_handle_event(struct fsnotify_group *group, |
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index dc4ae70a7413..84c74d08c62b 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c | |||
@@ -2361,7 +2361,6 @@ static void audit_log_task(struct audit_buffer *ab) | |||
2361 | kuid_t auid, uid; | 2361 | kuid_t auid, uid; |
2362 | kgid_t gid; | 2362 | kgid_t gid; |
2363 | unsigned int sessionid; | 2363 | unsigned int sessionid; |
2364 | struct mm_struct *mm = current->mm; | ||
2365 | char comm[sizeof(current->comm)]; | 2364 | char comm[sizeof(current->comm)]; |
2366 | 2365 | ||
2367 | auid = audit_get_loginuid(current); | 2366 | auid = audit_get_loginuid(current); |
@@ -2376,13 +2375,7 @@ static void audit_log_task(struct audit_buffer *ab) | |||
2376 | audit_log_task_context(ab); | 2375 | audit_log_task_context(ab); |
2377 | audit_log_format(ab, " pid=%d comm=", task_pid_nr(current)); | 2376 | audit_log_format(ab, " pid=%d comm=", task_pid_nr(current)); |
2378 | audit_log_untrustedstring(ab, get_task_comm(comm, current)); | 2377 | audit_log_untrustedstring(ab, get_task_comm(comm, current)); |
2379 | if (mm) { | 2378 | audit_log_d_path_exe(ab, current->mm); |
2380 | down_read(&mm->mmap_sem); | ||
2381 | if (mm->exe_file) | ||
2382 | audit_log_d_path(ab, " exe=", &mm->exe_file->f_path); | ||
2383 | up_read(&mm->mmap_sem); | ||
2384 | } else | ||
2385 | audit_log_format(ab, " exe=(null)"); | ||
2386 | } | 2379 | } |
2387 | 2380 | ||
2388 | /** | 2381 | /** |