* [PATCH v6 1/1] audit: Record fanotify access control decisions
@ 2017-09-26 21:11 Steve Grubb
2017-09-29 19:35 ` kbuild test robot
2017-09-30 0:09 ` kbuild test robot
0 siblings, 2 replies; 4+ messages in thread
From: Steve Grubb @ 2017-09-26 21:11 UTC (permalink / raw)
To: fsdevel; +Cc: Linux Audit, inux-api, Jan Kara, Amir Goldstein, Paul Moore
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.
* This v6 update adds empty inline audit_fanotify function for when
CONFIG_AUDITSYSCALL is not defined.
Signed-off-by: sgrubb <sgrubb@redhat.com>
Reviewed-by: Amir Goldstein <amir73il@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_enabled)
+ 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_enabled = 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_enabled)
+ 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_enabled;
} 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
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH v6 1/1] audit: Record fanotify access control decisions
2017-09-26 21:11 [PATCH v6 1/1] audit: Record fanotify access control decisions Steve Grubb
@ 2017-09-29 19:35 ` kbuild test robot
2017-09-30 0:09 ` kbuild test robot
1 sibling, 0 replies; 4+ messages in thread
From: kbuild test robot @ 2017-09-29 19:35 UTC (permalink / raw)
To: Steve Grubb
Cc: kbuild-all, fsdevel, Linux Audit, inux-api, Jan Kara,
Amir Goldstein, Paul Moore
[-- Attachment #1: Type: text/plain, Size: 4937 bytes --]
Hi Steve,
[auto build test ERROR on linus/master]
[also build test ERROR on v4.14-rc2 next-20170929]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Steve-Grubb/audit-Record-fanotify-access-control-decisions/20170930-005627
config: i386-randconfig-x0-09300058 (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
# save the attached .config to linux build tree
make ARCH=i386
All error/warnings (new ones prefixed by >>):
In file included from fs/exec.c:56:0:
>> include/linux/audit.h:215:23: error: expected identifier or '(' before numeric constant
#define audit_enabled 0
^
>> include/linux/fsnotify_backend.h:193:9: note: in expansion of macro 'audit_enabled'
bool audit_enabled;
^~~~~~~~~~~~~
In file included from include/linux/fsnotify.h:14:0,
from fs/exec.c:59:
>> include/linux/fsnotify_backend.h:194:3: warning: no semicolon at end of struct or union
} fanotify_data;
^
vim +215 include/linux/audit.h
96368701 Paul Moore 2016-01-13 168
96368701 Paul Moore 2016-01-13 169 extern u32 audit_enabled;
96368701 Paul Moore 2016-01-13 170 #else /* CONFIG_AUDIT */
96368701 Paul Moore 2016-01-13 171 static inline __printf(4, 5)
96368701 Paul Moore 2016-01-13 172 void audit_log(struct audit_context *ctx, gfp_t gfp_mask, int type,
96368701 Paul Moore 2016-01-13 173 const char *fmt, ...)
96368701 Paul Moore 2016-01-13 174 { }
96368701 Paul Moore 2016-01-13 175 static inline struct audit_buffer *audit_log_start(struct audit_context *ctx,
96368701 Paul Moore 2016-01-13 176 gfp_t gfp_mask, int type)
96368701 Paul Moore 2016-01-13 177 {
96368701 Paul Moore 2016-01-13 178 return NULL;
96368701 Paul Moore 2016-01-13 179 }
96368701 Paul Moore 2016-01-13 180 static inline __printf(2, 3)
96368701 Paul Moore 2016-01-13 181 void audit_log_format(struct audit_buffer *ab, const char *fmt, ...)
96368701 Paul Moore 2016-01-13 182 { }
96368701 Paul Moore 2016-01-13 183 static inline void audit_log_end(struct audit_buffer *ab)
96368701 Paul Moore 2016-01-13 184 { }
96368701 Paul Moore 2016-01-13 185 static inline void audit_log_n_hex(struct audit_buffer *ab,
96368701 Paul Moore 2016-01-13 186 const unsigned char *buf, size_t len)
96368701 Paul Moore 2016-01-13 187 { }
96368701 Paul Moore 2016-01-13 188 static inline void audit_log_n_string(struct audit_buffer *ab,
96368701 Paul Moore 2016-01-13 189 const char *buf, size_t n)
96368701 Paul Moore 2016-01-13 190 { }
96368701 Paul Moore 2016-01-13 191 static inline void audit_log_n_untrustedstring(struct audit_buffer *ab,
96368701 Paul Moore 2016-01-13 192 const char *string, size_t n)
96368701 Paul Moore 2016-01-13 193 { }
96368701 Paul Moore 2016-01-13 194 static inline void audit_log_untrustedstring(struct audit_buffer *ab,
96368701 Paul Moore 2016-01-13 195 const char *string)
96368701 Paul Moore 2016-01-13 196 { }
96368701 Paul Moore 2016-01-13 197 static inline void audit_log_d_path(struct audit_buffer *ab,
96368701 Paul Moore 2016-01-13 198 const char *prefix,
96368701 Paul Moore 2016-01-13 199 const struct path *path)
96368701 Paul Moore 2016-01-13 200 { }
96368701 Paul Moore 2016-01-13 201 static inline void audit_log_key(struct audit_buffer *ab, char *key)
96368701 Paul Moore 2016-01-13 202 { }
96368701 Paul Moore 2016-01-13 203 static inline void audit_log_link_denied(const char *string,
96368701 Paul Moore 2016-01-13 204 const struct path *link)
96368701 Paul Moore 2016-01-13 205 { }
96368701 Paul Moore 2016-01-13 206 static inline void audit_log_secctx(struct audit_buffer *ab, u32 secid)
96368701 Paul Moore 2016-01-13 207 { }
96368701 Paul Moore 2016-01-13 208 static inline int audit_log_task_context(struct audit_buffer *ab)
96368701 Paul Moore 2016-01-13 209 {
96368701 Paul Moore 2016-01-13 210 return 0;
96368701 Paul Moore 2016-01-13 211 }
96368701 Paul Moore 2016-01-13 212 static inline void audit_log_task_info(struct audit_buffer *ab,
96368701 Paul Moore 2016-01-13 213 struct task_struct *tsk)
96368701 Paul Moore 2016-01-13 214 { }
96368701 Paul Moore 2016-01-13 @215 #define audit_enabled 0
96368701 Paul Moore 2016-01-13 216 #endif /* CONFIG_AUDIT */
96368701 Paul Moore 2016-01-13 217
:::::: The code at line 215 was first introduced by commit
:::::: 96368701e1c89057bbf39222e965161c68a85b4b audit: force seccomp event logging to honor the audit_enabled flag
:::::: TO: Paul Moore <pmoore@redhat.com>
:::::: CC: Paul Moore <paul@paul-moore.com>
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 27638 bytes --]
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH v6 1/1] audit: Record fanotify access control decisions
2017-09-26 21:11 [PATCH v6 1/1] audit: Record fanotify access control decisions Steve Grubb
2017-09-29 19:35 ` kbuild test robot
@ 2017-09-30 0:09 ` kbuild test robot
1 sibling, 0 replies; 4+ messages in thread
From: kbuild test robot @ 2017-09-30 0:09 UTC (permalink / raw)
To: Steve Grubb
Cc: kbuild-all, fsdevel, Linux Audit, inux-api, Jan Kara,
Amir Goldstein, Paul Moore
[-- Attachment #1: Type: text/plain, Size: 4557 bytes --]
Hi Steve,
[auto build test ERROR on linus/master]
[also build test ERROR on v4.14-rc2 next-20170929]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Steve-Grubb/audit-Record-fanotify-access-control-decisions/20170930-005627
config: x86_64-randconfig-b0-09300453 (attached as .config)
compiler: gcc-4.4 (Debian 4.4.7-8) 4.4.7
reproduce:
# save the attached .config to linux build tree
make ARCH=x86_64
All errors (new ones prefixed by >>):
In file included from include/linux/fsnotify.h:14,
from fs/exec.c:59:
>> include/linux/fsnotify_backend.h:193: error: expected identifier or '(' before numeric constant
include/linux/fsnotify_backend.h:194: warning: no semicolon at end of struct or union
vim +193 include/linux/fsnotify_backend.h
122
123 /*
124 * A group is a "thing" that wants to receive notification about filesystem
125 * events. The mask holds the subset of event types this group cares about.
126 * refcnt on a group is up to the implementor and at any moment if it goes 0
127 * everything will be cleaned up.
128 */
129 struct fsnotify_group {
130 /*
131 * How the refcnt is used is up to each group. When the refcnt hits 0
132 * fsnotify will clean up all of the resources associated with this group.
133 * As an example, the dnotify group will always have a refcnt=1 and that
134 * will never change. Inotify, on the other hand, has a group per
135 * inotify_init() and the refcnt will hit 0 only when that fd has been
136 * closed.
137 */
138 atomic_t refcnt; /* things with interest in this group */
139
140 const struct fsnotify_ops *ops; /* how this group handles things */
141
142 /* needed to send notification to userspace */
143 spinlock_t notification_lock; /* protect the notification_list */
144 struct list_head notification_list; /* list of event_holder this group needs to send to userspace */
145 wait_queue_head_t notification_waitq; /* read() on the notification file blocks on this waitq */
146 unsigned int q_len; /* events on the queue */
147 unsigned int max_events; /* maximum events allowed on the list */
148 /*
149 * Valid fsnotify group priorities. Events are send in order from highest
150 * priority to lowest priority. We default to the lowest priority.
151 */
152 #define FS_PRIO_0 0 /* normal notifiers, no permissions */
153 #define FS_PRIO_1 1 /* fanotify content based access control */
154 #define FS_PRIO_2 2 /* fanotify pre-content access */
155 unsigned int priority;
156 bool shutdown; /* group is being shut down, don't queue more events */
157
158 /* stores all fastpath marks assoc with this group so they can be cleaned on unregister */
159 struct mutex mark_mutex; /* protect marks_list */
160 atomic_t num_marks; /* 1 for each mark and 1 for not being
161 * past the point of no return when freeing
162 * a group */
163 struct list_head marks_list; /* all inode marks for this group */
164
165 struct fasync_struct *fsn_fa; /* async notification */
166
167 struct fsnotify_event *overflow_event; /* Event we queue when the
168 * notification list is too
169 * full */
170 atomic_t user_waits; /* Number of tasks waiting for user
171 * response */
172
173 /* groups can define private fields here or use the void *private */
174 union {
175 void *private;
176 #ifdef CONFIG_INOTIFY_USER
177 struct inotify_group_private_data {
178 spinlock_t idr_lock;
179 struct idr idr;
180 struct ucounts *ucounts;
181 } inotify_data;
182 #endif
183 #ifdef CONFIG_FANOTIFY
184 struct fanotify_group_private_data {
185 #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
186 /* allows a group to block waiting for a userspace response */
187 struct list_head access_list;
188 wait_queue_head_t access_waitq;
189 #endif /* CONFIG_FANOTIFY_ACCESS_PERMISSIONS */
190 int f_flags;
191 unsigned int max_marks;
192 struct user_struct *user;
> 193 bool audit_enabled;
194 } fanotify_data;
195 #endif /* CONFIG_FANOTIFY */
196 };
197 };
198
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 29090 bytes --]
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH v6 1/1] audit: Record fanotify access control decisions
@ 2017-09-26 21:14 Steve Grubb
0 siblings, 0 replies; 4+ messages in thread
From: Steve Grubb @ 2017-09-26 21:14 UTC (permalink / raw)
To: linux-api-u79uwXL29TY76Z2rM5mHXA
Forwarding a copy due to a copy & paste error
---------- Forwarded Message ----------
Subject: [PATCH v6 1/1] audit: Record fanotify access control decisions
Date: Tuesday, September 26, 2017, 5:11:48 PM EDT
From: Steve Grubb <sgrubb-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
To: fsdevel <linux-fsdevel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>
CC: Linux Audit <linux-audit-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>, inux-api-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Jan Kara
<jack-AlSwsSmVLrQ@public.gmane.org>, Amir Goldstein <amir73il-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>, Paul Moore
<pmoore-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
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.
* This v6 update adds empty inline audit_fanotify function for when
CONFIG_AUDITSYSCALL is not defined.
Signed-off-by: sgrubb <sgrubb-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
Reviewed-by: Amir Goldstein <amir73il-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
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_enabled)
+ 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_enabled = 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_enabled)
+ 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_enabled;
} 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
-----------------------------------------
^ permalink raw reply related [flat|nested] 4+ messages in thread
end of thread, other threads:[~2017-09-30 0:10 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-09-26 21:11 [PATCH v6 1/1] audit: Record fanotify access control decisions Steve Grubb
2017-09-29 19:35 ` kbuild test robot
2017-09-30 0:09 ` kbuild test robot
2017-09-26 21:14 Steve Grubb
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.