From 29c1372d6a9b872acf479ba2744e4e7f043981c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ondrej=20Mosn=C3=A1=C4=8Dek?= Date: Wed, 30 May 2018 10:45:24 +0200 Subject: audit: allow other filter list types for AUDIT_EXE This patch removes the restriction of the AUDIT_EXE field to only SYSCALL filter and teaches audit_filter to recognize this field. This makes it possible to write rule lists such as: auditctl -a exit,always [some general rule] # Filter out events with executable name /bin/exe1 or /bin/exe2: auditctl -a exclude,always -F exe=/bin/exe1 auditctl -a exclude,always -F exe=/bin/exe2 See: https://github.com/linux-audit/audit-kernel/issues/54 Signed-off-by: Ondrej Mosnacek Reviewed-by: Richard Guy Briggs Signed-off-by: Paul Moore --- kernel/auditfilter.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'kernel') diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index eaa320148d97..6db9847ca031 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c @@ -428,8 +428,6 @@ static int audit_field_valid(struct audit_entry *entry, struct audit_field *f) case AUDIT_EXE: if (f->op != Audit_not_equal && f->op != Audit_equal) return -EINVAL; - if (entry->rule.listnr != AUDIT_FILTER_EXIT) - return -EINVAL; break; } return 0; @@ -1360,6 +1358,11 @@ int audit_filter(int msgtype, unsigned int listtype) f->type, f->op, f->lsm_rule, NULL); } break; + case AUDIT_EXE: + result = audit_exe_compare(current, e->rule.exe); + if (f->op == Audit_not_equal) + result = !result; + break; default: goto unlock_and_return; } -- cgit v1.2.3 From 9b8753fffe7b3642688135f28aa8a0a0f45fd9ab Mon Sep 17 00:00:00 2001 From: Richard Guy Briggs Date: Thu, 31 May 2018 16:27:24 -0400 Subject: audit: tie SECCOMP records to syscall Since seccomp events are triggered by user activity, tie the SECCOMP record to the syscall record to collect all records from the same event. See: https://github.com/linux-audit/audit-kernel/issues/87 Signed-off-by: Richard Guy Briggs Signed-off-by: Paul Moore --- kernel/auditsc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'kernel') diff --git a/kernel/auditsc.c b/kernel/auditsc.c index ceb1c4596c51..fefb9e215cd0 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -2485,7 +2485,7 @@ void audit_seccomp(unsigned long syscall, long signr, int code) { struct audit_buffer *ab; - ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_SECCOMP); + ab = audit_log_start(audit_context(), GFP_KERNEL, AUDIT_SECCOMP); if (unlikely(!ab)) return; audit_log_task(ab); -- cgit v1.2.3 From d87de4a878e110d0061fb22726d37a54a281285d Mon Sep 17 00:00:00 2001 From: Richard Guy Briggs Date: Thu, 31 May 2018 16:28:12 -0400 Subject: audit: tie ANOM_ABEND records to syscall Since core dump events are triggered by user activity, tie the ANOM_ABEND record to the syscall record to collect all records from the same event. See: https://github.com/linux-audit/audit-kernel/issues/88 Signed-off-by: Richard Guy Briggs Signed-off-by: Paul Moore --- kernel/auditsc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'kernel') diff --git a/kernel/auditsc.c b/kernel/auditsc.c index fefb9e215cd0..5f0bd5ece578 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -2461,7 +2461,7 @@ void audit_core_dumps(long signr) if (signr == SIGQUIT) /* don't care for those */ return; - ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_ANOM_ABEND); + ab = audit_log_start(audit_context(), GFP_KERNEL, AUDIT_ANOM_ABEND); if (unlikely(!ab)) return; audit_log_task(ab); -- cgit v1.2.3 From af85d1772e31fed34165a1b3decef340cf4080c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ondrej=20Mosn=C3=A1=C4=8Dek?= Date: Tue, 5 Jun 2018 11:00:10 +0200 Subject: audit: Fix extended comparison of GID/EGID The audit_filter_rules() function in auditsc.c used the in_[e]group_p() functions to check GID/EGID match, but these functions use the current task's credentials, while the comparison should use the credentials of the task given to audit_filter_rules() as a parameter (tsk). Note that we can use group_search(cred->group_info, ...) as a replacement for both in_group_p and in_egroup_p as these functions only compare the parameter to cred->fsgid/egid and then call group_search. In fact, the usage of in_group_p was even more incorrect: it compares to cred->fsgid (which is usually equal to cred->egid) and not cred->gid. GitHub issue: https://github.com/linux-audit/audit-kernel/issues/82 Fixes: 37eebe39c973 ("audit: improve GID/EGID comparation logic") Signed-off-by: Ondrej Mosnacek Signed-off-by: Paul Moore --- kernel/auditsc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'kernel') diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 5f0bd5ece578..d762e0b8160e 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -494,20 +494,20 @@ static int audit_filter_rules(struct task_struct *tsk, result = audit_gid_comparator(cred->gid, f->op, f->gid); if (f->op == Audit_equal) { if (!result) - result = in_group_p(f->gid); + result = groups_search(cred->group_info, f->gid); } else if (f->op == Audit_not_equal) { if (result) - result = !in_group_p(f->gid); + result = !groups_search(cred->group_info, f->gid); } break; case AUDIT_EGID: result = audit_gid_comparator(cred->egid, f->op, f->gid); if (f->op == Audit_equal) { if (!result) - result = in_egroup_p(f->gid); + result = groups_search(cred->group_info, f->gid); } else if (f->op == Audit_not_equal) { if (result) - result = !in_egroup_p(f->gid); + result = !groups_search(cred->group_info, f->gid); } break; case AUDIT_SGID: -- cgit v1.2.3 From d904ac0320d3c4ff4e9d80e4294ca5dde803696f Mon Sep 17 00:00:00 2001 From: Richard Guy Briggs Date: Tue, 5 Jun 2018 11:45:07 -0400 Subject: audit: rename FILTER_TYPE to FILTER_EXCLUDE The AUDIT_FILTER_TYPE name is vague and misleading due to not describing where or when the filter is applied and obsolete due to its available filter fields having been expanded. Userspace has already renamed it from AUDIT_FILTER_TYPE to AUDIT_FILTER_EXCLUDE without checking if it already exists. The userspace maintainer assures that as long as it is set to the same value it will not be a problem since the userspace code does not treat compiler warnings as errors. If this policy changes then checks if it already exists can be added at the same time. See: https://github.com/linux-audit/audit-kernel/issues/89 Signed-off-by: Richard Guy Briggs Signed-off-by: Paul Moore --- kernel/audit.c | 2 +- kernel/auditfilter.c | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'kernel') diff --git a/kernel/audit.c b/kernel/audit.c index e7478cb58079..5c0a1d7b0c7b 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -1754,7 +1754,7 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask, if (audit_initialized != AUDIT_INITIALIZED) return NULL; - if (unlikely(!audit_filter(type, AUDIT_FILTER_TYPE))) + if (unlikely(!audit_filter(type, AUDIT_FILTER_EXCLUDE))) return NULL; /* NOTE: don't ever fail/sleep on these two conditions: diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index 6db9847ca031..bf309f2592c4 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c @@ -264,7 +264,7 @@ static inline struct audit_entry *audit_to_entry_common(struct audit_rule_data * case AUDIT_FILTER_TASK: #endif case AUDIT_FILTER_USER: - case AUDIT_FILTER_TYPE: + case AUDIT_FILTER_EXCLUDE: case AUDIT_FILTER_FS: ; } @@ -337,7 +337,7 @@ static int audit_field_valid(struct audit_entry *entry, struct audit_field *f) { switch(f->type) { case AUDIT_MSGTYPE: - if (entry->rule.listnr != AUDIT_FILTER_TYPE && + if (entry->rule.listnr != AUDIT_FILTER_EXCLUDE && entry->rule.listnr != AUDIT_FILTER_USER) return -EINVAL; break; @@ -929,7 +929,7 @@ static inline int audit_add_rule(struct audit_entry *entry) /* If any of these, don't count towards total */ switch(entry->rule.listnr) { case AUDIT_FILTER_USER: - case AUDIT_FILTER_TYPE: + case AUDIT_FILTER_EXCLUDE: case AUDIT_FILTER_FS: dont_count = 1; } @@ -1011,7 +1011,7 @@ int audit_del_rule(struct audit_entry *entry) /* If any of these, don't count towards total */ switch(entry->rule.listnr) { case AUDIT_FILTER_USER: - case AUDIT_FILTER_TYPE: + case AUDIT_FILTER_EXCLUDE: case AUDIT_FILTER_FS: dont_count = 1; } @@ -1372,7 +1372,7 @@ int audit_filter(int msgtype, unsigned int listtype) break; } if (result > 0) { - if (e->rule.action == AUDIT_NEVER || listtype == AUDIT_FILTER_TYPE) + if (e->rule.action == AUDIT_NEVER || listtype == AUDIT_FILTER_EXCLUDE) ret = 0; break; } -- cgit v1.2.3 From f7859590d97614815b35a755c8213dfb8f2766bd Mon Sep 17 00:00:00 2001 From: Richard Guy Briggs Date: Tue, 5 Jun 2018 19:20:39 -0400 Subject: audit: eliminate audit_enabled magic number comparison Remove comparison of audit_enabled to magic numbers outside of audit. Related: https://github.com/linux-audit/audit-kernel/issues/86 Signed-off-by: Richard Guy Briggs Signed-off-by: Paul Moore --- kernel/audit.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'kernel') diff --git a/kernel/audit.c b/kernel/audit.c index 5c0a1d7b0c7b..0f3222e4edde 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -83,9 +83,6 @@ #define AUDIT_INITIALIZED 1 static int audit_initialized; -#define AUDIT_OFF 0 -#define AUDIT_ON 1 -#define AUDIT_LOCKED 2 u32 audit_enabled = AUDIT_OFF; bool audit_ever_enabled = !!AUDIT_OFF; -- cgit v1.2.3 From 65a8766f5f50a5cd342f3d8f77a30917648ddb67 Mon Sep 17 00:00:00 2001 From: Richard Guy Briggs Date: Thu, 14 Jun 2018 16:20:05 -0400 Subject: audit: check audit_enabled in audit_tree_log_remove_rule() Respect the audit_enabled flag when printing tree rule config change records. See: https://github.com/linux-audit/audit-kernel/issues/50 Signed-off-by: Richard Guy Briggs [PM: tweak the subject line] Signed-off-by: Paul Moore --- kernel/audit_tree.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'kernel') diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c index c99ebaae5abc..9f6eaeb6919f 100644 --- a/kernel/audit_tree.c +++ b/kernel/audit_tree.c @@ -497,6 +497,8 @@ static void audit_tree_log_remove_rule(struct audit_krule *rule) { struct audit_buffer *ab; + if (!audit_enabled) + return; ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); if (unlikely(!ab)) return; -- cgit v1.2.3 From 4fa7f086993594e79f456a04656da2fcb5691209 Mon Sep 17 00:00:00 2001 From: Richard Guy Briggs Date: Thu, 14 Jun 2018 16:20:06 -0400 Subject: audit: simplify audit_enabled check in audit_watch_log_rule_change() Check the audit_enabled flag and bail immediately. This does not change the functionality, but brings the code format in line with similar checks in audit_tree_log_remove_rule(), audit_mark_log_rule_change(), and elsewhere in the audit code. See: https://github.com/linux-audit/audit-kernel/issues/50 Signed-off-by: Richard Guy Briggs [PM: tweaked subject line] Signed-off-by: Paul Moore --- kernel/audit_watch.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) (limited to 'kernel') diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c index c17c0c268436..6f249bdf2d84 100644 --- a/kernel/audit_watch.c +++ b/kernel/audit_watch.c @@ -238,20 +238,21 @@ out: static void audit_watch_log_rule_change(struct audit_krule *r, struct audit_watch *w, char *op) { - if (audit_enabled) { - struct audit_buffer *ab; - ab = audit_log_start(NULL, GFP_NOFS, AUDIT_CONFIG_CHANGE); - if (unlikely(!ab)) - return; - audit_log_format(ab, "auid=%u ses=%u op=%s", - from_kuid(&init_user_ns, audit_get_loginuid(current)), - audit_get_sessionid(current), op); - audit_log_format(ab, " path="); - audit_log_untrustedstring(ab, w->path); - audit_log_key(ab, r->filterkey); - audit_log_format(ab, " list=%d res=1", r->listnr); - audit_log_end(ab); - } + struct audit_buffer *ab; + + if (!audit_enabled) + return; + ab = audit_log_start(NULL, GFP_NOFS, AUDIT_CONFIG_CHANGE); + if (!ab) + return; + audit_log_format(ab, "auid=%u ses=%u op=%s", + from_kuid(&init_user_ns, audit_get_loginuid(current)), + audit_get_sessionid(current), op); + audit_log_format(ab, " path="); + audit_log_untrustedstring(ab, w->path); + audit_log_key(ab, r->filterkey); + audit_log_format(ab, " list=%d res=1", r->listnr); + audit_log_end(ab); } /* Update inode info in audit rules based on filesystem event. */ -- cgit v1.2.3 From c72051d5778a9c0e5df31d6553a6fa3507b3685c Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 18 Jun 2018 16:58:24 +0200 Subject: audit: use ktime_get_coarse_ts64() for time access The API got renamed for consistency with the other time accessors, this changes the audit caller as well. Signed-off-by: Arnd Bergmann Reviewed-by: Richard Guy Briggs Signed-off-by: Paul Moore --- kernel/audit.c | 2 +- kernel/auditsc.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'kernel') diff --git a/kernel/audit.c b/kernel/audit.c index 0f3222e4edde..e17bc697d11c 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -1721,7 +1721,7 @@ static inline void audit_get_stamp(struct audit_context *ctx, struct timespec64 *t, unsigned int *serial) { if (!ctx || !auditsc_get_stamp(ctx, t, serial)) { - *t = current_kernel_time64(); + ktime_get_coarse_ts64(t); *serial = audit_serial(); } } diff --git a/kernel/auditsc.c b/kernel/auditsc.c index d762e0b8160e..f6a0cb32d76e 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -1540,10 +1540,10 @@ void __audit_syscall_entry(int major, unsigned long a1, unsigned long a2, context->argv[2] = a3; context->argv[3] = a4; context->serial = 0; - context->ctime = current_kernel_time64(); context->in_syscall = 1; context->current_state = state; context->ppid = 0; + ktime_get_coarse_ts64(&context->ctime); } /** -- cgit v1.2.3 From 290e44b7dd116cc61cf37b7ca0be13313bb11e37 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Tue, 17 Jul 2018 14:45:08 -0400 Subject: audit: use ktime_get_coarse_real_ts64() for timestamps Commit c72051d5778a ("audit: use ktime_get_coarse_ts64() for time access") converted audit's use of current_kernel_time64() to the new ktime_get_coarse_ts64() function. Unfortunately this resulted in incorrect timestamps, e.g. events stamped with the year 1969 despite it being 2018. This patch corrects this by using ktime_get_coarse_real_ts64() just like the current_kernel_time64() wrapper. Fixes: c72051d5778a ("audit: use ktime_get_coarse_ts64() for time access") Reviewed-by: Arnd Bergmann Signed-off-by: Paul Moore --- kernel/audit.c | 2 +- kernel/auditsc.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'kernel') diff --git a/kernel/audit.c b/kernel/audit.c index e17bc697d11c..2a8058764aa6 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -1721,7 +1721,7 @@ static inline void audit_get_stamp(struct audit_context *ctx, struct timespec64 *t, unsigned int *serial) { if (!ctx || !auditsc_get_stamp(ctx, t, serial)) { - ktime_get_coarse_ts64(t); + ktime_get_coarse_real_ts64(t); *serial = audit_serial(); } } diff --git a/kernel/auditsc.c b/kernel/auditsc.c index f6a0cb32d76e..fb207466e99b 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -1543,7 +1543,7 @@ void __audit_syscall_entry(int major, unsigned long a1, unsigned long a2, context->in_syscall = 1; context->current_state = state; context->ppid = 0; - ktime_get_coarse_ts64(&context->ctime); + ktime_get_coarse_real_ts64(&context->ctime); } /** -- cgit v1.2.3 From baa2a4fdd525c8c4b0f704d20457195b29437839 Mon Sep 17 00:00:00 2001 From: Ronny Chevalier Date: Wed, 11 Jul 2018 14:39:37 +0200 Subject: audit: fix use-after-free in audit_add_watch audit_add_watch stores locally krule->watch without taking a reference on watch. Then, it calls audit_add_to_parent, and uses the watch stored locally. Unfortunately, it is possible that audit_add_to_parent updates krule->watch. When it happens, it also drops a reference of watch which could free the watch. How to reproduce (with KASAN enabled): auditctl -w /etc/passwd -F success=0 -k test_passwd auditctl -w /etc/passwd -F success=1 -k test_passwd2 The second call to auditctl triggers the use-after-free, because audit_to_parent updates krule->watch to use a previous existing watch and drops the reference to the newly created watch. To fix the issue, we grab a reference of watch and we release it at the end of the function. Signed-off-by: Ronny Chevalier Reviewed-by: Richard Guy Briggs Signed-off-by: Paul Moore --- kernel/audit_watch.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'kernel') diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c index 6f249bdf2d84..787c7afdf829 100644 --- a/kernel/audit_watch.c +++ b/kernel/audit_watch.c @@ -420,6 +420,13 @@ int audit_add_watch(struct audit_krule *krule, struct list_head **list) struct path parent_path; int h, ret = 0; + /* + * When we will be calling audit_add_to_parent, krule->watch might have + * been updated and watch might have been freed. + * So we need to keep a reference of watch. + */ + audit_get_watch(watch); + mutex_unlock(&audit_filter_mutex); /* Avoid calling path_lookup under audit_filter_mutex. */ @@ -428,8 +435,10 @@ int audit_add_watch(struct audit_krule *krule, struct list_head **list) /* caller expects mutex locked */ mutex_lock(&audit_filter_mutex); - if (ret) + if (ret) { + audit_put_watch(watch); return ret; + } /* either find an old parent or attach a new one */ parent = audit_find_parent(d_backing_inode(parent_path.dentry)); @@ -447,6 +456,7 @@ int audit_add_watch(struct audit_krule *krule, struct list_head **list) *list = &audit_inode_hash[h]; error: path_put(&parent_path); + audit_put_watch(watch); return ret; } -- cgit v1.2.3