From d590dca62bb8a315a2356159444de07278a3ad83 Mon Sep 17 00:00:00 2001 From: Richard Guy Briggs Date: Sat, 3 Feb 2018 00:33:11 -0500 Subject: [PATCH 01/11] audit: update bugtracker and source URIs Since the Linux Audit project has transitioned completely over to github, update the MAINTAINERS file and the primary audit source file to reflect that reality. Signed-off-by: Richard Guy Briggs Signed-off-by: Paul Moore --- MAINTAINERS | 1 - kernel/audit.c | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 845fc25812f1db..fba48756e4958e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2479,7 +2479,6 @@ M: Paul Moore M: Eric Paris L: linux-audit@redhat.com (moderated for non-subscribers) W: https://github.com/linux-audit -W: https://people.redhat.com/sgrubb/audit T: git git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/audit.git S: Supported F: include/linux/audit.h diff --git a/kernel/audit.c b/kernel/audit.c index 227db99b0f19a8..5c25449843758a 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -38,7 +38,8 @@ * 6) Support low-overhead kernel-based filtering to minimize the * information that must be passed to user-space. * - * Example user-space utilities: http://people.redhat.com/sgrubb/audit/ + * Audit userspace, documentation, tests, and bug/issue trackers: + * https://github.com/linux-audit */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt From 6387440e15db1c9ee58028433cd87291cae488e7 Mon Sep 17 00:00:00 2001 From: Richard Guy Briggs Date: Mon, 12 Feb 2018 05:04:53 -0500 Subject: [PATCH 02/11] audit: session ID should not set arch quick field pointer A bug was introduced in 8fae47705685fcaa75a1fe4c8c3e18300a702979 ("audit: add support for session ID user filter") See: https://github.com/linux-audit/audit-kernel/issues/4 When setting a session ID filter, the session ID filter field overwrote the quick pointer reference to the arch field, potentially causing the arch field to be misinterpreted. Passes audit-testsuite. Signed-off-by: Richard Guy Briggs Signed-off-by: Paul Moore --- kernel/auditfilter.c | 1 - 1 file changed, 1 deletion(-) diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index 4a1758adb22249..739a6d2d4df884 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c @@ -496,7 +496,6 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, if (!gid_valid(f->gid)) goto exit_free; break; - case AUDIT_SESSIONID: case AUDIT_ARCH: entry->rule.arch_f = f; break; From 5260ecc2e0480cc7e184901ab4c3721d0c2765e3 Mon Sep 17 00:00:00 2001 From: Richard Guy Briggs Date: Wed, 14 Feb 2018 21:47:43 -0500 Subject: [PATCH 03/11] audit: deprecate the AUDIT_FILTER_ENTRY filter The audit entry filter has been long deprecated with userspace support finally removed in audit-v2.6.7 and plans to remove kernel support have existed since kernel-v2.6.31. Remove it. Since removing the audit entry filter, test for early return before setting up any context state. Passes audit-testsuite. See: https://github.com/linux-audit/audit-kernel/issues/6 Signed-off-by: Richard Guy Briggs Signed-off-by: Paul Moore --- kernel/auditfilter.c | 4 ++-- kernel/auditsc.c | 21 +++++++++++---------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index 739a6d2d4df884..d7a807e814514c 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c @@ -258,8 +258,8 @@ static inline struct audit_entry *audit_to_entry_common(struct audit_rule_data * goto exit_err; #ifdef CONFIG_AUDITSYSCALL case AUDIT_FILTER_ENTRY: - if (rule->action == AUDIT_ALWAYS) - goto exit_err; + pr_err("AUDIT_FILTER_ENTRY is deprecated\n"); + goto exit_err; case AUDIT_FILTER_EXIT: case AUDIT_FILTER_TASK: #endif diff --git a/kernel/auditsc.c b/kernel/auditsc.c index e80459f7e13277..bc534bfb49a40e 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -1519,22 +1519,23 @@ void __audit_syscall_entry(int major, unsigned long a1, unsigned long a2, if (!audit_enabled) return; - context->arch = syscall_get_arch(); - context->major = major; - context->argv[0] = a1; - context->argv[1] = a2; - context->argv[2] = a3; - context->argv[3] = a4; - state = context->state; + if (state == AUDIT_DISABLED) + return; + context->dummy = !audit_n_rules; if (!context->dummy && state == AUDIT_BUILD_CONTEXT) { context->prio = 0; - state = audit_filter_syscall(tsk, context, &audit_filter_list[AUDIT_FILTER_ENTRY]); + if (auditd_test_task(tsk)) + return; } - if (state == AUDIT_DISABLED) - return; + context->arch = syscall_get_arch(); + context->major = major; + context->argv[0] = a1; + context->argv[1] = a2; + context->argv[2] = a3; + context->argv[3] = a4; context->serial = 0; context->ctime = current_kernel_time64(); context->in_syscall = 1; From 94d14e3e7b41d99f0d62a41fd856183057e1e474 Mon Sep 17 00:00:00 2001 From: Richard Guy Briggs Date: Wed, 14 Feb 2018 21:47:44 -0500 Subject: [PATCH 04/11] audit: bail before bug check if audit disabled If audit is disabled, who cares if there is a bug indicating syscall in process or names already recorded. Bail immediately on audit disabled. Signed-off-by: Richard Guy Briggs Signed-off-by: Paul Moore --- kernel/auditsc.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/kernel/auditsc.c b/kernel/auditsc.c index bc534bfb49a40e..4e0a4ac803db72 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -1511,14 +1511,11 @@ void __audit_syscall_entry(int major, unsigned long a1, unsigned long a2, struct audit_context *context = tsk->audit_context; enum audit_state state; - if (!context) + if (!audit_enabled || !context) return; BUG_ON(context->in_syscall || context->name_count); - if (!audit_enabled) - return; - state = context->state; if (state == AUDIT_DISABLED) return; From 23138ead270045f1b3e912e667967b6094244999 Mon Sep 17 00:00:00 2001 From: Richard Guy Briggs Date: Wed, 21 Feb 2018 04:30:07 -0500 Subject: [PATCH 05/11] audit: return on memory error to avoid null pointer dereference If there is a memory allocation error when trying to change an audit kernel feature value, the ignored allocation error will trigger a NULL pointer dereference oops on subsequent use of that pointer. Return instead. Passes audit-testsuite. See: https://github.com/linux-audit/audit-kernel/issues/76 Signed-off-by: Richard Guy Briggs [PM: not necessary (other funcs check for NULL), but a good practice] Signed-off-by: Paul Moore --- kernel/audit.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel/audit.c b/kernel/audit.c index 5c25449843758a..2de74be7cef5aa 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -1059,6 +1059,8 @@ static void audit_log_feature_change(int which, u32 old_feature, u32 new_feature return; ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_FEATURE_CHANGE); + if (!ab) + return; audit_log_task_info(ab, current); audit_log_format(ab, " feature=%s old=%u new=%u old_lock=%u new_lock=%u res=%d", audit_feature_names[which], !!old_feature, !!new_feature, From ce423631ce1f20564f818e7de6bc0eee0c01badd Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Tue, 20 Feb 2018 09:52:38 -0500 Subject: [PATCH 06/11] audit: track the owner of the command mutex ourselves Evidently the __mutex_owner() function was never intended for use outside the core mutex code, so build a thing locking wrapper around the mutex code which allows us to track the mutex owner. One, arguably positive, side effect is that this allows us to hide the audit_cmd_mutex inside of kernel/audit.c behind the lock/unlock functions. Reported-by: Peter Zijlstra Reviewed-by: Richard Guy Briggs Signed-off-by: Paul Moore --- kernel/audit.c | 66 +++++++++++++++++++++++++++++++++++++-------- kernel/audit.h | 3 ++- kernel/audit_tree.c | 8 +++--- 3 files changed, 61 insertions(+), 16 deletions(-) diff --git a/kernel/audit.c b/kernel/audit.c index 2de74be7cef5aa..1a3e75d9a66c44 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -181,9 +181,21 @@ static char *audit_feature_names[2] = { "loginuid_immutable", }; - -/* Serialize requests from userspace. */ -DEFINE_MUTEX(audit_cmd_mutex); +/** + * struct audit_ctl_mutex - serialize requests from userspace + * @lock: the mutex used for locking + * @owner: the task which owns the lock + * + * Description: + * This is the lock struct used to ensure we only process userspace requests + * in an orderly fashion. We can't simply use a mutex/lock here because we + * need to track lock ownership so we don't end up blocking the lock owner in + * audit_log_start() or similar. + */ +static struct audit_ctl_mutex { + struct mutex lock; + void *owner; +} audit_cmd_mutex; /* AUDIT_BUFSIZ is the size of the temporary buffer used for formatting * audit records. Since printk uses a 1024 byte buffer, this buffer @@ -227,6 +239,36 @@ int auditd_test_task(struct task_struct *task) return rc; } +/** + * audit_ctl_lock - Take the audit control lock + */ +void audit_ctl_lock(void) +{ + mutex_lock(&audit_cmd_mutex.lock); + audit_cmd_mutex.owner = current; +} + +/** + * audit_ctl_unlock - Drop the audit control lock + */ +void audit_ctl_unlock(void) +{ + audit_cmd_mutex.owner = NULL; + mutex_unlock(&audit_cmd_mutex.lock); +} + +/** + * audit_ctl_owner_current - Test to see if the current task owns the lock + * + * Description: + * Return true if the current task owns the audit control lock, false if it + * doesn't own the lock. + */ +static bool audit_ctl_owner_current(void) +{ + return (current == audit_cmd_mutex.owner); +} + /** * auditd_pid_vnr - Return the auditd PID relative to the namespace * @@ -861,8 +903,8 @@ int audit_send_list(void *_dest) struct sock *sk = audit_get_sk(dest->net); /* wait for parent to finish and send an ACK */ - mutex_lock(&audit_cmd_mutex); - mutex_unlock(&audit_cmd_mutex); + audit_ctl_lock(); + audit_ctl_unlock(); while ((skb = __skb_dequeue(&dest->q)) != NULL) netlink_unicast(sk, skb, dest->portid, 0); @@ -903,8 +945,8 @@ static int audit_send_reply_thread(void *arg) struct audit_reply *reply = (struct audit_reply *)arg; struct sock *sk = audit_get_sk(reply->net); - mutex_lock(&audit_cmd_mutex); - mutex_unlock(&audit_cmd_mutex); + audit_ctl_lock(); + audit_ctl_unlock(); /* Ignore failure. It'll only happen if the sender goes away, because our timeout is set to infinite. */ @@ -1469,7 +1511,7 @@ static void audit_receive(struct sk_buff *skb) nlh = nlmsg_hdr(skb); len = skb->len; - mutex_lock(&audit_cmd_mutex); + audit_ctl_lock(); while (nlmsg_ok(nlh, len)) { err = audit_receive_msg(skb, nlh); /* if err or if this message says it wants a response */ @@ -1478,7 +1520,7 @@ static void audit_receive(struct sk_buff *skb) nlh = nlmsg_next(nlh, &len); } - mutex_unlock(&audit_cmd_mutex); + audit_ctl_unlock(); } /* Run custom bind function on netlink socket group connect or bind requests. */ @@ -1550,6 +1592,9 @@ static int __init audit_init(void) for (i = 0; i < AUDIT_INODE_BUCKETS; i++) INIT_LIST_HEAD(&audit_inode_hash[i]); + mutex_init(&audit_cmd_mutex.lock); + audit_cmd_mutex.owner = NULL; + pr_info("initializing netlink subsys (%s)\n", audit_default ? "enabled" : "disabled"); register_pernet_subsys(&audit_net_ops); @@ -1713,8 +1758,7 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask, * using a PID anchored in the caller's namespace * 2. generator holding the audit_cmd_mutex - we don't want to block * while holding the mutex */ - if (!(auditd_test_task(current) || - (current == __mutex_owner(&audit_cmd_mutex)))) { + if (!(auditd_test_task(current) || audit_ctl_owner_current())) { long stime = audit_backlog_wait_time; while (audit_backlog_limit && diff --git a/kernel/audit.h b/kernel/audit.h index af5bc59487ed69..214e1494837060 100644 --- a/kernel/audit.h +++ b/kernel/audit.h @@ -341,4 +341,5 @@ extern struct list_head *audit_killed_trees(void); #define audit_filter_inodes(t,c) AUDIT_DISABLED #endif -extern struct mutex audit_cmd_mutex; +extern void audit_ctl_lock(void); +extern void audit_ctl_unlock(void); diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c index fd353120e0d946..67e6956c0b61d0 100644 --- a/kernel/audit_tree.c +++ b/kernel/audit_tree.c @@ -709,7 +709,7 @@ static int prune_tree_thread(void *unused) schedule(); } - mutex_lock(&audit_cmd_mutex); + audit_ctl_lock(); mutex_lock(&audit_filter_mutex); while (!list_empty(&prune_list)) { @@ -727,7 +727,7 @@ static int prune_tree_thread(void *unused) } mutex_unlock(&audit_filter_mutex); - mutex_unlock(&audit_cmd_mutex); + audit_ctl_unlock(); } return 0; } @@ -924,7 +924,7 @@ static void audit_schedule_prune(void) */ void audit_kill_trees(struct list_head *list) { - mutex_lock(&audit_cmd_mutex); + audit_ctl_lock(); mutex_lock(&audit_filter_mutex); while (!list_empty(list)) { @@ -942,7 +942,7 @@ void audit_kill_trees(struct list_head *list) } mutex_unlock(&audit_filter_mutex); - mutex_unlock(&audit_cmd_mutex); + audit_ctl_unlock(); } /* From 11dd2666375e191757dd4271d5020820c6d0e4a5 Mon Sep 17 00:00:00 2001 From: Greg Edwards Date: Mon, 5 Mar 2018 15:05:20 -0700 Subject: [PATCH 07/11] audit: do not panic on invalid boot parameter If you pass in an invalid audit boot parameter value, e.g. "audit=off", the kernel panics very early in boot before the regular console is initialized. Unless you have earlyprintk enabled, there is no indication of what the problem is on the console. Convert the panic() calls to pr_err(), and leave auditing enabled if an invalid parameter value was passed in. Modify the parameter to also accept "on" or "off" as valid values, and update the documentation accordingly. Signed-off-by: Greg Edwards Signed-off-by: Paul Moore --- .../admin-guide/kernel-parameters.txt | 14 ++++++------- kernel/audit.c | 21 ++++++++++++------- 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index 46b26bfee27ba8..93366b00bb6299 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -387,15 +387,15 @@ Use software keyboard repeat audit= [KNL] Enable the audit sub-system - Format: { "0" | "1" } (0 = disabled, 1 = enabled) - 0 - kernel audit is disabled and can not be enabled - until the next reboot + Format: { "0" | "1" | "off" | "on" } + 0 | off - kernel audit is disabled and can not be + enabled until the next reboot unset - kernel audit is initialized but disabled and will be fully enabled by the userspace auditd. - 1 - kernel audit is initialized and partially enabled, - storing at most audit_backlog_limit messages in - RAM until it is fully enabled by the userspace - auditd. + 1 | on - kernel audit is initialized and partially + enabled, storing at most audit_backlog_limit + messages in RAM until it is fully enabled by the + userspace auditd. Default: unset audit_backlog_limit= [KNL] Set the audit queue size limit. diff --git a/kernel/audit.c b/kernel/audit.c index 1a3e75d9a66c44..69ef8de69f0378 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -1615,19 +1615,26 @@ static int __init audit_init(void) } postcore_initcall(audit_init); -/* Process kernel command-line parameter at boot time. audit=0 or audit=1. */ +/* + * Process kernel command-line parameter at boot time. + * audit={0|off} or audit={1|on}. + */ static int __init audit_enable(char *str) { - long val; - - if (kstrtol(str, 0, &val)) - panic("audit: invalid 'audit' parameter value (%s)\n", str); - audit_default = (val ? AUDIT_ON : AUDIT_OFF); + if (!strcasecmp(str, "off") || !strcmp(str, "0")) + audit_default = AUDIT_OFF; + else if (!strcasecmp(str, "on") || !strcmp(str, "1")) + audit_default = AUDIT_ON; + else { + pr_err("audit: invalid 'audit' parameter value (%s)\n", str); + audit_default = AUDIT_ON; + } if (audit_default == AUDIT_OFF) audit_initialized = AUDIT_DISABLED; if (audit_set_enabled(audit_default)) - panic("audit: error setting audit state (%d)\n", audit_default); + pr_err("audit: error setting audit state (%d)\n", + audit_default); pr_info("%s\n", audit_default ? "enabled (after initialization)" : "disabled (until reboot)"); From 15564ff0a16e2d994e78d62c23d227ff182ee864 Mon Sep 17 00:00:00 2001 From: Richard Guy Briggs Date: Wed, 14 Feb 2018 11:18:21 -0500 Subject: [PATCH 08/11] audit: make ANOM_LINK obey audit_enabled and audit_dummy_context Audit link denied events emit disjointed records when audit is disabled. No records should be emitted when audit is disabled. See: https://github.com/linux-audit/audit-kernel/issues/21 Signed-off-by: Richard Guy Briggs Signed-off-by: Paul Moore --- kernel/audit.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/kernel/audit.c b/kernel/audit.c index 69ef8de69f0378..46cd8f66af170c 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -2315,6 +2315,9 @@ void audit_log_link_denied(const char *operation, const struct path *link) struct audit_buffer *ab; struct audit_names *name; + if (!audit_enabled || audit_dummy_context()) + return; + name = kzalloc(sizeof(*name), GFP_NOFS); if (!name) return; From 45b578fe4c3cade6f4ca1fc934ce199afd857edc Mon Sep 17 00:00:00 2001 From: Richard Guy Briggs Date: Wed, 14 Feb 2018 11:18:22 -0500 Subject: [PATCH 09/11] audit: link denied should not directly generate PATH record Audit link denied events generate duplicate PATH records which disagree in different ways from symlink and hardlink denials. audit_log_link_denied() should not directly generate PATH records. See: https://github.com/linux-audit/audit-kernel/issues/21 Signed-off-by: Richard Guy Briggs Signed-off-by: Paul Moore --- kernel/audit.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/kernel/audit.c b/kernel/audit.c index 46cd8f66af170c..3f2f143edadfa8 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -2313,31 +2313,19 @@ EXPORT_SYMBOL(audit_log_task_info); void audit_log_link_denied(const char *operation, const struct path *link) { struct audit_buffer *ab; - struct audit_names *name; if (!audit_enabled || audit_dummy_context()) return; - name = kzalloc(sizeof(*name), GFP_NOFS); - if (!name) - return; - /* Generate AUDIT_ANOM_LINK with subject, operation, outcome. */ ab = audit_log_start(current->audit_context, GFP_KERNEL, AUDIT_ANOM_LINK); if (!ab) - goto out; + return; audit_log_format(ab, "op=%s", operation); audit_log_task_info(ab, current); audit_log_format(ab, " res=0"); audit_log_end(ab); - - /* Generate AUDIT_PATH record with object. */ - name->type = AUDIT_TYPE_NORMAL; - audit_copy_inode(name, link->dentry, d_backing_inode(link->dentry)); - audit_log_name(current->audit_context, name, link, 0, NULL); -out: - kfree(name); } /** From 94b9d9b7a14cbb1640868d53b27f403ed2e5b4a9 Mon Sep 17 00:00:00 2001 From: Richard Guy Briggs Date: Wed, 21 Mar 2018 04:42:20 -0400 Subject: [PATCH 10/11] audit: remove path param from link denied function In commit 45b578fe4c3cade6f4ca1fc934ce199afd857edc ("audit: link denied should not directly generate PATH record") the need for the struct path *link parameter was removed. Remove the now useless struct path argument. Signed-off-by: Richard Guy Briggs Signed-off-by: Paul Moore --- fs/namei.c | 4 ++-- include/linux/audit.h | 6 ++---- kernel/audit.c | 3 +-- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/fs/namei.c b/fs/namei.c index 9cc91fb7f15654..e3682bb72cb5d6 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -945,7 +945,7 @@ static inline int may_follow_link(struct nameidata *nd) if (nd->flags & LOOKUP_RCU) return -ECHILD; - audit_log_link_denied("follow_link", &nd->stack[0].link); + audit_log_link_denied("follow_link"); return -EACCES; } @@ -1011,7 +1011,7 @@ static int may_linkat(struct path *link) if (safe_hardlink_source(inode) || inode_owner_or_capable(inode)) return 0; - audit_log_link_denied("linkat", link); + audit_log_link_denied("linkat"); return -EPERM; } diff --git a/include/linux/audit.h b/include/linux/audit.h index af410d9fbf2da9..75d5b031e80271 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -146,8 +146,7 @@ extern void audit_log_d_path(struct audit_buffer *ab, const struct path *path); extern void audit_log_key(struct audit_buffer *ab, char *key); -extern void audit_log_link_denied(const char *operation, - const struct path *link); +extern void audit_log_link_denied(const char *operation); extern void audit_log_lost(const char *message); extern int audit_log_task_context(struct audit_buffer *ab); @@ -194,8 +193,7 @@ static inline void audit_log_d_path(struct audit_buffer *ab, { } static inline void audit_log_key(struct audit_buffer *ab, char *key) { } -static inline void audit_log_link_denied(const char *string, - const struct path *link) +static inline void audit_log_link_denied(const char *string) { } static inline int audit_log_task_context(struct audit_buffer *ab) { diff --git a/kernel/audit.c b/kernel/audit.c index 3f2f143edadfa8..e8bf8d78ac4afe 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -2308,9 +2308,8 @@ EXPORT_SYMBOL(audit_log_task_info); /** * audit_log_link_denied - report a link restriction denial * @operation: specific link operation - * @link: the path that triggered the restriction */ -void audit_log_link_denied(const char *operation, const struct path *link) +void audit_log_link_denied(const char *operation) { struct audit_buffer *ab; From ea841bafda3f7f9aa8b06a09f0f3e41c207af84f Mon Sep 17 00:00:00 2001 From: Richard Guy Briggs Date: Wed, 21 Mar 2018 04:42:21 -0400 Subject: [PATCH 11/11] audit: add refused symlink to audit_names Audit link denied events for symlinks had duplicate PATH records rather than just updating the existing PATH record. Update the symlink's PATH record with the current dentry and inode information. See: https://github.com/linux-audit/audit-kernel/issues/21 Signed-off-by: Richard Guy Briggs Signed-off-by: Paul Moore --- fs/namei.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/namei.c b/fs/namei.c index e3682bb72cb5d6..5f8e8e2732e165 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -945,6 +945,7 @@ static inline int may_follow_link(struct nameidata *nd) if (nd->flags & LOOKUP_RCU) return -ECHILD; + audit_inode(nd->name, nd->stack[0].link.dentry, 0); audit_log_link_denied("follow_link"); return -EACCES; }