[PATCH v2] audit: add missing fields to AUDIT_CONFIG_CHANGE event
by Steve Grubb
There are very important fields necessary to understand who is adding
audit rules and a little more context about the environment in which
its happening. This adds pid, uid, tty, subj, comm, and exe
information to the event. These are required fields.
* V2 added calls to audit_put_tty()
See: https://github.com/linux-audit/audit-kernel/issues/59
Signed-off-by: Steve Grubb <sgrubb(a)redhat.com>
Reviewed-by: Richard Guy Briggs <rgb(a)redhat.com>
---
kernel/audit_watch.c | 24 ++++++++++++++++++++----
kernel/auditfilter.c | 19 ++++++++++++++++---
2 files changed, 36 insertions(+), 7 deletions(-)
diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c
index 9eb8b3511636..fd68e99042f1 100644
--- a/kernel/audit_watch.c
+++ b/kernel/audit_watch.c
@@ -239,14 +239,30 @@ static struct audit_watch *audit_dupe_watch(struct
audit_watch *old)
static void audit_watch_log_rule_change(struct audit_krule *r, struct
audit_watch *w, char *op)
{
if (audit_enabled) {
+ struct tty_struct *tty;
+ const struct cred *cred;
struct audit_buffer *ab;
+ char comm[sizeof(current->comm)];
+
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=");
+
+ cred = current_cred();
+ tty = audit_get_tty(current);
+ audit_log_format(ab, "pid=%d uid=%u auid=%u tty=%s ses=%u",
+ task_tgid_nr(current),
+ from_kuid(&init_user_ns, cred->uid),
+ from_kuid(&init_user_ns,
+ audit_get_loginuid(current)),
+ tty ? tty_name(tty) : "(none)",
+ audit_get_sessionid(current));
+ audit_put_tty(tty);
+ audit_log_task_context(ab);
+ audit_log_format(ab, " comm=");
+ audit_log_untrustedstring(ab, get_task_comm(comm, current));
+ audit_log_d_path_exe(ab, current->mm);
+ audit_log_format(ab, "op=%s path=", op);
audit_log_untrustedstring(ab, w->path);
audit_log_key(ab, r->filterkey);
audit_log_format(ab, " list=%d res=1", r->listnr);
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index 0b0aa5854dac..9dd4d67f1b95 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -1065,8 +1065,9 @@ static void audit_list_rules(int seq, struct
sk_buff_head *q)
static void audit_log_rule_change(char *action, struct audit_krule *rule, int
res)
{
struct audit_buffer *ab;
- uid_t loginuid = from_kuid(&init_user_ns, audit_get_loginuid(current));
- unsigned int sessionid = audit_get_sessionid(current);
+ struct tty_struct *tty;
+ const struct cred *cred;
+ char comm[sizeof(current->comm)];
if (!audit_enabled)
return;
@@ -1074,8 +1075,20 @@ static void audit_log_rule_change(char *action, struct
audit_krule *rule, int re
ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
if (!ab)
return;
- audit_log_format(ab, "auid=%u ses=%u" ,loginuid, sessionid);
+
+ cred = current_cred();
+ tty = audit_get_tty(current);
+ audit_log_format(ab, "pid=%d uid=%u auid=%u tty=%s ses=%u",
+ task_tgid_nr(current),
+ from_kuid(&init_user_ns, cred->uid),
+ from_kuid(&init_user_ns, audit_get_loginuid(current)),
+ tty ? tty_name(tty) : "(none)",
+ audit_get_sessionid(current));
+ audit_put_tty(tty);
audit_log_task_context(ab);
+ audit_log_format(ab, " comm=");
+ audit_log_untrustedstring(ab, get_task_comm(comm, current));
+ audit_log_d_path_exe(ab, current->mm);
audit_log_format(ab, " op=%s", action);
audit_log_key(ab, rule->filterkey);
audit_log_format(ab, " list=%d res=%d", rule->listnr, res);
--
2.13.6
7 years
libaudit issues
by Valerio Ramicone
Hello.
I would like to have a list of issues from libaudit. Is there a database?
Thanks
7 years
[PATCH 1/1] audit: log binding and unbinding to netlink multicast
by Steve Grubb
Log information about programs connecting and disconnecting to the audit
netlink multicast socket. This is needed so that during investigations a
security officer can tell who or what had access to the audit trail. This
helps to meet the FAU_SAR.2 requirement for Common Criteria. Sample
event:
type=UNKNOWN[1332] msg=audit(1507924331.540:3): pid=1 uid=0
auid=4294967295 tty=(none) ses=4294967295 subj=kernel comm="systemd"
exe="/usr/lib/systemd/systemd" nlnk-grp=1 op=connect res=1
Signed-off-by: sgrubb <sgrubb(a)redhat.com>
---
include/uapi/linux/audit.h | 1 +
kernel/audit.c | 48 ++++++++++++++++++++++++++++++++++++++++++----
2 files changed, 45 insertions(+), 4 deletions(-)
diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h
index 0714a66f0e0c..892e63d9f2c1 100644
--- a/include/uapi/linux/audit.h
+++ b/include/uapi/linux/audit.h
@@ -112,6 +112,7 @@
#define AUDIT_FEATURE_CHANGE 1328 /* audit log listing feature changes */
#define AUDIT_REPLACE 1329 /* Replace auditd if this packet unanswerd */
#define AUDIT_KERN_MODULE 1330 /* Kernel Module events */
+#define AUDIT_EVENT_LISTENER 1332 /* Task joined multicast read socket */
#define AUDIT_AVC 1400 /* SE Linux avc denial or grant */
#define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */
diff --git a/kernel/audit.c b/kernel/audit.c
index 1baabc9539b4..3d2461be83a8 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -1476,22 +1476,61 @@ static void audit_receive(struct sk_buff *skb)
mutex_unlock(&audit_cmd_mutex);
}
+/* Log information about who is connecting to the audit multicast socket */
+static void audit_log_multicast_bind(int group, const char *op, int err)
+{
+ const struct cred *cred;
+ struct tty_struct *tty;
+ char comm[sizeof(current->comm)];
+ struct audit_buffer *ab;
+
+ ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_EVENT_LISTENER);
+ if (!ab)
+ return;
+
+ cred = current_cred();
+ tty = audit_get_tty(current);
+
+ audit_log_format(ab, "pid=%u uid=%u auid=%u tty=%s ses=%u",
+ task_pid_nr(current),
+ from_kuid(&init_user_ns, cred->uid),
+ from_kuid(&init_user_ns, audit_get_loginuid(current)),
+ tty ? tty_name(tty) : "(none)",
+ audit_get_sessionid(current));
+ audit_put_tty(tty);
+ audit_log_task_context(ab); /* subj= */
+ audit_log_format(ab, " comm=");
+ audit_log_untrustedstring(ab, get_task_comm(comm, current));
+ audit_log_d_path_exe(ab, current->mm); /* exe= */
+ audit_log_format(ab, " nlnk-grp=%d op=%s res=%d", group, op, !err);
+ audit_log_end(ab);
+}
+
/* Run custom bind function on netlink socket group connect or bind requests. */
-static int audit_bind(struct net *net, int group)
+static int audit_multicast_bind(struct net *net, int group)
{
+ int err = 0;
+
if (!capable(CAP_AUDIT_READ))
- return -EPERM;
+ err = -EPERM;
+ audit_log_multicast_bind(group, "connect", err);
- return 0;
+ return err;
+}
+
+static void audit_multicast_unbind(struct net *net, int group)
+{
+ audit_log_multicast_bind(group, "disconnect", 0);
}
static int __net_init audit_net_init(struct net *net)
{
struct netlink_kernel_cfg cfg = {
.input = audit_receive,
- .bind = audit_bind,
+ .bind = audit_multicast_bind,
.flags = NL_CFG_F_NONROOT_RECV,
.groups = AUDIT_NLGRP_MAX,
+ .unbind = audit_multicast_unbind,
};
struct audit_net *aunet = net_generic(net, audit_net_id);
--
2.13.6
7 years
[PATCH 1/1] audit: add missing fields to AUDIT_CONFIG_CHANGE event
by Steve Grubb
There are very important fields necessary to understand who is adding
audit rules and a little more context about the environment in which
its happening. This adds pid, uid, tty, subj, comm, and exe
information to the event. These are required fields.
Signed-off-by: sgrubb <sgrubb(a)redhat.com>
---
kernel/audit_watch.c | 23 +++++++++++++++++++----
kernel/auditfilter.c | 18 +++++++++++++++---
2 files changed, 34 insertions(+), 7 deletions(-)
diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c
index 9eb8b3511636..63abc2ba1372 100644
--- a/kernel/audit_watch.c
+++ b/kernel/audit_watch.c
@@ -239,14 +239,29 @@ static struct audit_watch *audit_dupe_watch(struct audit_watch *old)
static void audit_watch_log_rule_change(struct audit_krule *r, struct audit_watch *w, char *op)
{
if (audit_enabled) {
+ struct tty_struct *tty;
+ const struct cred *cred;
struct audit_buffer *ab;
+ char comm[sizeof(current->comm)];
+
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=");
+
+ tty = audit_get_tty(current);
+ cred = current_cred();
+ audit_log_format(ab, "pid=%d uid=%u auid=%u tty=%s ses=%u",
+ task_tgid_nr(current),
+ from_kuid(&init_user_ns, cred->uid),
+ from_kuid(&init_user_ns,
+ audit_get_loginuid(current)),
+ tty ? tty_name(tty) : "(none)",
+ audit_get_sessionid(current));
+ audit_log_task_context(ab);
+ audit_log_format(ab, " comm=");
+ audit_log_untrustedstring(ab, get_task_comm(comm, current));
+ audit_log_d_path_exe(ab, current->mm);
+ audit_log_format(ab, "op=%s path=", op);
audit_log_untrustedstring(ab, w->path);
audit_log_key(ab, r->filterkey);
audit_log_format(ab, " list=%d res=1", r->listnr);
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index 0b0aa5854dac..5e2a953da29a 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -1065,17 +1065,29 @@ static void audit_list_rules(int seq, struct sk_buff_head *q)
static void audit_log_rule_change(char *action, struct audit_krule *rule, int res)
{
struct audit_buffer *ab;
- uid_t loginuid = from_kuid(&init_user_ns, audit_get_loginuid(current));
- unsigned int sessionid = audit_get_sessionid(current);
+ struct tty_struct *tty;
+ const struct cred *cred;
+ char comm[sizeof(current->comm)];
if (!audit_enabled)
return;
+ tty = audit_get_tty(current);
+ cred = current_cred();
+
ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
if (!ab)
return;
- audit_log_format(ab, "auid=%u ses=%u" ,loginuid, sessionid);
+ audit_log_format(ab, "pid=%d uid=%u auid=%u tty=%s ses=%u",
+ task_tgid_nr(current),
+ from_kuid(&init_user_ns, cred->uid),
+ from_kuid(&init_user_ns, audit_get_loginuid(current)),
+ tty ? tty_name(tty) : "(none)",
+ audit_get_sessionid(current));
audit_log_task_context(ab);
+ audit_log_format(ab, " comm=");
+ audit_log_untrustedstring(ab, get_task_comm(comm, current));
+ audit_log_d_path_exe(ab, current->mm);
audit_log_format(ab, " op=%s", action);
audit_log_key(ab, rule->filterkey);
audit_log_format(ab, " list=%d res=%d", rule->listnr, res);
--
2.13.6
7 years
[PATCH 1/1] audit: Add new syscalls to the perm=w filter
by Steve Grubb
The audit subsystem allows selecting audit events based on watches for
a particular behavior like writing to a file. A lot of syscalls have
been added without updating the list. This patch adds 2 syscalls to the
write filters: fallocate and renameat2.
Signed-off-by: sgrubb <sgrubb(a)redhat.com>
---
include/asm-generic/audit_dir_write.h | 4 ++++
include/asm-generic/audit_write.h | 3 +++
2 files changed, 7 insertions(+)
diff --git a/include/asm-generic/audit_dir_write.h b/include/asm-generic/audit_dir_write.h
index 7b61db4fe72b..d9a53eaeea35 100644
--- a/include/asm-generic/audit_dir_write.h
+++ b/include/asm-generic/audit_dir_write.h
@@ -30,3 +30,7 @@ __NR_renameat,
__NR_linkat,
__NR_symlinkat,
#endif
+#ifdef __NR_renameat2
+__NR_renameat2,
+#endif
+
diff --git a/include/asm-generic/audit_write.h b/include/asm-generic/audit_write.h
index 274575d7129f..4fa65816acd3 100644
--- a/include/asm-generic/audit_write.h
+++ b/include/asm-generic/audit_write.h
@@ -19,3 +19,6 @@ __NR_ftruncate64,
#ifdef __NR_bind
__NR_bind, /* bind can affect fs object only in one way... */
#endif
+#ifdef __NR_fallocate
+__NR_fallocate,
+#endif
--
2.13.6
7 years
Detecting execution of files in rwtab
by Kevin Sullivan
Sorry if this topic has already been discussed, but I was unable to find
information about it in the mailing list.
I am running auditd on a machine that is configured with readonly-root
support. For this configuration to work, I have files listed in
/etc/rwtab.d/ that need to be read-write, but are on my hard-drive that is
read-only.
So if I add an audit rule for a random file:
# auditctl -w /etc/rc.d/rc.local -p x -k rclocal
If /etc/rc.d/rc.local is mounted in a tmpfs (because of readonly-root),
running rc.local will not produce an event. If I unmount /etc/rc.d/rc.local
and run it, an event will be generated.
How am I supposed to audit files that are mounted in tmpfs due to rwtab and
readonly-root?
Thanks,
Kevin
7 years
[PATCH 1/1] audit: Allow auditd to set pid to 0 to end auditing
by Steve Grubb
The API to end auditing has historically been for auditd to set the
pid to 0. This patch restores that functionality.
Signed-off-by: sgrubb <sgrubb(a)redhat.com>
---
kernel/audit.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/kernel/audit.c b/kernel/audit.c
index 6dd556931739..1baabc9539b4 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -1197,8 +1197,9 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
pid_t auditd_pid;
struct pid *req_pid = task_tgid(current);
- /* sanity check - PID values must match */
- if (new_pid != pid_vnr(req_pid))
+ /* Sanity check - PID values must match. A 0
+ * pid is how auditd normally ends auditing. */
+ if (new_pid && (new_pid != pid_vnr(req_pid)))
return -EINVAL;
/* test the auditd connection */
@@ -1206,7 +1207,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
auditd_pid = auditd_pid_vnr();
/* only the current auditd can unregister itself */
- if ((!new_pid) && (new_pid != auditd_pid)) {
+ if (new_pid && auditd_pid && (new_pid != auditd_pid)) {
audit_log_config_change("audit_pid", new_pid,
auditd_pid, 0);
return -EACCES;
--
2.13.6
7 years
audit 2.8.1 released
by Steve Grubb
Hello,
I've just released a new version of the audit daemon. It can be downloaded
from http://people.redhat.com/sgrubb/audit. It will also be in rawhide
soon. The ChangeLog is:
- Fix NULL ptr dereference in audispd plugin_dir parser
- Signed/unsigned cleanup
It was discovered that in a new installation which used the updated
audispd.conf, a NULL pointer would be dereferenced leading audispd to crash on
boot. This was fixed and the code was checked by static analysis. Some signed
/ unsigned things were fixed up.
SHA256: 1becde92ff6e81798fa8878820ab2497d867036a6596f55109504b37c8b33b6c
Please let me know if you run across any problems with this release.
-Steve
7 years
audit 2.8 released
by Steve Grubb
Hello,
I've just released a new version of the audit daemon. It can be downloaded
from http://people.redhat.com/sgrubb/audit. It will also be in rawhide
soon. The ChangeLog is:
- Add support for ambient capability fields (Richard Guy Briggs)
- Update auparse-normalizer to support TTY events
- Add auparse_normalize_object_primary2 API
- In ausearch text format, add 'to xxx' for mount operations
- In ausearch add new --extra-obj2 option for CSV output
- In auparse_normalize, pick up second file name for rename syscalls
- In auparse_normalize, pick up permission & ownership changes as obj2
- In auparse_normalize, pick up uid/gid for setuid/gid syscalls as obj2
- In auparse_normalize, pick up link for symlink syscalls as obj2
- In auparse_normalize, correct mount records based on success
- In auparse_normalize, correct object for USER_MGMT, ACCT_LOCK, & ACCT_UNLOCK
- Add default port to auditd.conf (#1455598)
- Fix auvirt to report AVC's (#982154)
- Add sockaddr accessor functions in auparse
- In ausearch, use auparse_interpret_sock_address for text mode output
- In remote logging, inform client auditd is suspended and please disconnect
- Auditd and audisp-remote now supports IPv6
- In auparse function auparse_goto_record_num, make it positioned on first
field
- In auparse_normalize, finish support for MAC_STATUS and MAC_CONFIG events
- Add support for filesystem filter type (Richard Guy Briggs)
- Add file system type table for fstype lookup
- Add command line option to auditd & audispd for config dir path (Dan Born)
- Fix auparse serial parsing of event when system time < 9 characters (kruvin)
- In auparse, allow non-equality comparisons for uid & gid fields (#1399314)
- In auparse_normalize, add support for USER_DEVICE events
- In audispd.conf, add new plugin_dir config item to customize plugin location
- Add support for FANOTIFY event
- Improve auparse_normalize support for SECCOMP events
- In auparse_normalize, pick up comm for successful memory allocations
This is a big release with a lot of code changes all over. There's too much to
give a detailed description of, so I'll summarize the major items.
Lots of updates for the auparse_normalizer to improve support on many events.
Added new object2 api to access a second object when available. Remote logging
now supports IPv6 and other remote logging improvements. Fix bugs in auvirt
that prevented locating AVC's for the VM. Add support for filesystem filter
type. Add command line option to auditd & audispd for config dir path. In
auparse, allow non-equality comparisons for uid & gid fields.
SHA256: b4012cbc21e34e53f26696e551d22b2dded07669207554ecb670ee082f0145a7
Please let me know if you run across any problems with this release.
-Steve
7 years
[PATCH v7 1/1] audit: Record fanotify access control decisions
by Steve Grubb
Hello,
The fanotify interface allows user space daemons to make access
control decisions. Under common criteria requirements, we need to
optionally record decisions based on policy. This patch adds a bit mask,
FAN_AUDIT, that a user space daemon can 'or' into the response decision
which will tell the kernel that it made a decision and record it.
It would be used something like this in user space code:
response.response = FAN_DENY | FAN_AUDIT;
write(fd, &response, sizeof(struct fanotify_response));
When the syscall ends, the audit system will record the decision as a
AUDIT_FANOTIFY auxiliary record to denote that the reason this event
occurred is the result of an access control decision from fanotify
rather than DAC or MAC policy.
A sample event looks like this:
type=PATH msg=audit(1504310584.332:290): item=0 name="./evil-ls"
inode=1319561 dev=fc:03 mode=0100755 ouid=1000 ogid=1000 rdev=00:00
obj=unconfined_u:object_r:user_home_t:s0 nametype=NORMAL
type=CWD msg=audit(1504310584.332:290): cwd="/home/sgrubb"
type=SYSCALL msg=audit(1504310584.332:290): arch=c000003e syscall=2
success=no exit=-1 a0=32cb3fca90 a1=0 a2=43 a3=8 items=1 ppid=901
pid=959 auid=1000 uid=1000 gid=1000 euid=1000 suid=1000
fsuid=1000 egid=1000 sgid=1000 fsgid=1000 tty=pts1 ses=3 comm="bash"
exe="/usr/bin/bash" subj=unconfined_u:unconfined_r:unconfined_t:
s0-s0:c0.c1023 key=(null)
type=FANOTIFY msg=audit(1504310584.332:290): resp=2
Prior to using the audit flag, the developer needs to call
fanotify_init or'ing in FAN_ENABLE_AUDIT to ensure that the kernel
supports auditing. The calling process must also have the CAP_AUDIT_WRITE
capability.
* v5 remove ifdef around code block and == 0 from boolean check
* v6 update adds empty inline audit_fanotify function for when
CONFIG_AUDITSYSCALL is not defined.
* v7 rename audit_enabled variable to "audit" to avoid symbol collision
Signed-off-by: sgrubb <sgrubb(a)redhat.com>
Reviewed-by: Amir Goldstein <amir73il(a)gmail.com>
---
fs/notify/fanotify/fanotify.c | 8 +++++++-
fs/notify/fanotify/fanotify_user.c | 16 +++++++++++++++-
fs/notify/fdinfo.c | 3 +++
include/linux/audit.h | 10 ++++++++++
include/linux/fsnotify_backend.h | 1 +
include/uapi/linux/audit.h | 1 +
include/uapi/linux/fanotify.h | 3 +++
kernel/auditsc.c | 6 ++++++
8 files changed, 46 insertions(+), 2 deletions(-)
diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c
index 2fa99ae..1968d21 100644
--- a/fs/notify/fanotify/fanotify.c
+++ b/fs/notify/fanotify/fanotify.c
@@ -9,6 +9,7 @@
#include <linux/sched/user.h>
#include <linux/types.h>
#include <linux/wait.h>
+#include <linux/audit.h>
#include "fanotify.h"
@@ -78,7 +79,7 @@ static int fanotify_get_response(struct fsnotify_group *group,
fsnotify_finish_user_wait(iter_info);
out:
/* userspace responded, convert to something usable */
- switch (event->response) {
+ switch (event->response & ~FAN_AUDIT) {
case FAN_ALLOW:
ret = 0;
break;
@@ -86,6 +87,11 @@ static int fanotify_get_response(struct fsnotify_group *group,
default:
ret = -EPERM;
}
+
+ /* Check if the response should be audited */
+ if (event->response & FAN_AUDIT)
+ audit_fanotify(event->response & ~FAN_AUDIT);
+
event->response = 0;
pr_debug("%s: group=%p event=%p about to return ret=%d\n", __func__,
diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c
index 907a481..ea3c458 100644
--- a/fs/notify/fanotify/fanotify_user.c
+++ b/fs/notify/fanotify/fanotify_user.c
@@ -179,7 +179,7 @@ static int process_access_response(struct fsnotify_group *group,
* userspace can send a valid response or we will clean it up after the
* timeout
*/
- switch (response) {
+ switch (response & ~FAN_AUDIT) {
case FAN_ALLOW:
case FAN_DENY:
break;
@@ -190,6 +190,9 @@ static int process_access_response(struct fsnotify_group *group,
if (fd < 0)
return -EINVAL;
+ if ((response & FAN_AUDIT) && !group->fanotify_data.audit)
+ return -EINVAL;
+
event = dequeue_event(group, fd);
if (!event)
return -ENOENT;
@@ -721,7 +724,11 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
+#ifdef CONFIG_AUDITSYSCALL
+ if (flags & ~(FAN_ALL_INIT_FLAGS | FAN_ENABLE_AUDIT))
+#else
if (flags & ~FAN_ALL_INIT_FLAGS)
+#endif
return -EINVAL;
if (event_f_flags & ~FANOTIFY_INIT_ALL_EVENT_F_BITS)
@@ -805,6 +812,13 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
group->fanotify_data.max_marks = FANOTIFY_DEFAULT_MAX_MARKS;
}
+ if (flags & FAN_ENABLE_AUDIT) {
+ fd = -EPERM;
+ if (!capable(CAP_AUDIT_WRITE))
+ goto out_destroy_group;
+ group->fanotify_data.audit = true;
+ }
+
fd = anon_inode_getfd("[fanotify]", &fanotify_fops, group, f_flags);
if (fd < 0)
goto out_destroy_group;
diff --git a/fs/notify/fdinfo.c b/fs/notify/fdinfo.c
index dd63aa9..ed311e3 100644
--- a/fs/notify/fdinfo.c
+++ b/fs/notify/fdinfo.c
@@ -156,6 +156,9 @@ void fanotify_show_fdinfo(struct seq_file *m, struct file *f)
if (group->fanotify_data.max_marks == UINT_MAX)
flags |= FAN_UNLIMITED_MARKS;
+ if (group->fanotify_data.audit)
+ flags |= FAN_ENABLE_AUDIT;
+
seq_printf(m, "fanotify flags:%x event-flags:%x\n",
flags, group->fanotify_data.f_flags);
diff --git a/include/linux/audit.h b/include/linux/audit.h
index 2150bdc..9095617 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -360,6 +360,7 @@ extern int __audit_log_bprm_fcaps(struct linux_binprm *bprm,
extern void __audit_log_capset(const struct cred *new, const struct cred *old);
extern void __audit_mmap_fd(int fd, int flags);
extern void __audit_log_kern_module(char *name);
+extern void __audit_fanotify(unsigned int response);
static inline void audit_ipc_obj(struct kern_ipc_perm *ipcp)
{
@@ -456,6 +457,12 @@ static inline void audit_log_kern_module(char *name)
__audit_log_kern_module(name);
}
+static inline void audit_fanotify(unsigned int response)
+{
+ if (!audit_dummy_context())
+ __audit_fanotify(response);
+}
+
extern int audit_n_rules;
extern int audit_signals;
#else /* CONFIG_AUDITSYSCALL */
@@ -572,6 +579,9 @@ static inline void audit_log_kern_module(char *name)
{
}
+static inline void audit_fanotify(unsigned int response)
+{ }
+
static inline void audit_ptrace(struct task_struct *t)
{ }
#define audit_n_rules 0
diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h
index c6c6931..f4131f2 100644
--- a/include/linux/fsnotify_backend.h
+++ b/include/linux/fsnotify_backend.h
@@ -190,6 +190,7 @@ struct fsnotify_group {
int f_flags;
unsigned int max_marks;
struct user_struct *user;
+ bool audit;
} fanotify_data;
#endif /* CONFIG_FANOTIFY */
};
diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h
index 0714a66..221f8b7 100644
--- a/include/uapi/linux/audit.h
+++ b/include/uapi/linux/audit.h
@@ -112,6 +112,7 @@
#define AUDIT_FEATURE_CHANGE 1328 /* audit log listing feature changes */
#define AUDIT_REPLACE 1329 /* Replace auditd if this packet unanswerd */
#define AUDIT_KERN_MODULE 1330 /* Kernel Module events */
+#define AUDIT_FANOTIFY 1331 /* Fanotify access decision */
#define AUDIT_AVC 1400 /* SE Linux avc denial or grant */
#define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */
diff --git a/include/uapi/linux/fanotify.h b/include/uapi/linux/fanotify.h
index 030508d..5dda19a 100644
--- a/include/uapi/linux/fanotify.h
+++ b/include/uapi/linux/fanotify.h
@@ -35,6 +35,7 @@
#define FAN_UNLIMITED_QUEUE 0x00000010
#define FAN_UNLIMITED_MARKS 0x00000020
+#define FAN_ENABLE_AUDIT 0x00000040
#define FAN_ALL_INIT_FLAGS (FAN_CLOEXEC | FAN_NONBLOCK | \
FAN_ALL_CLASS_BITS | FAN_UNLIMITED_QUEUE |\
@@ -99,6 +100,8 @@ struct fanotify_response {
/* Legit userspace responses to a _PERM event */
#define FAN_ALLOW 0x01
#define FAN_DENY 0x02
+#define FAN_AUDIT 0x10 /* Bit mask to create audit record for result */
+
/* No fd set in event */
#define FAN_NOFD -1
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 3260ba2..e046de8 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -2390,6 +2390,12 @@ void __audit_log_kern_module(char *name)
context->type = AUDIT_KERN_MODULE;
}
+void __audit_fanotify(unsigned int response)
+{
+ audit_log(current->audit_context, GFP_KERNEL,
+ AUDIT_FANOTIFY, "resp=%u", response);
+}
+
static void audit_log_task(struct audit_buffer *ab)
{
kuid_t auid, uid;
--
2.9.5
7 years