All of lore.kernel.org
 help / color / mirror / Atom feed
* [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.