[PATCH] audit: always enable syscall auditing when supported and audit is enabled
by Paul Moore
To the best of our knowledge, everyone who enables audit at compile
time also enables syscall auditing; this patch simplifies the Kconfig
menus by removing the option to disable syscall auditing when audit
is selected and the target arch supports it.
Signed-off-by: Paul Moore <pmoore(a)redhat.com>
---
init/Kconfig | 11 +++--------
1 file changed, 3 insertions(+), 8 deletions(-)
diff --git a/init/Kconfig b/init/Kconfig
index c24b6f7..d4663b1 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -299,20 +299,15 @@ config AUDIT
help
Enable auditing infrastructure that can be used with another
kernel subsystem, such as SELinux (which requires this for
- logging of avc messages output). Does not do system-call
- auditing without CONFIG_AUDITSYSCALL.
+ logging of avc messages output). System call auditing is included
+ on architectures which support it.
config HAVE_ARCH_AUDITSYSCALL
bool
config AUDITSYSCALL
- bool "Enable system-call auditing support"
+ def_bool y
depends on AUDIT && HAVE_ARCH_AUDITSYSCALL
- default y if SECURITY_SELINUX
- help
- Enable low-overhead system-call auditing infrastructure that
- can be used independently or with another kernel subsystem,
- such as SELinux.
config AUDIT_WATCH
def_bool y
5 years, 10 months
[RFC PATCH 0/3] simplify struct audit_krule reveals bug
by Richard Guy Briggs
In the process of trying to track down a potential bug altering the
registered arch for a syscall rule, a simplification of struct
audit_krule that removes a seemingly unnecessary member has revealed a
surprising NULL pointer dereference.
The struct audit_field *arch_f member should not be necessary since it
is the first field present if it is present at all, and is only
necessary for syscall rules, so iterating over the fields to find it is
simple and only happens when adding or deleting a rule. Shrinking the
struct audit_krule seemed to be a good idea, but appears to have openned
a can of worms. The first patch triggered this OOPS:
BUG: unable to handle kernel NULL pointer dereference at 0000000000000009
IP: audit_match_signal+0x42/0x120
PGD 0 P4D 0
Oops: 0000 [#1] SMP PTI
Modules linked in: sunrpc 8139too i2c_piix4 pcspkr virtio_balloon 8139cp i2c_core mii sch_fq_codel floppy serio_raw ata_generic pata_acpi
CPU: 1 PID: 325 Comm: auditctl Not tainted 4.15.0-bz1462178-arch-changed+ #636
Hardware name: Red Hat KVM, BIOS 0.5.1 01/01/2011
RIP: 0010:audit_match_signal+0x42/0x120
RSP: 0018:ffffc900003dfc08 EFLAGS: 00010202
RAX: 0000000000000003 RBX: ffff880036588000 RCX: 0000000000000003
RDX: ffff88003c7f02e0 RSI: ffff88003c7f02a0 RDI: ffff880036588000
RBP: ffff88003671de00 R08: 0000000000000001 R09: 0000000000000000
R10: ffff880036a0b190 R11: 0000000000000000 R12: 0000000000000000
R13: ffff880036588178 R14: ffff880036588000 R15: ffffffff8247f880
FS: 00007fa53c6d9740(0000) GS:ffff88003e400000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000000000000009 CR3: 00000000347ba000 CR4: 00000000000006e0
Call Trace:
audit_rule_change+0xb32/0xce0
audit_receive_msg+0x163/0x1090
? netlink_deliver_tap+0x90/0x350
? kvm_sched_clock_read+0x5/0x10
? sched_clock+0x5/0x10
audit_receive+0x4d/0xa0
netlink_unicast+0x195/0x250
netlink_sendmsg+0x2fe/0x3f0
sock_sendmsg+0x32/0x60
SYSC_sendto+0xda/0x140
? syscall_trace_enter+0x2dc/0x400
? return_from_SYSCALL_64+0x10/0x75
do_syscall_64+0x83/0x360
entry_SYSCALL64_slow_path+0x25/0x25
RIP: 0033:0x7fa53bbb1607
RSP: 002b:00007fff33f48c78 EFLAGS: 00000246 ORIG_RAX: 000000000000002c
RAX: ffffffffffffffda RBX: 0000000000000444 RCX: 00007fa53bbb1607
RDX: 0000000000000444 RSI: 00007fff33f48cb0 RDI: 0000000000000003
RBP: 0000000000000431 R08: 00007fff33f48c9c R09: 000000000000000c
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000003
R13: 00007fff33f48cb0 R14: 00007fff33f48c9c R15: 00000000000003f3
Code: 01 00 00 83 3e 0b 0f 84 ef 00 00 00 31 c0 eb 0f 48 63 d0 48 c1 e2 05 48 01 f2 83 3a 0b 74 7d 83 c0 01 39 c8 75 ea 4d 85 c0 74 79 <41> 8b 78 08 e8 25 ff ed ff 85 c0 74 31 83 f8 01 75 58 48 8b 0d
RIP: audit_match_signal+0x42/0x120 RSP: ffffc900003dfc08
CR2: 0000000000000009
The second patch surprisingly fixes the OOPS.
Adding debug output, the OOPS is consistently happenning in the 7th STIG rule
that includes an arch parameter, but the value that causes the OOPS
dereferences, copies and prints out fine:
-a always,exit -F arch=b32 -S adjtimex,settimeofday,stime -F key=time-change
ams_: i=0 f=00000000e5612893 type=11 op=0 val=40000003 key="time-change"
-a always,exit -F arch=b64 -S adjtimex,settimeofday -F key=time-change
ams_: i=0 f=00000000cf222aca type=11 op=0 val=c000003e key="time-change"
-a always,exit -F arch=b32 -S clock_settime -F a0=0x0 -F key=time-change
ams_: i=0 f=00000000ad39bfc6 type=11 op=0 val=40000003 key="time-change"
-a always,exit -F arch=b64 -S clock_settime -F a0=0x0 -F key=time-change
ams_: i=0 f=00000000c9f83209 type=11 op=0 val=c000003e key="time-change"
-a always,exit -F arch=b32 -S sethostname,setdomainname -F key=system-locale
ams_: i=0 f=000000005a19d216 type=11 op=0 val=40000003 key="system-locale"
-a always,exit -F arch=b64 -S sethostname,setdomainname -F key=system-locale
ams_: i=0 f=000000003280e47a type=11 op=0 val=c000003e key="system-locale"
OOPS
-a always,exit -F arch=b32 -S chmod,fchmod,fchmodat -F auid>=1000 -F auid!=4294967295 -F key=perm_mod
ams_: i=0 f=000000008368170a type=11 op=0 val=40000003 key="perm_mod"
I'd let sleeping dogs lie, but I haven't tracked down the source of the
original rule that changes arch between addition and listing (nor reproduced it
yet since I don't have access to that HW arch), and it seems to reveal
potentially another bug.
Help! Any observations or hints?
Richard Guy Briggs (3):
audit: remove arch_f pointer from struct audit_krule
fixup! audit: remove arch_f pointer from struct audit_krule
debug! audit: remove arch_f pointer from struct audit_krule
include/linux/audit.h | 1 -
kernel/auditfilter.c | 18 +++++++++++++-----
2 files changed, 13 insertions(+), 6 deletions(-)
--
1.8.3.1
6 years
[RFC PATCH ghak90 (was ghak32) V3 00/10] audit: implement container identifier
by Richard Guy Briggs
Implement kernel audit container identifier.
This patchset is a third based on the proposal document (V3)
posted:
https://www.redhat.com/archives/linux-audit/2018-January/msg00014.html
The first patch implements the proc fs write to set the audit container
identifier of a process, emitting an AUDIT_CONTAINER_ID record to announce the
registration of that audit container identifier on that process. This patch
requires userspace support for record acceptance and proper type
display.
The second implements the auxiliary record AUDIT_CONTAINER if an
audit container identifier is identifiable with an event. This patch
requires userspace support for proper type display.
The third adds signal and ptrace support.
The 4th creates a local audit context to be able to bind a standalone
record with a locally created auxiliary record.
The 5th patch adds audit container identifier records to the tty
standalone record.
The 6th adds audit container identifier filtering to the exit,
exclude and user lists. This patch adds the AUDIT_CONTID field and
requires auditctl userspace support for the --contid option.
The 7th adds network namespace audit container identifier labelling
based on member tasks' audit container identifier labels.
The 8th adds audit container identifier support to standalone netfilter
records that don't have a task context and lists each container to which
that net namespace belongs.
The 9th implements reading the audit container identifier from the proc
filesystem for debugging. This patch isn't planned for upstream
inclusion.
The 10th fixes an rfkill spelling mistake in a comment that is otherwise
the only match for "contid" in the kernel.
Example: Set an audit container identifier of 123456 to the "sleep" task:
sleep 2&
child=$!
echo 123456 > /proc/$child/audit_containerid; echo $?
ausearch -ts recent -m container
echo child:$child contid:$( cat /proc/$child/audit_containerid)
This should produce a record such as:
type=CONTAINER_ID msg=audit(2018-06-06 12:39:29.636:26949) : op=set opid=2209 old-contid=18446744073709551615 contid=123456 pid=628 auid=root uid=root tty=ttyS0 ses=1 subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 comm=bash exe=/usr/bin/bash res=yes
Example: Set a filter on an audit container identifier 123459 on /tmp/tmpcontainerid:
contid=123459
key=tmpcontainerid
auditctl -a exit,always -F dir=/tmp -F perm=wa -F contid=$contid -F key=$key
perl -e "sleep 1; open(my \$tmpfile, '>', \"/tmp/$key\"); close(\$tmpfile);" &
child=$!
echo $contid > /proc/$child/audit_containerid
sleep 2
ausearch -i -ts recent -k $key
auditctl -d exit,always -F dir=/tmp -F perm=wa -F contid=$contid -F key=$key
rm -f /tmp/$key
This should produce an event such as:
type=CONTAINER msg=audit(2018-06-06 12:46:31.707:26953) : op=task contid=123459
type=PROCTITLE msg=audit(2018-06-06 12:46:31.707:26953) : proctitle=perl -e sleep 1; open(my $tmpfile, '>', "/tmp/tmpcontainerid"); close($tmpfile);
type=PATH msg=audit(2018-06-06 12:46:31.707:26953) : item=1 name=/tmp/tmpcontainerid inode=25656 dev=00:26 mode=file,644 ouid=root ogid=root rdev=00:00 obj=unconfined_u:object_r:user_tmp_t:s0 nametype=CREATE cap_fp=none cap_fi=none cap_fe=0 cap_fver=0
type=PATH msg=audit(2018-06-06 12:46:31.707:26953) : item=0 name=/tmp/ inode=8985 dev=00:26 mode=dir,sticky,777 ouid=root ogid=root rdev=00:00 obj=system_u:object_r:tmp_t:s0 nametype=PARENT cap_fp=none cap_fi=none cap_fe=0 cap_fver=0
type=CWD msg=audit(2018-06-06 12:46:31.707:26953) : cwd=/root
type=SYSCALL msg=audit(2018-06-06 12:46:31.707:26953) : arch=x86_64 syscall=openat success=yes exit=3 a0=0xffffffffffffff9c a1=0x5621f2b81900 a2=O_WRONLY|O_CREAT|O_TRUNC a3=0x1b6 items=2 ppid=628 pid=2232 auid=root uid=root gid=root euid=root suid=root fsuid=root egid=root sgid=root fsgid=root tty=ttyS0 ses=1 comm=perl exe=/usr/bin/perl subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 key=tmpcontainerid
Requires: https://github.com/linux-audit/audit-kernel/issues/81
See: https://github.com/linux-audit/audit-kernel/issues/90
See: https://github.com/linux-audit/audit-userspace/issues/40
See: https://github.com/linux-audit/audit-testsuite/issues/64
See: https://github.com/linux-audit/audit-kernel/wiki/RFE-Audit-Container-ID
Changelog:
v3
- switched from containerid in task_struct to audit_task_info (depends on ghak81)
- drop INVALID_CID in favour of only AUDIT_CID_UNSET
- check for !audit_task_info, throw -ENOPROTOOPT on set
- changed -EPERM to -EEXIST for parent check
- return AUDIT_CID_UNSET if !audit_enabled
- squash child/thread check patch into AUDIT_CONTAINER_ID patch
- changed -EPERM to -EBUSY for child check
- separate child and thread checks, use -EALREADY for latter
- move addition of op= from ptrace/signal patch to AUDIT_CONTAINER patch
- fix && to || bashism in ptrace/signal patch
- uninline and export function for audit_free_context()
- drop CONFIG_CHANGE, FEATURE_CHANGE, ANOM_ABEND, ANOM_SECCOMP patches
- move audit_enabled check (xt_AUDIT)
- switched from containerid list in struct net to net_generic's struct audit_net
- move containerid list iteration into audit (xt_AUDIT)
- create function to move namespace switch into audit
- switched /proc/PID/ entry from containerid to audit_containerid
- call kzalloc with GFP_ATOMIC on in_atomic() in audit_alloc_context()
- call kzalloc with GFP_ATOMIC on in_atomic() in audit_log_container_info()
- use xt_net(par) instead of sock_net(skb->sk) to get net
- switched record and field names: initial CONTAINER_ID, aux CONTAINER, field CONTID
- allow to set own contid
- open code audit_set_containerid
- add contid inherited flag
- ccontainerid and pcontainerid eliminated due to inherited flag
- change name of container list funcitons
- rename containerid to contid
- convert initial container record to syscall aux
- fix spelling mistake of contidion in net/rfkill/core.c to avoid contid name collision
v2
- add check for children and threads
- add network namespace container identifier list
- add NETFILTER_PKT audit container identifier logging
- patch description and documentation clean-up and example
- reap unused ppid
Richard Guy Briggs (10):
audit: add container id
audit: log container info of syscalls
audit: add containerid support for ptrace and signals
audit: add support for non-syscall auxiliary records
audit: add containerid support for tty_audit
audit: add containerid filtering
audit: add support for containerid to network namespaces
audit: NETFILTER_PKT: record each container ID associated with a netNS
debug audit: read container ID of a process
rfkill: fix spelling mistake contidion to condition
drivers/tty/tty_audit.c | 5 +-
fs/proc/base.c | 53 +++++++++++++++++++
include/linux/audit.h | 68 ++++++++++++++++++++++++
include/uapi/linux/audit.h | 8 ++-
kernel/audit.c | 114 ++++++++++++++++++++++++++++++++++++++++
kernel/audit.h | 3 ++
kernel/auditfilter.c | 47 +++++++++++++++++
kernel/auditsc.c | 128 ++++++++++++++++++++++++++++++++++++++++++---
kernel/nsproxy.c | 4 ++
net/netfilter/xt_AUDIT.c | 12 ++++-
net/rfkill/core.c | 2 +-
11 files changed, 433 insertions(+), 11 deletions(-)
--
1.8.3.1
6 years, 4 months
[RFC PATCH ghak59 V1 0/6] audit: config_change normalizations and event record gathering
by Richard Guy Briggs
Make a number of changes to normalize CONFIG_CHANGE records by adding
missing op= fields, providing more information in existing op fields and
connecting all records to existing audit events.
The user record patch is included but is *optional* since there is doubt
that we want to disconnect the records from a single event.
Since tree purge records are processed after the EOE record is produced,
the order of operation of the EOE record and the purge will have to be
reversed so that the purge records can be included in the event.
Could I get some feedback on the format of the op field values
themselves? They shouldn't cause any text processing headaches but
there may be a better way of expressing them.
For reference, here are the calling methods and function tree for all
CONFIG_CHANGE events:
- audit_log_config_change() "op=set"
- AUDIT_SET:AUDIT_STATUS_PID
- AUDIT_SET:AUDIT_STATUS_LOST
- audit_do_config_change()
- AUDIT_SET:AUDIT_STATUS_FAILURE
- AUDIT_SET:AUDIT_STATUS_ENABLED
- AUDIT_SET:AUDIT_STATUS_RATE_LIMIT
- AUDIT_SET:AUDIT_STATUS_BACKLOG_LIMIT
- AUDIT_SET:AUDIT_STATUS_BACKLOG_WAIT_TIME
- audit_log_common_recv_msg()
- AUDIT_*USER* events (not CONFIG_CHANGE like all the rest)
- AUDIT_LOCKED "op=%s_rule"(add/remove)
- AUDIT_TRIM "op=trim"
- AUDIT_MAKE_EQUIV: "op=make_equiv"
- AUDIT_TTY_SET: "op=tty_set"
- audit_log_rule_change()
- AUDIT_ADD_RULE -F dir=:
- AUDIT_DEL_RULE -F dir=:
- audit_mark_log_rule_change()
- audit_autoremove_mark_rule() "op=autoremove_rule(mark)"
- audit_mark_handle_event()
- audit_mark_fsnotify_ops.handle_event
- audit_tree_log_remove_rule() "op=remove_rule(tree:%s)" from kill_rules()
- from trim_marked()
- AUDIT_TRIM: audit_trim_trees() "trim"
- audit_add_tree_rule() iterate_mounts err "add"
- audit_add_rule()
- audit_rule_change()
- AUDIT_ADD_RULE -F dir=:
- AUDIT_MAKE_EQUIV: audit_tag_tree() iterate_mounts err "equiv"
- from audit_kill_trees()
- __audit_free() "free"
- do_exit()
- copy_process() err
- __audit_syscall_exit() "exit"
- from evict_chunk() "evict"
- audit_tree_freeing_mark()
- audit_tree_ops.freeing_mark
- audit_watch_log_rule_change()
- audit_update_watch() "updated_rules(watch:inval)" : "updated_rules(watch:set)"
- audit_watch_handle_event() FS_CREATE|FS_MOVED_TO, FS_DELETE|FS_MOVED_FROM
- audit_watch_fsnotify_ops.handle_event
- audit_remove_parent_watches() "remove_rule(watch:parent)"
- audit_watch_handle_event() FS_DELETE_SELF|FS_UNMOUNT|FS_MOVE_SELF
- audit_watch_fsnotify_ops.handle_event
See: https://github.com/linux-audit/audit-kernel/issues/50
See: https://github.com/linux-audit/audit-kernel/issues/59
Richard Guy Briggs (6):
audit: give a clue what CONFIG_CHANGE op was involved
audit: add syscall information to CONFIG_CHANGE records
audit: exclude user records from syscall context
audit: hand taken context to audit_kill_trees for syscall logging
audit: move EOE record after kill_trees for exit/free
audit: extend config_change mark/watch/tree rule changes
kernel/audit.c | 20 ++++++++++++++------
kernel/audit.h | 4 ++--
kernel/audit_fsnotify.c | 4 ++--
kernel/audit_tree.c | 28 +++++++++++++++-------------
kernel/audit_watch.c | 8 +++++---
kernel/auditfilter.c | 2 +-
kernel/auditsc.c | 26 ++++++++++++++++++--------
7 files changed, 57 insertions(+), 35 deletions(-)
--
1.8.3.1
6 years, 5 months
[PATCH 0/6] audit: Fix various races when tagging and untagging mounts
by Jan Kara
Hello,
this series addresses the problems I have identified when trying to understand
how exactly is kernel/audit_tree.c using generic fsnotify framework. I hope
I have understood all the interactions right but careful review is certainly
welcome (CCing Al as he was the one implementing this code originally).
The patches have been tested by a stress test I have written which mounts &
unmounts filesystems in the directory tree while adding and removing audit
rules for this tree in parallel and accessing the tree to generate events.
Still some real-world testing would be welcome.
Honza
6 years, 5 months
[PATCH v2] audit: fix use-after-free in audit_add_watch
by Ronny Chevalier
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 <ronny.chevalier(a)hp.com>
---
v2:
- Move audit_get_watch before audit_find_parent. In the case of
audit_get_nd failing.
---
kernel/audit_watch.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c
index f1ba88994508..6d9b3f2bb1e2 100644
--- a/kernel/audit_watch.c
+++ b/kernel/audit_watch.c
@@ -430,6 +430,14 @@ int audit_add_watch(struct audit_krule *krule, struct list_head **list)
if (ret)
return ret;
+ /*
+ * 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);
+
/* either find an old parent or attach a new one */
parent = audit_find_parent(d_backing_inode(parent_path.dentry));
if (!parent) {
@@ -446,6 +454,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;
}
--
2.17.1
6 years, 5 months
[PATCH] audit: use ktime_get_coarse_ts64() for time access
by Arnd Bergmann
The API got renamed for consistency with the other time accessors,
this changes the audit caller as well.
Signed-off-by: Arnd Bergmann <arnd(a)arndb.de>
---
kernel/audit.c | 2 +-
kernel/auditsc.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/kernel/audit.c b/kernel/audit.c
index e7478cb58079..3e34b9f03cfe 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -1724,7 +1724,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 ceb1c4596c51..dbbf02f513a8 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);
}
/**
--
2.9.0
6 years, 5 months
auditctl for admin's accessing other user files
by Skaggs, Nicholas C
Hello
I noticed in the man page for auditctl, an example of how to monitor if admins are accessing other user's files. I created a rule like the one in the example. This is great that it is pulling the action and user calling the action!
The rule
-a always,exit -S all -F dir=/home/username/ -F uid=0 -C auid!=obj_uid
I will pull a report on the findings with
aureport -f -i | grep /home/username/
The report is heavier than anticipated so I tried to make an adjustment to only capture what happens in the directory
-a always,exit -S all -F path=/home/username/ -F uid=0 -C auid!=obj_uid
... but that is returning with Error sending add rule data request (Invalid argument)
I then tried the below rule; it does not return an error upon add, but when I do an auditctl -l there are no rules listed
-a always,exit -S all -F path=/home/username/ -p=rwxa -F uid=0 -C auid!=obj_uid
Is there a preferred way to set the rule, maybe on the inode of the directory, but does not lose the ability to see if an admin is doing it and what action? I have been adding these on the fly, instead of adding to the /etc/audit/audit.rules file, for now.
Thanks!
Nick Skaggs
6 years, 5 months
[PATCH] audit: fix use-after-free in audit_add_watch
by Ronny Chevalier
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 <ronny.chevalier(a)hp.com>
---
kernel/audit_watch.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c
index f1ba88994508..4bb8d7718fbc 100644
--- a/kernel/audit_watch.c
+++ b/kernel/audit_watch.c
@@ -421,6 +421,14 @@ int audit_add_watch(struct audit_krule *krule, struct list_head **list)
mutex_unlock(&audit_filter_mutex);
+ /*
+ * 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);
+
/* Avoid calling path_lookup under audit_filter_mutex. */
ret = audit_get_nd(watch, &parent_path);
@@ -446,6 +454,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;
}
--
2.17.1
6 years, 5 months