linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH ghak90 V5 00/10] audit: implement container identifier
@ 2019-03-15 18:29 Richard Guy Briggs
  2019-03-15 18:29 ` [PATCH ghak90 V5 01/10] audit: collect audit task parameters Richard Guy Briggs
                   ` (9 more replies)
  0 siblings, 10 replies; 64+ messages in thread
From: Richard Guy Briggs @ 2019-03-15 18:29 UTC (permalink / raw)
  To: containers, linux-api, Linux-Audit Mailing List, linux-fsdevel,
	LKML, netdev, netfilter-devel
  Cc: Paul Moore, sgrubb, omosnace, dhowells, simo, eparis, serge,
	ebiederm, nhorman, Richard Guy Briggs

Implement kernel audit container identifier.

This patchset is a fifth based on the proposal document (V3)
posted:
	https://www.redhat.com/archives/linux-audit/2018-January/msg00014.html

The first patch was the last patch from ghak81 that was absorbed into
this patchset since its primary justification is the rest of this
patchset.

The second patch implements the proc fs write to set the audit container
identifier of a process, emitting an AUDIT_CONTAINER_OP 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 third implements reading the audit container identifier from the proc
filesystem for debugging.  This patch wasn't planned for upstream
inclusion but is starting to become more likely.

The fourth implements the auxiliary record AUDIT_CONTAINER if an
audit container identifier is associated with an event.  This patch
requires userspace support for proper type display.

The 5th adds signal and ptrace support.

The 6th creates a local audit context to be able to bind a standalone
record with a locally created auxiliary record.

The 7th patch adds audit container identifier records to the user
standalone records.

The 8th 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 9th adds network namespace audit container identifier labelling
based on member tasks' audit container identifier labels.

The 10th 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.

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_op
  echo child:$child contid:$( cat /proc/$child/audit_containerid)

This should produce a record such as:

  type=CONTAINER_OP 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_ID msg=audit(2018-06-06 12:46:31.707:26953) : 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 

Example: Test multiple containers on one netns:

  sleep 5 &
  child1=$!
  containerid1=123451
  echo $containerid1 > /proc/$child1/audit_containerid
  sleep 5 &
  child2=$!
  containerid2=123452
  echo $containerid2 > /proc/$child2/audit_containerid
  iptables -I INPUT -i lo -p icmp --icmp-type echo-request -j AUDIT --type accept
  iptables -I INPUT  -t mangle -i lo -p icmp --icmp-type echo-request -j MARK --set-mark 0x12345555
  sleep 1;
  bash -c "ping -q -c 1 127.0.0.1 >/dev/null 2>&1"
  sleep 1;
  ausearch -i -m NETFILTER_PKT -ts boot|grep mark=0x12345555
  ausearch -i -m NETFILTER_PKT -ts boot|grep contid=|grep $containerid1|grep $containerid2

This should produce an event such as:

  type=NETFILTER_PKT msg=audit(03/15/2019 14:16:13.369:244) : mark=0x12345555 saddr=127.0.0.1 daddr=127.0.0.1 proto=icmp 
  type=CONTAINER_ID msg=audit(03/15/2019 14:16:13.369:244) : contid=123452,123451


Includes the last patch of https://github.com/linux-audit/audit-kernel/issues/81
See the github issue for the kernel code 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:

v5
- address loginuid and sessionid syscall scope in ghak104
- address audit_context in CONFIG_AUDIT vs CONFIG_AUDITSYSCALL in ghak105
- remove tty patch, addressed in ghak106
- rebase on audit/next v5.0-rc1
  w/ghak59/ghak104/ghak103/ghak100/ghak107/ghak105/ghak106/ghak105sup
- update CONTAINER_ID to CONTAINER_OP in patch description
- move audit_context in audit_task_info to CONFIG_AUDITSYSCALL
- move audit_alloc() and audit_free() out of CONFIG_AUDITSYSCALL and into
  CONFIG_AUDIT and create audit_{alloc,free}_syscall
- use plain kmem_cache_alloc() rather than kmem_cache_zalloc() in audit_alloc()
- fix audit_get_contid() declaration type error
- move audit_set_contid() from auditsc.c to audit.c
- audit_log_contid() returns void
- audit_log_contid() handed contid rather than tsk
- switch from AUDIT_CONTAINER to AUDIT_CONTAINER_ID for aux record
- move audit_log_contid(tsk/contid) & audit_contid_set(tsk)/audit_contid_valid(contid)
- switch from tsk to current
- audit_alloc_local() calls audit_log_lost() on failure to allocate a context
- add AUDIT_USER* non-syscall contid record
- cosmetic cleanup double parens, goto out on err
- ditch audit_get_ns_contid_list_lock(), fix aunet lock race
- switch from all-cpu read spinlock to rcu, keep spinlock for write
- update audit_alloc_local() to use ktime_get_coarse_real_ts64()
- add nft_log support
- add call from do_exit() in audit_free() to remove contid from netns
- relegate AUDIT_CONTAINER ref= field (was op=) to debug patch

v4
- preface set with ghak81:"collect audit task parameters"
- add shallyn and sgrubb acks
- rename feature bitmap macro
- rename cid_valid() to audit_contid_valid()
- rename AUDIT_CONTAINER_ID to AUDIT_CONTAINER_OP
- delete audit_get_contid_list() from headers
- move work into inner if, delete "found"
- change netns contid list function names
- move exports for audit_log_contid audit_alloc_local audit_free_context to non-syscall patch
- list contids CSV
- pass in gfp flags to audit_alloc_local() (fix audit_alloc_context callers)
- use "local" in lieu of abusing in_syscall for auditsc_get_stamp()
- read_lock(&tasklist_lock) around children and thread check
- task_lock(tsk) should be taken before first check of tsk->audit
- add spin lock to contid list in aunet
- restrict /proc read to CAP_AUDIT_CONTROL
- remove set again prohibition and inherited flag
- delete contidion spelling fix from patchset, send to netdev/linux-wireless

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: collect audit task parameters
  audit: add container id
  audit: read container ID of a process
  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 user records
  audit: add containerid filtering
  audit: add support for containerid to network namespaces
  audit: NETFILTER_PKT: record each container ID associated with a netNS

 fs/proc/base.c             |  55 +++++++++
 include/linux/audit.h      | 107 +++++++++++++---
 include/linux/sched.h      |   7 +-
 include/uapi/linux/audit.h |   8 +-
 init/init_task.c           |   3 +-
 init/main.c                |   2 +
 kernel/audit.c             | 300 +++++++++++++++++++++++++++++++++++++++++++--
 kernel/audit.h             |   9 ++
 kernel/auditfilter.c       |  47 +++++++
 kernel/auditsc.c           |  89 ++++++++++----
 kernel/fork.c              |   1 -
 kernel/nsproxy.c           |   4 +
 net/netfilter/nft_log.c    |  11 +-
 net/netfilter/xt_AUDIT.c   |  11 +-
 14 files changed, 592 insertions(+), 62 deletions(-)

-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 64+ messages in thread

* [PATCH ghak90 V5 01/10] audit: collect audit task parameters
  2019-03-15 18:29 [PATCH ghak90 V5 00/10] audit: implement container identifier Richard Guy Briggs
@ 2019-03-15 18:29 ` Richard Guy Briggs
  2019-03-16 19:57   ` Neil Horman
  2019-03-27 20:33   ` Ondrej Mosnacek
  2019-03-15 18:29 ` [PATCH ghak90 V5 02/10] audit: add container id Richard Guy Briggs
                   ` (8 subsequent siblings)
  9 siblings, 2 replies; 64+ messages in thread
From: Richard Guy Briggs @ 2019-03-15 18:29 UTC (permalink / raw)
  To: containers, linux-api, Linux-Audit Mailing List, linux-fsdevel,
	LKML, netdev, netfilter-devel
  Cc: Paul Moore, sgrubb, omosnace, dhowells, simo, eparis, serge,
	ebiederm, nhorman, Richard Guy Briggs

The audit-related parameters in struct task_struct should ideally be
collected together and accessed through a standard audit API.

Collect the existing loginuid, sessionid and audit_context together in a
new struct audit_task_info called "audit" in struct task_struct.

Use kmem_cache to manage this pool of memory.
Un-inline audit_free() to be able to always recover that memory.

Please see the upstream github issue
https://github.com/linux-audit/audit-kernel/issues/81
but that issue has been closed with this patch included with
https://github.com/linux-audit/audit-kernel/issues/90

Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
---
 include/linux/audit.h | 49 +++++++++++++++++++++++------------
 include/linux/sched.h |  7 +----
 init/init_task.c      |  3 +--
 init/main.c           |  2 ++
 kernel/audit.c        | 71 +++++++++++++++++++++++++++++++++++++++++++++++++--
 kernel/audit.h        |  5 ++++
 kernel/auditsc.c      | 26 ++++++++++---------
 kernel/fork.c         |  1 -
 8 files changed, 124 insertions(+), 40 deletions(-)

diff --git a/include/linux/audit.h b/include/linux/audit.h
index 1e69d9fe16da..bde346e73f0c 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -86,6 +86,16 @@ struct audit_field {
 	u32				op;
 };
 
+struct audit_task_info {
+	kuid_t			loginuid;
+	unsigned int		sessionid;
+#ifdef CONFIG_AUDITSYSCALL
+	struct audit_context	*ctx;
+#endif
+};
+
+extern struct audit_task_info init_struct_audit;
+
 extern int is_audit_feature_set(int which);
 
 extern int __init audit_register_class(int class, unsigned *list);
@@ -122,6 +132,9 @@ struct audit_field {
 #ifdef CONFIG_AUDIT
 /* These are defined in audit.c */
 				/* Public API */
+extern int  audit_alloc(struct task_struct *task);
+extern void audit_free(struct task_struct *task);
+extern void __init audit_task_init(void);
 extern __printf(4, 5)
 void audit_log(struct audit_context *ctx, gfp_t gfp_mask, int type,
 	       const char *fmt, ...);
@@ -164,16 +177,28 @@ extern void		    audit_log_key(struct audit_buffer *ab,
 
 static inline kuid_t audit_get_loginuid(struct task_struct *tsk)
 {
-	return tsk->loginuid;
+	if (!tsk->audit)
+		return INVALID_UID;
+	return tsk->audit->loginuid;
 }
 
 static inline unsigned int audit_get_sessionid(struct task_struct *tsk)
 {
-	return tsk->sessionid;
+	if (!tsk->audit)
+		return AUDIT_SID_UNSET;
+	return tsk->audit->sessionid;
 }
 
 extern u32 audit_enabled;
 #else /* CONFIG_AUDIT */
+static inline int audit_alloc(struct task_struct *task)
+{
+	return 0;
+}
+static inline void audit_free(struct task_struct *task)
+{ }
+static inline void __init audit_task_init(void)
+{ }
 static inline __printf(4, 5)
 void audit_log(struct audit_context *ctx, gfp_t gfp_mask, int type,
 	       const char *fmt, ...)
@@ -239,8 +264,6 @@ static inline unsigned int audit_get_sessionid(struct task_struct *tsk)
 
 /* These are defined in auditsc.c */
 				/* Public API */
-extern int  audit_alloc(struct task_struct *task);
-extern void __audit_free(struct task_struct *task);
 extern void __audit_syscall_entry(int major, unsigned long a0, unsigned long a1,
 				  unsigned long a2, unsigned long a3);
 extern void __audit_syscall_exit(int ret_success, long ret_value);
@@ -263,12 +286,14 @@ extern void audit_seccomp_actions_logged(const char *names,
 
 static inline void audit_set_context(struct task_struct *task, struct audit_context *ctx)
 {
-	task->audit_context = ctx;
+	task->audit->ctx = ctx;
 }
 
 static inline struct audit_context *audit_context(void)
 {
-	return current->audit_context;
+	if (!current->audit)
+		return NULL;
+	return current->audit->ctx;
 }
 
 static inline bool audit_dummy_context(void)
@@ -276,11 +301,7 @@ static inline bool audit_dummy_context(void)
 	void *p = audit_context();
 	return !p || *(int *)p;
 }
-static inline void audit_free(struct task_struct *task)
-{
-	if (unlikely(task->audit_context))
-		__audit_free(task);
-}
+
 static inline void audit_syscall_entry(int major, unsigned long a0,
 				       unsigned long a1, unsigned long a2,
 				       unsigned long a3)
@@ -470,12 +491,6 @@ static inline void audit_fanotify(unsigned int response)
 extern int audit_n_rules;
 extern int audit_signals;
 #else /* CONFIG_AUDITSYSCALL */
-static inline int audit_alloc(struct task_struct *task)
-{
-	return 0;
-}
-static inline void audit_free(struct task_struct *task)
-{ }
 static inline void audit_syscall_entry(int major, unsigned long a0,
 				       unsigned long a1, unsigned long a2,
 				       unsigned long a3)
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 765119df759a..6850d1e48ace 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -31,7 +31,6 @@
 #include <linux/rseq.h>
 
 /* task_struct member predeclarations (sorted alphabetically): */
-struct audit_context;
 struct backing_dev_info;
 struct bio_list;
 struct blk_plug;
@@ -886,11 +885,7 @@ struct task_struct {
 	struct callback_head		*task_works;
 
 #ifdef CONFIG_AUDIT
-#ifdef CONFIG_AUDITSYSCALL
-	struct audit_context		*audit_context;
-#endif
-	kuid_t				loginuid;
-	unsigned int			sessionid;
+	struct audit_task_info		*audit;
 #endif
 	struct seccomp			seccomp;
 
diff --git a/init/init_task.c b/init/init_task.c
index 39c3109acc1a..f9685e1edda1 100644
--- a/init/init_task.c
+++ b/init/init_task.c
@@ -122,8 +122,7 @@ struct task_struct init_task
 	.thread_group	= LIST_HEAD_INIT(init_task.thread_group),
 	.thread_node	= LIST_HEAD_INIT(init_signals.thread_head),
 #ifdef CONFIG_AUDIT
-	.loginuid	= INVALID_UID,
-	.sessionid	= AUDIT_SID_UNSET,
+	.audit		= &init_struct_audit,
 #endif
 #ifdef CONFIG_PERF_EVENTS
 	.perf_event_mutex = __MUTEX_INITIALIZER(init_task.perf_event_mutex),
diff --git a/init/main.c b/init/main.c
index e2e80ca3165a..8a1c36625d12 100644
--- a/init/main.c
+++ b/init/main.c
@@ -92,6 +92,7 @@
 #include <linux/rodata_test.h>
 #include <linux/jump_label.h>
 #include <linux/mem_encrypt.h>
+#include <linux/audit.h>
 
 #include <asm/io.h>
 #include <asm/bugs.h>
@@ -727,6 +728,7 @@ asmlinkage __visible void __init start_kernel(void)
 	nsfs_init();
 	cpuset_init();
 	cgroup_init();
+	audit_task_init();
 	taskstats_init_early();
 	delayacct_init();
 
diff --git a/kernel/audit.c b/kernel/audit.c
index c89ea48c70a6..67498c5690bb 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -215,6 +215,73 @@ struct audit_reply {
 	struct sk_buff *skb;
 };
 
+static struct kmem_cache *audit_task_cache;
+
+void __init audit_task_init(void)
+{
+	audit_task_cache = kmem_cache_create("audit_task",
+					     sizeof(struct audit_task_info),
+					     0, SLAB_PANIC, NULL);
+}
+
+/**
+ * audit_alloc - allocate an audit info block for a task
+ * @tsk: task
+ *
+ * Call audit_alloc_syscall to filter on the task information and
+ * allocate a per-task audit context if necessary.  This is called from
+ * copy_process, so no lock is needed.
+ */
+int audit_alloc(struct task_struct *tsk)
+{
+	int ret = 0;
+	struct audit_task_info *info;
+
+	info = kmem_cache_alloc(audit_task_cache, GFP_KERNEL);
+	if (!info) {
+		ret = -ENOMEM;
+		goto out;
+	}
+	info->loginuid = audit_get_loginuid(current);
+	info->sessionid = audit_get_sessionid(current);
+	tsk->audit = info;
+
+	ret = audit_alloc_syscall(tsk);
+	if (ret) {
+		tsk->audit = NULL;
+		kmem_cache_free(audit_task_cache, info);
+	}
+out:
+	return ret;
+}
+
+struct audit_task_info init_struct_audit = {
+	.loginuid = INVALID_UID,
+	.sessionid = AUDIT_SID_UNSET,
+#ifdef CONFIG_AUDITSYSCALL
+	.ctx = NULL,
+#endif
+};
+
+/**
+ * audit_free - free per-task audit info
+ * @tsk: task whose audit info block to free
+ *
+ * Called from copy_process and do_exit
+ */
+void audit_free(struct task_struct *tsk)
+{
+	struct audit_task_info *info = tsk->audit;
+
+	audit_free_syscall(tsk);
+	/* Freeing the audit_task_info struct must be performed after
+	 * audit_log_exit() due to need for loginuid and sessionid.
+	 */
+	info = tsk->audit;
+	tsk->audit = NULL;
+	kmem_cache_free(audit_task_cache, info);
+}
+
 /**
  * auditd_test_task - Check to see if a given task is an audit daemon
  * @task: the task to check
@@ -2266,8 +2333,8 @@ int audit_set_loginuid(kuid_t loginuid)
 			sessionid = (unsigned int)atomic_inc_return(&session_id);
 	}
 
-	current->sessionid = sessionid;
-	current->loginuid = loginuid;
+	current->audit->sessionid = sessionid;
+	current->audit->loginuid = loginuid;
 out:
 	audit_log_set_loginuid(oldloginuid, loginuid, oldsessionid, sessionid, rc);
 	return rc;
diff --git a/kernel/audit.h b/kernel/audit.h
index 958d5b8fc1b3..c00e2ee3c6b3 100644
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -264,6 +264,8 @@ extern void audit_log_d_path_exe(struct audit_buffer *ab,
 extern unsigned int audit_serial(void);
 extern int auditsc_get_stamp(struct audit_context *ctx,
 			      struct timespec64 *t, unsigned int *serial);
+extern int audit_alloc_syscall(struct task_struct *tsk);
+extern void audit_free_syscall(struct task_struct *tsk);
 
 extern void audit_put_watch(struct audit_watch *watch);
 extern void audit_get_watch(struct audit_watch *watch);
@@ -305,6 +307,9 @@ extern void audit_filter_inodes(struct task_struct *tsk,
 extern struct list_head *audit_killed_trees(void);
 #else /* CONFIG_AUDITSYSCALL */
 #define auditsc_get_stamp(c, t, s) 0
+#define audit_alloc_syscall(t) 0
+#define audit_free_syscall(t) {}
+
 #define audit_put_watch(w) {}
 #define audit_get_watch(w) {}
 #define audit_to_watch(k, p, l, o) (-EINVAL)
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index d1eab1d4a930..8090eff7868d 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -885,23 +885,25 @@ static inline struct audit_context *audit_alloc_context(enum audit_state state)
 	return context;
 }
 
-/**
- * audit_alloc - allocate an audit context block for a task
+/*
+ * audit_alloc_syscall - allocate an audit context block for a task
  * @tsk: task
  *
  * Filter on the task information and allocate a per-task audit context
  * if necessary.  Doing so turns on system call auditing for the
- * specified task.  This is called from copy_process, so no lock is
- * needed.
+ * specified task.  This is called from copy_process via audit_alloc, so
+ * no lock is needed.
  */
-int audit_alloc(struct task_struct *tsk)
+int audit_alloc_syscall(struct task_struct *tsk)
 {
 	struct audit_context *context;
 	enum audit_state     state;
 	char *key = NULL;
 
-	if (likely(!audit_ever_enabled))
+	if (likely(!audit_ever_enabled)) {
+		audit_set_context(tsk, NULL);
 		return 0; /* Return if not auditing. */
+	}
 
 	state = audit_filter_task(tsk, &key);
 	if (state == AUDIT_DISABLED) {
@@ -911,7 +913,7 @@ int audit_alloc(struct task_struct *tsk)
 
 	if (!(context = audit_alloc_context(state))) {
 		kfree(key);
-		audit_log_lost("out of memory in audit_alloc");
+		audit_log_lost("out of memory in audit_alloc_syscall");
 		return -ENOMEM;
 	}
 	context->filterkey = key;
@@ -1555,14 +1557,15 @@ static void audit_log_exit(void)
 }
 
 /**
- * __audit_free - free a per-task audit context
+ * audit_free_syscall - free per-task audit context info
  * @tsk: task whose audit context block to free
  *
- * Called from copy_process and do_exit
+ * Called from audit_free
  */
-void __audit_free(struct task_struct *tsk)
+void audit_free_syscall(struct task_struct *tsk)
 {
-	struct audit_context *context = tsk->audit_context;
+	struct audit_task_info *info = tsk->audit;
+	struct audit_context *context = info->ctx;
 
 	if (!context)
 		return;
@@ -1585,7 +1588,6 @@ void __audit_free(struct task_struct *tsk)
 		if (context->current_state == AUDIT_RECORD_CONTEXT)
 			audit_log_exit();
 	}
-
 	audit_set_context(tsk, NULL);
 	audit_free_context(context);
 }
diff --git a/kernel/fork.c b/kernel/fork.c
index a60459947f18..1107bd8b8ad8 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1836,7 +1836,6 @@ static __latent_entropy struct task_struct *copy_process(
 	p->start_time = ktime_get_ns();
 	p->real_start_time = ktime_get_boot_ns();
 	p->io_context = NULL;
-	audit_set_context(p, NULL);
 	cgroup_fork(p);
 #ifdef CONFIG_NUMA
 	p->mempolicy = mpol_dup(p->mempolicy);
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH ghak90 V5 02/10] audit: add container id
  2019-03-15 18:29 [PATCH ghak90 V5 00/10] audit: implement container identifier Richard Guy Briggs
  2019-03-15 18:29 ` [PATCH ghak90 V5 01/10] audit: collect audit task parameters Richard Guy Briggs
@ 2019-03-15 18:29 ` Richard Guy Briggs
  2019-03-16 20:00   ` Neil Horman
  2019-03-27 20:38   ` Ondrej Mosnacek
  2019-03-15 18:29 ` [PATCH ghak90 V5 03/10] audit: read container ID of a process Richard Guy Briggs
                   ` (7 subsequent siblings)
  9 siblings, 2 replies; 64+ messages in thread
From: Richard Guy Briggs @ 2019-03-15 18:29 UTC (permalink / raw)
  To: containers, linux-api, Linux-Audit Mailing List, linux-fsdevel,
	LKML, netdev, netfilter-devel
  Cc: Paul Moore, sgrubb, omosnace, dhowells, simo, eparis, serge,
	ebiederm, nhorman, Richard Guy Briggs

Implement the proc fs write to set the audit container identifier of a
process, emitting an AUDIT_CONTAINER_OP record to document the event.

This is a write from the container orchestrator task to a proc entry of
the form /proc/PID/audit_containerid where PID is the process ID of the
newly created task that is to become the first task in a container, or
an additional task added to a container.

The write expects up to a u64 value (unset: 18446744073709551615).

The writer must have capability CAP_AUDIT_CONTROL.

This will produce a record such as this:
  type=CONTAINER_OP 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

The "op" field indicates an initial set.  The "pid" to "ses" fields are
the orchestrator while the "opid" field is the object's PID, the process
being "contained".  Old and new audit container identifier values are
given in the "contid" fields, while res indicates its success.

It is not permitted to unset the audit container identifier.
A child inherits its parent's audit container identifier.

See: https://github.com/linux-audit/audit-kernel/issues/90
See: https://github.com/linux-audit/audit-userspace/issues/51
See: https://github.com/linux-audit/audit-testsuite/issues/64
See: https://github.com/linux-audit/audit-kernel/wiki/RFE-Audit-Container-ID

Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
Acked-by: Serge Hallyn <serge@hallyn.com>
Acked-by: Steve Grubb <sgrubb@redhat.com>
Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
---
 fs/proc/base.c             | 36 ++++++++++++++++++++++++
 include/linux/audit.h      | 25 +++++++++++++++++
 include/uapi/linux/audit.h |  2 ++
 kernel/audit.c             | 68 ++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 131 insertions(+)

diff --git a/fs/proc/base.c b/fs/proc/base.c
index a23651ce6960..2505c46c8701 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -1294,6 +1294,40 @@ static ssize_t proc_sessionid_read(struct file * file, char __user * buf,
 	.read		= proc_sessionid_read,
 	.llseek		= generic_file_llseek,
 };
+
+static ssize_t proc_contid_write(struct file *file, const char __user *buf,
+				   size_t count, loff_t *ppos)
+{
+	struct inode *inode = file_inode(file);
+	u64 contid;
+	int rv;
+	struct task_struct *task = get_proc_task(inode);
+
+	if (!task)
+		return -ESRCH;
+	if (*ppos != 0) {
+		/* No partial writes. */
+		put_task_struct(task);
+		return -EINVAL;
+	}
+
+	rv = kstrtou64_from_user(buf, count, 10, &contid);
+	if (rv < 0) {
+		put_task_struct(task);
+		return rv;
+	}
+
+	rv = audit_set_contid(task, contid);
+	put_task_struct(task);
+	if (rv < 0)
+		return rv;
+	return count;
+}
+
+static const struct file_operations proc_contid_operations = {
+	.write		= proc_contid_write,
+	.llseek		= generic_file_llseek,
+};
 #endif
 
 #ifdef CONFIG_FAULT_INJECTION
@@ -3005,6 +3039,7 @@ static int proc_stack_depth(struct seq_file *m, struct pid_namespace *ns,
 #ifdef CONFIG_AUDIT
 	REG("loginuid",   S_IWUSR|S_IRUGO, proc_loginuid_operations),
 	REG("sessionid",  S_IRUGO, proc_sessionid_operations),
+	REG("audit_containerid", S_IWUSR, proc_contid_operations),
 #endif
 #ifdef CONFIG_FAULT_INJECTION
 	REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations),
@@ -3393,6 +3428,7 @@ static int proc_tid_comm_permission(struct inode *inode, int mask)
 #ifdef CONFIG_AUDIT
 	REG("loginuid",  S_IWUSR|S_IRUGO, proc_loginuid_operations),
 	REG("sessionid",  S_IRUGO, proc_sessionid_operations),
+	REG("audit_containerid", S_IWUSR, proc_contid_operations),
 #endif
 #ifdef CONFIG_FAULT_INJECTION
 	REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations),
diff --git a/include/linux/audit.h b/include/linux/audit.h
index bde346e73f0c..301337776193 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -89,6 +89,7 @@ struct audit_field {
 struct audit_task_info {
 	kuid_t			loginuid;
 	unsigned int		sessionid;
+	u64			contid;
 #ifdef CONFIG_AUDITSYSCALL
 	struct audit_context	*ctx;
 #endif
@@ -189,6 +190,15 @@ static inline unsigned int audit_get_sessionid(struct task_struct *tsk)
 	return tsk->audit->sessionid;
 }
 
+extern int audit_set_contid(struct task_struct *tsk, u64 contid);
+
+static inline u64 audit_get_contid(struct task_struct *tsk)
+{
+	if (!tsk->audit)
+		return AUDIT_CID_UNSET;
+	return tsk->audit->contid;
+}
+
 extern u32 audit_enabled;
 #else /* CONFIG_AUDIT */
 static inline int audit_alloc(struct task_struct *task)
@@ -250,6 +260,11 @@ static inline unsigned int audit_get_sessionid(struct task_struct *tsk)
 	return AUDIT_SID_UNSET;
 }
 
+static inline u64 audit_get_contid(struct task_struct *tsk)
+{
+	return AUDIT_CID_UNSET;
+}
+
 #define audit_enabled AUDIT_OFF
 #endif /* CONFIG_AUDIT */
 
@@ -606,6 +621,16 @@ static inline bool audit_loginuid_set(struct task_struct *tsk)
 	return uid_valid(audit_get_loginuid(tsk));
 }
 
+static inline bool audit_contid_valid(u64 contid)
+{
+	return contid != AUDIT_CID_UNSET;
+}
+
+static inline bool audit_contid_set(struct task_struct *tsk)
+{
+	return audit_contid_valid(audit_get_contid(tsk));
+}
+
 static inline void audit_log_string(struct audit_buffer *ab, const char *buf)
 {
 	audit_log_n_string(ab, buf, strlen(buf));
diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h
index 36a7e3f18e69..d475cf3b4d7f 100644
--- a/include/uapi/linux/audit.h
+++ b/include/uapi/linux/audit.h
@@ -71,6 +71,7 @@
 #define AUDIT_TTY_SET		1017	/* Set TTY auditing status */
 #define AUDIT_SET_FEATURE	1018	/* Turn an audit feature on or off */
 #define AUDIT_GET_FEATURE	1019	/* Get which features are enabled */
+#define AUDIT_CONTAINER_OP	1020	/* Define the container id and information */
 
 #define AUDIT_FIRST_USER_MSG	1100	/* Userspace messages mostly uninteresting to kernel */
 #define AUDIT_USER_AVC		1107	/* We filter this differently */
@@ -471,6 +472,7 @@ struct audit_tty_status {
 
 #define AUDIT_UID_UNSET (unsigned int)-1
 #define AUDIT_SID_UNSET ((unsigned int)-1)
+#define AUDIT_CID_UNSET ((u64)-1)
 
 /* audit_rule_data supports filter rules with both integer and string
  * fields.  It corresponds with AUDIT_ADD_RULE, AUDIT_DEL_RULE and
diff --git a/kernel/audit.c b/kernel/audit.c
index 67498c5690bb..b5c702abeb42 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -244,6 +244,7 @@ int audit_alloc(struct task_struct *tsk)
 	}
 	info->loginuid = audit_get_loginuid(current);
 	info->sessionid = audit_get_sessionid(current);
+	info->contid = audit_get_contid(current);
 	tsk->audit = info;
 
 	ret = audit_alloc_syscall(tsk);
@@ -258,6 +259,7 @@ int audit_alloc(struct task_struct *tsk)
 struct audit_task_info init_struct_audit = {
 	.loginuid = INVALID_UID,
 	.sessionid = AUDIT_SID_UNSET,
+	.contid = AUDIT_CID_UNSET,
 #ifdef CONFIG_AUDITSYSCALL
 	.ctx = NULL,
 #endif
@@ -2341,6 +2343,72 @@ int audit_set_loginuid(kuid_t loginuid)
 }
 
 /**
+ * audit_set_contid - set current task's audit contid
+ * @contid: contid value
+ *
+ * Returns 0 on success, -EPERM on permission failure.
+ *
+ * Called (set) from fs/proc/base.c::proc_contid_write().
+ */
+int audit_set_contid(struct task_struct *task, u64 contid)
+{
+	u64 oldcontid;
+	int rc = 0;
+	struct audit_buffer *ab;
+	uid_t uid;
+	struct tty_struct *tty;
+	char comm[sizeof(current->comm)];
+
+	task_lock(task);
+	/* Can't set if audit disabled */
+	if (!task->audit) {
+		task_unlock(task);
+		return -ENOPROTOOPT;
+	}
+	oldcontid = audit_get_contid(task);
+	read_lock(&tasklist_lock);
+	/* Don't allow the audit containerid to be unset */
+	if (!audit_contid_valid(contid))
+		rc = -EINVAL;
+	/* if we don't have caps, reject */
+	else if (!capable(CAP_AUDIT_CONTROL))
+		rc = -EPERM;
+	/* if task has children or is not single-threaded, deny */
+	else if (!list_empty(&task->children))
+		rc = -EBUSY;
+	else if (!(thread_group_leader(task) && thread_group_empty(task)))
+		rc = -EALREADY;
+	read_unlock(&tasklist_lock);
+	if (!rc)
+		task->audit->contid = contid;
+	task_unlock(task);
+
+	if (!audit_enabled)
+		return rc;
+
+	ab = audit_log_start(audit_context(), GFP_KERNEL, AUDIT_CONTAINER_OP);
+	if (!ab)
+		return rc;
+
+	uid = from_kuid(&init_user_ns, task_uid(current));
+	tty = audit_get_tty();
+	audit_log_format(ab, "op=set opid=%d old-contid=%llu contid=%llu pid=%d uid=%u auid=%u tty=%s ses=%u",
+			 task_tgid_nr(task), oldcontid, contid,
+			 task_tgid_nr(current), 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, " res=%d", !rc);
+	audit_log_end(ab);
+	return rc;
+}
+
+/**
  * audit_log_end - end one audit record
  * @ab: the audit_buffer
  *
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH ghak90 V5 03/10] audit: read container ID of a process
  2019-03-15 18:29 [PATCH ghak90 V5 00/10] audit: implement container identifier Richard Guy Briggs
  2019-03-15 18:29 ` [PATCH ghak90 V5 01/10] audit: collect audit task parameters Richard Guy Briggs
  2019-03-15 18:29 ` [PATCH ghak90 V5 02/10] audit: add container id Richard Guy Briggs
@ 2019-03-15 18:29 ` Richard Guy Briggs
  2019-03-18 11:10   ` Neil Horman
  2019-03-27 20:44   ` Ondrej Mosnacek
  2019-03-15 18:29 ` [PATCH ghak90 V5 04/10] audit: log container info of syscalls Richard Guy Briggs
                   ` (6 subsequent siblings)
  9 siblings, 2 replies; 64+ messages in thread
From: Richard Guy Briggs @ 2019-03-15 18:29 UTC (permalink / raw)
  To: containers, linux-api, Linux-Audit Mailing List, linux-fsdevel,
	LKML, netdev, netfilter-devel
  Cc: Paul Moore, sgrubb, omosnace, dhowells, simo, eparis, serge,
	ebiederm, nhorman, Richard Guy Briggs

Add support for reading the audit container identifier from the proc
filesystem.

This is a read from the proc entry of the form
/proc/PID/audit_containerid where PID is the process ID of the task
whose audit container identifier is sought.

The read expects up to a u64 value (unset: 18446744073709551615).

This read requires CAP_AUDIT_CONTROL.

Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
Acked-by: Serge Hallyn <serge@hallyn.com>
---
 fs/proc/base.c | 23 +++++++++++++++++++++--
 1 file changed, 21 insertions(+), 2 deletions(-)

diff --git a/fs/proc/base.c b/fs/proc/base.c
index 2505c46c8701..0b833cbdf5b6 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -1295,6 +1295,24 @@ static ssize_t proc_sessionid_read(struct file * file, char __user * buf,
 	.llseek		= generic_file_llseek,
 };
 
+static ssize_t proc_contid_read(struct file *file, char __user *buf,
+				  size_t count, loff_t *ppos)
+{
+	struct inode *inode = file_inode(file);
+	struct task_struct *task = get_proc_task(inode);
+	ssize_t length;
+	char tmpbuf[TMPBUFLEN*2];
+
+	if (!task)
+		return -ESRCH;
+	/* if we don't have caps, reject */
+	if (!capable(CAP_AUDIT_CONTROL))
+		return -EPERM;
+	length = scnprintf(tmpbuf, TMPBUFLEN*2, "%llu", audit_get_contid(task));
+	put_task_struct(task);
+	return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
+}
+
 static ssize_t proc_contid_write(struct file *file, const char __user *buf,
 				   size_t count, loff_t *ppos)
 {
@@ -1325,6 +1343,7 @@ static ssize_t proc_contid_write(struct file *file, const char __user *buf,
 }
 
 static const struct file_operations proc_contid_operations = {
+	.read		= proc_contid_read,
 	.write		= proc_contid_write,
 	.llseek		= generic_file_llseek,
 };
@@ -3039,7 +3058,7 @@ static int proc_stack_depth(struct seq_file *m, struct pid_namespace *ns,
 #ifdef CONFIG_AUDIT
 	REG("loginuid",   S_IWUSR|S_IRUGO, proc_loginuid_operations),
 	REG("sessionid",  S_IRUGO, proc_sessionid_operations),
-	REG("audit_containerid", S_IWUSR, proc_contid_operations),
+	REG("audit_containerid", S_IWUSR|S_IRUSR, proc_contid_operations),
 #endif
 #ifdef CONFIG_FAULT_INJECTION
 	REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations),
@@ -3428,7 +3447,7 @@ static int proc_tid_comm_permission(struct inode *inode, int mask)
 #ifdef CONFIG_AUDIT
 	REG("loginuid",  S_IWUSR|S_IRUGO, proc_loginuid_operations),
 	REG("sessionid",  S_IRUGO, proc_sessionid_operations),
-	REG("audit_containerid", S_IWUSR, proc_contid_operations),
+	REG("audit_containerid", S_IWUSR|S_IRUSR, proc_contid_operations),
 #endif
 #ifdef CONFIG_FAULT_INJECTION
 	REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations),
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH ghak90 V5 04/10] audit: log container info of syscalls
  2019-03-15 18:29 [PATCH ghak90 V5 00/10] audit: implement container identifier Richard Guy Briggs
                   ` (2 preceding siblings ...)
  2019-03-15 18:29 ` [PATCH ghak90 V5 03/10] audit: read container ID of a process Richard Guy Briggs
@ 2019-03-15 18:29 ` Richard Guy Briggs
  2019-03-16 22:44   ` Neil Horman
  2019-03-27 21:01   ` Ondrej Mosnacek
  2019-03-15 18:29 ` [PATCH ghak90 V5 05/10] audit: add containerid support for ptrace and signals Richard Guy Briggs
                   ` (5 subsequent siblings)
  9 siblings, 2 replies; 64+ messages in thread
From: Richard Guy Briggs @ 2019-03-15 18:29 UTC (permalink / raw)
  To: containers, linux-api, Linux-Audit Mailing List, linux-fsdevel,
	LKML, netdev, netfilter-devel
  Cc: Paul Moore, sgrubb, omosnace, dhowells, simo, eparis, serge,
	ebiederm, nhorman, Richard Guy Briggs

Create a new audit record AUDIT_CONTAINER_ID to document the audit
container identifier of a process if it is present.

Called from audit_log_exit(), syscalls are covered.

A sample raw event:
type=SYSCALL msg=audit(1519924845.499:257): arch=c000003e syscall=257 success=yes exit=3 a0=ffffff9c a1=56374e1cef30 a2=241 a3=1b6 items=2 ppid=606 pid=635 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts0 ses=3 comm="bash" exe="/usr/bin/bash" subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 key="tmpcontainerid"
type=CWD msg=audit(1519924845.499:257): cwd="/root"
type=PATH msg=audit(1519924845.499:257): item=0 name="/tmp/" inode=13863 dev=00:27 mode=041777 ouid=0 ogid=0 rdev=00:00 obj=system_u:object_r:tmp_t:s0 nametype= PARENT cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0
type=PATH msg=audit(1519924845.499:257): item=1 name="/tmp/tmpcontainerid" inode=17729 dev=00:27 mode=0100644 ouid=0 ogid=0 rdev=00:00 obj=unconfined_u:object_r:user_tmp_t:s0 nametype=CREATE cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0
type=PROCTITLE msg=audit(1519924845.499:257): proctitle=62617368002D6300736C65657020313B206563686F2074657374203E202F746D702F746D70636F6E7461696E65726964
type=CONTAINER_ID msg=audit(1519924845.499:257): contid=123458

See: https://github.com/linux-audit/audit-kernel/issues/90
See: https://github.com/linux-audit/audit-userspace/issues/51
See: https://github.com/linux-audit/audit-testsuite/issues/64
See: https://github.com/linux-audit/audit-kernel/wiki/RFE-Audit-Container-ID
Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
Acked-by: Serge Hallyn <serge@hallyn.com>
Acked-by: Steve Grubb <sgrubb@redhat.com>
Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
---
 include/linux/audit.h      |  5 +++++
 include/uapi/linux/audit.h |  1 +
 kernel/audit.c             | 21 +++++++++++++++++++++
 kernel/auditsc.c           |  2 ++
 4 files changed, 29 insertions(+)

diff --git a/include/linux/audit.h b/include/linux/audit.h
index 301337776193..43438192ca2a 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -199,6 +199,8 @@ static inline u64 audit_get_contid(struct task_struct *tsk)
 	return tsk->audit->contid;
 }
 
+extern void audit_log_contid(struct audit_context *context, u64 contid);
+
 extern u32 audit_enabled;
 #else /* CONFIG_AUDIT */
 static inline int audit_alloc(struct task_struct *task)
@@ -265,6 +267,9 @@ static inline u64 audit_get_contid(struct task_struct *tsk)
 	return AUDIT_CID_UNSET;
 }
 
+static inline void audit_log_contid(struct audit_context *context, u64 contid)
+{ }
+
 #define audit_enabled AUDIT_OFF
 #endif /* CONFIG_AUDIT */
 
diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h
index d475cf3b4d7f..a6383e28b2c8 100644
--- a/include/uapi/linux/audit.h
+++ b/include/uapi/linux/audit.h
@@ -115,6 +115,7 @@
 #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_CONTAINER_ID	1332	/* Container ID */
 
 #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 b5c702abeb42..8cc0e88d7f2a 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -2127,6 +2127,27 @@ void audit_log_session_info(struct audit_buffer *ab)
 	audit_log_format(ab, "auid=%u ses=%u", auid, sessionid);
 }
 
+/*
+ * audit_log_contid - report container info
+ * @context: task or local context for record
+ * @contid: container ID to report
+ */
+void audit_log_contid(struct audit_context *context, u64 contid)
+{
+	struct audit_buffer *ab;
+
+	if (!audit_contid_valid(contid))
+		return;
+	/* Generate AUDIT_CONTAINER_ID record with container ID */
+	ab = audit_log_start(context, GFP_KERNEL, AUDIT_CONTAINER_ID);
+	if (!ab)
+		return;
+	audit_log_format(ab, "contid=%llu", contid);
+	audit_log_end(ab);
+	return;
+}
+EXPORT_SYMBOL(audit_log_contid);
+
 void audit_log_key(struct audit_buffer *ab, char *key)
 {
 	audit_log_format(ab, " key=");
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 8090eff7868d..a8c8b44b954d 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -1548,6 +1548,8 @@ static void audit_log_exit(void)
 
 	audit_log_proctitle();
 
+	audit_log_contid(context, audit_get_contid(current));
+
 	/* Send end of event record to help user space know we are finished */
 	ab = audit_log_start(context, GFP_KERNEL, AUDIT_EOE);
 	if (ab)
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH ghak90 V5 05/10] audit: add containerid support for ptrace and signals
  2019-03-15 18:29 [PATCH ghak90 V5 00/10] audit: implement container identifier Richard Guy Briggs
                   ` (3 preceding siblings ...)
  2019-03-15 18:29 ` [PATCH ghak90 V5 04/10] audit: log container info of syscalls Richard Guy Briggs
@ 2019-03-15 18:29 ` Richard Guy Briggs
  2019-03-18 19:04   ` Neil Horman
  2019-03-27 21:17   ` Ondrej Mosnacek
  2019-03-15 18:29 ` [PATCH ghak90 V5 06/10] audit: add support for non-syscall auxiliary records Richard Guy Briggs
                   ` (4 subsequent siblings)
  9 siblings, 2 replies; 64+ messages in thread
From: Richard Guy Briggs @ 2019-03-15 18:29 UTC (permalink / raw)
  To: containers, linux-api, Linux-Audit Mailing List, linux-fsdevel,
	LKML, netdev, netfilter-devel
  Cc: Paul Moore, sgrubb, omosnace, dhowells, simo, eparis, serge,
	ebiederm, nhorman, Richard Guy Briggs

Add audit container identifier support to ptrace and signals.  In
particular, the "ref" field provides a way to label the auxiliary record
to which it is associated.

Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
Acked-by: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
---
 include/linux/audit.h |  1 +
 kernel/audit.c        |  2 ++
 kernel/audit.h        |  2 ++
 kernel/auditsc.c      | 23 +++++++++++++++++------
 4 files changed, 22 insertions(+), 6 deletions(-)

diff --git a/include/linux/audit.h b/include/linux/audit.h
index 43438192ca2a..ebd6625ca80e 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -35,6 +35,7 @@ struct audit_sig_info {
 	uid_t		uid;
 	pid_t		pid;
 	char		ctx[0];
+	u64		cid;
 };
 
 struct audit_buffer;
diff --git a/kernel/audit.c b/kernel/audit.c
index 8cc0e88d7f2a..cfa659b3f6c4 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -138,6 +138,7 @@ struct audit_net {
 kuid_t		audit_sig_uid = INVALID_UID;
 pid_t		audit_sig_pid = -1;
 u32		audit_sig_sid = 0;
+u64		audit_sig_cid = AUDIT_CID_UNSET;
 
 /* Records can be lost in several ways:
    0) [suppressed in audit_alloc]
@@ -1515,6 +1516,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 			memcpy(sig_data->ctx, ctx, len);
 			security_release_secctx(ctx, len);
 		}
+		sig_data->cid = audit_sig_cid;
 		audit_send_reply(skb, seq, AUDIT_SIGNAL_INFO, 0, 0,
 				 sig_data, sizeof(*sig_data) + len);
 		kfree(sig_data);
diff --git a/kernel/audit.h b/kernel/audit.h
index c00e2ee3c6b3..c5ac6436317e 100644
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -148,6 +148,7 @@ struct audit_context {
 	kuid_t		    target_uid;
 	unsigned int	    target_sessionid;
 	u32		    target_sid;
+	u64		    target_cid;
 	char		    target_comm[TASK_COMM_LEN];
 
 	struct audit_tree_refs *trees, *first_trees;
@@ -344,6 +345,7 @@ extern void audit_filter_inodes(struct task_struct *tsk,
 extern pid_t audit_sig_pid;
 extern kuid_t audit_sig_uid;
 extern u32 audit_sig_sid;
+extern u64 audit_sig_cid;
 
 extern int audit_filter(int msgtype, unsigned int listtype);
 
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index a8c8b44b954d..f04e115df5dc 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -113,6 +113,7 @@ struct audit_aux_data_pids {
 	kuid_t			target_uid[AUDIT_AUX_PIDS];
 	unsigned int		target_sessionid[AUDIT_AUX_PIDS];
 	u32			target_sid[AUDIT_AUX_PIDS];
+	u64			target_cid[AUDIT_AUX_PIDS];
 	char 			target_comm[AUDIT_AUX_PIDS][TASK_COMM_LEN];
 	int			pid_count;
 };
@@ -1514,7 +1515,7 @@ static void audit_log_exit(void)
 	for (aux = context->aux_pids; aux; aux = aux->next) {
 		struct audit_aux_data_pids *axs = (void *)aux;
 
-		for (i = 0; i < axs->pid_count; i++)
+		for (i = 0; i < axs->pid_count; i++) {
 			if (audit_log_pid_context(context, axs->target_pid[i],
 						  axs->target_auid[i],
 						  axs->target_uid[i],
@@ -1522,14 +1523,20 @@ static void audit_log_exit(void)
 						  axs->target_sid[i],
 						  axs->target_comm[i]))
 				call_panic = 1;
+			audit_log_contid(context, axs->target_cid[i]);
+		}
 	}
 
-	if (context->target_pid &&
-	    audit_log_pid_context(context, context->target_pid,
-				  context->target_auid, context->target_uid,
-				  context->target_sessionid,
-				  context->target_sid, context->target_comm))
+	if (context->target_pid) {
+		if (audit_log_pid_context(context, context->target_pid,
+					  context->target_auid,
+					  context->target_uid,
+					  context->target_sessionid,
+					  context->target_sid,
+					  context->target_comm))
 			call_panic = 1;
+		audit_log_contid(context, context->target_cid);
+	}
 
 	if (context->pwd.dentry && context->pwd.mnt) {
 		ab = audit_log_start(context, GFP_KERNEL, AUDIT_CWD);
@@ -2360,6 +2367,7 @@ void __audit_ptrace(struct task_struct *t)
 	context->target_uid = task_uid(t);
 	context->target_sessionid = audit_get_sessionid(t);
 	security_task_getsecid(t, &context->target_sid);
+	context->target_cid = audit_get_contid(t);
 	memcpy(context->target_comm, t->comm, TASK_COMM_LEN);
 }
 
@@ -2387,6 +2395,7 @@ int audit_signal_info(int sig, struct task_struct *t)
 		else
 			audit_sig_uid = uid;
 		security_task_getsecid(current, &audit_sig_sid);
+		audit_sig_cid = audit_get_contid(current);
 	}
 
 	if (!audit_signals || audit_dummy_context())
@@ -2400,6 +2409,7 @@ int audit_signal_info(int sig, struct task_struct *t)
 		ctx->target_uid = t_uid;
 		ctx->target_sessionid = audit_get_sessionid(t);
 		security_task_getsecid(t, &ctx->target_sid);
+		ctx->target_cid = audit_get_contid(t);
 		memcpy(ctx->target_comm, t->comm, TASK_COMM_LEN);
 		return 0;
 	}
@@ -2421,6 +2431,7 @@ int audit_signal_info(int sig, struct task_struct *t)
 	axp->target_uid[axp->pid_count] = t_uid;
 	axp->target_sessionid[axp->pid_count] = audit_get_sessionid(t);
 	security_task_getsecid(t, &axp->target_sid[axp->pid_count]);
+	axp->target_cid[axp->pid_count] = audit_get_contid(t);
 	memcpy(axp->target_comm[axp->pid_count], t->comm, TASK_COMM_LEN);
 	axp->pid_count++;
 
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH ghak90 V5 06/10] audit: add support for non-syscall auxiliary records
  2019-03-15 18:29 [PATCH ghak90 V5 00/10] audit: implement container identifier Richard Guy Briggs
                   ` (4 preceding siblings ...)
  2019-03-15 18:29 ` [PATCH ghak90 V5 05/10] audit: add containerid support for ptrace and signals Richard Guy Briggs
@ 2019-03-15 18:29 ` Richard Guy Briggs
  2019-03-18 19:34   ` Neil Horman
                     ` (2 more replies)
  2019-03-15 18:29 ` [PATCH ghak90 V5 07/10] audit: add containerid support for user records Richard Guy Briggs
                   ` (3 subsequent siblings)
  9 siblings, 3 replies; 64+ messages in thread
From: Richard Guy Briggs @ 2019-03-15 18:29 UTC (permalink / raw)
  To: containers, linux-api, Linux-Audit Mailing List, linux-fsdevel,
	LKML, netdev, netfilter-devel
  Cc: Paul Moore, sgrubb, omosnace, dhowells, simo, eparis, serge,
	ebiederm, nhorman, Richard Guy Briggs

Standalone audit records have the timestamp and serial number generated
on the fly and as such are unique, making them standalone.  This new
function audit_alloc_local() generates a local audit context that will
be used only for a standalone record and its auxiliary record(s).  The
context is discarded immediately after the local associated records are
produced.

Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
Acked-by: Serge Hallyn <serge@hallyn.com>
---
 include/linux/audit.h |  8 ++++++++
 kernel/audit.h        |  1 +
 kernel/auditsc.c      | 35 ++++++++++++++++++++++++++++++-----
 3 files changed, 39 insertions(+), 5 deletions(-)

diff --git a/include/linux/audit.h b/include/linux/audit.h
index ebd6625ca80e..6db5aba7cc01 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -285,6 +285,8 @@ static inline void audit_log_contid(struct audit_context *context, u64 contid)
 
 /* These are defined in auditsc.c */
 				/* Public API */
+extern struct audit_context *audit_alloc_local(gfp_t gfpflags);
+extern void audit_free_context(struct audit_context *context);
 extern void __audit_syscall_entry(int major, unsigned long a0, unsigned long a1,
 				  unsigned long a2, unsigned long a3);
 extern void __audit_syscall_exit(int ret_success, long ret_value);
@@ -512,6 +514,12 @@ static inline void audit_fanotify(unsigned int response)
 extern int audit_n_rules;
 extern int audit_signals;
 #else /* CONFIG_AUDITSYSCALL */
+static inline struct audit_context *audit_alloc_local(gfp_t gfpflags)
+{
+	return NULL;
+}
+static inline void audit_free_context(struct audit_context *context)
+{ }
 static inline void audit_syscall_entry(int major, unsigned long a0,
 				       unsigned long a1, unsigned long a2,
 				       unsigned long a3)
diff --git a/kernel/audit.h b/kernel/audit.h
index c5ac6436317e..2a1a8b8a8019 100644
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -111,6 +111,7 @@ struct audit_proctitle {
 struct audit_context {
 	int		    dummy;	/* must be the first element */
 	int		    in_syscall;	/* 1 if task is in a syscall */
+	bool		    local;	/* local context needed */
 	enum audit_state    state, current_state;
 	unsigned int	    serial;     /* serial number for record */
 	int		    major;      /* syscall number */
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index f04e115df5dc..aa5d13b4fbbb 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -872,11 +872,13 @@ static inline void audit_free_aux(struct audit_context *context)
 	}
 }
 
-static inline struct audit_context *audit_alloc_context(enum audit_state state)
+static inline struct audit_context *audit_alloc_context(enum audit_state state,
+							gfp_t gfpflags)
 {
 	struct audit_context *context;
 
-	context = kzalloc(sizeof(*context), GFP_KERNEL);
+	/* We can be called in atomic context via audit_tg() */
+	context = kzalloc(sizeof(*context), gfpflags);
 	if (!context)
 		return NULL;
 	context->state = state;
@@ -912,7 +914,8 @@ int audit_alloc_syscall(struct task_struct *tsk)
 		return 0;
 	}
 
-	if (!(context = audit_alloc_context(state))) {
+	context = audit_alloc_context(state, GFP_KERNEL);
+	if (!context) {
 		kfree(key);
 		audit_log_lost("out of memory in audit_alloc_syscall");
 		return -ENOMEM;
@@ -924,8 +927,29 @@ int audit_alloc_syscall(struct task_struct *tsk)
 	return 0;
 }
 
-static inline void audit_free_context(struct audit_context *context)
+struct audit_context *audit_alloc_local(gfp_t gfpflags)
 {
+	struct audit_context *context = NULL;
+
+	if (!audit_ever_enabled)
+		goto out; /* Return if not auditing. */
+	context = audit_alloc_context(AUDIT_RECORD_CONTEXT, gfpflags);
+	if (!context) {
+		audit_log_lost("out of memory in audit_alloc_local");
+		goto out;
+	}
+	context->serial = audit_serial();
+	ktime_get_coarse_real_ts64(&context->ctime);
+	context->local = true;
+out:
+	return context;
+}
+EXPORT_SYMBOL(audit_alloc_local);
+
+void audit_free_context(struct audit_context *context)
+{
+	if (!context)
+		return;
 	audit_free_names(context);
 	unroll_tree_refs(context, NULL, 0);
 	free_tree_refs(context);
@@ -935,6 +959,7 @@ static inline void audit_free_context(struct audit_context *context)
 	audit_proctitle_free(context);
 	kfree(context);
 }
+EXPORT_SYMBOL(audit_free_context);
 
 static int audit_log_pid_context(struct audit_context *context, pid_t pid,
 				 kuid_t auid, kuid_t uid, unsigned int sessionid,
@@ -2163,7 +2188,7 @@ void __audit_inode_child(struct inode *parent,
 int auditsc_get_stamp(struct audit_context *ctx,
 		       struct timespec64 *t, unsigned int *serial)
 {
-	if (!ctx->in_syscall)
+	if (!ctx->in_syscall && !ctx->local)
 		return 0;
 	if (!ctx->serial)
 		ctx->serial = audit_serial();
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH ghak90 V5 07/10] audit: add containerid support for user records
  2019-03-15 18:29 [PATCH ghak90 V5 00/10] audit: implement container identifier Richard Guy Briggs
                   ` (5 preceding siblings ...)
  2019-03-15 18:29 ` [PATCH ghak90 V5 06/10] audit: add support for non-syscall auxiliary records Richard Guy Briggs
@ 2019-03-15 18:29 ` Richard Guy Briggs
  2019-03-18 19:41   ` Neil Horman
  2019-03-27 21:30   ` Ondrej Mosnacek
  2019-03-15 18:29 ` [PATCH ghak90 V5 08/10] audit: add containerid filtering Richard Guy Briggs
                   ` (2 subsequent siblings)
  9 siblings, 2 replies; 64+ messages in thread
From: Richard Guy Briggs @ 2019-03-15 18:29 UTC (permalink / raw)
  To: containers, linux-api, Linux-Audit Mailing List, linux-fsdevel,
	LKML, netdev, netfilter-devel
  Cc: Paul Moore, sgrubb, omosnace, dhowells, simo, eparis, serge,
	ebiederm, nhorman, Richard Guy Briggs

Add audit container identifier auxiliary record to user event standalone
records.

Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
---
 kernel/audit.c | 13 ++++++-------
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/kernel/audit.c b/kernel/audit.c
index cfa659b3f6c4..cf448599ef34 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -1142,12 +1142,6 @@ static void audit_log_common_recv_msg(struct audit_context *context,
 	audit_log_task_context(*ab);
 }
 
-static inline void audit_log_user_recv_msg(struct audit_buffer **ab,
-					   u16 msg_type)
-{
-	audit_log_common_recv_msg(NULL, ab, msg_type);
-}
-
 int is_audit_feature_set(int i)
 {
 	return af.features & AUDIT_FEATURE_TO_MASK(i);
@@ -1409,13 +1403,16 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 
 		err = audit_filter(msg_type, AUDIT_FILTER_USER);
 		if (err == 1) { /* match or error */
+			struct audit_context *context;
+
 			err = 0;
 			if (msg_type == AUDIT_USER_TTY) {
 				err = tty_audit_push();
 				if (err)
 					break;
 			}
-			audit_log_user_recv_msg(&ab, msg_type);
+			context = audit_alloc_local(GFP_KERNEL);
+			audit_log_common_recv_msg(context, &ab, msg_type);
 			if (msg_type != AUDIT_USER_TTY)
 				audit_log_format(ab, " msg='%.*s'",
 						 AUDIT_MESSAGE_TEXT_MAX,
@@ -1431,6 +1428,8 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 				audit_log_n_untrustedstring(ab, data, size);
 			}
 			audit_log_end(ab);
+			audit_log_contid(context, audit_get_contid(current));
+			audit_free_context(context);
 		}
 		break;
 	case AUDIT_ADD_RULE:
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH ghak90 V5 08/10] audit: add containerid filtering
  2019-03-15 18:29 [PATCH ghak90 V5 00/10] audit: implement container identifier Richard Guy Briggs
                   ` (6 preceding siblings ...)
  2019-03-15 18:29 ` [PATCH ghak90 V5 07/10] audit: add containerid support for user records Richard Guy Briggs
@ 2019-03-15 18:29 ` Richard Guy Briggs
  2019-03-18 20:02   ` Ondrej Mosnacek
  2019-03-18 20:39   ` Neil Horman
  2019-03-15 18:29 ` [PATCH ghak90 V5 09/10] audit: add support for containerid to network namespaces Richard Guy Briggs
  2019-03-15 18:29 ` [PATCH ghak90 V5 10/10] audit: NETFILTER_PKT: record each container ID associated with a netNS Richard Guy Briggs
  9 siblings, 2 replies; 64+ messages in thread
From: Richard Guy Briggs @ 2019-03-15 18:29 UTC (permalink / raw)
  To: containers, linux-api, Linux-Audit Mailing List, linux-fsdevel,
	LKML, netdev, netfilter-devel
  Cc: Paul Moore, sgrubb, omosnace, dhowells, simo, eparis, serge,
	ebiederm, nhorman, Richard Guy Briggs

Implement audit container identifier filtering using the AUDIT_CONTID
field name to send an 8-character string representing a u64 since the
value field is only u32.

Sending it as two u32 was considered, but gathering and comparing two
fields was more complex.

The feature indicator is AUDIT_FEATURE_BITMAP_CONTAINERID.

See: https://github.com/linux-audit/audit-kernel/issues/91
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
Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
Acked-by: Serge Hallyn <serge@hallyn.com>
---
 include/linux/audit.h      |  1 +
 include/uapi/linux/audit.h |  5 ++++-
 kernel/audit.h             |  1 +
 kernel/auditfilter.c       | 47 ++++++++++++++++++++++++++++++++++++++++++++++
 kernel/auditsc.c           |  3 +++
 5 files changed, 56 insertions(+), 1 deletion(-)

diff --git a/include/linux/audit.h b/include/linux/audit.h
index 6db5aba7cc01..fa19fa408931 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -77,6 +77,7 @@ struct audit_field {
 	u32				type;
 	union {
 		u32			val;
+		u64			val64;
 		kuid_t			uid;
 		kgid_t			gid;
 		struct {
diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h
index a6383e28b2c8..741ab6f38294 100644
--- a/include/uapi/linux/audit.h
+++ b/include/uapi/linux/audit.h
@@ -265,6 +265,7 @@
 #define AUDIT_LOGINUID_SET	24
 #define AUDIT_SESSIONID	25	/* Session ID */
 #define AUDIT_FSTYPE	26	/* FileSystem Type */
+#define AUDIT_CONTID	27	/* Container ID */
 
 				/* These are ONLY useful when checking
 				 * at syscall exit time (AUDIT_AT_EXIT). */
@@ -345,6 +346,7 @@ enum {
 #define AUDIT_FEATURE_BITMAP_SESSIONID_FILTER	0x00000010
 #define AUDIT_FEATURE_BITMAP_LOST_RESET		0x00000020
 #define AUDIT_FEATURE_BITMAP_FILTER_FS		0x00000040
+#define AUDIT_FEATURE_BITMAP_CONTAINERID	0x00000080
 
 #define AUDIT_FEATURE_BITMAP_ALL (AUDIT_FEATURE_BITMAP_BACKLOG_LIMIT | \
 				  AUDIT_FEATURE_BITMAP_BACKLOG_WAIT_TIME | \
@@ -352,7 +354,8 @@ enum {
 				  AUDIT_FEATURE_BITMAP_EXCLUDE_EXTEND | \
 				  AUDIT_FEATURE_BITMAP_SESSIONID_FILTER | \
 				  AUDIT_FEATURE_BITMAP_LOST_RESET | \
-				  AUDIT_FEATURE_BITMAP_FILTER_FS)
+				  AUDIT_FEATURE_BITMAP_FILTER_FS | \
+				  AUDIT_FEATURE_BITMAP_CONTAINERID)
 
 /* deprecated: AUDIT_VERSION_* */
 #define AUDIT_VERSION_LATEST 		AUDIT_FEATURE_BITMAP_ALL
diff --git a/kernel/audit.h b/kernel/audit.h
index 2a1a8b8a8019..3a40b608bf8d 100644
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -230,6 +230,7 @@ static inline int audit_hash_ino(u32 ino)
 
 extern int audit_match_class(int class, unsigned syscall);
 extern int audit_comparator(const u32 left, const u32 op, const u32 right);
+extern int audit_comparator64(const u64 left, const u32 op, const u64 right);
 extern int audit_uid_comparator(kuid_t left, u32 op, kuid_t right);
 extern int audit_gid_comparator(kgid_t left, u32 op, kgid_t right);
 extern int parent_len(const char *path);
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index add360b46b38..516b8e58959e 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -410,6 +410,7 @@ static int audit_field_valid(struct audit_entry *entry, struct audit_field *f)
 	/* FALL THROUGH */
 	case AUDIT_ARCH:
 	case AUDIT_FSTYPE:
+	case AUDIT_CONTID:
 		if (f->op != Audit_not_equal && f->op != Audit_equal)
 			return -EINVAL;
 		break;
@@ -582,6 +583,14 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
 			}
 			entry->rule.exe = audit_mark;
 			break;
+		case AUDIT_CONTID:
+			if (f->val != sizeof(u64))
+				goto exit_free;
+			str = audit_unpack_string(&bufp, &remain, f->val);
+			if (IS_ERR(str))
+				goto exit_free;
+			f->val64 = ((u64 *)str)[0];
+			break;
 		}
 	}
 
@@ -664,6 +673,11 @@ static struct audit_rule_data *audit_krule_to_data(struct audit_krule *krule)
 			data->buflen += data->values[i] =
 				audit_pack_string(&bufp, audit_mark_path(krule->exe));
 			break;
+		case AUDIT_CONTID:
+			data->buflen += data->values[i] = sizeof(u64);
+			for (i = 0; i < sizeof(u64); i++)
+				((char *)bufp)[i] = ((char *)&f->val64)[i];
+			break;
 		case AUDIT_LOGINUID_SET:
 			if (krule->pflags & AUDIT_LOGINUID_LEGACY && !f->val) {
 				data->fields[i] = AUDIT_LOGINUID;
@@ -750,6 +764,10 @@ static int audit_compare_rule(struct audit_krule *a, struct audit_krule *b)
 			if (!gid_eq(a->fields[i].gid, b->fields[i].gid))
 				return 1;
 			break;
+		case AUDIT_CONTID:
+			if (a->fields[i].val64 != b->fields[i].val64)
+				return 1;
+			break;
 		default:
 			if (a->fields[i].val != b->fields[i].val)
 				return 1;
@@ -1206,6 +1224,31 @@ int audit_comparator(u32 left, u32 op, u32 right)
 	}
 }
 
+int audit_comparator64(u64 left, u32 op, u64 right)
+{
+	switch (op) {
+	case Audit_equal:
+		return (left == right);
+	case Audit_not_equal:
+		return (left != right);
+	case Audit_lt:
+		return (left < right);
+	case Audit_le:
+		return (left <= right);
+	case Audit_gt:
+		return (left > right);
+	case Audit_ge:
+		return (left >= right);
+	case Audit_bitmask:
+		return (left & right);
+	case Audit_bittest:
+		return ((left & right) == right);
+	default:
+		BUG();
+		return 0;
+	}
+}
+
 int audit_uid_comparator(kuid_t left, u32 op, kuid_t right)
 {
 	switch (op) {
@@ -1344,6 +1387,10 @@ int audit_filter(int msgtype, unsigned int listtype)
 				result = audit_comparator(audit_loginuid_set(current),
 							  f->op, f->val);
 				break;
+			case AUDIT_CONTID:
+				result = audit_comparator64(audit_get_contid(current),
+							      f->op, f->val64);
+				break;
 			case AUDIT_MSGTYPE:
 				result = audit_comparator(msgtype, f->op, f->val);
 				break;
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index aa5d13b4fbbb..2d74238e9638 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -616,6 +616,9 @@ static int audit_filter_rules(struct task_struct *tsk,
 		case AUDIT_LOGINUID_SET:
 			result = audit_comparator(audit_loginuid_set(tsk), f->op, f->val);
 			break;
+		case AUDIT_CONTID:
+			result = audit_comparator64(audit_get_contid(tsk), f->op, f->val64);
+			break;
 		case AUDIT_SUBJ_USER:
 		case AUDIT_SUBJ_ROLE:
 		case AUDIT_SUBJ_TYPE:
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH ghak90 V5 09/10] audit: add support for containerid to network namespaces
  2019-03-15 18:29 [PATCH ghak90 V5 00/10] audit: implement container identifier Richard Guy Briggs
                   ` (7 preceding siblings ...)
  2019-03-15 18:29 ` [PATCH ghak90 V5 08/10] audit: add containerid filtering Richard Guy Briggs
@ 2019-03-15 18:29 ` Richard Guy Briggs
  2019-03-18 20:56   ` Neil Horman
                     ` (2 more replies)
  2019-03-15 18:29 ` [PATCH ghak90 V5 10/10] audit: NETFILTER_PKT: record each container ID associated with a netNS Richard Guy Briggs
  9 siblings, 3 replies; 64+ messages in thread
From: Richard Guy Briggs @ 2019-03-15 18:29 UTC (permalink / raw)
  To: containers, linux-api, Linux-Audit Mailing List, linux-fsdevel,
	LKML, netdev, netfilter-devel
  Cc: Paul Moore, sgrubb, omosnace, dhowells, simo, eparis, serge,
	ebiederm, nhorman, Richard Guy Briggs

Audit events could happen in a network namespace outside of a task
context due to packets received from the net that trigger an auditing
rule prior to being associated with a running task.  The network
namespace could be in use by multiple containers by association to the
tasks in that network namespace.  We still want a way to attribute
these events to any potential containers.  Keep a list per network
namespace to track these audit container identifiiers.

Add/increment the audit container identifier on:
- initial setting of the audit container identifier via /proc
- clone/fork call that inherits an audit container identifier
- unshare call that inherits an audit container identifier
- setns call that inherits an audit container identifier
Delete/decrement the audit container identifier on:
- an inherited audit container identifier dropped when child set
- process exit
- unshare call that drops a net namespace
- setns call that drops a net namespace

See: https://github.com/linux-audit/audit-kernel/issues/92
See: https://github.com/linux-audit/audit-testsuite/issues/64
See: https://github.com/linux-audit/audit-kernel/wiki/RFE-Audit-Container-ID
Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
---
 include/linux/audit.h | 19 ++++++++++++
 kernel/audit.c        | 86 +++++++++++++++++++++++++++++++++++++++++++++++++--
 kernel/nsproxy.c      |  4 +++
 3 files changed, 106 insertions(+), 3 deletions(-)

diff --git a/include/linux/audit.h b/include/linux/audit.h
index fa19fa408931..70255c2dfb9f 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -27,6 +27,7 @@
 #include <linux/ptrace.h>
 #include <linux/namei.h>  /* LOOKUP_* */
 #include <uapi/linux/audit.h>
+#include <linux/refcount.h>
 
 #define AUDIT_INO_UNSET ((unsigned long)-1)
 #define AUDIT_DEV_UNSET ((dev_t)-1)
@@ -99,6 +100,13 @@ struct audit_task_info {
 
 extern struct audit_task_info init_struct_audit;
 
+struct audit_contid {
+	struct list_head	list;
+	u64			id;
+	refcount_t		refcount;
+	struct rcu_head		rcu;
+};
+
 extern int is_audit_feature_set(int which);
 
 extern int __init audit_register_class(int class, unsigned *list);
@@ -202,6 +210,10 @@ static inline u64 audit_get_contid(struct task_struct *tsk)
 }
 
 extern void audit_log_contid(struct audit_context *context, u64 contid);
+extern void audit_netns_contid_add(struct net *net, u64 contid);
+extern void audit_netns_contid_del(struct net *net, u64 contid);
+extern void audit_switch_task_namespaces(struct nsproxy *ns,
+					 struct task_struct *p);
 
 extern u32 audit_enabled;
 #else /* CONFIG_AUDIT */
@@ -271,6 +283,13 @@ static inline u64 audit_get_contid(struct task_struct *tsk)
 
 static inline void audit_log_contid(struct audit_context *context, u64 contid)
 { }
+static inline void audit_netns_contid_add(struct net *net, u64 contid)
+{ }
+static inline void audit_netns_contid_del(struct net *net, u64 contid)
+{ }
+static inline void audit_switch_task_namespaces(struct nsproxy *ns,
+						struct task_struct *p)
+{ }
 
 #define audit_enabled AUDIT_OFF
 #endif /* CONFIG_AUDIT */
diff --git a/kernel/audit.c b/kernel/audit.c
index cf448599ef34..7fa3194f5342 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -72,6 +72,7 @@
 #include <linux/freezer.h>
 #include <linux/pid_namespace.h>
 #include <net/netns/generic.h>
+#include <net/net_namespace.h>
 
 #include "audit.h"
 
@@ -99,9 +100,13 @@
 /**
  * struct audit_net - audit private network namespace data
  * @sk: communication socket
+ * @contid_list: audit container identifier list
+ * @contid_list_lock audit container identifier list lock
  */
 struct audit_net {
 	struct sock *sk;
+	struct list_head contid_list;
+	spinlock_t contid_list_lock;
 };
 
 /**
@@ -275,8 +280,11 @@ struct audit_task_info init_struct_audit = {
 void audit_free(struct task_struct *tsk)
 {
 	struct audit_task_info *info = tsk->audit;
+	struct nsproxy *ns = tsk->nsproxy;
 
 	audit_free_syscall(tsk);
+	if (ns)
+		audit_netns_contid_del(ns->net_ns, audit_get_contid(tsk));
 	/* Freeing the audit_task_info struct must be performed after
 	 * audit_log_exit() due to need for loginuid and sessionid.
 	 */
@@ -376,6 +384,73 @@ static struct sock *audit_get_sk(const struct net *net)
 	return aunet->sk;
 }
 
+void audit_netns_contid_add(struct net *net, u64 contid)
+{
+	struct audit_net *aunet = net_generic(net, audit_net_id);
+	struct list_head *contid_list = &aunet->contid_list;
+	struct audit_contid *cont;
+
+	if (!audit_contid_valid(contid))
+		return;
+	if (!aunet)
+		return;
+	spin_lock(&aunet->contid_list_lock);
+	if (!list_empty(contid_list))
+		list_for_each_entry_rcu(cont, contid_list, list)
+			if (cont->id == contid) {
+				refcount_inc(&cont->refcount);
+				goto out;
+			}
+	cont = kmalloc(sizeof(struct audit_contid), GFP_ATOMIC);
+	if (cont) {
+		INIT_LIST_HEAD(&cont->list);
+		cont->id = contid;
+		refcount_set(&cont->refcount, 1);
+		list_add_rcu(&cont->list, contid_list);
+	}
+out:
+	spin_unlock(&aunet->contid_list_lock);
+}
+
+void audit_netns_contid_del(struct net *net, u64 contid)
+{
+	struct audit_net *aunet;
+	struct list_head *contid_list;
+	struct audit_contid *cont = NULL;
+
+	if (!net)
+		return;
+	if (!audit_contid_valid(contid))
+		return;
+	aunet = net_generic(net, audit_net_id);
+	if (!aunet)
+		return;
+	contid_list = &aunet->contid_list;
+	spin_lock(&aunet->contid_list_lock);
+	if (!list_empty(contid_list))
+		list_for_each_entry_rcu(cont, contid_list, list)
+			if (cont->id == contid) {
+				if (refcount_dec_and_test(&cont->refcount)) {
+					list_del_rcu(&cont->list);
+					kfree_rcu(cont, rcu);
+				}
+				break;
+			}
+	spin_unlock(&aunet->contid_list_lock);
+}
+
+void audit_switch_task_namespaces(struct nsproxy *ns, struct task_struct *p)
+{
+	u64 contid = audit_get_contid(p);
+	struct nsproxy *new = p->nsproxy;
+
+	if (!audit_contid_valid(contid))
+		return;
+	audit_netns_contid_del(ns->net_ns, contid);
+	if (new)
+		audit_netns_contid_add(new->net_ns, contid);
+}
+
 void audit_panic(const char *message)
 {
 	switch (audit_failure) {
@@ -1619,7 +1694,6 @@ static int __net_init audit_net_init(struct net *net)
 		.flags	= NL_CFG_F_NONROOT_RECV,
 		.groups	= AUDIT_NLGRP_MAX,
 	};
-
 	struct audit_net *aunet = net_generic(net, audit_net_id);
 
 	aunet->sk = netlink_kernel_create(net, NETLINK_AUDIT, &cfg);
@@ -1628,7 +1702,8 @@ static int __net_init audit_net_init(struct net *net)
 		return -ENOMEM;
 	}
 	aunet->sk->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT;
-
+	INIT_LIST_HEAD(&aunet->contid_list);
+	spin_lock_init(&aunet->contid_list_lock);
 	return 0;
 }
 
@@ -2380,6 +2455,7 @@ int audit_set_contid(struct task_struct *task, u64 contid)
 	uid_t uid;
 	struct tty_struct *tty;
 	char comm[sizeof(current->comm)];
+	struct net *net = task->nsproxy->net_ns;
 
 	task_lock(task);
 	/* Can't set if audit disabled */
@@ -2401,8 +2477,12 @@ int audit_set_contid(struct task_struct *task, u64 contid)
 	else if (!(thread_group_leader(task) && thread_group_empty(task)))
 		rc = -EALREADY;
 	read_unlock(&tasklist_lock);
-	if (!rc)
+	if (!rc) {
+		if (audit_contid_valid(oldcontid))
+			audit_netns_contid_del(net, oldcontid);
 		task->audit->contid = contid;
+		audit_netns_contid_add(net, contid);
+	}
 	task_unlock(task);
 
 	if (!audit_enabled)
diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c
index f6c5d330059a..718b1201ae70 100644
--- a/kernel/nsproxy.c
+++ b/kernel/nsproxy.c
@@ -27,6 +27,7 @@
 #include <linux/syscalls.h>
 #include <linux/cgroup.h>
 #include <linux/perf_event.h>
+#include <linux/audit.h>
 
 static struct kmem_cache *nsproxy_cachep;
 
@@ -140,6 +141,7 @@ int copy_namespaces(unsigned long flags, struct task_struct *tsk)
 	struct nsproxy *old_ns = tsk->nsproxy;
 	struct user_namespace *user_ns = task_cred_xxx(tsk, user_ns);
 	struct nsproxy *new_ns;
+	u64 contid = audit_get_contid(tsk);
 
 	if (likely(!(flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC |
 			      CLONE_NEWPID | CLONE_NEWNET |
@@ -167,6 +169,7 @@ int copy_namespaces(unsigned long flags, struct task_struct *tsk)
 		return  PTR_ERR(new_ns);
 
 	tsk->nsproxy = new_ns;
+	audit_netns_contid_add(new_ns->net_ns, contid);
 	return 0;
 }
 
@@ -224,6 +227,7 @@ void switch_task_namespaces(struct task_struct *p, struct nsproxy *new)
 	ns = p->nsproxy;
 	p->nsproxy = new;
 	task_unlock(p);
+	audit_switch_task_namespaces(ns, p);
 
 	if (ns && atomic_dec_and_test(&ns->count))
 		free_nsproxy(ns);
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH ghak90 V5 10/10] audit: NETFILTER_PKT: record each container ID associated with a netNS
  2019-03-15 18:29 [PATCH ghak90 V5 00/10] audit: implement container identifier Richard Guy Briggs
                   ` (8 preceding siblings ...)
  2019-03-15 18:29 ` [PATCH ghak90 V5 09/10] audit: add support for containerid to network namespaces Richard Guy Briggs
@ 2019-03-15 18:29 ` Richard Guy Briggs
  2019-03-18 20:58   ` Neil Horman
                     ` (2 more replies)
  9 siblings, 3 replies; 64+ messages in thread
From: Richard Guy Briggs @ 2019-03-15 18:29 UTC (permalink / raw)
  To: containers, linux-api, Linux-Audit Mailing List, linux-fsdevel,
	LKML, netdev, netfilter-devel
  Cc: Paul Moore, sgrubb, omosnace, dhowells, simo, eparis, serge,
	ebiederm, nhorman, Richard Guy Briggs

Add audit container identifier auxiliary record(s) to NETFILTER_PKT
event standalone records.  Iterate through all potential audit container
identifiers associated with a network namespace.

Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
---
 include/linux/audit.h    |  5 +++++
 kernel/audit.c           | 41 +++++++++++++++++++++++++++++++++++++++++
 net/netfilter/nft_log.c  | 11 +++++++++--
 net/netfilter/xt_AUDIT.c | 11 +++++++++--
 4 files changed, 64 insertions(+), 4 deletions(-)

diff --git a/include/linux/audit.h b/include/linux/audit.h
index 70255c2dfb9f..723e2d020228 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -214,6 +214,8 @@ static inline u64 audit_get_contid(struct task_struct *tsk)
 extern void audit_netns_contid_del(struct net *net, u64 contid);
 extern void audit_switch_task_namespaces(struct nsproxy *ns,
 					 struct task_struct *p);
+extern void audit_log_netns_contid_list(struct net *net,
+					struct audit_context *context);
 
 extern u32 audit_enabled;
 #else /* CONFIG_AUDIT */
@@ -290,6 +292,9 @@ static inline void audit_netns_contid_del(struct net *net, u64 contid)
 static inline void audit_switch_task_namespaces(struct nsproxy *ns,
 						struct task_struct *p)
 { }
+static inline void audit_log_netns_contid_list(struct net *net,
+					       struct audit_context *context)
+{ }
 
 #define audit_enabled AUDIT_OFF
 #endif /* CONFIG_AUDIT */
diff --git a/kernel/audit.c b/kernel/audit.c
index 7fa3194f5342..80ed323feeb5 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -451,6 +451,47 @@ void audit_switch_task_namespaces(struct nsproxy *ns, struct task_struct *p)
 		audit_netns_contid_add(new->net_ns, contid);
 }
 
+/**
+ * audit_log_netns_contid_list - List contids for the given network namespace
+ * @net: the network namespace of interest
+ * @context: the audit context to use
+ *
+ * Description:
+ * Issues a CONTAINER_ID record with a CSV list of contids associated
+ * with a network namespace to accompany a NETFILTER_PKT record.
+ */
+void audit_log_netns_contid_list(struct net *net, struct audit_context *context)
+{
+	struct audit_buffer *ab = NULL;
+	struct audit_contid *cont;
+	bool first = true;
+	struct audit_net *aunet;
+
+	/* Generate AUDIT_CONTAINER_ID record with container ID CSV list */
+	rcu_read_lock();
+	aunet = net_generic(net, audit_net_id);
+	if (!aunet)
+		goto out;
+	list_for_each_entry_rcu(cont, &aunet->contid_list, list) {
+		if (first) {
+			ab = audit_log_start(context, GFP_ATOMIC,
+					     AUDIT_CONTAINER_ID);
+			if (!ab) {
+				audit_log_lost("out of memory in audit_log_netns_contid_list");
+				goto out;
+			}
+			audit_log_format(ab, "contid=");
+		} else 
+			audit_log_format(ab, ",");
+		audit_log_format(ab, "%llu", cont->id);
+		first = false;
+	}
+	audit_log_end(ab);
+out:
+	rcu_read_unlock();
+}
+EXPORT_SYMBOL(audit_log_netns_contid_list);
+
 void audit_panic(const char *message)
 {
 	switch (audit_failure) {
diff --git a/net/netfilter/nft_log.c b/net/netfilter/nft_log.c
index 655187bed5d8..bdb1ec2368a7 100644
--- a/net/netfilter/nft_log.c
+++ b/net/netfilter/nft_log.c
@@ -69,13 +69,16 @@ static void nft_log_eval_audit(const struct nft_pktinfo *pkt)
 	struct sk_buff *skb = pkt->skb;
 	struct audit_buffer *ab;
 	int fam = -1;
+	struct audit_context *context;
+	struct net *net;
 
 	if (!audit_enabled)
 		return;
 
-	ab = audit_log_start(NULL, GFP_ATOMIC, AUDIT_NETFILTER_PKT);
+	context = audit_alloc_local(GFP_ATOMIC);
+	ab = audit_log_start(context, GFP_ATOMIC, AUDIT_NETFILTER_PKT);
 	if (!ab)
-		return;
+		goto errout;
 
 	audit_log_format(ab, "mark=%#x", skb->mark);
 
@@ -102,6 +105,10 @@ static void nft_log_eval_audit(const struct nft_pktinfo *pkt)
 		audit_log_format(ab, " saddr=? daddr=? proto=-1");
 
 	audit_log_end(ab);
+	net = xt_net(&pkt->xt);
+	audit_log_netns_contid_list(net, context);
+errout:
+	audit_free_context(context);
 }
 
 static void nft_log_eval(const struct nft_expr *expr,
diff --git a/net/netfilter/xt_AUDIT.c b/net/netfilter/xt_AUDIT.c
index af883f1b64f9..a3e547435f13 100644
--- a/net/netfilter/xt_AUDIT.c
+++ b/net/netfilter/xt_AUDIT.c
@@ -71,10 +71,13 @@ static bool audit_ip6(struct audit_buffer *ab, struct sk_buff *skb)
 {
 	struct audit_buffer *ab;
 	int fam = -1;
+	struct audit_context *context;
+	struct net *net;
 
 	if (audit_enabled == AUDIT_OFF)
-		goto errout;
-	ab = audit_log_start(NULL, GFP_ATOMIC, AUDIT_NETFILTER_PKT);
+		goto out;
+	context = audit_alloc_local(GFP_ATOMIC);
+	ab = audit_log_start(context, GFP_ATOMIC, AUDIT_NETFILTER_PKT);
 	if (ab == NULL)
 		goto errout;
 
@@ -104,7 +107,11 @@ static bool audit_ip6(struct audit_buffer *ab, struct sk_buff *skb)
 
 	audit_log_end(ab);
 
+	net = xt_net(par);
+	audit_log_netns_contid_list(net, context);
 errout:
+	audit_free_context(context);
+out:
 	return XT_CONTINUE;
 }
 
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* Re: [PATCH ghak90 V5 01/10] audit: collect audit task parameters
  2019-03-15 18:29 ` [PATCH ghak90 V5 01/10] audit: collect audit task parameters Richard Guy Briggs
@ 2019-03-16 19:57   ` Neil Horman
  2019-03-27 20:33   ` Ondrej Mosnacek
  1 sibling, 0 replies; 64+ messages in thread
From: Neil Horman @ 2019-03-16 19:57 UTC (permalink / raw)
  To: Richard Guy Briggs
  Cc: containers, linux-api, Linux-Audit Mailing List, linux-fsdevel,
	LKML, netdev, netfilter-devel, Paul Moore, sgrubb, omosnace,
	dhowells, simo, eparis, serge, ebiederm

On Fri, Mar 15, 2019 at 02:29:49PM -0400, Richard Guy Briggs wrote:
> The audit-related parameters in struct task_struct should ideally be
> collected together and accessed through a standard audit API.
> 
> Collect the existing loginuid, sessionid and audit_context together in a
> new struct audit_task_info called "audit" in struct task_struct.
> 
> Use kmem_cache to manage this pool of memory.
> Un-inline audit_free() to be able to always recover that memory.
> 
> Please see the upstream github issue
> https://github.com/linux-audit/audit-kernel/issues/81
> but that issue has been closed with this patch included with
> https://github.com/linux-audit/audit-kernel/issues/90
> 
> Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> ---
>  include/linux/audit.h | 49 +++++++++++++++++++++++------------
>  include/linux/sched.h |  7 +----
>  init/init_task.c      |  3 +--
>  init/main.c           |  2 ++
>  kernel/audit.c        | 71 +++++++++++++++++++++++++++++++++++++++++++++++++--
>  kernel/audit.h        |  5 ++++
>  kernel/auditsc.c      | 26 ++++++++++---------
>  kernel/fork.c         |  1 -
>  8 files changed, 124 insertions(+), 40 deletions(-)
> 
> diff --git a/include/linux/audit.h b/include/linux/audit.h
> index 1e69d9fe16da..bde346e73f0c 100644
> --- a/include/linux/audit.h
> +++ b/include/linux/audit.h
> @@ -86,6 +86,16 @@ struct audit_field {
>  	u32				op;
>  };
>  
> +struct audit_task_info {
> +	kuid_t			loginuid;
> +	unsigned int		sessionid;
> +#ifdef CONFIG_AUDITSYSCALL
> +	struct audit_context	*ctx;
> +#endif
> +};
> +
> +extern struct audit_task_info init_struct_audit;
> +
>  extern int is_audit_feature_set(int which);
>  
>  extern int __init audit_register_class(int class, unsigned *list);
> @@ -122,6 +132,9 @@ struct audit_field {
>  #ifdef CONFIG_AUDIT
>  /* These are defined in audit.c */
>  				/* Public API */
> +extern int  audit_alloc(struct task_struct *task);
> +extern void audit_free(struct task_struct *task);
> +extern void __init audit_task_init(void);
>  extern __printf(4, 5)
>  void audit_log(struct audit_context *ctx, gfp_t gfp_mask, int type,
>  	       const char *fmt, ...);
> @@ -164,16 +177,28 @@ extern void		    audit_log_key(struct audit_buffer *ab,
>  
>  static inline kuid_t audit_get_loginuid(struct task_struct *tsk)
>  {
> -	return tsk->loginuid;
> +	if (!tsk->audit)
> +		return INVALID_UID;
> +	return tsk->audit->loginuid;
>  }
>  
>  static inline unsigned int audit_get_sessionid(struct task_struct *tsk)
>  {
> -	return tsk->sessionid;
> +	if (!tsk->audit)
> +		return AUDIT_SID_UNSET;
> +	return tsk->audit->sessionid;
>  }
>  
>  extern u32 audit_enabled;
>  #else /* CONFIG_AUDIT */
> +static inline int audit_alloc(struct task_struct *task)
> +{
> +	return 0;
> +}
> +static inline void audit_free(struct task_struct *task)
> +{ }
> +static inline void __init audit_task_init(void)
> +{ }
>  static inline __printf(4, 5)
>  void audit_log(struct audit_context *ctx, gfp_t gfp_mask, int type,
>  	       const char *fmt, ...)
> @@ -239,8 +264,6 @@ static inline unsigned int audit_get_sessionid(struct task_struct *tsk)
>  
>  /* These are defined in auditsc.c */
>  				/* Public API */
> -extern int  audit_alloc(struct task_struct *task);
> -extern void __audit_free(struct task_struct *task);
>  extern void __audit_syscall_entry(int major, unsigned long a0, unsigned long a1,
>  				  unsigned long a2, unsigned long a3);
>  extern void __audit_syscall_exit(int ret_success, long ret_value);
> @@ -263,12 +286,14 @@ extern void audit_seccomp_actions_logged(const char *names,
>  
>  static inline void audit_set_context(struct task_struct *task, struct audit_context *ctx)
>  {
> -	task->audit_context = ctx;
> +	task->audit->ctx = ctx;
>  }
>  
>  static inline struct audit_context *audit_context(void)
>  {
> -	return current->audit_context;
> +	if (!current->audit)
> +		return NULL;
> +	return current->audit->ctx;
>  }
>  
>  static inline bool audit_dummy_context(void)
> @@ -276,11 +301,7 @@ static inline bool audit_dummy_context(void)
>  	void *p = audit_context();
>  	return !p || *(int *)p;
>  }
> -static inline void audit_free(struct task_struct *task)
> -{
> -	if (unlikely(task->audit_context))
> -		__audit_free(task);
> -}
> +
>  static inline void audit_syscall_entry(int major, unsigned long a0,
>  				       unsigned long a1, unsigned long a2,
>  				       unsigned long a3)
> @@ -470,12 +491,6 @@ static inline void audit_fanotify(unsigned int response)
>  extern int audit_n_rules;
>  extern int audit_signals;
>  #else /* CONFIG_AUDITSYSCALL */
> -static inline int audit_alloc(struct task_struct *task)
> -{
> -	return 0;
> -}
> -static inline void audit_free(struct task_struct *task)
> -{ }
>  static inline void audit_syscall_entry(int major, unsigned long a0,
>  				       unsigned long a1, unsigned long a2,
>  				       unsigned long a3)
> diff --git a/include/linux/sched.h b/include/linux/sched.h
> index 765119df759a..6850d1e48ace 100644
> --- a/include/linux/sched.h
> +++ b/include/linux/sched.h
> @@ -31,7 +31,6 @@
>  #include <linux/rseq.h>
>  
>  /* task_struct member predeclarations (sorted alphabetically): */
> -struct audit_context;
>  struct backing_dev_info;
>  struct bio_list;
>  struct blk_plug;
> @@ -886,11 +885,7 @@ struct task_struct {
>  	struct callback_head		*task_works;
>  
>  #ifdef CONFIG_AUDIT
> -#ifdef CONFIG_AUDITSYSCALL
> -	struct audit_context		*audit_context;
> -#endif
> -	kuid_t				loginuid;
> -	unsigned int			sessionid;
> +	struct audit_task_info		*audit;
>  #endif
>  	struct seccomp			seccomp;
>  
> diff --git a/init/init_task.c b/init/init_task.c
> index 39c3109acc1a..f9685e1edda1 100644
> --- a/init/init_task.c
> +++ b/init/init_task.c
> @@ -122,8 +122,7 @@ struct task_struct init_task
>  	.thread_group	= LIST_HEAD_INIT(init_task.thread_group),
>  	.thread_node	= LIST_HEAD_INIT(init_signals.thread_head),
>  #ifdef CONFIG_AUDIT
> -	.loginuid	= INVALID_UID,
> -	.sessionid	= AUDIT_SID_UNSET,
> +	.audit		= &init_struct_audit,
>  #endif
>  #ifdef CONFIG_PERF_EVENTS
>  	.perf_event_mutex = __MUTEX_INITIALIZER(init_task.perf_event_mutex),
> diff --git a/init/main.c b/init/main.c
> index e2e80ca3165a..8a1c36625d12 100644
> --- a/init/main.c
> +++ b/init/main.c
> @@ -92,6 +92,7 @@
>  #include <linux/rodata_test.h>
>  #include <linux/jump_label.h>
>  #include <linux/mem_encrypt.h>
> +#include <linux/audit.h>
>  
>  #include <asm/io.h>
>  #include <asm/bugs.h>
> @@ -727,6 +728,7 @@ asmlinkage __visible void __init start_kernel(void)
>  	nsfs_init();
>  	cpuset_init();
>  	cgroup_init();
> +	audit_task_init();
>  	taskstats_init_early();
>  	delayacct_init();
>  
> diff --git a/kernel/audit.c b/kernel/audit.c
> index c89ea48c70a6..67498c5690bb 100644
> --- a/kernel/audit.c
> +++ b/kernel/audit.c
> @@ -215,6 +215,73 @@ struct audit_reply {
>  	struct sk_buff *skb;
>  };
>  
> +static struct kmem_cache *audit_task_cache;
> +
> +void __init audit_task_init(void)
> +{
> +	audit_task_cache = kmem_cache_create("audit_task",
> +					     sizeof(struct audit_task_info),
> +					     0, SLAB_PANIC, NULL);
> +}
> +
> +/**
> + * audit_alloc - allocate an audit info block for a task
> + * @tsk: task
> + *
> + * Call audit_alloc_syscall to filter on the task information and
> + * allocate a per-task audit context if necessary.  This is called from
> + * copy_process, so no lock is needed.
> + */
> +int audit_alloc(struct task_struct *tsk)
> +{
> +	int ret = 0;
> +	struct audit_task_info *info;
> +
> +	info = kmem_cache_alloc(audit_task_cache, GFP_KERNEL);
> +	if (!info) {
> +		ret = -ENOMEM;
> +		goto out;
> +	}
> +	info->loginuid = audit_get_loginuid(current);
> +	info->sessionid = audit_get_sessionid(current);
> +	tsk->audit = info;
> +
> +	ret = audit_alloc_syscall(tsk);
> +	if (ret) {
> +		tsk->audit = NULL;
> +		kmem_cache_free(audit_task_cache, info);
> +	}
> +out:
> +	return ret;
> +}
> +
> +struct audit_task_info init_struct_audit = {
> +	.loginuid = INVALID_UID,
> +	.sessionid = AUDIT_SID_UNSET,
> +#ifdef CONFIG_AUDITSYSCALL
> +	.ctx = NULL,
> +#endif
> +};
> +
> +/**
> + * audit_free - free per-task audit info
> + * @tsk: task whose audit info block to free
> + *
> + * Called from copy_process and do_exit
> + */
> +void audit_free(struct task_struct *tsk)
> +{
> +	struct audit_task_info *info = tsk->audit;
> +
> +	audit_free_syscall(tsk);
> +	/* Freeing the audit_task_info struct must be performed after
> +	 * audit_log_exit() due to need for loginuid and sessionid.
> +	 */
> +	info = tsk->audit;
> +	tsk->audit = NULL;
> +	kmem_cache_free(audit_task_cache, info);
> +}
> +
>  /**
>   * auditd_test_task - Check to see if a given task is an audit daemon
>   * @task: the task to check
> @@ -2266,8 +2333,8 @@ int audit_set_loginuid(kuid_t loginuid)
>  			sessionid = (unsigned int)atomic_inc_return(&session_id);
>  	}
>  
> -	current->sessionid = sessionid;
> -	current->loginuid = loginuid;
> +	current->audit->sessionid = sessionid;
> +	current->audit->loginuid = loginuid;
>  out:
>  	audit_log_set_loginuid(oldloginuid, loginuid, oldsessionid, sessionid, rc);
>  	return rc;
> diff --git a/kernel/audit.h b/kernel/audit.h
> index 958d5b8fc1b3..c00e2ee3c6b3 100644
> --- a/kernel/audit.h
> +++ b/kernel/audit.h
> @@ -264,6 +264,8 @@ extern void audit_log_d_path_exe(struct audit_buffer *ab,
>  extern unsigned int audit_serial(void);
>  extern int auditsc_get_stamp(struct audit_context *ctx,
>  			      struct timespec64 *t, unsigned int *serial);
> +extern int audit_alloc_syscall(struct task_struct *tsk);
> +extern void audit_free_syscall(struct task_struct *tsk);
>  
>  extern void audit_put_watch(struct audit_watch *watch);
>  extern void audit_get_watch(struct audit_watch *watch);
> @@ -305,6 +307,9 @@ extern void audit_filter_inodes(struct task_struct *tsk,
>  extern struct list_head *audit_killed_trees(void);
>  #else /* CONFIG_AUDITSYSCALL */
>  #define auditsc_get_stamp(c, t, s) 0
> +#define audit_alloc_syscall(t) 0
> +#define audit_free_syscall(t) {}
> +
>  #define audit_put_watch(w) {}
>  #define audit_get_watch(w) {}
>  #define audit_to_watch(k, p, l, o) (-EINVAL)
> diff --git a/kernel/auditsc.c b/kernel/auditsc.c
> index d1eab1d4a930..8090eff7868d 100644
> --- a/kernel/auditsc.c
> +++ b/kernel/auditsc.c
> @@ -885,23 +885,25 @@ static inline struct audit_context *audit_alloc_context(enum audit_state state)
>  	return context;
>  }
>  
> -/**
> - * audit_alloc - allocate an audit context block for a task
> +/*
> + * audit_alloc_syscall - allocate an audit context block for a task
>   * @tsk: task
>   *
>   * Filter on the task information and allocate a per-task audit context
>   * if necessary.  Doing so turns on system call auditing for the
> - * specified task.  This is called from copy_process, so no lock is
> - * needed.
> + * specified task.  This is called from copy_process via audit_alloc, so
> + * no lock is needed.
>   */
> -int audit_alloc(struct task_struct *tsk)
> +int audit_alloc_syscall(struct task_struct *tsk)
>  {
>  	struct audit_context *context;
>  	enum audit_state     state;
>  	char *key = NULL;
>  
> -	if (likely(!audit_ever_enabled))
> +	if (likely(!audit_ever_enabled)) {
> +		audit_set_context(tsk, NULL);
>  		return 0; /* Return if not auditing. */
> +	}
>  
>  	state = audit_filter_task(tsk, &key);
>  	if (state == AUDIT_DISABLED) {
> @@ -911,7 +913,7 @@ int audit_alloc(struct task_struct *tsk)
>  
>  	if (!(context = audit_alloc_context(state))) {
>  		kfree(key);
> -		audit_log_lost("out of memory in audit_alloc");
> +		audit_log_lost("out of memory in audit_alloc_syscall");
>  		return -ENOMEM;
>  	}
>  	context->filterkey = key;
> @@ -1555,14 +1557,15 @@ static void audit_log_exit(void)
>  }
>  
>  /**
> - * __audit_free - free a per-task audit context
> + * audit_free_syscall - free per-task audit context info
>   * @tsk: task whose audit context block to free
>   *
> - * Called from copy_process and do_exit
> + * Called from audit_free
>   */
> -void __audit_free(struct task_struct *tsk)
> +void audit_free_syscall(struct task_struct *tsk)
>  {
> -	struct audit_context *context = tsk->audit_context;
> +	struct audit_task_info *info = tsk->audit;
> +	struct audit_context *context = info->ctx;
>  
>  	if (!context)
>  		return;
> @@ -1585,7 +1588,6 @@ void __audit_free(struct task_struct *tsk)
>  		if (context->current_state == AUDIT_RECORD_CONTEXT)
>  			audit_log_exit();
>  	}
> -
>  	audit_set_context(tsk, NULL);
>  	audit_free_context(context);
>  }
> diff --git a/kernel/fork.c b/kernel/fork.c
> index a60459947f18..1107bd8b8ad8 100644
> --- a/kernel/fork.c
> +++ b/kernel/fork.c
> @@ -1836,7 +1836,6 @@ static __latent_entropy struct task_struct *copy_process(
>  	p->start_time = ktime_get_ns();
>  	p->real_start_time = ktime_get_boot_ns();
>  	p->io_context = NULL;
> -	audit_set_context(p, NULL);
>  	cgroup_fork(p);
>  #ifdef CONFIG_NUMA
>  	p->mempolicy = mpol_dup(p->mempolicy);
> -- 
> 1.8.3.1
> 
> 
Acked-by: Neil Horman <nhorman@tuxdriver.com>


^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH ghak90 V5 02/10] audit: add container id
  2019-03-15 18:29 ` [PATCH ghak90 V5 02/10] audit: add container id Richard Guy Briggs
@ 2019-03-16 20:00   ` Neil Horman
  2019-03-27 20:38   ` Ondrej Mosnacek
  1 sibling, 0 replies; 64+ messages in thread
From: Neil Horman @ 2019-03-16 20:00 UTC (permalink / raw)
  To: Richard Guy Briggs
  Cc: containers, linux-api, Linux-Audit Mailing List, linux-fsdevel,
	LKML, netdev, netfilter-devel, Paul Moore, sgrubb, omosnace,
	dhowells, simo, eparis, serge, ebiederm

On Fri, Mar 15, 2019 at 02:29:50PM -0400, Richard Guy Briggs wrote:
> Implement the proc fs write to set the audit container identifier of a
> process, emitting an AUDIT_CONTAINER_OP record to document the event.
> 
> This is a write from the container orchestrator task to a proc entry of
> the form /proc/PID/audit_containerid where PID is the process ID of the
> newly created task that is to become the first task in a container, or
> an additional task added to a container.
> 
> The write expects up to a u64 value (unset: 18446744073709551615).
> 
> The writer must have capability CAP_AUDIT_CONTROL.
> 
> This will produce a record such as this:
>   type=CONTAINER_OP 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
> 
> The "op" field indicates an initial set.  The "pid" to "ses" fields are
> the orchestrator while the "opid" field is the object's PID, the process
> being "contained".  Old and new audit container identifier values are
> given in the "contid" fields, while res indicates its success.
> 
> It is not permitted to unset the audit container identifier.
> A child inherits its parent's audit container identifier.
> 
> See: https://github.com/linux-audit/audit-kernel/issues/90
> See: https://github.com/linux-audit/audit-userspace/issues/51
> See: https://github.com/linux-audit/audit-testsuite/issues/64
> See: https://github.com/linux-audit/audit-kernel/wiki/RFE-Audit-Container-ID
> 
> Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> Acked-by: Serge Hallyn <serge@hallyn.com>
> Acked-by: Steve Grubb <sgrubb@redhat.com>
> Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> ---
>  fs/proc/base.c             | 36 ++++++++++++++++++++++++
>  include/linux/audit.h      | 25 +++++++++++++++++
>  include/uapi/linux/audit.h |  2 ++
>  kernel/audit.c             | 68 ++++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 131 insertions(+)
> 
> diff --git a/fs/proc/base.c b/fs/proc/base.c
> index a23651ce6960..2505c46c8701 100644
> --- a/fs/proc/base.c
> +++ b/fs/proc/base.c
> @@ -1294,6 +1294,40 @@ static ssize_t proc_sessionid_read(struct file * file, char __user * buf,
>  	.read		= proc_sessionid_read,
>  	.llseek		= generic_file_llseek,
>  };
> +
> +static ssize_t proc_contid_write(struct file *file, const char __user *buf,
> +				   size_t count, loff_t *ppos)
> +{
> +	struct inode *inode = file_inode(file);
> +	u64 contid;
> +	int rv;
> +	struct task_struct *task = get_proc_task(inode);
> +
> +	if (!task)
> +		return -ESRCH;
> +	if (*ppos != 0) {
> +		/* No partial writes. */
> +		put_task_struct(task);
> +		return -EINVAL;
> +	}
> +
> +	rv = kstrtou64_from_user(buf, count, 10, &contid);
> +	if (rv < 0) {
> +		put_task_struct(task);
> +		return rv;
> +	}
> +
> +	rv = audit_set_contid(task, contid);
> +	put_task_struct(task);
> +	if (rv < 0)
> +		return rv;
> +	return count;
> +}
> +
> +static const struct file_operations proc_contid_operations = {
> +	.write		= proc_contid_write,
> +	.llseek		= generic_file_llseek,
> +};
>  #endif
>  
>  #ifdef CONFIG_FAULT_INJECTION
> @@ -3005,6 +3039,7 @@ static int proc_stack_depth(struct seq_file *m, struct pid_namespace *ns,
>  #ifdef CONFIG_AUDIT
>  	REG("loginuid",   S_IWUSR|S_IRUGO, proc_loginuid_operations),
>  	REG("sessionid",  S_IRUGO, proc_sessionid_operations),
> +	REG("audit_containerid", S_IWUSR, proc_contid_operations),
>  #endif
>  #ifdef CONFIG_FAULT_INJECTION
>  	REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations),
> @@ -3393,6 +3428,7 @@ static int proc_tid_comm_permission(struct inode *inode, int mask)
>  #ifdef CONFIG_AUDIT
>  	REG("loginuid",  S_IWUSR|S_IRUGO, proc_loginuid_operations),
>  	REG("sessionid",  S_IRUGO, proc_sessionid_operations),
> +	REG("audit_containerid", S_IWUSR, proc_contid_operations),
>  #endif
>  #ifdef CONFIG_FAULT_INJECTION
>  	REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations),
> diff --git a/include/linux/audit.h b/include/linux/audit.h
> index bde346e73f0c..301337776193 100644
> --- a/include/linux/audit.h
> +++ b/include/linux/audit.h
> @@ -89,6 +89,7 @@ struct audit_field {
>  struct audit_task_info {
>  	kuid_t			loginuid;
>  	unsigned int		sessionid;
> +	u64			contid;
>  #ifdef CONFIG_AUDITSYSCALL
>  	struct audit_context	*ctx;
>  #endif
> @@ -189,6 +190,15 @@ static inline unsigned int audit_get_sessionid(struct task_struct *tsk)
>  	return tsk->audit->sessionid;
>  }
>  
> +extern int audit_set_contid(struct task_struct *tsk, u64 contid);
> +
> +static inline u64 audit_get_contid(struct task_struct *tsk)
> +{
> +	if (!tsk->audit)
> +		return AUDIT_CID_UNSET;
> +	return tsk->audit->contid;
> +}
> +
>  extern u32 audit_enabled;
>  #else /* CONFIG_AUDIT */
>  static inline int audit_alloc(struct task_struct *task)
> @@ -250,6 +260,11 @@ static inline unsigned int audit_get_sessionid(struct task_struct *tsk)
>  	return AUDIT_SID_UNSET;
>  }
>  
> +static inline u64 audit_get_contid(struct task_struct *tsk)
> +{
> +	return AUDIT_CID_UNSET;
> +}
> +
>  #define audit_enabled AUDIT_OFF
>  #endif /* CONFIG_AUDIT */
>  
> @@ -606,6 +621,16 @@ static inline bool audit_loginuid_set(struct task_struct *tsk)
>  	return uid_valid(audit_get_loginuid(tsk));
>  }
>  
> +static inline bool audit_contid_valid(u64 contid)
> +{
> +	return contid != AUDIT_CID_UNSET;
> +}
> +
> +static inline bool audit_contid_set(struct task_struct *tsk)
> +{
> +	return audit_contid_valid(audit_get_contid(tsk));
> +}
> +
>  static inline void audit_log_string(struct audit_buffer *ab, const char *buf)
>  {
>  	audit_log_n_string(ab, buf, strlen(buf));
> diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h
> index 36a7e3f18e69..d475cf3b4d7f 100644
> --- a/include/uapi/linux/audit.h
> +++ b/include/uapi/linux/audit.h
> @@ -71,6 +71,7 @@
>  #define AUDIT_TTY_SET		1017	/* Set TTY auditing status */
>  #define AUDIT_SET_FEATURE	1018	/* Turn an audit feature on or off */
>  #define AUDIT_GET_FEATURE	1019	/* Get which features are enabled */
> +#define AUDIT_CONTAINER_OP	1020	/* Define the container id and information */
>  
>  #define AUDIT_FIRST_USER_MSG	1100	/* Userspace messages mostly uninteresting to kernel */
>  #define AUDIT_USER_AVC		1107	/* We filter this differently */
> @@ -471,6 +472,7 @@ struct audit_tty_status {
>  
>  #define AUDIT_UID_UNSET (unsigned int)-1
>  #define AUDIT_SID_UNSET ((unsigned int)-1)
> +#define AUDIT_CID_UNSET ((u64)-1)
>  
>  /* audit_rule_data supports filter rules with both integer and string
>   * fields.  It corresponds with AUDIT_ADD_RULE, AUDIT_DEL_RULE and
> diff --git a/kernel/audit.c b/kernel/audit.c
> index 67498c5690bb..b5c702abeb42 100644
> --- a/kernel/audit.c
> +++ b/kernel/audit.c
> @@ -244,6 +244,7 @@ int audit_alloc(struct task_struct *tsk)
>  	}
>  	info->loginuid = audit_get_loginuid(current);
>  	info->sessionid = audit_get_sessionid(current);
> +	info->contid = audit_get_contid(current);
>  	tsk->audit = info;
>  
>  	ret = audit_alloc_syscall(tsk);
> @@ -258,6 +259,7 @@ int audit_alloc(struct task_struct *tsk)
>  struct audit_task_info init_struct_audit = {
>  	.loginuid = INVALID_UID,
>  	.sessionid = AUDIT_SID_UNSET,
> +	.contid = AUDIT_CID_UNSET,
>  #ifdef CONFIG_AUDITSYSCALL
>  	.ctx = NULL,
>  #endif
> @@ -2341,6 +2343,72 @@ int audit_set_loginuid(kuid_t loginuid)
>  }
>  
>  /**
> + * audit_set_contid - set current task's audit contid
> + * @contid: contid value
> + *
> + * Returns 0 on success, -EPERM on permission failure.
> + *
> + * Called (set) from fs/proc/base.c::proc_contid_write().
> + */
> +int audit_set_contid(struct task_struct *task, u64 contid)
> +{
> +	u64 oldcontid;
> +	int rc = 0;
> +	struct audit_buffer *ab;
> +	uid_t uid;
> +	struct tty_struct *tty;
> +	char comm[sizeof(current->comm)];
> +
> +	task_lock(task);
> +	/* Can't set if audit disabled */
> +	if (!task->audit) {
> +		task_unlock(task);
> +		return -ENOPROTOOPT;
> +	}
> +	oldcontid = audit_get_contid(task);
> +	read_lock(&tasklist_lock);
> +	/* Don't allow the audit containerid to be unset */
> +	if (!audit_contid_valid(contid))
> +		rc = -EINVAL;
> +	/* if we don't have caps, reject */
> +	else if (!capable(CAP_AUDIT_CONTROL))
> +		rc = -EPERM;
> +	/* if task has children or is not single-threaded, deny */
> +	else if (!list_empty(&task->children))
> +		rc = -EBUSY;
> +	else if (!(thread_group_leader(task) && thread_group_empty(task)))
> +		rc = -EALREADY;
> +	read_unlock(&tasklist_lock);
> +	if (!rc)
> +		task->audit->contid = contid;
> +	task_unlock(task);
> +
> +	if (!audit_enabled)
> +		return rc;
> +
> +	ab = audit_log_start(audit_context(), GFP_KERNEL, AUDIT_CONTAINER_OP);
> +	if (!ab)
> +		return rc;
> +
> +	uid = from_kuid(&init_user_ns, task_uid(current));
> +	tty = audit_get_tty();
> +	audit_log_format(ab, "op=set opid=%d old-contid=%llu contid=%llu pid=%d uid=%u auid=%u tty=%s ses=%u",
> +			 task_tgid_nr(task), oldcontid, contid,
> +			 task_tgid_nr(current), 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, " res=%d", !rc);
> +	audit_log_end(ab);
> +	return rc;
> +}
> +
> +/**
>   * audit_log_end - end one audit record
>   * @ab: the audit_buffer
>   *
> -- 
> 1.8.3.1
> 
> 
Acked-by: Neil Horman <nhorman@tuxdriver.com>

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH ghak90 V5 04/10] audit: log container info of syscalls
  2019-03-15 18:29 ` [PATCH ghak90 V5 04/10] audit: log container info of syscalls Richard Guy Briggs
@ 2019-03-16 22:44   ` Neil Horman
  2019-03-27 21:01   ` Ondrej Mosnacek
  1 sibling, 0 replies; 64+ messages in thread
From: Neil Horman @ 2019-03-16 22:44 UTC (permalink / raw)
  To: Richard Guy Briggs
  Cc: containers, linux-api, Linux-Audit Mailing List, linux-fsdevel,
	LKML, netdev, netfilter-devel, Paul Moore, sgrubb, omosnace,
	dhowells, simo, eparis, serge, ebiederm

On Fri, Mar 15, 2019 at 02:29:52PM -0400, Richard Guy Briggs wrote:
> Create a new audit record AUDIT_CONTAINER_ID to document the audit
> container identifier of a process if it is present.
> 
> Called from audit_log_exit(), syscalls are covered.
> 
> A sample raw event:
> type=SYSCALL msg=audit(1519924845.499:257): arch=c000003e syscall=257 success=yes exit=3 a0=ffffff9c a1=56374e1cef30 a2=241 a3=1b6 items=2 ppid=606 pid=635 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts0 ses=3 comm="bash" exe="/usr/bin/bash" subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 key="tmpcontainerid"
> type=CWD msg=audit(1519924845.499:257): cwd="/root"
> type=PATH msg=audit(1519924845.499:257): item=0 name="/tmp/" inode=13863 dev=00:27 mode=041777 ouid=0 ogid=0 rdev=00:00 obj=system_u:object_r:tmp_t:s0 nametype= PARENT cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0
> type=PATH msg=audit(1519924845.499:257): item=1 name="/tmp/tmpcontainerid" inode=17729 dev=00:27 mode=0100644 ouid=0 ogid=0 rdev=00:00 obj=unconfined_u:object_r:user_tmp_t:s0 nametype=CREATE cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0
> type=PROCTITLE msg=audit(1519924845.499:257): proctitle=62617368002D6300736C65657020313B206563686F2074657374203E202F746D702F746D70636F6E7461696E65726964
> type=CONTAINER_ID msg=audit(1519924845.499:257): contid=123458
> 
> See: https://github.com/linux-audit/audit-kernel/issues/90
> See: https://github.com/linux-audit/audit-userspace/issues/51
> See: https://github.com/linux-audit/audit-testsuite/issues/64
> See: https://github.com/linux-audit/audit-kernel/wiki/RFE-Audit-Container-ID
> Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> Acked-by: Serge Hallyn <serge@hallyn.com>
> Acked-by: Steve Grubb <sgrubb@redhat.com>
> Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> ---
>  include/linux/audit.h      |  5 +++++
>  include/uapi/linux/audit.h |  1 +
>  kernel/audit.c             | 21 +++++++++++++++++++++
>  kernel/auditsc.c           |  2 ++
>  4 files changed, 29 insertions(+)
> 
> diff --git a/include/linux/audit.h b/include/linux/audit.h
> index 301337776193..43438192ca2a 100644
> --- a/include/linux/audit.h
> +++ b/include/linux/audit.h
> @@ -199,6 +199,8 @@ static inline u64 audit_get_contid(struct task_struct *tsk)
>  	return tsk->audit->contid;
>  }
>  
> +extern void audit_log_contid(struct audit_context *context, u64 contid);
> +
>  extern u32 audit_enabled;
>  #else /* CONFIG_AUDIT */
>  static inline int audit_alloc(struct task_struct *task)
> @@ -265,6 +267,9 @@ static inline u64 audit_get_contid(struct task_struct *tsk)
>  	return AUDIT_CID_UNSET;
>  }
>  
> +static inline void audit_log_contid(struct audit_context *context, u64 contid)
> +{ }
> +
>  #define audit_enabled AUDIT_OFF
>  #endif /* CONFIG_AUDIT */
>  
> diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h
> index d475cf3b4d7f..a6383e28b2c8 100644
> --- a/include/uapi/linux/audit.h
> +++ b/include/uapi/linux/audit.h
> @@ -115,6 +115,7 @@
>  #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_CONTAINER_ID	1332	/* Container ID */
>  
>  #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 b5c702abeb42..8cc0e88d7f2a 100644
> --- a/kernel/audit.c
> +++ b/kernel/audit.c
> @@ -2127,6 +2127,27 @@ void audit_log_session_info(struct audit_buffer *ab)
>  	audit_log_format(ab, "auid=%u ses=%u", auid, sessionid);
>  }
>  
> +/*
> + * audit_log_contid - report container info
> + * @context: task or local context for record
> + * @contid: container ID to report
> + */
> +void audit_log_contid(struct audit_context *context, u64 contid)
> +{
> +	struct audit_buffer *ab;
> +
> +	if (!audit_contid_valid(contid))
> +		return;
> +	/* Generate AUDIT_CONTAINER_ID record with container ID */
> +	ab = audit_log_start(context, GFP_KERNEL, AUDIT_CONTAINER_ID);
> +	if (!ab)
> +		return;
> +	audit_log_format(ab, "contid=%llu", contid);
> +	audit_log_end(ab);
> +	return;
> +}
> +EXPORT_SYMBOL(audit_log_contid);
> +
>  void audit_log_key(struct audit_buffer *ab, char *key)
>  {
>  	audit_log_format(ab, " key=");
> diff --git a/kernel/auditsc.c b/kernel/auditsc.c
> index 8090eff7868d..a8c8b44b954d 100644
> --- a/kernel/auditsc.c
> +++ b/kernel/auditsc.c
> @@ -1548,6 +1548,8 @@ static void audit_log_exit(void)
>  
>  	audit_log_proctitle();
>  
> +	audit_log_contid(context, audit_get_contid(current));
> +
>  	/* Send end of event record to help user space know we are finished */
>  	ab = audit_log_start(context, GFP_KERNEL, AUDIT_EOE);
>  	if (ab)
> -- 
> 1.8.3.1
> 
> 
Acked-by: Neil Horman <nhorman@tuxdriver.com>


^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH ghak90 V5 03/10] audit: read container ID of a process
  2019-03-15 18:29 ` [PATCH ghak90 V5 03/10] audit: read container ID of a process Richard Guy Briggs
@ 2019-03-18 11:10   ` Neil Horman
  2019-03-18 18:17     ` Richard Guy Briggs
  2019-03-27 20:44   ` Ondrej Mosnacek
  1 sibling, 1 reply; 64+ messages in thread
From: Neil Horman @ 2019-03-18 11:10 UTC (permalink / raw)
  To: Richard Guy Briggs
  Cc: containers, linux-api, Linux-Audit Mailing List, linux-fsdevel,
	LKML, netdev, netfilter-devel, Paul Moore, sgrubb, omosnace,
	dhowells, simo, eparis, serge, ebiederm

On Fri, Mar 15, 2019 at 02:29:51PM -0400, Richard Guy Briggs wrote:
> Add support for reading the audit container identifier from the proc
> filesystem.
> 
> This is a read from the proc entry of the form
> /proc/PID/audit_containerid where PID is the process ID of the task
> whose audit container identifier is sought.
> 
> The read expects up to a u64 value (unset: 18446744073709551615).
> 
> This read requires CAP_AUDIT_CONTROL.
> 
> Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> Acked-by: Serge Hallyn <serge@hallyn.com>
> ---
>  fs/proc/base.c | 23 +++++++++++++++++++++--
>  1 file changed, 21 insertions(+), 2 deletions(-)
> 
> diff --git a/fs/proc/base.c b/fs/proc/base.c
> index 2505c46c8701..0b833cbdf5b6 100644
> --- a/fs/proc/base.c
> +++ b/fs/proc/base.c
> @@ -1295,6 +1295,24 @@ static ssize_t proc_sessionid_read(struct file * file, char __user * buf,
>  	.llseek		= generic_file_llseek,
>  };
>  
> +static ssize_t proc_contid_read(struct file *file, char __user *buf,
> +				  size_t count, loff_t *ppos)
> +{
> +	struct inode *inode = file_inode(file);
> +	struct task_struct *task = get_proc_task(inode);
> +	ssize_t length;
> +	char tmpbuf[TMPBUFLEN*2];
> +
Sorry, didn't notice this previously, but..
Why *2 here?  Its not wrong per-se, but would it be better to just change
TMPBUFLEN to be 22 bytes unilaterally?  Its only ever used on stack calls that
arent that deep, and then you won't have to think about adjusting this call site
if you ever change the value of TMPBUFLEN in the future.

I'm fine with doing this in another patch later, but it seems like a worthwhile
cleanup

functionality looks good beyond that nit.

> +	if (!task)
> +		return -ESRCH;
> +	/* if we don't have caps, reject */
> +	if (!capable(CAP_AUDIT_CONTROL))
> +		return -EPERM;
> +	length = scnprintf(tmpbuf, TMPBUFLEN*2, "%llu", audit_get_contid(task));
> +	put_task_struct(task);
> +	return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
> +}
> +
>  static ssize_t proc_contid_write(struct file *file, const char __user *buf,
>  				   size_t count, loff_t *ppos)
>  {
> @@ -1325,6 +1343,7 @@ static ssize_t proc_contid_write(struct file *file, const char __user *buf,
>  }
>  
>  static const struct file_operations proc_contid_operations = {
> +	.read		= proc_contid_read,
>  	.write		= proc_contid_write,
>  	.llseek		= generic_file_llseek,
>  };
> @@ -3039,7 +3058,7 @@ static int proc_stack_depth(struct seq_file *m, struct pid_namespace *ns,
>  #ifdef CONFIG_AUDIT
>  	REG("loginuid",   S_IWUSR|S_IRUGO, proc_loginuid_operations),
>  	REG("sessionid",  S_IRUGO, proc_sessionid_operations),
> -	REG("audit_containerid", S_IWUSR, proc_contid_operations),
> +	REG("audit_containerid", S_IWUSR|S_IRUSR, proc_contid_operations),
>  #endif
>  #ifdef CONFIG_FAULT_INJECTION
>  	REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations),
> @@ -3428,7 +3447,7 @@ static int proc_tid_comm_permission(struct inode *inode, int mask)
>  #ifdef CONFIG_AUDIT
>  	REG("loginuid",  S_IWUSR|S_IRUGO, proc_loginuid_operations),
>  	REG("sessionid",  S_IRUGO, proc_sessionid_operations),
> -	REG("audit_containerid", S_IWUSR, proc_contid_operations),
> +	REG("audit_containerid", S_IWUSR|S_IRUSR, proc_contid_operations),
>  #endif
>  #ifdef CONFIG_FAULT_INJECTION
>  	REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations),
> -- 
> 1.8.3.1
> 
> 
Acked-by: Neil Horman <nhorman@tuxdriver.com>


^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH ghak90 V5 03/10] audit: read container ID of a process
  2019-03-18 11:10   ` Neil Horman
@ 2019-03-18 18:17     ` Richard Guy Briggs
  2019-03-18 18:48       ` Neil Horman
  0 siblings, 1 reply; 64+ messages in thread
From: Richard Guy Briggs @ 2019-03-18 18:17 UTC (permalink / raw)
  To: Neil Horman
  Cc: containers, linux-api, Linux-Audit Mailing List, linux-fsdevel,
	LKML, netdev, netfilter-devel, Paul Moore, sgrubb, omosnace,
	dhowells, simo, eparis, serge, ebiederm

On 2019-03-18 07:10, Neil Horman wrote:
> On Fri, Mar 15, 2019 at 02:29:51PM -0400, Richard Guy Briggs wrote:
> > Add support for reading the audit container identifier from the proc
> > filesystem.
> > 
> > This is a read from the proc entry of the form
> > /proc/PID/audit_containerid where PID is the process ID of the task
> > whose audit container identifier is sought.
> > 
> > The read expects up to a u64 value (unset: 18446744073709551615).
> > 
> > This read requires CAP_AUDIT_CONTROL.
> > 
> > Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> > Acked-by: Serge Hallyn <serge@hallyn.com>
> > ---
> >  fs/proc/base.c | 23 +++++++++++++++++++++--
> >  1 file changed, 21 insertions(+), 2 deletions(-)
> > 
> > diff --git a/fs/proc/base.c b/fs/proc/base.c
> > index 2505c46c8701..0b833cbdf5b6 100644
> > --- a/fs/proc/base.c
> > +++ b/fs/proc/base.c
> > @@ -1295,6 +1295,24 @@ static ssize_t proc_sessionid_read(struct file * file, char __user * buf,
> >  	.llseek		= generic_file_llseek,
> >  };
> >  
> > +static ssize_t proc_contid_read(struct file *file, char __user *buf,
> > +				  size_t count, loff_t *ppos)
> > +{
> > +	struct inode *inode = file_inode(file);
> > +	struct task_struct *task = get_proc_task(inode);
> > +	ssize_t length;
> > +	char tmpbuf[TMPBUFLEN*2];
> > +
> Sorry, didn't notice this previously, but..
> Why *2 here?  Its not wrong per-se, but would it be better to just change
> TMPBUFLEN to be 22 bytes unilaterally?  Its only ever used on stack calls that
> arent that deep, and then you won't have to think about adjusting this call site
> if you ever change the value of TMPBUFLEN in the future.

TMPBUFLEN is 11 to accomodate a decimal representation of a u32 with
terminating NULL.  Since the contid is a u64, it was least disruptive
and made sense to me to just double it.  I could define a TMPBUFLEN2 to
be 21 if you prefer?

> I'm fine with doing this in another patch later, but it seems like a worthwhile
> cleanup
> 
> functionality looks good beyond that nit.
> 
> > +	if (!task)
> > +		return -ESRCH;
> > +	/* if we don't have caps, reject */
> > +	if (!capable(CAP_AUDIT_CONTROL))
> > +		return -EPERM;
> > +	length = scnprintf(tmpbuf, TMPBUFLEN*2, "%llu", audit_get_contid(task));
> > +	put_task_struct(task);
> > +	return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
> > +}
> > +
> >  static ssize_t proc_contid_write(struct file *file, const char __user *buf,
> >  				   size_t count, loff_t *ppos)
> >  {
> > @@ -1325,6 +1343,7 @@ static ssize_t proc_contid_write(struct file *file, const char __user *buf,
> >  }
> >  
> >  static const struct file_operations proc_contid_operations = {
> > +	.read		= proc_contid_read,
> >  	.write		= proc_contid_write,
> >  	.llseek		= generic_file_llseek,
> >  };
> > @@ -3039,7 +3058,7 @@ static int proc_stack_depth(struct seq_file *m, struct pid_namespace *ns,
> >  #ifdef CONFIG_AUDIT
> >  	REG("loginuid",   S_IWUSR|S_IRUGO, proc_loginuid_operations),
> >  	REG("sessionid",  S_IRUGO, proc_sessionid_operations),
> > -	REG("audit_containerid", S_IWUSR, proc_contid_operations),
> > +	REG("audit_containerid", S_IWUSR|S_IRUSR, proc_contid_operations),
> >  #endif
> >  #ifdef CONFIG_FAULT_INJECTION
> >  	REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations),
> > @@ -3428,7 +3447,7 @@ static int proc_tid_comm_permission(struct inode *inode, int mask)
> >  #ifdef CONFIG_AUDIT
> >  	REG("loginuid",  S_IWUSR|S_IRUGO, proc_loginuid_operations),
> >  	REG("sessionid",  S_IRUGO, proc_sessionid_operations),
> > -	REG("audit_containerid", S_IWUSR, proc_contid_operations),
> > +	REG("audit_containerid", S_IWUSR|S_IRUSR, proc_contid_operations),
> >  #endif
> >  #ifdef CONFIG_FAULT_INJECTION
> >  	REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations),
> > -- 
> > 1.8.3.1
> > 
> > 
> Acked-by: Neil Horman <nhorman@tuxdriver.com>
> 

- RGB

--
Richard Guy Briggs <rgb@redhat.com>
Sr. S/W Engineer, Kernel Security, Base Operating Systems
Remote, Ottawa, Red Hat Canada
IRC: rgb, SunRaycer
Voice: +1.647.777.2635, Internal: (81) 32635

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH ghak90 V5 03/10] audit: read container ID of a process
  2019-03-18 18:17     ` Richard Guy Briggs
@ 2019-03-18 18:48       ` Neil Horman
  2019-03-18 18:54         ` Richard Guy Briggs
  0 siblings, 1 reply; 64+ messages in thread
From: Neil Horman @ 2019-03-18 18:48 UTC (permalink / raw)
  To: Richard Guy Briggs
  Cc: containers, linux-api, Linux-Audit Mailing List, linux-fsdevel,
	LKML, netdev, netfilter-devel, Paul Moore, sgrubb, omosnace,
	dhowells, simo, eparis, serge, ebiederm

On Mon, Mar 18, 2019 at 02:17:21PM -0400, Richard Guy Briggs wrote:
> On 2019-03-18 07:10, Neil Horman wrote:
> > On Fri, Mar 15, 2019 at 02:29:51PM -0400, Richard Guy Briggs wrote:
> > > Add support for reading the audit container identifier from the proc
> > > filesystem.
> > > 
> > > This is a read from the proc entry of the form
> > > /proc/PID/audit_containerid where PID is the process ID of the task
> > > whose audit container identifier is sought.
> > > 
> > > The read expects up to a u64 value (unset: 18446744073709551615).
> > > 
> > > This read requires CAP_AUDIT_CONTROL.
> > > 
> > > Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> > > Acked-by: Serge Hallyn <serge@hallyn.com>
> > > ---
> > >  fs/proc/base.c | 23 +++++++++++++++++++++--
> > >  1 file changed, 21 insertions(+), 2 deletions(-)
> > > 
> > > diff --git a/fs/proc/base.c b/fs/proc/base.c
> > > index 2505c46c8701..0b833cbdf5b6 100644
> > > --- a/fs/proc/base.c
> > > +++ b/fs/proc/base.c
> > > @@ -1295,6 +1295,24 @@ static ssize_t proc_sessionid_read(struct file * file, char __user * buf,
> > >  	.llseek		= generic_file_llseek,
> > >  };
> > >  
> > > +static ssize_t proc_contid_read(struct file *file, char __user *buf,
> > > +				  size_t count, loff_t *ppos)
> > > +{
> > > +	struct inode *inode = file_inode(file);
> > > +	struct task_struct *task = get_proc_task(inode);
> > > +	ssize_t length;
> > > +	char tmpbuf[TMPBUFLEN*2];
> > > +
> > Sorry, didn't notice this previously, but..
> > Why *2 here?  Its not wrong per-se, but would it be better to just change
> > TMPBUFLEN to be 22 bytes unilaterally?  Its only ever used on stack calls that
> > arent that deep, and then you won't have to think about adjusting this call site
> > if you ever change the value of TMPBUFLEN in the future.
> 
> TMPBUFLEN is 11 to accomodate a decimal representation of a u32 with
> terminating NULL.  Since the contid is a u64, it was least disruptive
> and made sense to me to just double it.  I could define a TMPBUFLEN2 to
> be 21 if you prefer?
> 
I'm not adamant on any particular change, just noticing the inconsistency.  I
usually write macro buffer sizes to accomodate the largest string I plan to
hold, so it can be used ubiquitously when the overage is small and transiently
allocated, but if you feel like the space would be better conserved a TMPBUFLEN/
TMPBUFLEN2 approach would be fine (or a TMPBUFLENU32 / TMPBUFLENU64 macro set).

Its not anything that needs fixing now, just an observation for clean up at some
future point.
Neil

> > I'm fine with doing this in another patch later, but it seems like a worthwhile
> > cleanup
> > 
> > functionality looks good beyond that nit.
> > 
> > > +	if (!task)
> > > +		return -ESRCH;
> > > +	/* if we don't have caps, reject */
> > > +	if (!capable(CAP_AUDIT_CONTROL))
> > > +		return -EPERM;
> > > +	length = scnprintf(tmpbuf, TMPBUFLEN*2, "%llu", audit_get_contid(task));
> > > +	put_task_struct(task);
> > > +	return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
> > > +}
> > > +
> > >  static ssize_t proc_contid_write(struct file *file, const char __user *buf,
> > >  				   size_t count, loff_t *ppos)
> > >  {
> > > @@ -1325,6 +1343,7 @@ static ssize_t proc_contid_write(struct file *file, const char __user *buf,
> > >  }
> > >  
> > >  static const struct file_operations proc_contid_operations = {
> > > +	.read		= proc_contid_read,
> > >  	.write		= proc_contid_write,
> > >  	.llseek		= generic_file_llseek,
> > >  };
> > > @@ -3039,7 +3058,7 @@ static int proc_stack_depth(struct seq_file *m, struct pid_namespace *ns,
> > >  #ifdef CONFIG_AUDIT
> > >  	REG("loginuid",   S_IWUSR|S_IRUGO, proc_loginuid_operations),
> > >  	REG("sessionid",  S_IRUGO, proc_sessionid_operations),
> > > -	REG("audit_containerid", S_IWUSR, proc_contid_operations),
> > > +	REG("audit_containerid", S_IWUSR|S_IRUSR, proc_contid_operations),
> > >  #endif
> > >  #ifdef CONFIG_FAULT_INJECTION
> > >  	REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations),
> > > @@ -3428,7 +3447,7 @@ static int proc_tid_comm_permission(struct inode *inode, int mask)
> > >  #ifdef CONFIG_AUDIT
> > >  	REG("loginuid",  S_IWUSR|S_IRUGO, proc_loginuid_operations),
> > >  	REG("sessionid",  S_IRUGO, proc_sessionid_operations),
> > > -	REG("audit_containerid", S_IWUSR, proc_contid_operations),
> > > +	REG("audit_containerid", S_IWUSR|S_IRUSR, proc_contid_operations),
> > >  #endif
> > >  #ifdef CONFIG_FAULT_INJECTION
> > >  	REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations),
> > > -- 
> > > 1.8.3.1
> > > 
> > > 
> > Acked-by: Neil Horman <nhorman@tuxdriver.com>
> > 
> 
> - RGB
> 
> --
> Richard Guy Briggs <rgb@redhat.com>
> Sr. S/W Engineer, Kernel Security, Base Operating Systems
> Remote, Ottawa, Red Hat Canada
> IRC: rgb, SunRaycer
> Voice: +1.647.777.2635, Internal: (81) 32635
> 

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH ghak90 V5 03/10] audit: read container ID of a process
  2019-03-18 18:48       ` Neil Horman
@ 2019-03-18 18:54         ` Richard Guy Briggs
  0 siblings, 0 replies; 64+ messages in thread
From: Richard Guy Briggs @ 2019-03-18 18:54 UTC (permalink / raw)
  To: Neil Horman
  Cc: containers, linux-api, Linux-Audit Mailing List, linux-fsdevel,
	LKML, netdev, netfilter-devel, Paul Moore, sgrubb, omosnace,
	dhowells, simo, eparis, serge, ebiederm

On 2019-03-18 14:48, Neil Horman wrote:
> On Mon, Mar 18, 2019 at 02:17:21PM -0400, Richard Guy Briggs wrote:
> > On 2019-03-18 07:10, Neil Horman wrote:
> > > On Fri, Mar 15, 2019 at 02:29:51PM -0400, Richard Guy Briggs wrote:
> > > > Add support for reading the audit container identifier from the proc
> > > > filesystem.
> > > > 
> > > > This is a read from the proc entry of the form
> > > > /proc/PID/audit_containerid where PID is the process ID of the task
> > > > whose audit container identifier is sought.
> > > > 
> > > > The read expects up to a u64 value (unset: 18446744073709551615).
> > > > 
> > > > This read requires CAP_AUDIT_CONTROL.
> > > > 
> > > > Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> > > > Acked-by: Serge Hallyn <serge@hallyn.com>
> > > > ---
> > > >  fs/proc/base.c | 23 +++++++++++++++++++++--
> > > >  1 file changed, 21 insertions(+), 2 deletions(-)
> > > > 
> > > > diff --git a/fs/proc/base.c b/fs/proc/base.c
> > > > index 2505c46c8701..0b833cbdf5b6 100644
> > > > --- a/fs/proc/base.c
> > > > +++ b/fs/proc/base.c
> > > > @@ -1295,6 +1295,24 @@ static ssize_t proc_sessionid_read(struct file * file, char __user * buf,
> > > >  	.llseek		= generic_file_llseek,
> > > >  };
> > > >  
> > > > +static ssize_t proc_contid_read(struct file *file, char __user *buf,
> > > > +				  size_t count, loff_t *ppos)
> > > > +{
> > > > +	struct inode *inode = file_inode(file);
> > > > +	struct task_struct *task = get_proc_task(inode);
> > > > +	ssize_t length;
> > > > +	char tmpbuf[TMPBUFLEN*2];
> > > > +
> > > Sorry, didn't notice this previously, but..
> > > Why *2 here?  Its not wrong per-se, but would it be better to just change
> > > TMPBUFLEN to be 22 bytes unilaterally?  Its only ever used on stack calls that
> > > arent that deep, and then you won't have to think about adjusting this call site
> > > if you ever change the value of TMPBUFLEN in the future.
> > 
> > TMPBUFLEN is 11 to accomodate a decimal representation of a u32 with
> > terminating NULL.  Since the contid is a u64, it was least disruptive
> > and made sense to me to just double it.  I could define a TMPBUFLEN2 to
> > be 21 if you prefer?
> > 
> I'm not adamant on any particular change, just noticing the inconsistency.  I
> usually write macro buffer sizes to accomodate the largest string I plan to
> hold, so it can be used ubiquitously when the overage is small and transiently
> allocated, but if you feel like the space would be better conserved a TMPBUFLEN/
> TMPBUFLEN2 approach would be fine (or a TMPBUFLENU32 / TMPBUFLENU64 macro set).

Ok, I see your point about it being transient.  I'll fix it up if there
is a respin.

> Its not anything that needs fixing now, just an observation for clean up at some
> future point.
> Neil
> 
> > > I'm fine with doing this in another patch later, but it seems like a worthwhile
> > > cleanup
> > > 
> > > functionality looks good beyond that nit.
> > > 
> > > > +	if (!task)
> > > > +		return -ESRCH;
> > > > +	/* if we don't have caps, reject */
> > > > +	if (!capable(CAP_AUDIT_CONTROL))
> > > > +		return -EPERM;
> > > > +	length = scnprintf(tmpbuf, TMPBUFLEN*2, "%llu", audit_get_contid(task));
> > > > +	put_task_struct(task);
> > > > +	return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
> > > > +}
> > > > +
> > > >  static ssize_t proc_contid_write(struct file *file, const char __user *buf,
> > > >  				   size_t count, loff_t *ppos)
> > > >  {
> > > > @@ -1325,6 +1343,7 @@ static ssize_t proc_contid_write(struct file *file, const char __user *buf,
> > > >  }
> > > >  
> > > >  static const struct file_operations proc_contid_operations = {
> > > > +	.read		= proc_contid_read,
> > > >  	.write		= proc_contid_write,
> > > >  	.llseek		= generic_file_llseek,
> > > >  };
> > > > @@ -3039,7 +3058,7 @@ static int proc_stack_depth(struct seq_file *m, struct pid_namespace *ns,
> > > >  #ifdef CONFIG_AUDIT
> > > >  	REG("loginuid",   S_IWUSR|S_IRUGO, proc_loginuid_operations),
> > > >  	REG("sessionid",  S_IRUGO, proc_sessionid_operations),
> > > > -	REG("audit_containerid", S_IWUSR, proc_contid_operations),
> > > > +	REG("audit_containerid", S_IWUSR|S_IRUSR, proc_contid_operations),
> > > >  #endif
> > > >  #ifdef CONFIG_FAULT_INJECTION
> > > >  	REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations),
> > > > @@ -3428,7 +3447,7 @@ static int proc_tid_comm_permission(struct inode *inode, int mask)
> > > >  #ifdef CONFIG_AUDIT
> > > >  	REG("loginuid",  S_IWUSR|S_IRUGO, proc_loginuid_operations),
> > > >  	REG("sessionid",  S_IRUGO, proc_sessionid_operations),
> > > > -	REG("audit_containerid", S_IWUSR, proc_contid_operations),
> > > > +	REG("audit_containerid", S_IWUSR|S_IRUSR, proc_contid_operations),
> > > >  #endif
> > > >  #ifdef CONFIG_FAULT_INJECTION
> > > >  	REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations),
> > > > -- 
> > > > 1.8.3.1
> > > > 
> > > Acked-by: Neil Horman <nhorman@tuxdriver.com>
> > 
> > - RGB

- RGB

--
Richard Guy Briggs <rgb@redhat.com>
Sr. S/W Engineer, Kernel Security, Base Operating Systems
Remote, Ottawa, Red Hat Canada
IRC: rgb, SunRaycer
Voice: +1.647.777.2635, Internal: (81) 32635

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH ghak90 V5 05/10] audit: add containerid support for ptrace and signals
  2019-03-15 18:29 ` [PATCH ghak90 V5 05/10] audit: add containerid support for ptrace and signals Richard Guy Briggs
@ 2019-03-18 19:04   ` Neil Horman
  2019-03-18 19:29     ` Richard Guy Briggs
  2019-03-27 21:17   ` Ondrej Mosnacek
  1 sibling, 1 reply; 64+ messages in thread
From: Neil Horman @ 2019-03-18 19:04 UTC (permalink / raw)
  To: Richard Guy Briggs
  Cc: containers, linux-api, Linux-Audit Mailing List, linux-fsdevel,
	LKML, netdev, netfilter-devel, Paul Moore, sgrubb, omosnace,
	dhowells, simo, eparis, serge, ebiederm

On Fri, Mar 15, 2019 at 02:29:53PM -0400, Richard Guy Briggs wrote:
> Add audit container identifier support to ptrace and signals.  In
> particular, the "ref" field provides a way to label the auxiliary record
> to which it is associated.
> 
> Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> Acked-by: Serge Hallyn <serge@hallyn.com>
> Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> ---
>  include/linux/audit.h |  1 +
>  kernel/audit.c        |  2 ++
>  kernel/audit.h        |  2 ++
>  kernel/auditsc.c      | 23 +++++++++++++++++------
>  4 files changed, 22 insertions(+), 6 deletions(-)
> 
> diff --git a/include/linux/audit.h b/include/linux/audit.h
> index 43438192ca2a..ebd6625ca80e 100644
> --- a/include/linux/audit.h
> +++ b/include/linux/audit.h
> @@ -35,6 +35,7 @@ struct audit_sig_info {
>  	uid_t		uid;
>  	pid_t		pid;
>  	char		ctx[0];
> +	u64		cid;
>  };
Sorry, just noticed this.  How does this work?  Given that ctx[] is a variable
length array, one assumes that the receiver of this message (userspace
applications by the looks of it, presume that the ctx data occupies the skb from
the byte following pid to the end of the transmitted buffer.  How are they to
know that the last byte is actually the cid value?  Wouldn't it be better to
move cid above ctx[0], so that the semantics of the variable length data are
preserved?

Or am I missing something?

otherwise this looks ok to me.
Neil

>  
>  struct audit_buffer;
> diff --git a/kernel/audit.c b/kernel/audit.c
> index 8cc0e88d7f2a..cfa659b3f6c4 100644
> --- a/kernel/audit.c
> +++ b/kernel/audit.c
> @@ -138,6 +138,7 @@ struct audit_net {
>  kuid_t		audit_sig_uid = INVALID_UID;
>  pid_t		audit_sig_pid = -1;
>  u32		audit_sig_sid = 0;
> +u64		audit_sig_cid = AUDIT_CID_UNSET;
>  
>  /* Records can be lost in several ways:
>     0) [suppressed in audit_alloc]
> @@ -1515,6 +1516,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
>  			memcpy(sig_data->ctx, ctx, len);
>  			security_release_secctx(ctx, len);
>  		}
> +		sig_data->cid = audit_sig_cid;
>  		audit_send_reply(skb, seq, AUDIT_SIGNAL_INFO, 0, 0,
>  				 sig_data, sizeof(*sig_data) + len);
>  		kfree(sig_data);
> diff --git a/kernel/audit.h b/kernel/audit.h
> index c00e2ee3c6b3..c5ac6436317e 100644
> --- a/kernel/audit.h
> +++ b/kernel/audit.h
> @@ -148,6 +148,7 @@ struct audit_context {
>  	kuid_t		    target_uid;
>  	unsigned int	    target_sessionid;
>  	u32		    target_sid;
> +	u64		    target_cid;
>  	char		    target_comm[TASK_COMM_LEN];
>  
>  	struct audit_tree_refs *trees, *first_trees;
> @@ -344,6 +345,7 @@ extern void audit_filter_inodes(struct task_struct *tsk,
>  extern pid_t audit_sig_pid;
>  extern kuid_t audit_sig_uid;
>  extern u32 audit_sig_sid;
> +extern u64 audit_sig_cid;
>  
>  extern int audit_filter(int msgtype, unsigned int listtype);
>  
> diff --git a/kernel/auditsc.c b/kernel/auditsc.c
> index a8c8b44b954d..f04e115df5dc 100644
> --- a/kernel/auditsc.c
> +++ b/kernel/auditsc.c
> @@ -113,6 +113,7 @@ struct audit_aux_data_pids {
>  	kuid_t			target_uid[AUDIT_AUX_PIDS];
>  	unsigned int		target_sessionid[AUDIT_AUX_PIDS];
>  	u32			target_sid[AUDIT_AUX_PIDS];
> +	u64			target_cid[AUDIT_AUX_PIDS];
>  	char 			target_comm[AUDIT_AUX_PIDS][TASK_COMM_LEN];
>  	int			pid_count;
>  };
> @@ -1514,7 +1515,7 @@ static void audit_log_exit(void)
>  	for (aux = context->aux_pids; aux; aux = aux->next) {
>  		struct audit_aux_data_pids *axs = (void *)aux;
>  
> -		for (i = 0; i < axs->pid_count; i++)
> +		for (i = 0; i < axs->pid_count; i++) {
>  			if (audit_log_pid_context(context, axs->target_pid[i],
>  						  axs->target_auid[i],
>  						  axs->target_uid[i],
> @@ -1522,14 +1523,20 @@ static void audit_log_exit(void)
>  						  axs->target_sid[i],
>  						  axs->target_comm[i]))
>  				call_panic = 1;
> +			audit_log_contid(context, axs->target_cid[i]);
> +		}
>  	}
>  
> -	if (context->target_pid &&
> -	    audit_log_pid_context(context, context->target_pid,
> -				  context->target_auid, context->target_uid,
> -				  context->target_sessionid,
> -				  context->target_sid, context->target_comm))
> +	if (context->target_pid) {
> +		if (audit_log_pid_context(context, context->target_pid,
> +					  context->target_auid,
> +					  context->target_uid,
> +					  context->target_sessionid,
> +					  context->target_sid,
> +					  context->target_comm))
>  			call_panic = 1;
> +		audit_log_contid(context, context->target_cid);
> +	}
>  
>  	if (context->pwd.dentry && context->pwd.mnt) {
>  		ab = audit_log_start(context, GFP_KERNEL, AUDIT_CWD);
> @@ -2360,6 +2367,7 @@ void __audit_ptrace(struct task_struct *t)
>  	context->target_uid = task_uid(t);
>  	context->target_sessionid = audit_get_sessionid(t);
>  	security_task_getsecid(t, &context->target_sid);
> +	context->target_cid = audit_get_contid(t);
>  	memcpy(context->target_comm, t->comm, TASK_COMM_LEN);
>  }
>  
> @@ -2387,6 +2395,7 @@ int audit_signal_info(int sig, struct task_struct *t)
>  		else
>  			audit_sig_uid = uid;
>  		security_task_getsecid(current, &audit_sig_sid);
> +		audit_sig_cid = audit_get_contid(current);
>  	}
>  
>  	if (!audit_signals || audit_dummy_context())
> @@ -2400,6 +2409,7 @@ int audit_signal_info(int sig, struct task_struct *t)
>  		ctx->target_uid = t_uid;
>  		ctx->target_sessionid = audit_get_sessionid(t);
>  		security_task_getsecid(t, &ctx->target_sid);
> +		ctx->target_cid = audit_get_contid(t);
>  		memcpy(ctx->target_comm, t->comm, TASK_COMM_LEN);
>  		return 0;
>  	}
> @@ -2421,6 +2431,7 @@ int audit_signal_info(int sig, struct task_struct *t)
>  	axp->target_uid[axp->pid_count] = t_uid;
>  	axp->target_sessionid[axp->pid_count] = audit_get_sessionid(t);
>  	security_task_getsecid(t, &axp->target_sid[axp->pid_count]);
> +	axp->target_cid[axp->pid_count] = audit_get_contid(t);
>  	memcpy(axp->target_comm[axp->pid_count], t->comm, TASK_COMM_LEN);
>  	axp->pid_count++;
>  
> -- 
> 1.8.3.1
> 
> 

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH ghak90 V5 05/10] audit: add containerid support for ptrace and signals
  2019-03-18 19:04   ` Neil Horman
@ 2019-03-18 19:29     ` Richard Guy Briggs
  0 siblings, 0 replies; 64+ messages in thread
From: Richard Guy Briggs @ 2019-03-18 19:29 UTC (permalink / raw)
  To: Neil Horman
  Cc: containers, linux-api, Linux-Audit Mailing List, linux-fsdevel,
	LKML, netdev, netfilter-devel, Paul Moore, sgrubb, omosnace,
	dhowells, simo, eparis, serge, ebiederm

On 2019-03-18 15:04, Neil Horman wrote:
> On Fri, Mar 15, 2019 at 02:29:53PM -0400, Richard Guy Briggs wrote:
> > Add audit container identifier support to ptrace and signals.  In
> > particular, the "ref" field provides a way to label the auxiliary record
> > to which it is associated.
> > 
> > Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> > Acked-by: Serge Hallyn <serge@hallyn.com>
> > Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> > ---
> >  include/linux/audit.h |  1 +
> >  kernel/audit.c        |  2 ++
> >  kernel/audit.h        |  2 ++
> >  kernel/auditsc.c      | 23 +++++++++++++++++------
> >  4 files changed, 22 insertions(+), 6 deletions(-)
> > 
> > diff --git a/include/linux/audit.h b/include/linux/audit.h
> > index 43438192ca2a..ebd6625ca80e 100644
> > --- a/include/linux/audit.h
> > +++ b/include/linux/audit.h
> > @@ -35,6 +35,7 @@ struct audit_sig_info {
> >  	uid_t		uid;
> >  	pid_t		pid;
> >  	char		ctx[0];
> > +	u64		cid;
> >  };
> Sorry, just noticed this.  How does this work?  Given that ctx[] is a variable
> length array, one assumes that the receiver of this message (userspace
> applications by the looks of it, presume that the ctx data occupies the skb from
> the byte following pid to the end of the transmitted buffer.  How are they to
> know that the last byte is actually the cid value?  Wouldn't it be better to
> move cid above ctx[0], so that the semantics of the variable length data are
> preserved?
> 
> Or am I missing something?

Nope you're not missing anything, but I am!  That's a bug.  Thanks for
spotting that!

> otherwise this looks ok to me.
> Neil
> 
> >  
> >  struct audit_buffer;
> > diff --git a/kernel/audit.c b/kernel/audit.c
> > index 8cc0e88d7f2a..cfa659b3f6c4 100644
> > --- a/kernel/audit.c
> > +++ b/kernel/audit.c
> > @@ -138,6 +138,7 @@ struct audit_net {
> >  kuid_t		audit_sig_uid = INVALID_UID;
> >  pid_t		audit_sig_pid = -1;
> >  u32		audit_sig_sid = 0;
> > +u64		audit_sig_cid = AUDIT_CID_UNSET;
> >  
> >  /* Records can be lost in several ways:
> >     0) [suppressed in audit_alloc]
> > @@ -1515,6 +1516,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
> >  			memcpy(sig_data->ctx, ctx, len);
> >  			security_release_secctx(ctx, len);
> >  		}
> > +		sig_data->cid = audit_sig_cid;
> >  		audit_send_reply(skb, seq, AUDIT_SIGNAL_INFO, 0, 0,
> >  				 sig_data, sizeof(*sig_data) + len);
> >  		kfree(sig_data);
> > diff --git a/kernel/audit.h b/kernel/audit.h
> > index c00e2ee3c6b3..c5ac6436317e 100644
> > --- a/kernel/audit.h
> > +++ b/kernel/audit.h
> > @@ -148,6 +148,7 @@ struct audit_context {
> >  	kuid_t		    target_uid;
> >  	unsigned int	    target_sessionid;
> >  	u32		    target_sid;
> > +	u64		    target_cid;
> >  	char		    target_comm[TASK_COMM_LEN];
> >  
> >  	struct audit_tree_refs *trees, *first_trees;
> > @@ -344,6 +345,7 @@ extern void audit_filter_inodes(struct task_struct *tsk,
> >  extern pid_t audit_sig_pid;
> >  extern kuid_t audit_sig_uid;
> >  extern u32 audit_sig_sid;
> > +extern u64 audit_sig_cid;
> >  
> >  extern int audit_filter(int msgtype, unsigned int listtype);
> >  
> > diff --git a/kernel/auditsc.c b/kernel/auditsc.c
> > index a8c8b44b954d..f04e115df5dc 100644
> > --- a/kernel/auditsc.c
> > +++ b/kernel/auditsc.c
> > @@ -113,6 +113,7 @@ struct audit_aux_data_pids {
> >  	kuid_t			target_uid[AUDIT_AUX_PIDS];
> >  	unsigned int		target_sessionid[AUDIT_AUX_PIDS];
> >  	u32			target_sid[AUDIT_AUX_PIDS];
> > +	u64			target_cid[AUDIT_AUX_PIDS];
> >  	char 			target_comm[AUDIT_AUX_PIDS][TASK_COMM_LEN];
> >  	int			pid_count;
> >  };
> > @@ -1514,7 +1515,7 @@ static void audit_log_exit(void)
> >  	for (aux = context->aux_pids; aux; aux = aux->next) {
> >  		struct audit_aux_data_pids *axs = (void *)aux;
> >  
> > -		for (i = 0; i < axs->pid_count; i++)
> > +		for (i = 0; i < axs->pid_count; i++) {
> >  			if (audit_log_pid_context(context, axs->target_pid[i],
> >  						  axs->target_auid[i],
> >  						  axs->target_uid[i],
> > @@ -1522,14 +1523,20 @@ static void audit_log_exit(void)
> >  						  axs->target_sid[i],
> >  						  axs->target_comm[i]))
> >  				call_panic = 1;
> > +			audit_log_contid(context, axs->target_cid[i]);
> > +		}
> >  	}
> >  
> > -	if (context->target_pid &&
> > -	    audit_log_pid_context(context, context->target_pid,
> > -				  context->target_auid, context->target_uid,
> > -				  context->target_sessionid,
> > -				  context->target_sid, context->target_comm))
> > +	if (context->target_pid) {
> > +		if (audit_log_pid_context(context, context->target_pid,
> > +					  context->target_auid,
> > +					  context->target_uid,
> > +					  context->target_sessionid,
> > +					  context->target_sid,
> > +					  context->target_comm))
> >  			call_panic = 1;
> > +		audit_log_contid(context, context->target_cid);
> > +	}
> >  
> >  	if (context->pwd.dentry && context->pwd.mnt) {
> >  		ab = audit_log_start(context, GFP_KERNEL, AUDIT_CWD);
> > @@ -2360,6 +2367,7 @@ void __audit_ptrace(struct task_struct *t)
> >  	context->target_uid = task_uid(t);
> >  	context->target_sessionid = audit_get_sessionid(t);
> >  	security_task_getsecid(t, &context->target_sid);
> > +	context->target_cid = audit_get_contid(t);
> >  	memcpy(context->target_comm, t->comm, TASK_COMM_LEN);
> >  }
> >  
> > @@ -2387,6 +2395,7 @@ int audit_signal_info(int sig, struct task_struct *t)
> >  		else
> >  			audit_sig_uid = uid;
> >  		security_task_getsecid(current, &audit_sig_sid);
> > +		audit_sig_cid = audit_get_contid(current);
> >  	}
> >  
> >  	if (!audit_signals || audit_dummy_context())
> > @@ -2400,6 +2409,7 @@ int audit_signal_info(int sig, struct task_struct *t)
> >  		ctx->target_uid = t_uid;
> >  		ctx->target_sessionid = audit_get_sessionid(t);
> >  		security_task_getsecid(t, &ctx->target_sid);
> > +		ctx->target_cid = audit_get_contid(t);
> >  		memcpy(ctx->target_comm, t->comm, TASK_COMM_LEN);
> >  		return 0;
> >  	}
> > @@ -2421,6 +2431,7 @@ int audit_signal_info(int sig, struct task_struct *t)
> >  	axp->target_uid[axp->pid_count] = t_uid;
> >  	axp->target_sessionid[axp->pid_count] = audit_get_sessionid(t);
> >  	security_task_getsecid(t, &axp->target_sid[axp->pid_count]);
> > +	axp->target_cid[axp->pid_count] = audit_get_contid(t);
> >  	memcpy(axp->target_comm[axp->pid_count], t->comm, TASK_COMM_LEN);
> >  	axp->pid_count++;
> >  
> > -- 
> > 1.8.3.1
> > 
> > 

- RGB

--
Richard Guy Briggs <rgb@redhat.com>
Sr. S/W Engineer, Kernel Security, Base Operating Systems
Remote, Ottawa, Red Hat Canada
IRC: rgb, SunRaycer
Voice: +1.647.777.2635, Internal: (81) 32635

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH ghak90 V5 06/10] audit: add support for non-syscall auxiliary records
  2019-03-15 18:29 ` [PATCH ghak90 V5 06/10] audit: add support for non-syscall auxiliary records Richard Guy Briggs
@ 2019-03-18 19:34   ` Neil Horman
  2019-03-27 21:22   ` Ondrej Mosnacek
  2019-04-01 14:49   ` Paul Moore
  2 siblings, 0 replies; 64+ messages in thread
From: Neil Horman @ 2019-03-18 19:34 UTC (permalink / raw)
  To: Richard Guy Briggs
  Cc: containers, linux-api, Linux-Audit Mailing List, linux-fsdevel,
	LKML, netdev, netfilter-devel, Paul Moore, sgrubb, omosnace,
	dhowells, simo, eparis, serge, ebiederm

On Fri, Mar 15, 2019 at 02:29:54PM -0400, Richard Guy Briggs wrote:
> Standalone audit records have the timestamp and serial number generated
> on the fly and as such are unique, making them standalone.  This new
> function audit_alloc_local() generates a local audit context that will
> be used only for a standalone record and its auxiliary record(s).  The
> context is discarded immediately after the local associated records are
> produced.
> 
> Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> Acked-by: Serge Hallyn <serge@hallyn.com>
> ---
>  include/linux/audit.h |  8 ++++++++
>  kernel/audit.h        |  1 +
>  kernel/auditsc.c      | 35 ++++++++++++++++++++++++++++++-----
>  3 files changed, 39 insertions(+), 5 deletions(-)
> 
> diff --git a/include/linux/audit.h b/include/linux/audit.h
> index ebd6625ca80e..6db5aba7cc01 100644
> --- a/include/linux/audit.h
> +++ b/include/linux/audit.h
> @@ -285,6 +285,8 @@ static inline void audit_log_contid(struct audit_context *context, u64 contid)
>  
>  /* These are defined in auditsc.c */
>  				/* Public API */
> +extern struct audit_context *audit_alloc_local(gfp_t gfpflags);
> +extern void audit_free_context(struct audit_context *context);
>  extern void __audit_syscall_entry(int major, unsigned long a0, unsigned long a1,
>  				  unsigned long a2, unsigned long a3);
>  extern void __audit_syscall_exit(int ret_success, long ret_value);
> @@ -512,6 +514,12 @@ static inline void audit_fanotify(unsigned int response)
>  extern int audit_n_rules;
>  extern int audit_signals;
>  #else /* CONFIG_AUDITSYSCALL */
> +static inline struct audit_context *audit_alloc_local(gfp_t gfpflags)
> +{
> +	return NULL;
> +}
> +static inline void audit_free_context(struct audit_context *context)
> +{ }
>  static inline void audit_syscall_entry(int major, unsigned long a0,
>  				       unsigned long a1, unsigned long a2,
>  				       unsigned long a3)
> diff --git a/kernel/audit.h b/kernel/audit.h
> index c5ac6436317e..2a1a8b8a8019 100644
> --- a/kernel/audit.h
> +++ b/kernel/audit.h
> @@ -111,6 +111,7 @@ struct audit_proctitle {
>  struct audit_context {
>  	int		    dummy;	/* must be the first element */
>  	int		    in_syscall;	/* 1 if task is in a syscall */
> +	bool		    local;	/* local context needed */
>  	enum audit_state    state, current_state;
>  	unsigned int	    serial;     /* serial number for record */
>  	int		    major;      /* syscall number */
> diff --git a/kernel/auditsc.c b/kernel/auditsc.c
> index f04e115df5dc..aa5d13b4fbbb 100644
> --- a/kernel/auditsc.c
> +++ b/kernel/auditsc.c
> @@ -872,11 +872,13 @@ static inline void audit_free_aux(struct audit_context *context)
>  	}
>  }
>  
> -static inline struct audit_context *audit_alloc_context(enum audit_state state)
> +static inline struct audit_context *audit_alloc_context(enum audit_state state,
> +							gfp_t gfpflags)
>  {
>  	struct audit_context *context;
>  
> -	context = kzalloc(sizeof(*context), GFP_KERNEL);
> +	/* We can be called in atomic context via audit_tg() */
> +	context = kzalloc(sizeof(*context), gfpflags);
>  	if (!context)
>  		return NULL;
>  	context->state = state;
> @@ -912,7 +914,8 @@ int audit_alloc_syscall(struct task_struct *tsk)
>  		return 0;
>  	}
>  
> -	if (!(context = audit_alloc_context(state))) {
> +	context = audit_alloc_context(state, GFP_KERNEL);
> +	if (!context) {
>  		kfree(key);
>  		audit_log_lost("out of memory in audit_alloc_syscall");
>  		return -ENOMEM;
> @@ -924,8 +927,29 @@ int audit_alloc_syscall(struct task_struct *tsk)
>  	return 0;
>  }
>  
> -static inline void audit_free_context(struct audit_context *context)
> +struct audit_context *audit_alloc_local(gfp_t gfpflags)
>  {
> +	struct audit_context *context = NULL;
> +
> +	if (!audit_ever_enabled)
> +		goto out; /* Return if not auditing. */
> +	context = audit_alloc_context(AUDIT_RECORD_CONTEXT, gfpflags);
> +	if (!context) {
> +		audit_log_lost("out of memory in audit_alloc_local");
> +		goto out;
> +	}
> +	context->serial = audit_serial();
> +	ktime_get_coarse_real_ts64(&context->ctime);
> +	context->local = true;
> +out:
> +	return context;
> +}
> +EXPORT_SYMBOL(audit_alloc_local);
> +
> +void audit_free_context(struct audit_context *context)
> +{
> +	if (!context)
> +		return;
>  	audit_free_names(context);
>  	unroll_tree_refs(context, NULL, 0);
>  	free_tree_refs(context);
> @@ -935,6 +959,7 @@ static inline void audit_free_context(struct audit_context *context)
>  	audit_proctitle_free(context);
>  	kfree(context);
>  }
> +EXPORT_SYMBOL(audit_free_context);
>  
>  static int audit_log_pid_context(struct audit_context *context, pid_t pid,
>  				 kuid_t auid, kuid_t uid, unsigned int sessionid,
> @@ -2163,7 +2188,7 @@ void __audit_inode_child(struct inode *parent,
>  int auditsc_get_stamp(struct audit_context *ctx,
>  		       struct timespec64 *t, unsigned int *serial)
>  {
> -	if (!ctx->in_syscall)
> +	if (!ctx->in_syscall && !ctx->local)
>  		return 0;
>  	if (!ctx->serial)
>  		ctx->serial = audit_serial();
> -- 
> 1.8.3.1
> 
> 
Acked-by: Neil Horman <nhorman@tuxdriver.com>

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH ghak90 V5 07/10] audit: add containerid support for user records
  2019-03-15 18:29 ` [PATCH ghak90 V5 07/10] audit: add containerid support for user records Richard Guy Briggs
@ 2019-03-18 19:41   ` Neil Horman
  2019-03-27 21:30   ` Ondrej Mosnacek
  1 sibling, 0 replies; 64+ messages in thread
From: Neil Horman @ 2019-03-18 19:41 UTC (permalink / raw)
  To: Richard Guy Briggs
  Cc: containers, linux-api, Linux-Audit Mailing List, linux-fsdevel,
	LKML, netdev, netfilter-devel, Paul Moore, sgrubb, omosnace,
	dhowells, simo, eparis, serge, ebiederm

On Fri, Mar 15, 2019 at 02:29:55PM -0400, Richard Guy Briggs wrote:
> Add audit container identifier auxiliary record to user event standalone
> records.
> 
> Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> ---
>  kernel/audit.c | 13 ++++++-------
>  1 file changed, 6 insertions(+), 7 deletions(-)
> 
> diff --git a/kernel/audit.c b/kernel/audit.c
> index cfa659b3f6c4..cf448599ef34 100644
> --- a/kernel/audit.c
> +++ b/kernel/audit.c
> @@ -1142,12 +1142,6 @@ static void audit_log_common_recv_msg(struct audit_context *context,
>  	audit_log_task_context(*ab);
>  }
>  
> -static inline void audit_log_user_recv_msg(struct audit_buffer **ab,
> -					   u16 msg_type)
> -{
> -	audit_log_common_recv_msg(NULL, ab, msg_type);
> -}
> -
>  int is_audit_feature_set(int i)
>  {
>  	return af.features & AUDIT_FEATURE_TO_MASK(i);
> @@ -1409,13 +1403,16 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
>  
>  		err = audit_filter(msg_type, AUDIT_FILTER_USER);
>  		if (err == 1) { /* match or error */
> +			struct audit_context *context;
> +
>  			err = 0;
>  			if (msg_type == AUDIT_USER_TTY) {
>  				err = tty_audit_push();
>  				if (err)
>  					break;
>  			}
> -			audit_log_user_recv_msg(&ab, msg_type);
> +			context = audit_alloc_local(GFP_KERNEL);
> +			audit_log_common_recv_msg(context, &ab, msg_type);
>  			if (msg_type != AUDIT_USER_TTY)
>  				audit_log_format(ab, " msg='%.*s'",
>  						 AUDIT_MESSAGE_TEXT_MAX,
> @@ -1431,6 +1428,8 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
>  				audit_log_n_untrustedstring(ab, data, size);
>  			}
>  			audit_log_end(ab);
> +			audit_log_contid(context, audit_get_contid(current));
> +			audit_free_context(context);
>  		}
>  		break;
>  	case AUDIT_ADD_RULE:
> -- 
> 1.8.3.1
> 
> 
Acked-by: Neil Horman <nhorman@tuxdriver.com>


^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH ghak90 V5 08/10] audit: add containerid filtering
  2019-03-15 18:29 ` [PATCH ghak90 V5 08/10] audit: add containerid filtering Richard Guy Briggs
@ 2019-03-18 20:02   ` Ondrej Mosnacek
  2019-03-18 23:47     ` Richard Guy Briggs
  2019-03-18 20:39   ` Neil Horman
  1 sibling, 1 reply; 64+ messages in thread
From: Ondrej Mosnacek @ 2019-03-18 20:02 UTC (permalink / raw)
  To: Richard Guy Briggs
  Cc: containers, linux-api, Linux-Audit Mailing List, linux-fsdevel,
	LKML, netdev, netfilter-devel, Paul Moore, Steve Grubb,
	David Howells, simo, Eric Paris, Serge E. Hallyn,
	Eric W . Biederman, nhorman

On Fri, Mar 15, 2019 at 7:35 PM Richard Guy Briggs <rgb@redhat.com> wrote:
>
> Implement audit container identifier filtering using the AUDIT_CONTID
> field name to send an 8-character string representing a u64 since the
> value field is only u32.
>
> Sending it as two u32 was considered, but gathering and comparing two
> fields was more complex.
>
> The feature indicator is AUDIT_FEATURE_BITMAP_CONTAINERID.
>
> See: https://github.com/linux-audit/audit-kernel/issues/91
> 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
> Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> Acked-by: Serge Hallyn <serge@hallyn.com>
> ---
>  include/linux/audit.h      |  1 +
>  include/uapi/linux/audit.h |  5 ++++-
>  kernel/audit.h             |  1 +
>  kernel/auditfilter.c       | 47 ++++++++++++++++++++++++++++++++++++++++++++++
>  kernel/auditsc.c           |  3 +++
>  5 files changed, 56 insertions(+), 1 deletion(-)
>
> diff --git a/include/linux/audit.h b/include/linux/audit.h
> index 6db5aba7cc01..fa19fa408931 100644
> --- a/include/linux/audit.h
> +++ b/include/linux/audit.h
> @@ -77,6 +77,7 @@ struct audit_field {
>         u32                             type;
>         union {
>                 u32                     val;
> +               u64                     val64;
>                 kuid_t                  uid;
>                 kgid_t                  gid;
>                 struct {
> diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h
> index a6383e28b2c8..741ab6f38294 100644
> --- a/include/uapi/linux/audit.h
> +++ b/include/uapi/linux/audit.h
> @@ -265,6 +265,7 @@
>  #define AUDIT_LOGINUID_SET     24
>  #define AUDIT_SESSIONID        25      /* Session ID */
>  #define AUDIT_FSTYPE   26      /* FileSystem Type */
> +#define AUDIT_CONTID   27      /* Container ID */
>
>                                 /* These are ONLY useful when checking
>                                  * at syscall exit time (AUDIT_AT_EXIT). */
> @@ -345,6 +346,7 @@ enum {
>  #define AUDIT_FEATURE_BITMAP_SESSIONID_FILTER  0x00000010
>  #define AUDIT_FEATURE_BITMAP_LOST_RESET                0x00000020
>  #define AUDIT_FEATURE_BITMAP_FILTER_FS         0x00000040
> +#define AUDIT_FEATURE_BITMAP_CONTAINERID       0x00000080
>
>  #define AUDIT_FEATURE_BITMAP_ALL (AUDIT_FEATURE_BITMAP_BACKLOG_LIMIT | \
>                                   AUDIT_FEATURE_BITMAP_BACKLOG_WAIT_TIME | \
> @@ -352,7 +354,8 @@ enum {
>                                   AUDIT_FEATURE_BITMAP_EXCLUDE_EXTEND | \
>                                   AUDIT_FEATURE_BITMAP_SESSIONID_FILTER | \
>                                   AUDIT_FEATURE_BITMAP_LOST_RESET | \
> -                                 AUDIT_FEATURE_BITMAP_FILTER_FS)
> +                                 AUDIT_FEATURE_BITMAP_FILTER_FS | \
> +                                 AUDIT_FEATURE_BITMAP_CONTAINERID)
>
>  /* deprecated: AUDIT_VERSION_* */
>  #define AUDIT_VERSION_LATEST           AUDIT_FEATURE_BITMAP_ALL
> diff --git a/kernel/audit.h b/kernel/audit.h
> index 2a1a8b8a8019..3a40b608bf8d 100644
> --- a/kernel/audit.h
> +++ b/kernel/audit.h
> @@ -230,6 +230,7 @@ static inline int audit_hash_ino(u32 ino)
>
>  extern int audit_match_class(int class, unsigned syscall);
>  extern int audit_comparator(const u32 left, const u32 op, const u32 right);
> +extern int audit_comparator64(const u64 left, const u32 op, const u64 right);
>  extern int audit_uid_comparator(kuid_t left, u32 op, kuid_t right);
>  extern int audit_gid_comparator(kgid_t left, u32 op, kgid_t right);
>  extern int parent_len(const char *path);
> diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
> index add360b46b38..516b8e58959e 100644
> --- a/kernel/auditfilter.c
> +++ b/kernel/auditfilter.c
> @@ -410,6 +410,7 @@ static int audit_field_valid(struct audit_entry *entry, struct audit_field *f)
>         /* FALL THROUGH */
>         case AUDIT_ARCH:
>         case AUDIT_FSTYPE:
> +       case AUDIT_CONTID:
>                 if (f->op != Audit_not_equal && f->op != Audit_equal)
>                         return -EINVAL;
>                 break;
> @@ -582,6 +583,14 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
>                         }
>                         entry->rule.exe = audit_mark;
>                         break;
> +               case AUDIT_CONTID:
> +                       if (f->val != sizeof(u64))
> +                               goto exit_free;
> +                       str = audit_unpack_string(&bufp, &remain, f->val);
> +                       if (IS_ERR(str))
> +                               goto exit_free;
> +                       f->val64 = ((u64 *)str)[0];
> +                       break;
>                 }
>         }
>
> @@ -664,6 +673,11 @@ static struct audit_rule_data *audit_krule_to_data(struct audit_krule *krule)
>                         data->buflen += data->values[i] =
>                                 audit_pack_string(&bufp, audit_mark_path(krule->exe));
>                         break;
> +               case AUDIT_CONTID:
> +                       data->buflen += data->values[i] = sizeof(u64);
> +                       for (i = 0; i < sizeof(u64); i++)
> +                               ((char *)bufp)[i] = ((char *)&f->val64)[i];

How about just:

memcpy(bufp, &f->val64, sizeof(u64));

instead of the awkward for loop? It is simpler and also more in line
with the code in audit_pack_string().

Also, doesn't this loop interfere with the outer loop that also uses
'i' as the control variable?

> +                       break;
>                 case AUDIT_LOGINUID_SET:
>                         if (krule->pflags & AUDIT_LOGINUID_LEGACY && !f->val) {
>                                 data->fields[i] = AUDIT_LOGINUID;
> @@ -750,6 +764,10 @@ static int audit_compare_rule(struct audit_krule *a, struct audit_krule *b)
>                         if (!gid_eq(a->fields[i].gid, b->fields[i].gid))
>                                 return 1;
>                         break;
> +               case AUDIT_CONTID:
> +                       if (a->fields[i].val64 != b->fields[i].val64)
> +                               return 1;
> +                       break;
>                 default:
>                         if (a->fields[i].val != b->fields[i].val)
>                                 return 1;
> @@ -1206,6 +1224,31 @@ int audit_comparator(u32 left, u32 op, u32 right)
>         }
>  }
>
> +int audit_comparator64(u64 left, u32 op, u64 right)
> +{
> +       switch (op) {
> +       case Audit_equal:
> +               return (left == right);
> +       case Audit_not_equal:
> +               return (left != right);
> +       case Audit_lt:
> +               return (left < right);
> +       case Audit_le:
> +               return (left <= right);
> +       case Audit_gt:
> +               return (left > right);
> +       case Audit_ge:
> +               return (left >= right);
> +       case Audit_bitmask:
> +               return (left & right);
> +       case Audit_bittest:
> +               return ((left & right) == right);
> +       default:
> +               BUG();
> +               return 0;
> +       }
> +}
> +
>  int audit_uid_comparator(kuid_t left, u32 op, kuid_t right)
>  {
>         switch (op) {
> @@ -1344,6 +1387,10 @@ int audit_filter(int msgtype, unsigned int listtype)
>                                 result = audit_comparator(audit_loginuid_set(current),
>                                                           f->op, f->val);
>                                 break;
> +                       case AUDIT_CONTID:
> +                               result = audit_comparator64(audit_get_contid(current),
> +                                                             f->op, f->val64);
> +                               break;
>                         case AUDIT_MSGTYPE:
>                                 result = audit_comparator(msgtype, f->op, f->val);
>                                 break;
> diff --git a/kernel/auditsc.c b/kernel/auditsc.c
> index aa5d13b4fbbb..2d74238e9638 100644
> --- a/kernel/auditsc.c
> +++ b/kernel/auditsc.c
> @@ -616,6 +616,9 @@ static int audit_filter_rules(struct task_struct *tsk,
>                 case AUDIT_LOGINUID_SET:
>                         result = audit_comparator(audit_loginuid_set(tsk), f->op, f->val);
>                         break;
> +               case AUDIT_CONTID:
> +                       result = audit_comparator64(audit_get_contid(tsk), f->op, f->val64);
> +                       break;
>                 case AUDIT_SUBJ_USER:
>                 case AUDIT_SUBJ_ROLE:
>                 case AUDIT_SUBJ_TYPE:
> --
> 1.8.3.1
>


-- 
Ondrej Mosnacek <omosnace at redhat dot com>
Associate Software Engineer, Security Technologies
Red Hat, Inc.

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH ghak90 V5 08/10] audit: add containerid filtering
  2019-03-15 18:29 ` [PATCH ghak90 V5 08/10] audit: add containerid filtering Richard Guy Briggs
  2019-03-18 20:02   ` Ondrej Mosnacek
@ 2019-03-18 20:39   ` Neil Horman
  1 sibling, 0 replies; 64+ messages in thread
From: Neil Horman @ 2019-03-18 20:39 UTC (permalink / raw)
  To: Richard Guy Briggs
  Cc: containers, linux-api, Linux-Audit Mailing List, linux-fsdevel,
	LKML, netdev, netfilter-devel, Paul Moore, sgrubb, omosnace,
	dhowells, simo, eparis, serge, ebiederm

On Fri, Mar 15, 2019 at 02:29:56PM -0400, Richard Guy Briggs wrote:
> Implement audit container identifier filtering using the AUDIT_CONTID
> field name to send an 8-character string representing a u64 since the
> value field is only u32.
> 
> Sending it as two u32 was considered, but gathering and comparing two
> fields was more complex.
> 
> The feature indicator is AUDIT_FEATURE_BITMAP_CONTAINERID.
> 
> See: https://github.com/linux-audit/audit-kernel/issues/91
> 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
> Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> Acked-by: Serge Hallyn <serge@hallyn.com>
> ---
>  include/linux/audit.h      |  1 +
>  include/uapi/linux/audit.h |  5 ++++-
>  kernel/audit.h             |  1 +
>  kernel/auditfilter.c       | 47 ++++++++++++++++++++++++++++++++++++++++++++++
>  kernel/auditsc.c           |  3 +++
>  5 files changed, 56 insertions(+), 1 deletion(-)
> 
> diff --git a/include/linux/audit.h b/include/linux/audit.h
> index 6db5aba7cc01..fa19fa408931 100644
> --- a/include/linux/audit.h
> +++ b/include/linux/audit.h
> @@ -77,6 +77,7 @@ struct audit_field {
>  	u32				type;
>  	union {
>  		u32			val;
> +		u64			val64;
>  		kuid_t			uid;
>  		kgid_t			gid;
>  		struct {
> diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h
> index a6383e28b2c8..741ab6f38294 100644
> --- a/include/uapi/linux/audit.h
> +++ b/include/uapi/linux/audit.h
> @@ -265,6 +265,7 @@
>  #define AUDIT_LOGINUID_SET	24
>  #define AUDIT_SESSIONID	25	/* Session ID */
>  #define AUDIT_FSTYPE	26	/* FileSystem Type */
> +#define AUDIT_CONTID	27	/* Container ID */
>  
>  				/* These are ONLY useful when checking
>  				 * at syscall exit time (AUDIT_AT_EXIT). */
> @@ -345,6 +346,7 @@ enum {
>  #define AUDIT_FEATURE_BITMAP_SESSIONID_FILTER	0x00000010
>  #define AUDIT_FEATURE_BITMAP_LOST_RESET		0x00000020
>  #define AUDIT_FEATURE_BITMAP_FILTER_FS		0x00000040
> +#define AUDIT_FEATURE_BITMAP_CONTAINERID	0x00000080
>  
>  #define AUDIT_FEATURE_BITMAP_ALL (AUDIT_FEATURE_BITMAP_BACKLOG_LIMIT | \
>  				  AUDIT_FEATURE_BITMAP_BACKLOG_WAIT_TIME | \
> @@ -352,7 +354,8 @@ enum {
>  				  AUDIT_FEATURE_BITMAP_EXCLUDE_EXTEND | \
>  				  AUDIT_FEATURE_BITMAP_SESSIONID_FILTER | \
>  				  AUDIT_FEATURE_BITMAP_LOST_RESET | \
> -				  AUDIT_FEATURE_BITMAP_FILTER_FS)
> +				  AUDIT_FEATURE_BITMAP_FILTER_FS | \
> +				  AUDIT_FEATURE_BITMAP_CONTAINERID)
>  
>  /* deprecated: AUDIT_VERSION_* */
>  #define AUDIT_VERSION_LATEST 		AUDIT_FEATURE_BITMAP_ALL
> diff --git a/kernel/audit.h b/kernel/audit.h
> index 2a1a8b8a8019..3a40b608bf8d 100644
> --- a/kernel/audit.h
> +++ b/kernel/audit.h
> @@ -230,6 +230,7 @@ static inline int audit_hash_ino(u32 ino)
>  
>  extern int audit_match_class(int class, unsigned syscall);
>  extern int audit_comparator(const u32 left, const u32 op, const u32 right);
> +extern int audit_comparator64(const u64 left, const u32 op, const u64 right);
>  extern int audit_uid_comparator(kuid_t left, u32 op, kuid_t right);
>  extern int audit_gid_comparator(kgid_t left, u32 op, kgid_t right);
>  extern int parent_len(const char *path);
> diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
> index add360b46b38..516b8e58959e 100644
> --- a/kernel/auditfilter.c
> +++ b/kernel/auditfilter.c
> @@ -410,6 +410,7 @@ static int audit_field_valid(struct audit_entry *entry, struct audit_field *f)
>  	/* FALL THROUGH */
>  	case AUDIT_ARCH:
>  	case AUDIT_FSTYPE:
> +	case AUDIT_CONTID:
>  		if (f->op != Audit_not_equal && f->op != Audit_equal)
>  			return -EINVAL;
>  		break;
> @@ -582,6 +583,14 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
>  			}
>  			entry->rule.exe = audit_mark;
>  			break;
> +		case AUDIT_CONTID:
> +			if (f->val != sizeof(u64))
> +				goto exit_free;
> +			str = audit_unpack_string(&bufp, &remain, f->val);
> +			if (IS_ERR(str))
> +				goto exit_free;
> +			f->val64 = ((u64 *)str)[0];
> +			break;
>  		}
>  	}
>  
> @@ -664,6 +673,11 @@ static struct audit_rule_data *audit_krule_to_data(struct audit_krule *krule)
>  			data->buflen += data->values[i] =
>  				audit_pack_string(&bufp, audit_mark_path(krule->exe));
>  			break;
> +		case AUDIT_CONTID:
> +			data->buflen += data->values[i] = sizeof(u64);
> +			for (i = 0; i < sizeof(u64); i++)
> +				((char *)bufp)[i] = ((char *)&f->val64)[i];
> +			break;
>  		case AUDIT_LOGINUID_SET:
>  			if (krule->pflags & AUDIT_LOGINUID_LEGACY && !f->val) {
>  				data->fields[i] = AUDIT_LOGINUID;
> @@ -750,6 +764,10 @@ static int audit_compare_rule(struct audit_krule *a, struct audit_krule *b)
>  			if (!gid_eq(a->fields[i].gid, b->fields[i].gid))
>  				return 1;
>  			break;
> +		case AUDIT_CONTID:
> +			if (a->fields[i].val64 != b->fields[i].val64)
> +				return 1;
> +			break;
>  		default:
>  			if (a->fields[i].val != b->fields[i].val)
>  				return 1;
> @@ -1206,6 +1224,31 @@ int audit_comparator(u32 left, u32 op, u32 right)
>  	}
>  }
>  
> +int audit_comparator64(u64 left, u32 op, u64 right)
> +{
> +	switch (op) {
> +	case Audit_equal:
> +		return (left == right);
> +	case Audit_not_equal:
> +		return (left != right);
> +	case Audit_lt:
> +		return (left < right);
> +	case Audit_le:
> +		return (left <= right);
> +	case Audit_gt:
> +		return (left > right);
> +	case Audit_ge:
> +		return (left >= right);
> +	case Audit_bitmask:
> +		return (left & right);
> +	case Audit_bittest:
> +		return ((left & right) == right);
> +	default:
> +		BUG();
> +		return 0;
> +	}
> +}
> +
>  int audit_uid_comparator(kuid_t left, u32 op, kuid_t right)
>  {
>  	switch (op) {
> @@ -1344,6 +1387,10 @@ int audit_filter(int msgtype, unsigned int listtype)
>  				result = audit_comparator(audit_loginuid_set(current),
>  							  f->op, f->val);
>  				break;
> +			case AUDIT_CONTID:
> +				result = audit_comparator64(audit_get_contid(current),
> +							      f->op, f->val64);
> +				break;
>  			case AUDIT_MSGTYPE:
>  				result = audit_comparator(msgtype, f->op, f->val);
>  				break;
> diff --git a/kernel/auditsc.c b/kernel/auditsc.c
> index aa5d13b4fbbb..2d74238e9638 100644
> --- a/kernel/auditsc.c
> +++ b/kernel/auditsc.c
> @@ -616,6 +616,9 @@ static int audit_filter_rules(struct task_struct *tsk,
>  		case AUDIT_LOGINUID_SET:
>  			result = audit_comparator(audit_loginuid_set(tsk), f->op, f->val);
>  			break;
> +		case AUDIT_CONTID:
> +			result = audit_comparator64(audit_get_contid(tsk), f->op, f->val64);
> +			break;
>  		case AUDIT_SUBJ_USER:
>  		case AUDIT_SUBJ_ROLE:
>  		case AUDIT_SUBJ_TYPE:
> -- 
> 1.8.3.1
> 
> 
Acked-by: Neil Horman <nhorman@tuxdriver.com>

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH ghak90 V5 09/10] audit: add support for containerid to network namespaces
  2019-03-15 18:29 ` [PATCH ghak90 V5 09/10] audit: add support for containerid to network namespaces Richard Guy Briggs
@ 2019-03-18 20:56   ` Neil Horman
  2019-03-27 22:42   ` Ondrej Mosnacek
  2019-04-01 14:50   ` Paul Moore
  2 siblings, 0 replies; 64+ messages in thread
From: Neil Horman @ 2019-03-18 20:56 UTC (permalink / raw)
  To: Richard Guy Briggs
  Cc: containers, linux-api, Linux-Audit Mailing List, linux-fsdevel,
	LKML, netdev, netfilter-devel, Paul Moore, sgrubb, omosnace,
	dhowells, simo, eparis, serge, ebiederm

On Fri, Mar 15, 2019 at 02:29:57PM -0400, Richard Guy Briggs wrote:
> Audit events could happen in a network namespace outside of a task
> context due to packets received from the net that trigger an auditing
> rule prior to being associated with a running task.  The network
> namespace could be in use by multiple containers by association to the
> tasks in that network namespace.  We still want a way to attribute
> these events to any potential containers.  Keep a list per network
> namespace to track these audit container identifiiers.
> 
> Add/increment the audit container identifier on:
> - initial setting of the audit container identifier via /proc
> - clone/fork call that inherits an audit container identifier
> - unshare call that inherits an audit container identifier
> - setns call that inherits an audit container identifier
> Delete/decrement the audit container identifier on:
> - an inherited audit container identifier dropped when child set
> - process exit
> - unshare call that drops a net namespace
> - setns call that drops a net namespace
> 
> See: https://github.com/linux-audit/audit-kernel/issues/92
> See: https://github.com/linux-audit/audit-testsuite/issues/64
> See: https://github.com/linux-audit/audit-kernel/wiki/RFE-Audit-Container-ID
> Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> ---
>  include/linux/audit.h | 19 ++++++++++++
>  kernel/audit.c        | 86 +++++++++++++++++++++++++++++++++++++++++++++++++--
>  kernel/nsproxy.c      |  4 +++
>  3 files changed, 106 insertions(+), 3 deletions(-)
> 
> diff --git a/include/linux/audit.h b/include/linux/audit.h
> index fa19fa408931..70255c2dfb9f 100644
> --- a/include/linux/audit.h
> +++ b/include/linux/audit.h
> @@ -27,6 +27,7 @@
>  #include <linux/ptrace.h>
>  #include <linux/namei.h>  /* LOOKUP_* */
>  #include <uapi/linux/audit.h>
> +#include <linux/refcount.h>
>  
>  #define AUDIT_INO_UNSET ((unsigned long)-1)
>  #define AUDIT_DEV_UNSET ((dev_t)-1)
> @@ -99,6 +100,13 @@ struct audit_task_info {
>  
>  extern struct audit_task_info init_struct_audit;
>  
> +struct audit_contid {
> +	struct list_head	list;
> +	u64			id;
> +	refcount_t		refcount;
> +	struct rcu_head		rcu;
> +};
> +
>  extern int is_audit_feature_set(int which);
>  
>  extern int __init audit_register_class(int class, unsigned *list);
> @@ -202,6 +210,10 @@ static inline u64 audit_get_contid(struct task_struct *tsk)
>  }
>  
>  extern void audit_log_contid(struct audit_context *context, u64 contid);
> +extern void audit_netns_contid_add(struct net *net, u64 contid);
> +extern void audit_netns_contid_del(struct net *net, u64 contid);
> +extern void audit_switch_task_namespaces(struct nsproxy *ns,
> +					 struct task_struct *p);
>  
>  extern u32 audit_enabled;
>  #else /* CONFIG_AUDIT */
> @@ -271,6 +283,13 @@ static inline u64 audit_get_contid(struct task_struct *tsk)
>  
>  static inline void audit_log_contid(struct audit_context *context, u64 contid)
>  { }
> +static inline void audit_netns_contid_add(struct net *net, u64 contid)
> +{ }
> +static inline void audit_netns_contid_del(struct net *net, u64 contid)
> +{ }
> +static inline void audit_switch_task_namespaces(struct nsproxy *ns,
> +						struct task_struct *p)
> +{ }
>  
>  #define audit_enabled AUDIT_OFF
>  #endif /* CONFIG_AUDIT */
> diff --git a/kernel/audit.c b/kernel/audit.c
> index cf448599ef34..7fa3194f5342 100644
> --- a/kernel/audit.c
> +++ b/kernel/audit.c
> @@ -72,6 +72,7 @@
>  #include <linux/freezer.h>
>  #include <linux/pid_namespace.h>
>  #include <net/netns/generic.h>
> +#include <net/net_namespace.h>
>  
>  #include "audit.h"
>  
> @@ -99,9 +100,13 @@
>  /**
>   * struct audit_net - audit private network namespace data
>   * @sk: communication socket
> + * @contid_list: audit container identifier list
> + * @contid_list_lock audit container identifier list lock
>   */
>  struct audit_net {
>  	struct sock *sk;
> +	struct list_head contid_list;
> +	spinlock_t contid_list_lock;
>  };
>  
>  /**
> @@ -275,8 +280,11 @@ struct audit_task_info init_struct_audit = {
>  void audit_free(struct task_struct *tsk)
>  {
>  	struct audit_task_info *info = tsk->audit;
> +	struct nsproxy *ns = tsk->nsproxy;
>  
>  	audit_free_syscall(tsk);
> +	if (ns)
> +		audit_netns_contid_del(ns->net_ns, audit_get_contid(tsk));
>  	/* Freeing the audit_task_info struct must be performed after
>  	 * audit_log_exit() due to need for loginuid and sessionid.
>  	 */
> @@ -376,6 +384,73 @@ static struct sock *audit_get_sk(const struct net *net)
>  	return aunet->sk;
>  }
>  
> +void audit_netns_contid_add(struct net *net, u64 contid)
> +{
> +	struct audit_net *aunet = net_generic(net, audit_net_id);
> +	struct list_head *contid_list = &aunet->contid_list;
> +	struct audit_contid *cont;
> +
> +	if (!audit_contid_valid(contid))
> +		return;
> +	if (!aunet)
> +		return;
> +	spin_lock(&aunet->contid_list_lock);
> +	if (!list_empty(contid_list))
> +		list_for_each_entry_rcu(cont, contid_list, list)
> +			if (cont->id == contid) {
> +				refcount_inc(&cont->refcount);
> +				goto out;
> +			}
> +	cont = kmalloc(sizeof(struct audit_contid), GFP_ATOMIC);
> +	if (cont) {
> +		INIT_LIST_HEAD(&cont->list);
> +		cont->id = contid;
> +		refcount_set(&cont->refcount, 1);
> +		list_add_rcu(&cont->list, contid_list);
> +	}
> +out:
> +	spin_unlock(&aunet->contid_list_lock);
> +}
> +
> +void audit_netns_contid_del(struct net *net, u64 contid)
> +{
> +	struct audit_net *aunet;
> +	struct list_head *contid_list;
> +	struct audit_contid *cont = NULL;
> +
> +	if (!net)
> +		return;
> +	if (!audit_contid_valid(contid))
> +		return;
> +	aunet = net_generic(net, audit_net_id);
> +	if (!aunet)
> +		return;
> +	contid_list = &aunet->contid_list;
> +	spin_lock(&aunet->contid_list_lock);
> +	if (!list_empty(contid_list))
> +		list_for_each_entry_rcu(cont, contid_list, list)
> +			if (cont->id == contid) {
> +				if (refcount_dec_and_test(&cont->refcount)) {
> +					list_del_rcu(&cont->list);
> +					kfree_rcu(cont, rcu);
> +				}
> +				break;
> +			}
> +	spin_unlock(&aunet->contid_list_lock);
> +}
> +
> +void audit_switch_task_namespaces(struct nsproxy *ns, struct task_struct *p)
> +{
> +	u64 contid = audit_get_contid(p);
> +	struct nsproxy *new = p->nsproxy;
> +
> +	if (!audit_contid_valid(contid))
> +		return;
> +	audit_netns_contid_del(ns->net_ns, contid);
> +	if (new)
> +		audit_netns_contid_add(new->net_ns, contid);
> +}
> +
>  void audit_panic(const char *message)
>  {
>  	switch (audit_failure) {
> @@ -1619,7 +1694,6 @@ static int __net_init audit_net_init(struct net *net)
>  		.flags	= NL_CFG_F_NONROOT_RECV,
>  		.groups	= AUDIT_NLGRP_MAX,
>  	};
> -
>  	struct audit_net *aunet = net_generic(net, audit_net_id);
>  
>  	aunet->sk = netlink_kernel_create(net, NETLINK_AUDIT, &cfg);
> @@ -1628,7 +1702,8 @@ static int __net_init audit_net_init(struct net *net)
>  		return -ENOMEM;
>  	}
>  	aunet->sk->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT;
> -
> +	INIT_LIST_HEAD(&aunet->contid_list);
> +	spin_lock_init(&aunet->contid_list_lock);
>  	return 0;
>  }
>  
> @@ -2380,6 +2455,7 @@ int audit_set_contid(struct task_struct *task, u64 contid)
>  	uid_t uid;
>  	struct tty_struct *tty;
>  	char comm[sizeof(current->comm)];
> +	struct net *net = task->nsproxy->net_ns;
>  
>  	task_lock(task);
>  	/* Can't set if audit disabled */
> @@ -2401,8 +2477,12 @@ int audit_set_contid(struct task_struct *task, u64 contid)
>  	else if (!(thread_group_leader(task) && thread_group_empty(task)))
>  		rc = -EALREADY;
>  	read_unlock(&tasklist_lock);
> -	if (!rc)
> +	if (!rc) {
> +		if (audit_contid_valid(oldcontid))
> +			audit_netns_contid_del(net, oldcontid);
>  		task->audit->contid = contid;
> +		audit_netns_contid_add(net, contid);
> +	}
>  	task_unlock(task);
>  
>  	if (!audit_enabled)
> diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c
> index f6c5d330059a..718b1201ae70 100644
> --- a/kernel/nsproxy.c
> +++ b/kernel/nsproxy.c
> @@ -27,6 +27,7 @@
>  #include <linux/syscalls.h>
>  #include <linux/cgroup.h>
>  #include <linux/perf_event.h>
> +#include <linux/audit.h>
>  
>  static struct kmem_cache *nsproxy_cachep;
>  
> @@ -140,6 +141,7 @@ int copy_namespaces(unsigned long flags, struct task_struct *tsk)
>  	struct nsproxy *old_ns = tsk->nsproxy;
>  	struct user_namespace *user_ns = task_cred_xxx(tsk, user_ns);
>  	struct nsproxy *new_ns;
> +	u64 contid = audit_get_contid(tsk);
>  
>  	if (likely(!(flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC |
>  			      CLONE_NEWPID | CLONE_NEWNET |
> @@ -167,6 +169,7 @@ int copy_namespaces(unsigned long flags, struct task_struct *tsk)
>  		return  PTR_ERR(new_ns);
>  
>  	tsk->nsproxy = new_ns;
> +	audit_netns_contid_add(new_ns->net_ns, contid);
>  	return 0;
>  }
>  
> @@ -224,6 +227,7 @@ void switch_task_namespaces(struct task_struct *p, struct nsproxy *new)
>  	ns = p->nsproxy;
>  	p->nsproxy = new;
>  	task_unlock(p);
> +	audit_switch_task_namespaces(ns, p);
>  
>  	if (ns && atomic_dec_and_test(&ns->count))
>  		free_nsproxy(ns);
> -- 
> 1.8.3.1
> 
> 
Acked-by: Neil Horman <nhorman@tuxdriver.com>

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH ghak90 V5 10/10] audit: NETFILTER_PKT: record each container ID associated with a netNS
  2019-03-15 18:29 ` [PATCH ghak90 V5 10/10] audit: NETFILTER_PKT: record each container ID associated with a netNS Richard Guy Briggs
@ 2019-03-18 20:58   ` Neil Horman
  2019-03-27 22:52   ` Ondrej Mosnacek
  2019-04-01 14:50   ` Paul Moore
  2 siblings, 0 replies; 64+ messages in thread
From: Neil Horman @ 2019-03-18 20:58 UTC (permalink / raw)
  To: Richard Guy Briggs
  Cc: containers, linux-api, Linux-Audit Mailing List, linux-fsdevel,
	LKML, netdev, netfilter-devel, Paul Moore, sgrubb, omosnace,
	dhowells, simo, eparis, serge, ebiederm

On Fri, Mar 15, 2019 at 02:29:58PM -0400, Richard Guy Briggs wrote:
> Add audit container identifier auxiliary record(s) to NETFILTER_PKT
> event standalone records.  Iterate through all potential audit container
> identifiers associated with a network namespace.
> 
> Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> ---
>  include/linux/audit.h    |  5 +++++
>  kernel/audit.c           | 41 +++++++++++++++++++++++++++++++++++++++++
>  net/netfilter/nft_log.c  | 11 +++++++++--
>  net/netfilter/xt_AUDIT.c | 11 +++++++++--
>  4 files changed, 64 insertions(+), 4 deletions(-)
> 
> diff --git a/include/linux/audit.h b/include/linux/audit.h
> index 70255c2dfb9f..723e2d020228 100644
> --- a/include/linux/audit.h
> +++ b/include/linux/audit.h
> @@ -214,6 +214,8 @@ static inline u64 audit_get_contid(struct task_struct *tsk)
>  extern void audit_netns_contid_del(struct net *net, u64 contid);
>  extern void audit_switch_task_namespaces(struct nsproxy *ns,
>  					 struct task_struct *p);
> +extern void audit_log_netns_contid_list(struct net *net,
> +					struct audit_context *context);
>  
>  extern u32 audit_enabled;
>  #else /* CONFIG_AUDIT */
> @@ -290,6 +292,9 @@ static inline void audit_netns_contid_del(struct net *net, u64 contid)
>  static inline void audit_switch_task_namespaces(struct nsproxy *ns,
>  						struct task_struct *p)
>  { }
> +static inline void audit_log_netns_contid_list(struct net *net,
> +					       struct audit_context *context)
> +{ }
>  
>  #define audit_enabled AUDIT_OFF
>  #endif /* CONFIG_AUDIT */
> diff --git a/kernel/audit.c b/kernel/audit.c
> index 7fa3194f5342..80ed323feeb5 100644
> --- a/kernel/audit.c
> +++ b/kernel/audit.c
> @@ -451,6 +451,47 @@ void audit_switch_task_namespaces(struct nsproxy *ns, struct task_struct *p)
>  		audit_netns_contid_add(new->net_ns, contid);
>  }
>  
> +/**
> + * audit_log_netns_contid_list - List contids for the given network namespace
> + * @net: the network namespace of interest
> + * @context: the audit context to use
> + *
> + * Description:
> + * Issues a CONTAINER_ID record with a CSV list of contids associated
> + * with a network namespace to accompany a NETFILTER_PKT record.
> + */
> +void audit_log_netns_contid_list(struct net *net, struct audit_context *context)
> +{
> +	struct audit_buffer *ab = NULL;
> +	struct audit_contid *cont;
> +	bool first = true;
> +	struct audit_net *aunet;
> +
> +	/* Generate AUDIT_CONTAINER_ID record with container ID CSV list */
> +	rcu_read_lock();
> +	aunet = net_generic(net, audit_net_id);
> +	if (!aunet)
> +		goto out;
> +	list_for_each_entry_rcu(cont, &aunet->contid_list, list) {
> +		if (first) {
> +			ab = audit_log_start(context, GFP_ATOMIC,
> +					     AUDIT_CONTAINER_ID);
> +			if (!ab) {
> +				audit_log_lost("out of memory in audit_log_netns_contid_list");
> +				goto out;
> +			}
> +			audit_log_format(ab, "contid=");
> +		} else 
> +			audit_log_format(ab, ",");
> +		audit_log_format(ab, "%llu", cont->id);
> +		first = false;
> +	}
> +	audit_log_end(ab);
> +out:
> +	rcu_read_unlock();
> +}
> +EXPORT_SYMBOL(audit_log_netns_contid_list);
> +
>  void audit_panic(const char *message)
>  {
>  	switch (audit_failure) {
> diff --git a/net/netfilter/nft_log.c b/net/netfilter/nft_log.c
> index 655187bed5d8..bdb1ec2368a7 100644
> --- a/net/netfilter/nft_log.c
> +++ b/net/netfilter/nft_log.c
> @@ -69,13 +69,16 @@ static void nft_log_eval_audit(const struct nft_pktinfo *pkt)
>  	struct sk_buff *skb = pkt->skb;
>  	struct audit_buffer *ab;
>  	int fam = -1;
> +	struct audit_context *context;
> +	struct net *net;
>  
>  	if (!audit_enabled)
>  		return;
>  
> -	ab = audit_log_start(NULL, GFP_ATOMIC, AUDIT_NETFILTER_PKT);
> +	context = audit_alloc_local(GFP_ATOMIC);
> +	ab = audit_log_start(context, GFP_ATOMIC, AUDIT_NETFILTER_PKT);
>  	if (!ab)
> -		return;
> +		goto errout;
>  
>  	audit_log_format(ab, "mark=%#x", skb->mark);
>  
> @@ -102,6 +105,10 @@ static void nft_log_eval_audit(const struct nft_pktinfo *pkt)
>  		audit_log_format(ab, " saddr=? daddr=? proto=-1");
>  
>  	audit_log_end(ab);
> +	net = xt_net(&pkt->xt);
> +	audit_log_netns_contid_list(net, context);
> +errout:
> +	audit_free_context(context);
>  }
>  
>  static void nft_log_eval(const struct nft_expr *expr,
> diff --git a/net/netfilter/xt_AUDIT.c b/net/netfilter/xt_AUDIT.c
> index af883f1b64f9..a3e547435f13 100644
> --- a/net/netfilter/xt_AUDIT.c
> +++ b/net/netfilter/xt_AUDIT.c
> @@ -71,10 +71,13 @@ static bool audit_ip6(struct audit_buffer *ab, struct sk_buff *skb)
>  {
>  	struct audit_buffer *ab;
>  	int fam = -1;
> +	struct audit_context *context;
> +	struct net *net;
>  
>  	if (audit_enabled == AUDIT_OFF)
> -		goto errout;
> -	ab = audit_log_start(NULL, GFP_ATOMIC, AUDIT_NETFILTER_PKT);
> +		goto out;
> +	context = audit_alloc_local(GFP_ATOMIC);
> +	ab = audit_log_start(context, GFP_ATOMIC, AUDIT_NETFILTER_PKT);
>  	if (ab == NULL)
>  		goto errout;
>  
> @@ -104,7 +107,11 @@ static bool audit_ip6(struct audit_buffer *ab, struct sk_buff *skb)
>  
>  	audit_log_end(ab);
>  
> +	net = xt_net(par);
> +	audit_log_netns_contid_list(net, context);
>  errout:
> +	audit_free_context(context);
> +out:
>  	return XT_CONTINUE;
>  }
>  
> -- 
> 1.8.3.1
> 
> 
minus the whitespace fix
Acked-by: Neil Horman <nhorman@tuxdriver.com>


^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH ghak90 V5 08/10] audit: add containerid filtering
  2019-03-18 20:02   ` Ondrej Mosnacek
@ 2019-03-18 23:47     ` Richard Guy Briggs
  2019-03-27 21:41       ` Ondrej Mosnacek
  0 siblings, 1 reply; 64+ messages in thread
From: Richard Guy Briggs @ 2019-03-18 23:47 UTC (permalink / raw)
  To: Ondrej Mosnacek
  Cc: containers, linux-api, Linux-Audit Mailing List, linux-fsdevel,
	LKML, netdev, netfilter-devel, Paul Moore, Steve Grubb,
	David Howells, simo, Eric Paris, Serge E. Hallyn,
	Eric W . Biederman, nhorman

On 2019-03-18 21:02, Ondrej Mosnacek wrote:
> On Fri, Mar 15, 2019 at 7:35 PM Richard Guy Briggs <rgb@redhat.com> wrote:
> >
> > Implement audit container identifier filtering using the AUDIT_CONTID
> > field name to send an 8-character string representing a u64 since the
> > value field is only u32.
> >
> > Sending it as two u32 was considered, but gathering and comparing two
> > fields was more complex.
> >
> > The feature indicator is AUDIT_FEATURE_BITMAP_CONTAINERID.
> >
> > See: https://github.com/linux-audit/audit-kernel/issues/91
> > 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
> > Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> > Acked-by: Serge Hallyn <serge@hallyn.com>
> > ---
> >  include/linux/audit.h      |  1 +
> >  include/uapi/linux/audit.h |  5 ++++-
> >  kernel/audit.h             |  1 +
> >  kernel/auditfilter.c       | 47 ++++++++++++++++++++++++++++++++++++++++++++++
> >  kernel/auditsc.c           |  3 +++
> >  5 files changed, 56 insertions(+), 1 deletion(-)
> >
> > diff --git a/include/linux/audit.h b/include/linux/audit.h
> > index 6db5aba7cc01..fa19fa408931 100644
> > --- a/include/linux/audit.h
> > +++ b/include/linux/audit.h
> > @@ -77,6 +77,7 @@ struct audit_field {
> >         u32                             type;
> >         union {
> >                 u32                     val;
> > +               u64                     val64;
> >                 kuid_t                  uid;
> >                 kgid_t                  gid;
> >                 struct {
> > diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h
> > index a6383e28b2c8..741ab6f38294 100644
> > --- a/include/uapi/linux/audit.h
> > +++ b/include/uapi/linux/audit.h
> > @@ -265,6 +265,7 @@
> >  #define AUDIT_LOGINUID_SET     24
> >  #define AUDIT_SESSIONID        25      /* Session ID */
> >  #define AUDIT_FSTYPE   26      /* FileSystem Type */
> > +#define AUDIT_CONTID   27      /* Container ID */
> >
> >                                 /* These are ONLY useful when checking
> >                                  * at syscall exit time (AUDIT_AT_EXIT). */
> > @@ -345,6 +346,7 @@ enum {
> >  #define AUDIT_FEATURE_BITMAP_SESSIONID_FILTER  0x00000010
> >  #define AUDIT_FEATURE_BITMAP_LOST_RESET                0x00000020
> >  #define AUDIT_FEATURE_BITMAP_FILTER_FS         0x00000040
> > +#define AUDIT_FEATURE_BITMAP_CONTAINERID       0x00000080
> >
> >  #define AUDIT_FEATURE_BITMAP_ALL (AUDIT_FEATURE_BITMAP_BACKLOG_LIMIT | \
> >                                   AUDIT_FEATURE_BITMAP_BACKLOG_WAIT_TIME | \
> > @@ -352,7 +354,8 @@ enum {
> >                                   AUDIT_FEATURE_BITMAP_EXCLUDE_EXTEND | \
> >                                   AUDIT_FEATURE_BITMAP_SESSIONID_FILTER | \
> >                                   AUDIT_FEATURE_BITMAP_LOST_RESET | \
> > -                                 AUDIT_FEATURE_BITMAP_FILTER_FS)
> > +                                 AUDIT_FEATURE_BITMAP_FILTER_FS | \
> > +                                 AUDIT_FEATURE_BITMAP_CONTAINERID)
> >
> >  /* deprecated: AUDIT_VERSION_* */
> >  #define AUDIT_VERSION_LATEST           AUDIT_FEATURE_BITMAP_ALL
> > diff --git a/kernel/audit.h b/kernel/audit.h
> > index 2a1a8b8a8019..3a40b608bf8d 100644
> > --- a/kernel/audit.h
> > +++ b/kernel/audit.h
> > @@ -230,6 +230,7 @@ static inline int audit_hash_ino(u32 ino)
> >
> >  extern int audit_match_class(int class, unsigned syscall);
> >  extern int audit_comparator(const u32 left, const u32 op, const u32 right);
> > +extern int audit_comparator64(const u64 left, const u32 op, const u64 right);
> >  extern int audit_uid_comparator(kuid_t left, u32 op, kuid_t right);
> >  extern int audit_gid_comparator(kgid_t left, u32 op, kgid_t right);
> >  extern int parent_len(const char *path);
> > diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
> > index add360b46b38..516b8e58959e 100644
> > --- a/kernel/auditfilter.c
> > +++ b/kernel/auditfilter.c
> > @@ -410,6 +410,7 @@ static int audit_field_valid(struct audit_entry *entry, struct audit_field *f)
> >         /* FALL THROUGH */
> >         case AUDIT_ARCH:
> >         case AUDIT_FSTYPE:
> > +       case AUDIT_CONTID:
> >                 if (f->op != Audit_not_equal && f->op != Audit_equal)
> >                         return -EINVAL;
> >                 break;
> > @@ -582,6 +583,14 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
> >                         }
> >                         entry->rule.exe = audit_mark;
> >                         break;
> > +               case AUDIT_CONTID:
> > +                       if (f->val != sizeof(u64))
> > +                               goto exit_free;
> > +                       str = audit_unpack_string(&bufp, &remain, f->val);
> > +                       if (IS_ERR(str))
> > +                               goto exit_free;
> > +                       f->val64 = ((u64 *)str)[0];
> > +                       break;
> >                 }
> >         }
> >
> > @@ -664,6 +673,11 @@ static struct audit_rule_data *audit_krule_to_data(struct audit_krule *krule)
> >                         data->buflen += data->values[i] =
> >                                 audit_pack_string(&bufp, audit_mark_path(krule->exe));
> >                         break;
> > +               case AUDIT_CONTID:
> > +                       data->buflen += data->values[i] = sizeof(u64);
> > +                       for (i = 0; i < sizeof(u64); i++)
> > +                               ((char *)bufp)[i] = ((char *)&f->val64)[i];
> 
> How about just:
> 
> memcpy(bufp, &f->val64, sizeof(u64));
> 
> instead of the awkward for loop? It is simpler and also more in line
> with the code in audit_pack_string().

I'll grant you that.  I'll use that instead.

> Also, doesn't this loop interfere with the outer loop that also uses
> 'i' as the control variable?

Yes, it does.  Thank you for catching that.  Doing a auditctl -l reveals
this.

> > +                       break;
> >                 case AUDIT_LOGINUID_SET:
> >                         if (krule->pflags & AUDIT_LOGINUID_LEGACY && !f->val) {
> >                                 data->fields[i] = AUDIT_LOGINUID;
> > @@ -750,6 +764,10 @@ static int audit_compare_rule(struct audit_krule *a, struct audit_krule *b)
> >                         if (!gid_eq(a->fields[i].gid, b->fields[i].gid))
> >                                 return 1;
> >                         break;
> > +               case AUDIT_CONTID:
> > +                       if (a->fields[i].val64 != b->fields[i].val64)
> > +                               return 1;
> > +                       break;
> >                 default:
> >                         if (a->fields[i].val != b->fields[i].val)
> >                                 return 1;
> > @@ -1206,6 +1224,31 @@ int audit_comparator(u32 left, u32 op, u32 right)
> >         }
> >  }
> >
> > +int audit_comparator64(u64 left, u32 op, u64 right)
> > +{
> > +       switch (op) {
> > +       case Audit_equal:
> > +               return (left == right);
> > +       case Audit_not_equal:
> > +               return (left != right);
> > +       case Audit_lt:
> > +               return (left < right);
> > +       case Audit_le:
> > +               return (left <= right);
> > +       case Audit_gt:
> > +               return (left > right);
> > +       case Audit_ge:
> > +               return (left >= right);
> > +       case Audit_bitmask:
> > +               return (left & right);
> > +       case Audit_bittest:
> > +               return ((left & right) == right);
> > +       default:
> > +               BUG();
> > +               return 0;
> > +       }
> > +}
> > +
> >  int audit_uid_comparator(kuid_t left, u32 op, kuid_t right)
> >  {
> >         switch (op) {
> > @@ -1344,6 +1387,10 @@ int audit_filter(int msgtype, unsigned int listtype)
> >                                 result = audit_comparator(audit_loginuid_set(current),
> >                                                           f->op, f->val);
> >                                 break;
> > +                       case AUDIT_CONTID:
> > +                               result = audit_comparator64(audit_get_contid(current),
> > +                                                             f->op, f->val64);
> > +                               break;
> >                         case AUDIT_MSGTYPE:
> >                                 result = audit_comparator(msgtype, f->op, f->val);
> >                                 break;
> > diff --git a/kernel/auditsc.c b/kernel/auditsc.c
> > index aa5d13b4fbbb..2d74238e9638 100644
> > --- a/kernel/auditsc.c
> > +++ b/kernel/auditsc.c
> > @@ -616,6 +616,9 @@ static int audit_filter_rules(struct task_struct *tsk,
> >                 case AUDIT_LOGINUID_SET:
> >                         result = audit_comparator(audit_loginuid_set(tsk), f->op, f->val);
> >                         break;
> > +               case AUDIT_CONTID:
> > +                       result = audit_comparator64(audit_get_contid(tsk), f->op, f->val64);
> > +                       break;
> >                 case AUDIT_SUBJ_USER:
> >                 case AUDIT_SUBJ_ROLE:
> >                 case AUDIT_SUBJ_TYPE:
> > --
> > 1.8.3.1
> >
> 
> 
> -- 
> Ondrej Mosnacek <omosnace at redhat dot com>
> Associate Software Engineer, Security Technologies
> Red Hat, Inc.

- RGB

--
Richard Guy Briggs <rgb@redhat.com>
Sr. S/W Engineer, Kernel Security, Base Operating Systems
Remote, Ottawa, Red Hat Canada
IRC: rgb, SunRaycer
Voice: +1.647.777.2635, Internal: (81) 32635

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH ghak90 V5 01/10] audit: collect audit task parameters
  2019-03-15 18:29 ` [PATCH ghak90 V5 01/10] audit: collect audit task parameters Richard Guy Briggs
  2019-03-16 19:57   ` Neil Horman
@ 2019-03-27 20:33   ` Ondrej Mosnacek
  1 sibling, 0 replies; 64+ messages in thread
From: Ondrej Mosnacek @ 2019-03-27 20:33 UTC (permalink / raw)
  To: Richard Guy Briggs
  Cc: containers, linux-api, Linux-Audit Mailing List, linux-fsdevel,
	LKML, netdev, netfilter-devel, Paul Moore, Steve Grubb,
	David Howells, Simo Sorce, Eric Paris, Serge E. Hallyn,
	Eric W . Biederman, nhorman

On Fri, Mar 15, 2019 at 7:33 PM Richard Guy Briggs <rgb@redhat.com> wrote:
> The audit-related parameters in struct task_struct should ideally be
> collected together and accessed through a standard audit API.
>
> Collect the existing loginuid, sessionid and audit_context together in a
> new struct audit_task_info called "audit" in struct task_struct.
>
> Use kmem_cache to manage this pool of memory.
> Un-inline audit_free() to be able to always recover that memory.
>
> Please see the upstream github issue
> https://github.com/linux-audit/audit-kernel/issues/81
> but that issue has been closed with this patch included with
> https://github.com/linux-audit/audit-kernel/issues/90
>
> Signed-off-by: Richard Guy Briggs <rgb@redhat.com>

Reviewed-by: Ondrej Mosnacek <omosnace@redhat.com>


> ---
>  include/linux/audit.h | 49 +++++++++++++++++++++++------------
>  include/linux/sched.h |  7 +----
>  init/init_task.c      |  3 +--
>  init/main.c           |  2 ++
>  kernel/audit.c        | 71 +++++++++++++++++++++++++++++++++++++++++++++++++--
>  kernel/audit.h        |  5 ++++
>  kernel/auditsc.c      | 26 ++++++++++---------
>  kernel/fork.c         |  1 -
>  8 files changed, 124 insertions(+), 40 deletions(-)
>
> diff --git a/include/linux/audit.h b/include/linux/audit.h
> index 1e69d9fe16da..bde346e73f0c 100644
> --- a/include/linux/audit.h
> +++ b/include/linux/audit.h
> @@ -86,6 +86,16 @@ struct audit_field {
>         u32                             op;
>  };
>
> +struct audit_task_info {
> +       kuid_t                  loginuid;
> +       unsigned int            sessionid;
> +#ifdef CONFIG_AUDITSYSCALL
> +       struct audit_context    *ctx;
> +#endif
> +};
> +
> +extern struct audit_task_info init_struct_audit;
> +
>  extern int is_audit_feature_set(int which);
>
>  extern int __init audit_register_class(int class, unsigned *list);
> @@ -122,6 +132,9 @@ struct audit_field {
>  #ifdef CONFIG_AUDIT
>  /* These are defined in audit.c */
>                                 /* Public API */
> +extern int  audit_alloc(struct task_struct *task);
> +extern void audit_free(struct task_struct *task);
> +extern void __init audit_task_init(void);
>  extern __printf(4, 5)
>  void audit_log(struct audit_context *ctx, gfp_t gfp_mask, int type,
>                const char *fmt, ...);
> @@ -164,16 +177,28 @@ extern void                   audit_log_key(struct audit_buffer *ab,
>
>  static inline kuid_t audit_get_loginuid(struct task_struct *tsk)
>  {
> -       return tsk->loginuid;
> +       if (!tsk->audit)
> +               return INVALID_UID;
> +       return tsk->audit->loginuid;
>  }
>
>  static inline unsigned int audit_get_sessionid(struct task_struct *tsk)
>  {
> -       return tsk->sessionid;
> +       if (!tsk->audit)
> +               return AUDIT_SID_UNSET;
> +       return tsk->audit->sessionid;
>  }
>
>  extern u32 audit_enabled;
>  #else /* CONFIG_AUDIT */
> +static inline int audit_alloc(struct task_struct *task)
> +{
> +       return 0;
> +}
> +static inline void audit_free(struct task_struct *task)
> +{ }
> +static inline void __init audit_task_init(void)
> +{ }
>  static inline __printf(4, 5)
>  void audit_log(struct audit_context *ctx, gfp_t gfp_mask, int type,
>                const char *fmt, ...)
> @@ -239,8 +264,6 @@ static inline unsigned int audit_get_sessionid(struct task_struct *tsk)
>
>  /* These are defined in auditsc.c */
>                                 /* Public API */
> -extern int  audit_alloc(struct task_struct *task);
> -extern void __audit_free(struct task_struct *task);
>  extern void __audit_syscall_entry(int major, unsigned long a0, unsigned long a1,
>                                   unsigned long a2, unsigned long a3);
>  extern void __audit_syscall_exit(int ret_success, long ret_value);
> @@ -263,12 +286,14 @@ extern void audit_seccomp_actions_logged(const char *names,
>
>  static inline void audit_set_context(struct task_struct *task, struct audit_context *ctx)
>  {
> -       task->audit_context = ctx;
> +       task->audit->ctx = ctx;
>  }
>
>  static inline struct audit_context *audit_context(void)
>  {
> -       return current->audit_context;
> +       if (!current->audit)
> +               return NULL;
> +       return current->audit->ctx;
>  }
>
>  static inline bool audit_dummy_context(void)
> @@ -276,11 +301,7 @@ static inline bool audit_dummy_context(void)
>         void *p = audit_context();
>         return !p || *(int *)p;
>  }
> -static inline void audit_free(struct task_struct *task)
> -{
> -       if (unlikely(task->audit_context))
> -               __audit_free(task);
> -}
> +
>  static inline void audit_syscall_entry(int major, unsigned long a0,
>                                        unsigned long a1, unsigned long a2,
>                                        unsigned long a3)
> @@ -470,12 +491,6 @@ static inline void audit_fanotify(unsigned int response)
>  extern int audit_n_rules;
>  extern int audit_signals;
>  #else /* CONFIG_AUDITSYSCALL */
> -static inline int audit_alloc(struct task_struct *task)
> -{
> -       return 0;
> -}
> -static inline void audit_free(struct task_struct *task)
> -{ }
>  static inline void audit_syscall_entry(int major, unsigned long a0,
>                                        unsigned long a1, unsigned long a2,
>                                        unsigned long a3)
> diff --git a/include/linux/sched.h b/include/linux/sched.h
> index 765119df759a..6850d1e48ace 100644
> --- a/include/linux/sched.h
> +++ b/include/linux/sched.h
> @@ -31,7 +31,6 @@
>  #include <linux/rseq.h>
>
>  /* task_struct member predeclarations (sorted alphabetically): */
> -struct audit_context;
>  struct backing_dev_info;
>  struct bio_list;
>  struct blk_plug;
> @@ -886,11 +885,7 @@ struct task_struct {
>         struct callback_head            *task_works;
>
>  #ifdef CONFIG_AUDIT
> -#ifdef CONFIG_AUDITSYSCALL
> -       struct audit_context            *audit_context;
> -#endif
> -       kuid_t                          loginuid;
> -       unsigned int                    sessionid;
> +       struct audit_task_info          *audit;
>  #endif
>         struct seccomp                  seccomp;
>
> diff --git a/init/init_task.c b/init/init_task.c
> index 39c3109acc1a..f9685e1edda1 100644
> --- a/init/init_task.c
> +++ b/init/init_task.c
> @@ -122,8 +122,7 @@ struct task_struct init_task
>         .thread_group   = LIST_HEAD_INIT(init_task.thread_group),
>         .thread_node    = LIST_HEAD_INIT(init_signals.thread_head),
>  #ifdef CONFIG_AUDIT
> -       .loginuid       = INVALID_UID,
> -       .sessionid      = AUDIT_SID_UNSET,
> +       .audit          = &init_struct_audit,
>  #endif
>  #ifdef CONFIG_PERF_EVENTS
>         .perf_event_mutex = __MUTEX_INITIALIZER(init_task.perf_event_mutex),
> diff --git a/init/main.c b/init/main.c
> index e2e80ca3165a..8a1c36625d12 100644
> --- a/init/main.c
> +++ b/init/main.c
> @@ -92,6 +92,7 @@
>  #include <linux/rodata_test.h>
>  #include <linux/jump_label.h>
>  #include <linux/mem_encrypt.h>
> +#include <linux/audit.h>
>
>  #include <asm/io.h>
>  #include <asm/bugs.h>
> @@ -727,6 +728,7 @@ asmlinkage __visible void __init start_kernel(void)
>         nsfs_init();
>         cpuset_init();
>         cgroup_init();
> +       audit_task_init();
>         taskstats_init_early();
>         delayacct_init();
>
> diff --git a/kernel/audit.c b/kernel/audit.c
> index c89ea48c70a6..67498c5690bb 100644
> --- a/kernel/audit.c
> +++ b/kernel/audit.c
> @@ -215,6 +215,73 @@ struct audit_reply {
>         struct sk_buff *skb;
>  };
>
> +static struct kmem_cache *audit_task_cache;
> +
> +void __init audit_task_init(void)
> +{
> +       audit_task_cache = kmem_cache_create("audit_task",
> +                                            sizeof(struct audit_task_info),
> +                                            0, SLAB_PANIC, NULL);
> +}
> +
> +/**
> + * audit_alloc - allocate an audit info block for a task
> + * @tsk: task
> + *
> + * Call audit_alloc_syscall to filter on the task information and
> + * allocate a per-task audit context if necessary.  This is called from
> + * copy_process, so no lock is needed.
> + */
> +int audit_alloc(struct task_struct *tsk)
> +{
> +       int ret = 0;
> +       struct audit_task_info *info;
> +
> +       info = kmem_cache_alloc(audit_task_cache, GFP_KERNEL);
> +       if (!info) {
> +               ret = -ENOMEM;
> +               goto out;
> +       }
> +       info->loginuid = audit_get_loginuid(current);
> +       info->sessionid = audit_get_sessionid(current);
> +       tsk->audit = info;
> +
> +       ret = audit_alloc_syscall(tsk);
> +       if (ret) {
> +               tsk->audit = NULL;
> +               kmem_cache_free(audit_task_cache, info);
> +       }
> +out:
> +       return ret;
> +}
> +
> +struct audit_task_info init_struct_audit = {
> +       .loginuid = INVALID_UID,
> +       .sessionid = AUDIT_SID_UNSET,
> +#ifdef CONFIG_AUDITSYSCALL
> +       .ctx = NULL,
> +#endif
> +};
> +
> +/**
> + * audit_free - free per-task audit info
> + * @tsk: task whose audit info block to free
> + *
> + * Called from copy_process and do_exit
> + */
> +void audit_free(struct task_struct *tsk)
> +{
> +       struct audit_task_info *info = tsk->audit;
> +
> +       audit_free_syscall(tsk);
> +       /* Freeing the audit_task_info struct must be performed after
> +        * audit_log_exit() due to need for loginuid and sessionid.
> +        */
> +       info = tsk->audit;
> +       tsk->audit = NULL;
> +       kmem_cache_free(audit_task_cache, info);
> +}
> +
>  /**
>   * auditd_test_task - Check to see if a given task is an audit daemon
>   * @task: the task to check
> @@ -2266,8 +2333,8 @@ int audit_set_loginuid(kuid_t loginuid)
>                         sessionid = (unsigned int)atomic_inc_return(&session_id);
>         }
>
> -       current->sessionid = sessionid;
> -       current->loginuid = loginuid;
> +       current->audit->sessionid = sessionid;
> +       current->audit->loginuid = loginuid;
>  out:
>         audit_log_set_loginuid(oldloginuid, loginuid, oldsessionid, sessionid, rc);
>         return rc;
> diff --git a/kernel/audit.h b/kernel/audit.h
> index 958d5b8fc1b3..c00e2ee3c6b3 100644
> --- a/kernel/audit.h
> +++ b/kernel/audit.h
> @@ -264,6 +264,8 @@ extern void audit_log_d_path_exe(struct audit_buffer *ab,
>  extern unsigned int audit_serial(void);
>  extern int auditsc_get_stamp(struct audit_context *ctx,
>                               struct timespec64 *t, unsigned int *serial);
> +extern int audit_alloc_syscall(struct task_struct *tsk);
> +extern void audit_free_syscall(struct task_struct *tsk);
>
>  extern void audit_put_watch(struct audit_watch *watch);
>  extern void audit_get_watch(struct audit_watch *watch);
> @@ -305,6 +307,9 @@ extern void audit_filter_inodes(struct task_struct *tsk,
>  extern struct list_head *audit_killed_trees(void);
>  #else /* CONFIG_AUDITSYSCALL */
>  #define auditsc_get_stamp(c, t, s) 0
> +#define audit_alloc_syscall(t) 0
> +#define audit_free_syscall(t) {}
> +
>  #define audit_put_watch(w) {}
>  #define audit_get_watch(w) {}
>  #define audit_to_watch(k, p, l, o) (-EINVAL)
> diff --git a/kernel/auditsc.c b/kernel/auditsc.c
> index d1eab1d4a930..8090eff7868d 100644
> --- a/kernel/auditsc.c
> +++ b/kernel/auditsc.c
> @@ -885,23 +885,25 @@ static inline struct audit_context *audit_alloc_context(enum audit_state state)
>         return context;
>  }
>
> -/**
> - * audit_alloc - allocate an audit context block for a task
> +/*
> + * audit_alloc_syscall - allocate an audit context block for a task
>   * @tsk: task
>   *
>   * Filter on the task information and allocate a per-task audit context
>   * if necessary.  Doing so turns on system call auditing for the
> - * specified task.  This is called from copy_process, so no lock is
> - * needed.
> + * specified task.  This is called from copy_process via audit_alloc, so
> + * no lock is needed.
>   */
> -int audit_alloc(struct task_struct *tsk)
> +int audit_alloc_syscall(struct task_struct *tsk)
>  {
>         struct audit_context *context;
>         enum audit_state     state;
>         char *key = NULL;
>
> -       if (likely(!audit_ever_enabled))
> +       if (likely(!audit_ever_enabled)) {
> +               audit_set_context(tsk, NULL);
>                 return 0; /* Return if not auditing. */
> +       }
>
>         state = audit_filter_task(tsk, &key);
>         if (state == AUDIT_DISABLED) {
> @@ -911,7 +913,7 @@ int audit_alloc(struct task_struct *tsk)
>
>         if (!(context = audit_alloc_context(state))) {
>                 kfree(key);
> -               audit_log_lost("out of memory in audit_alloc");
> +               audit_log_lost("out of memory in audit_alloc_syscall");
>                 return -ENOMEM;
>         }
>         context->filterkey = key;
> @@ -1555,14 +1557,15 @@ static void audit_log_exit(void)
>  }
>
>  /**
> - * __audit_free - free a per-task audit context
> + * audit_free_syscall - free per-task audit context info
>   * @tsk: task whose audit context block to free
>   *
> - * Called from copy_process and do_exit
> + * Called from audit_free
>   */
> -void __audit_free(struct task_struct *tsk)
> +void audit_free_syscall(struct task_struct *tsk)
>  {
> -       struct audit_context *context = tsk->audit_context;
> +       struct audit_task_info *info = tsk->audit;
> +       struct audit_context *context = info->ctx;
>
>         if (!context)
>                 return;
> @@ -1585,7 +1588,6 @@ void __audit_free(struct task_struct *tsk)
>                 if (context->current_state == AUDIT_RECORD_CONTEXT)
>                         audit_log_exit();
>         }
> -
>         audit_set_context(tsk, NULL);
>         audit_free_context(context);
>  }
> diff --git a/kernel/fork.c b/kernel/fork.c
> index a60459947f18..1107bd8b8ad8 100644
> --- a/kernel/fork.c
> +++ b/kernel/fork.c
> @@ -1836,7 +1836,6 @@ static __latent_entropy struct task_struct *copy_process(
>         p->start_time = ktime_get_ns();
>         p->real_start_time = ktime_get_boot_ns();
>         p->io_context = NULL;
> -       audit_set_context(p, NULL);
>         cgroup_fork(p);
>  #ifdef CONFIG_NUMA
>         p->mempolicy = mpol_dup(p->mempolicy);
> --
> 1.8.3.1
>


--
Ondrej Mosnacek <omosnace at redhat dot com>
Software Engineer, Security Technologies
Red Hat, Inc.

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH ghak90 V5 02/10] audit: add container id
  2019-03-15 18:29 ` [PATCH ghak90 V5 02/10] audit: add container id Richard Guy Briggs
  2019-03-16 20:00   ` Neil Horman
@ 2019-03-27 20:38   ` Ondrej Mosnacek
  2019-03-27 20:44     ` Richard Guy Briggs
  1 sibling, 1 reply; 64+ messages in thread
From: Ondrej Mosnacek @ 2019-03-27 20:38 UTC (permalink / raw)
  To: Richard Guy Briggs
  Cc: containers, linux-api, Linux-Audit Mailing List, linux-fsdevel,
	LKML, netdev, netfilter-devel, Paul Moore, Steve Grubb,
	David Howells, Simo Sorce, Eric Paris, Serge E. Hallyn,
	Eric W . Biederman, nhorman

On Fri, Mar 15, 2019 at 7:33 PM Richard Guy Briggs <rgb@redhat.com> wrote:
> Implement the proc fs write to set the audit container identifier of a
> process, emitting an AUDIT_CONTAINER_OP record to document the event.
>
> This is a write from the container orchestrator task to a proc entry of
> the form /proc/PID/audit_containerid where PID is the process ID of the
> newly created task that is to become the first task in a container, or
> an additional task added to a container.
>
> The write expects up to a u64 value (unset: 18446744073709551615).
>
> The writer must have capability CAP_AUDIT_CONTROL.
>
> This will produce a record such as this:
>   type=CONTAINER_OP 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
>
> The "op" field indicates an initial set.  The "pid" to "ses" fields are
> the orchestrator while the "opid" field is the object's PID, the process
> being "contained".  Old and new audit container identifier values are
> given in the "contid" fields, while res indicates its success.
>
> It is not permitted to unset the audit container identifier.
> A child inherits its parent's audit container identifier.
>
> See: https://github.com/linux-audit/audit-kernel/issues/90
> See: https://github.com/linux-audit/audit-userspace/issues/51
> See: https://github.com/linux-audit/audit-testsuite/issues/64
> See: https://github.com/linux-audit/audit-kernel/wiki/RFE-Audit-Container-ID
>
> Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> Acked-by: Serge Hallyn <serge@hallyn.com>
> Acked-by: Steve Grubb <sgrubb@redhat.com>
> Signed-off-by: Richard Guy Briggs <rgb@redhat.com>

Note that you have duplicate Signed-off here ^^

Took me a while to understand the flow in audit_set_contid(), but once
understood it all made perfect sense, so:

Reviewed-by: Ondrej Mosnacek <omosnace@redhat.com>


> ---
>  fs/proc/base.c             | 36 ++++++++++++++++++++++++
>  include/linux/audit.h      | 25 +++++++++++++++++
>  include/uapi/linux/audit.h |  2 ++
>  kernel/audit.c             | 68 ++++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 131 insertions(+)
>
> diff --git a/fs/proc/base.c b/fs/proc/base.c
> index a23651ce6960..2505c46c8701 100644
> --- a/fs/proc/base.c
> +++ b/fs/proc/base.c
> @@ -1294,6 +1294,40 @@ static ssize_t proc_sessionid_read(struct file * file, char __user * buf,
>         .read           = proc_sessionid_read,
>         .llseek         = generic_file_llseek,
>  };
> +
> +static ssize_t proc_contid_write(struct file *file, const char __user *buf,
> +                                  size_t count, loff_t *ppos)
> +{
> +       struct inode *inode = file_inode(file);
> +       u64 contid;
> +       int rv;
> +       struct task_struct *task = get_proc_task(inode);
> +
> +       if (!task)
> +               return -ESRCH;
> +       if (*ppos != 0) {
> +               /* No partial writes. */
> +               put_task_struct(task);
> +               return -EINVAL;
> +       }
> +
> +       rv = kstrtou64_from_user(buf, count, 10, &contid);
> +       if (rv < 0) {
> +               put_task_struct(task);
> +               return rv;
> +       }
> +
> +       rv = audit_set_contid(task, contid);
> +       put_task_struct(task);
> +       if (rv < 0)
> +               return rv;
> +       return count;
> +}
> +
> +static const struct file_operations proc_contid_operations = {
> +       .write          = proc_contid_write,
> +       .llseek         = generic_file_llseek,
> +};
>  #endif
>
>  #ifdef CONFIG_FAULT_INJECTION
> @@ -3005,6 +3039,7 @@ static int proc_stack_depth(struct seq_file *m, struct pid_namespace *ns,
>  #ifdef CONFIG_AUDIT
>         REG("loginuid",   S_IWUSR|S_IRUGO, proc_loginuid_operations),
>         REG("sessionid",  S_IRUGO, proc_sessionid_operations),
> +       REG("audit_containerid", S_IWUSR, proc_contid_operations),
>  #endif
>  #ifdef CONFIG_FAULT_INJECTION
>         REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations),
> @@ -3393,6 +3428,7 @@ static int proc_tid_comm_permission(struct inode *inode, int mask)
>  #ifdef CONFIG_AUDIT
>         REG("loginuid",  S_IWUSR|S_IRUGO, proc_loginuid_operations),
>         REG("sessionid",  S_IRUGO, proc_sessionid_operations),
> +       REG("audit_containerid", S_IWUSR, proc_contid_operations),
>  #endif
>  #ifdef CONFIG_FAULT_INJECTION
>         REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations),
> diff --git a/include/linux/audit.h b/include/linux/audit.h
> index bde346e73f0c..301337776193 100644
> --- a/include/linux/audit.h
> +++ b/include/linux/audit.h
> @@ -89,6 +89,7 @@ struct audit_field {
>  struct audit_task_info {
>         kuid_t                  loginuid;
>         unsigned int            sessionid;
> +       u64                     contid;
>  #ifdef CONFIG_AUDITSYSCALL
>         struct audit_context    *ctx;
>  #endif
> @@ -189,6 +190,15 @@ static inline unsigned int audit_get_sessionid(struct task_struct *tsk)
>         return tsk->audit->sessionid;
>  }
>
> +extern int audit_set_contid(struct task_struct *tsk, u64 contid);
> +
> +static inline u64 audit_get_contid(struct task_struct *tsk)
> +{
> +       if (!tsk->audit)
> +               return AUDIT_CID_UNSET;
> +       return tsk->audit->contid;
> +}
> +
>  extern u32 audit_enabled;
>  #else /* CONFIG_AUDIT */
>  static inline int audit_alloc(struct task_struct *task)
> @@ -250,6 +260,11 @@ static inline unsigned int audit_get_sessionid(struct task_struct *tsk)
>         return AUDIT_SID_UNSET;
>  }
>
> +static inline u64 audit_get_contid(struct task_struct *tsk)
> +{
> +       return AUDIT_CID_UNSET;
> +}
> +
>  #define audit_enabled AUDIT_OFF
>  #endif /* CONFIG_AUDIT */
>
> @@ -606,6 +621,16 @@ static inline bool audit_loginuid_set(struct task_struct *tsk)
>         return uid_valid(audit_get_loginuid(tsk));
>  }
>
> +static inline bool audit_contid_valid(u64 contid)
> +{
> +       return contid != AUDIT_CID_UNSET;
> +}
> +
> +static inline bool audit_contid_set(struct task_struct *tsk)
> +{
> +       return audit_contid_valid(audit_get_contid(tsk));
> +}
> +
>  static inline void audit_log_string(struct audit_buffer *ab, const char *buf)
>  {
>         audit_log_n_string(ab, buf, strlen(buf));
> diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h
> index 36a7e3f18e69..d475cf3b4d7f 100644
> --- a/include/uapi/linux/audit.h
> +++ b/include/uapi/linux/audit.h
> @@ -71,6 +71,7 @@
>  #define AUDIT_TTY_SET          1017    /* Set TTY auditing status */
>  #define AUDIT_SET_FEATURE      1018    /* Turn an audit feature on or off */
>  #define AUDIT_GET_FEATURE      1019    /* Get which features are enabled */
> +#define AUDIT_CONTAINER_OP     1020    /* Define the container id and information */
>
>  #define AUDIT_FIRST_USER_MSG   1100    /* Userspace messages mostly uninteresting to kernel */
>  #define AUDIT_USER_AVC         1107    /* We filter this differently */
> @@ -471,6 +472,7 @@ struct audit_tty_status {
>
>  #define AUDIT_UID_UNSET (unsigned int)-1
>  #define AUDIT_SID_UNSET ((unsigned int)-1)
> +#define AUDIT_CID_UNSET ((u64)-1)
>
>  /* audit_rule_data supports filter rules with both integer and string
>   * fields.  It corresponds with AUDIT_ADD_RULE, AUDIT_DEL_RULE and
> diff --git a/kernel/audit.c b/kernel/audit.c
> index 67498c5690bb..b5c702abeb42 100644
> --- a/kernel/audit.c
> +++ b/kernel/audit.c
> @@ -244,6 +244,7 @@ int audit_alloc(struct task_struct *tsk)
>         }
>         info->loginuid = audit_get_loginuid(current);
>         info->sessionid = audit_get_sessionid(current);
> +       info->contid = audit_get_contid(current);
>         tsk->audit = info;
>
>         ret = audit_alloc_syscall(tsk);
> @@ -258,6 +259,7 @@ int audit_alloc(struct task_struct *tsk)
>  struct audit_task_info init_struct_audit = {
>         .loginuid = INVALID_UID,
>         .sessionid = AUDIT_SID_UNSET,
> +       .contid = AUDIT_CID_UNSET,
>  #ifdef CONFIG_AUDITSYSCALL
>         .ctx = NULL,
>  #endif
> @@ -2341,6 +2343,72 @@ int audit_set_loginuid(kuid_t loginuid)
>  }
>
>  /**
> + * audit_set_contid - set current task's audit contid
> + * @contid: contid value
> + *
> + * Returns 0 on success, -EPERM on permission failure.
> + *
> + * Called (set) from fs/proc/base.c::proc_contid_write().
> + */
> +int audit_set_contid(struct task_struct *task, u64 contid)
> +{
> +       u64 oldcontid;
> +       int rc = 0;
> +       struct audit_buffer *ab;
> +       uid_t uid;
> +       struct tty_struct *tty;
> +       char comm[sizeof(current->comm)];
> +
> +       task_lock(task);
> +       /* Can't set if audit disabled */
> +       if (!task->audit) {
> +               task_unlock(task);
> +               return -ENOPROTOOPT;
> +       }
> +       oldcontid = audit_get_contid(task);
> +       read_lock(&tasklist_lock);
> +       /* Don't allow the audit containerid to be unset */
> +       if (!audit_contid_valid(contid))
> +               rc = -EINVAL;
> +       /* if we don't have caps, reject */
> +       else if (!capable(CAP_AUDIT_CONTROL))
> +               rc = -EPERM;
> +       /* if task has children or is not single-threaded, deny */
> +       else if (!list_empty(&task->children))
> +               rc = -EBUSY;
> +       else if (!(thread_group_leader(task) && thread_group_empty(task)))
> +               rc = -EALREADY;
> +       read_unlock(&tasklist_lock);
> +       if (!rc)
> +               task->audit->contid = contid;
> +       task_unlock(task);
> +
> +       if (!audit_enabled)
> +               return rc;
> +
> +       ab = audit_log_start(audit_context(), GFP_KERNEL, AUDIT_CONTAINER_OP);
> +       if (!ab)
> +               return rc;
> +
> +       uid = from_kuid(&init_user_ns, task_uid(current));
> +       tty = audit_get_tty();
> +       audit_log_format(ab, "op=set opid=%d old-contid=%llu contid=%llu pid=%d uid=%u auid=%u tty=%s ses=%u",
> +                        task_tgid_nr(task), oldcontid, contid,
> +                        task_tgid_nr(current), 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, " res=%d", !rc);
> +       audit_log_end(ab);
> +       return rc;
> +}
> +
> +/**
>   * audit_log_end - end one audit record
>   * @ab: the audit_buffer
>   *
> --
> 1.8.3.1
>

--
Ondrej Mosnacek <omosnace at redhat dot com>
Software Engineer, Security Technologies
Red Hat, Inc.

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH ghak90 V5 02/10] audit: add container id
  2019-03-27 20:38   ` Ondrej Mosnacek
@ 2019-03-27 20:44     ` Richard Guy Briggs
  0 siblings, 0 replies; 64+ messages in thread
From: Richard Guy Briggs @ 2019-03-27 20:44 UTC (permalink / raw)
  To: Ondrej Mosnacek
  Cc: containers, linux-api, Linux-Audit Mailing List, linux-fsdevel,
	LKML, netdev, netfilter-devel, Paul Moore, Steve Grubb,
	David Howells, Simo Sorce, Eric Paris, Serge E. Hallyn,
	Eric W . Biederman, nhorman

On 2019-03-27 21:38, Ondrej Mosnacek wrote:
> On Fri, Mar 15, 2019 at 7:33 PM Richard Guy Briggs <rgb@redhat.com> wrote:
> > Implement the proc fs write to set the audit container identifier of a
> > process, emitting an AUDIT_CONTAINER_OP record to document the event.
> >
> > This is a write from the container orchestrator task to a proc entry of
> > the form /proc/PID/audit_containerid where PID is the process ID of the
> > newly created task that is to become the first task in a container, or
> > an additional task added to a container.
> >
> > The write expects up to a u64 value (unset: 18446744073709551615).
> >
> > The writer must have capability CAP_AUDIT_CONTROL.
> >
> > This will produce a record such as this:
> >   type=CONTAINER_OP 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
> >
> > The "op" field indicates an initial set.  The "pid" to "ses" fields are
> > the orchestrator while the "opid" field is the object's PID, the process
> > being "contained".  Old and new audit container identifier values are
> > given in the "contid" fields, while res indicates its success.
> >
> > It is not permitted to unset the audit container identifier.
> > A child inherits its parent's audit container identifier.
> >
> > See: https://github.com/linux-audit/audit-kernel/issues/90
> > See: https://github.com/linux-audit/audit-userspace/issues/51
> > See: https://github.com/linux-audit/audit-testsuite/issues/64
> > See: https://github.com/linux-audit/audit-kernel/wiki/RFE-Audit-Container-ID
> >
> > Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> > Acked-by: Serge Hallyn <serge@hallyn.com>
> > Acked-by: Steve Grubb <sgrubb@redhat.com>
> > Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> 
> Note that you have duplicate Signed-off here ^^

Yeah, I caught a few of those for v6 and a number of other formatting
issues.

> Took me a while to understand the flow in audit_set_contid(), but once
> understood it all made perfect sense, so:
> 
> Reviewed-by: Ondrej Mosnacek <omosnace@redhat.com>
> 
> 
> > ---
> >  fs/proc/base.c             | 36 ++++++++++++++++++++++++
> >  include/linux/audit.h      | 25 +++++++++++++++++
> >  include/uapi/linux/audit.h |  2 ++
> >  kernel/audit.c             | 68 ++++++++++++++++++++++++++++++++++++++++++++++
> >  4 files changed, 131 insertions(+)
> >
> > diff --git a/fs/proc/base.c b/fs/proc/base.c
> > index a23651ce6960..2505c46c8701 100644
> > --- a/fs/proc/base.c
> > +++ b/fs/proc/base.c
> > @@ -1294,6 +1294,40 @@ static ssize_t proc_sessionid_read(struct file * file, char __user * buf,
> >         .read           = proc_sessionid_read,
> >         .llseek         = generic_file_llseek,
> >  };
> > +
> > +static ssize_t proc_contid_write(struct file *file, const char __user *buf,
> > +                                  size_t count, loff_t *ppos)
> > +{
> > +       struct inode *inode = file_inode(file);
> > +       u64 contid;
> > +       int rv;
> > +       struct task_struct *task = get_proc_task(inode);
> > +
> > +       if (!task)
> > +               return -ESRCH;
> > +       if (*ppos != 0) {
> > +               /* No partial writes. */
> > +               put_task_struct(task);
> > +               return -EINVAL;
> > +       }
> > +
> > +       rv = kstrtou64_from_user(buf, count, 10, &contid);
> > +       if (rv < 0) {
> > +               put_task_struct(task);
> > +               return rv;
> > +       }
> > +
> > +       rv = audit_set_contid(task, contid);
> > +       put_task_struct(task);
> > +       if (rv < 0)
> > +               return rv;
> > +       return count;
> > +}
> > +
> > +static const struct file_operations proc_contid_operations = {
> > +       .write          = proc_contid_write,
> > +       .llseek         = generic_file_llseek,
> > +};
> >  #endif
> >
> >  #ifdef CONFIG_FAULT_INJECTION
> > @@ -3005,6 +3039,7 @@ static int proc_stack_depth(struct seq_file *m, struct pid_namespace *ns,
> >  #ifdef CONFIG_AUDIT
> >         REG("loginuid",   S_IWUSR|S_IRUGO, proc_loginuid_operations),
> >         REG("sessionid",  S_IRUGO, proc_sessionid_operations),
> > +       REG("audit_containerid", S_IWUSR, proc_contid_operations),
> >  #endif
> >  #ifdef CONFIG_FAULT_INJECTION
> >         REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations),
> > @@ -3393,6 +3428,7 @@ static int proc_tid_comm_permission(struct inode *inode, int mask)
> >  #ifdef CONFIG_AUDIT
> >         REG("loginuid",  S_IWUSR|S_IRUGO, proc_loginuid_operations),
> >         REG("sessionid",  S_IRUGO, proc_sessionid_operations),
> > +       REG("audit_containerid", S_IWUSR, proc_contid_operations),
> >  #endif
> >  #ifdef CONFIG_FAULT_INJECTION
> >         REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations),
> > diff --git a/include/linux/audit.h b/include/linux/audit.h
> > index bde346e73f0c..301337776193 100644
> > --- a/include/linux/audit.h
> > +++ b/include/linux/audit.h
> > @@ -89,6 +89,7 @@ struct audit_field {
> >  struct audit_task_info {
> >         kuid_t                  loginuid;
> >         unsigned int            sessionid;
> > +       u64                     contid;
> >  #ifdef CONFIG_AUDITSYSCALL
> >         struct audit_context    *ctx;
> >  #endif
> > @@ -189,6 +190,15 @@ static inline unsigned int audit_get_sessionid(struct task_struct *tsk)
> >         return tsk->audit->sessionid;
> >  }
> >
> > +extern int audit_set_contid(struct task_struct *tsk, u64 contid);
> > +
> > +static inline u64 audit_get_contid(struct task_struct *tsk)
> > +{
> > +       if (!tsk->audit)
> > +               return AUDIT_CID_UNSET;
> > +       return tsk->audit->contid;
> > +}
> > +
> >  extern u32 audit_enabled;
> >  #else /* CONFIG_AUDIT */
> >  static inline int audit_alloc(struct task_struct *task)
> > @@ -250,6 +260,11 @@ static inline unsigned int audit_get_sessionid(struct task_struct *tsk)
> >         return AUDIT_SID_UNSET;
> >  }
> >
> > +static inline u64 audit_get_contid(struct task_struct *tsk)
> > +{
> > +       return AUDIT_CID_UNSET;
> > +}
> > +
> >  #define audit_enabled AUDIT_OFF
> >  #endif /* CONFIG_AUDIT */
> >
> > @@ -606,6 +621,16 @@ static inline bool audit_loginuid_set(struct task_struct *tsk)
> >         return uid_valid(audit_get_loginuid(tsk));
> >  }
> >
> > +static inline bool audit_contid_valid(u64 contid)
> > +{
> > +       return contid != AUDIT_CID_UNSET;
> > +}
> > +
> > +static inline bool audit_contid_set(struct task_struct *tsk)
> > +{
> > +       return audit_contid_valid(audit_get_contid(tsk));
> > +}
> > +
> >  static inline void audit_log_string(struct audit_buffer *ab, const char *buf)
> >  {
> >         audit_log_n_string(ab, buf, strlen(buf));
> > diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h
> > index 36a7e3f18e69..d475cf3b4d7f 100644
> > --- a/include/uapi/linux/audit.h
> > +++ b/include/uapi/linux/audit.h
> > @@ -71,6 +71,7 @@
> >  #define AUDIT_TTY_SET          1017    /* Set TTY auditing status */
> >  #define AUDIT_SET_FEATURE      1018    /* Turn an audit feature on or off */
> >  #define AUDIT_GET_FEATURE      1019    /* Get which features are enabled */
> > +#define AUDIT_CONTAINER_OP     1020    /* Define the container id and information */
> >
> >  #define AUDIT_FIRST_USER_MSG   1100    /* Userspace messages mostly uninteresting to kernel */
> >  #define AUDIT_USER_AVC         1107    /* We filter this differently */
> > @@ -471,6 +472,7 @@ struct audit_tty_status {
> >
> >  #define AUDIT_UID_UNSET (unsigned int)-1
> >  #define AUDIT_SID_UNSET ((unsigned int)-1)
> > +#define AUDIT_CID_UNSET ((u64)-1)
> >
> >  /* audit_rule_data supports filter rules with both integer and string
> >   * fields.  It corresponds with AUDIT_ADD_RULE, AUDIT_DEL_RULE and
> > diff --git a/kernel/audit.c b/kernel/audit.c
> > index 67498c5690bb..b5c702abeb42 100644
> > --- a/kernel/audit.c
> > +++ b/kernel/audit.c
> > @@ -244,6 +244,7 @@ int audit_alloc(struct task_struct *tsk)
> >         }
> >         info->loginuid = audit_get_loginuid(current);
> >         info->sessionid = audit_get_sessionid(current);
> > +       info->contid = audit_get_contid(current);
> >         tsk->audit = info;
> >
> >         ret = audit_alloc_syscall(tsk);
> > @@ -258,6 +259,7 @@ int audit_alloc(struct task_struct *tsk)
> >  struct audit_task_info init_struct_audit = {
> >         .loginuid = INVALID_UID,
> >         .sessionid = AUDIT_SID_UNSET,
> > +       .contid = AUDIT_CID_UNSET,
> >  #ifdef CONFIG_AUDITSYSCALL
> >         .ctx = NULL,
> >  #endif
> > @@ -2341,6 +2343,72 @@ int audit_set_loginuid(kuid_t loginuid)
> >  }
> >
> >  /**
> > + * audit_set_contid - set current task's audit contid
> > + * @contid: contid value
> > + *
> > + * Returns 0 on success, -EPERM on permission failure.
> > + *
> > + * Called (set) from fs/proc/base.c::proc_contid_write().
> > + */
> > +int audit_set_contid(struct task_struct *task, u64 contid)
> > +{
> > +       u64 oldcontid;
> > +       int rc = 0;
> > +       struct audit_buffer *ab;
> > +       uid_t uid;
> > +       struct tty_struct *tty;
> > +       char comm[sizeof(current->comm)];
> > +
> > +       task_lock(task);
> > +       /* Can't set if audit disabled */
> > +       if (!task->audit) {
> > +               task_unlock(task);
> > +               return -ENOPROTOOPT;
> > +       }
> > +       oldcontid = audit_get_contid(task);
> > +       read_lock(&tasklist_lock);
> > +       /* Don't allow the audit containerid to be unset */
> > +       if (!audit_contid_valid(contid))
> > +               rc = -EINVAL;
> > +       /* if we don't have caps, reject */
> > +       else if (!capable(CAP_AUDIT_CONTROL))
> > +               rc = -EPERM;
> > +       /* if task has children or is not single-threaded, deny */
> > +       else if (!list_empty(&task->children))
> > +               rc = -EBUSY;
> > +       else if (!(thread_group_leader(task) && thread_group_empty(task)))
> > +               rc = -EALREADY;
> > +       read_unlock(&tasklist_lock);
> > +       if (!rc)
> > +               task->audit->contid = contid;
> > +       task_unlock(task);
> > +
> > +       if (!audit_enabled)
> > +               return rc;
> > +
> > +       ab = audit_log_start(audit_context(), GFP_KERNEL, AUDIT_CONTAINER_OP);
> > +       if (!ab)
> > +               return rc;
> > +
> > +       uid = from_kuid(&init_user_ns, task_uid(current));
> > +       tty = audit_get_tty();
> > +       audit_log_format(ab, "op=set opid=%d old-contid=%llu contid=%llu pid=%d uid=%u auid=%u tty=%s ses=%u",
> > +                        task_tgid_nr(task), oldcontid, contid,
> > +                        task_tgid_nr(current), 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, " res=%d", !rc);
> > +       audit_log_end(ab);
> > +       return rc;
> > +}
> > +
> > +/**
> >   * audit_log_end - end one audit record
> >   * @ab: the audit_buffer
> >   *
> > --
> > 1.8.3.1
> >
> 
> --
> Ondrej Mosnacek <omosnace at redhat dot com>
> Software Engineer, Security Technologies
> Red Hat, Inc.

- RGB

--
Richard Guy Briggs <rgb@redhat.com>
Sr. S/W Engineer, Kernel Security, Base Operating Systems
Remote, Ottawa, Red Hat Canada
IRC: rgb, SunRaycer
Voice: +1.647.777.2635, Internal: (81) 32635

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH ghak90 V5 03/10] audit: read container ID of a process
  2019-03-15 18:29 ` [PATCH ghak90 V5 03/10] audit: read container ID of a process Richard Guy Briggs
  2019-03-18 11:10   ` Neil Horman
@ 2019-03-27 20:44   ` Ondrej Mosnacek
  1 sibling, 0 replies; 64+ messages in thread
From: Ondrej Mosnacek @ 2019-03-27 20:44 UTC (permalink / raw)
  To: Richard Guy Briggs
  Cc: containers, linux-api, Linux-Audit Mailing List, linux-fsdevel,
	LKML, netdev, netfilter-devel, Paul Moore, Steve Grubb,
	David Howells, Simo Sorce, Eric Paris, Serge E. Hallyn,
	Eric W . Biederman, nhorman

On Fri, Mar 15, 2019 at 7:33 PM Richard Guy Briggs <rgb@redhat.com> wrote:
> Add support for reading the audit container identifier from the proc
> filesystem.
>
> This is a read from the proc entry of the form
> /proc/PID/audit_containerid where PID is the process ID of the task
> whose audit container identifier is sought.
>
> The read expects up to a u64 value (unset: 18446744073709551615).
>
> This read requires CAP_AUDIT_CONTROL.
>
> Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> Acked-by: Serge Hallyn <serge@hallyn.com>

Reviewed-by: Ondrej Mosnacek <omosnace@redhat.com>

> ---
>  fs/proc/base.c | 23 +++++++++++++++++++++--
>  1 file changed, 21 insertions(+), 2 deletions(-)
>
> diff --git a/fs/proc/base.c b/fs/proc/base.c
> index 2505c46c8701..0b833cbdf5b6 100644
> --- a/fs/proc/base.c
> +++ b/fs/proc/base.c
> @@ -1295,6 +1295,24 @@ static ssize_t proc_sessionid_read(struct file * file, char __user * buf,
>         .llseek         = generic_file_llseek,
>  };
>
> +static ssize_t proc_contid_read(struct file *file, char __user *buf,
> +                                 size_t count, loff_t *ppos)
> +{
> +       struct inode *inode = file_inode(file);
> +       struct task_struct *task = get_proc_task(inode);
> +       ssize_t length;
> +       char tmpbuf[TMPBUFLEN*2];
> +
> +       if (!task)
> +               return -ESRCH;
> +       /* if we don't have caps, reject */
> +       if (!capable(CAP_AUDIT_CONTROL))
> +               return -EPERM;
> +       length = scnprintf(tmpbuf, TMPBUFLEN*2, "%llu", audit_get_contid(task));
> +       put_task_struct(task);
> +       return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
> +}
> +
>  static ssize_t proc_contid_write(struct file *file, const char __user *buf,
>                                    size_t count, loff_t *ppos)
>  {
> @@ -1325,6 +1343,7 @@ static ssize_t proc_contid_write(struct file *file, const char __user *buf,
>  }
>
>  static const struct file_operations proc_contid_operations = {
> +       .read           = proc_contid_read,
>         .write          = proc_contid_write,
>         .llseek         = generic_file_llseek,
>  };
> @@ -3039,7 +3058,7 @@ static int proc_stack_depth(struct seq_file *m, struct pid_namespace *ns,
>  #ifdef CONFIG_AUDIT
>         REG("loginuid",   S_IWUSR|S_IRUGO, proc_loginuid_operations),
>         REG("sessionid",  S_IRUGO, proc_sessionid_operations),
> -       REG("audit_containerid", S_IWUSR, proc_contid_operations),
> +       REG("audit_containerid", S_IWUSR|S_IRUSR, proc_contid_operations),
>  #endif
>  #ifdef CONFIG_FAULT_INJECTION
>         REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations),
> @@ -3428,7 +3447,7 @@ static int proc_tid_comm_permission(struct inode *inode, int mask)
>  #ifdef CONFIG_AUDIT
>         REG("loginuid",  S_IWUSR|S_IRUGO, proc_loginuid_operations),
>         REG("sessionid",  S_IRUGO, proc_sessionid_operations),
> -       REG("audit_containerid", S_IWUSR, proc_contid_operations),
> +       REG("audit_containerid", S_IWUSR|S_IRUSR, proc_contid_operations),
>  #endif
>  #ifdef CONFIG_FAULT_INJECTION
>         REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations),
> --
> 1.8.3.1
>

-- 
Ondrej Mosnacek <omosnace at redhat dot com>
Software Engineer, Security Technologies
Red Hat, Inc.

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH ghak90 V5 04/10] audit: log container info of syscalls
  2019-03-15 18:29 ` [PATCH ghak90 V5 04/10] audit: log container info of syscalls Richard Guy Briggs
  2019-03-16 22:44   ` Neil Horman
@ 2019-03-27 21:01   ` Ondrej Mosnacek
  2019-03-27 22:10     ` Richard Guy Briggs
  1 sibling, 1 reply; 64+ messages in thread
From: Ondrej Mosnacek @ 2019-03-27 21:01 UTC (permalink / raw)
  To: Richard Guy Briggs
  Cc: containers, linux-api, Linux-Audit Mailing List, linux-fsdevel,
	LKML, netdev, netfilter-devel, Paul Moore, Steve Grubb,
	David Howells, Simo Sorce, Eric Paris, Serge E. Hallyn,
	Eric W . Biederman, nhorman

On Fri, Mar 15, 2019 at 7:34 PM Richard Guy Briggs <rgb@redhat.com> wrote:
> Create a new audit record AUDIT_CONTAINER_ID to document the audit
> container identifier of a process if it is present.
>
> Called from audit_log_exit(), syscalls are covered.
>
> A sample raw event:
> type=SYSCALL msg=audit(1519924845.499:257): arch=c000003e syscall=257 success=yes exit=3 a0=ffffff9c a1=56374e1cef30 a2=241 a3=1b6 items=2 ppid=606 pid=635 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts0 ses=3 comm="bash" exe="/usr/bin/bash" subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 key="tmpcontainerid"
> type=CWD msg=audit(1519924845.499:257): cwd="/root"
> type=PATH msg=audit(1519924845.499:257): item=0 name="/tmp/" inode=13863 dev=00:27 mode=041777 ouid=0 ogid=0 rdev=00:00 obj=system_u:object_r:tmp_t:s0 nametype= PARENT cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0
> type=PATH msg=audit(1519924845.499:257): item=1 name="/tmp/tmpcontainerid" inode=17729 dev=00:27 mode=0100644 ouid=0 ogid=0 rdev=00:00 obj=unconfined_u:object_r:user_tmp_t:s0 nametype=CREATE cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0
> type=PROCTITLE msg=audit(1519924845.499:257): proctitle=62617368002D6300736C65657020313B206563686F2074657374203E202F746D702F746D70636F6E7461696E65726964
> type=CONTAINER_ID msg=audit(1519924845.499:257): contid=123458
>
> See: https://github.com/linux-audit/audit-kernel/issues/90
> See: https://github.com/linux-audit/audit-userspace/issues/51
> See: https://github.com/linux-audit/audit-testsuite/issues/64
> See: https://github.com/linux-audit/audit-kernel/wiki/RFE-Audit-Container-ID
> Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> Acked-by: Serge Hallyn <serge@hallyn.com>
> Acked-by: Steve Grubb <sgrubb@redhat.com>
> Signed-off-by: Richard Guy Briggs <rgb@redhat.com>

Barring one minor nit below,

Reviewed-by: Ondrej Mosnacek <omosnace@redhat.com>

> ---
>  include/linux/audit.h      |  5 +++++
>  include/uapi/linux/audit.h |  1 +
>  kernel/audit.c             | 21 +++++++++++++++++++++
>  kernel/auditsc.c           |  2 ++
>  4 files changed, 29 insertions(+)
>
> diff --git a/include/linux/audit.h b/include/linux/audit.h
> index 301337776193..43438192ca2a 100644
> --- a/include/linux/audit.h
> +++ b/include/linux/audit.h
> @@ -199,6 +199,8 @@ static inline u64 audit_get_contid(struct task_struct *tsk)
>         return tsk->audit->contid;
>  }
>
> +extern void audit_log_contid(struct audit_context *context, u64 contid);
> +
>  extern u32 audit_enabled;
>  #else /* CONFIG_AUDIT */
>  static inline int audit_alloc(struct task_struct *task)
> @@ -265,6 +267,9 @@ static inline u64 audit_get_contid(struct task_struct *tsk)
>         return AUDIT_CID_UNSET;
>  }
>
> +static inline void audit_log_contid(struct audit_context *context, u64 contid)
> +{ }
> +
>  #define audit_enabled AUDIT_OFF
>  #endif /* CONFIG_AUDIT */
>
> diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h
> index d475cf3b4d7f..a6383e28b2c8 100644
> --- a/include/uapi/linux/audit.h
> +++ b/include/uapi/linux/audit.h
> @@ -115,6 +115,7 @@
>  #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_CONTAINER_ID     1332    /* Container ID */
>
>  #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 b5c702abeb42..8cc0e88d7f2a 100644
> --- a/kernel/audit.c
> +++ b/kernel/audit.c
> @@ -2127,6 +2127,27 @@ void audit_log_session_info(struct audit_buffer *ab)
>         audit_log_format(ab, "auid=%u ses=%u", auid, sessionid);
>  }
>
> +/*
> + * audit_log_contid - report container info
> + * @context: task or local context for record
> + * @contid: container ID to report
> + */
> +void audit_log_contid(struct audit_context *context, u64 contid)
> +{
> +       struct audit_buffer *ab;
> +
> +       if (!audit_contid_valid(contid))
> +               return;
> +       /* Generate AUDIT_CONTAINER_ID record with container ID */
> +       ab = audit_log_start(context, GFP_KERNEL, AUDIT_CONTAINER_ID);
> +       if (!ab)
> +               return;
> +       audit_log_format(ab, "contid=%llu", contid);

Just realized that you *might* get a compiler/static checker warning
since u64 could technically be something else than unsigned long long
on some arches... maybe this is not case in the kernel, but might be
safer to cast it to unsigned long long before passing to
audit_log_format(). Possibly there are similar occurrences in previous
(later) patches that I didn't (won't) notice.

> +       audit_log_end(ab);
> +       return;
> +}
> +EXPORT_SYMBOL(audit_log_contid);
> +
>  void audit_log_key(struct audit_buffer *ab, char *key)
>  {
>         audit_log_format(ab, " key=");
> diff --git a/kernel/auditsc.c b/kernel/auditsc.c
> index 8090eff7868d..a8c8b44b954d 100644
> --- a/kernel/auditsc.c
> +++ b/kernel/auditsc.c
> @@ -1548,6 +1548,8 @@ static void audit_log_exit(void)
>
>         audit_log_proctitle();
>
> +       audit_log_contid(context, audit_get_contid(current));
> +
>         /* Send end of event record to help user space know we are finished */
>         ab = audit_log_start(context, GFP_KERNEL, AUDIT_EOE);
>         if (ab)
> --
> 1.8.3.1
>


-- 
Ondrej Mosnacek <omosnace at redhat dot com>
Software Engineer, Security Technologies
Red Hat, Inc.

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH ghak90 V5 05/10] audit: add containerid support for ptrace and signals
  2019-03-15 18:29 ` [PATCH ghak90 V5 05/10] audit: add containerid support for ptrace and signals Richard Guy Briggs
  2019-03-18 19:04   ` Neil Horman
@ 2019-03-27 21:17   ` Ondrej Mosnacek
  2019-03-28  2:04     ` Richard Guy Briggs
  1 sibling, 1 reply; 64+ messages in thread
From: Ondrej Mosnacek @ 2019-03-27 21:17 UTC (permalink / raw)
  To: Richard Guy Briggs
  Cc: containers, linux-api, Linux-Audit Mailing List, linux-fsdevel,
	LKML, netdev, netfilter-devel, Paul Moore, Steve Grubb,
	David Howells, Simo Sorce, Eric Paris, Serge E. Hallyn,
	Eric W . Biederman, nhorman

On Fri, Mar 15, 2019 at 7:34 PM Richard Guy Briggs <rgb@redhat.com> wrote:
> Add audit container identifier support to ptrace and signals.  In
> particular, the "ref" field provides a way to label the auxiliary record
> to which it is associated.
>
> Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> Acked-by: Serge Hallyn <serge@hallyn.com>
> Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> ---
>  include/linux/audit.h |  1 +
>  kernel/audit.c        |  2 ++
>  kernel/audit.h        |  2 ++
>  kernel/auditsc.c      | 23 +++++++++++++++++------
>  4 files changed, 22 insertions(+), 6 deletions(-)
>
> diff --git a/include/linux/audit.h b/include/linux/audit.h
> index 43438192ca2a..ebd6625ca80e 100644
> --- a/include/linux/audit.h
> +++ b/include/linux/audit.h
> @@ -35,6 +35,7 @@ struct audit_sig_info {
>         uid_t           uid;
>         pid_t           pid;
>         char            ctx[0];
> +       u64             cid;
>  };

It seems like this structure implicitly defines the format of some
message that is sent to userspace... If so, how will userspace detect
that a new format (including the cid) is being used? Even assuming the
fixed order as pointed out by Neil, the message still seems to be
variable-sized so userspace cannot even use the length to infer that.
Am I missing something here? (I hope I am :)

>
>  struct audit_buffer;
> diff --git a/kernel/audit.c b/kernel/audit.c
> index 8cc0e88d7f2a..cfa659b3f6c4 100644
> --- a/kernel/audit.c
> +++ b/kernel/audit.c
> @@ -138,6 +138,7 @@ struct audit_net {
>  kuid_t         audit_sig_uid = INVALID_UID;
>  pid_t          audit_sig_pid = -1;
>  u32            audit_sig_sid = 0;
> +u64            audit_sig_cid = AUDIT_CID_UNSET;
>
>  /* Records can be lost in several ways:
>     0) [suppressed in audit_alloc]
> @@ -1515,6 +1516,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
>                         memcpy(sig_data->ctx, ctx, len);
>                         security_release_secctx(ctx, len);
>                 }
> +               sig_data->cid = audit_sig_cid;
>                 audit_send_reply(skb, seq, AUDIT_SIGNAL_INFO, 0, 0,
>                                  sig_data, sizeof(*sig_data) + len);
>                 kfree(sig_data);
> diff --git a/kernel/audit.h b/kernel/audit.h
> index c00e2ee3c6b3..c5ac6436317e 100644
> --- a/kernel/audit.h
> +++ b/kernel/audit.h
> @@ -148,6 +148,7 @@ struct audit_context {
>         kuid_t              target_uid;
>         unsigned int        target_sessionid;
>         u32                 target_sid;
> +       u64                 target_cid;
>         char                target_comm[TASK_COMM_LEN];
>
>         struct audit_tree_refs *trees, *first_trees;
> @@ -344,6 +345,7 @@ extern void audit_filter_inodes(struct task_struct *tsk,
>  extern pid_t audit_sig_pid;
>  extern kuid_t audit_sig_uid;
>  extern u32 audit_sig_sid;
> +extern u64 audit_sig_cid;
>
>  extern int audit_filter(int msgtype, unsigned int listtype);
>
> diff --git a/kernel/auditsc.c b/kernel/auditsc.c
> index a8c8b44b954d..f04e115df5dc 100644
> --- a/kernel/auditsc.c
> +++ b/kernel/auditsc.c
> @@ -113,6 +113,7 @@ struct audit_aux_data_pids {
>         kuid_t                  target_uid[AUDIT_AUX_PIDS];
>         unsigned int            target_sessionid[AUDIT_AUX_PIDS];
>         u32                     target_sid[AUDIT_AUX_PIDS];
> +       u64                     target_cid[AUDIT_AUX_PIDS];
>         char                    target_comm[AUDIT_AUX_PIDS][TASK_COMM_LEN];
>         int                     pid_count;
>  };
> @@ -1514,7 +1515,7 @@ static void audit_log_exit(void)
>         for (aux = context->aux_pids; aux; aux = aux->next) {
>                 struct audit_aux_data_pids *axs = (void *)aux;
>
> -               for (i = 0; i < axs->pid_count; i++)
> +               for (i = 0; i < axs->pid_count; i++) {
>                         if (audit_log_pid_context(context, axs->target_pid[i],
>                                                   axs->target_auid[i],
>                                                   axs->target_uid[i],
> @@ -1522,14 +1523,20 @@ static void audit_log_exit(void)
>                                                   axs->target_sid[i],
>                                                   axs->target_comm[i]))
>                                 call_panic = 1;
> +                       audit_log_contid(context, axs->target_cid[i]);
> +               }
>         }
>
> -       if (context->target_pid &&
> -           audit_log_pid_context(context, context->target_pid,
> -                                 context->target_auid, context->target_uid,
> -                                 context->target_sessionid,
> -                                 context->target_sid, context->target_comm))
> +       if (context->target_pid) {
> +               if (audit_log_pid_context(context, context->target_pid,
> +                                         context->target_auid,
> +                                         context->target_uid,
> +                                         context->target_sessionid,
> +                                         context->target_sid,
> +                                         context->target_comm))
>                         call_panic = 1;
> +               audit_log_contid(context, context->target_cid);
> +       }
>
>         if (context->pwd.dentry && context->pwd.mnt) {
>                 ab = audit_log_start(context, GFP_KERNEL, AUDIT_CWD);
> @@ -2360,6 +2367,7 @@ void __audit_ptrace(struct task_struct *t)
>         context->target_uid = task_uid(t);
>         context->target_sessionid = audit_get_sessionid(t);
>         security_task_getsecid(t, &context->target_sid);
> +       context->target_cid = audit_get_contid(t);
>         memcpy(context->target_comm, t->comm, TASK_COMM_LEN);
>  }
>
> @@ -2387,6 +2395,7 @@ int audit_signal_info(int sig, struct task_struct *t)
>                 else
>                         audit_sig_uid = uid;
>                 security_task_getsecid(current, &audit_sig_sid);
> +               audit_sig_cid = audit_get_contid(current);
>         }
>
>         if (!audit_signals || audit_dummy_context())
> @@ -2400,6 +2409,7 @@ int audit_signal_info(int sig, struct task_struct *t)
>                 ctx->target_uid = t_uid;
>                 ctx->target_sessionid = audit_get_sessionid(t);
>                 security_task_getsecid(t, &ctx->target_sid);
> +               ctx->target_cid = audit_get_contid(t);
>                 memcpy(ctx->target_comm, t->comm, TASK_COMM_LEN);
>                 return 0;
>         }
> @@ -2421,6 +2431,7 @@ int audit_signal_info(int sig, struct task_struct *t)
>         axp->target_uid[axp->pid_count] = t_uid;
>         axp->target_sessionid[axp->pid_count] = audit_get_sessionid(t);
>         security_task_getsecid(t, &axp->target_sid[axp->pid_count]);
> +       axp->target_cid[axp->pid_count] = audit_get_contid(t);
>         memcpy(axp->target_comm[axp->pid_count], t->comm, TASK_COMM_LEN);
>         axp->pid_count++;
>
> --
> 1.8.3.1
>


-- 
Ondrej Mosnacek <omosnace at redhat dot com>
Software Engineer, Security Technologies
Red Hat, Inc.

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH ghak90 V5 06/10] audit: add support for non-syscall auxiliary records
  2019-03-15 18:29 ` [PATCH ghak90 V5 06/10] audit: add support for non-syscall auxiliary records Richard Guy Briggs
  2019-03-18 19:34   ` Neil Horman
@ 2019-03-27 21:22   ` Ondrej Mosnacek
  2019-04-01 14:49   ` Paul Moore
  2 siblings, 0 replies; 64+ messages in thread
From: Ondrej Mosnacek @ 2019-03-27 21:22 UTC (permalink / raw)
  To: Richard Guy Briggs
  Cc: containers, linux-api, Linux-Audit Mailing List, linux-fsdevel,
	LKML, netdev, netfilter-devel, Paul Moore, Steve Grubb,
	David Howells, Simo Sorce, Eric Paris, Serge E. Hallyn,
	Eric W . Biederman, nhorman

On Fri, Mar 15, 2019 at 7:34 PM Richard Guy Briggs <rgb@redhat.com> wrote:
> Standalone audit records have the timestamp and serial number generated
> on the fly and as such are unique, making them standalone.  This new
> function audit_alloc_local() generates a local audit context that will
> be used only for a standalone record and its auxiliary record(s).  The
> context is discarded immediately after the local associated records are
> produced.
>
> Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> Acked-by: Serge Hallyn <serge@hallyn.com>

Reviewed-by: Ondrej Mosnacek <omosnace@redhat.com>

> ---
>  include/linux/audit.h |  8 ++++++++
>  kernel/audit.h        |  1 +
>  kernel/auditsc.c      | 35 ++++++++++++++++++++++++++++++-----
>  3 files changed, 39 insertions(+), 5 deletions(-)
>
> diff --git a/include/linux/audit.h b/include/linux/audit.h
> index ebd6625ca80e..6db5aba7cc01 100644
> --- a/include/linux/audit.h
> +++ b/include/linux/audit.h
> @@ -285,6 +285,8 @@ static inline void audit_log_contid(struct audit_context *context, u64 contid)
>
>  /* These are defined in auditsc.c */
>                                 /* Public API */
> +extern struct audit_context *audit_alloc_local(gfp_t gfpflags);
> +extern void audit_free_context(struct audit_context *context);
>  extern void __audit_syscall_entry(int major, unsigned long a0, unsigned long a1,
>                                   unsigned long a2, unsigned long a3);
>  extern void __audit_syscall_exit(int ret_success, long ret_value);
> @@ -512,6 +514,12 @@ static inline void audit_fanotify(unsigned int response)
>  extern int audit_n_rules;
>  extern int audit_signals;
>  #else /* CONFIG_AUDITSYSCALL */
> +static inline struct audit_context *audit_alloc_local(gfp_t gfpflags)
> +{
> +       return NULL;
> +}
> +static inline void audit_free_context(struct audit_context *context)
> +{ }
>  static inline void audit_syscall_entry(int major, unsigned long a0,
>                                        unsigned long a1, unsigned long a2,
>                                        unsigned long a3)
> diff --git a/kernel/audit.h b/kernel/audit.h
> index c5ac6436317e..2a1a8b8a8019 100644
> --- a/kernel/audit.h
> +++ b/kernel/audit.h
> @@ -111,6 +111,7 @@ struct audit_proctitle {
>  struct audit_context {
>         int                 dummy;      /* must be the first element */
>         int                 in_syscall; /* 1 if task is in a syscall */
> +       bool                local;      /* local context needed */
>         enum audit_state    state, current_state;
>         unsigned int        serial;     /* serial number for record */
>         int                 major;      /* syscall number */
> diff --git a/kernel/auditsc.c b/kernel/auditsc.c
> index f04e115df5dc..aa5d13b4fbbb 100644
> --- a/kernel/auditsc.c
> +++ b/kernel/auditsc.c
> @@ -872,11 +872,13 @@ static inline void audit_free_aux(struct audit_context *context)
>         }
>  }
>
> -static inline struct audit_context *audit_alloc_context(enum audit_state state)
> +static inline struct audit_context *audit_alloc_context(enum audit_state state,
> +                                                       gfp_t gfpflags)
>  {
>         struct audit_context *context;
>
> -       context = kzalloc(sizeof(*context), GFP_KERNEL);
> +       /* We can be called in atomic context via audit_tg() */
> +       context = kzalloc(sizeof(*context), gfpflags);
>         if (!context)
>                 return NULL;
>         context->state = state;
> @@ -912,7 +914,8 @@ int audit_alloc_syscall(struct task_struct *tsk)
>                 return 0;
>         }
>
> -       if (!(context = audit_alloc_context(state))) {
> +       context = audit_alloc_context(state, GFP_KERNEL);
> +       if (!context) {
>                 kfree(key);
>                 audit_log_lost("out of memory in audit_alloc_syscall");
>                 return -ENOMEM;
> @@ -924,8 +927,29 @@ int audit_alloc_syscall(struct task_struct *tsk)
>         return 0;
>  }
>
> -static inline void audit_free_context(struct audit_context *context)
> +struct audit_context *audit_alloc_local(gfp_t gfpflags)
>  {
> +       struct audit_context *context = NULL;
> +
> +       if (!audit_ever_enabled)
> +               goto out; /* Return if not auditing. */
> +       context = audit_alloc_context(AUDIT_RECORD_CONTEXT, gfpflags);
> +       if (!context) {
> +               audit_log_lost("out of memory in audit_alloc_local");
> +               goto out;
> +       }
> +       context->serial = audit_serial();
> +       ktime_get_coarse_real_ts64(&context->ctime);
> +       context->local = true;
> +out:
> +       return context;
> +}
> +EXPORT_SYMBOL(audit_alloc_local);
> +
> +void audit_free_context(struct audit_context *context)
> +{
> +       if (!context)
> +               return;
>         audit_free_names(context);
>         unroll_tree_refs(context, NULL, 0);
>         free_tree_refs(context);
> @@ -935,6 +959,7 @@ static inline void audit_free_context(struct audit_context *context)
>         audit_proctitle_free(context);
>         kfree(context);
>  }
> +EXPORT_SYMBOL(audit_free_context);
>
>  static int audit_log_pid_context(struct audit_context *context, pid_t pid,
>                                  kuid_t auid, kuid_t uid, unsigned int sessionid,
> @@ -2163,7 +2188,7 @@ void __audit_inode_child(struct inode *parent,
>  int auditsc_get_stamp(struct audit_context *ctx,
>                        struct timespec64 *t, unsigned int *serial)
>  {
> -       if (!ctx->in_syscall)
> +       if (!ctx->in_syscall && !ctx->local)
>                 return 0;
>         if (!ctx->serial)
>                 ctx->serial = audit_serial();
> --
> 1.8.3.1
>


-- 
Ondrej Mosnacek <omosnace at redhat dot com>
Software Engineer, Security Technologies
Red Hat, Inc.

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH ghak90 V5 07/10] audit: add containerid support for user records
  2019-03-15 18:29 ` [PATCH ghak90 V5 07/10] audit: add containerid support for user records Richard Guy Briggs
  2019-03-18 19:41   ` Neil Horman
@ 2019-03-27 21:30   ` Ondrej Mosnacek
  1 sibling, 0 replies; 64+ messages in thread
From: Ondrej Mosnacek @ 2019-03-27 21:30 UTC (permalink / raw)
  To: Richard Guy Briggs
  Cc: containers, linux-api, Linux-Audit Mailing List, linux-fsdevel,
	LKML, netdev, netfilter-devel, Paul Moore, Steve Grubb,
	David Howells, Simo Sorce, Eric Paris, Serge E. Hallyn,
	Eric W . Biederman, nhorman

On Fri, Mar 15, 2019 at 7:34 PM Richard Guy Briggs <rgb@redhat.com> wrote:
> Add audit container identifier auxiliary record to user event standalone
> records.
>
> Signed-off-by: Richard Guy Briggs <rgb@redhat.com>

Reviewed-by: Ondrej Mosnacek <omosnace@redhat.com>

> ---
>  kernel/audit.c | 13 ++++++-------
>  1 file changed, 6 insertions(+), 7 deletions(-)
>
> diff --git a/kernel/audit.c b/kernel/audit.c
> index cfa659b3f6c4..cf448599ef34 100644
> --- a/kernel/audit.c
> +++ b/kernel/audit.c
> @@ -1142,12 +1142,6 @@ static void audit_log_common_recv_msg(struct audit_context *context,
>         audit_log_task_context(*ab);
>  }
>
> -static inline void audit_log_user_recv_msg(struct audit_buffer **ab,
> -                                          u16 msg_type)
> -{
> -       audit_log_common_recv_msg(NULL, ab, msg_type);
> -}
> -
>  int is_audit_feature_set(int i)
>  {
>         return af.features & AUDIT_FEATURE_TO_MASK(i);
> @@ -1409,13 +1403,16 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
>
>                 err = audit_filter(msg_type, AUDIT_FILTER_USER);
>                 if (err == 1) { /* match or error */
> +                       struct audit_context *context;
> +
>                         err = 0;
>                         if (msg_type == AUDIT_USER_TTY) {
>                                 err = tty_audit_push();
>                                 if (err)
>                                         break;
>                         }
> -                       audit_log_user_recv_msg(&ab, msg_type);
> +                       context = audit_alloc_local(GFP_KERNEL);
> +                       audit_log_common_recv_msg(context, &ab, msg_type);
>                         if (msg_type != AUDIT_USER_TTY)
>                                 audit_log_format(ab, " msg='%.*s'",
>                                                  AUDIT_MESSAGE_TEXT_MAX,
> @@ -1431,6 +1428,8 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
>                                 audit_log_n_untrustedstring(ab, data, size);
>                         }
>                         audit_log_end(ab);
> +                       audit_log_contid(context, audit_get_contid(current));
> +                       audit_free_context(context);
>                 }
>                 break;
>         case AUDIT_ADD_RULE:
> --
> 1.8.3.1
>


-- 
Ondrej Mosnacek <omosnace at redhat dot com>
Software Engineer, Security Technologies
Red Hat, Inc.

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH ghak90 V5 08/10] audit: add containerid filtering
  2019-03-18 23:47     ` Richard Guy Briggs
@ 2019-03-27 21:41       ` Ondrej Mosnacek
  2019-03-27 22:00         ` Richard Guy Briggs
  0 siblings, 1 reply; 64+ messages in thread
From: Ondrej Mosnacek @ 2019-03-27 21:41 UTC (permalink / raw)
  To: Richard Guy Briggs
  Cc: containers, linux-api, Linux-Audit Mailing List, linux-fsdevel,
	LKML, netdev, netfilter-devel, Paul Moore, Steve Grubb,
	David Howells, Simo Sorce, Eric Paris, Serge E. Hallyn,
	Eric W . Biederman, nhorman

On Tue, Mar 19, 2019 at 12:47 AM Richard Guy Briggs <rgb@redhat.com> wrote:
> On 2019-03-18 21:02, Ondrej Mosnacek wrote:
> > On Fri, Mar 15, 2019 at 7:35 PM Richard Guy Briggs <rgb@redhat.com> wrote:
> > >
> > > Implement audit container identifier filtering using the AUDIT_CONTID
> > > field name to send an 8-character string representing a u64 since the
> > > value field is only u32.
> > >
> > > Sending it as two u32 was considered, but gathering and comparing two
> > > fields was more complex.
> > >
> > > The feature indicator is AUDIT_FEATURE_BITMAP_CONTAINERID.
> > >
> > > See: https://github.com/linux-audit/audit-kernel/issues/91
> > > 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
> > > Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> > > Acked-by: Serge Hallyn <serge@hallyn.com>
> > > ---
> > >  include/linux/audit.h      |  1 +
> > >  include/uapi/linux/audit.h |  5 ++++-
> > >  kernel/audit.h             |  1 +
> > >  kernel/auditfilter.c       | 47 ++++++++++++++++++++++++++++++++++++++++++++++
> > >  kernel/auditsc.c           |  3 +++
> > >  5 files changed, 56 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/include/linux/audit.h b/include/linux/audit.h
> > > index 6db5aba7cc01..fa19fa408931 100644
> > > --- a/include/linux/audit.h
> > > +++ b/include/linux/audit.h
> > > @@ -77,6 +77,7 @@ struct audit_field {
> > >         u32                             type;
> > >         union {
> > >                 u32                     val;
> > > +               u64                     val64;
> > >                 kuid_t                  uid;
> > >                 kgid_t                  gid;
> > >                 struct {
> > > diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h
> > > index a6383e28b2c8..741ab6f38294 100644
> > > --- a/include/uapi/linux/audit.h
> > > +++ b/include/uapi/linux/audit.h
> > > @@ -265,6 +265,7 @@
> > >  #define AUDIT_LOGINUID_SET     24
> > >  #define AUDIT_SESSIONID        25      /* Session ID */
> > >  #define AUDIT_FSTYPE   26      /* FileSystem Type */
> > > +#define AUDIT_CONTID   27      /* Container ID */
> > >
> > >                                 /* These are ONLY useful when checking
> > >                                  * at syscall exit time (AUDIT_AT_EXIT). */
> > > @@ -345,6 +346,7 @@ enum {
> > >  #define AUDIT_FEATURE_BITMAP_SESSIONID_FILTER  0x00000010
> > >  #define AUDIT_FEATURE_BITMAP_LOST_RESET                0x00000020
> > >  #define AUDIT_FEATURE_BITMAP_FILTER_FS         0x00000040
> > > +#define AUDIT_FEATURE_BITMAP_CONTAINERID       0x00000080
> > >
> > >  #define AUDIT_FEATURE_BITMAP_ALL (AUDIT_FEATURE_BITMAP_BACKLOG_LIMIT | \
> > >                                   AUDIT_FEATURE_BITMAP_BACKLOG_WAIT_TIME | \
> > > @@ -352,7 +354,8 @@ enum {
> > >                                   AUDIT_FEATURE_BITMAP_EXCLUDE_EXTEND | \
> > >                                   AUDIT_FEATURE_BITMAP_SESSIONID_FILTER | \
> > >                                   AUDIT_FEATURE_BITMAP_LOST_RESET | \
> > > -                                 AUDIT_FEATURE_BITMAP_FILTER_FS)
> > > +                                 AUDIT_FEATURE_BITMAP_FILTER_FS | \
> > > +                                 AUDIT_FEATURE_BITMAP_CONTAINERID)
> > >
> > >  /* deprecated: AUDIT_VERSION_* */
> > >  #define AUDIT_VERSION_LATEST           AUDIT_FEATURE_BITMAP_ALL
> > > diff --git a/kernel/audit.h b/kernel/audit.h
> > > index 2a1a8b8a8019..3a40b608bf8d 100644
> > > --- a/kernel/audit.h
> > > +++ b/kernel/audit.h
> > > @@ -230,6 +230,7 @@ static inline int audit_hash_ino(u32 ino)
> > >
> > >  extern int audit_match_class(int class, unsigned syscall);
> > >  extern int audit_comparator(const u32 left, const u32 op, const u32 right);
> > > +extern int audit_comparator64(const u64 left, const u32 op, const u64 right);
> > >  extern int audit_uid_comparator(kuid_t left, u32 op, kuid_t right);
> > >  extern int audit_gid_comparator(kgid_t left, u32 op, kgid_t right);
> > >  extern int parent_len(const char *path);
> > > diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
> > > index add360b46b38..516b8e58959e 100644
> > > --- a/kernel/auditfilter.c
> > > +++ b/kernel/auditfilter.c
> > > @@ -410,6 +410,7 @@ static int audit_field_valid(struct audit_entry *entry, struct audit_field *f)
> > >         /* FALL THROUGH */
> > >         case AUDIT_ARCH:
> > >         case AUDIT_FSTYPE:
> > > +       case AUDIT_CONTID:
> > >                 if (f->op != Audit_not_equal && f->op != Audit_equal)
> > >                         return -EINVAL;
> > >                 break;
> > > @@ -582,6 +583,14 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
> > >                         }
> > >                         entry->rule.exe = audit_mark;
> > >                         break;
> > > +               case AUDIT_CONTID:
> > > +                       if (f->val != sizeof(u64))
> > > +                               goto exit_free;
> > > +                       str = audit_unpack_string(&bufp, &remain, f->val);
> > > +                       if (IS_ERR(str))
> > > +                               goto exit_free;
> > > +                       f->val64 = ((u64 *)str)[0];
> > > +                       break;
> > >                 }
> > >         }
> > >
> > > @@ -664,6 +673,11 @@ static struct audit_rule_data *audit_krule_to_data(struct audit_krule *krule)
> > >                         data->buflen += data->values[i] =
> > >                                 audit_pack_string(&bufp, audit_mark_path(krule->exe));
> > >                         break;
> > > +               case AUDIT_CONTID:
> > > +                       data->buflen += data->values[i] = sizeof(u64);
> > > +                       for (i = 0; i < sizeof(u64); i++)
> > > +                               ((char *)bufp)[i] = ((char *)&f->val64)[i];
> >
> > How about just:
> >
> > memcpy(bufp, &f->val64, sizeof(u64));
> >
> > instead of the awkward for loop? It is simpler and also more in line
> > with the code in audit_pack_string().
>
> I'll grant you that.  I'll use that instead.

Assuming the above tweak will be done, you can add:

Reviewed-by: Ondrej Mosnacek <omosnace@redhat.com>

>
> > Also, doesn't this loop interfere with the outer loop that also uses
> > 'i' as the control variable?
>
> Yes, it does.  Thank you for catching that.  Doing a auditctl -l reveals
> this.
>
> > > +                       break;
> > >                 case AUDIT_LOGINUID_SET:
> > >                         if (krule->pflags & AUDIT_LOGINUID_LEGACY && !f->val) {
> > >                                 data->fields[i] = AUDIT_LOGINUID;
> > > @@ -750,6 +764,10 @@ static int audit_compare_rule(struct audit_krule *a, struct audit_krule *b)
> > >                         if (!gid_eq(a->fields[i].gid, b->fields[i].gid))
> > >                                 return 1;
> > >                         break;
> > > +               case AUDIT_CONTID:
> > > +                       if (a->fields[i].val64 != b->fields[i].val64)
> > > +                               return 1;
> > > +                       break;
> > >                 default:
> > >                         if (a->fields[i].val != b->fields[i].val)
> > >                                 return 1;
> > > @@ -1206,6 +1224,31 @@ int audit_comparator(u32 left, u32 op, u32 right)
> > >         }
> > >  }
> > >
> > > +int audit_comparator64(u64 left, u32 op, u64 right)
> > > +{
> > > +       switch (op) {
> > > +       case Audit_equal:
> > > +               return (left == right);
> > > +       case Audit_not_equal:
> > > +               return (left != right);
> > > +       case Audit_lt:
> > > +               return (left < right);
> > > +       case Audit_le:
> > > +               return (left <= right);
> > > +       case Audit_gt:
> > > +               return (left > right);
> > > +       case Audit_ge:
> > > +               return (left >= right);
> > > +       case Audit_bitmask:
> > > +               return (left & right);
> > > +       case Audit_bittest:
> > > +               return ((left & right) == right);
> > > +       default:
> > > +               BUG();
> > > +               return 0;
> > > +       }
> > > +}
> > > +
> > >  int audit_uid_comparator(kuid_t left, u32 op, kuid_t right)
> > >  {
> > >         switch (op) {
> > > @@ -1344,6 +1387,10 @@ int audit_filter(int msgtype, unsigned int listtype)
> > >                                 result = audit_comparator(audit_loginuid_set(current),
> > >                                                           f->op, f->val);
> > >                                 break;
> > > +                       case AUDIT_CONTID:
> > > +                               result = audit_comparator64(audit_get_contid(current),
> > > +                                                             f->op, f->val64);
> > > +                               break;
> > >                         case AUDIT_MSGTYPE:
> > >                                 result = audit_comparator(msgtype, f->op, f->val);
> > >                                 break;
> > > diff --git a/kernel/auditsc.c b/kernel/auditsc.c
> > > index aa5d13b4fbbb..2d74238e9638 100644
> > > --- a/kernel/auditsc.c
> > > +++ b/kernel/auditsc.c
> > > @@ -616,6 +616,9 @@ static int audit_filter_rules(struct task_struct *tsk,
> > >                 case AUDIT_LOGINUID_SET:
> > >                         result = audit_comparator(audit_loginuid_set(tsk), f->op, f->val);
> > >                         break;
> > > +               case AUDIT_CONTID:
> > > +                       result = audit_comparator64(audit_get_contid(tsk), f->op, f->val64);
> > > +                       break;
> > >                 case AUDIT_SUBJ_USER:
> > >                 case AUDIT_SUBJ_ROLE:
> > >                 case AUDIT_SUBJ_TYPE:
> > > --
> > > 1.8.3.1
> > >
> >
> >
> > --
> > Ondrej Mosnacek <omosnace at redhat dot com>
> > Associate Software Engineer, Security Technologies
> > Red Hat, Inc.
>
> - RGB
>
> --
> Richard Guy Briggs <rgb@redhat.com>
> Sr. S/W Engineer, Kernel Security, Base Operating Systems
> Remote, Ottawa, Red Hat Canada
> IRC: rgb, SunRaycer
> Voice: +1.647.777.2635, Internal: (81) 32635



-- 
Ondrej Mosnacek <omosnace at redhat dot com>
Software Engineer, Security Technologies
Red Hat, Inc.

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH ghak90 V5 08/10] audit: add containerid filtering
  2019-03-27 21:41       ` Ondrej Mosnacek
@ 2019-03-27 22:00         ` Richard Guy Briggs
  0 siblings, 0 replies; 64+ messages in thread
From: Richard Guy Briggs @ 2019-03-27 22:00 UTC (permalink / raw)
  To: Ondrej Mosnacek
  Cc: containers, linux-api, Linux-Audit Mailing List, linux-fsdevel,
	LKML, netdev, netfilter-devel, Paul Moore, Steve Grubb,
	David Howells, Simo Sorce, Eric Paris, Serge E. Hallyn,
	Eric W . Biederman, nhorman

On 2019-03-27 22:41, Ondrej Mosnacek wrote:
> On Tue, Mar 19, 2019 at 12:47 AM Richard Guy Briggs <rgb@redhat.com> wrote:
> > On 2019-03-18 21:02, Ondrej Mosnacek wrote:
> > > On Fri, Mar 15, 2019 at 7:35 PM Richard Guy Briggs <rgb@redhat.com> wrote:
> > > >
> > > > Implement audit container identifier filtering using the AUDIT_CONTID
> > > > field name to send an 8-character string representing a u64 since the
> > > > value field is only u32.
> > > >
> > > > Sending it as two u32 was considered, but gathering and comparing two
> > > > fields was more complex.
> > > >
> > > > The feature indicator is AUDIT_FEATURE_BITMAP_CONTAINERID.
> > > >
> > > > See: https://github.com/linux-audit/audit-kernel/issues/91
> > > > 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
> > > > Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> > > > Acked-by: Serge Hallyn <serge@hallyn.com>
> > > > ---
> > > >  include/linux/audit.h      |  1 +
> > > >  include/uapi/linux/audit.h |  5 ++++-
> > > >  kernel/audit.h             |  1 +
> > > >  kernel/auditfilter.c       | 47 ++++++++++++++++++++++++++++++++++++++++++++++
> > > >  kernel/auditsc.c           |  3 +++
> > > >  5 files changed, 56 insertions(+), 1 deletion(-)
> > > >
> > > > diff --git a/include/linux/audit.h b/include/linux/audit.h
> > > > index 6db5aba7cc01..fa19fa408931 100644
> > > > --- a/include/linux/audit.h
> > > > +++ b/include/linux/audit.h
> > > > @@ -77,6 +77,7 @@ struct audit_field {
> > > >         u32                             type;
> > > >         union {
> > > >                 u32                     val;
> > > > +               u64                     val64;
> > > >                 kuid_t                  uid;
> > > >                 kgid_t                  gid;
> > > >                 struct {
> > > > diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h
> > > > index a6383e28b2c8..741ab6f38294 100644
> > > > --- a/include/uapi/linux/audit.h
> > > > +++ b/include/uapi/linux/audit.h
> > > > @@ -265,6 +265,7 @@
> > > >  #define AUDIT_LOGINUID_SET     24
> > > >  #define AUDIT_SESSIONID        25      /* Session ID */
> > > >  #define AUDIT_FSTYPE   26      /* FileSystem Type */
> > > > +#define AUDIT_CONTID   27      /* Container ID */
> > > >
> > > >                                 /* These are ONLY useful when checking
> > > >                                  * at syscall exit time (AUDIT_AT_EXIT). */
> > > > @@ -345,6 +346,7 @@ enum {
> > > >  #define AUDIT_FEATURE_BITMAP_SESSIONID_FILTER  0x00000010
> > > >  #define AUDIT_FEATURE_BITMAP_LOST_RESET                0x00000020
> > > >  #define AUDIT_FEATURE_BITMAP_FILTER_FS         0x00000040
> > > > +#define AUDIT_FEATURE_BITMAP_CONTAINERID       0x00000080
> > > >
> > > >  #define AUDIT_FEATURE_BITMAP_ALL (AUDIT_FEATURE_BITMAP_BACKLOG_LIMIT | \
> > > >                                   AUDIT_FEATURE_BITMAP_BACKLOG_WAIT_TIME | \
> > > > @@ -352,7 +354,8 @@ enum {
> > > >                                   AUDIT_FEATURE_BITMAP_EXCLUDE_EXTEND | \
> > > >                                   AUDIT_FEATURE_BITMAP_SESSIONID_FILTER | \
> > > >                                   AUDIT_FEATURE_BITMAP_LOST_RESET | \
> > > > -                                 AUDIT_FEATURE_BITMAP_FILTER_FS)
> > > > +                                 AUDIT_FEATURE_BITMAP_FILTER_FS | \
> > > > +                                 AUDIT_FEATURE_BITMAP_CONTAINERID)
> > > >
> > > >  /* deprecated: AUDIT_VERSION_* */
> > > >  #define AUDIT_VERSION_LATEST           AUDIT_FEATURE_BITMAP_ALL
> > > > diff --git a/kernel/audit.h b/kernel/audit.h
> > > > index 2a1a8b8a8019..3a40b608bf8d 100644
> > > > --- a/kernel/audit.h
> > > > +++ b/kernel/audit.h
> > > > @@ -230,6 +230,7 @@ static inline int audit_hash_ino(u32 ino)
> > > >
> > > >  extern int audit_match_class(int class, unsigned syscall);
> > > >  extern int audit_comparator(const u32 left, const u32 op, const u32 right);
> > > > +extern int audit_comparator64(const u64 left, const u32 op, const u64 right);
> > > >  extern int audit_uid_comparator(kuid_t left, u32 op, kuid_t right);
> > > >  extern int audit_gid_comparator(kgid_t left, u32 op, kgid_t right);
> > > >  extern int parent_len(const char *path);
> > > > diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
> > > > index add360b46b38..516b8e58959e 100644
> > > > --- a/kernel/auditfilter.c
> > > > +++ b/kernel/auditfilter.c
> > > > @@ -410,6 +410,7 @@ static int audit_field_valid(struct audit_entry *entry, struct audit_field *f)
> > > >         /* FALL THROUGH */
> > > >         case AUDIT_ARCH:
> > > >         case AUDIT_FSTYPE:
> > > > +       case AUDIT_CONTID:
> > > >                 if (f->op != Audit_not_equal && f->op != Audit_equal)
> > > >                         return -EINVAL;
> > > >                 break;
> > > > @@ -582,6 +583,14 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
> > > >                         }
> > > >                         entry->rule.exe = audit_mark;
> > > >                         break;
> > > > +               case AUDIT_CONTID:
> > > > +                       if (f->val != sizeof(u64))
> > > > +                               goto exit_free;
> > > > +                       str = audit_unpack_string(&bufp, &remain, f->val);
> > > > +                       if (IS_ERR(str))
> > > > +                               goto exit_free;
> > > > +                       f->val64 = ((u64 *)str)[0];
> > > > +                       break;
> > > >                 }
> > > >         }
> > > >
> > > > @@ -664,6 +673,11 @@ static struct audit_rule_data *audit_krule_to_data(struct audit_krule *krule)
> > > >                         data->buflen += data->values[i] =
> > > >                                 audit_pack_string(&bufp, audit_mark_path(krule->exe));
> > > >                         break;
> > > > +               case AUDIT_CONTID:
> > > > +                       data->buflen += data->values[i] = sizeof(u64);
> > > > +                       for (i = 0; i < sizeof(u64); i++)
> > > > +                               ((char *)bufp)[i] = ((char *)&f->val64)[i];
> > >
> > > How about just:
> > >
> > > memcpy(bufp, &f->val64, sizeof(u64));
> > >
> > > instead of the awkward for loop? It is simpler and also more in line
> > > with the code in audit_pack_string().
> >
> > I'll grant you that.  I'll use that instead.
> 
> Assuming the above tweak will be done, you can add:
> 
> Reviewed-by: Ondrej Mosnacek <omosnace@redhat.com>

Thanks.  In the process of fixing that, I had also found a buffer
pointer increment bug which has been fixed and a new test added to check
for both.

> > > Also, doesn't this loop interfere with the outer loop that also uses
> > > 'i' as the control variable?
> >
> > Yes, it does.  Thank you for catching that.  Doing a auditctl -l reveals
> > this.
> >
> > > > +                       break;
> > > >                 case AUDIT_LOGINUID_SET:
> > > >                         if (krule->pflags & AUDIT_LOGINUID_LEGACY && !f->val) {
> > > >                                 data->fields[i] = AUDIT_LOGINUID;
> > > > @@ -750,6 +764,10 @@ static int audit_compare_rule(struct audit_krule *a, struct audit_krule *b)
> > > >                         if (!gid_eq(a->fields[i].gid, b->fields[i].gid))
> > > >                                 return 1;
> > > >                         break;
> > > > +               case AUDIT_CONTID:
> > > > +                       if (a->fields[i].val64 != b->fields[i].val64)
> > > > +                               return 1;
> > > > +                       break;
> > > >                 default:
> > > >                         if (a->fields[i].val != b->fields[i].val)
> > > >                                 return 1;
> > > > @@ -1206,6 +1224,31 @@ int audit_comparator(u32 left, u32 op, u32 right)
> > > >         }
> > > >  }
> > > >
> > > > +int audit_comparator64(u64 left, u32 op, u64 right)
> > > > +{
> > > > +       switch (op) {
> > > > +       case Audit_equal:
> > > > +               return (left == right);
> > > > +       case Audit_not_equal:
> > > > +               return (left != right);
> > > > +       case Audit_lt:
> > > > +               return (left < right);
> > > > +       case Audit_le:
> > > > +               return (left <= right);
> > > > +       case Audit_gt:
> > > > +               return (left > right);
> > > > +       case Audit_ge:
> > > > +               return (left >= right);
> > > > +       case Audit_bitmask:
> > > > +               return (left & right);
> > > > +       case Audit_bittest:
> > > > +               return ((left & right) == right);
> > > > +       default:
> > > > +               BUG();
> > > > +               return 0;
> > > > +       }
> > > > +}
> > > > +
> > > >  int audit_uid_comparator(kuid_t left, u32 op, kuid_t right)
> > > >  {
> > > >         switch (op) {
> > > > @@ -1344,6 +1387,10 @@ int audit_filter(int msgtype, unsigned int listtype)
> > > >                                 result = audit_comparator(audit_loginuid_set(current),
> > > >                                                           f->op, f->val);
> > > >                                 break;
> > > > +                       case AUDIT_CONTID:
> > > > +                               result = audit_comparator64(audit_get_contid(current),
> > > > +                                                             f->op, f->val64);
> > > > +                               break;
> > > >                         case AUDIT_MSGTYPE:
> > > >                                 result = audit_comparator(msgtype, f->op, f->val);
> > > >                                 break;
> > > > diff --git a/kernel/auditsc.c b/kernel/auditsc.c
> > > > index aa5d13b4fbbb..2d74238e9638 100644
> > > > --- a/kernel/auditsc.c
> > > > +++ b/kernel/auditsc.c
> > > > @@ -616,6 +616,9 @@ static int audit_filter_rules(struct task_struct *tsk,
> > > >                 case AUDIT_LOGINUID_SET:
> > > >                         result = audit_comparator(audit_loginuid_set(tsk), f->op, f->val);
> > > >                         break;
> > > > +               case AUDIT_CONTID:
> > > > +                       result = audit_comparator64(audit_get_contid(tsk), f->op, f->val64);
> > > > +                       break;
> > > >                 case AUDIT_SUBJ_USER:
> > > >                 case AUDIT_SUBJ_ROLE:
> > > >                 case AUDIT_SUBJ_TYPE:
> > >
> > > Ondrej Mosnacek <omosnace at redhat dot com>
> >
> > - RGB
> >
> > Richard Guy Briggs <rgb@redhat.com>
> 
> Ondrej Mosnacek <omosnace at redhat dot com>

- RGB

--
Richard Guy Briggs <rgb@redhat.com>
Sr. S/W Engineer, Kernel Security, Base Operating Systems
Remote, Ottawa, Red Hat Canada
IRC: rgb, SunRaycer
Voice: +1.647.777.2635, Internal: (81) 32635

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH ghak90 V5 04/10] audit: log container info of syscalls
  2019-03-27 21:01   ` Ondrej Mosnacek
@ 2019-03-27 22:10     ` Richard Guy Briggs
  0 siblings, 0 replies; 64+ messages in thread
From: Richard Guy Briggs @ 2019-03-27 22:10 UTC (permalink / raw)
  To: Ondrej Mosnacek
  Cc: nhorman, linux-api, containers, LKML, David Howells,
	Linux-Audit Mailing List, netfilter-devel, Eric W . Biederman,
	Simo Sorce, netdev, linux-fsdevel, Eric Paris, Serge E. Hallyn

On 2019-03-27 22:01, Ondrej Mosnacek wrote:
> On Fri, Mar 15, 2019 at 7:34 PM Richard Guy Briggs <rgb@redhat.com> wrote:
> > Create a new audit record AUDIT_CONTAINER_ID to document the audit
> > container identifier of a process if it is present.
> >
> > Called from audit_log_exit(), syscalls are covered.
> >
> > A sample raw event:
> > type=SYSCALL msg=audit(1519924845.499:257): arch=c000003e syscall=257 success=yes exit=3 a0=ffffff9c a1=56374e1cef30 a2=241 a3=1b6 items=2 ppid=606 pid=635 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts0 ses=3 comm="bash" exe="/usr/bin/bash" subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 key="tmpcontainerid"
> > type=CWD msg=audit(1519924845.499:257): cwd="/root"
> > type=PATH msg=audit(1519924845.499:257): item=0 name="/tmp/" inode=13863 dev=00:27 mode=041777 ouid=0 ogid=0 rdev=00:00 obj=system_u:object_r:tmp_t:s0 nametype= PARENT cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0
> > type=PATH msg=audit(1519924845.499:257): item=1 name="/tmp/tmpcontainerid" inode=17729 dev=00:27 mode=0100644 ouid=0 ogid=0 rdev=00:00 obj=unconfined_u:object_r:user_tmp_t:s0 nametype=CREATE cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0
> > type=PROCTITLE msg=audit(1519924845.499:257): proctitle=62617368002D6300736C65657020313B206563686F2074657374203E202F746D702F746D70636F6E7461696E65726964
> > type=CONTAINER_ID msg=audit(1519924845.499:257): contid=123458
> >
> > See: https://github.com/linux-audit/audit-kernel/issues/90
> > See: https://github.com/linux-audit/audit-userspace/issues/51
> > See: https://github.com/linux-audit/audit-testsuite/issues/64
> > See: https://github.com/linux-audit/audit-kernel/wiki/RFE-Audit-Container-ID
> > Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> > Acked-by: Serge Hallyn <serge@hallyn.com>
> > Acked-by: Steve Grubb <sgrubb@redhat.com>
> > Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> 
> Barring one minor nit below,
> 
> Reviewed-by: Ondrej Mosnacek <omosnace@redhat.com>
> 
> > ---
> >  include/linux/audit.h      |  5 +++++
> >  include/uapi/linux/audit.h |  1 +
> >  kernel/audit.c             | 21 +++++++++++++++++++++
> >  kernel/auditsc.c           |  2 ++
> >  4 files changed, 29 insertions(+)
> >
> > diff --git a/include/linux/audit.h b/include/linux/audit.h
> > index 301337776193..43438192ca2a 100644
> > --- a/include/linux/audit.h
> > +++ b/include/linux/audit.h
> > @@ -199,6 +199,8 @@ static inline u64 audit_get_contid(struct task_struct *tsk)
> >         return tsk->audit->contid;
> >  }
> >
> > +extern void audit_log_contid(struct audit_context *context, u64 contid);
> > +
> >  extern u32 audit_enabled;
> >  #else /* CONFIG_AUDIT */
> >  static inline int audit_alloc(struct task_struct *task)
> > @@ -265,6 +267,9 @@ static inline u64 audit_get_contid(struct task_struct *tsk)
> >         return AUDIT_CID_UNSET;
> >  }
> >
> > +static inline void audit_log_contid(struct audit_context *context, u64 contid)
> > +{ }
> > +
> >  #define audit_enabled AUDIT_OFF
> >  #endif /* CONFIG_AUDIT */
> >
> > diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h
> > index d475cf3b4d7f..a6383e28b2c8 100644
> > --- a/include/uapi/linux/audit.h
> > +++ b/include/uapi/linux/audit.h
> > @@ -115,6 +115,7 @@
> >  #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_CONTAINER_ID     1332    /* Container ID */
> >
> >  #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 b5c702abeb42..8cc0e88d7f2a 100644
> > --- a/kernel/audit.c
> > +++ b/kernel/audit.c
> > @@ -2127,6 +2127,27 @@ void audit_log_session_info(struct audit_buffer *ab)
> >         audit_log_format(ab, "auid=%u ses=%u", auid, sessionid);
> >  }
> >
> > +/*
> > + * audit_log_contid - report container info
> > + * @context: task or local context for record
> > + * @contid: container ID to report
> > + */
> > +void audit_log_contid(struct audit_context *context, u64 contid)
> > +{
> > +       struct audit_buffer *ab;
> > +
> > +       if (!audit_contid_valid(contid))
> > +               return;
> > +       /* Generate AUDIT_CONTAINER_ID record with container ID */
> > +       ab = audit_log_start(context, GFP_KERNEL, AUDIT_CONTAINER_ID);
> > +       if (!ab)
> > +               return;
> > +       audit_log_format(ab, "contid=%llu", contid);
> 
> Just realized that you *might* get a compiler/static checker warning
> since u64 could technically be something else than unsigned long long
> on some arches... maybe this is not case in the kernel, but might be
> safer to cast it to unsigned long long before passing to
> audit_log_format(). Possibly there are similar occurrences in previous
> (later) patches that I didn't (won't) notice.

Ok, since it is guaranteed to be at least 64 bits, a cast won't truncate
it.

> > +       audit_log_end(ab);
> > +       return;
> > +}
> > +EXPORT_SYMBOL(audit_log_contid);
> > +
> >  void audit_log_key(struct audit_buffer *ab, char *key)
> >  {
> >         audit_log_format(ab, " key=");
> > diff --git a/kernel/auditsc.c b/kernel/auditsc.c
> > index 8090eff7868d..a8c8b44b954d 100644
> > --- a/kernel/auditsc.c
> > +++ b/kernel/auditsc.c
> > @@ -1548,6 +1548,8 @@ static void audit_log_exit(void)
> >
> >         audit_log_proctitle();
> >
> > +       audit_log_contid(context, audit_get_contid(current));
> > +
> >         /* Send end of event record to help user space know we are finished */
> >         ab = audit_log_start(context, GFP_KERNEL, AUDIT_EOE);
> >         if (ab)
> 
> Ondrej Mosnacek <omosnace at redhat dot com>

- RGB

--
Richard Guy Briggs <rgb@redhat.com>
Sr. S/W Engineer, Kernel Security, Base Operating Systems
Remote, Ottawa, Red Hat Canada
IRC: rgb, SunRaycer
Voice: +1.647.777.2635, Internal: (81) 32635

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH ghak90 V5 09/10] audit: add support for containerid to network namespaces
  2019-03-15 18:29 ` [PATCH ghak90 V5 09/10] audit: add support for containerid to network namespaces Richard Guy Briggs
  2019-03-18 20:56   ` Neil Horman
@ 2019-03-27 22:42   ` Ondrej Mosnacek
  2019-03-28  1:12     ` Richard Guy Briggs
  2019-04-01 14:50   ` Paul Moore
  2 siblings, 1 reply; 64+ messages in thread
From: Ondrej Mosnacek @ 2019-03-27 22:42 UTC (permalink / raw)
  To: Richard Guy Briggs
  Cc: containers, linux-api, Linux-Audit Mailing List, linux-fsdevel,
	LKML, netdev, netfilter-devel, Paul Moore, Steve Grubb,
	David Howells, Simo Sorce, Eric Paris, Serge E. Hallyn,
	Eric W . Biederman, nhorman

On Fri, Mar 15, 2019 at 7:35 PM Richard Guy Briggs <rgb@redhat.com> wrote:
> Audit events could happen in a network namespace outside of a task
> context due to packets received from the net that trigger an auditing
> rule prior to being associated with a running task.  The network
> namespace could be in use by multiple containers by association to the
> tasks in that network namespace.  We still want a way to attribute
> these events to any potential containers.  Keep a list per network
> namespace to track these audit container identifiiers.
>
> Add/increment the audit container identifier on:
> - initial setting of the audit container identifier via /proc
> - clone/fork call that inherits an audit container identifier
> - unshare call that inherits an audit container identifier
> - setns call that inherits an audit container identifier
> Delete/decrement the audit container identifier on:
> - an inherited audit container identifier dropped when child set
> - process exit
> - unshare call that drops a net namespace
> - setns call that drops a net namespace
>
> See: https://github.com/linux-audit/audit-kernel/issues/92
> See: https://github.com/linux-audit/audit-testsuite/issues/64
> See: https://github.com/linux-audit/audit-kernel/wiki/RFE-Audit-Container-ID
> Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> ---
>  include/linux/audit.h | 19 ++++++++++++
>  kernel/audit.c        | 86 +++++++++++++++++++++++++++++++++++++++++++++++++--
>  kernel/nsproxy.c      |  4 +++
>  3 files changed, 106 insertions(+), 3 deletions(-)
>
> diff --git a/include/linux/audit.h b/include/linux/audit.h
> index fa19fa408931..70255c2dfb9f 100644
> --- a/include/linux/audit.h
> +++ b/include/linux/audit.h
> @@ -27,6 +27,7 @@
>  #include <linux/ptrace.h>
>  #include <linux/namei.h>  /* LOOKUP_* */
>  #include <uapi/linux/audit.h>
> +#include <linux/refcount.h>
>
>  #define AUDIT_INO_UNSET ((unsigned long)-1)
>  #define AUDIT_DEV_UNSET ((dev_t)-1)
> @@ -99,6 +100,13 @@ struct audit_task_info {
>
>  extern struct audit_task_info init_struct_audit;
>
> +struct audit_contid {
> +       struct list_head        list;
> +       u64                     id;
> +       refcount_t              refcount;

Hm, since we only ever touch the refcount under a spinlock, I wonder
if we could just make it a regular unsigned int (we don't need the
atomicity guarantees). OTOH, refcount_t comes with some extra overflow
checking, so it's probably better to leave it as is...

> +       struct rcu_head         rcu;
> +};
> +
>  extern int is_audit_feature_set(int which);
>
>  extern int __init audit_register_class(int class, unsigned *list);
> @@ -202,6 +210,10 @@ static inline u64 audit_get_contid(struct task_struct *tsk)
>  }
>
>  extern void audit_log_contid(struct audit_context *context, u64 contid);
> +extern void audit_netns_contid_add(struct net *net, u64 contid);
> +extern void audit_netns_contid_del(struct net *net, u64 contid);
> +extern void audit_switch_task_namespaces(struct nsproxy *ns,
> +                                        struct task_struct *p);
>
>  extern u32 audit_enabled;
>  #else /* CONFIG_AUDIT */
> @@ -271,6 +283,13 @@ static inline u64 audit_get_contid(struct task_struct *tsk)
>
>  static inline void audit_log_contid(struct audit_context *context, u64 contid)
>  { }
> +static inline void audit_netns_contid_add(struct net *net, u64 contid)
> +{ }
> +static inline void audit_netns_contid_del(struct net *net, u64 contid)
> +{ }
> +static inline void audit_switch_task_namespaces(struct nsproxy *ns,
> +                                               struct task_struct *p)
> +{ }
>
>  #define audit_enabled AUDIT_OFF
>  #endif /* CONFIG_AUDIT */
> diff --git a/kernel/audit.c b/kernel/audit.c
> index cf448599ef34..7fa3194f5342 100644
> --- a/kernel/audit.c
> +++ b/kernel/audit.c
> @@ -72,6 +72,7 @@
>  #include <linux/freezer.h>
>  #include <linux/pid_namespace.h>
>  #include <net/netns/generic.h>
> +#include <net/net_namespace.h>
>
>  #include "audit.h"
>
> @@ -99,9 +100,13 @@
>  /**
>   * struct audit_net - audit private network namespace data
>   * @sk: communication socket
> + * @contid_list: audit container identifier list
> + * @contid_list_lock audit container identifier list lock
>   */
>  struct audit_net {
>         struct sock *sk;
> +       struct list_head contid_list;
> +       spinlock_t contid_list_lock;
>  };
>
>  /**
> @@ -275,8 +280,11 @@ struct audit_task_info init_struct_audit = {
>  void audit_free(struct task_struct *tsk)
>  {
>         struct audit_task_info *info = tsk->audit;
> +       struct nsproxy *ns = tsk->nsproxy;
>
>         audit_free_syscall(tsk);
> +       if (ns)
> +               audit_netns_contid_del(ns->net_ns, audit_get_contid(tsk));
>         /* Freeing the audit_task_info struct must be performed after
>          * audit_log_exit() due to need for loginuid and sessionid.
>          */
> @@ -376,6 +384,73 @@ static struct sock *audit_get_sk(const struct net *net)
>         return aunet->sk;
>  }
>
> +void audit_netns_contid_add(struct net *net, u64 contid)
> +{
> +       struct audit_net *aunet = net_generic(net, audit_net_id);
> +       struct list_head *contid_list = &aunet->contid_list;
> +       struct audit_contid *cont;
> +
> +       if (!audit_contid_valid(contid))
> +               return;
> +       if (!aunet)
> +               return;
> +       spin_lock(&aunet->contid_list_lock);
> +       if (!list_empty(contid_list))
> +               list_for_each_entry_rcu(cont, contid_list, list)
> +                       if (cont->id == contid) {
> +                               refcount_inc(&cont->refcount);
> +                               goto out;
> +                       }
> +       cont = kmalloc(sizeof(struct audit_contid), GFP_ATOMIC);
> +       if (cont) {
> +               INIT_LIST_HEAD(&cont->list);
> +               cont->id = contid;
> +               refcount_set(&cont->refcount, 1);
> +               list_add_rcu(&cont->list, contid_list);
> +       }
> +out:
> +       spin_unlock(&aunet->contid_list_lock);
> +}
> +
> +void audit_netns_contid_del(struct net *net, u64 contid)
> +{
> +       struct audit_net *aunet;
> +       struct list_head *contid_list;
> +       struct audit_contid *cont = NULL;
> +
> +       if (!net)
> +               return;
> +       if (!audit_contid_valid(contid))
> +               return;
> +       aunet = net_generic(net, audit_net_id);
> +       if (!aunet)
> +               return;
> +       contid_list = &aunet->contid_list;
> +       spin_lock(&aunet->contid_list_lock);
> +       if (!list_empty(contid_list))
> +               list_for_each_entry_rcu(cont, contid_list, list)
> +                       if (cont->id == contid) {
> +                               if (refcount_dec_and_test(&cont->refcount)) {
> +                                       list_del_rcu(&cont->list);
> +                                       kfree_rcu(cont, rcu);
> +                               }
> +                               break;
> +                       }
> +       spin_unlock(&aunet->contid_list_lock);
> +}
> +
> +void audit_switch_task_namespaces(struct nsproxy *ns, struct task_struct *p)
> +{
> +       u64 contid = audit_get_contid(p);
> +       struct nsproxy *new = p->nsproxy;
> +
> +       if (!audit_contid_valid(contid))
> +               return;
> +       audit_netns_contid_del(ns->net_ns, contid);
> +       if (new)
> +               audit_netns_contid_add(new->net_ns, contid);
> +}
> +
>  void audit_panic(const char *message)
>  {
>         switch (audit_failure) {
> @@ -1619,7 +1694,6 @@ static int __net_init audit_net_init(struct net *net)
>                 .flags  = NL_CFG_F_NONROOT_RECV,
>                 .groups = AUDIT_NLGRP_MAX,
>         };
> -
>         struct audit_net *aunet = net_generic(net, audit_net_id);
>
>         aunet->sk = netlink_kernel_create(net, NETLINK_AUDIT, &cfg);
> @@ -1628,7 +1702,8 @@ static int __net_init audit_net_init(struct net *net)
>                 return -ENOMEM;
>         }
>         aunet->sk->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT;
> -
> +       INIT_LIST_HEAD(&aunet->contid_list);
> +       spin_lock_init(&aunet->contid_list_lock);
>         return 0;
>  }
>
> @@ -2380,6 +2455,7 @@ int audit_set_contid(struct task_struct *task, u64 contid)
>         uid_t uid;
>         struct tty_struct *tty;
>         char comm[sizeof(current->comm)];
> +       struct net *net = task->nsproxy->net_ns;
>
>         task_lock(task);
>         /* Can't set if audit disabled */
> @@ -2401,8 +2477,12 @@ int audit_set_contid(struct task_struct *task, u64 contid)
>         else if (!(thread_group_leader(task) && thread_group_empty(task)))
>                 rc = -EALREADY;
>         read_unlock(&tasklist_lock);
> -       if (!rc)
> +       if (!rc) {
> +               if (audit_contid_valid(oldcontid))
> +                       audit_netns_contid_del(net, oldcontid);
>                 task->audit->contid = contid;
> +               audit_netns_contid_add(net, contid);
> +       }
>         task_unlock(task);
>
>         if (!audit_enabled)
> diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c
> index f6c5d330059a..718b1201ae70 100644
> --- a/kernel/nsproxy.c
> +++ b/kernel/nsproxy.c
> @@ -27,6 +27,7 @@
>  #include <linux/syscalls.h>
>  #include <linux/cgroup.h>
>  #include <linux/perf_event.h>
> +#include <linux/audit.h>
>
>  static struct kmem_cache *nsproxy_cachep;
>
> @@ -140,6 +141,7 @@ int copy_namespaces(unsigned long flags, struct task_struct *tsk)
>         struct nsproxy *old_ns = tsk->nsproxy;
>         struct user_namespace *user_ns = task_cred_xxx(tsk, user_ns);
>         struct nsproxy *new_ns;
> +       u64 contid = audit_get_contid(tsk);
>
>         if (likely(!(flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC |
>                               CLONE_NEWPID | CLONE_NEWNET |
> @@ -167,6 +169,7 @@ int copy_namespaces(unsigned long flags, struct task_struct *tsk)
>                 return  PTR_ERR(new_ns);
>
>         tsk->nsproxy = new_ns;
> +       audit_netns_contid_add(new_ns->net_ns, contid);
>         return 0;
>  }
>
> @@ -224,6 +227,7 @@ void switch_task_namespaces(struct task_struct *p, struct nsproxy *new)
>         ns = p->nsproxy;
>         p->nsproxy = new;
>         task_unlock(p);
> +       audit_switch_task_namespaces(ns, p);

Since we call audit_switch_task_namespaces() after task_unlock(),
could there be a potential race condition? I'm not going to dive too
much into this now, because it's getting late here, but on first look
it seems like p->nsproxy could change under our hands before we fetch
it in audit_switch_task_namespaces()...

>
>         if (ns && atomic_dec_and_test(&ns->count))
>                 free_nsproxy(ns);
> --
> 1.8.3.1
>

-- 
Ondrej Mosnacek <omosnace at redhat dot com>
Software Engineer, Security Technologies
Red Hat, Inc.

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH ghak90 V5 10/10] audit: NETFILTER_PKT: record each container ID associated with a netNS
  2019-03-15 18:29 ` [PATCH ghak90 V5 10/10] audit: NETFILTER_PKT: record each container ID associated with a netNS Richard Guy Briggs
  2019-03-18 20:58   ` Neil Horman
@ 2019-03-27 22:52   ` Ondrej Mosnacek
  2019-04-01 14:50   ` Paul Moore
  2 siblings, 0 replies; 64+ messages in thread
From: Ondrej Mosnacek @ 2019-03-27 22:52 UTC (permalink / raw)
  To: Richard Guy Briggs
  Cc: containers, linux-api, Linux-Audit Mailing List, linux-fsdevel,
	LKML, netdev, netfilter-devel, Paul Moore, Steve Grubb,
	David Howells, Simo Sorce, Eric Paris, Serge E. Hallyn,
	Eric W . Biederman, nhorman

On Fri, Mar 15, 2019 at 7:35 PM Richard Guy Briggs <rgb@redhat.com> wrote:
> Add audit container identifier auxiliary record(s) to NETFILTER_PKT
> event standalone records.  Iterate through all potential audit container
> identifiers associated with a network namespace.
>
> Signed-off-by: Richard Guy Briggs <rgb@redhat.com>

Reviewed-by: Ondrej Mosnacek <omosnace@redhat.com>

(Just note another "%llu"/u64 occurence, in case you plan to add the casts.)

> ---
>  include/linux/audit.h    |  5 +++++
>  kernel/audit.c           | 41 +++++++++++++++++++++++++++++++++++++++++
>  net/netfilter/nft_log.c  | 11 +++++++++--
>  net/netfilter/xt_AUDIT.c | 11 +++++++++--
>  4 files changed, 64 insertions(+), 4 deletions(-)
>
> diff --git a/include/linux/audit.h b/include/linux/audit.h
> index 70255c2dfb9f..723e2d020228 100644
> --- a/include/linux/audit.h
> +++ b/include/linux/audit.h
> @@ -214,6 +214,8 @@ static inline u64 audit_get_contid(struct task_struct *tsk)
>  extern void audit_netns_contid_del(struct net *net, u64 contid);
>  extern void audit_switch_task_namespaces(struct nsproxy *ns,
>                                          struct task_struct *p);
> +extern void audit_log_netns_contid_list(struct net *net,
> +                                       struct audit_context *context);
>
>  extern u32 audit_enabled;
>  #else /* CONFIG_AUDIT */
> @@ -290,6 +292,9 @@ static inline void audit_netns_contid_del(struct net *net, u64 contid)
>  static inline void audit_switch_task_namespaces(struct nsproxy *ns,
>                                                 struct task_struct *p)
>  { }
> +static inline void audit_log_netns_contid_list(struct net *net,
> +                                              struct audit_context *context)
> +{ }
>
>  #define audit_enabled AUDIT_OFF
>  #endif /* CONFIG_AUDIT */
> diff --git a/kernel/audit.c b/kernel/audit.c
> index 7fa3194f5342..80ed323feeb5 100644
> --- a/kernel/audit.c
> +++ b/kernel/audit.c
> @@ -451,6 +451,47 @@ void audit_switch_task_namespaces(struct nsproxy *ns, struct task_struct *p)
>                 audit_netns_contid_add(new->net_ns, contid);
>  }
>
> +/**
> + * audit_log_netns_contid_list - List contids for the given network namespace
> + * @net: the network namespace of interest
> + * @context: the audit context to use
> + *
> + * Description:
> + * Issues a CONTAINER_ID record with a CSV list of contids associated
> + * with a network namespace to accompany a NETFILTER_PKT record.
> + */
> +void audit_log_netns_contid_list(struct net *net, struct audit_context *context)
> +{
> +       struct audit_buffer *ab = NULL;
> +       struct audit_contid *cont;
> +       bool first = true;
> +       struct audit_net *aunet;
> +
> +       /* Generate AUDIT_CONTAINER_ID record with container ID CSV list */
> +       rcu_read_lock();
> +       aunet = net_generic(net, audit_net_id);
> +       if (!aunet)
> +               goto out;
> +       list_for_each_entry_rcu(cont, &aunet->contid_list, list) {
> +               if (first) {
> +                       ab = audit_log_start(context, GFP_ATOMIC,
> +                                            AUDIT_CONTAINER_ID);
> +                       if (!ab) {
> +                               audit_log_lost("out of memory in audit_log_netns_contid_list");
> +                               goto out;
> +                       }
> +                       audit_log_format(ab, "contid=");
> +               } else
> +                       audit_log_format(ab, ",");
> +               audit_log_format(ab, "%llu", cont->id);
> +               first = false;
> +       }
> +       audit_log_end(ab);
> +out:
> +       rcu_read_unlock();
> +}
> +EXPORT_SYMBOL(audit_log_netns_contid_list);
> +
>  void audit_panic(const char *message)
>  {
>         switch (audit_failure) {
> diff --git a/net/netfilter/nft_log.c b/net/netfilter/nft_log.c
> index 655187bed5d8..bdb1ec2368a7 100644
> --- a/net/netfilter/nft_log.c
> +++ b/net/netfilter/nft_log.c
> @@ -69,13 +69,16 @@ static void nft_log_eval_audit(const struct nft_pktinfo *pkt)
>         struct sk_buff *skb = pkt->skb;
>         struct audit_buffer *ab;
>         int fam = -1;
> +       struct audit_context *context;
> +       struct net *net;
>
>         if (!audit_enabled)
>                 return;
>
> -       ab = audit_log_start(NULL, GFP_ATOMIC, AUDIT_NETFILTER_PKT);
> +       context = audit_alloc_local(GFP_ATOMIC);
> +       ab = audit_log_start(context, GFP_ATOMIC, AUDIT_NETFILTER_PKT);
>         if (!ab)
> -               return;
> +               goto errout;
>
>         audit_log_format(ab, "mark=%#x", skb->mark);
>
> @@ -102,6 +105,10 @@ static void nft_log_eval_audit(const struct nft_pktinfo *pkt)
>                 audit_log_format(ab, " saddr=? daddr=? proto=-1");
>
>         audit_log_end(ab);
> +       net = xt_net(&pkt->xt);
> +       audit_log_netns_contid_list(net, context);
> +errout:
> +       audit_free_context(context);
>  }
>
>  static void nft_log_eval(const struct nft_expr *expr,
> diff --git a/net/netfilter/xt_AUDIT.c b/net/netfilter/xt_AUDIT.c
> index af883f1b64f9..a3e547435f13 100644
> --- a/net/netfilter/xt_AUDIT.c
> +++ b/net/netfilter/xt_AUDIT.c
> @@ -71,10 +71,13 @@ static bool audit_ip6(struct audit_buffer *ab, struct sk_buff *skb)
>  {
>         struct audit_buffer *ab;
>         int fam = -1;
> +       struct audit_context *context;
> +       struct net *net;
>
>         if (audit_enabled == AUDIT_OFF)
> -               goto errout;
> -       ab = audit_log_start(NULL, GFP_ATOMIC, AUDIT_NETFILTER_PKT);
> +               goto out;
> +       context = audit_alloc_local(GFP_ATOMIC);
> +       ab = audit_log_start(context, GFP_ATOMIC, AUDIT_NETFILTER_PKT);
>         if (ab == NULL)
>                 goto errout;
>
> @@ -104,7 +107,11 @@ static bool audit_ip6(struct audit_buffer *ab, struct sk_buff *skb)
>
>         audit_log_end(ab);
>
> +       net = xt_net(par);
> +       audit_log_netns_contid_list(net, context);
>  errout:
> +       audit_free_context(context);
> +out:
>         return XT_CONTINUE;
>  }
>
> --
> 1.8.3.1
>


-- 
Ondrej Mosnacek <omosnace at redhat dot com>
Software Engineer, Security Technologies
Red Hat, Inc.

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH ghak90 V5 09/10] audit: add support for containerid to network namespaces
  2019-03-27 22:42   ` Ondrej Mosnacek
@ 2019-03-28  1:12     ` Richard Guy Briggs
  2019-03-28  8:01       ` Ondrej Mosnacek
                         ` (2 more replies)
  0 siblings, 3 replies; 64+ messages in thread
From: Richard Guy Briggs @ 2019-03-28  1:12 UTC (permalink / raw)
  To: Ondrej Mosnacek
  Cc: nhorman, linux-api, containers, LKML, David Howells,
	Linux-Audit Mailing List, netfilter-devel, Eric W . Biederman,
	Simo Sorce, netdev, linux-fsdevel, Eric Paris, Serge E. Hallyn

On 2019-03-27 23:42, Ondrej Mosnacek wrote:
> On Fri, Mar 15, 2019 at 7:35 PM Richard Guy Briggs <rgb@redhat.com> wrote:
> > Audit events could happen in a network namespace outside of a task
> > context due to packets received from the net that trigger an auditing
> > rule prior to being associated with a running task.  The network
> > namespace could be in use by multiple containers by association to the
> > tasks in that network namespace.  We still want a way to attribute
> > these events to any potential containers.  Keep a list per network
> > namespace to track these audit container identifiiers.
> >
> > Add/increment the audit container identifier on:
> > - initial setting of the audit container identifier via /proc
> > - clone/fork call that inherits an audit container identifier
> > - unshare call that inherits an audit container identifier
> > - setns call that inherits an audit container identifier
> > Delete/decrement the audit container identifier on:
> > - an inherited audit container identifier dropped when child set
> > - process exit
> > - unshare call that drops a net namespace
> > - setns call that drops a net namespace
> >
> > See: https://github.com/linux-audit/audit-kernel/issues/92
> > See: https://github.com/linux-audit/audit-testsuite/issues/64
> > See: https://github.com/linux-audit/audit-kernel/wiki/RFE-Audit-Container-ID
> > Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> > ---
> >  include/linux/audit.h | 19 ++++++++++++
> >  kernel/audit.c        | 86 +++++++++++++++++++++++++++++++++++++++++++++++++--
> >  kernel/nsproxy.c      |  4 +++
> >  3 files changed, 106 insertions(+), 3 deletions(-)
> >
> > diff --git a/include/linux/audit.h b/include/linux/audit.h
> > index fa19fa408931..70255c2dfb9f 100644
> > --- a/include/linux/audit.h
> > +++ b/include/linux/audit.h
> > @@ -27,6 +27,7 @@
> >  #include <linux/ptrace.h>
> >  #include <linux/namei.h>  /* LOOKUP_* */
> >  #include <uapi/linux/audit.h>
> > +#include <linux/refcount.h>
> >
> >  #define AUDIT_INO_UNSET ((unsigned long)-1)
> >  #define AUDIT_DEV_UNSET ((dev_t)-1)
> > @@ -99,6 +100,13 @@ struct audit_task_info {
> >
> >  extern struct audit_task_info init_struct_audit;
> >
> > +struct audit_contid {
> > +       struct list_head        list;
> > +       u64                     id;
> > +       refcount_t              refcount;
> 
> Hm, since we only ever touch the refcount under a spinlock, I wonder
> if we could just make it a regular unsigned int (we don't need the
> atomicity guarantees). OTOH, refcount_t comes with some extra overflow
> checking, so it's probably better to leave it as is...

Since the update is done using rcu-safe methods, do we even need the
spin_lock?  Neil?  Paul?

> > +       struct rcu_head         rcu;
> > +};
> > +
> >  extern int is_audit_feature_set(int which);
> >
> >  extern int __init audit_register_class(int class, unsigned *list);
> > @@ -202,6 +210,10 @@ static inline u64 audit_get_contid(struct task_struct *tsk)
> >  }
> >
> >  extern void audit_log_contid(struct audit_context *context, u64 contid);
> > +extern void audit_netns_contid_add(struct net *net, u64 contid);
> > +extern void audit_netns_contid_del(struct net *net, u64 contid);
> > +extern void audit_switch_task_namespaces(struct nsproxy *ns,
> > +                                        struct task_struct *p);
> >
> >  extern u32 audit_enabled;
> >  #else /* CONFIG_AUDIT */
> > @@ -271,6 +283,13 @@ static inline u64 audit_get_contid(struct task_struct *tsk)
> >
> >  static inline void audit_log_contid(struct audit_context *context, u64 contid)
> >  { }
> > +static inline void audit_netns_contid_add(struct net *net, u64 contid)
> > +{ }
> > +static inline void audit_netns_contid_del(struct net *net, u64 contid)
> > +{ }
> > +static inline void audit_switch_task_namespaces(struct nsproxy *ns,
> > +                                               struct task_struct *p)
> > +{ }
> >
> >  #define audit_enabled AUDIT_OFF
> >  #endif /* CONFIG_AUDIT */
> > diff --git a/kernel/audit.c b/kernel/audit.c
> > index cf448599ef34..7fa3194f5342 100644
> > --- a/kernel/audit.c
> > +++ b/kernel/audit.c
> > @@ -72,6 +72,7 @@
> >  #include <linux/freezer.h>
> >  #include <linux/pid_namespace.h>
> >  #include <net/netns/generic.h>
> > +#include <net/net_namespace.h>
> >
> >  #include "audit.h"
> >
> > @@ -99,9 +100,13 @@
> >  /**
> >   * struct audit_net - audit private network namespace data
> >   * @sk: communication socket
> > + * @contid_list: audit container identifier list
> > + * @contid_list_lock audit container identifier list lock
> >   */
> >  struct audit_net {
> >         struct sock *sk;
> > +       struct list_head contid_list;
> > +       spinlock_t contid_list_lock;
> >  };
> >
> >  /**
> > @@ -275,8 +280,11 @@ struct audit_task_info init_struct_audit = {
> >  void audit_free(struct task_struct *tsk)
> >  {
> >         struct audit_task_info *info = tsk->audit;
> > +       struct nsproxy *ns = tsk->nsproxy;
> >
> >         audit_free_syscall(tsk);
> > +       if (ns)
> > +               audit_netns_contid_del(ns->net_ns, audit_get_contid(tsk));
> >         /* Freeing the audit_task_info struct must be performed after
> >          * audit_log_exit() due to need for loginuid and sessionid.
> >          */
> > @@ -376,6 +384,73 @@ static struct sock *audit_get_sk(const struct net *net)
> >         return aunet->sk;
> >  }
> >
> > +void audit_netns_contid_add(struct net *net, u64 contid)
> > +{
> > +       struct audit_net *aunet = net_generic(net, audit_net_id);
> > +       struct list_head *contid_list = &aunet->contid_list;
> > +       struct audit_contid *cont;
> > +
> > +       if (!audit_contid_valid(contid))
> > +               return;
> > +       if (!aunet)
> > +               return;
> > +       spin_lock(&aunet->contid_list_lock);
> > +       if (!list_empty(contid_list))
> > +               list_for_each_entry_rcu(cont, contid_list, list)
> > +                       if (cont->id == contid) {
> > +                               refcount_inc(&cont->refcount);
> > +                               goto out;
> > +                       }
> > +       cont = kmalloc(sizeof(struct audit_contid), GFP_ATOMIC);
> > +       if (cont) {
> > +               INIT_LIST_HEAD(&cont->list);
> > +               cont->id = contid;
> > +               refcount_set(&cont->refcount, 1);
> > +               list_add_rcu(&cont->list, contid_list);
> > +       }
> > +out:
> > +       spin_unlock(&aunet->contid_list_lock);
> > +}
> > +
> > +void audit_netns_contid_del(struct net *net, u64 contid)
> > +{
> > +       struct audit_net *aunet;
> > +       struct list_head *contid_list;
> > +       struct audit_contid *cont = NULL;
> > +
> > +       if (!net)
> > +               return;
> > +       if (!audit_contid_valid(contid))
> > +               return;
> > +       aunet = net_generic(net, audit_net_id);
> > +       if (!aunet)
> > +               return;
> > +       contid_list = &aunet->contid_list;
> > +       spin_lock(&aunet->contid_list_lock);
> > +       if (!list_empty(contid_list))
> > +               list_for_each_entry_rcu(cont, contid_list, list)
> > +                       if (cont->id == contid) {
> > +                               if (refcount_dec_and_test(&cont->refcount)) {
> > +                                       list_del_rcu(&cont->list);
> > +                                       kfree_rcu(cont, rcu);
> > +                               }
> > +                               break;
> > +                       }
> > +       spin_unlock(&aunet->contid_list_lock);
> > +}
> > +
> > +void audit_switch_task_namespaces(struct nsproxy *ns, struct task_struct *p)
> > +{
> > +       u64 contid = audit_get_contid(p);
> > +       struct nsproxy *new = p->nsproxy;
> > +
> > +       if (!audit_contid_valid(contid))
> > +               return;
> > +       audit_netns_contid_del(ns->net_ns, contid);
> > +       if (new)
> > +               audit_netns_contid_add(new->net_ns, contid);
> > +}
> > +
> >  void audit_panic(const char *message)
> >  {
> >         switch (audit_failure) {
> > @@ -1619,7 +1694,6 @@ static int __net_init audit_net_init(struct net *net)
> >                 .flags  = NL_CFG_F_NONROOT_RECV,
> >                 .groups = AUDIT_NLGRP_MAX,
> >         };
> > -
> >         struct audit_net *aunet = net_generic(net, audit_net_id);
> >
> >         aunet->sk = netlink_kernel_create(net, NETLINK_AUDIT, &cfg);
> > @@ -1628,7 +1702,8 @@ static int __net_init audit_net_init(struct net *net)
> >                 return -ENOMEM;
> >         }
> >         aunet->sk->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT;
> > -
> > +       INIT_LIST_HEAD(&aunet->contid_list);
> > +       spin_lock_init(&aunet->contid_list_lock);
> >         return 0;
> >  }
> >
> > @@ -2380,6 +2455,7 @@ int audit_set_contid(struct task_struct *task, u64 contid)
> >         uid_t uid;
> >         struct tty_struct *tty;
> >         char comm[sizeof(current->comm)];
> > +       struct net *net = task->nsproxy->net_ns;
> >
> >         task_lock(task);
> >         /* Can't set if audit disabled */
> > @@ -2401,8 +2477,12 @@ int audit_set_contid(struct task_struct *task, u64 contid)
> >         else if (!(thread_group_leader(task) && thread_group_empty(task)))
> >                 rc = -EALREADY;
> >         read_unlock(&tasklist_lock);
> > -       if (!rc)
> > +       if (!rc) {
> > +               if (audit_contid_valid(oldcontid))
> > +                       audit_netns_contid_del(net, oldcontid);
> >                 task->audit->contid = contid;
> > +               audit_netns_contid_add(net, contid);
> > +       }
> >         task_unlock(task);
> >
> >         if (!audit_enabled)
> > diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c
> > index f6c5d330059a..718b1201ae70 100644
> > --- a/kernel/nsproxy.c
> > +++ b/kernel/nsproxy.c
> > @@ -27,6 +27,7 @@
> >  #include <linux/syscalls.h>
> >  #include <linux/cgroup.h>
> >  #include <linux/perf_event.h>
> > +#include <linux/audit.h>
> >
> >  static struct kmem_cache *nsproxy_cachep;
> >
> > @@ -140,6 +141,7 @@ int copy_namespaces(unsigned long flags, struct task_struct *tsk)
> >         struct nsproxy *old_ns = tsk->nsproxy;
> >         struct user_namespace *user_ns = task_cred_xxx(tsk, user_ns);
> >         struct nsproxy *new_ns;
> > +       u64 contid = audit_get_contid(tsk);
> >
> >         if (likely(!(flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC |
> >                               CLONE_NEWPID | CLONE_NEWNET |
> > @@ -167,6 +169,7 @@ int copy_namespaces(unsigned long flags, struct task_struct *tsk)
> >                 return  PTR_ERR(new_ns);
> >
> >         tsk->nsproxy = new_ns;
> > +       audit_netns_contid_add(new_ns->net_ns, contid);
> >         return 0;
> >  }
> >
> > @@ -224,6 +227,7 @@ void switch_task_namespaces(struct task_struct *p, struct nsproxy *new)
> >         ns = p->nsproxy;
> >         p->nsproxy = new;
> >         task_unlock(p);
> > +       audit_switch_task_namespaces(ns, p);
> 
> Since we call audit_switch_task_namespaces() after task_unlock(),
> could there be a potential race condition? I'm not going to dive too
> much into this now, because it's getting late here, but on first look
> it seems like p->nsproxy could change under our hands before we fetch
> it in audit_switch_task_namespaces()...

The rules are defined in include/linux/nsproxy.h.

Since the callers (sys_setns, do_exit, copy_process error path) are all
current or handing it a dead task and we are not writing nsproxy or its
pointers, which is only allowed by current anyway, we don't need the
lock.

> >
> >         if (ns && atomic_dec_and_test(&ns->count))
> >                 free_nsproxy(ns);
> > --
> > 1.8.3.1
> 
> Ondrej Mosnacek <omosnace at redhat dot com>

- RGB

--
Richard Guy Briggs <rgb@redhat.com>
Sr. S/W Engineer, Kernel Security, Base Operating Systems
Remote, Ottawa, Red Hat Canada
IRC: rgb, SunRaycer
Voice: +1.647.777.2635, Internal: (81) 32635

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH ghak90 V5 05/10] audit: add containerid support for ptrace and signals
  2019-03-27 21:17   ` Ondrej Mosnacek
@ 2019-03-28  2:04     ` Richard Guy Briggs
  2019-03-30 12:55       ` Richard Guy Briggs
  0 siblings, 1 reply; 64+ messages in thread
From: Richard Guy Briggs @ 2019-03-28  2:04 UTC (permalink / raw)
  To: Ondrej Mosnacek
  Cc: containers, linux-api, Linux-Audit Mailing List, linux-fsdevel,
	LKML, netdev, netfilter-devel, Paul Moore, Steve Grubb,
	David Howells, Simo Sorce, Eric Paris, Serge E. Hallyn,
	Eric W . Biederman, nhorman

On 2019-03-27 22:17, Ondrej Mosnacek wrote:
> On Fri, Mar 15, 2019 at 7:34 PM Richard Guy Briggs <rgb@redhat.com> wrote:
> > Add audit container identifier support to ptrace and signals.  In
> > particular, the "ref" field provides a way to label the auxiliary record
> > to which it is associated.
> >
> > Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> > Acked-by: Serge Hallyn <serge@hallyn.com>
> > Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> > ---
> >  include/linux/audit.h |  1 +
> >  kernel/audit.c        |  2 ++
> >  kernel/audit.h        |  2 ++
> >  kernel/auditsc.c      | 23 +++++++++++++++++------
> >  4 files changed, 22 insertions(+), 6 deletions(-)
> >
> > diff --git a/include/linux/audit.h b/include/linux/audit.h
> > index 43438192ca2a..ebd6625ca80e 100644
> > --- a/include/linux/audit.h
> > +++ b/include/linux/audit.h
> > @@ -35,6 +35,7 @@ struct audit_sig_info {
> >         uid_t           uid;
> >         pid_t           pid;
> >         char            ctx[0];
> > +       u64             cid;
> >  };
> 
> It seems like this structure implicitly defines the format of some
> message that is sent to userspace... If so, how will userspace detect
> that a new format (including the cid) is being used? Even assuming the
> fixed order as pointed out by Neil, the message still seems to be
> variable-sized so userspace cannot even use the length to infer that.
> Am I missing something here? (I hope I am :)

How humble of you again.  No, you're not missing something.  This ends
up being an api change...  That can be fixed in userspace by checking
for AUDIT_FEATURE_BITMAP_CONTAINERID, but how do we make a newer kernel
not break an older userspace...  I think this was the original rationale
for adding it after the ctx but totally missing the fact that the latter
is a variable-length field.

This patch really should be split into audit_sig_cid changes in a patch
by itself and target_cid changes which could go with the second and
fourth patches.

> >  struct audit_buffer;
> > diff --git a/kernel/audit.c b/kernel/audit.c
> > index 8cc0e88d7f2a..cfa659b3f6c4 100644
> > --- a/kernel/audit.c
> > +++ b/kernel/audit.c
> > @@ -138,6 +138,7 @@ struct audit_net {
> >  kuid_t         audit_sig_uid = INVALID_UID;
> >  pid_t          audit_sig_pid = -1;
> >  u32            audit_sig_sid = 0;
> > +u64            audit_sig_cid = AUDIT_CID_UNSET;
> >
> >  /* Records can be lost in several ways:
> >     0) [suppressed in audit_alloc]
> > @@ -1515,6 +1516,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
> >                         memcpy(sig_data->ctx, ctx, len);
> >                         security_release_secctx(ctx, len);
> >                 }
> > +               sig_data->cid = audit_sig_cid;
> >                 audit_send_reply(skb, seq, AUDIT_SIGNAL_INFO, 0, 0,
> >                                  sig_data, sizeof(*sig_data) + len);
> >                 kfree(sig_data);
> > diff --git a/kernel/audit.h b/kernel/audit.h
> > index c00e2ee3c6b3..c5ac6436317e 100644
> > --- a/kernel/audit.h
> > +++ b/kernel/audit.h
> > @@ -148,6 +148,7 @@ struct audit_context {
> >         kuid_t              target_uid;
> >         unsigned int        target_sessionid;
> >         u32                 target_sid;
> > +       u64                 target_cid;
> >         char                target_comm[TASK_COMM_LEN];
> >
> >         struct audit_tree_refs *trees, *first_trees;
> > @@ -344,6 +345,7 @@ extern void audit_filter_inodes(struct task_struct *tsk,
> >  extern pid_t audit_sig_pid;
> >  extern kuid_t audit_sig_uid;
> >  extern u32 audit_sig_sid;
> > +extern u64 audit_sig_cid;
> >
> >  extern int audit_filter(int msgtype, unsigned int listtype);
> >
> > diff --git a/kernel/auditsc.c b/kernel/auditsc.c
> > index a8c8b44b954d..f04e115df5dc 100644
> > --- a/kernel/auditsc.c
> > +++ b/kernel/auditsc.c
> > @@ -113,6 +113,7 @@ struct audit_aux_data_pids {
> >         kuid_t                  target_uid[AUDIT_AUX_PIDS];
> >         unsigned int            target_sessionid[AUDIT_AUX_PIDS];
> >         u32                     target_sid[AUDIT_AUX_PIDS];
> > +       u64                     target_cid[AUDIT_AUX_PIDS];
> >         char                    target_comm[AUDIT_AUX_PIDS][TASK_COMM_LEN];
> >         int                     pid_count;
> >  };
> > @@ -1514,7 +1515,7 @@ static void audit_log_exit(void)
> >         for (aux = context->aux_pids; aux; aux = aux->next) {
> >                 struct audit_aux_data_pids *axs = (void *)aux;
> >
> > -               for (i = 0; i < axs->pid_count; i++)
> > +               for (i = 0; i < axs->pid_count; i++) {
> >                         if (audit_log_pid_context(context, axs->target_pid[i],
> >                                                   axs->target_auid[i],
> >                                                   axs->target_uid[i],
> > @@ -1522,14 +1523,20 @@ static void audit_log_exit(void)
> >                                                   axs->target_sid[i],
> >                                                   axs->target_comm[i]))
> >                                 call_panic = 1;
> > +                       audit_log_contid(context, axs->target_cid[i]);
> > +               }
> >         }
> >
> > -       if (context->target_pid &&
> > -           audit_log_pid_context(context, context->target_pid,
> > -                                 context->target_auid, context->target_uid,
> > -                                 context->target_sessionid,
> > -                                 context->target_sid, context->target_comm))
> > +       if (context->target_pid) {
> > +               if (audit_log_pid_context(context, context->target_pid,
> > +                                         context->target_auid,
> > +                                         context->target_uid,
> > +                                         context->target_sessionid,
> > +                                         context->target_sid,
> > +                                         context->target_comm))
> >                         call_panic = 1;
> > +               audit_log_contid(context, context->target_cid);
> > +       }
> >
> >         if (context->pwd.dentry && context->pwd.mnt) {
> >                 ab = audit_log_start(context, GFP_KERNEL, AUDIT_CWD);
> > @@ -2360,6 +2367,7 @@ void __audit_ptrace(struct task_struct *t)
> >         context->target_uid = task_uid(t);
> >         context->target_sessionid = audit_get_sessionid(t);
> >         security_task_getsecid(t, &context->target_sid);
> > +       context->target_cid = audit_get_contid(t);
> >         memcpy(context->target_comm, t->comm, TASK_COMM_LEN);
> >  }
> >
> > @@ -2387,6 +2395,7 @@ int audit_signal_info(int sig, struct task_struct *t)
> >                 else
> >                         audit_sig_uid = uid;
> >                 security_task_getsecid(current, &audit_sig_sid);
> > +               audit_sig_cid = audit_get_contid(current);
> >         }
> >
> >         if (!audit_signals || audit_dummy_context())
> > @@ -2400,6 +2409,7 @@ int audit_signal_info(int sig, struct task_struct *t)
> >                 ctx->target_uid = t_uid;
> >                 ctx->target_sessionid = audit_get_sessionid(t);
> >                 security_task_getsecid(t, &ctx->target_sid);
> > +               ctx->target_cid = audit_get_contid(t);
> >                 memcpy(ctx->target_comm, t->comm, TASK_COMM_LEN);
> >                 return 0;
> >         }
> > @@ -2421,6 +2431,7 @@ int audit_signal_info(int sig, struct task_struct *t)
> >         axp->target_uid[axp->pid_count] = t_uid;
> >         axp->target_sessionid[axp->pid_count] = audit_get_sessionid(t);
> >         security_task_getsecid(t, &axp->target_sid[axp->pid_count]);
> > +       axp->target_cid[axp->pid_count] = audit_get_contid(t);
> >         memcpy(axp->target_comm[axp->pid_count], t->comm, TASK_COMM_LEN);
> >         axp->pid_count++;
> >
> > --
> > 1.8.3.1
> >
> 
> 
> -- 
> Ondrej Mosnacek <omosnace at redhat dot com>
> Software Engineer, Security Technologies
> Red Hat, Inc.

- RGB

--
Richard Guy Briggs <rgb@redhat.com>
Sr. S/W Engineer, Kernel Security, Base Operating Systems
Remote, Ottawa, Red Hat Canada
IRC: rgb, SunRaycer
Voice: +1.647.777.2635, Internal: (81) 32635

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH ghak90 V5 09/10] audit: add support for containerid to network namespaces
  2019-03-28  1:12     ` Richard Guy Briggs
@ 2019-03-28  8:01       ` Ondrej Mosnacek
  2019-03-28 15:46       ` Paul Moore
  2019-03-29 14:49       ` Neil Horman
  2 siblings, 0 replies; 64+ messages in thread
From: Ondrej Mosnacek @ 2019-03-28  8:01 UTC (permalink / raw)
  To: Richard Guy Briggs
  Cc: nhorman, linux-api, containers, LKML, David Howells,
	Linux-Audit Mailing List, netfilter-devel, Eric W . Biederman,
	Simo Sorce, netdev, linux-fsdevel, Eric Paris, Serge E. Hallyn

On Thu, Mar 28, 2019 at 2:12 AM Richard Guy Briggs <rgb@redhat.com> wrote:
> On 2019-03-27 23:42, Ondrej Mosnacek wrote:
> > On Fri, Mar 15, 2019 at 7:35 PM Richard Guy Briggs <rgb@redhat.com> wrote:
> > > Audit events could happen in a network namespace outside of a task
> > > context due to packets received from the net that trigger an auditing
> > > rule prior to being associated with a running task.  The network
> > > namespace could be in use by multiple containers by association to the
> > > tasks in that network namespace.  We still want a way to attribute
> > > these events to any potential containers.  Keep a list per network
> > > namespace to track these audit container identifiiers.
> > >
> > > Add/increment the audit container identifier on:
> > > - initial setting of the audit container identifier via /proc
> > > - clone/fork call that inherits an audit container identifier
> > > - unshare call that inherits an audit container identifier
> > > - setns call that inherits an audit container identifier
> > > Delete/decrement the audit container identifier on:
> > > - an inherited audit container identifier dropped when child set
> > > - process exit
> > > - unshare call that drops a net namespace
> > > - setns call that drops a net namespace
> > >
> > > See: https://github.com/linux-audit/audit-kernel/issues/92
> > > See: https://github.com/linux-audit/audit-testsuite/issues/64
> > > See: https://github.com/linux-audit/audit-kernel/wiki/RFE-Audit-Container-ID
> > > Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> > > ---
> > >  include/linux/audit.h | 19 ++++++++++++
> > >  kernel/audit.c        | 86 +++++++++++++++++++++++++++++++++++++++++++++++++--
> > >  kernel/nsproxy.c      |  4 +++
> > >  3 files changed, 106 insertions(+), 3 deletions(-)
> > >
> > > diff --git a/include/linux/audit.h b/include/linux/audit.h
> > > index fa19fa408931..70255c2dfb9f 100644
> > > --- a/include/linux/audit.h
> > > +++ b/include/linux/audit.h
> > > @@ -27,6 +27,7 @@
> > >  #include <linux/ptrace.h>
> > >  #include <linux/namei.h>  /* LOOKUP_* */
> > >  #include <uapi/linux/audit.h>
> > > +#include <linux/refcount.h>
> > >
> > >  #define AUDIT_INO_UNSET ((unsigned long)-1)
> > >  #define AUDIT_DEV_UNSET ((dev_t)-1)
> > > @@ -99,6 +100,13 @@ struct audit_task_info {
> > >
> > >  extern struct audit_task_info init_struct_audit;
> > >
> > > +struct audit_contid {
> > > +       struct list_head        list;
> > > +       u64                     id;
> > > +       refcount_t              refcount;
> >
> > Hm, since we only ever touch the refcount under a spinlock, I wonder
> > if we could just make it a regular unsigned int (we don't need the
> > atomicity guarantees). OTOH, refcount_t comes with some extra overflow
> > checking, so it's probably better to leave it as is...
>
> Since the update is done using rcu-safe methods, do we even need the
> spin_lock?  Neil?  Paul?
>
> > > +       struct rcu_head         rcu;
> > > +};
> > > +
> > >  extern int is_audit_feature_set(int which);
> > >
> > >  extern int __init audit_register_class(int class, unsigned *list);
> > > @@ -202,6 +210,10 @@ static inline u64 audit_get_contid(struct task_struct *tsk)
> > >  }
> > >
> > >  extern void audit_log_contid(struct audit_context *context, u64 contid);
> > > +extern void audit_netns_contid_add(struct net *net, u64 contid);
> > > +extern void audit_netns_contid_del(struct net *net, u64 contid);
> > > +extern void audit_switch_task_namespaces(struct nsproxy *ns,
> > > +                                        struct task_struct *p);
> > >
> > >  extern u32 audit_enabled;
> > >  #else /* CONFIG_AUDIT */
> > > @@ -271,6 +283,13 @@ static inline u64 audit_get_contid(struct task_struct *tsk)
> > >
> > >  static inline void audit_log_contid(struct audit_context *context, u64 contid)
> > >  { }
> > > +static inline void audit_netns_contid_add(struct net *net, u64 contid)
> > > +{ }
> > > +static inline void audit_netns_contid_del(struct net *net, u64 contid)
> > > +{ }
> > > +static inline void audit_switch_task_namespaces(struct nsproxy *ns,
> > > +                                               struct task_struct *p)
> > > +{ }
> > >
> > >  #define audit_enabled AUDIT_OFF
> > >  #endif /* CONFIG_AUDIT */
> > > diff --git a/kernel/audit.c b/kernel/audit.c
> > > index cf448599ef34..7fa3194f5342 100644
> > > --- a/kernel/audit.c
> > > +++ b/kernel/audit.c
> > > @@ -72,6 +72,7 @@
> > >  #include <linux/freezer.h>
> > >  #include <linux/pid_namespace.h>
> > >  #include <net/netns/generic.h>
> > > +#include <net/net_namespace.h>
> > >
> > >  #include "audit.h"
> > >
> > > @@ -99,9 +100,13 @@
> > >  /**
> > >   * struct audit_net - audit private network namespace data
> > >   * @sk: communication socket
> > > + * @contid_list: audit container identifier list
> > > + * @contid_list_lock audit container identifier list lock
> > >   */
> > >  struct audit_net {
> > >         struct sock *sk;
> > > +       struct list_head contid_list;
> > > +       spinlock_t contid_list_lock;
> > >  };
> > >
> > >  /**
> > > @@ -275,8 +280,11 @@ struct audit_task_info init_struct_audit = {
> > >  void audit_free(struct task_struct *tsk)
> > >  {
> > >         struct audit_task_info *info = tsk->audit;
> > > +       struct nsproxy *ns = tsk->nsproxy;
> > >
> > >         audit_free_syscall(tsk);
> > > +       if (ns)
> > > +               audit_netns_contid_del(ns->net_ns, audit_get_contid(tsk));
> > >         /* Freeing the audit_task_info struct must be performed after
> > >          * audit_log_exit() due to need for loginuid and sessionid.
> > >          */
> > > @@ -376,6 +384,73 @@ static struct sock *audit_get_sk(const struct net *net)
> > >         return aunet->sk;
> > >  }
> > >
> > > +void audit_netns_contid_add(struct net *net, u64 contid)
> > > +{
> > > +       struct audit_net *aunet = net_generic(net, audit_net_id);
> > > +       struct list_head *contid_list = &aunet->contid_list;
> > > +       struct audit_contid *cont;
> > > +
> > > +       if (!audit_contid_valid(contid))
> > > +               return;
> > > +       if (!aunet)
> > > +               return;
> > > +       spin_lock(&aunet->contid_list_lock);
> > > +       if (!list_empty(contid_list))
> > > +               list_for_each_entry_rcu(cont, contid_list, list)
> > > +                       if (cont->id == contid) {
> > > +                               refcount_inc(&cont->refcount);
> > > +                               goto out;
> > > +                       }
> > > +       cont = kmalloc(sizeof(struct audit_contid), GFP_ATOMIC);
> > > +       if (cont) {
> > > +               INIT_LIST_HEAD(&cont->list);
> > > +               cont->id = contid;
> > > +               refcount_set(&cont->refcount, 1);
> > > +               list_add_rcu(&cont->list, contid_list);
> > > +       }
> > > +out:
> > > +       spin_unlock(&aunet->contid_list_lock);
> > > +}
> > > +
> > > +void audit_netns_contid_del(struct net *net, u64 contid)
> > > +{
> > > +       struct audit_net *aunet;
> > > +       struct list_head *contid_list;
> > > +       struct audit_contid *cont = NULL;
> > > +
> > > +       if (!net)
> > > +               return;
> > > +       if (!audit_contid_valid(contid))
> > > +               return;
> > > +       aunet = net_generic(net, audit_net_id);
> > > +       if (!aunet)
> > > +               return;
> > > +       contid_list = &aunet->contid_list;
> > > +       spin_lock(&aunet->contid_list_lock);
> > > +       if (!list_empty(contid_list))
> > > +               list_for_each_entry_rcu(cont, contid_list, list)
> > > +                       if (cont->id == contid) {
> > > +                               if (refcount_dec_and_test(&cont->refcount)) {
> > > +                                       list_del_rcu(&cont->list);
> > > +                                       kfree_rcu(cont, rcu);
> > > +                               }
> > > +                               break;
> > > +                       }
> > > +       spin_unlock(&aunet->contid_list_lock);
> > > +}
> > > +
> > > +void audit_switch_task_namespaces(struct nsproxy *ns, struct task_struct *p)
> > > +{
> > > +       u64 contid = audit_get_contid(p);
> > > +       struct nsproxy *new = p->nsproxy;
> > > +
> > > +       if (!audit_contid_valid(contid))
> > > +               return;
> > > +       audit_netns_contid_del(ns->net_ns, contid);
> > > +       if (new)
> > > +               audit_netns_contid_add(new->net_ns, contid);
> > > +}
> > > +
> > >  void audit_panic(const char *message)
> > >  {
> > >         switch (audit_failure) {
> > > @@ -1619,7 +1694,6 @@ static int __net_init audit_net_init(struct net *net)
> > >                 .flags  = NL_CFG_F_NONROOT_RECV,
> > >                 .groups = AUDIT_NLGRP_MAX,
> > >         };
> > > -
> > >         struct audit_net *aunet = net_generic(net, audit_net_id);
> > >
> > >         aunet->sk = netlink_kernel_create(net, NETLINK_AUDIT, &cfg);
> > > @@ -1628,7 +1702,8 @@ static int __net_init audit_net_init(struct net *net)
> > >                 return -ENOMEM;
> > >         }
> > >         aunet->sk->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT;
> > > -
> > > +       INIT_LIST_HEAD(&aunet->contid_list);
> > > +       spin_lock_init(&aunet->contid_list_lock);
> > >         return 0;
> > >  }
> > >
> > > @@ -2380,6 +2455,7 @@ int audit_set_contid(struct task_struct *task, u64 contid)
> > >         uid_t uid;
> > >         struct tty_struct *tty;
> > >         char comm[sizeof(current->comm)];
> > > +       struct net *net = task->nsproxy->net_ns;
> > >
> > >         task_lock(task);
> > >         /* Can't set if audit disabled */
> > > @@ -2401,8 +2477,12 @@ int audit_set_contid(struct task_struct *task, u64 contid)
> > >         else if (!(thread_group_leader(task) && thread_group_empty(task)))
> > >                 rc = -EALREADY;
> > >         read_unlock(&tasklist_lock);
> > > -       if (!rc)
> > > +       if (!rc) {
> > > +               if (audit_contid_valid(oldcontid))
> > > +                       audit_netns_contid_del(net, oldcontid);
> > >                 task->audit->contid = contid;
> > > +               audit_netns_contid_add(net, contid);
> > > +       }
> > >         task_unlock(task);
> > >
> > >         if (!audit_enabled)
> > > diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c
> > > index f6c5d330059a..718b1201ae70 100644
> > > --- a/kernel/nsproxy.c
> > > +++ b/kernel/nsproxy.c
> > > @@ -27,6 +27,7 @@
> > >  #include <linux/syscalls.h>
> > >  #include <linux/cgroup.h>
> > >  #include <linux/perf_event.h>
> > > +#include <linux/audit.h>
> > >
> > >  static struct kmem_cache *nsproxy_cachep;
> > >
> > > @@ -140,6 +141,7 @@ int copy_namespaces(unsigned long flags, struct task_struct *tsk)
> > >         struct nsproxy *old_ns = tsk->nsproxy;
> > >         struct user_namespace *user_ns = task_cred_xxx(tsk, user_ns);
> > >         struct nsproxy *new_ns;
> > > +       u64 contid = audit_get_contid(tsk);
> > >
> > >         if (likely(!(flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC |
> > >                               CLONE_NEWPID | CLONE_NEWNET |
> > > @@ -167,6 +169,7 @@ int copy_namespaces(unsigned long flags, struct task_struct *tsk)
> > >                 return  PTR_ERR(new_ns);
> > >
> > >         tsk->nsproxy = new_ns;
> > > +       audit_netns_contid_add(new_ns->net_ns, contid);
> > >         return 0;
> > >  }
> > >
> > > @@ -224,6 +227,7 @@ void switch_task_namespaces(struct task_struct *p, struct nsproxy *new)
> > >         ns = p->nsproxy;
> > >         p->nsproxy = new;
> > >         task_unlock(p);
> > > +       audit_switch_task_namespaces(ns, p);
> >
> > Since we call audit_switch_task_namespaces() after task_unlock(),
> > could there be a potential race condition? I'm not going to dive too
> > much into this now, because it's getting late here, but on first look
> > it seems like p->nsproxy could change under our hands before we fetch
> > it in audit_switch_task_namespaces()...
>
> The rules are defined in include/linux/nsproxy.h.
>
> Since the callers (sys_setns, do_exit, copy_process error path) are all
> current or handing it a dead task and we are not writing nsproxy or its
> pointers, which is only allowed by current anyway, we don't need the
> lock.

I see, so the task lock is taken during the swap only to protect
against races with other tasks reading this task's nsproxy... makes
sense. Thanks for clarifying!

The refcount/spinlock issue is not blocking (and could be addressed in
a follow-up patch later), so:

Reviewed-by: Ondrej Mosnacek <omosnace@redhat.com>

>
> > >
> > >         if (ns && atomic_dec_and_test(&ns->count))
> > >                 free_nsproxy(ns);
> > > --
> > > 1.8.3.1
> >
> > Ondrej Mosnacek <omosnace at redhat dot com>
>
> - RGB
>
> --
> Richard Guy Briggs <rgb@redhat.com>
> Sr. S/W Engineer, Kernel Security, Base Operating Systems
> Remote, Ottawa, Red Hat Canada
> IRC: rgb, SunRaycer
> Voice: +1.647.777.2635, Internal: (81) 32635

--
Ondrej Mosnacek <omosnace at redhat dot com>
Software Engineer, Security Technologies
Red Hat, Inc.

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH ghak90 V5 09/10] audit: add support for containerid to network namespaces
  2019-03-28  1:12     ` Richard Guy Briggs
  2019-03-28  8:01       ` Ondrej Mosnacek
@ 2019-03-28 15:46       ` Paul Moore
  2019-03-28 21:40         ` Richard Guy Briggs
  2019-03-29 14:49       ` Neil Horman
  2 siblings, 1 reply; 64+ messages in thread
From: Paul Moore @ 2019-03-28 15:46 UTC (permalink / raw)
  To: Richard Guy Briggs
  Cc: Ondrej Mosnacek, nhorman, linux-api, containers, LKML,
	David Howells, Linux-Audit Mailing List, netfilter-devel,
	Eric W . Biederman, Simo Sorce, netdev, linux-fsdevel,
	Eric Paris, Serge E. Hallyn

On Wed, Mar 27, 2019 at 9:12 PM Richard Guy Briggs <rgb@redhat.com> wrote:
>
> On 2019-03-27 23:42, Ondrej Mosnacek wrote:
> > On Fri, Mar 15, 2019 at 7:35 PM Richard Guy Briggs <rgb@redhat.com> wrote:
> > > Audit events could happen in a network namespace outside of a task
> > > context due to packets received from the net that trigger an auditing
> > > rule prior to being associated with a running task.  The network
> > > namespace could be in use by multiple containers by association to the
> > > tasks in that network namespace.  We still want a way to attribute
> > > these events to any potential containers.  Keep a list per network
> > > namespace to track these audit container identifiiers.
> > >
> > > Add/increment the audit container identifier on:
> > > - initial setting of the audit container identifier via /proc
> > > - clone/fork call that inherits an audit container identifier
> > > - unshare call that inherits an audit container identifier
> > > - setns call that inherits an audit container identifier
> > > Delete/decrement the audit container identifier on:
> > > - an inherited audit container identifier dropped when child set
> > > - process exit
> > > - unshare call that drops a net namespace
> > > - setns call that drops a net namespace
> > >
> > > See: https://github.com/linux-audit/audit-kernel/issues/92
> > > See: https://github.com/linux-audit/audit-testsuite/issues/64
> > > See: https://github.com/linux-audit/audit-kernel/wiki/RFE-Audit-Container-ID
> > > Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> > > ---
> > >  include/linux/audit.h | 19 ++++++++++++
> > >  kernel/audit.c        | 86 +++++++++++++++++++++++++++++++++++++++++++++++++--
> > >  kernel/nsproxy.c      |  4 +++
> > >  3 files changed, 106 insertions(+), 3 deletions(-)
> > >
> > > diff --git a/include/linux/audit.h b/include/linux/audit.h
> > > index fa19fa408931..70255c2dfb9f 100644
> > > --- a/include/linux/audit.h
> > > +++ b/include/linux/audit.h
> > > @@ -27,6 +27,7 @@
> > >  #include <linux/ptrace.h>
> > >  #include <linux/namei.h>  /* LOOKUP_* */
> > >  #include <uapi/linux/audit.h>
> > > +#include <linux/refcount.h>
> > >
> > >  #define AUDIT_INO_UNSET ((unsigned long)-1)
> > >  #define AUDIT_DEV_UNSET ((dev_t)-1)
> > > @@ -99,6 +100,13 @@ struct audit_task_info {
> > >
> > >  extern struct audit_task_info init_struct_audit;
> > >
> > > +struct audit_contid {
> > > +       struct list_head        list;
> > > +       u64                     id;
> > > +       refcount_t              refcount;
> >
> > Hm, since we only ever touch the refcount under a spinlock, I wonder
> > if we could just make it a regular unsigned int (we don't need the
> > atomicity guarantees). OTOH, refcount_t comes with some extra overflow
> > checking, so it's probably better to leave it as is...
>
> Since the update is done using rcu-safe methods, do we even need the
> spin_lock?  Neil?  Paul?

As discussed, the refcount field is protected against simultaneous
writes by the spinlock that protects additions/removals from the list
as a whole so I don't believe the refcount_t atomicity is critical in
this regard.

Where it gets tricky, and I can't say I'm 100% confident on my answer
here, is if refcount was a regular int and we wanted to access it
outside of a spinlock (to be clear, it doesn't look like this patch
currently does this).  With RCU, if refcount was a regular int
(unsigned or otherwise), I believe it would be possible for different
threads of execution to potentially see different values of refcount
(assuming one thread was adding/removing from the list).  Using a
refcount_t would protect against this, alternatively, taking the
spinlock should also protect against this.

As we all know, RCU can be tricky at times, so I may be off on the
above; if I am, please provide an explanation so I (and likely others
as well) can learn a little bit more. :)

-- 
paul moore
www.paul-moore.com

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH ghak90 V5 09/10] audit: add support for containerid to network namespaces
  2019-03-28 15:46       ` Paul Moore
@ 2019-03-28 21:40         ` Richard Guy Briggs
  2019-03-28 22:00           ` Paul Moore
  2019-03-29 14:50           ` Neil Horman
  0 siblings, 2 replies; 64+ messages in thread
From: Richard Guy Briggs @ 2019-03-28 21:40 UTC (permalink / raw)
  To: Paul Moore
  Cc: Ondrej Mosnacek, nhorman, linux-api, containers, LKML,
	David Howells, Linux-Audit Mailing List, netfilter-devel,
	Eric W . Biederman, Simo Sorce, netdev, linux-fsdevel,
	Eric Paris, Serge E. Hallyn

On 2019-03-28 11:46, Paul Moore wrote:
> On Wed, Mar 27, 2019 at 9:12 PM Richard Guy Briggs <rgb@redhat.com> wrote:
> >
> > On 2019-03-27 23:42, Ondrej Mosnacek wrote:
> > > On Fri, Mar 15, 2019 at 7:35 PM Richard Guy Briggs <rgb@redhat.com> wrote:
> > > > Audit events could happen in a network namespace outside of a task
> > > > context due to packets received from the net that trigger an auditing
> > > > rule prior to being associated with a running task.  The network
> > > > namespace could be in use by multiple containers by association to the
> > > > tasks in that network namespace.  We still want a way to attribute
> > > > these events to any potential containers.  Keep a list per network
> > > > namespace to track these audit container identifiiers.
> > > >
> > > > Add/increment the audit container identifier on:
> > > > - initial setting of the audit container identifier via /proc
> > > > - clone/fork call that inherits an audit container identifier
> > > > - unshare call that inherits an audit container identifier
> > > > - setns call that inherits an audit container identifier
> > > > Delete/decrement the audit container identifier on:
> > > > - an inherited audit container identifier dropped when child set
> > > > - process exit
> > > > - unshare call that drops a net namespace
> > > > - setns call that drops a net namespace
> > > >
> > > > See: https://github.com/linux-audit/audit-kernel/issues/92
> > > > See: https://github.com/linux-audit/audit-testsuite/issues/64
> > > > See: https://github.com/linux-audit/audit-kernel/wiki/RFE-Audit-Container-ID
> > > > Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> > > > ---
> > > >  include/linux/audit.h | 19 ++++++++++++
> > > >  kernel/audit.c        | 86 +++++++++++++++++++++++++++++++++++++++++++++++++--
> > > >  kernel/nsproxy.c      |  4 +++
> > > >  3 files changed, 106 insertions(+), 3 deletions(-)
> > > >
> > > > diff --git a/include/linux/audit.h b/include/linux/audit.h
> > > > index fa19fa408931..70255c2dfb9f 100644
> > > > --- a/include/linux/audit.h
> > > > +++ b/include/linux/audit.h
> > > > @@ -27,6 +27,7 @@
> > > >  #include <linux/ptrace.h>
> > > >  #include <linux/namei.h>  /* LOOKUP_* */
> > > >  #include <uapi/linux/audit.h>
> > > > +#include <linux/refcount.h>
> > > >
> > > >  #define AUDIT_INO_UNSET ((unsigned long)-1)
> > > >  #define AUDIT_DEV_UNSET ((dev_t)-1)
> > > > @@ -99,6 +100,13 @@ struct audit_task_info {
> > > >
> > > >  extern struct audit_task_info init_struct_audit;
> > > >
> > > > +struct audit_contid {
> > > > +       struct list_head        list;
> > > > +       u64                     id;
> > > > +       refcount_t              refcount;
> > >
> > > Hm, since we only ever touch the refcount under a spinlock, I wonder
> > > if we could just make it a regular unsigned int (we don't need the
> > > atomicity guarantees). OTOH, refcount_t comes with some extra overflow
> > > checking, so it's probably better to leave it as is...
> >
> > Since the update is done using rcu-safe methods, do we even need the
> > spin_lock?  Neil?  Paul?
> 
> As discussed, the refcount field is protected against simultaneous
> writes by the spinlock that protects additions/removals from the list
> as a whole so I don't believe the refcount_t atomicity is critical in
> this regard.
> 
> Where it gets tricky, and I can't say I'm 100% confident on my answer
> here, is if refcount was a regular int and we wanted to access it
> outside of a spinlock (to be clear, it doesn't look like this patch
> currently does this).  With RCU, if refcount was a regular int
> (unsigned or otherwise), I believe it would be possible for different
> threads of execution to potentially see different values of refcount
> (assuming one thread was adding/removing from the list).  Using a
> refcount_t would protect against this, alternatively, taking the
> spinlock should also protect against this.

Ok, from the above it isn't clear to me if you are happy with the
current code or would prefer any changes, or from below that you still
need to work it through to make a pronouncement.  It sounds to me you
would be ok with *either* spinlock *or* refcount_t, but don't see the
need for both.

> As we all know, RCU can be tricky at times, so I may be off on the
> above; if I am, please provide an explanation so I (and likely others
> as well) can learn a little bit more. :)
> 
> -- 
> paul moore
> www.paul-moore.com

- RGB

--
Richard Guy Briggs <rgb@redhat.com>
Sr. S/W Engineer, Kernel Security, Base Operating Systems
Remote, Ottawa, Red Hat Canada
IRC: rgb, SunRaycer
Voice: +1.647.777.2635, Internal: (81) 32635

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH ghak90 V5 09/10] audit: add support for containerid to network namespaces
  2019-03-28 21:40         ` Richard Guy Briggs
@ 2019-03-28 22:00           ` Paul Moore
  2019-03-31  2:11             ` Neil Horman
  2019-03-29 14:50           ` Neil Horman
  1 sibling, 1 reply; 64+ messages in thread
From: Paul Moore @ 2019-03-28 22:00 UTC (permalink / raw)
  To: Richard Guy Briggs
  Cc: Ondrej Mosnacek, nhorman, linux-api, containers, LKML,
	David Howells, Linux-Audit Mailing List, netfilter-devel,
	Eric W . Biederman, Simo Sorce, netdev, linux-fsdevel,
	Eric Paris, Serge E. Hallyn

On Thu, Mar 28, 2019 at 5:40 PM Richard Guy Briggs <rgb@redhat.com> wrote:
> On 2019-03-28 11:46, Paul Moore wrote:
> > On Wed, Mar 27, 2019 at 9:12 PM Richard Guy Briggs <rgb@redhat.com> wrote:
> > >
> > > On 2019-03-27 23:42, Ondrej Mosnacek wrote:
> > > > On Fri, Mar 15, 2019 at 7:35 PM Richard Guy Briggs <rgb@redhat.com> wrote:
> > > > > Audit events could happen in a network namespace outside of a task
> > > > > context due to packets received from the net that trigger an auditing
> > > > > rule prior to being associated with a running task.  The network
> > > > > namespace could be in use by multiple containers by association to the
> > > > > tasks in that network namespace.  We still want a way to attribute
> > > > > these events to any potential containers.  Keep a list per network
> > > > > namespace to track these audit container identifiiers.
> > > > >
> > > > > Add/increment the audit container identifier on:
> > > > > - initial setting of the audit container identifier via /proc
> > > > > - clone/fork call that inherits an audit container identifier
> > > > > - unshare call that inherits an audit container identifier
> > > > > - setns call that inherits an audit container identifier
> > > > > Delete/decrement the audit container identifier on:
> > > > > - an inherited audit container identifier dropped when child set
> > > > > - process exit
> > > > > - unshare call that drops a net namespace
> > > > > - setns call that drops a net namespace
> > > > >
> > > > > See: https://github.com/linux-audit/audit-kernel/issues/92
> > > > > See: https://github.com/linux-audit/audit-testsuite/issues/64
> > > > > See: https://github.com/linux-audit/audit-kernel/wiki/RFE-Audit-Container-ID
> > > > > Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> > > > > ---
> > > > >  include/linux/audit.h | 19 ++++++++++++
> > > > >  kernel/audit.c        | 86 +++++++++++++++++++++++++++++++++++++++++++++++++--
> > > > >  kernel/nsproxy.c      |  4 +++
> > > > >  3 files changed, 106 insertions(+), 3 deletions(-)
> > > > >
> > > > > diff --git a/include/linux/audit.h b/include/linux/audit.h
> > > > > index fa19fa408931..70255c2dfb9f 100644
> > > > > --- a/include/linux/audit.h
> > > > > +++ b/include/linux/audit.h
> > > > > @@ -27,6 +27,7 @@
> > > > >  #include <linux/ptrace.h>
> > > > >  #include <linux/namei.h>  /* LOOKUP_* */
> > > > >  #include <uapi/linux/audit.h>
> > > > > +#include <linux/refcount.h>
> > > > >
> > > > >  #define AUDIT_INO_UNSET ((unsigned long)-1)
> > > > >  #define AUDIT_DEV_UNSET ((dev_t)-1)
> > > > > @@ -99,6 +100,13 @@ struct audit_task_info {
> > > > >
> > > > >  extern struct audit_task_info init_struct_audit;
> > > > >
> > > > > +struct audit_contid {
> > > > > +       struct list_head        list;
> > > > > +       u64                     id;
> > > > > +       refcount_t              refcount;
> > > >
> > > > Hm, since we only ever touch the refcount under a spinlock, I wonder
> > > > if we could just make it a regular unsigned int (we don't need the
> > > > atomicity guarantees). OTOH, refcount_t comes with some extra overflow
> > > > checking, so it's probably better to leave it as is...
> > >
> > > Since the update is done using rcu-safe methods, do we even need the
> > > spin_lock?  Neil?  Paul?
> >
> > As discussed, the refcount field is protected against simultaneous
> > writes by the spinlock that protects additions/removals from the list
> > as a whole so I don't believe the refcount_t atomicity is critical in
> > this regard.
> >
> > Where it gets tricky, and I can't say I'm 100% confident on my answer
> > here, is if refcount was a regular int and we wanted to access it
> > outside of a spinlock (to be clear, it doesn't look like this patch
> > currently does this).  With RCU, if refcount was a regular int
> > (unsigned or otherwise), I believe it would be possible for different
> > threads of execution to potentially see different values of refcount
> > (assuming one thread was adding/removing from the list).  Using a
> > refcount_t would protect against this, alternatively, taking the
> > spinlock should also protect against this.
>
> Ok, from the above it isn't clear to me if you are happy with the
> current code or would prefer any changes, or from below that you still
> need to work it through to make a pronouncement.  It sounds to me you
> would be ok with *either* spinlock *or* refcount_t, but don't see the
> need for both.

To be fair you didn't ask if I was "happy" with the approach above,
you asked if we needed the spinlock/refcount_t.  I believe I answered
that question as comprehensively as I could, but perhaps you wanted a
hard yes or no?  In that case, since refcount_t is obviously safer, I
would stick with that for now just to limit the number of possible
failures.  If someone smarter than you or I comes along and
definitively says you are 100% safe to use an int, then go ahead and
use an int.

Beyond that, I'm still in the process of reviewing your patches, but I
haven't finished yet, so no "pronouncement" or whatever you want to
call it.

-- 
paul moore
www.paul-moore.com

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH ghak90 V5 09/10] audit: add support for containerid to network namespaces
  2019-03-28  1:12     ` Richard Guy Briggs
  2019-03-28  8:01       ` Ondrej Mosnacek
  2019-03-28 15:46       ` Paul Moore
@ 2019-03-29 14:49       ` Neil Horman
  2 siblings, 0 replies; 64+ messages in thread
From: Neil Horman @ 2019-03-29 14:49 UTC (permalink / raw)
  To: Richard Guy Briggs
  Cc: Ondrej Mosnacek, linux-api, containers, LKML, David Howells,
	Linux-Audit Mailing List, netfilter-devel, Eric W . Biederman,
	Simo Sorce, netdev, linux-fsdevel, Eric Paris, Serge E. Hallyn

On Wed, Mar 27, 2019 at 09:12:02PM -0400, Richard Guy Briggs wrote:
> On 2019-03-27 23:42, Ondrej Mosnacek wrote:
> > On Fri, Mar 15, 2019 at 7:35 PM Richard Guy Briggs <rgb@redhat.com> wrote:
> > > Audit events could happen in a network namespace outside of a task
> > > context due to packets received from the net that trigger an auditing
> > > rule prior to being associated with a running task.  The network
> > > namespace could be in use by multiple containers by association to the
> > > tasks in that network namespace.  We still want a way to attribute
> > > these events to any potential containers.  Keep a list per network
> > > namespace to track these audit container identifiiers.
> > >
> > > Add/increment the audit container identifier on:
> > > - initial setting of the audit container identifier via /proc
> > > - clone/fork call that inherits an audit container identifier
> > > - unshare call that inherits an audit container identifier
> > > - setns call that inherits an audit container identifier
> > > Delete/decrement the audit container identifier on:
> > > - an inherited audit container identifier dropped when child set
> > > - process exit
> > > - unshare call that drops a net namespace
> > > - setns call that drops a net namespace
> > >
> > > See: https://github.com/linux-audit/audit-kernel/issues/92
> > > See: https://github.com/linux-audit/audit-testsuite/issues/64
> > > See: https://github.com/linux-audit/audit-kernel/wiki/RFE-Audit-Container-ID
> > > Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> > > ---
> > >  include/linux/audit.h | 19 ++++++++++++
> > >  kernel/audit.c        | 86 +++++++++++++++++++++++++++++++++++++++++++++++++--
> > >  kernel/nsproxy.c      |  4 +++
> > >  3 files changed, 106 insertions(+), 3 deletions(-)
> > >
> > > diff --git a/include/linux/audit.h b/include/linux/audit.h
> > > index fa19fa408931..70255c2dfb9f 100644
> > > --- a/include/linux/audit.h
> > > +++ b/include/linux/audit.h
> > > @@ -27,6 +27,7 @@
> > >  #include <linux/ptrace.h>
> > >  #include <linux/namei.h>  /* LOOKUP_* */
> > >  #include <uapi/linux/audit.h>
> > > +#include <linux/refcount.h>
> > >
> > >  #define AUDIT_INO_UNSET ((unsigned long)-1)
> > >  #define AUDIT_DEV_UNSET ((dev_t)-1)
> > > @@ -99,6 +100,13 @@ struct audit_task_info {
> > >
> > >  extern struct audit_task_info init_struct_audit;
> > >
> > > +struct audit_contid {
> > > +       struct list_head        list;
> > > +       u64                     id;
> > > +       refcount_t              refcount;
> > 
> > Hm, since we only ever touch the refcount under a spinlock, I wonder
> > if we could just make it a regular unsigned int (we don't need the
> > atomicity guarantees). OTOH, refcount_t comes with some extra overflow
> > checking, so it's probably better to leave it as is...
> 
> Since the update is done using rcu-safe methods, do we even need the
> spin_lock?  Neil?  Paul?
> 
Yes, we do.  Rcu-safe methods only apply to read side operations, we still need
traditional mutual exclusion on the write side of the operation.  That is to say
we need to protect the list against multiple writers at the same time, and for
that we need a spin lock.

Neil

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH ghak90 V5 09/10] audit: add support for containerid to network namespaces
  2019-03-28 21:40         ` Richard Guy Briggs
  2019-03-28 22:00           ` Paul Moore
@ 2019-03-29 14:50           ` Neil Horman
  1 sibling, 0 replies; 64+ messages in thread
From: Neil Horman @ 2019-03-29 14:50 UTC (permalink / raw)
  To: Richard Guy Briggs
  Cc: Paul Moore, Ondrej Mosnacek, linux-api, containers, LKML,
	David Howells, Linux-Audit Mailing List, netfilter-devel,
	Eric W . Biederman, Simo Sorce, netdev, linux-fsdevel,
	Eric Paris, Serge E. Hallyn

On Thu, Mar 28, 2019 at 05:40:23PM -0400, Richard Guy Briggs wrote:
> On 2019-03-28 11:46, Paul Moore wrote:
> > On Wed, Mar 27, 2019 at 9:12 PM Richard Guy Briggs <rgb@redhat.com> wrote:
> > >
> > > On 2019-03-27 23:42, Ondrej Mosnacek wrote:
> > > > On Fri, Mar 15, 2019 at 7:35 PM Richard Guy Briggs <rgb@redhat.com> wrote:
> > > > > Audit events could happen in a network namespace outside of a task
> > > > > context due to packets received from the net that trigger an auditing
> > > > > rule prior to being associated with a running task.  The network
> > > > > namespace could be in use by multiple containers by association to the
> > > > > tasks in that network namespace.  We still want a way to attribute
> > > > > these events to any potential containers.  Keep a list per network
> > > > > namespace to track these audit container identifiiers.
> > > > >
> > > > > Add/increment the audit container identifier on:
> > > > > - initial setting of the audit container identifier via /proc
> > > > > - clone/fork call that inherits an audit container identifier
> > > > > - unshare call that inherits an audit container identifier
> > > > > - setns call that inherits an audit container identifier
> > > > > Delete/decrement the audit container identifier on:
> > > > > - an inherited audit container identifier dropped when child set
> > > > > - process exit
> > > > > - unshare call that drops a net namespace
> > > > > - setns call that drops a net namespace
> > > > >
> > > > > See: https://github.com/linux-audit/audit-kernel/issues/92
> > > > > See: https://github.com/linux-audit/audit-testsuite/issues/64
> > > > > See: https://github.com/linux-audit/audit-kernel/wiki/RFE-Audit-Container-ID
> > > > > Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> > > > > ---
> > > > >  include/linux/audit.h | 19 ++++++++++++
> > > > >  kernel/audit.c        | 86 +++++++++++++++++++++++++++++++++++++++++++++++++--
> > > > >  kernel/nsproxy.c      |  4 +++
> > > > >  3 files changed, 106 insertions(+), 3 deletions(-)
> > > > >
> > > > > diff --git a/include/linux/audit.h b/include/linux/audit.h
> > > > > index fa19fa408931..70255c2dfb9f 100644
> > > > > --- a/include/linux/audit.h
> > > > > +++ b/include/linux/audit.h
> > > > > @@ -27,6 +27,7 @@
> > > > >  #include <linux/ptrace.h>
> > > > >  #include <linux/namei.h>  /* LOOKUP_* */
> > > > >  #include <uapi/linux/audit.h>
> > > > > +#include <linux/refcount.h>
> > > > >
> > > > >  #define AUDIT_INO_UNSET ((unsigned long)-1)
> > > > >  #define AUDIT_DEV_UNSET ((dev_t)-1)
> > > > > @@ -99,6 +100,13 @@ struct audit_task_info {
> > > > >
> > > > >  extern struct audit_task_info init_struct_audit;
> > > > >
> > > > > +struct audit_contid {
> > > > > +       struct list_head        list;
> > > > > +       u64                     id;
> > > > > +       refcount_t              refcount;
> > > >
> > > > Hm, since we only ever touch the refcount under a spinlock, I wonder
> > > > if we could just make it a regular unsigned int (we don't need the
> > > > atomicity guarantees). OTOH, refcount_t comes with some extra overflow
> > > > checking, so it's probably better to leave it as is...
> > >
> > > Since the update is done using rcu-safe methods, do we even need the
> > > spin_lock?  Neil?  Paul?
> > 
> > As discussed, the refcount field is protected against simultaneous
> > writes by the spinlock that protects additions/removals from the list
> > as a whole so I don't believe the refcount_t atomicity is critical in
> > this regard.
> > 
> > Where it gets tricky, and I can't say I'm 100% confident on my answer
> > here, is if refcount was a regular int and we wanted to access it
> > outside of a spinlock (to be clear, it doesn't look like this patch
> > currently does this).  With RCU, if refcount was a regular int
> > (unsigned or otherwise), I believe it would be possible for different
> > threads of execution to potentially see different values of refcount
> > (assuming one thread was adding/removing from the list).  Using a
> > refcount_t would protect against this, alternatively, taking the
> > spinlock should also protect against this.
> 
> Ok, from the above it isn't clear to me if you are happy with the
> current code or would prefer any changes, or from below that you still
> need to work it through to make a pronouncement.  It sounds to me you
> would be ok with *either* spinlock *or* refcount_t, but don't see the
> need for both.
> 
I'll reiterate I think we should keep the refcount type just as it is, not for
safetys sake, but for readability and convienience.

Because the refcount currently only is used on add and delete operations
(implying it is only read in paths where its also modified), we need to
guarantee atomicity against multiple parallel writes.  We already have that
guarantee because every path in which we call
refcount_set/refcount_inc/refcount_dec_and_test occurs under the protection of
the list spin lock, and so from that standpoint we don't need the additional
guarantees offered by the refcount_t type.

However, if it were to be converted to an int type, we would have to replace the
refcount_dec_and_test call with this:
if (x == 0)
   warn_on_underflow
   return
x -= 1;
if (x == 0)
   preform_operations_to_free_list_entry

I find refcount_dec_and_test to be far easier to read and maintain, and you
still have to do all of this under the protection of a spin lock, to protect
against multiple writes.  And if you ever find that you are adding a pure read
side query of the refcount, you would need to hold the spin lock there as well,
instead of just using the available refcount_read api call

Yeah, you would save a few cycles if you didn't use an atomic type here, but
we're only talking about paths from user space making system calls executing
here (no high volume per packet receive paths or anything), and these paths have
already taken a few locks (the list lock, the task lock, etc), so eliminating
this one atomic isn't going to amount to anything.  Lets leave it as it is and
buy ourselves the extra code readability.

Neil

> > As we all know, RCU can be tricky at times, so I may be off on the
> > above; if I am, please provide an explanation so I (and likely others
> > as well) can learn a little bit more. :)
> > 
> > -- 
> > paul moore
> > www.paul-moore.com
> 
> - RGB
> 
> --
> Richard Guy Briggs <rgb@redhat.com>
> Sr. S/W Engineer, Kernel Security, Base Operating Systems
> Remote, Ottawa, Red Hat Canada
> IRC: rgb, SunRaycer
> Voice: +1.647.777.2635, Internal: (81) 32635
> 
> 

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH ghak90 V5 05/10] audit: add containerid support for ptrace and signals
  2019-03-28  2:04     ` Richard Guy Briggs
@ 2019-03-30 12:55       ` Richard Guy Briggs
  0 siblings, 0 replies; 64+ messages in thread
From: Richard Guy Briggs @ 2019-03-30 12:55 UTC (permalink / raw)
  To: Ondrej Mosnacek
  Cc: containers, linux-api, Linux-Audit Mailing List, linux-fsdevel,
	LKML, netdev, netfilter-devel, Paul Moore, Steve Grubb,
	David Howells, Simo Sorce, Eric Paris, Serge E. Hallyn,
	Eric W . Biederman, nhorman

On 2019-03-27 22:04, Richard Guy Briggs wrote:
> On 2019-03-27 22:17, Ondrej Mosnacek wrote:
> > On Fri, Mar 15, 2019 at 7:34 PM Richard Guy Briggs <rgb@redhat.com> wrote:
> > > Add audit container identifier support to ptrace and signals.  In
> > > particular, the "ref" field provides a way to label the auxiliary record
> > > to which it is associated.
> > >
> > > Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> > > Acked-by: Serge Hallyn <serge@hallyn.com>
> > > Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> > > ---
> > >  include/linux/audit.h |  1 +
> > >  kernel/audit.c        |  2 ++
> > >  kernel/audit.h        |  2 ++
> > >  kernel/auditsc.c      | 23 +++++++++++++++++------
> > >  4 files changed, 22 insertions(+), 6 deletions(-)
> > >
> > > diff --git a/include/linux/audit.h b/include/linux/audit.h
> > > index 43438192ca2a..ebd6625ca80e 100644
> > > --- a/include/linux/audit.h
> > > +++ b/include/linux/audit.h
> > > @@ -35,6 +35,7 @@ struct audit_sig_info {
> > >         uid_t           uid;
> > >         pid_t           pid;
> > >         char            ctx[0];
> > > +       u64             cid;
> > >  };
> > 
> > It seems like this structure implicitly defines the format of some
> > message that is sent to userspace... If so, how will userspace detect
> > that a new format (including the cid) is being used? Even assuming the
> > fixed order as pointed out by Neil, the message still seems to be
> > variable-sized so userspace cannot even use the length to infer that.
> > Am I missing something here? (I hope I am :)
> 
> How humble of you again.  No, you're not missing something.  This ends
> up being an api change...  That can be fixed in userspace by checking
> for AUDIT_FEATURE_BITMAP_CONTAINERID, but how do we make a newer kernel
> not break an older userspace...  I think this was the original rationale
> for adding it after the ctx but totally missing the fact that the latter
> is a variable-length field.

The way to address this on Steve Grubb's advice is to create a new
message type that incorporates a new struct with the structure above,
leaving the old one with the old message type deprecated.  I've coded
this up along with userspace support.

> This patch really should be split into audit_sig_cid changes in a patch
> by itself and target_cid changes which could go with the second and
> fourth patches.

I've also done this which Paul had already asked for, not quite in this
form.

I believe this addresses all the outstanding issues.

> > >  struct audit_buffer;
> > > diff --git a/kernel/audit.c b/kernel/audit.c
> > > index 8cc0e88d7f2a..cfa659b3f6c4 100644
> > > --- a/kernel/audit.c
> > > +++ b/kernel/audit.c
> > > @@ -138,6 +138,7 @@ struct audit_net {
> > >  kuid_t         audit_sig_uid = INVALID_UID;
> > >  pid_t          audit_sig_pid = -1;
> > >  u32            audit_sig_sid = 0;
> > > +u64            audit_sig_cid = AUDIT_CID_UNSET;
> > >
> > >  /* Records can be lost in several ways:
> > >     0) [suppressed in audit_alloc]
> > > @@ -1515,6 +1516,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
> > >                         memcpy(sig_data->ctx, ctx, len);
> > >                         security_release_secctx(ctx, len);
> > >                 }
> > > +               sig_data->cid = audit_sig_cid;
> > >                 audit_send_reply(skb, seq, AUDIT_SIGNAL_INFO, 0, 0,
> > >                                  sig_data, sizeof(*sig_data) + len);
> > >                 kfree(sig_data);
> > > diff --git a/kernel/audit.h b/kernel/audit.h
> > > index c00e2ee3c6b3..c5ac6436317e 100644
> > > --- a/kernel/audit.h
> > > +++ b/kernel/audit.h
> > > @@ -148,6 +148,7 @@ struct audit_context {
> > >         kuid_t              target_uid;
> > >         unsigned int        target_sessionid;
> > >         u32                 target_sid;
> > > +       u64                 target_cid;
> > >         char                target_comm[TASK_COMM_LEN];
> > >
> > >         struct audit_tree_refs *trees, *first_trees;
> > > @@ -344,6 +345,7 @@ extern void audit_filter_inodes(struct task_struct *tsk,
> > >  extern pid_t audit_sig_pid;
> > >  extern kuid_t audit_sig_uid;
> > >  extern u32 audit_sig_sid;
> > > +extern u64 audit_sig_cid;
> > >
> > >  extern int audit_filter(int msgtype, unsigned int listtype);
> > >
> > > diff --git a/kernel/auditsc.c b/kernel/auditsc.c
> > > index a8c8b44b954d..f04e115df5dc 100644
> > > --- a/kernel/auditsc.c
> > > +++ b/kernel/auditsc.c
> > > @@ -113,6 +113,7 @@ struct audit_aux_data_pids {
> > >         kuid_t                  target_uid[AUDIT_AUX_PIDS];
> > >         unsigned int            target_sessionid[AUDIT_AUX_PIDS];
> > >         u32                     target_sid[AUDIT_AUX_PIDS];
> > > +       u64                     target_cid[AUDIT_AUX_PIDS];
> > >         char                    target_comm[AUDIT_AUX_PIDS][TASK_COMM_LEN];
> > >         int                     pid_count;
> > >  };
> > > @@ -1514,7 +1515,7 @@ static void audit_log_exit(void)
> > >         for (aux = context->aux_pids; aux; aux = aux->next) {
> > >                 struct audit_aux_data_pids *axs = (void *)aux;
> > >
> > > -               for (i = 0; i < axs->pid_count; i++)
> > > +               for (i = 0; i < axs->pid_count; i++) {
> > >                         if (audit_log_pid_context(context, axs->target_pid[i],
> > >                                                   axs->target_auid[i],
> > >                                                   axs->target_uid[i],
> > > @@ -1522,14 +1523,20 @@ static void audit_log_exit(void)
> > >                                                   axs->target_sid[i],
> > >                                                   axs->target_comm[i]))
> > >                                 call_panic = 1;
> > > +                       audit_log_contid(context, axs->target_cid[i]);
> > > +               }
> > >         }
> > >
> > > -       if (context->target_pid &&
> > > -           audit_log_pid_context(context, context->target_pid,
> > > -                                 context->target_auid, context->target_uid,
> > > -                                 context->target_sessionid,
> > > -                                 context->target_sid, context->target_comm))
> > > +       if (context->target_pid) {
> > > +               if (audit_log_pid_context(context, context->target_pid,
> > > +                                         context->target_auid,
> > > +                                         context->target_uid,
> > > +                                         context->target_sessionid,
> > > +                                         context->target_sid,
> > > +                                         context->target_comm))
> > >                         call_panic = 1;
> > > +               audit_log_contid(context, context->target_cid);
> > > +       }
> > >
> > >         if (context->pwd.dentry && context->pwd.mnt) {
> > >                 ab = audit_log_start(context, GFP_KERNEL, AUDIT_CWD);
> > > @@ -2360,6 +2367,7 @@ void __audit_ptrace(struct task_struct *t)
> > >         context->target_uid = task_uid(t);
> > >         context->target_sessionid = audit_get_sessionid(t);
> > >         security_task_getsecid(t, &context->target_sid);
> > > +       context->target_cid = audit_get_contid(t);
> > >         memcpy(context->target_comm, t->comm, TASK_COMM_LEN);
> > >  }
> > >
> > > @@ -2387,6 +2395,7 @@ int audit_signal_info(int sig, struct task_struct *t)
> > >                 else
> > >                         audit_sig_uid = uid;
> > >                 security_task_getsecid(current, &audit_sig_sid);
> > > +               audit_sig_cid = audit_get_contid(current);
> > >         }
> > >
> > >         if (!audit_signals || audit_dummy_context())
> > > @@ -2400,6 +2409,7 @@ int audit_signal_info(int sig, struct task_struct *t)
> > >                 ctx->target_uid = t_uid;
> > >                 ctx->target_sessionid = audit_get_sessionid(t);
> > >                 security_task_getsecid(t, &ctx->target_sid);
> > > +               ctx->target_cid = audit_get_contid(t);
> > >                 memcpy(ctx->target_comm, t->comm, TASK_COMM_LEN);
> > >                 return 0;
> > >         }
> > > @@ -2421,6 +2431,7 @@ int audit_signal_info(int sig, struct task_struct *t)
> > >         axp->target_uid[axp->pid_count] = t_uid;
> > >         axp->target_sessionid[axp->pid_count] = audit_get_sessionid(t);
> > >         security_task_getsecid(t, &axp->target_sid[axp->pid_count]);
> > > +       axp->target_cid[axp->pid_count] = audit_get_contid(t);
> > >         memcpy(axp->target_comm[axp->pid_count], t->comm, TASK_COMM_LEN);
> > >         axp->pid_count++;
> > >
> > 
> > Ondrej Mosnacek <omosnace at redhat dot com>
> 
> - RGB

- RGB

--
Richard Guy Briggs <rgb@redhat.com>
Sr. S/W Engineer, Kernel Security, Base Operating Systems
Remote, Ottawa, Red Hat Canada
IRC: rgb, SunRaycer
Voice: +1.647.777.2635, Internal: (81) 32635

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH ghak90 V5 09/10] audit: add support for containerid to network namespaces
  2019-03-28 22:00           ` Paul Moore
@ 2019-03-31  2:11             ` Neil Horman
  0 siblings, 0 replies; 64+ messages in thread
From: Neil Horman @ 2019-03-31  2:11 UTC (permalink / raw)
  To: Paul Moore
  Cc: Richard Guy Briggs, Ondrej Mosnacek, linux-api, containers, LKML,
	David Howells, Linux-Audit Mailing List, netfilter-devel,
	Eric W . Biederman, Simo Sorce, netdev, linux-fsdevel,
	Eric Paris, Serge E. Hallyn

On Thu, Mar 28, 2019 at 06:00:21PM -0400, Paul Moore wrote:
> On Thu, Mar 28, 2019 at 5:40 PM Richard Guy Briggs <rgb@redhat.com> wrote:
> > On 2019-03-28 11:46, Paul Moore wrote:
> > > On Wed, Mar 27, 2019 at 9:12 PM Richard Guy Briggs <rgb@redhat.com> wrote:
> > > >
> > > > On 2019-03-27 23:42, Ondrej Mosnacek wrote:
> > > > > On Fri, Mar 15, 2019 at 7:35 PM Richard Guy Briggs <rgb@redhat.com> wrote:
> > > > > > Audit events could happen in a network namespace outside of a task
> > > > > > context due to packets received from the net that trigger an auditing
> > > > > > rule prior to being associated with a running task.  The network
> > > > > > namespace could be in use by multiple containers by association to the
> > > > > > tasks in that network namespace.  We still want a way to attribute
> > > > > > these events to any potential containers.  Keep a list per network
> > > > > > namespace to track these audit container identifiiers.
> > > > > >
> > > > > > Add/increment the audit container identifier on:
> > > > > > - initial setting of the audit container identifier via /proc
> > > > > > - clone/fork call that inherits an audit container identifier
> > > > > > - unshare call that inherits an audit container identifier
> > > > > > - setns call that inherits an audit container identifier
> > > > > > Delete/decrement the audit container identifier on:
> > > > > > - an inherited audit container identifier dropped when child set
> > > > > > - process exit
> > > > > > - unshare call that drops a net namespace
> > > > > > - setns call that drops a net namespace
> > > > > >
> > > > > > See: https://github.com/linux-audit/audit-kernel/issues/92
> > > > > > See: https://github.com/linux-audit/audit-testsuite/issues/64
> > > > > > See: https://github.com/linux-audit/audit-kernel/wiki/RFE-Audit-Container-ID
> > > > > > Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> > > > > > ---
> > > > > >  include/linux/audit.h | 19 ++++++++++++
> > > > > >  kernel/audit.c        | 86 +++++++++++++++++++++++++++++++++++++++++++++++++--
> > > > > >  kernel/nsproxy.c      |  4 +++
> > > > > >  3 files changed, 106 insertions(+), 3 deletions(-)
> > > > > >
> > > > > > diff --git a/include/linux/audit.h b/include/linux/audit.h
> > > > > > index fa19fa408931..70255c2dfb9f 100644
> > > > > > --- a/include/linux/audit.h
> > > > > > +++ b/include/linux/audit.h
> > > > > > @@ -27,6 +27,7 @@
> > > > > >  #include <linux/ptrace.h>
> > > > > >  #include <linux/namei.h>  /* LOOKUP_* */
> > > > > >  #include <uapi/linux/audit.h>
> > > > > > +#include <linux/refcount.h>
> > > > > >
> > > > > >  #define AUDIT_INO_UNSET ((unsigned long)-1)
> > > > > >  #define AUDIT_DEV_UNSET ((dev_t)-1)
> > > > > > @@ -99,6 +100,13 @@ struct audit_task_info {
> > > > > >
> > > > > >  extern struct audit_task_info init_struct_audit;
> > > > > >
> > > > > > +struct audit_contid {
> > > > > > +       struct list_head        list;
> > > > > > +       u64                     id;
> > > > > > +       refcount_t              refcount;
> > > > >
> > > > > Hm, since we only ever touch the refcount under a spinlock, I wonder
> > > > > if we could just make it a regular unsigned int (we don't need the
> > > > > atomicity guarantees). OTOH, refcount_t comes with some extra overflow
> > > > > checking, so it's probably better to leave it as is...
> > > >
> > > > Since the update is done using rcu-safe methods, do we even need the
> > > > spin_lock?  Neil?  Paul?
> > >
> > > As discussed, the refcount field is protected against simultaneous
> > > writes by the spinlock that protects additions/removals from the list
> > > as a whole so I don't believe the refcount_t atomicity is critical in
> > > this regard.
> > >
> > > Where it gets tricky, and I can't say I'm 100% confident on my answer
> > > here, is if refcount was a regular int and we wanted to access it
> > > outside of a spinlock (to be clear, it doesn't look like this patch
> > > currently does this).  With RCU, if refcount was a regular int
> > > (unsigned or otherwise), I believe it would be possible for different
> > > threads of execution to potentially see different values of refcount
> > > (assuming one thread was adding/removing from the list).  Using a
> > > refcount_t would protect against this, alternatively, taking the
> > > spinlock should also protect against this.
> >
> > Ok, from the above it isn't clear to me if you are happy with the
> > current code or would prefer any changes, or from below that you still
> > need to work it through to make a pronouncement.  It sounds to me you
> > would be ok with *either* spinlock *or* refcount_t, but don't see the
> > need for both.
> 
> To be fair you didn't ask if I was "happy" with the approach above,
> you asked if we needed the spinlock/refcount_t.  I believe I answered
> that question as comprehensively as I could, but perhaps you wanted a
> hard yes or no?  In that case, since refcount_t is obviously safer, I
> would stick with that for now just to limit the number of possible
> failures.  If someone smarter than you or I comes along and
> definitively says you are 100% safe to use an int, then go ahead and
> use an int.
> 
> Beyond that, I'm still in the process of reviewing your patches, but I
> haven't finished yet, so no "pronouncement" or whatever you want to
> call it.
> 

We definately need the spinlock, as its not meant to protect the refcount
alterations, its meant to protect parallel modifications to the list pointers.
Without the spinlock, the list can become corrupted (protecting the refcount is
just a byproduct).

Because of that byproduct, the atomicity of the refcount isn't required, and so
we could modify it to be an int or some other non-atomic ordinal type, but as I
noted, I don't think thats a good idea.  The refcount type helps denote clearly
what the variable is used for, making it more readable, and given the relative
non-performance critical path that the reference count is read/written in, and
the relatively more expensive locking we are already doing there, I think there
is more value in using the refcount to make the code legible than making
marginally more performant by altering it to be an int type.

Neil

> -- 
> paul moore
> www.paul-moore.com
> 

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH ghak90 V5 06/10] audit: add support for non-syscall auxiliary records
  2019-03-15 18:29 ` [PATCH ghak90 V5 06/10] audit: add support for non-syscall auxiliary records Richard Guy Briggs
  2019-03-18 19:34   ` Neil Horman
  2019-03-27 21:22   ` Ondrej Mosnacek
@ 2019-04-01 14:49   ` Paul Moore
  2019-04-01 17:44     ` Richard Guy Briggs
  2 siblings, 1 reply; 64+ messages in thread
From: Paul Moore @ 2019-04-01 14:49 UTC (permalink / raw)
  To: Richard Guy Briggs
  Cc: containers, linux-api, Linux-Audit Mailing List, linux-fsdevel,
	LKML, netdev, netfilter-devel, sgrubb, omosnace, dhowells, simo,
	Eric Paris, Serge Hallyn, ebiederm, nhorman

On Fri, Mar 15, 2019 at 2:34 PM Richard Guy Briggs <rgb@redhat.com> wrote:
> Standalone audit records have the timestamp and serial number generated
> on the fly and as such are unique, making them standalone.  This new
> function audit_alloc_local() generates a local audit context that will
> be used only for a standalone record and its auxiliary record(s).  The
> context is discarded immediately after the local associated records are
> produced.
>
> Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> Acked-by: Serge Hallyn <serge@hallyn.com>
> ---
>  include/linux/audit.h |  8 ++++++++
>  kernel/audit.h        |  1 +
>  kernel/auditsc.c      | 35 ++++++++++++++++++++++++++++++-----
>  3 files changed, 39 insertions(+), 5 deletions(-)

...

> diff --git a/include/linux/audit.h b/include/linux/audit.h
> index ebd6625ca80e..6db5aba7cc01 100644
> --- a/include/linux/audit.h
> +++ b/include/linux/audit.h
> @@ -285,6 +285,8 @@ static inline void audit_log_contid(struct audit_context *context, u64 contid)
>
>  /* These are defined in auditsc.c */
>                                 /* Public API */
> +extern struct audit_context *audit_alloc_local(gfp_t gfpflags);
> +extern void audit_free_context(struct audit_context *context);
>  extern void __audit_syscall_entry(int major, unsigned long a0, unsigned long a1,
>                                   unsigned long a2, unsigned long a3);
>  extern void __audit_syscall_exit(int ret_success, long ret_value);
> @@ -512,6 +514,12 @@ static inline void audit_fanotify(unsigned int response)
>  extern int audit_n_rules;
>  extern int audit_signals;
>  #else /* CONFIG_AUDITSYSCALL */
> +static inline struct audit_context *audit_alloc_local(gfp_t gfpflags)
> +{
> +       return NULL;
> +}
> +static inline void audit_free_context(struct audit_context *context)
> +{ }
>  static inline void audit_syscall_entry(int major, unsigned long a0,
>                                        unsigned long a1, unsigned long a2,
>                                        unsigned long a3)
> diff --git a/kernel/audit.h b/kernel/audit.h
> index c5ac6436317e..2a1a8b8a8019 100644
> --- a/kernel/audit.h
> +++ b/kernel/audit.h
> @@ -111,6 +111,7 @@ struct audit_proctitle {
>  struct audit_context {
>         int                 dummy;      /* must be the first element */
>         int                 in_syscall; /* 1 if task is in a syscall */
> +       bool                local;      /* local context needed */

It's very possible I've missed it, but "local" never gets used in any
meaningful way in this patchset does it?

>         enum audit_state    state, current_state;
>         unsigned int        serial;     /* serial number for record */
>         int                 major;      /* syscall number */

-- 
paul moore
www.paul-moore.com

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH ghak90 V5 09/10] audit: add support for containerid to network namespaces
  2019-03-15 18:29 ` [PATCH ghak90 V5 09/10] audit: add support for containerid to network namespaces Richard Guy Briggs
  2019-03-18 20:56   ` Neil Horman
  2019-03-27 22:42   ` Ondrej Mosnacek
@ 2019-04-01 14:50   ` Paul Moore
  2019-04-01 20:41     ` Richard Guy Briggs
  2019-04-02 11:31     ` Neil Horman
  2 siblings, 2 replies; 64+ messages in thread
From: Paul Moore @ 2019-04-01 14:50 UTC (permalink / raw)
  To: Richard Guy Briggs
  Cc: containers, linux-api, Linux-Audit Mailing List, linux-fsdevel,
	LKML, netdev, netfilter-devel, sgrubb, omosnace, dhowells, simo,
	Eric Paris, Serge Hallyn, ebiederm, nhorman

On Fri, Mar 15, 2019 at 2:35 PM Richard Guy Briggs <rgb@redhat.com> wrote:
> Audit events could happen in a network namespace outside of a task
> context due to packets received from the net that trigger an auditing
> rule prior to being associated with a running task.  The network
> namespace could be in use by multiple containers by association to the
> tasks in that network namespace.  We still want a way to attribute
> these events to any potential containers.  Keep a list per network
> namespace to track these audit container identifiiers.
>
> Add/increment the audit container identifier on:
> - initial setting of the audit container identifier via /proc
> - clone/fork call that inherits an audit container identifier
> - unshare call that inherits an audit container identifier
> - setns call that inherits an audit container identifier
> Delete/decrement the audit container identifier on:
> - an inherited audit container identifier dropped when child set
> - process exit
> - unshare call that drops a net namespace
> - setns call that drops a net namespace
>
> See: https://github.com/linux-audit/audit-kernel/issues/92
> See: https://github.com/linux-audit/audit-testsuite/issues/64
> See: https://github.com/linux-audit/audit-kernel/wiki/RFE-Audit-Container-ID
> Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> ---
>  include/linux/audit.h | 19 ++++++++++++
>  kernel/audit.c        | 86 +++++++++++++++++++++++++++++++++++++++++++++++++--
>  kernel/nsproxy.c      |  4 +++
>  3 files changed, 106 insertions(+), 3 deletions(-)

...

> diff --git a/kernel/audit.c b/kernel/audit.c
> index cf448599ef34..7fa3194f5342 100644
> --- a/kernel/audit.c
> +++ b/kernel/audit.c
> @@ -72,6 +72,7 @@
>  #include <linux/freezer.h>
>  #include <linux/pid_namespace.h>
>  #include <net/netns/generic.h>
> +#include <net/net_namespace.h>
>
>  #include "audit.h"
>
> @@ -99,9 +100,13 @@
>  /**
>   * struct audit_net - audit private network namespace data
>   * @sk: communication socket
> + * @contid_list: audit container identifier list
> + * @contid_list_lock audit container identifier list lock
>   */
>  struct audit_net {
>         struct sock *sk;
> +       struct list_head contid_list;
> +       spinlock_t contid_list_lock;
>  };
>
>  /**
> @@ -275,8 +280,11 @@ struct audit_task_info init_struct_audit = {
>  void audit_free(struct task_struct *tsk)
>  {
>         struct audit_task_info *info = tsk->audit;
> +       struct nsproxy *ns = tsk->nsproxy;
>
>         audit_free_syscall(tsk);
> +       if (ns)
> +               audit_netns_contid_del(ns->net_ns, audit_get_contid(tsk));
>         /* Freeing the audit_task_info struct must be performed after
>          * audit_log_exit() due to need for loginuid and sessionid.
>          */
> @@ -376,6 +384,73 @@ static struct sock *audit_get_sk(const struct net *net)
>         return aunet->sk;
>  }
>
> +void audit_netns_contid_add(struct net *net, u64 contid)
> +{
> +       struct audit_net *aunet = net_generic(net, audit_net_id);
> +       struct list_head *contid_list = &aunet->contid_list;
> +       struct audit_contid *cont;
> +
> +       if (!audit_contid_valid(contid))
> +               return;
> +       if (!aunet)
> +               return;

We should move the contid_list assignment below this check, or decide
that aunet is always going to valid (?) and get rid of this check
completely.

> +       spin_lock(&aunet->contid_list_lock);
> +       if (!list_empty(contid_list))

We don't need the list_empty() check here do we?  I think we can just
call list_for_each_entry_rcu(), yes?

> +               list_for_each_entry_rcu(cont, contid_list, list)
> +                       if (cont->id == contid) {
> +                               refcount_inc(&cont->refcount);
> +                               goto out;
> +                       }
> +       cont = kmalloc(sizeof(struct audit_contid), GFP_ATOMIC);

If you had to guess, what do you think is going to be more common:
bumping the refcount of an existing entry in the list, or adding a new
entry?  I'm asking because I always get a little nervous when doing
allocations while holding a spinlock.  Yes, you are doing it with
GFP_ATOMIC, but it still seems like something to try and avoid if this
is going to approach 50%.  However, if the new entry is rare then the
extra work of always doing the allocation before taking the lock and
then freeing it afterwards might be a bad tradeoff.

My gut feeling says we might do about as many allocations as refcount
bumps, but I could be thinking about this wrong.

Moving the allocation outside the spinlock might also open the door to
doing this as GFP_KERNEL, which is a good thing, but I haven't looked
at the callers to see if that is possible (it may not be).  That's an
exercise left to the patch author (if he hasn't done that already).

> +       if (cont) {
> +               INIT_LIST_HEAD(&cont->list);

Unless there is some guidance that INIT_LIST_HEAD() should be used
regardless, you shouldn't need to call this here since list_add_rcu()
will take care of any list.h related initialization.

> +               cont->id = contid;
> +               refcount_set(&cont->refcount, 1);
> +               list_add_rcu(&cont->list, contid_list);
> +       }
> +out:
> +       spin_unlock(&aunet->contid_list_lock);
> +}

-- 
paul moore
www.paul-moore.com

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH ghak90 V5 10/10] audit: NETFILTER_PKT: record each container ID associated with a netNS
  2019-03-15 18:29 ` [PATCH ghak90 V5 10/10] audit: NETFILTER_PKT: record each container ID associated with a netNS Richard Guy Briggs
  2019-03-18 20:58   ` Neil Horman
  2019-03-27 22:52   ` Ondrej Mosnacek
@ 2019-04-01 14:50   ` Paul Moore
  2019-04-01 17:50     ` Richard Guy Briggs
  2 siblings, 1 reply; 64+ messages in thread
From: Paul Moore @ 2019-04-01 14:50 UTC (permalink / raw)
  To: Richard Guy Briggs
  Cc: containers, linux-api, Linux-Audit Mailing List, linux-fsdevel,
	LKML, netdev, netfilter-devel, sgrubb, omosnace, dhowells, simo,
	Eric Paris, Serge Hallyn, ebiederm, nhorman

On Fri, Mar 15, 2019 at 2:35 PM Richard Guy Briggs <rgb@redhat.com> wrote:
> Add audit container identifier auxiliary record(s) to NETFILTER_PKT
> event standalone records.  Iterate through all potential audit container
> identifiers associated with a network namespace.
>
> Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> ---
>  include/linux/audit.h    |  5 +++++
>  kernel/audit.c           | 41 +++++++++++++++++++++++++++++++++++++++++
>  net/netfilter/nft_log.c  | 11 +++++++++--
>  net/netfilter/xt_AUDIT.c | 11 +++++++++--
>  4 files changed, 64 insertions(+), 4 deletions(-)

...

> diff --git a/kernel/audit.c b/kernel/audit.c
> index 7fa3194f5342..80ed323feeb5 100644
> --- a/kernel/audit.c
> +++ b/kernel/audit.c
> @@ -451,6 +451,47 @@ void audit_switch_task_namespaces(struct nsproxy *ns, struct task_struct *p)
>                 audit_netns_contid_add(new->net_ns, contid);
>  }
>
> +/**
> + * audit_log_netns_contid_list - List contids for the given network namespace
> + * @net: the network namespace of interest
> + * @context: the audit context to use
> + *
> + * Description:
> + * Issues a CONTAINER_ID record with a CSV list of contids associated
> + * with a network namespace to accompany a NETFILTER_PKT record.
> + */
> +void audit_log_netns_contid_list(struct net *net, struct audit_context *context)
> +{
> +       struct audit_buffer *ab = NULL;
> +       struct audit_contid *cont;
> +       bool first = true;
> +       struct audit_net *aunet;
> +
> +       /* Generate AUDIT_CONTAINER_ID record with container ID CSV list */
> +       rcu_read_lock();
> +       aunet = net_generic(net, audit_net_id);
> +       if (!aunet)
> +               goto out;
> +       list_for_each_entry_rcu(cont, &aunet->contid_list, list) {
> +               if (first) {

This is borderline nit-picky, but it seems like we could get rid of
"first" and just check to see if "ab" is still NULL.

> +                       ab = audit_log_start(context, GFP_ATOMIC,
> +                                            AUDIT_CONTAINER_ID);
> +                       if (!ab) {
> +                               audit_log_lost("out of memory in audit_log_netns_contid_list");
> +                               goto out;
> +                       }
> +                       audit_log_format(ab, "contid=");
> +               } else
> +                       audit_log_format(ab, ",");
> +               audit_log_format(ab, "%llu", cont->id);
> +               first = false;
> +       }
> +       audit_log_end(ab);
> +out:
> +       rcu_read_unlock();
> +}
> +EXPORT_SYMBOL(audit_log_netns_contid_list);

-- 
paul moore
www.paul-moore.com

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH ghak90 V5 06/10] audit: add support for non-syscall auxiliary records
  2019-04-01 14:49   ` Paul Moore
@ 2019-04-01 17:44     ` Richard Guy Briggs
  2019-04-01 18:57       ` Paul Moore
  0 siblings, 1 reply; 64+ messages in thread
From: Richard Guy Briggs @ 2019-04-01 17:44 UTC (permalink / raw)
  To: Paul Moore
  Cc: containers, linux-api, Linux-Audit Mailing List, linux-fsdevel,
	LKML, netdev, netfilter-devel, sgrubb, omosnace, dhowells, simo,
	Eric Paris, Serge Hallyn, ebiederm, nhorman

On 2019-04-01 10:49, Paul Moore wrote:
> On Fri, Mar 15, 2019 at 2:34 PM Richard Guy Briggs <rgb@redhat.com> wrote:
> > Standalone audit records have the timestamp and serial number generated
> > on the fly and as such are unique, making them standalone.  This new
> > function audit_alloc_local() generates a local audit context that will
> > be used only for a standalone record and its auxiliary record(s).  The
> > context is discarded immediately after the local associated records are
> > produced.
> >
> > Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> > Acked-by: Serge Hallyn <serge@hallyn.com>
> > ---
> >  include/linux/audit.h |  8 ++++++++
> >  kernel/audit.h        |  1 +
> >  kernel/auditsc.c      | 35 ++++++++++++++++++++++++++++++-----
> >  3 files changed, 39 insertions(+), 5 deletions(-)
> 
> ...
> 
> > diff --git a/include/linux/audit.h b/include/linux/audit.h
> > index ebd6625ca80e..6db5aba7cc01 100644
> > --- a/include/linux/audit.h
> > +++ b/include/linux/audit.h
> > @@ -285,6 +285,8 @@ static inline void audit_log_contid(struct audit_context *context, u64 contid)
> >
> >  /* These are defined in auditsc.c */
> >                                 /* Public API */
> > +extern struct audit_context *audit_alloc_local(gfp_t gfpflags);
> > +extern void audit_free_context(struct audit_context *context);
> >  extern void __audit_syscall_entry(int major, unsigned long a0, unsigned long a1,
> >                                   unsigned long a2, unsigned long a3);
> >  extern void __audit_syscall_exit(int ret_success, long ret_value);
> > @@ -512,6 +514,12 @@ static inline void audit_fanotify(unsigned int response)
> >  extern int audit_n_rules;
> >  extern int audit_signals;
> >  #else /* CONFIG_AUDITSYSCALL */
> > +static inline struct audit_context *audit_alloc_local(gfp_t gfpflags)
> > +{
> > +       return NULL;
> > +}
> > +static inline void audit_free_context(struct audit_context *context)
> > +{ }
> >  static inline void audit_syscall_entry(int major, unsigned long a0,
> >                                        unsigned long a1, unsigned long a2,
> >                                        unsigned long a3)
> > diff --git a/kernel/audit.h b/kernel/audit.h
> > index c5ac6436317e..2a1a8b8a8019 100644
> > --- a/kernel/audit.h
> > +++ b/kernel/audit.h
> > @@ -111,6 +111,7 @@ struct audit_proctitle {
> >  struct audit_context {
> >         int                 dummy;      /* must be the first element */
> >         int                 in_syscall; /* 1 if task is in a syscall */
> > +       bool                local;      /* local context needed */
> 
> It's very possible I've missed it, but "local" never gets used in any
> meaningful way in this patchset does it?

It is used in audit_alloc_local() to signal to audit_get_stamp() that in
absence of a syscall flag, check for a local flag to continue rather
than return.

> >         enum audit_state    state, current_state;
> >         unsigned int        serial;     /* serial number for record */
> >         int                 major;      /* syscall number */
> 
> paul moore

- RGB

--
Richard Guy Briggs <rgb@redhat.com>
Sr. S/W Engineer, Kernel Security, Base Operating Systems
Remote, Ottawa, Red Hat Canada
IRC: rgb, SunRaycer
Voice: +1.647.777.2635, Internal: (81) 32635

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH ghak90 V5 10/10] audit: NETFILTER_PKT: record each container ID associated with a netNS
  2019-04-01 14:50   ` Paul Moore
@ 2019-04-01 17:50     ` Richard Guy Briggs
  0 siblings, 0 replies; 64+ messages in thread
From: Richard Guy Briggs @ 2019-04-01 17:50 UTC (permalink / raw)
  To: Paul Moore
  Cc: containers, linux-api, Linux-Audit Mailing List, linux-fsdevel,
	LKML, netdev, netfilter-devel, sgrubb, omosnace, dhowells, simo,
	Eric Paris, Serge Hallyn, ebiederm, nhorman

On 2019-04-01 10:50, Paul Moore wrote:
> On Fri, Mar 15, 2019 at 2:35 PM Richard Guy Briggs <rgb@redhat.com> wrote:
> > Add audit container identifier auxiliary record(s) to NETFILTER_PKT
> > event standalone records.  Iterate through all potential audit container
> > identifiers associated with a network namespace.
> >
> > Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> > ---
> >  include/linux/audit.h    |  5 +++++
> >  kernel/audit.c           | 41 +++++++++++++++++++++++++++++++++++++++++
> >  net/netfilter/nft_log.c  | 11 +++++++++--
> >  net/netfilter/xt_AUDIT.c | 11 +++++++++--
> >  4 files changed, 64 insertions(+), 4 deletions(-)
> 
> ...
> 
> > diff --git a/kernel/audit.c b/kernel/audit.c
> > index 7fa3194f5342..80ed323feeb5 100644
> > --- a/kernel/audit.c
> > +++ b/kernel/audit.c
> > @@ -451,6 +451,47 @@ void audit_switch_task_namespaces(struct nsproxy *ns, struct task_struct *p)
> >                 audit_netns_contid_add(new->net_ns, contid);
> >  }
> >
> > +/**
> > + * audit_log_netns_contid_list - List contids for the given network namespace
> > + * @net: the network namespace of interest
> > + * @context: the audit context to use
> > + *
> > + * Description:
> > + * Issues a CONTAINER_ID record with a CSV list of contids associated
> > + * with a network namespace to accompany a NETFILTER_PKT record.
> > + */
> > +void audit_log_netns_contid_list(struct net *net, struct audit_context *context)
> > +{
> > +       struct audit_buffer *ab = NULL;
> > +       struct audit_contid *cont;
> > +       bool first = true;
> > +       struct audit_net *aunet;
> > +
> > +       /* Generate AUDIT_CONTAINER_ID record with container ID CSV list */
> > +       rcu_read_lock();
> > +       aunet = net_generic(net, audit_net_id);
> > +       if (!aunet)
> > +               goto out;
> > +       list_for_each_entry_rcu(cont, &aunet->contid_list, list) {
> > +               if (first) {
> 
> This is borderline nit-picky, but it seems like we could get rid of
> "first" and just check to see if "ab" is still NULL.

Yes, this is a better way, thank you.

> > +                       ab = audit_log_start(context, GFP_ATOMIC,
> > +                                            AUDIT_CONTAINER_ID);
> > +                       if (!ab) {
> > +                               audit_log_lost("out of memory in audit_log_netns_contid_list");
> > +                               goto out;
> > +                       }
> > +                       audit_log_format(ab, "contid=");
> > +               } else
> > +                       audit_log_format(ab, ",");
> > +               audit_log_format(ab, "%llu", cont->id);
> > +               first = false;
> > +       }
> > +       audit_log_end(ab);
> > +out:
> > +       rcu_read_unlock();
> > +}
> > +EXPORT_SYMBOL(audit_log_netns_contid_list);
> 
> paul moore

- RGB

--
Richard Guy Briggs <rgb@redhat.com>
Sr. S/W Engineer, Kernel Security, Base Operating Systems
Remote, Ottawa, Red Hat Canada
IRC: rgb, SunRaycer
Voice: +1.647.777.2635, Internal: (81) 32635

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH ghak90 V5 06/10] audit: add support for non-syscall auxiliary records
  2019-04-01 17:44     ` Richard Guy Briggs
@ 2019-04-01 18:57       ` Paul Moore
  2019-04-01 20:43         ` Richard Guy Briggs
  0 siblings, 1 reply; 64+ messages in thread
From: Paul Moore @ 2019-04-01 18:57 UTC (permalink / raw)
  To: Richard Guy Briggs
  Cc: containers, linux-api, Linux-Audit Mailing List, linux-fsdevel,
	LKML, netdev, netfilter-devel, sgrubb, omosnace, dhowells, simo,
	Eric Paris, Serge Hallyn, ebiederm, nhorman

On Mon, Apr 1, 2019 at 1:44 PM Richard Guy Briggs <rgb@redhat.com> wrote:
> On 2019-04-01 10:49, Paul Moore wrote:
> > On Fri, Mar 15, 2019 at 2:34 PM Richard Guy Briggs <rgb@redhat.com> wrote:
> > > Standalone audit records have the timestamp and serial number generated
> > > on the fly and as such are unique, making them standalone.  This new
> > > function audit_alloc_local() generates a local audit context that will
> > > be used only for a standalone record and its auxiliary record(s).  The
> > > context is discarded immediately after the local associated records are
> > > produced.
> > >
> > > Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> > > Acked-by: Serge Hallyn <serge@hallyn.com>
> > > ---
> > >  include/linux/audit.h |  8 ++++++++
> > >  kernel/audit.h        |  1 +
> > >  kernel/auditsc.c      | 35 ++++++++++++++++++++++++++++++-----
> > >  3 files changed, 39 insertions(+), 5 deletions(-)
> >
> > ...
> >
> > > diff --git a/include/linux/audit.h b/include/linux/audit.h
> > > index ebd6625ca80e..6db5aba7cc01 100644
> > > --- a/include/linux/audit.h
> > > +++ b/include/linux/audit.h
> > > @@ -285,6 +285,8 @@ static inline void audit_log_contid(struct audit_context *context, u64 contid)
> > >
> > >  /* These are defined in auditsc.c */
> > >                                 /* Public API */
> > > +extern struct audit_context *audit_alloc_local(gfp_t gfpflags);
> > > +extern void audit_free_context(struct audit_context *context);
> > >  extern void __audit_syscall_entry(int major, unsigned long a0, unsigned long a1,
> > >                                   unsigned long a2, unsigned long a3);
> > >  extern void __audit_syscall_exit(int ret_success, long ret_value);
> > > @@ -512,6 +514,12 @@ static inline void audit_fanotify(unsigned int response)
> > >  extern int audit_n_rules;
> > >  extern int audit_signals;
> > >  #else /* CONFIG_AUDITSYSCALL */
> > > +static inline struct audit_context *audit_alloc_local(gfp_t gfpflags)
> > > +{
> > > +       return NULL;
> > > +}
> > > +static inline void audit_free_context(struct audit_context *context)
> > > +{ }
> > >  static inline void audit_syscall_entry(int major, unsigned long a0,
> > >                                        unsigned long a1, unsigned long a2,
> > >                                        unsigned long a3)
> > > diff --git a/kernel/audit.h b/kernel/audit.h
> > > index c5ac6436317e..2a1a8b8a8019 100644
> > > --- a/kernel/audit.h
> > > +++ b/kernel/audit.h
> > > @@ -111,6 +111,7 @@ struct audit_proctitle {
> > >  struct audit_context {
> > >         int                 dummy;      /* must be the first element */
> > >         int                 in_syscall; /* 1 if task is in a syscall */
> > > +       bool                local;      /* local context needed */
> >
> > It's very possible I've missed it, but "local" never gets used in any
> > meaningful way in this patchset does it?
>
> It is used in audit_alloc_local() to signal to audit_get_stamp() that in
> absence of a syscall flag, check for a local flag to continue rather
> than return.

I'm guessing you meant auditsc_get_stamp()?  If so, okay.

-- 
paul moore
www.paul-moore.com

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH ghak90 V5 09/10] audit: add support for containerid to network namespaces
  2019-04-01 14:50   ` Paul Moore
@ 2019-04-01 20:41     ` Richard Guy Briggs
  2019-04-02 11:31     ` Neil Horman
  1 sibling, 0 replies; 64+ messages in thread
From: Richard Guy Briggs @ 2019-04-01 20:41 UTC (permalink / raw)
  To: Paul Moore
  Cc: containers, linux-api, Linux-Audit Mailing List, linux-fsdevel,
	LKML, netdev, netfilter-devel, sgrubb, omosnace, dhowells, simo,
	Eric Paris, Serge Hallyn, ebiederm, nhorman

On 2019-04-01 10:50, Paul Moore wrote:
> On Fri, Mar 15, 2019 at 2:35 PM Richard Guy Briggs <rgb@redhat.com> wrote:
> > Audit events could happen in a network namespace outside of a task
> > context due to packets received from the net that trigger an auditing
> > rule prior to being associated with a running task.  The network
> > namespace could be in use by multiple containers by association to the
> > tasks in that network namespace.  We still want a way to attribute
> > these events to any potential containers.  Keep a list per network
> > namespace to track these audit container identifiiers.
> >
> > Add/increment the audit container identifier on:
> > - initial setting of the audit container identifier via /proc
> > - clone/fork call that inherits an audit container identifier
> > - unshare call that inherits an audit container identifier
> > - setns call that inherits an audit container identifier
> > Delete/decrement the audit container identifier on:
> > - an inherited audit container identifier dropped when child set
> > - process exit
> > - unshare call that drops a net namespace
> > - setns call that drops a net namespace
> >
> > See: https://github.com/linux-audit/audit-kernel/issues/92
> > See: https://github.com/linux-audit/audit-testsuite/issues/64
> > See: https://github.com/linux-audit/audit-kernel/wiki/RFE-Audit-Container-ID
> > Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> > ---
> >  include/linux/audit.h | 19 ++++++++++++
> >  kernel/audit.c        | 86 +++++++++++++++++++++++++++++++++++++++++++++++++--
> >  kernel/nsproxy.c      |  4 +++
> >  3 files changed, 106 insertions(+), 3 deletions(-)
> 
> ...
> 
> > diff --git a/kernel/audit.c b/kernel/audit.c
> > index cf448599ef34..7fa3194f5342 100644
> > --- a/kernel/audit.c
> > +++ b/kernel/audit.c
> > @@ -72,6 +72,7 @@
> >  #include <linux/freezer.h>
> >  #include <linux/pid_namespace.h>
> >  #include <net/netns/generic.h>
> > +#include <net/net_namespace.h>
> >
> >  #include "audit.h"
> >
> > @@ -99,9 +100,13 @@
> >  /**
> >   * struct audit_net - audit private network namespace data
> >   * @sk: communication socket
> > + * @contid_list: audit container identifier list
> > + * @contid_list_lock audit container identifier list lock
> >   */
> >  struct audit_net {
> >         struct sock *sk;
> > +       struct list_head contid_list;
> > +       spinlock_t contid_list_lock;
> >  };
> >
> >  /**
> > @@ -275,8 +280,11 @@ struct audit_task_info init_struct_audit = {
> >  void audit_free(struct task_struct *tsk)
> >  {
> >         struct audit_task_info *info = tsk->audit;
> > +       struct nsproxy *ns = tsk->nsproxy;
> >
> >         audit_free_syscall(tsk);
> > +       if (ns)
> > +               audit_netns_contid_del(ns->net_ns, audit_get_contid(tsk));
> >         /* Freeing the audit_task_info struct must be performed after
> >          * audit_log_exit() due to need for loginuid and sessionid.
> >          */
> > @@ -376,6 +384,73 @@ static struct sock *audit_get_sk(const struct net *net)
> >         return aunet->sk;
> >  }
> >
> > +void audit_netns_contid_add(struct net *net, u64 contid)
> > +{
> > +       struct audit_net *aunet = net_generic(net, audit_net_id);
> > +       struct list_head *contid_list = &aunet->contid_list;
> > +       struct audit_contid *cont;
> > +
> > +       if (!audit_contid_valid(contid))
> > +               return;
> > +       if (!aunet)
> > +               return;
> 
> We should move the contid_list assignment below this check, or decide
> that aunet is always going to valid (?) and get rid of this check
> completely.

Yes, we should move the contid_list assignment below the aunet check.
At this point, testing has revlealed that audit_netns_contid_del() is
being called very infrequently (very early) with invalid net or aunet
which is why its code has been re-arranged to safeguard against it.  So
far, audit_netns_contid_add() has not had this problem, but I'd feel
safer leaving the check in and to make that check relevant (rather than
the contid_list assignment panicing) I'll move that assignment.

> > +       spin_lock(&aunet->contid_list_lock);
> > +       if (!list_empty(contid_list))
> 
> We don't need the list_empty() check here do we?  I think we can just
> call list_for_each_entry_rcu(), yes?

Yes, you appear to be correct.  The examples in auditfilter.c and
auditsc.c are stale since the original optimizations they were
protecting are no longer present, but the practice was copied by several
maintainers since.  I'll fix this and address the others seperately.

> > +               list_for_each_entry_rcu(cont, contid_list, list)
> > +                       if (cont->id == contid) {
> > +                               refcount_inc(&cont->refcount);
> > +                               goto out;
> > +                       }
> > +       cont = kmalloc(sizeof(struct audit_contid), GFP_ATOMIC);
> 
> If you had to guess, what do you think is going to be more common:
> bumping the refcount of an existing entry in the list, or adding a new
> entry?  I'm asking because I always get a little nervous when doing
> allocations while holding a spinlock.  Yes, you are doing it with
> GFP_ATOMIC, but it still seems like something to try and avoid if this
> is going to approach 50%.  However, if the new entry is rare then the
> extra work of always doing the allocation before taking the lock and
> then freeing it afterwards might be a bad tradeoff.
> 
> My gut feeling says we might do about as many allocations as refcount
> bumps, but I could be thinking about this wrong.

I'm sure we could find extreme use cases in both directions.  One
extreme is one task per container.  The other extreme is a distro
container where all processes for an entire O/S running in a container
just use the refcount.  The former seems more likely at this point.  We
break even at two tasks per container.

I'm willing to switch this over to alloc/dealloc and use GFP_KERNEL
which will inevitably make some kernel maintainers happier and others
cringe.  This could be a good candidate for kmem_cache since it is a
fixed size.

> Moving the allocation outside the spinlock might also open the door to
> doing this as GFP_KERNEL, which is a good thing, but I haven't looked
> at the callers to see if that is possible (it may not be).  That's an
> exercise left to the patch author (if he hasn't done that already).

Switching to GFP_KERNEL is certainly preferable.  None of the callers
will have a problem with that.

> > +       if (cont) {
> > +               INIT_LIST_HEAD(&cont->list);
> 
> Unless there is some guidance that INIT_LIST_HEAD() should be used
> regardless, you shouldn't need to call this here since list_add_rcu()
> will take care of any list.h related initialization.

I see enough examples without that suggest it isn't necessary.  I'll
remove it.

> > +               cont->id = contid;
> > +               refcount_set(&cont->refcount, 1);
> > +               list_add_rcu(&cont->list, contid_list);
> > +       }
> > +out:
> > +       spin_unlock(&aunet->contid_list_lock);
> > +}
> 
> paul moore

- RGB

--
Richard Guy Briggs <rgb@redhat.com>
Sr. S/W Engineer, Kernel Security, Base Operating Systems
Remote, Ottawa, Red Hat Canada
IRC: rgb, SunRaycer
Voice: +1.647.777.2635, Internal: (81) 32635

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH ghak90 V5 06/10] audit: add support for non-syscall auxiliary records
  2019-04-01 18:57       ` Paul Moore
@ 2019-04-01 20:43         ` Richard Guy Briggs
  0 siblings, 0 replies; 64+ messages in thread
From: Richard Guy Briggs @ 2019-04-01 20:43 UTC (permalink / raw)
  To: Paul Moore
  Cc: nhorman, linux-api, containers, LKML, dhowells,
	Linux-Audit Mailing List, netfilter-devel, ebiederm, simo,
	netdev, linux-fsdevel, Eric Paris, Serge Hallyn

On 2019-04-01 14:57, Paul Moore wrote:
> On Mon, Apr 1, 2019 at 1:44 PM Richard Guy Briggs <rgb@redhat.com> wrote:
> > On 2019-04-01 10:49, Paul Moore wrote:
> > > On Fri, Mar 15, 2019 at 2:34 PM Richard Guy Briggs <rgb@redhat.com> wrote:
> > > > Standalone audit records have the timestamp and serial number generated
> > > > on the fly and as such are unique, making them standalone.  This new
> > > > function audit_alloc_local() generates a local audit context that will
> > > > be used only for a standalone record and its auxiliary record(s).  The
> > > > context is discarded immediately after the local associated records are
> > > > produced.
> > > >
> > > > Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> > > > Acked-by: Serge Hallyn <serge@hallyn.com>
> > > > ---
> > > >  include/linux/audit.h |  8 ++++++++
> > > >  kernel/audit.h        |  1 +
> > > >  kernel/auditsc.c      | 35 ++++++++++++++++++++++++++++++-----
> > > >  3 files changed, 39 insertions(+), 5 deletions(-)
> > >
> > > ...
> > >
> > > > diff --git a/include/linux/audit.h b/include/linux/audit.h
> > > > index ebd6625ca80e..6db5aba7cc01 100644
> > > > --- a/include/linux/audit.h
> > > > +++ b/include/linux/audit.h
> > > > @@ -285,6 +285,8 @@ static inline void audit_log_contid(struct audit_context *context, u64 contid)
> > > >
> > > >  /* These are defined in auditsc.c */
> > > >                                 /* Public API */
> > > > +extern struct audit_context *audit_alloc_local(gfp_t gfpflags);
> > > > +extern void audit_free_context(struct audit_context *context);
> > > >  extern void __audit_syscall_entry(int major, unsigned long a0, unsigned long a1,
> > > >                                   unsigned long a2, unsigned long a3);
> > > >  extern void __audit_syscall_exit(int ret_success, long ret_value);
> > > > @@ -512,6 +514,12 @@ static inline void audit_fanotify(unsigned int response)
> > > >  extern int audit_n_rules;
> > > >  extern int audit_signals;
> > > >  #else /* CONFIG_AUDITSYSCALL */
> > > > +static inline struct audit_context *audit_alloc_local(gfp_t gfpflags)
> > > > +{
> > > > +       return NULL;
> > > > +}
> > > > +static inline void audit_free_context(struct audit_context *context)
> > > > +{ }
> > > >  static inline void audit_syscall_entry(int major, unsigned long a0,
> > > >                                        unsigned long a1, unsigned long a2,
> > > >                                        unsigned long a3)
> > > > diff --git a/kernel/audit.h b/kernel/audit.h
> > > > index c5ac6436317e..2a1a8b8a8019 100644
> > > > --- a/kernel/audit.h
> > > > +++ b/kernel/audit.h
> > > > @@ -111,6 +111,7 @@ struct audit_proctitle {
> > > >  struct audit_context {
> > > >         int                 dummy;      /* must be the first element */
> > > >         int                 in_syscall; /* 1 if task is in a syscall */
> > > > +       bool                local;      /* local context needed */
> > >
> > > It's very possible I've missed it, but "local" never gets used in any
> > > meaningful way in this patchset does it?
> >
> > It is used in audit_alloc_local() to signal to audit_get_stamp() that in
> > absence of a syscall flag, check for a local flag to continue rather
> > than return.
> 
> I'm guessing you meant auditsc_get_stamp()?  If so, okay.

Yes.  (I thought I remembered typing "auditsc...".)

> paul moore

- RGB

--
Richard Guy Briggs <rgb@redhat.com>
Sr. S/W Engineer, Kernel Security, Base Operating Systems
Remote, Ottawa, Red Hat Canada
IRC: rgb, SunRaycer
Voice: +1.647.777.2635, Internal: (81) 32635

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH ghak90 V5 09/10] audit: add support for containerid to network namespaces
  2019-04-01 14:50   ` Paul Moore
  2019-04-01 20:41     ` Richard Guy Briggs
@ 2019-04-02 11:31     ` Neil Horman
  2019-04-02 13:31       ` Paul Moore
  2019-04-04 21:40       ` Richard Guy Briggs
  1 sibling, 2 replies; 64+ messages in thread
From: Neil Horman @ 2019-04-02 11:31 UTC (permalink / raw)
  To: Paul Moore
  Cc: Richard Guy Briggs, containers, linux-api,
	Linux-Audit Mailing List, linux-fsdevel, LKML, netdev,
	netfilter-devel, sgrubb, omosnace, dhowells, simo, Eric Paris,
	Serge Hallyn, ebiederm

On Mon, Apr 01, 2019 at 10:50:03AM -0400, Paul Moore wrote:
> On Fri, Mar 15, 2019 at 2:35 PM Richard Guy Briggs <rgb@redhat.com> wrote:
> > Audit events could happen in a network namespace outside of a task
> > context due to packets received from the net that trigger an auditing
> > rule prior to being associated with a running task.  The network
> > namespace could be in use by multiple containers by association to the
> > tasks in that network namespace.  We still want a way to attribute
> > these events to any potential containers.  Keep a list per network
> > namespace to track these audit container identifiiers.
> >
> > Add/increment the audit container identifier on:
> > - initial setting of the audit container identifier via /proc
> > - clone/fork call that inherits an audit container identifier
> > - unshare call that inherits an audit container identifier
> > - setns call that inherits an audit container identifier
> > Delete/decrement the audit container identifier on:
> > - an inherited audit container identifier dropped when child set
> > - process exit
> > - unshare call that drops a net namespace
> > - setns call that drops a net namespace
> >
> > See: https://github.com/linux-audit/audit-kernel/issues/92
> > See: https://github.com/linux-audit/audit-testsuite/issues/64
> > See: https://github.com/linux-audit/audit-kernel/wiki/RFE-Audit-Container-ID
> > Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> > ---
> >  include/linux/audit.h | 19 ++++++++++++
> >  kernel/audit.c        | 86 +++++++++++++++++++++++++++++++++++++++++++++++++--
> >  kernel/nsproxy.c      |  4 +++
> >  3 files changed, 106 insertions(+), 3 deletions(-)
> 
> ...
> 
> > diff --git a/kernel/audit.c b/kernel/audit.c
> > index cf448599ef34..7fa3194f5342 100644
> > --- a/kernel/audit.c
> > +++ b/kernel/audit.c
> > @@ -72,6 +72,7 @@
> >  #include <linux/freezer.h>
> >  #include <linux/pid_namespace.h>
> >  #include <net/netns/generic.h>
> > +#include <net/net_namespace.h>
> >
> >  #include "audit.h"
> >
> > @@ -99,9 +100,13 @@
> >  /**
> >   * struct audit_net - audit private network namespace data
> >   * @sk: communication socket
> > + * @contid_list: audit container identifier list
> > + * @contid_list_lock audit container identifier list lock
> >   */
> >  struct audit_net {
> >         struct sock *sk;
> > +       struct list_head contid_list;
> > +       spinlock_t contid_list_lock;
> >  };
> >
> >  /**
> > @@ -275,8 +280,11 @@ struct audit_task_info init_struct_audit = {
> >  void audit_free(struct task_struct *tsk)
> >  {
> >         struct audit_task_info *info = tsk->audit;
> > +       struct nsproxy *ns = tsk->nsproxy;
> >
> >         audit_free_syscall(tsk);
> > +       if (ns)
> > +               audit_netns_contid_del(ns->net_ns, audit_get_contid(tsk));
> >         /* Freeing the audit_task_info struct must be performed after
> >          * audit_log_exit() due to need for loginuid and sessionid.
> >          */
> > @@ -376,6 +384,73 @@ static struct sock *audit_get_sk(const struct net *net)
> >         return aunet->sk;
> >  }
> >
> > +void audit_netns_contid_add(struct net *net, u64 contid)
> > +{
> > +       struct audit_net *aunet = net_generic(net, audit_net_id);
> > +       struct list_head *contid_list = &aunet->contid_list;
> > +       struct audit_contid *cont;
> > +
> > +       if (!audit_contid_valid(contid))
> > +               return;
> > +       if (!aunet)
> > +               return;
> 
> We should move the contid_list assignment below this check, or decide
> that aunet is always going to valid (?) and get rid of this check
> completely.
> 
I'm not sure why that would be needed.  Finding the net_id list is an operation
of a map relating net namespaces to lists, not contids to lists.  We could do
it, sure, but since they're unrelated operations, I don't think we experience
any slowdowns from doing it this way.

> > +       spin_lock(&aunet->contid_list_lock);
> > +       if (!list_empty(contid_list))
> 
> We don't need the list_empty() check here do we?  I think we can just
> call list_for_each_entry_rcu(), yes?
> 
This is true, the list_empty check is redundant, and the for loop will fall
through if the list is empty.

> > +               list_for_each_entry_rcu(cont, contid_list, list)
> > +                       if (cont->id == contid) {
> > +                               refcount_inc(&cont->refcount);
> > +                               goto out;
> > +                       }
> > +       cont = kmalloc(sizeof(struct audit_contid), GFP_ATOMIC);
> 
> If you had to guess, what do you think is going to be more common:
> bumping the refcount of an existing entry in the list, or adding a new
> entry?  I'm asking because I always get a little nervous when doing
> allocations while holding a spinlock.  Yes, you are doing it with
> GFP_ATOMIC, but it still seems like something to try and avoid if this
> is going to approach 50%.  However, if the new entry is rare then the
> extra work of always doing the allocation before taking the lock and
> then freeing it afterwards might be a bad tradeoff.
> 
I think this is another way of asking, will multiple processes exist in the same
network namespace?  That is to say, will we expect a process to create a net
namespace, and then have other processes enter that namespace (thereby
triggering multiple calls to audit_netns_contid_add with the same net pointer
and cont id).  Given that the kubernetes notion of a pod is almost by definition
multiple containers sharing a network namespace, I think the answer is that we
will be strongly biased towards the refcount_inc case, rather than the kmalloc
case.  I could be wrong, but I think this is likely already in the optimized
order.

> My gut feeling says we might do about as many allocations as refcount
> bumps, but I could be thinking about this wrong.
> 
> Moving the allocation outside the spinlock might also open the door to
> doing this as GFP_KERNEL, which is a good thing, but I haven't looked
> at the callers to see if that is possible (it may not be).  That's an
> exercise left to the patch author (if he hasn't done that already).
> 
> > +       if (cont) {
> > +               INIT_LIST_HEAD(&cont->list);
> 
> Unless there is some guidance that INIT_LIST_HEAD() should be used
> regardless, you shouldn't need to call this here since list_add_rcu()
> will take care of any list.h related initialization.
> 
There is a corner case that needs it.  list_add_rcu has a check that gets
called, __list_add_valid.  Its a noop in the regular case, but if
CONFIG_DEBUG_LIST is defined, its a check to ensure that the next and prev
pointers getting passed in aren't set to detectable corrupt values.  If we pass
in garbage, we can get transient false positives on that check, so we need to
set the list pointers to known good values before hand, either by using kzalloc,
or INIT_LIST_HEAD, as has been done here.  Given that we expressly set every
field of this structure, I think this is the right approach, as it uses the list
macro to expressly set the list values to their proper state.

> > +               cont->id = contid;
> > +               refcount_set(&cont->refcount, 1);
> > +               list_add_rcu(&cont->list, contid_list);
> > +       }
> > +out:
> > +       spin_unlock(&aunet->contid_list_lock);
> > +}
> 
> -- 
> paul moore
> www.paul-moore.com
> 

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH ghak90 V5 09/10] audit: add support for containerid to network namespaces
  2019-04-02 11:31     ` Neil Horman
@ 2019-04-02 13:31       ` Paul Moore
  2019-04-02 14:28         ` Neil Horman
  2019-04-04 21:40       ` Richard Guy Briggs
  1 sibling, 1 reply; 64+ messages in thread
From: Paul Moore @ 2019-04-02 13:31 UTC (permalink / raw)
  To: Neil Horman
  Cc: Richard Guy Briggs, containers, linux-api,
	Linux-Audit Mailing List, linux-fsdevel, LKML, netdev,
	netfilter-devel, sgrubb, omosnace, dhowells, simo, Eric Paris,
	Serge Hallyn, ebiederm

On Tue, Apr 2, 2019 at 7:32 AM Neil Horman <nhorman@tuxdriver.com> wrote:
> On Mon, Apr 01, 2019 at 10:50:03AM -0400, Paul Moore wrote:
> > On Fri, Mar 15, 2019 at 2:35 PM Richard Guy Briggs <rgb@redhat.com> wrote:
> > > Audit events could happen in a network namespace outside of a task
> > > context due to packets received from the net that trigger an auditing
> > > rule prior to being associated with a running task.  The network
> > > namespace could be in use by multiple containers by association to the
> > > tasks in that network namespace.  We still want a way to attribute
> > > these events to any potential containers.  Keep a list per network
> > > namespace to track these audit container identifiiers.
> > >
> > > Add/increment the audit container identifier on:
> > > - initial setting of the audit container identifier via /proc
> > > - clone/fork call that inherits an audit container identifier
> > > - unshare call that inherits an audit container identifier
> > > - setns call that inherits an audit container identifier
> > > Delete/decrement the audit container identifier on:
> > > - an inherited audit container identifier dropped when child set
> > > - process exit
> > > - unshare call that drops a net namespace
> > > - setns call that drops a net namespace
> > >
> > > See: https://github.com/linux-audit/audit-kernel/issues/92
> > > See: https://github.com/linux-audit/audit-testsuite/issues/64
> > > See: https://github.com/linux-audit/audit-kernel/wiki/RFE-Audit-Container-ID
> > > Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> > > ---
> > >  include/linux/audit.h | 19 ++++++++++++
> > >  kernel/audit.c        | 86 +++++++++++++++++++++++++++++++++++++++++++++++++--
> > >  kernel/nsproxy.c      |  4 +++
> > >  3 files changed, 106 insertions(+), 3 deletions(-)
> >
> > ...
> >
> > > diff --git a/kernel/audit.c b/kernel/audit.c
> > > index cf448599ef34..7fa3194f5342 100644
> > > --- a/kernel/audit.c
> > > +++ b/kernel/audit.c
> > > @@ -72,6 +72,7 @@
> > >  #include <linux/freezer.h>
> > >  #include <linux/pid_namespace.h>
> > >  #include <net/netns/generic.h>
> > > +#include <net/net_namespace.h>
> > >
> > >  #include "audit.h"
> > >
> > > @@ -99,9 +100,13 @@
> > >  /**
> > >   * struct audit_net - audit private network namespace data
> > >   * @sk: communication socket
> > > + * @contid_list: audit container identifier list
> > > + * @contid_list_lock audit container identifier list lock
> > >   */
> > >  struct audit_net {
> > >         struct sock *sk;
> > > +       struct list_head contid_list;
> > > +       spinlock_t contid_list_lock;
> > >  };
> > >
> > >  /**
> > > @@ -275,8 +280,11 @@ struct audit_task_info init_struct_audit = {
> > >  void audit_free(struct task_struct *tsk)
> > >  {
> > >         struct audit_task_info *info = tsk->audit;
> > > +       struct nsproxy *ns = tsk->nsproxy;
> > >
> > >         audit_free_syscall(tsk);
> > > +       if (ns)
> > > +               audit_netns_contid_del(ns->net_ns, audit_get_contid(tsk));
> > >         /* Freeing the audit_task_info struct must be performed after
> > >          * audit_log_exit() due to need for loginuid and sessionid.
> > >          */
> > > @@ -376,6 +384,73 @@ static struct sock *audit_get_sk(const struct net *net)
> > >         return aunet->sk;
> > >  }
> > >
> > > +void audit_netns_contid_add(struct net *net, u64 contid)
> > > +{
> > > +       struct audit_net *aunet = net_generic(net, audit_net_id);
> > > +       struct list_head *contid_list = &aunet->contid_list;
> > > +       struct audit_contid *cont;
> > > +
> > > +       if (!audit_contid_valid(contid))
> > > +               return;
> > > +       if (!aunet)
> > > +               return;
> >
> > We should move the contid_list assignment below this check, or decide
> > that aunet is always going to valid (?) and get rid of this check
> > completely.
> >
> I'm not sure why that would be needed.  Finding the net_id list is an operation
> of a map relating net namespaces to lists, not contids to lists.  We could do
> it, sure, but since they're unrelated operations, I don't think we experience
> any slowdowns from doing it this way.

In the first line of the function, when aunet is declared, it is also
assigned a value using net_generic():

  struct audit_net *aunet = net_generic(net, audit_net_id);

Later in the function there is check to see if aunet is NULL, yet on
the second line of the function (before the NULL check), there is this
line of code:

  struct list_head *contid_list = &aunet->contid_list;

... which could result in the dereference of a NULL pointer if aunet
is NULL.  My suggestion was either to move this assignment below the
aunet-NULL check or decide that aunet was always going to be valid
(e.g. non-NULL) and do away with the aunet-NULL check completely.
Richard has since replied that the aunet-NULL check has been
demonstrated to be necessary so the proper thing to do would be to
move the assignment.  I believe that is what Richard is planning on
doing.

> > > +       if (cont) {
> > > +               INIT_LIST_HEAD(&cont->list);
> >
> > Unless there is some guidance that INIT_LIST_HEAD() should be used
> > regardless, you shouldn't need to call this here since list_add_rcu()
> > will take care of any list.h related initialization.
>
> There is a corner case that needs it.  list_add_rcu has a check that gets
> called, __list_add_valid.  Its a noop in the regular case, but if
> CONFIG_DEBUG_LIST is defined, its a check to ensure that the next and prev
> pointers getting passed in aren't set to detectable corrupt values.  If we pass
> in garbage, we can get transient false positives on that check, so we need to
> set the list pointers to known good values before hand, either by using kzalloc,
> or INIT_LIST_HEAD, as has been done here.  Given that we expressly set every
> field of this structure, I think this is the right approach, as it uses the list
> macro to expressly set the list values to their proper state.

Good to know, thanks.

-- 
paul moore
www.paul-moore.com

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH ghak90 V5 09/10] audit: add support for containerid to network namespaces
  2019-04-02 13:31       ` Paul Moore
@ 2019-04-02 14:28         ` Neil Horman
  0 siblings, 0 replies; 64+ messages in thread
From: Neil Horman @ 2019-04-02 14:28 UTC (permalink / raw)
  To: Paul Moore
  Cc: Richard Guy Briggs, containers, linux-api,
	Linux-Audit Mailing List, linux-fsdevel, LKML, netdev,
	netfilter-devel, sgrubb, omosnace, dhowells, simo, Eric Paris,
	Serge Hallyn, ebiederm

On Tue, Apr 02, 2019 at 09:31:49AM -0400, Paul Moore wrote:
> On Tue, Apr 2, 2019 at 7:32 AM Neil Horman <nhorman@tuxdriver.com> wrote:
> > On Mon, Apr 01, 2019 at 10:50:03AM -0400, Paul Moore wrote:
> > > On Fri, Mar 15, 2019 at 2:35 PM Richard Guy Briggs <rgb@redhat.com> wrote:
> > > > Audit events could happen in a network namespace outside of a task
> > > > context due to packets received from the net that trigger an auditing
> > > > rule prior to being associated with a running task.  The network
> > > > namespace could be in use by multiple containers by association to the
> > > > tasks in that network namespace.  We still want a way to attribute
> > > > these events to any potential containers.  Keep a list per network
> > > > namespace to track these audit container identifiiers.
> > > >
> > > > Add/increment the audit container identifier on:
> > > > - initial setting of the audit container identifier via /proc
> > > > - clone/fork call that inherits an audit container identifier
> > > > - unshare call that inherits an audit container identifier
> > > > - setns call that inherits an audit container identifier
> > > > Delete/decrement the audit container identifier on:
> > > > - an inherited audit container identifier dropped when child set
> > > > - process exit
> > > > - unshare call that drops a net namespace
> > > > - setns call that drops a net namespace
> > > >
> > > > See: https://github.com/linux-audit/audit-kernel/issues/92
> > > > See: https://github.com/linux-audit/audit-testsuite/issues/64
> > > > See: https://github.com/linux-audit/audit-kernel/wiki/RFE-Audit-Container-ID
> > > > Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> > > > ---
> > > >  include/linux/audit.h | 19 ++++++++++++
> > > >  kernel/audit.c        | 86 +++++++++++++++++++++++++++++++++++++++++++++++++--
> > > >  kernel/nsproxy.c      |  4 +++
> > > >  3 files changed, 106 insertions(+), 3 deletions(-)
> > >
> > > ...
> > >
> > > > diff --git a/kernel/audit.c b/kernel/audit.c
> > > > index cf448599ef34..7fa3194f5342 100644
> > > > --- a/kernel/audit.c
> > > > +++ b/kernel/audit.c
> > > > @@ -72,6 +72,7 @@
> > > >  #include <linux/freezer.h>
> > > >  #include <linux/pid_namespace.h>
> > > >  #include <net/netns/generic.h>
> > > > +#include <net/net_namespace.h>
> > > >
> > > >  #include "audit.h"
> > > >
> > > > @@ -99,9 +100,13 @@
> > > >  /**
> > > >   * struct audit_net - audit private network namespace data
> > > >   * @sk: communication socket
> > > > + * @contid_list: audit container identifier list
> > > > + * @contid_list_lock audit container identifier list lock
> > > >   */
> > > >  struct audit_net {
> > > >         struct sock *sk;
> > > > +       struct list_head contid_list;
> > > > +       spinlock_t contid_list_lock;
> > > >  };
> > > >
> > > >  /**
> > > > @@ -275,8 +280,11 @@ struct audit_task_info init_struct_audit = {
> > > >  void audit_free(struct task_struct *tsk)
> > > >  {
> > > >         struct audit_task_info *info = tsk->audit;
> > > > +       struct nsproxy *ns = tsk->nsproxy;
> > > >
> > > >         audit_free_syscall(tsk);
> > > > +       if (ns)
> > > > +               audit_netns_contid_del(ns->net_ns, audit_get_contid(tsk));
> > > >         /* Freeing the audit_task_info struct must be performed after
> > > >          * audit_log_exit() due to need for loginuid and sessionid.
> > > >          */
> > > > @@ -376,6 +384,73 @@ static struct sock *audit_get_sk(const struct net *net)
> > > >         return aunet->sk;
> > > >  }
> > > >
> > > > +void audit_netns_contid_add(struct net *net, u64 contid)
> > > > +{
> > > > +       struct audit_net *aunet = net_generic(net, audit_net_id);
> > > > +       struct list_head *contid_list = &aunet->contid_list;
> > > > +       struct audit_contid *cont;
> > > > +
> > > > +       if (!audit_contid_valid(contid))
> > > > +               return;
> > > > +       if (!aunet)
> > > > +               return;
> > >
> > > We should move the contid_list assignment below this check, or decide
> > > that aunet is always going to valid (?) and get rid of this check
> > > completely.
> > >
> > I'm not sure why that would be needed.  Finding the net_id list is an operation
> > of a map relating net namespaces to lists, not contids to lists.  We could do
> > it, sure, but since they're unrelated operations, I don't think we experience
> > any slowdowns from doing it this way.
> 
> In the first line of the function, when aunet is declared, it is also
> assigned a value using net_generic():
> 
>   struct audit_net *aunet = net_generic(net, audit_net_id);
> 
> Later in the function there is check to see if aunet is NULL, yet on
> the second line of the function (before the NULL check), there is this
> line of code:
> 
>   struct list_head *contid_list = &aunet->contid_list;
> 
> ... which could result in the dereference of a NULL pointer if aunet
> is NULL.  My suggestion was either to move this assignment below the
> aunet-NULL check or decide that aunet was always going to be valid
> (e.g. non-NULL) and do away with the aunet-NULL check completely.
> Richard has since replied that the aunet-NULL check has been
> demonstrated to be necessary so the proper thing to do would be to
> move the assignment.  I believe that is what Richard is planning on
> doing.
> 
oh, I'm sorry, you're right, I was looking at the contid tests not the list
tests.

Neil

> > > > +       if (cont) {
> > > > +               INIT_LIST_HEAD(&cont->list);
> > >
> > > Unless there is some guidance that INIT_LIST_HEAD() should be used
> > > regardless, you shouldn't need to call this here since list_add_rcu()
> > > will take care of any list.h related initialization.
> >
> > There is a corner case that needs it.  list_add_rcu has a check that gets
> > called, __list_add_valid.  Its a noop in the regular case, but if
> > CONFIG_DEBUG_LIST is defined, its a check to ensure that the next and prev
> > pointers getting passed in aren't set to detectable corrupt values.  If we pass
> > in garbage, we can get transient false positives on that check, so we need to
> > set the list pointers to known good values before hand, either by using kzalloc,
> > or INIT_LIST_HEAD, as has been done here.  Given that we expressly set every
> > field of this structure, I think this is the right approach, as it uses the list
> > macro to expressly set the list values to their proper state.
> 
> Good to know, thanks.
> 
> -- 
> paul moore
> www.paul-moore.com
> 

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH ghak90 V5 09/10] audit: add support for containerid to network namespaces
  2019-04-02 11:31     ` Neil Horman
  2019-04-02 13:31       ` Paul Moore
@ 2019-04-04 21:40       ` Richard Guy Briggs
  2019-04-05  2:06         ` Paul Moore
  2019-04-05 11:32         ` Neil Horman
  1 sibling, 2 replies; 64+ messages in thread
From: Richard Guy Briggs @ 2019-04-04 21:40 UTC (permalink / raw)
  To: Neil Horman
  Cc: Paul Moore, linux-api, containers, LKML, dhowells,
	Linux-Audit Mailing List, netfilter-devel, ebiederm, simo,
	netdev, linux-fsdevel, Eric Paris, Serge Hallyn

On 2019-04-02 07:31, Neil Horman wrote:
> On Mon, Apr 01, 2019 at 10:50:03AM -0400, Paul Moore wrote:
> > On Fri, Mar 15, 2019 at 2:35 PM Richard Guy Briggs <rgb@redhat.com> wrote:
> > > Audit events could happen in a network namespace outside of a task
> > > context due to packets received from the net that trigger an auditing
> > > rule prior to being associated with a running task.  The network
> > > namespace could be in use by multiple containers by association to the
> > > tasks in that network namespace.  We still want a way to attribute
> > > these events to any potential containers.  Keep a list per network
> > > namespace to track these audit container identifiiers.
> > >
> > > Add/increment the audit container identifier on:
> > > - initial setting of the audit container identifier via /proc
> > > - clone/fork call that inherits an audit container identifier
> > > - unshare call that inherits an audit container identifier
> > > - setns call that inherits an audit container identifier
> > > Delete/decrement the audit container identifier on:
> > > - an inherited audit container identifier dropped when child set
> > > - process exit
> > > - unshare call that drops a net namespace
> > > - setns call that drops a net namespace
> > >
> > > See: https://github.com/linux-audit/audit-kernel/issues/92
> > > See: https://github.com/linux-audit/audit-testsuite/issues/64
> > > See: https://github.com/linux-audit/audit-kernel/wiki/RFE-Audit-Container-ID
> > > Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> > > ---
> > >  include/linux/audit.h | 19 ++++++++++++
> > >  kernel/audit.c        | 86 +++++++++++++++++++++++++++++++++++++++++++++++++--
> > >  kernel/nsproxy.c      |  4 +++
> > >  3 files changed, 106 insertions(+), 3 deletions(-)
> > 
> > ...
> > 
> > > diff --git a/kernel/audit.c b/kernel/audit.c
> > > index cf448599ef34..7fa3194f5342 100644
> > > --- a/kernel/audit.c
> > > +++ b/kernel/audit.c
> > > @@ -72,6 +72,7 @@
> > >  #include <linux/freezer.h>
> > >  #include <linux/pid_namespace.h>
> > >  #include <net/netns/generic.h>
> > > +#include <net/net_namespace.h>
> > >
> > >  #include "audit.h"
> > >
> > > @@ -99,9 +100,13 @@
> > >  /**
> > >   * struct audit_net - audit private network namespace data
> > >   * @sk: communication socket
> > > + * @contid_list: audit container identifier list
> > > + * @contid_list_lock audit container identifier list lock
> > >   */
> > >  struct audit_net {
> > >         struct sock *sk;
> > > +       struct list_head contid_list;
> > > +       spinlock_t contid_list_lock;
> > >  };
> > >
> > >  /**
> > > @@ -275,8 +280,11 @@ struct audit_task_info init_struct_audit = {
> > >  void audit_free(struct task_struct *tsk)
> > >  {
> > >         struct audit_task_info *info = tsk->audit;
> > > +       struct nsproxy *ns = tsk->nsproxy;
> > >
> > >         audit_free_syscall(tsk);
> > > +       if (ns)
> > > +               audit_netns_contid_del(ns->net_ns, audit_get_contid(tsk));
> > >         /* Freeing the audit_task_info struct must be performed after
> > >          * audit_log_exit() due to need for loginuid and sessionid.
> > >          */
> > > @@ -376,6 +384,73 @@ static struct sock *audit_get_sk(const struct net *net)
> > >         return aunet->sk;
> > >  }
> > >
> > > +void audit_netns_contid_add(struct net *net, u64 contid)
> > > +{
> > > +       struct audit_net *aunet = net_generic(net, audit_net_id);
> > > +       struct list_head *contid_list = &aunet->contid_list;
> > > +       struct audit_contid *cont;
> > > +
> > > +       if (!audit_contid_valid(contid))
> > > +               return;
> > > +       if (!aunet)
> > > +               return;
> > 
> > We should move the contid_list assignment below this check, or decide
> > that aunet is always going to valid (?) and get rid of this check
> > completely.
> > 
> I'm not sure why that would be needed.  Finding the net_id list is an operation
> of a map relating net namespaces to lists, not contids to lists.  We could do
> it, sure, but since they're unrelated operations, I don't think we experience
> any slowdowns from doing it this way.
> 
> > > +       spin_lock(&aunet->contid_list_lock);
> > > +       if (!list_empty(contid_list))
> > 
> > We don't need the list_empty() check here do we?  I think we can just
> > call list_for_each_entry_rcu(), yes?
> > 
> This is true, the list_empty check is redundant, and the for loop will fall
> through if the list is empty.
> 
> > > +               list_for_each_entry_rcu(cont, contid_list, list)
> > > +                       if (cont->id == contid) {
> > > +                               refcount_inc(&cont->refcount);
> > > +                               goto out;
> > > +                       }
> > > +       cont = kmalloc(sizeof(struct audit_contid), GFP_ATOMIC);
> > 
> > If you had to guess, what do you think is going to be more common:
> > bumping the refcount of an existing entry in the list, or adding a new
> > entry?  I'm asking because I always get a little nervous when doing
> > allocations while holding a spinlock.  Yes, you are doing it with
> > GFP_ATOMIC, but it still seems like something to try and avoid if this
> > is going to approach 50%.  However, if the new entry is rare then the
> > extra work of always doing the allocation before taking the lock and
> > then freeing it afterwards might be a bad tradeoff.
> > 
> I think this is another way of asking, will multiple processes exist in the same
> network namespace?  That is to say, will we expect a process to create a net
> namespace, and then have other processes enter that namespace (thereby
> triggering multiple calls to audit_netns_contid_add with the same net pointer
> and cont id).  Given that the kubernetes notion of a pod is almost by definition
> multiple containers sharing a network namespace, I think the answer is that we
> will be strongly biased towards the refcount_inc case, rather than the kmalloc
> case.  I could be wrong, but I think this is likely already in the optimized
> order.

I had a stab at doing a GFP_KERNEL alloc before the spinlock and releasing it
after if it wasn't needed (in Patch#1 below).  I also went one step further and
converted it to kmem_cache (in Patch#2 below).

> > My gut feeling says we might do about as many allocations as refcount
> > bumps, but I could be thinking about this wrong.
> > 
> > Moving the allocation outside the spinlock might also open the door to
> > doing this as GFP_KERNEL, which is a good thing, but I haven't looked
> > at the callers to see if that is possible (it may not be).  That's an
> > exercise left to the patch author (if he hasn't done that already).

Both appear to work, but after successfully running both the contid test and
audit_testsuite, once I start to push that test system a bit harder I end up
with a deadlock warning.

I am having trouble understanding why since it happens both without and with
the kmem_cache options, so it must be another part of the code that is
triggering it.  The task_lock is being held at this point in
audit_set_contid().  I haven't tried changing this alloc over to a GFP_ATOMIC
to see if that prevents it, just as a debugging check...
At this point, I'm inclined to leave it as it was without these two patches
since it works and there doesn't seem to be an obvious best way given the
uncertainty of the potential workloads.

======================================================
WARNING: possible circular locking dependency detected
5.1.0-rc1-ghak90-audit-containerID.v6.3+ #80 Not tainted
------------------------------------------------------
kswapd0/41 is trying to acquire lock:
0000000006a8c88b (&(&p->alloc_lock)->rlock){+.+.}, at: create_task_io_context+0xe9/0x150

but task is already holding lock:
0000000010aadb74 (fs_reclaim){+.+.}, at: __fs_reclaim_acquire+0x5/0x40

which lock already depends on the new lock.


the existing dependency chain (in reverse order) is:

-> #1 (fs_reclaim){+.+.}:
       __fs_reclaim_acquire+0x2c/0x40
       kmem_cache_alloc_trace+0x30/0x230
       audit_netns_contid_add.part.12+0xcf/0x210
       audit_set_contid+0x18f/0x480
       proc_contid_write+0x74/0x110
       vfs_write+0xad/0x1b0
       ksys_write+0x55/0xc0
       do_syscall_64+0x60/0x210
       entry_SYSCALL_64_after_hwframe+0x49/0xbe

-> #0 (&(&p->alloc_lock)->rlock){+.+.}:
       lock_acquire+0xd4/0x1c0
       _raw_spin_lock+0x2e/0x40
       create_task_io_context+0xe9/0x150
       generic_make_request_checks+0x8b4/0x970
       generic_make_request+0xbb/0x570
       submit_bio+0x6e/0x130
       __swap_writepage+0x281/0x420
       shmem_writepage+0x1d3/0x350
       pageout.isra.54+0x1e9/0x3f0
       shrink_page_list+0xa9f/0xe60
       shrink_inactive_list+0x263/0x6e0
       shrink_node_memcg+0x376/0x7c0
       shrink_node+0xdd/0x470
       balance_pgdat+0x26c/0x570
       kswapd+0x191/0x4f0
       kthread+0xf8/0x130
       ret_from_fork+0x3a/0x50

other info that might help us debug this:

 Possible unsafe locking scenario:

       CPU0                    CPU1
       ----                    ----
  lock(fs_reclaim);
                               lock(&(&p->alloc_lock)->rlock);
                               lock(fs_reclaim);
  lock(&(&p->alloc_lock)->rlock);

 *** DEADLOCK ***

1 lock held by kswapd0/41:
 #0: 0000000010aadb74 (fs_reclaim){+.+.}, at: __fs_reclaim_acquire+0x5/0x40

> > paul moore

Patch#1:
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -388,7 +388,7 @@ void audit_netns_contid_add(struct net *net, u64 contid)
 {
        struct audit_net *aunet;
        struct list_head *contid_list;
-       struct audit_contid *cont;
+       struct audit_contid *cont, *newcont;
 
        if (!net)
                return;
@@ -398,18 +398,19 @@ void audit_netns_contid_add(struct net *net, u64 contid)
        if (!aunet)
                return;
        contid_list = &aunet->contid_list;
+       newcont = kmalloc(sizeof(struct audit_contid), GFP_KERNEL);
        spin_lock(&aunet->contid_list_lock);
        list_for_each_entry_rcu(cont, contid_list, list)
                if (cont->id == contid) {
                        refcount_inc(&cont->refcount);
+                       kfree(newcont);
                        goto out;
                }
-       cont = kmalloc(sizeof(struct audit_contid), GFP_ATOMIC);
-       if (cont) {
-               INIT_LIST_HEAD(&cont->list);
-               cont->id = contid;
-               refcount_set(&cont->refcount, 1);
-               list_add_rcu(&cont->list, contid_list);
+       if (newcont) {
+               INIT_LIST_HEAD(&newcont->list);
+               newcont->id = contid;
+               refcount_set(&newcont->refcount, 1);
+               list_add_rcu(&newcont->list, contid_list);
        }
 out:
        spin_unlock(&aunet->contid_list_lock);


Patch#2:
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -222,12 +222,16 @@ struct audit_reply {
 };
 
 static struct kmem_cache *audit_task_cache;
+static struct kmem_cache *audit_contid_cache;
 
 void __init audit_task_init(void)
 {
        audit_task_cache = kmem_cache_create("audit_task",
                                             sizeof(struct audit_task_info),
                                             0, SLAB_PANIC, NULL);
+       audit_contid_cache = kmem_cache_create("audit_contid",
+                                            sizeof(struct audit_contid),
+                                            0, SLAB_PANIC, NULL);
 }
 
 /**
@@ -388,7 +392,7 @@ void audit_netns_contid_add(struct net *net, u64 contid)
 {
        struct audit_net *aunet;
        struct list_head *contid_list;
-       struct audit_contid *cont;
+       struct audit_contid *cont, *newcont;
 
        if (!net)
                return;
@@ -398,23 +402,32 @@ void audit_netns_contid_add(struct net *net, u64 contid)
        if (!aunet)
                return;
        contid_list = &aunet->contid_list;
+       newcont = kmem_cache_alloc(audit_contid_cache, GFP_KERNEL);
        spin_lock(&aunet->contid_list_lock);
        list_for_each_entry_rcu(cont, contid_list, list)
                if (cont->id == contid) {
                        refcount_inc(&cont->refcount);
+                       kmem_cache_free(audit_contid_cache, newcont);
                        goto out;
                }
-       cont = kmalloc(sizeof(struct audit_contid), GFP_ATOMIC);
-       if (cont) {
-               INIT_LIST_HEAD(&cont->list);
-               cont->id = contid;
-               refcount_set(&cont->refcount, 1);
-               list_add_rcu(&cont->list, contid_list);
+       if (newcont) {
+               INIT_LIST_HEAD(&newcont->list);
+               newcont->id = contid;
+               refcount_set(&newcont->refcount, 1);
+               list_add_rcu(&newcont->list, contid_list);
        }
 out:
        spin_unlock(&aunet->contid_list_lock);
 }
 
+static void audit_contid_free(struct rcu_head *rcu)
+{
+       struct audit_contid *cont;
+
+       cont = container_of(rcu, struct audit_contid, rcu);
+       kmem_cache_free(audit_contid_cache, cont);
+}
+
 void audit_netns_contid_del(struct net *net, u64 contid)
 {
        struct audit_net *aunet;
@@ -434,7 +447,7 @@ void audit_netns_contid_del(struct net *net, u64 contid)
                if (cont->id == contid) {
                        if (refcount_dec_and_test(&cont->refcount)) {
                                list_del_rcu(&cont->list);
-                               kfree_rcu(cont, rcu);
+                               call_rcu(&cont->rcu, audit_contid_free);
                        }
                        break;
                }

- RGB

--
Richard Guy Briggs <rgb@redhat.com>
Sr. S/W Engineer, Kernel Security, Base Operating Systems
Remote, Ottawa, Red Hat Canada
IRC: rgb, SunRaycer
Voice: +1.647.777.2635, Internal: (81) 32635

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH ghak90 V5 09/10] audit: add support for containerid to network namespaces
  2019-04-04 21:40       ` Richard Guy Briggs
@ 2019-04-05  2:06         ` Paul Moore
  2019-04-05 11:32         ` Neil Horman
  1 sibling, 0 replies; 64+ messages in thread
From: Paul Moore @ 2019-04-05  2:06 UTC (permalink / raw)
  To: Richard Guy Briggs
  Cc: Neil Horman, linux-api, containers, LKML, dhowells,
	Linux-Audit Mailing List, netfilter-devel, ebiederm, simo,
	netdev, linux-fsdevel, Eric Paris, Serge Hallyn

On Thu, Apr 4, 2019 at 5:40 PM Richard Guy Briggs <rgb@redhat.com> wrote:
> On 2019-04-02 07:31, Neil Horman wrote:
> > On Mon, Apr 01, 2019 at 10:50:03AM -0400, Paul Moore wrote:
> > > On Fri, Mar 15, 2019 at 2:35 PM Richard Guy Briggs <rgb@redhat.com> wrote:
> > > > Audit events could happen in a network namespace outside of a task
> > > > context due to packets received from the net that trigger an auditing
> > > > rule prior to being associated with a running task.  The network
> > > > namespace could be in use by multiple containers by association to the
> > > > tasks in that network namespace.  We still want a way to attribute
> > > > these events to any potential containers.  Keep a list per network
> > > > namespace to track these audit container identifiiers.
> > > >
> > > > Add/increment the audit container identifier on:
> > > > - initial setting of the audit container identifier via /proc
> > > > - clone/fork call that inherits an audit container identifier
> > > > - unshare call that inherits an audit container identifier
> > > > - setns call that inherits an audit container identifier
> > > > Delete/decrement the audit container identifier on:
> > > > - an inherited audit container identifier dropped when child set
> > > > - process exit
> > > > - unshare call that drops a net namespace
> > > > - setns call that drops a net namespace
> > > >
> > > > See: https://github.com/linux-audit/audit-kernel/issues/92
> > > > See: https://github.com/linux-audit/audit-testsuite/issues/64
> > > > See: https://github.com/linux-audit/audit-kernel/wiki/RFE-Audit-Container-ID
> > > > Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> > > > ---
> > > >  include/linux/audit.h | 19 ++++++++++++
> > > >  kernel/audit.c        | 86 +++++++++++++++++++++++++++++++++++++++++++++++++--
> > > >  kernel/nsproxy.c      |  4 +++
> > > >  3 files changed, 106 insertions(+), 3 deletions(-)

...

> > > > +               list_for_each_entry_rcu(cont, contid_list, list)
> > > > +                       if (cont->id == contid) {
> > > > +                               refcount_inc(&cont->refcount);
> > > > +                               goto out;
> > > > +                       }
> > > > +       cont = kmalloc(sizeof(struct audit_contid), GFP_ATOMIC);
> > >
> > > If you had to guess, what do you think is going to be more common:
> > > bumping the refcount of an existing entry in the list, or adding a new
> > > entry?  I'm asking because I always get a little nervous when doing
> > > allocations while holding a spinlock.  Yes, you are doing it with
> > > GFP_ATOMIC, but it still seems like something to try and avoid if this
> > > is going to approach 50%.  However, if the new entry is rare then the
> > > extra work of always doing the allocation before taking the lock and
> > > then freeing it afterwards might be a bad tradeoff.
> > >
> > I think this is another way of asking, will multiple processes exist in the same
> > network namespace?  That is to say, will we expect a process to create a net
> > namespace, and then have other processes enter that namespace (thereby
> > triggering multiple calls to audit_netns_contid_add with the same net pointer
> > and cont id).  Given that the kubernetes notion of a pod is almost by definition
> > multiple containers sharing a network namespace, I think the answer is that we
> > will be strongly biased towards the refcount_inc case, rather than the kmalloc
> > case.  I could be wrong, but I think this is likely already in the optimized
> > order.
>
> I had a stab at doing a GFP_KERNEL alloc before the spinlock and releasing it
> after if it wasn't needed (in Patch#1 below).  I also went one step further and
> converted it to kmem_cache (in Patch#2 below).
>
> > > My gut feeling says we might do about as many allocations as refcount
> > > bumps, but I could be thinking about this wrong.
> > >
> > > Moving the allocation outside the spinlock might also open the door to
> > > doing this as GFP_KERNEL, which is a good thing, but I haven't looked
> > > at the callers to see if that is possible (it may not be).  That's an
> > > exercise left to the patch author (if he hasn't done that already).
>
> Both appear to work, but after successfully running both the contid test and
> audit_testsuite, once I start to push that test system a bit harder I end up
> with a deadlock warning.
>
> I am having trouble understanding why since it happens both without and with
> the kmem_cache options, so it must be another part of the code that is
> triggering it.  The task_lock is being held at this point in
> audit_set_contid().  I haven't tried changing this alloc over to a GFP_ATOMIC
> to see if that prevents it, just as a debugging check...
> At this point, I'm inclined to leave it as it was without these two patches
> since it works and there doesn't seem to be an obvious best way given the
> uncertainty of the potential workloads.

I'm definitely not a mm expert, but I wonder if you might be able to
get this working using GFP_NOFS, but I see just now that they
recommend you *not* use GFP_NOFS; even if this did solve the problem,
it's probably not the right approach.

I'm okay with leaving it as-is with GFP_ATOMIC.  My original response
to this was more of a question about optimizing for a given use case,
having something that works is far more important.

-- 
paul moore
www.paul-moore.com

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH ghak90 V5 09/10] audit: add support for containerid to network namespaces
  2019-04-04 21:40       ` Richard Guy Briggs
  2019-04-05  2:06         ` Paul Moore
@ 2019-04-05 11:32         ` Neil Horman
  1 sibling, 0 replies; 64+ messages in thread
From: Neil Horman @ 2019-04-05 11:32 UTC (permalink / raw)
  To: Richard Guy Briggs
  Cc: Paul Moore, linux-api, containers, LKML, dhowells,
	Linux-Audit Mailing List, netfilter-devel, ebiederm, simo,
	netdev, linux-fsdevel, Eric Paris, Serge Hallyn

On Thu, Apr 04, 2019 at 05:40:06PM -0400, Richard Guy Briggs wrote:
> On 2019-04-02 07:31, Neil Horman wrote:
> > On Mon, Apr 01, 2019 at 10:50:03AM -0400, Paul Moore wrote:
> > > On Fri, Mar 15, 2019 at 2:35 PM Richard Guy Briggs <rgb@redhat.com> wrote:
> > > > Audit events could happen in a network namespace outside of a task
> > > > context due to packets received from the net that trigger an auditing
> > > > rule prior to being associated with a running task.  The network
> > > > namespace could be in use by multiple containers by association to the
> > > > tasks in that network namespace.  We still want a way to attribute
> > > > these events to any potential containers.  Keep a list per network
> > > > namespace to track these audit container identifiiers.
> > > >
> > > > Add/increment the audit container identifier on:
> > > > - initial setting of the audit container identifier via /proc
> > > > - clone/fork call that inherits an audit container identifier
> > > > - unshare call that inherits an audit container identifier
> > > > - setns call that inherits an audit container identifier
> > > > Delete/decrement the audit container identifier on:
> > > > - an inherited audit container identifier dropped when child set
> > > > - process exit
> > > > - unshare call that drops a net namespace
> > > > - setns call that drops a net namespace
> > > >
> > > > See: https://github.com/linux-audit/audit-kernel/issues/92
> > > > See: https://github.com/linux-audit/audit-testsuite/issues/64
> > > > See: https://github.com/linux-audit/audit-kernel/wiki/RFE-Audit-Container-ID
> > > > Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> > > > ---
> > > >  include/linux/audit.h | 19 ++++++++++++
> > > >  kernel/audit.c        | 86 +++++++++++++++++++++++++++++++++++++++++++++++++--
> > > >  kernel/nsproxy.c      |  4 +++
> > > >  3 files changed, 106 insertions(+), 3 deletions(-)
> > > 
> > > ...
> > > 
> > > > diff --git a/kernel/audit.c b/kernel/audit.c
> > > > index cf448599ef34..7fa3194f5342 100644
> > > > --- a/kernel/audit.c
> > > > +++ b/kernel/audit.c
> > > > @@ -72,6 +72,7 @@
> > > >  #include <linux/freezer.h>
> > > >  #include <linux/pid_namespace.h>
> > > >  #include <net/netns/generic.h>
> > > > +#include <net/net_namespace.h>
> > > >
> > > >  #include "audit.h"
> > > >
> > > > @@ -99,9 +100,13 @@
> > > >  /**
> > > >   * struct audit_net - audit private network namespace data
> > > >   * @sk: communication socket
> > > > + * @contid_list: audit container identifier list
> > > > + * @contid_list_lock audit container identifier list lock
> > > >   */
> > > >  struct audit_net {
> > > >         struct sock *sk;
> > > > +       struct list_head contid_list;
> > > > +       spinlock_t contid_list_lock;
> > > >  };
> > > >
> > > >  /**
> > > > @@ -275,8 +280,11 @@ struct audit_task_info init_struct_audit = {
> > > >  void audit_free(struct task_struct *tsk)
> > > >  {
> > > >         struct audit_task_info *info = tsk->audit;
> > > > +       struct nsproxy *ns = tsk->nsproxy;
> > > >
> > > >         audit_free_syscall(tsk);
> > > > +       if (ns)
> > > > +               audit_netns_contid_del(ns->net_ns, audit_get_contid(tsk));
> > > >         /* Freeing the audit_task_info struct must be performed after
> > > >          * audit_log_exit() due to need for loginuid and sessionid.
> > > >          */
> > > > @@ -376,6 +384,73 @@ static struct sock *audit_get_sk(const struct net *net)
> > > >         return aunet->sk;
> > > >  }
> > > >
> > > > +void audit_netns_contid_add(struct net *net, u64 contid)
> > > > +{
> > > > +       struct audit_net *aunet = net_generic(net, audit_net_id);
> > > > +       struct list_head *contid_list = &aunet->contid_list;
> > > > +       struct audit_contid *cont;
> > > > +
> > > > +       if (!audit_contid_valid(contid))
> > > > +               return;
> > > > +       if (!aunet)
> > > > +               return;
> > > 
> > > We should move the contid_list assignment below this check, or decide
> > > that aunet is always going to valid (?) and get rid of this check
> > > completely.
> > > 
> > I'm not sure why that would be needed.  Finding the net_id list is an operation
> > of a map relating net namespaces to lists, not contids to lists.  We could do
> > it, sure, but since they're unrelated operations, I don't think we experience
> > any slowdowns from doing it this way.
> > 
> > > > +       spin_lock(&aunet->contid_list_lock);
> > > > +       if (!list_empty(contid_list))
> > > 
> > > We don't need the list_empty() check here do we?  I think we can just
> > > call list_for_each_entry_rcu(), yes?
> > > 
> > This is true, the list_empty check is redundant, and the for loop will fall
> > through if the list is empty.
> > 
> > > > +               list_for_each_entry_rcu(cont, contid_list, list)
> > > > +                       if (cont->id == contid) {
> > > > +                               refcount_inc(&cont->refcount);
> > > > +                               goto out;
> > > > +                       }
> > > > +       cont = kmalloc(sizeof(struct audit_contid), GFP_ATOMIC);
> > > 
> > > If you had to guess, what do you think is going to be more common:
> > > bumping the refcount of an existing entry in the list, or adding a new
> > > entry?  I'm asking because I always get a little nervous when doing
> > > allocations while holding a spinlock.  Yes, you are doing it with
> > > GFP_ATOMIC, but it still seems like something to try and avoid if this
> > > is going to approach 50%.  However, if the new entry is rare then the
> > > extra work of always doing the allocation before taking the lock and
> > > then freeing it afterwards might be a bad tradeoff.
> > > 
> > I think this is another way of asking, will multiple processes exist in the same
> > network namespace?  That is to say, will we expect a process to create a net
> > namespace, and then have other processes enter that namespace (thereby
> > triggering multiple calls to audit_netns_contid_add with the same net pointer
> > and cont id).  Given that the kubernetes notion of a pod is almost by definition
> > multiple containers sharing a network namespace, I think the answer is that we
> > will be strongly biased towards the refcount_inc case, rather than the kmalloc
> > case.  I could be wrong, but I think this is likely already in the optimized
> > order.
> 
> I had a stab at doing a GFP_KERNEL alloc before the spinlock and releasing it
> after if it wasn't needed (in Patch#1 below).  I also went one step further and
> converted it to kmem_cache (in Patch#2 below).
> 
> > > My gut feeling says we might do about as many allocations as refcount
> > > bumps, but I could be thinking about this wrong.
> > > 
> > > Moving the allocation outside the spinlock might also open the door to
> > > doing this as GFP_KERNEL, which is a good thing, but I haven't looked
> > > at the callers to see if that is possible (it may not be).  That's an
> > > exercise left to the patch author (if he hasn't done that already).
> 
> Both appear to work, but after successfully running both the contid test and
> audit_testsuite, once I start to push that test system a bit harder I end up
> with a deadlock warning.
> 
> I am having trouble understanding why since it happens both without and with
> the kmem_cache options, so it must be another part of the code that is
> triggering it.  The task_lock is being held at this point in
> audit_set_contid().  I haven't tried changing this alloc over to a GFP_ATOMIC
> to see if that prevents it, just as a debugging check...
> At this point, I'm inclined to leave it as it was without these two patches
> since it works and there doesn't seem to be an obvious best way given the
> uncertainty of the potential workloads.
> 
I would agree.  The trace below says that, when you use GFP_KERNEL, you are
allowing the memory subsystem to block the memory allocating task on memory
reclaim operations (effectively to sleep until kswapd reclaims sufficient memory
to grant the allocation), but kswapd wants to lock the task that is doing the
allocation with task_lock, which the task calling kmalloc(...,GFP_KEREL) already
holds, ergo, deadlock.

In short, you can't hold a tasks lock while preforming a sleeping operation
involving memory allocation. You either need to use GFP_ATOMIC, or release the
tasks lock before allocating memory with GFP_KERNEL.  Given the possible race
conditions surrounding releasing and re-aquiring the lock, I'm inclined to say
just use GFP_ATOMIC

Neil

> ======================================================
> WARNING: possible circular locking dependency detected
> 5.1.0-rc1-ghak90-audit-containerID.v6.3+ #80 Not tainted
> ------------------------------------------------------
> kswapd0/41 is trying to acquire lock:
> 0000000006a8c88b (&(&p->alloc_lock)->rlock){+.+.}, at: create_task_io_context+0xe9/0x150
> 
> but task is already holding lock:
> 0000000010aadb74 (fs_reclaim){+.+.}, at: __fs_reclaim_acquire+0x5/0x40
> 
> which lock already depends on the new lock.
> 
> 
> the existing dependency chain (in reverse order) is:
> 
> -> #1 (fs_reclaim){+.+.}:
>        __fs_reclaim_acquire+0x2c/0x40
>        kmem_cache_alloc_trace+0x30/0x230
>        audit_netns_contid_add.part.12+0xcf/0x210
>        audit_set_contid+0x18f/0x480
>        proc_contid_write+0x74/0x110
>        vfs_write+0xad/0x1b0
>        ksys_write+0x55/0xc0
>        do_syscall_64+0x60/0x210
>        entry_SYSCALL_64_after_hwframe+0x49/0xbe
> 
> -> #0 (&(&p->alloc_lock)->rlock){+.+.}:
>        lock_acquire+0xd4/0x1c0
>        _raw_spin_lock+0x2e/0x40
>        create_task_io_context+0xe9/0x150
>        generic_make_request_checks+0x8b4/0x970
>        generic_make_request+0xbb/0x570
>        submit_bio+0x6e/0x130
>        __swap_writepage+0x281/0x420
>        shmem_writepage+0x1d3/0x350
>        pageout.isra.54+0x1e9/0x3f0
>        shrink_page_list+0xa9f/0xe60
>        shrink_inactive_list+0x263/0x6e0
>        shrink_node_memcg+0x376/0x7c0
>        shrink_node+0xdd/0x470
>        balance_pgdat+0x26c/0x570
>        kswapd+0x191/0x4f0
>        kthread+0xf8/0x130
>        ret_from_fork+0x3a/0x50
> 
> other info that might help us debug this:
> 
>  Possible unsafe locking scenario:
> 
>        CPU0                    CPU1
>        ----                    ----
>   lock(fs_reclaim);
>                                lock(&(&p->alloc_lock)->rlock);
>                                lock(fs_reclaim);
>   lock(&(&p->alloc_lock)->rlock);
> 
>  *** DEADLOCK ***
> 
> 1 lock held by kswapd0/41:
>  #0: 0000000010aadb74 (fs_reclaim){+.+.}, at: __fs_reclaim_acquire+0x5/0x40
> 
> > > paul moore
> 
> Patch#1:
> --- a/kernel/audit.c
> +++ b/kernel/audit.c
> @@ -388,7 +388,7 @@ void audit_netns_contid_add(struct net *net, u64 contid)
>  {
>         struct audit_net *aunet;
>         struct list_head *contid_list;
> -       struct audit_contid *cont;
> +       struct audit_contid *cont, *newcont;
>  
>         if (!net)
>                 return;
> @@ -398,18 +398,19 @@ void audit_netns_contid_add(struct net *net, u64 contid)
>         if (!aunet)
>                 return;
>         contid_list = &aunet->contid_list;
> +       newcont = kmalloc(sizeof(struct audit_contid), GFP_KERNEL);
>         spin_lock(&aunet->contid_list_lock);
>         list_for_each_entry_rcu(cont, contid_list, list)
>                 if (cont->id == contid) {
>                         refcount_inc(&cont->refcount);
> +                       kfree(newcont);
>                         goto out;
>                 }
> -       cont = kmalloc(sizeof(struct audit_contid), GFP_ATOMIC);
> -       if (cont) {
> -               INIT_LIST_HEAD(&cont->list);
> -               cont->id = contid;
> -               refcount_set(&cont->refcount, 1);
> -               list_add_rcu(&cont->list, contid_list);
> +       if (newcont) {
> +               INIT_LIST_HEAD(&newcont->list);
> +               newcont->id = contid;
> +               refcount_set(&newcont->refcount, 1);
> +               list_add_rcu(&newcont->list, contid_list);
>         }
>  out:
>         spin_unlock(&aunet->contid_list_lock);
> 
> 
> Patch#2:
> --- a/kernel/audit.c
> +++ b/kernel/audit.c
> @@ -222,12 +222,16 @@ struct audit_reply {
>  };
>  
>  static struct kmem_cache *audit_task_cache;
> +static struct kmem_cache *audit_contid_cache;
>  
>  void __init audit_task_init(void)
>  {
>         audit_task_cache = kmem_cache_create("audit_task",
>                                              sizeof(struct audit_task_info),
>                                              0, SLAB_PANIC, NULL);
> +       audit_contid_cache = kmem_cache_create("audit_contid",
> +                                            sizeof(struct audit_contid),
> +                                            0, SLAB_PANIC, NULL);
>  }
>  
>  /**
> @@ -388,7 +392,7 @@ void audit_netns_contid_add(struct net *net, u64 contid)
>  {
>         struct audit_net *aunet;
>         struct list_head *contid_list;
> -       struct audit_contid *cont;
> +       struct audit_contid *cont, *newcont;
>  
>         if (!net)
>                 return;
> @@ -398,23 +402,32 @@ void audit_netns_contid_add(struct net *net, u64 contid)
>         if (!aunet)
>                 return;
>         contid_list = &aunet->contid_list;
> +       newcont = kmem_cache_alloc(audit_contid_cache, GFP_KERNEL);
>         spin_lock(&aunet->contid_list_lock);
>         list_for_each_entry_rcu(cont, contid_list, list)
>                 if (cont->id == contid) {
>                         refcount_inc(&cont->refcount);
> +                       kmem_cache_free(audit_contid_cache, newcont);
>                         goto out;
>                 }
> -       cont = kmalloc(sizeof(struct audit_contid), GFP_ATOMIC);
> -       if (cont) {
> -               INIT_LIST_HEAD(&cont->list);
> -               cont->id = contid;
> -               refcount_set(&cont->refcount, 1);
> -               list_add_rcu(&cont->list, contid_list);
> +       if (newcont) {
> +               INIT_LIST_HEAD(&newcont->list);
> +               newcont->id = contid;
> +               refcount_set(&newcont->refcount, 1);
> +               list_add_rcu(&newcont->list, contid_list);
>         }
>  out:
>         spin_unlock(&aunet->contid_list_lock);
>  }
>  
> +static void audit_contid_free(struct rcu_head *rcu)
> +{
> +       struct audit_contid *cont;
> +
> +       cont = container_of(rcu, struct audit_contid, rcu);
> +       kmem_cache_free(audit_contid_cache, cont);
> +}
> +
>  void audit_netns_contid_del(struct net *net, u64 contid)
>  {
>         struct audit_net *aunet;
> @@ -434,7 +447,7 @@ void audit_netns_contid_del(struct net *net, u64 contid)
>                 if (cont->id == contid) {
>                         if (refcount_dec_and_test(&cont->refcount)) {
>                                 list_del_rcu(&cont->list);
> -                               kfree_rcu(cont, rcu);
> +                               call_rcu(&cont->rcu, audit_contid_free);
>                         }
>                         break;
>                 }
> 
> - RGB
> 
> --
> Richard Guy Briggs <rgb@redhat.com>
> Sr. S/W Engineer, Kernel Security, Base Operating Systems
> Remote, Ottawa, Red Hat Canada
> IRC: rgb, SunRaycer
> Voice: +1.647.777.2635, Internal: (81) 32635
> 

^ permalink raw reply	[flat|nested] 64+ messages in thread

end of thread, other threads:[~2019-04-05 11:32 UTC | newest]

Thread overview: 64+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-03-15 18:29 [PATCH ghak90 V5 00/10] audit: implement container identifier Richard Guy Briggs
2019-03-15 18:29 ` [PATCH ghak90 V5 01/10] audit: collect audit task parameters Richard Guy Briggs
2019-03-16 19:57   ` Neil Horman
2019-03-27 20:33   ` Ondrej Mosnacek
2019-03-15 18:29 ` [PATCH ghak90 V5 02/10] audit: add container id Richard Guy Briggs
2019-03-16 20:00   ` Neil Horman
2019-03-27 20:38   ` Ondrej Mosnacek
2019-03-27 20:44     ` Richard Guy Briggs
2019-03-15 18:29 ` [PATCH ghak90 V5 03/10] audit: read container ID of a process Richard Guy Briggs
2019-03-18 11:10   ` Neil Horman
2019-03-18 18:17     ` Richard Guy Briggs
2019-03-18 18:48       ` Neil Horman
2019-03-18 18:54         ` Richard Guy Briggs
2019-03-27 20:44   ` Ondrej Mosnacek
2019-03-15 18:29 ` [PATCH ghak90 V5 04/10] audit: log container info of syscalls Richard Guy Briggs
2019-03-16 22:44   ` Neil Horman
2019-03-27 21:01   ` Ondrej Mosnacek
2019-03-27 22:10     ` Richard Guy Briggs
2019-03-15 18:29 ` [PATCH ghak90 V5 05/10] audit: add containerid support for ptrace and signals Richard Guy Briggs
2019-03-18 19:04   ` Neil Horman
2019-03-18 19:29     ` Richard Guy Briggs
2019-03-27 21:17   ` Ondrej Mosnacek
2019-03-28  2:04     ` Richard Guy Briggs
2019-03-30 12:55       ` Richard Guy Briggs
2019-03-15 18:29 ` [PATCH ghak90 V5 06/10] audit: add support for non-syscall auxiliary records Richard Guy Briggs
2019-03-18 19:34   ` Neil Horman
2019-03-27 21:22   ` Ondrej Mosnacek
2019-04-01 14:49   ` Paul Moore
2019-04-01 17:44     ` Richard Guy Briggs
2019-04-01 18:57       ` Paul Moore
2019-04-01 20:43         ` Richard Guy Briggs
2019-03-15 18:29 ` [PATCH ghak90 V5 07/10] audit: add containerid support for user records Richard Guy Briggs
2019-03-18 19:41   ` Neil Horman
2019-03-27 21:30   ` Ondrej Mosnacek
2019-03-15 18:29 ` [PATCH ghak90 V5 08/10] audit: add containerid filtering Richard Guy Briggs
2019-03-18 20:02   ` Ondrej Mosnacek
2019-03-18 23:47     ` Richard Guy Briggs
2019-03-27 21:41       ` Ondrej Mosnacek
2019-03-27 22:00         ` Richard Guy Briggs
2019-03-18 20:39   ` Neil Horman
2019-03-15 18:29 ` [PATCH ghak90 V5 09/10] audit: add support for containerid to network namespaces Richard Guy Briggs
2019-03-18 20:56   ` Neil Horman
2019-03-27 22:42   ` Ondrej Mosnacek
2019-03-28  1:12     ` Richard Guy Briggs
2019-03-28  8:01       ` Ondrej Mosnacek
2019-03-28 15:46       ` Paul Moore
2019-03-28 21:40         ` Richard Guy Briggs
2019-03-28 22:00           ` Paul Moore
2019-03-31  2:11             ` Neil Horman
2019-03-29 14:50           ` Neil Horman
2019-03-29 14:49       ` Neil Horman
2019-04-01 14:50   ` Paul Moore
2019-04-01 20:41     ` Richard Guy Briggs
2019-04-02 11:31     ` Neil Horman
2019-04-02 13:31       ` Paul Moore
2019-04-02 14:28         ` Neil Horman
2019-04-04 21:40       ` Richard Guy Briggs
2019-04-05  2:06         ` Paul Moore
2019-04-05 11:32         ` Neil Horman
2019-03-15 18:29 ` [PATCH ghak90 V5 10/10] audit: NETFILTER_PKT: record each container ID associated with a netNS Richard Guy Briggs
2019-03-18 20:58   ` Neil Horman
2019-03-27 22:52   ` Ondrej Mosnacek
2019-04-01 14:50   ` Paul Moore
2019-04-01 17:50     ` Richard Guy Briggs

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).