2018-07-31 20:13:05

by Richard Guy Briggs

[permalink] [raw]
Subject: [PATCH ghak90 (was ghak32) V4 00/10] audit: implement container identifier

Implement kernel audit container identifier.

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

The first patch is the last patch from ghak81 that is included here as a
convenience.

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 the auxiliary record AUDIT_CONTAINER if an
audit container identifier is identifiable with an event. This patch
requires userspace support for proper type display.

The 4th adds signal and ptrace support.

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

The 6th patch adds audit container identifier records to the tty
standalone record.

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

The 9th adds audit container identifier support to standalone netfilter
records that don't have a task context and lists each container to which
that net namespace belongs.

The 10th implements reading the audit container identifier from the proc
filesystem for debugging. This patch isn't planned for upstream
inclusion.


Example: Set an audit container identifier of 123456 to the "sleep" task:

sleep 2&
child=$!
echo 123456 > /proc/$child/audit_containerid; echo $?
ausearch -ts recent -m container
echo child:$child contid:$( cat /proc/$child/audit_containerid)

This should produce a record such as:

type=CONTAINER_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 msg=audit(2018-06-06 12:46:31.707:26953) : op=task contid=123459
type=PROCTITLE msg=audit(2018-06-06 12:46:31.707:26953) : proctitle=perl -e sleep 1; open(my $tmpfile, '>', "/tmp/tmpcontainerid"); close($tmpfile);
type=PATH msg=audit(2018-06-06 12:46:31.707:26953) : item=1 name=/tmp/tmpcontainerid inode=25656 dev=00:26 mode=file,644 ouid=root ogid=root rdev=00:00 obj=unconfined_u:object_r:user_tmp_t:s0 nametype=CREATE cap_fp=none cap_fi=none cap_fe=0 cap_fver=0
type=PATH msg=audit(2018-06-06 12:46:31.707:26953) : item=0 name=/tmp/ inode=8985 dev=00:26 mode=dir,sticky,777 ouid=root ogid=root rdev=00:00 obj=system_u:object_r:tmp_t:s0 nametype=PARENT cap_fp=none cap_fi=none cap_fe=0 cap_fver=0
type=CWD msg=audit(2018-06-06 12:46:31.707:26953) : cwd=/root
type=SYSCALL msg=audit(2018-06-06 12:46:31.707:26953) : arch=x86_64 syscall=openat success=yes exit=3 a0=0xffffffffffffff9c a1=0x5621f2b81900 a2=O_WRONLY|O_CREAT|O_TRUNC a3=0x1b6 items=2 ppid=628 pid=2232 auid=root uid=root gid=root euid=root suid=root fsuid=root egid=root sgid=root fsgid=root tty=ttyS0 ses=1 comm=perl exe=/usr/bin/perl subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 key=tmpcontainerid


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

Changelog:

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: log container info of syscalls
audit: add containerid support for ptrace and signals
audit: add support for non-syscall auxiliary records
audit: add containerid support for tty_audit
audit: add containerid filtering
audit: add support for containerid to network namespaces
audit: NETFILTER_PKT: record each container ID associated with a netNS
debug audit: read container ID of a process

drivers/tty/tty_audit.c | 5 +-
fs/proc/base.c | 56 ++++++++++++++
include/linux/audit.h | 95 ++++++++++++++++++++---
include/linux/sched.h | 5 +-
include/uapi/linux/audit.h | 8 +-
init/init_task.c | 3 +-
init/main.c | 2 +
kernel/audit.c | 137 +++++++++++++++++++++++++++++++++
kernel/audit.h | 4 +
kernel/auditfilter.c | 47 ++++++++++++
kernel/auditsc.c | 183 ++++++++++++++++++++++++++++++++++++++++-----
kernel/fork.c | 4 +-
kernel/nsproxy.c | 4 +
net/netfilter/xt_AUDIT.c | 12 ++-
14 files changed, 526 insertions(+), 39 deletions(-)

--
1.8.3.1



2018-07-31 20:13:06

by Richard Guy Briggs

[permalink] [raw]
Subject: [PATCH ghak90 (was ghak32) V4 01/10] audit: collect audit task parameters

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.

See: https://github.com/linux-audit/audit-kernel/issues/81

Signed-off-by: Richard Guy Briggs <[email protected]>
---
include/linux/audit.h | 34 ++++++++++++++++++++++++----------
include/linux/sched.h | 5 +----
init/init_task.c | 3 +--
init/main.c | 2 ++
kernel/auditsc.c | 51 ++++++++++++++++++++++++++++++++++++++++++---------
kernel/fork.c | 4 +++-
6 files changed, 73 insertions(+), 26 deletions(-)

diff --git a/include/linux/audit.h b/include/linux/audit.h
index 9334fbe..8964332 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -219,8 +219,15 @@ static inline void audit_log_task_info(struct audit_buffer *ab,

/* These are defined in auditsc.c */
/* Public API */
+struct audit_task_info {
+ kuid_t loginuid;
+ unsigned int sessionid;
+ struct audit_context *ctx;
+};
+extern struct audit_task_info init_struct_audit;
+extern void __init audit_task_init(void);
extern int audit_alloc(struct task_struct *task);
-extern void __audit_free(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);
@@ -242,12 +249,15 @@ 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 current->audit->ctx;
+ else
+ return NULL;
}

static inline bool audit_dummy_context(void)
@@ -255,11 +265,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)
@@ -331,12 +337,18 @@ extern int auditsc_get_stamp(struct audit_context *ctx,

static inline kuid_t audit_get_loginuid(struct task_struct *tsk)
{
- return tsk->loginuid;
+ if (tsk->audit)
+ return tsk->audit->loginuid;
+ else
+ return INVALID_UID;
}

static inline unsigned int audit_get_sessionid(struct task_struct *tsk)
{
- return tsk->sessionid;
+ if (tsk->audit)
+ return tsk->audit->sessionid;
+ else
+ return AUDIT_SID_UNSET;
}

extern void __audit_ipc_obj(struct kern_ipc_perm *ipcp);
@@ -461,6 +473,8 @@ static inline void audit_fanotify(unsigned int response)
extern int audit_n_rules;
extern int audit_signals;
#else /* CONFIG_AUDITSYSCALL */
+static inline void __init audit_task_init(void)
+{ }
static inline int audit_alloc(struct task_struct *task)
{
return 0;
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 87bf02d..e117272 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -30,7 +30,6 @@
#include <linux/rseq.h>

/* task_struct member predeclarations (sorted alphabetically): */
-struct audit_context;
struct backing_dev_info;
struct bio_list;
struct blk_plug;
@@ -873,10 +872,8 @@ struct task_struct {

struct callback_head *task_works;

- struct audit_context *audit_context;
#ifdef CONFIG_AUDITSYSCALL
- 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 74f60ba..4058840 100644
--- a/init/init_task.c
+++ b/init/init_task.c
@@ -119,8 +119,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_AUDITSYSCALL
- .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 3b4ada1..6aba171 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>
@@ -721,6 +722,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/auditsc.c b/kernel/auditsc.c
index fb20746..88779a7 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -841,7 +841,7 @@ static inline struct audit_context *audit_take_context(struct task_struct *tsk,
int return_valid,
long return_code)
{
- struct audit_context *context = tsk->audit_context;
+ struct audit_context *context = tsk->audit->ctx;

if (!context)
return NULL;
@@ -926,6 +926,15 @@ static inline struct audit_context *audit_alloc_context(enum audit_state state)
return context;
}

+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 context block for a task
* @tsk: task
@@ -940,17 +949,28 @@ int audit_alloc(struct task_struct *tsk)
struct audit_context *context;
enum audit_state state;
char *key = NULL;
+ struct audit_task_info *info;
+
+ info = kmem_cache_zalloc(audit_task_cache, GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+ info->loginuid = audit_get_loginuid(current);
+ info->sessionid = audit_get_sessionid(current);
+ tsk->audit = info;

if (likely(!audit_ever_enabled))
return 0; /* Return if not auditing. */

state = audit_filter_task(tsk, &key);
if (state == AUDIT_DISABLED) {
+ audit_set_context(tsk, NULL);
clear_tsk_thread_flag(tsk, TIF_SYSCALL_AUDIT);
return 0;
}

if (!(context = audit_alloc_context(state))) {
+ tsk->audit = NULL;
+ kmem_cache_free(audit_task_cache, info);
kfree(key);
audit_log_lost("out of memory in audit_alloc");
return -ENOMEM;
@@ -962,6 +982,12 @@ int audit_alloc(struct task_struct *tsk)
return 0;
}

+struct audit_task_info init_struct_audit = {
+ .loginuid = INVALID_UID,
+ .sessionid = AUDIT_SID_UNSET,
+ .ctx = NULL,
+};
+
static inline void audit_free_context(struct audit_context *context)
{
audit_free_names(context);
@@ -1469,26 +1495,33 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
}

/**
- * __audit_free - free a per-task audit context
+ * audit_free - free a per-task audit context
* @tsk: task whose audit context block to free
*
* Called from copy_process and do_exit
*/
-void __audit_free(struct task_struct *tsk)
+void audit_free(struct task_struct *tsk)
{
struct audit_context *context;
+ struct audit_task_info *info;

context = audit_take_context(tsk, 0, 0);
- if (!context)
- return;
-
/* Check for system calls that do not go through the exit
* function (e.g., exit_group), then free context block.
* We use GFP_ATOMIC here because we might be doing this
* in the context of the idle thread */
/* that can happen only if we are called from do_exit() */
- if (context->in_syscall && context->current_state == AUDIT_RECORD_CONTEXT)
+ if (context && context->in_syscall &&
+ context->current_state == AUDIT_RECORD_CONTEXT)
audit_log_exit(context, 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);
+ if (!context)
+ return;
if (!list_empty(&context->killed_trees))
audit_kill_trees(&context->killed_trees);

@@ -2071,8 +2104,8 @@ int audit_set_loginuid(kuid_t loginuid)
sessionid = (unsigned int)atomic_inc_return(&session_id);
}

- task->sessionid = sessionid;
- task->loginuid = loginuid;
+ task->audit->sessionid = sessionid;
+ task->audit->loginuid = loginuid;
out:
audit_log_set_loginuid(oldloginuid, loginuid, oldsessionid, sessionid, rc);
return rc;
diff --git a/kernel/fork.c b/kernel/fork.c
index 9440d61..1bfb0ff 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1721,7 +1721,9 @@ 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);
+#ifdef CONFIG_AUDITSYSCALL
+ p->audit = NULL;
+#endif /* CONFIG_AUDITSYSCALL */
cgroup_fork(p);
#ifdef CONFIG_NUMA
p->mempolicy = mpol_dup(p->mempolicy);
--
1.8.3.1


2018-07-31 20:13:17

by Richard Guy Briggs

[permalink] [raw]
Subject: [PATCH ghak90 (was ghak32) V4 03/10] audit: log container info of syscalls

Create a new audit record AUDIT_CONTAINER 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=0000000000000000 cap_fi=0000000000000000 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=0000000000000000 cap_fi=0000000000000000 cap_fe=0 cap_fver=0
type=PROCTITLE msg=audit(1519924845.499:257): proctitle=62617368002D6300736C65657020313B206563686F2074657374203E202F746D702F746D70636F6E7461696E65726964
type=CONTAINER msg=audit(1519924845.499:257): op=task 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 <[email protected]>
Acked-by: Serge Hallyn <[email protected]>
Acked-by: Steve Grubb <[email protected]>
---
include/linux/audit.h | 7 +++++++
include/uapi/linux/audit.h | 1 +
kernel/audit.c | 24 ++++++++++++++++++++++++
kernel/auditsc.c | 3 +++
4 files changed, 35 insertions(+)

diff --git a/include/linux/audit.h b/include/linux/audit.h
index 71a6fc6..d5a48dc 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -155,6 +155,9 @@ extern void audit_log_key(struct audit_buffer *ab,
extern int audit_log_task_context(struct audit_buffer *ab);
extern void audit_log_task_info(struct audit_buffer *ab,
struct task_struct *tsk);
+extern int audit_log_contid(struct task_struct *tsk,
+ struct audit_context *context,
+ char *op);

extern int audit_update_lsm_rules(void);

@@ -205,6 +208,10 @@ static inline int audit_log_task_context(struct audit_buffer *ab)
static inline void audit_log_task_info(struct audit_buffer *ab,
struct task_struct *tsk)
{ }
+static inline int audit_log_contid(struct task_struct *tsk,
+ struct audit_context *context,
+ char *op)
+{ }
#define audit_enabled AUDIT_OFF
#endif /* CONFIG_AUDIT */

diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h
index 3474f57..dc259c7 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 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 2a80587..15f54c7 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -2045,6 +2045,30 @@ 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
+ * @tsk: task to be recorded
+ * @context: task or local context for record
+ * @op: contid string description
+ */
+int audit_log_contid(struct task_struct *tsk,
+ struct audit_context *context, char *op)
+{
+ struct audit_buffer *ab;
+
+ if (!audit_contid_set(tsk))
+ return 0;
+ /* Generate AUDIT_CONTAINER record with container ID */
+ ab = audit_log_start(context, GFP_KERNEL, AUDIT_CONTAINER);
+ if (!ab)
+ return -ENOMEM;
+ audit_log_format(ab, "op=%s contid=%llu",
+ op, audit_get_contid(tsk));
+ audit_log_end(ab);
+ return 0;
+}
+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 6125cef..39e5633 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -1488,10 +1488,13 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts

audit_log_proctitle(tsk, context);

+ audit_log_contid(tsk, context, "task");
+
/* Send end of event record to help user space know we are finished */
ab = audit_log_start(context, GFP_KERNEL, AUDIT_EOE);
if (ab)
audit_log_end(ab);
+
if (call_panic)
audit_panic("error converting sid to string");
}
--
1.8.3.1


2018-07-31 20:13:17

by Richard Guy Briggs

[permalink] [raw]
Subject: [PATCH ghak90 (was ghak32) V4 04/10] audit: add containerid support for ptrace and signals

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

Signed-off-by: Richard Guy Briggs <[email protected]>
Acked-by: Serge Hallyn <[email protected]>
---
include/linux/audit.h | 11 +++++------
kernel/audit.c | 13 +++++++------
kernel/audit.h | 2 ++
kernel/auditsc.c | 21 ++++++++++++++++-----
4 files changed, 30 insertions(+), 17 deletions(-)

diff --git a/include/linux/audit.h b/include/linux/audit.h
index d5a48dc..4f514ed 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -34,6 +34,7 @@ struct audit_sig_info {
uid_t uid;
pid_t pid;
char ctx[0];
+ u64 cid;
};

struct audit_buffer;
@@ -155,9 +156,8 @@ extern void audit_log_key(struct audit_buffer *ab,
extern int audit_log_task_context(struct audit_buffer *ab);
extern void audit_log_task_info(struct audit_buffer *ab,
struct task_struct *tsk);
-extern int audit_log_contid(struct task_struct *tsk,
- struct audit_context *context,
- char *op);
+extern int audit_log_contid(struct audit_context *context,
+ char *op, u64 contid);

extern int audit_update_lsm_rules(void);

@@ -208,9 +208,8 @@ static inline int audit_log_task_context(struct audit_buffer *ab)
static inline void audit_log_task_info(struct audit_buffer *ab,
struct task_struct *tsk)
{ }
-static inline int audit_log_contid(struct task_struct *tsk,
- struct audit_context *context,
- char *op)
+static inline int audit_log_contid(struct audit_context *context,
+ char *op, u64 contid)
{ }
#define audit_enabled AUDIT_OFF
#endif /* CONFIG_AUDIT */
diff --git a/kernel/audit.c b/kernel/audit.c
index 15f54c7..fc9f026f 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -139,6 +139,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]
@@ -1434,6 +1435,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);
@@ -2047,23 +2049,22 @@ void audit_log_session_info(struct audit_buffer *ab)

/*
* audit_log_contid - report container info
- * @tsk: task to be recorded
* @context: task or local context for record
* @op: contid string description
+ * @contid: container ID to report
*/
-int audit_log_contid(struct task_struct *tsk,
- struct audit_context *context, char *op)
+int audit_log_contid(struct audit_context *context,
+ char *op, u64 contid)
{
struct audit_buffer *ab;

- if (!audit_contid_set(tsk))
+ if (!audit_contid_valid(contid))
return 0;
/* Generate AUDIT_CONTAINER record with container ID */
ab = audit_log_start(context, GFP_KERNEL, AUDIT_CONTAINER);
if (!ab)
return -ENOMEM;
- audit_log_format(ab, "op=%s contid=%llu",
- op, audit_get_contid(tsk));
+ audit_log_format(ab, "op=%s contid=%llu", op, contid);
audit_log_end(ab);
return 0;
}
diff --git a/kernel/audit.h b/kernel/audit.h
index 214e149..1cf1c35 100644
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -147,6 +147,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;
@@ -329,6 +330,7 @@ extern void audit_log_d_path_exe(struct audit_buffer *ab,
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 39e5633..cdb24cf 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;
};
@@ -1454,21 +1455,27 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
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++) {
+ char axsn[sizeof("aux0xN ")];
+
+ sprintf(axsn, "aux0x%x", i);
if (audit_log_pid_context(context, axs->target_pid[i],
axs->target_auid[i],
axs->target_uid[i],
axs->target_sessionid[i],
axs->target_sid[i],
- axs->target_comm[i]))
+ axs->target_comm[i])
+ || audit_log_contid(context, axsn, axs->target_cid[i]))
call_panic = 1;
+ }
}

if (context->target_pid &&
- audit_log_pid_context(context, 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))
+ context->target_sid, context->target_comm)
+ || audit_log_contid(context, "target", context->target_cid)))
call_panic = 1;

if (context->pwd.dentry && context->pwd.mnt) {
@@ -1488,7 +1495,7 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts

audit_log_proctitle(tsk, context);

- audit_log_contid(tsk, context, "task");
+ audit_log_contid(context, "task", audit_get_contid(tsk));

/* Send end of event record to help user space know we are finished */
ab = audit_log_start(context, GFP_KERNEL, AUDIT_EOE);
@@ -2372,6 +2379,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);
}

@@ -2399,6 +2407,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())
@@ -2412,6 +2421,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;
}
@@ -2433,6 +2443,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


2018-07-31 20:13:21

by Richard Guy Briggs

[permalink] [raw]
Subject: [PATCH ghak90 (was ghak32) V4 06/10] audit: add containerid support for tty_audit

Add audit container identifier auxiliary record to tty logging rule
event standalone records.

Signed-off-by: Richard Guy Briggs <[email protected]>
Acked-by: Serge Hallyn <[email protected]>
---
drivers/tty/tty_audit.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/tty/tty_audit.c b/drivers/tty/tty_audit.c
index 50f567b..3e21477 100644
--- a/drivers/tty/tty_audit.c
+++ b/drivers/tty/tty_audit.c
@@ -66,8 +66,9 @@ static void tty_audit_log(const char *description, dev_t dev,
uid_t uid = from_kuid(&init_user_ns, task_uid(tsk));
uid_t loginuid = from_kuid(&init_user_ns, audit_get_loginuid(tsk));
unsigned int sessionid = audit_get_sessionid(tsk);
+ struct audit_context *context = audit_alloc_local(GFP_KERNEL);

- ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_TTY);
+ ab = audit_log_start(context, GFP_KERNEL, AUDIT_TTY);
if (ab) {
char name[sizeof(tsk->comm)];

@@ -80,6 +81,8 @@ static void tty_audit_log(const char *description, dev_t dev,
audit_log_n_hex(ab, data, size);
audit_log_end(ab);
}
+ audit_log_contid(context, "tty", audit_get_contid(tsk));
+ audit_free_context(context);
}

/**
--
1.8.3.1


2018-07-31 20:13:37

by Richard Guy Briggs

[permalink] [raw]
Subject: [PATCH ghak90 (was ghak32) V4 09/10] audit: NETFILTER_PKT: record each container ID associated with a netNS

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 <[email protected]>
---
include/linux/audit.h | 5 +++++
kernel/audit.c | 26 ++++++++++++++++++++++++++
net/netfilter/xt_AUDIT.c | 12 ++++++++++--
3 files changed, 41 insertions(+), 2 deletions(-)

diff --git a/include/linux/audit.h b/include/linux/audit.h
index 9a02095..8755f4d 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -169,6 +169,8 @@ extern int audit_log_contid(struct audit_context *context,
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 void audit_log_netns_contid_list(struct net *net,
+ struct audit_context *context);

extern int audit_update_lsm_rules(void);

@@ -228,6 +230,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 c5fed3b..b23711c 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -392,6 +392,32 @@ void audit_switch_task_namespaces(struct nsproxy *ns, struct task_struct *p)
audit_netns_contid_add(new->net_ns, contid);
}

+void audit_log_netns_contid_list(struct net *net, struct audit_context *context)
+{
+ spinlock_t *lock = audit_get_netns_contid_list_lock(net);
+ struct audit_buffer *ab;
+ struct audit_contid *cont;
+ bool first = true;
+
+ /* Generate AUDIT_CONTAINER record with container ID CSV list */
+ ab = audit_log_start(context, GFP_ATOMIC, AUDIT_CONTAINER);
+ if (!ab) {
+ audit_log_lost("out of memory in audit_log_netns_contid_list");
+ return;
+ }
+ audit_log_format(ab, "contid=");
+ spin_lock(lock);
+ list_for_each_entry(cont, audit_get_netns_contid_list(net), list) {
+ if (!first)
+ audit_log_format(ab, ",");
+ audit_log_format(ab, "%llu", cont->id);
+ first = false;
+ }
+ spin_unlock(lock);
+ audit_log_end(ab);
+}
+EXPORT_SYMBOL(audit_log_netns_contid_list);
+
void audit_panic(const char *message)
{
switch (audit_failure) {
diff --git a/net/netfilter/xt_AUDIT.c b/net/netfilter/xt_AUDIT.c
index af883f1..44fac3f 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,12 @@ 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


2018-07-31 20:13:38

by Richard Guy Briggs

[permalink] [raw]
Subject: [PATCH ghak90 (was ghak32) V4 08/10] audit: add support for containerid to network namespaces

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 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 <[email protected]>
---
include/linux/audit.h | 17 ++++++++++
kernel/audit.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++
kernel/auditsc.c | 8 ++++-
kernel/nsproxy.c | 4 +++
4 files changed, 114 insertions(+), 1 deletion(-)

diff --git a/include/linux/audit.h b/include/linux/audit.h
index 5580c25..9a02095 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -26,6 +26,7 @@
#include <linux/sched.h>
#include <linux/ptrace.h>
#include <uapi/linux/audit.h>
+#include <linux/refcount.h>

#define AUDIT_INO_UNSET ((unsigned long)-1)
#define AUDIT_DEV_UNSET ((dev_t)-1)
@@ -87,6 +88,12 @@ struct audit_field {
u32 op;
};

+struct audit_contid {
+ struct list_head list;
+ u64 id;
+ refcount_t refcount;
+};
+
extern int is_audit_feature_set(int which);

extern int __init audit_register_class(int class, unsigned *list);
@@ -159,6 +166,9 @@ extern void audit_log_task_info(struct audit_buffer *ab,
struct task_struct *tsk);
extern int audit_log_contid(struct audit_context *context,
char *op, 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 int audit_update_lsm_rules(void);

@@ -212,6 +222,13 @@ static inline void audit_log_task_info(struct audit_buffer *ab,
static inline int audit_log_contid(struct audit_context *context,
char *op, 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 fc9f026f..c5fed3b 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -100,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;
};

/**
@@ -308,6 +312,86 @@ static struct sock *audit_get_sk(const struct net *net)
return aunet->sk;
}

+/**
+ * audit_get_netns_contid_list - Return the audit container ID list for the given network namespace
+ * @net: the destination network namespace
+ *
+ * Description:
+ * Returns the list pointer if valid, NULL otherwise. The caller must ensure
+ * that a reference is held for the network namespace while the sock is in use.
+ */
+struct list_head *audit_get_netns_contid_list(const struct net *net)
+{
+ struct audit_net *aunet = net_generic(net, audit_net_id);
+
+ return &aunet->contid_list;
+}
+
+spinlock_t *audit_get_netns_contid_list_lock(const struct net *net)
+{
+ struct audit_net *aunet = net_generic(net, audit_net_id);
+
+ return &aunet->contid_list_lock;
+}
+
+void audit_netns_contid_add(struct net *net, u64 contid)
+{
+ spinlock_t *lock = audit_get_netns_contid_list_lock(net);
+ struct list_head *contid_list = audit_get_netns_contid_list(net);
+ struct audit_contid *cont;
+
+ if (!audit_contid_valid(contid))
+ return;
+ spin_lock(lock);
+ if (!list_empty(contid_list))
+ list_for_each_entry(cont, contid_list, list)
+ if (cont->id == contid) {
+ refcount_inc(&cont->refcount);
+ goto out;
+ }
+ cont = kmalloc(sizeof(struct audit_contid), GFP_KERNEL);
+ if (cont) {
+ INIT_LIST_HEAD(&cont->list);
+ cont->id = contid;
+ refcount_set(&cont->refcount, 1);
+ list_add(&cont->list, contid_list);
+ }
+out:
+ spin_unlock(lock);
+}
+
+void audit_netns_contid_del(struct net *net, u64 contid)
+{
+ spinlock_t *lock = audit_get_netns_contid_list_lock(net);
+ struct list_head *contid_list = audit_get_netns_contid_list(net);
+ struct audit_contid *cont = NULL;
+
+ if (!audit_contid_valid(contid))
+ return;
+ spin_lock(lock);
+ if (!list_empty(contid_list))
+ list_for_each_entry(cont, contid_list, list)
+ if (cont->id == contid) {
+ list_del(&cont->list);
+ if (refcount_dec_and_test(&cont->refcount))
+ kfree(cont);
+ break;
+ }
+ spin_unlock(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) {
@@ -1547,6 +1631,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;
}
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 610c6869..fdf3f68 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -75,6 +75,7 @@
#include <linux/uaccess.h>
#include <linux/fsnotify_backend.h>
#include <uapi/linux/limits.h>
+#include <net/net_namespace.h>

#include "audit.h"

@@ -2165,6 +2166,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 */
@@ -2186,8 +2188,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 f6c5d33..718b120 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


2018-07-31 20:13:39

by Richard Guy Briggs

[permalink] [raw]
Subject: [PATCH ghak90 (was ghak32) V4 10/10] debug audit: read container ID of a process

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 <[email protected]>
Acked-by: Serge Hallyn <[email protected]>
---
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 1b3cda1..95fc64a 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -1261,6 +1261,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)
{
@@ -1291,6 +1309,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,
};
@@ -2987,7 +3006,7 @@ static int proc_pid_patch_state(struct seq_file *m, struct pid_namespace *ns,
#ifdef CONFIG_AUDITSYSCALL
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),
@@ -3373,7 +3392,7 @@ static int proc_tid_comm_permission(struct inode *inode, int mask)
#ifdef CONFIG_AUDITSYSCALL
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


2018-07-31 20:13:52

by Richard Guy Briggs

[permalink] [raw]
Subject: [PATCH ghak90 (was ghak32) V4 02/10] audit: add container id

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_ID msg=audit(2018-06-06 12:39:29.636:26949) : op=set opid=2209 old-contid=18446744073709551615 contid=123456 pid=628 auid=root uid=root tty=ttyS0 ses=1 subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 comm=bash exe=/usr/bin/bash res=yes

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 <[email protected]>
Acked-by: Serge Hallyn <[email protected]>
Acked-by: Steve Grubb <[email protected]>
---
fs/proc/base.c | 37 +++++++++++++++++++++++++
include/linux/audit.h | 24 ++++++++++++++++
include/uapi/linux/audit.h | 2 ++
kernel/auditsc.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 131 insertions(+)

diff --git a/fs/proc/base.c b/fs/proc/base.c
index b657294..1b3cda1 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -1260,6 +1260,41 @@ 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
@@ -2952,6 +2987,7 @@ static int proc_pid_patch_state(struct seq_file *m, struct pid_namespace *ns,
#ifdef CONFIG_AUDITSYSCALL
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),
@@ -3337,6 +3373,7 @@ static int proc_tid_comm_permission(struct inode *inode, int mask)
#ifdef CONFIG_AUDITSYSCALL
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 8964332..71a6fc6 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -222,6 +222,7 @@ static inline void audit_log_task_info(struct audit_buffer *ab,
struct audit_task_info {
kuid_t loginuid;
unsigned int sessionid;
+ u64 contid;
struct audit_context *ctx;
};
extern struct audit_task_info init_struct_audit;
@@ -334,6 +335,7 @@ static inline void audit_ptrace(struct task_struct *t)
extern int auditsc_get_stamp(struct audit_context *ctx,
struct timespec64 *t, unsigned int *serial);
extern int audit_set_loginuid(kuid_t loginuid);
+extern int audit_set_contid(struct task_struct *tsk, u64 contid);

static inline kuid_t audit_get_loginuid(struct task_struct *tsk)
{
@@ -351,6 +353,14 @@ 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)
+{
+ if (!tsk->audit)
+ return AUDIT_CID_UNSET;
+ else
+ return tsk->audit->contid;
+}
+
extern void __audit_ipc_obj(struct kern_ipc_perm *ipcp);
extern void __audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, umode_t mode);
extern void __audit_bprm(struct linux_binprm *bprm);
@@ -545,6 +555,10 @@ static inline unsigned int audit_get_sessionid(struct task_struct *tsk)
{
return AUDIT_SID_UNSET;
}
+static inline kuid_t audit_get_contid(struct task_struct *tsk)
+{
+ return AUDIT_CID_UNSET;
+}
static inline void audit_ipc_obj(struct kern_ipc_perm *ipcp)
{ }
static inline void audit_ipc_set_perm(unsigned long qbytes, uid_t uid,
@@ -609,6 +623,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 4e3eaba..3474f57 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 */
@@ -468,6 +469,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/auditsc.c b/kernel/auditsc.c
index 88779a7..6125cef 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -956,6 +956,7 @@ int audit_alloc(struct task_struct *tsk)
return -ENOMEM;
info->loginuid = audit_get_loginuid(current);
info->sessionid = audit_get_sessionid(current);
+ info->contid = audit_get_contid(current);
tsk->audit = info;

if (likely(!audit_ever_enabled))
@@ -985,6 +986,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,
.ctx = NULL,
};

@@ -2112,6 +2114,72 @@ int audit_set_loginuid(kuid_t loginuid)
}

/**
+ * audit_set_contid - set current task's audit_context 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(current);
+ 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_mq_open - record audit data for a POSIX MQ open
* @oflag: open flag
* @mode: mode bits
--
1.8.3.1


2018-07-31 20:14:07

by Richard Guy Briggs

[permalink] [raw]
Subject: [PATCH ghak90 (was ghak32) V4 05/10] audit: add support for non-syscall auxiliary records

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 <[email protected]>
Acked-by: Serge Hallyn <[email protected]>
---
include/linux/audit.h | 8 ++++++++
kernel/audit.h | 1 +
kernel/auditsc.c | 33 ++++++++++++++++++++++++++++-----
3 files changed, 37 insertions(+), 5 deletions(-)

diff --git a/include/linux/audit.h b/include/linux/audit.h
index 4f514ed..1f340ad 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -234,7 +234,9 @@ struct audit_task_info {
extern struct audit_task_info init_struct_audit;
extern void __init audit_task_init(void);
extern int audit_alloc(struct task_struct *task);
+extern struct audit_context *audit_alloc_local(gfp_t gfpflags);
extern void audit_free(struct task_struct *task);
+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);
@@ -495,6 +497,12 @@ static inline int audit_alloc(struct task_struct *task)
{
return 0;
}
+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_free(struct task_struct *task)
{ }
static inline void audit_syscall_entry(int major, unsigned long a0,
diff --git a/kernel/audit.h b/kernel/audit.h
index 1cf1c35..a6d00a5 100644
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -110,6 +110,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 cdb24cf..7627f21 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -913,11 +913,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;
@@ -970,7 +972,8 @@ int audit_alloc(struct task_struct *tsk)
return 0;
}

- if (!(context = audit_alloc_context(state))) {
+ context = audit_alloc_context(state, GFP_KERNEL);
+ if (!(context)) {
tsk->audit = NULL;
kmem_cache_free(audit_task_cache, info);
kfree(key);
@@ -991,8 +994,27 @@ struct audit_task_info init_struct_audit = {
.ctx = NULL,
};

-static inline void audit_free_context(struct audit_context *context)
+struct audit_context *audit_alloc_local(gfp_t gfpflags)
{
+ struct audit_context *context;
+
+ if (!audit_ever_enabled)
+ return NULL; /* Return if not auditing. */
+
+ context = audit_alloc_context(AUDIT_RECORD_CONTEXT, gfpflags);
+ if (!context)
+ return NULL;
+ context->serial = audit_serial();
+ context->ctime = current_kernel_time64();
+ context->local = true;
+ 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);
@@ -1002,6 +1024,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,
@@ -2024,7 +2047,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


2018-07-31 20:15:02

by Richard Guy Briggs

[permalink] [raw]
Subject: [PATCH ghak90 (was ghak32) V4 07/10] audit: add containerid filtering

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 <[email protected]>
Acked-by: Serge Hallyn <[email protected]>
---
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 1f340ad..5580c25 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -76,6 +76,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 dc259c7..8bd2498 100644
--- a/include/uapi/linux/audit.h
+++ b/include/uapi/linux/audit.h
@@ -264,6 +264,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). */
@@ -344,6 +345,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 | \
@@ -351,7 +353,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 a6d00a5..7feaa1f 100644
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -236,6 +236,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 bf309f2..31a6733 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 7627f21..610c6869 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -622,6 +622,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


2018-08-24 16:03:28

by Steve Grubb

[permalink] [raw]
Subject: Re: [PATCH ghak90 (was ghak32) V4 02/10] audit: add container id

On Tuesday, July 31, 2018 4:07:37 PM EDT 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_ID msg=audit(2018-06-06 12:39:29.636:26949) : op=set
> opid=2209 old-contid=18446744073709551615 contid=123456 pid=628 auid=root
> uid=root tty=ttyS0 ses=1
> subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 comm=bash
> exe=/usr/bin/bash res=yes
>
> The "op" field indicates an initial set.

The op field seems to be entirely unnecessary. There is no unset event (nor
should there be) so op=set is implied by the record type. Otherwise the event
format looks fine.

-Steve

> 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 <[email protected]>
> Acked-by: Serge Hallyn <[email protected]>
> Acked-by: Steve Grubb <[email protected]>
> ---
> fs/proc/base.c | 37 +++++++++++++++++++++++++
> include/linux/audit.h | 24 ++++++++++++++++
> include/uapi/linux/audit.h | 2 ++
> kernel/auditsc.c | 68
> ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 131
> insertions(+)
>
> diff --git a/fs/proc/base.c b/fs/proc/base.c
> index b657294..1b3cda1 100644
> --- a/fs/proc/base.c
> +++ b/fs/proc/base.c
> @@ -1260,6 +1260,41 @@ 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
> @@ -2952,6 +2987,7 @@ static int proc_pid_patch_state(struct seq_file *m,
> struct pid_namespace *ns, #ifdef CONFIG_AUDITSYSCALL
> 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),
> @@ -3337,6 +3373,7 @@ static int proc_tid_comm_permission(struct inode
> *inode, int mask) #ifdef CONFIG_AUDITSYSCALL
> 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 8964332..71a6fc6 100644
> --- a/include/linux/audit.h
> +++ b/include/linux/audit.h
> @@ -222,6 +222,7 @@ static inline void audit_log_task_info(struct
> audit_buffer *ab, struct audit_task_info {
> kuid_t loginuid;
> unsigned int sessionid;
> + u64 contid;
> struct audit_context *ctx;
> };
> extern struct audit_task_info init_struct_audit;
> @@ -334,6 +335,7 @@ static inline void audit_ptrace(struct task_struct *t)
> extern int auditsc_get_stamp(struct audit_context *ctx,
> struct timespec64 *t, unsigned int *serial);
> extern int audit_set_loginuid(kuid_t loginuid);
> +extern int audit_set_contid(struct task_struct *tsk, u64 contid);
>
> static inline kuid_t audit_get_loginuid(struct task_struct *tsk)
> {
> @@ -351,6 +353,14 @@ 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)
> +{
> + if (!tsk->audit)
> + return AUDIT_CID_UNSET;
> + else
> + return tsk->audit->contid;
> +}
> +
> extern void __audit_ipc_obj(struct kern_ipc_perm *ipcp);
> extern void __audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t
> gid, umode_t mode); extern void __audit_bprm(struct linux_binprm *bprm);
> @@ -545,6 +555,10 @@ static inline unsigned int audit_get_sessionid(struct
> task_struct *tsk) {
> return AUDIT_SID_UNSET;
> }
> +static inline kuid_t audit_get_contid(struct task_struct *tsk)
> +{
> + return AUDIT_CID_UNSET;
> +}
> static inline void audit_ipc_obj(struct kern_ipc_perm *ipcp)
> { }
> static inline void audit_ipc_set_perm(unsigned long qbytes, uid_t uid,
> @@ -609,6 +623,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 4e3eaba..3474f57 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 */
> @@ -468,6 +469,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/auditsc.c b/kernel/auditsc.c
> index 88779a7..6125cef 100644
> --- a/kernel/auditsc.c
> +++ b/kernel/auditsc.c
> @@ -956,6 +956,7 @@ int audit_alloc(struct task_struct *tsk)
> return -ENOMEM;
> info->loginuid = audit_get_loginuid(current);
> info->sessionid = audit_get_sessionid(current);
> + info->contid = audit_get_contid(current);
> tsk->audit = info;
>
> if (likely(!audit_ever_enabled))
> @@ -985,6 +986,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,
> .ctx = NULL,
> };
>
> @@ -2112,6 +2114,72 @@ int audit_set_loginuid(kuid_t loginuid)
> }
>
> /**
> + * audit_set_contid - set current task's audit_context 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(current);
> + 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_mq_open - record audit data for a POSIX MQ open
> * @oflag: open flag
> * @mode: mode bits





2018-08-24 16:04:36

by Steve Grubb

[permalink] [raw]
Subject: Re: [PATCH ghak90 (was ghak32) V4 03/10] audit: log container info of syscalls

On Tuesday, July 31, 2018 4:07:38 PM EDT Richard Guy Briggs wrote:
> Create a new audit record AUDIT_CONTAINER 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=0000000000000000
> cap_fi=0000000000000000 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=0000000000000000 cap_fi=0000000000000000 cap_fe=0 cap_fver=0
> type=PROCTITLE msg=audit(1519924845.499:257):
> proctitle=62617368002D6300736C65657020313B206563686F2074657374203E202F746D
> 702F746D70636F6E7461696E65726964 type=CONTAINER
> msg=audit(1519924845.499:257): op=task contid=123458

Ack for the event format.

-Steve

> 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 <[email protected]>
> Acked-by: Serge Hallyn <[email protected]>
> Acked-by: Steve Grubb <[email protected]>
> ---
> include/linux/audit.h | 7 +++++++
> include/uapi/linux/audit.h | 1 +
> kernel/audit.c | 24 ++++++++++++++++++++++++
> kernel/auditsc.c | 3 +++
> 4 files changed, 35 insertions(+)
>
> diff --git a/include/linux/audit.h b/include/linux/audit.h
> index 71a6fc6..d5a48dc 100644
> --- a/include/linux/audit.h
> +++ b/include/linux/audit.h
> @@ -155,6 +155,9 @@ extern void audit_log_key(struct audit_buffer
*ab,
> extern int audit_log_task_context(struct audit_buffer *ab);
> extern void audit_log_task_info(struct audit_buffer *ab,
> struct task_struct *tsk);
> +extern int audit_log_contid(struct task_struct *tsk,
> + struct audit_context *context,
> + char *op);
>
> extern int audit_update_lsm_rules(void);
>
> @@ -205,6 +208,10 @@ static inline int audit_log_task_context(struct
> audit_buffer *ab) static inline void audit_log_task_info(struct
> audit_buffer *ab,
> struct task_struct *tsk)
> { }
> +static inline int audit_log_contid(struct task_struct *tsk,
> + struct audit_context *context,
> + char *op)
> +{ }
> #define audit_enabled AUDIT_OFF
> #endif /* CONFIG_AUDIT */
>
> diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h
> index 3474f57..dc259c7 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 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 2a80587..15f54c7 100644
> --- a/kernel/audit.c
> +++ b/kernel/audit.c
> @@ -2045,6 +2045,30 @@ 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
> + * @tsk: task to be recorded
> + * @context: task or local context for record
> + * @op: contid string description
> + */
> +int audit_log_contid(struct task_struct *tsk,
> + struct audit_context *context, char *op)
> +{
> + struct audit_buffer *ab;
> +
> + if (!audit_contid_set(tsk))
> + return 0;
> + /* Generate AUDIT_CONTAINER record with container ID */
> + ab = audit_log_start(context, GFP_KERNEL, AUDIT_CONTAINER);
> + if (!ab)
> + return -ENOMEM;
> + audit_log_format(ab, "op=%s contid=%llu",
> + op, audit_get_contid(tsk));
> + audit_log_end(ab);
> + return 0;
> +}
> +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 6125cef..39e5633 100644
> --- a/kernel/auditsc.c
> +++ b/kernel/auditsc.c
> @@ -1488,10 +1488,13 @@ static void audit_log_exit(struct audit_context
> *context, struct task_struct *ts
>
> audit_log_proctitle(tsk, context);
>
> + audit_log_contid(tsk, context, "task");
> +
> /* Send end of event record to help user space know we are finished */
> ab = audit_log_start(context, GFP_KERNEL, AUDIT_EOE);
> if (ab)
> audit_log_end(ab);
> +
> if (call_panic)
> audit_panic("error converting sid to string");
> }





2018-10-19 19:41:21

by Paul Moore

[permalink] [raw]
Subject: Re: [PATCH ghak90 (was ghak32) V4 02/10] audit: add container id

On Tue, Jul 31, 2018 at 4:11 PM Richard Guy Briggs <[email protected]> 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_ID msg=audit(2018-06-06 12:39:29.636:26949) : op=set opid=2209 old-contid=18446744073709551615 contid=123456 pid=628 auid=root uid=root tty=ttyS0 ses=1 subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 comm=bash exe=/usr/bin/bash res=yes

You need to update the record type in the example above.

> 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.

I understand Steve's concern around the "op" field, but I think it
might be a bit premature to think we might not need to do some sort of
audit container ID management in the future that would want to make
use of the CONTAINER_OP message type. I would like to see the "op"
field preserved.

> 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 <[email protected]>
> Acked-by: Serge Hallyn <[email protected]>
> Acked-by: Steve Grubb <[email protected]>
> ---
> fs/proc/base.c | 37 +++++++++++++++++++++++++
> include/linux/audit.h | 24 ++++++++++++++++
> include/uapi/linux/audit.h | 2 ++
> kernel/auditsc.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++
> 4 files changed, 131 insertions(+)

...

> @@ -2112,6 +2114,72 @@ int audit_set_loginuid(kuid_t loginuid)
> }
>
> /**
> + * audit_set_contid - set current task's audit_context 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);

I assume lockdep was happy with nesting the tasklist_lock inside the task 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(current);
> + 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;
> +}

--
paul moore
http://www.paul-moore.com

2018-10-19 19:41:56

by Paul Moore

[permalink] [raw]
Subject: Re: [PATCH ghak90 (was ghak32) V4 02/10] audit: add container id

Ooops, I hit send prematurely on this :/ My comments below should
stand, but for things like this I usually try to get through the
entire patchset before sending my comments as later patches can affect
my comments on the earlier patches.

On Fri, Oct 19, 2018 at 3:38 PM Paul Moore <[email protected]> wrote:
> On Tue, Jul 31, 2018 at 4:11 PM Richard Guy Briggs <[email protected]> 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_ID msg=audit(2018-06-06 12:39:29.636:26949) : op=set opid=2209 old-contid=18446744073709551615 contid=123456 pid=628 auid=root uid=root tty=ttyS0 ses=1 subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 comm=bash exe=/usr/bin/bash res=yes
>
> You need to update the record type in the example above.
>
> > 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.
>
> I understand Steve's concern around the "op" field, but I think it
> might be a bit premature to think we might not need to do some sort of
> audit container ID management in the future that would want to make
> use of the CONTAINER_OP message type. I would like to see the "op"
> field preserved.
>
> > 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 <[email protected]>
> > Acked-by: Serge Hallyn <[email protected]>
> > Acked-by: Steve Grubb <[email protected]>
> > ---
> > fs/proc/base.c | 37 +++++++++++++++++++++++++
> > include/linux/audit.h | 24 ++++++++++++++++
> > include/uapi/linux/audit.h | 2 ++
> > kernel/auditsc.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++
> > 4 files changed, 131 insertions(+)
>
> ...
>
> > @@ -2112,6 +2114,72 @@ int audit_set_loginuid(kuid_t loginuid)
> > }
> >
> > /**
> > + * audit_set_contid - set current task's audit_context 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);
>
> I assume lockdep was happy with nesting the tasklist_lock inside the task 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(current);
> > + 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;
> > +}
>
> --
> paul moore
> http://www.paul-moore.com



--
paul moore
http://www.paul-moore.com

2018-10-19 21:51:49

by Richard Guy Briggs

[permalink] [raw]
Subject: Re: [PATCH ghak90 (was ghak32) V4 02/10] audit: add container id

On 2018-10-19 15:38, Paul Moore wrote:
> On Tue, Jul 31, 2018 at 4:11 PM Richard Guy Briggs <[email protected]> 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_ID msg=audit(2018-06-06 12:39:29.636:26949) : op=set opid=2209 old-contid=18446744073709551615 contid=123456 pid=628 auid=root uid=root tty=ttyS0 ses=1 subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 comm=bash exe=/usr/bin/bash res=yes
>
> You need to update the record type in the example above.

Yup, thanks.

> > 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.
>
> I understand Steve's concern around the "op" field, but I think it
> might be a bit premature to think we might not need to do some sort of
> audit container ID management in the future that would want to make
> use of the CONTAINER_OP message type. I would like to see the "op"
> field preserved.

I strongly agree.

> > 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 <[email protected]>
> > Acked-by: Serge Hallyn <[email protected]>
> > Acked-by: Steve Grubb <[email protected]>
> > ---
> > fs/proc/base.c | 37 +++++++++++++++++++++++++
> > include/linux/audit.h | 24 ++++++++++++++++
> > include/uapi/linux/audit.h | 2 ++
> > kernel/auditsc.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++
> > 4 files changed, 131 insertions(+)
>
> ...
>
> > @@ -2112,6 +2114,72 @@ int audit_set_loginuid(kuid_t loginuid)
> > }
> >
> > /**
> > + * audit_set_contid - set current task's audit_context 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);
>
> I assume lockdep was happy with nesting the tasklist_lock inside the task lock?

Yup, I had gone through the logic and at first I had doubts, but the
function comments and other usage reassured me (as well as in-kernel
lock checks on boot) that this was the right order and approach.

> > + /* 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(current);
> > + 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;
> > +}
>
> --
> paul moore
> http://www.paul-moore.com

- RGB

--
Richard Guy Briggs <[email protected]>
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

2018-10-19 23:16:58

by Paul Moore

[permalink] [raw]
Subject: Re: [PATCH ghak90 (was ghak32) V4 01/10] audit: collect audit task parameters

On Sun, Aug 5, 2018 at 4:32 AM Richard Guy Briggs <[email protected]> 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.
>
> See: https://github.com/linux-audit/audit-kernel/issues/81
>
> Signed-off-by: Richard Guy Briggs <[email protected]>
> ---
> include/linux/audit.h | 34 ++++++++++++++++++++++++----------
> include/linux/sched.h | 5 +----
> init/init_task.c | 3 +--
> init/main.c | 2 ++
> kernel/auditsc.c | 51 ++++++++++++++++++++++++++++++++++++++++++---------
> kernel/fork.c | 4 +++-
> 6 files changed, 73 insertions(+), 26 deletions(-)

...

> diff --git a/include/linux/audit.h b/include/linux/audit.h
> index 9334fbe..8964332 100644
> --- a/include/linux/audit.h
> +++ b/include/linux/audit.h
> @@ -219,8 +219,15 @@ static inline void audit_log_task_info(struct audit_buffer *ab,
>
> /* These are defined in auditsc.c */
> /* Public API */
> +struct audit_task_info {
> + kuid_t loginuid;
> + unsigned int sessionid;
> + struct audit_context *ctx;
> +};

...

> diff --git a/include/linux/sched.h b/include/linux/sched.h
> index 87bf02d..e117272 100644
> --- a/include/linux/sched.h
> +++ b/include/linux/sched.h
> @@ -873,10 +872,8 @@ struct task_struct {
>
> struct callback_head *task_works;
>
> - struct audit_context *audit_context;
> #ifdef CONFIG_AUDITSYSCALL
> - kuid_t loginuid;
> - unsigned int sessionid;
> + struct audit_task_info *audit;
> #endif
> struct seccomp seccomp;

Prior to this patch audit_context was available regardless of
CONFIG_AUDITSYSCALL, after this patch the corresponding audit_context
is only available when CONFIG_AUDITSYSCALL is defined.

> diff --git a/init/main.c b/init/main.c
> index 3b4ada1..6aba171 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>
> @@ -721,6 +722,7 @@ asmlinkage __visible void __init start_kernel(void)
> nsfs_init();
> cpuset_init();
> cgroup_init();
> + audit_task_init();
> taskstats_init_early();
> delayacct_init();

It seems like we would need either init_struct_audit or
audit_task_init(), but not both, yes?

> diff --git a/kernel/auditsc.c b/kernel/auditsc.c
> index fb20746..88779a7 100644
> --- a/kernel/auditsc.c
> +++ b/kernel/auditsc.c
> @@ -841,7 +841,7 @@ static inline struct audit_context *audit_take_context(struct task_struct *tsk,
> int return_valid,
> long return_code)
> {
> - struct audit_context *context = tsk->audit_context;
> + struct audit_context *context = tsk->audit->ctx;
>
> if (!context)
> return NULL;
> @@ -926,6 +926,15 @@ static inline struct audit_context *audit_alloc_context(enum audit_state state)
> return context;
> }
>
> +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);
> +}

This is somewhat related to the CONFIG_AUDITSYSCALL comment above, but
since the audit_task_info contains generic audit state (not just
syscall related state), it seems like this, and the audit_task_info
accessors/helpers, should live in kernel/audit.c.

There are probably a few other things that should move to
kernel/audit.c too, e.g. audit_alloc(). Have you verified that this
builds/runs correctly on architectures that define CONFIG_AUDIT but
not CONFIG_AUDITSYSCALL?

> /**
> * audit_alloc - allocate an audit context block for a task
> * @tsk: task
> @@ -940,17 +949,28 @@ int audit_alloc(struct task_struct *tsk)
> struct audit_context *context;
> enum audit_state state;
> char *key = NULL;
> + struct audit_task_info *info;
> +
> + info = kmem_cache_zalloc(audit_task_cache, GFP_KERNEL);
> + if (!info)
> + return -ENOMEM;
> + info->loginuid = audit_get_loginuid(current);
> + info->sessionid = audit_get_sessionid(current);
> + tsk->audit = info;
>
> if (likely(!audit_ever_enabled))
> return 0; /* Return if not auditing. */

I don't view this as necessary for initial acceptance, and
synchronization/locking might render this undesirable, but it would be
curious to see if we could do something clever with refcnts and
copy-on-write to minimize the number of kmem_cache objects in use in
the !audit_ever_enabled (and possibly the AUDIT_DISABLED) case.

> state = audit_filter_task(tsk, &key);
> if (state == AUDIT_DISABLED) {
> + audit_set_context(tsk, NULL);

It's already NULL, isn't it?

> clear_tsk_thread_flag(tsk, TIF_SYSCALL_AUDIT);
> return 0;
> }
>
> if (!(context = audit_alloc_context(state))) {
> + tsk->audit = NULL;
> + kmem_cache_free(audit_task_cache, info);
> kfree(key);
> audit_log_lost("out of memory in audit_alloc");
> return -ENOMEM;
> @@ -962,6 +982,12 @@ int audit_alloc(struct task_struct *tsk)
> return 0;
> }
>
> +struct audit_task_info init_struct_audit = {
> + .loginuid = INVALID_UID,
> + .sessionid = AUDIT_SID_UNSET,
> + .ctx = NULL,
> +};
> +
> static inline void audit_free_context(struct audit_context *context)
> {
> audit_free_names(context);

--
paul moore
http://www.paul-moore.com

2018-10-19 23:17:46

by Paul Moore

[permalink] [raw]
Subject: Re: [PATCH ghak90 (was ghak32) V4 03/10] audit: log container info of syscalls

On Sun, Aug 5, 2018 at 4:32 AM Richard Guy Briggs <[email protected]> wrote:
> Create a new audit record AUDIT_CONTAINER 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=0000000000000000 cap_fi=0000000000000000 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=0000000000000000 cap_fi=0000000000000000 cap_fe=0 cap_fver=0
> type=PROCTITLE msg=audit(1519924845.499:257): proctitle=62617368002D6300736C65657020313B206563686F2074657374203E202F746D702F746D70636F6E7461696E65726964
> type=CONTAINER msg=audit(1519924845.499:257): op=task 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 <[email protected]>
> Acked-by: Serge Hallyn <[email protected]>
> Acked-by: Steve Grubb <[email protected]>
> ---
> include/linux/audit.h | 7 +++++++
> include/uapi/linux/audit.h | 1 +
> kernel/audit.c | 24 ++++++++++++++++++++++++
> kernel/auditsc.c | 3 +++
> 4 files changed, 35 insertions(+)

...

> @@ -2045,6 +2045,30 @@ 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
> + * @tsk: task to be recorded
> + * @context: task or local context for record
> + * @op: contid string description
> + */
> +int audit_log_contid(struct task_struct *tsk,
> + struct audit_context *context, char *op)
> +{
> + struct audit_buffer *ab;
> +
> + if (!audit_contid_set(tsk))
> + return 0;
> + /* Generate AUDIT_CONTAINER record with container ID */
> + ab = audit_log_start(context, GFP_KERNEL, AUDIT_CONTAINER);
> + if (!ab)
> + return -ENOMEM;
> + audit_log_format(ab, "op=%s contid=%llu",
> + op, audit_get_contid(tsk));
> + audit_log_end(ab);
> + return 0;
> +}
> +EXPORT_SYMBOL(audit_log_contid);

As discussed in the previous iteration of the patch, I prefer
AUDIT_CONTAINER_ID here over AUDIT_CONTAINER. If you feel strongly
about keeping it as-is with AUDIT_CONTAINER I suppose I could live
with that, but it is isn't my first choice.

However, I do care about the "op" field in this record. It just
doesn't make any sense; the way you are using it it is more of a
context field than an operations field, and even then why is the
context important from a logging and/or security perspective? Drop it
please.

--
paul moore
http://www.paul-moore.com

2018-10-19 23:18:10

by Paul Moore

[permalink] [raw]
Subject: Re: [PATCH ghak90 (was ghak32) V4 04/10] audit: add containerid support for ptrace and signals

On Tue, Jul 31, 2018 at 4:11 PM Richard Guy Briggs <[email protected]> wrote:
> Add audit container identifier support to ptrace and signals. In
> particular, the "op" field provides a way to label the auxiliary record
> to which it is associated.
>
> Signed-off-by: Richard Guy Briggs <[email protected]>
> Acked-by: Serge Hallyn <[email protected]>
> ---
> include/linux/audit.h | 11 +++++------
> kernel/audit.c | 13 +++++++------
> kernel/audit.h | 2 ++
> kernel/auditsc.c | 21 ++++++++++++++++-----
> 4 files changed, 30 insertions(+), 17 deletions(-)

...

> @@ -155,9 +156,8 @@ extern void audit_log_key(struct audit_buffer *ab,
> extern int audit_log_task_context(struct audit_buffer *ab);
> extern void audit_log_task_info(struct audit_buffer *ab,
> struct task_struct *tsk);
> -extern int audit_log_contid(struct task_struct *tsk,
> - struct audit_context *context,
> - char *op);
> +extern int audit_log_contid(struct audit_context *context,
> + char *op, u64 contid);
>
> extern int audit_update_lsm_rules(void);

...

> @@ -2047,23 +2049,22 @@ void audit_log_session_info(struct audit_buffer *ab)
>
> /*
> * audit_log_contid - report container info
> - * @tsk: task to be recorded
> * @context: task or local context for record
> * @op: contid string description
> + * @contid: container ID to report
> */
> -int audit_log_contid(struct task_struct *tsk,
> - struct audit_context *context, char *op)
> +int audit_log_contid(struct audit_context *context,
> + char *op, u64 contid)
> {
> struct audit_buffer *ab;
>
> - if (!audit_contid_set(tsk))
> + if (!audit_contid_valid(contid))
> return 0;
> /* Generate AUDIT_CONTAINER record with container ID */
> ab = audit_log_start(context, GFP_KERNEL, AUDIT_CONTAINER);
> if (!ab)
> return -ENOMEM;
> - audit_log_format(ab, "op=%s contid=%llu",
> - op, audit_get_contid(tsk));
> + audit_log_format(ab, "op=%s contid=%llu", op, contid);
> audit_log_end(ab);
> return 0;
> }

My previous comments still apply: these audit_log_contid() changes
should be done earlier in the patchset when you first define
audit_log_contid().

--
paul moore
http://www.paul-moore.com

2018-10-19 23:18:35

by Paul Moore

[permalink] [raw]
Subject: Re: [PATCH ghak90 (was ghak32) V4 05/10] audit: add support for non-syscall auxiliary records

On Sun, Aug 5, 2018 at 4:33 AM Richard Guy Briggs <[email protected]> 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 <[email protected]>
> Acked-by: Serge Hallyn <[email protected]>
> ---
> include/linux/audit.h | 8 ++++++++
> kernel/audit.h | 1 +
> kernel/auditsc.c | 33 ++++++++++++++++++++++++++++-----
> 3 files changed, 37 insertions(+), 5 deletions(-)

I'm not in love with the local flag, and the whole local context in
general, but that's a larger discussion and not something I want to
force on this patchset; we can fix it later.

I think this patch looks fine, but it seems a bit odd standalone; it's
almost always better to include new capabilities/functions in the same
patch as the user. Since the only user is the networking bits, it
might make more sense to fold this patch into that one.

> diff --git a/include/linux/audit.h b/include/linux/audit.h
> index 4f514ed..1f340ad 100644
> --- a/include/linux/audit.h
> +++ b/include/linux/audit.h
> @@ -234,7 +234,9 @@ struct audit_task_info {
> extern struct audit_task_info init_struct_audit;
> extern void __init audit_task_init(void);
> extern int audit_alloc(struct task_struct *task);
> +extern struct audit_context *audit_alloc_local(gfp_t gfpflags);
> extern void audit_free(struct task_struct *task);
> +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);
> @@ -495,6 +497,12 @@ static inline int audit_alloc(struct task_struct *task)
> {
> return 0;
> }
> +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_free(struct task_struct *task)
> { }
> static inline void audit_syscall_entry(int major, unsigned long a0,
> diff --git a/kernel/audit.h b/kernel/audit.h
> index 1cf1c35..a6d00a5 100644
> --- a/kernel/audit.h
> +++ b/kernel/audit.h
> @@ -110,6 +110,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 cdb24cf..7627f21 100644
> --- a/kernel/auditsc.c
> +++ b/kernel/auditsc.c
> @@ -913,11 +913,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;
> @@ -970,7 +972,8 @@ int audit_alloc(struct task_struct *tsk)
> return 0;
> }
>
> - if (!(context = audit_alloc_context(state))) {
> + context = audit_alloc_context(state, GFP_KERNEL);
> + if (!(context)) {
> tsk->audit = NULL;
> kmem_cache_free(audit_task_cache, info);
> kfree(key);
> @@ -991,8 +994,27 @@ struct audit_task_info init_struct_audit = {
> .ctx = NULL,
> };
>
> -static inline void audit_free_context(struct audit_context *context)
> +struct audit_context *audit_alloc_local(gfp_t gfpflags)
> {
> + struct audit_context *context;
> +
> + if (!audit_ever_enabled)
> + return NULL; /* Return if not auditing. */
> +
> + context = audit_alloc_context(AUDIT_RECORD_CONTEXT, gfpflags);
> + if (!context)
> + return NULL;
> + context->serial = audit_serial();
> + context->ctime = current_kernel_time64();
> + context->local = true;
> + 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);
> @@ -1002,6 +1024,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,
> @@ -2024,7 +2047,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();

--
paul moore
http://www.paul-moore.com

2018-10-19 23:20:18

by Paul Moore

[permalink] [raw]
Subject: Re: [PATCH ghak90 (was ghak32) V4 06/10] audit: add containerid support for tty_audit

On Sun, Aug 5, 2018 at 4:33 AM Richard Guy Briggs <[email protected]> wrote:
> Add audit container identifier auxiliary record to tty logging rule
> event standalone records.
>
> Signed-off-by: Richard Guy Briggs <[email protected]>
> Acked-by: Serge Hallyn <[email protected]>
> ---
> drivers/tty/tty_audit.c | 5 ++++-
> 1 file changed, 4 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/tty/tty_audit.c b/drivers/tty/tty_audit.c
> index 50f567b..3e21477 100644
> --- a/drivers/tty/tty_audit.c
> +++ b/drivers/tty/tty_audit.c
> @@ -66,8 +66,9 @@ static void tty_audit_log(const char *description, dev_t dev,
> uid_t uid = from_kuid(&init_user_ns, task_uid(tsk));
> uid_t loginuid = from_kuid(&init_user_ns, audit_get_loginuid(tsk));
> unsigned int sessionid = audit_get_sessionid(tsk);
> + struct audit_context *context = audit_alloc_local(GFP_KERNEL);
>
> - ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_TTY);
> + ab = audit_log_start(context, GFP_KERNEL, AUDIT_TTY);
> if (ab) {
> char name[sizeof(tsk->comm)];
>
> @@ -80,6 +81,8 @@ static void tty_audit_log(const char *description, dev_t dev,
> audit_log_n_hex(ab, data, size);
> audit_log_end(ab);
> }
> + audit_log_contid(context, "tty", audit_get_contid(tsk));
> + audit_free_context(context);
> }

Since I never polished up my task_struct/current fix patch enough to
get it past RFC status during this development window (new job, stolen
laptop, etc.) *and* it looks like you are going to need at least one
more respin of this patchset, go ahead and fix this patch to use
current instead of generating a local context. I'll deal with the
merge fallout if/when it happens.

Local contexts are a last resort. If you ever find yourself writing
code that generates a local context, you should first be 100% certain
that the event is not the the result of a process initiated action (in
which case it should take from the task's context).

--
paul moore
http://www.paul-moore.com

2018-10-19 23:20:31

by Paul Moore

[permalink] [raw]
Subject: Re: [PATCH ghak90 (was ghak32) V4 09/10] audit: NETFILTER_PKT: record each container ID associated with a netNS

On Sun, Aug 5, 2018 at 4:33 AM Richard Guy Briggs <[email protected]> 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 <[email protected]>
> ---
> include/linux/audit.h | 5 +++++
> kernel/audit.c | 26 ++++++++++++++++++++++++++
> net/netfilter/xt_AUDIT.c | 12 ++++++++++--
> 3 files changed, 41 insertions(+), 2 deletions(-)

...

> diff --git a/include/linux/audit.h b/include/linux/audit.h
> index 9a02095..8755f4d 100644
> --- a/include/linux/audit.h
> +++ b/include/linux/audit.h
> @@ -169,6 +169,8 @@ extern int audit_log_contid(struct audit_context *context,
> 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 void audit_log_netns_contid_list(struct net *net,
> + struct audit_context *context);
>
> extern int audit_update_lsm_rules(void);
>
> @@ -228,6 +230,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 c5fed3b..b23711c 100644
> --- a/kernel/audit.c
> +++ b/kernel/audit.c
> @@ -392,6 +392,32 @@ void audit_switch_task_namespaces(struct nsproxy *ns, struct task_struct *p)
> audit_netns_contid_add(new->net_ns, contid);
> }
>
> +void audit_log_netns_contid_list(struct net *net, struct audit_context *context)
> +{
> + spinlock_t *lock = audit_get_netns_contid_list_lock(net);
> + struct audit_buffer *ab;
> + struct audit_contid *cont;
> + bool first = true;
> +
> + /* Generate AUDIT_CONTAINER record with container ID CSV list */
> + ab = audit_log_start(context, GFP_ATOMIC, AUDIT_CONTAINER);
> + if (!ab) {
> + audit_log_lost("out of memory in audit_log_netns_contid_list");
> + return;
> + }
> + audit_log_format(ab, "contid=");
> + spin_lock(lock);
> + list_for_each_entry(cont, audit_get_netns_contid_list(net), list) {
> + if (!first)
> + audit_log_format(ab, ",");
> + audit_log_format(ab, "%llu", cont->id);
> + first = false;
> + }
> + spin_unlock(lock);

This is looking like potentially a lot of work to be doing under a
spinlock, not to mention a single spinlock that is shared across CPUs.
Considering that I expect changes to the list to be somewhat
infrequent, this might be a good candidate for a RCU based locking
scheme.

> + audit_log_end(ab);
> +}
> +EXPORT_SYMBOL(audit_log_netns_contid_list);
>
> void audit_panic(const char *message)
> {
> switch (audit_failure) {
> diff --git a/net/netfilter/xt_AUDIT.c b/net/netfilter/xt_AUDIT.c
> index af883f1..44fac3f 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,12 @@ 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;
> }
>

--
paul moore
http://www.paul-moore.com

2018-10-19 23:20:49

by Paul Moore

[permalink] [raw]
Subject: Re: [PATCH ghak90 (was ghak32) V4 08/10] audit: add support for containerid to network namespaces

On Tue, Jul 31, 2018 at 4:12 PM Richard Guy Briggs <[email protected]> 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 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 <[email protected]>
> ---
> include/linux/audit.h | 17 ++++++++++
> kernel/audit.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++
> kernel/auditsc.c | 8 ++++-
> kernel/nsproxy.c | 4 +++
> 4 files changed, 114 insertions(+), 1 deletion(-)

...

> @@ -308,6 +312,86 @@ static struct sock *audit_get_sk(const struct net *net)
> return aunet->sk;
> }
>
> +/**
> + * audit_get_netns_contid_list - Return the audit container ID list for the given network namespace
> + * @net: the destination network namespace
> + *
> + * Description:
> + * Returns the list pointer if valid, NULL otherwise. The caller must ensure
> + * that a reference is held for the network namespace while the sock is in use.
> + */
> +struct list_head *audit_get_netns_contid_list(const struct net *net)
> +{
> + struct audit_net *aunet = net_generic(net, audit_net_id);
> +
> + return &aunet->contid_list;
> +}
> +
> +spinlock_t *audit_get_netns_contid_list_lock(const struct net *net)
> +{
> + struct audit_net *aunet = net_generic(net, audit_net_id);
> +
> + return &aunet->contid_list_lock;
> +}

Instead of returning the spinlock, just do away with the
audit_get_ns_contid_list_lock() function and create two separate lock
and unlock functions that basically do the net_generic() and spinlock
operations together, for example:

static int audit_netns_contid_lock(const struct net *net)
{
aunet = net_generic(net, audit_net_id);

if (!aunet)
return -whatever;

spin_lock(aunet->lock);
return 0;
}

> +void audit_netns_contid_add(struct net *net, u64 contid)
> +{
> + spinlock_t *lock = audit_get_netns_contid_list_lock(net);
> + struct list_head *contid_list = audit_get_netns_contid_list(net);
> + struct audit_contid *cont;
> +
> + if (!audit_contid_valid(contid))
> + return;
> + spin_lock(lock);
> + if (!list_empty(contid_list))
> + list_for_each_entry(cont, contid_list, list)
> + if (cont->id == contid) {
> + refcount_inc(&cont->refcount);
> + goto out;
> + }
> + cont = kmalloc(sizeof(struct audit_contid), GFP_KERNEL);
> + if (cont) {
> + INIT_LIST_HEAD(&cont->list);
> + cont->id = contid;
> + refcount_set(&cont->refcount, 1);
> + list_add(&cont->list, contid_list);
> + }
> +out:
> + spin_unlock(lock);
> +}
> +
> +void audit_netns_contid_del(struct net *net, u64 contid)
> +{
> + spinlock_t *lock = audit_get_netns_contid_list_lock(net);
> + struct list_head *contid_list = audit_get_netns_contid_list(net);
> + struct audit_contid *cont = NULL;
> +
> + if (!audit_contid_valid(contid))
> + return;
> + spin_lock(lock);
> + if (!list_empty(contid_list))
> + list_for_each_entry(cont, contid_list, list)
> + if (cont->id == contid) {
> + list_del(&cont->list);
> + if (refcount_dec_and_test(&cont->refcount))
> + kfree(cont);
> + break;
> + }
> + spin_unlock(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) {
> @@ -1547,6 +1631,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;
> }
> diff --git a/kernel/auditsc.c b/kernel/auditsc.c
> index 610c6869..fdf3f68 100644
> --- a/kernel/auditsc.c
> +++ b/kernel/auditsc.c
> @@ -75,6 +75,7 @@
> #include <linux/uaccess.h>
> #include <linux/fsnotify_backend.h>
> #include <uapi/linux/limits.h>
> +#include <net/net_namespace.h>
>
> #include "audit.h"
>
> @@ -2165,6 +2166,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 */
> @@ -2186,8 +2188,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 f6c5d33..718b120 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);

--
paul moore
http://www.paul-moore.com

2018-10-24 15:18:44

by Richard Guy Briggs

[permalink] [raw]
Subject: Re: [PATCH ghak90 (was ghak32) V4 03/10] audit: log container info of syscalls

On 2018-10-19 19:16, Paul Moore wrote:
> On Sun, Aug 5, 2018 at 4:32 AM Richard Guy Briggs <[email protected]> wrote:
> > Create a new audit record AUDIT_CONTAINER 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=0000000000000000 cap_fi=0000000000000000 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=0000000000000000 cap_fi=0000000000000000 cap_fe=0 cap_fver=0
> > type=PROCTITLE msg=audit(1519924845.499:257): proctitle=62617368002D6300736C65657020313B206563686F2074657374203E202F746D702F746D70636F6E7461696E65726964
> > type=CONTAINER msg=audit(1519924845.499:257): op=task 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 <[email protected]>
> > Acked-by: Serge Hallyn <[email protected]>
> > Acked-by: Steve Grubb <[email protected]>
> > ---
> > include/linux/audit.h | 7 +++++++
> > include/uapi/linux/audit.h | 1 +
> > kernel/audit.c | 24 ++++++++++++++++++++++++
> > kernel/auditsc.c | 3 +++
> > 4 files changed, 35 insertions(+)
>
> ...
>
> > @@ -2045,6 +2045,30 @@ 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
> > + * @tsk: task to be recorded
> > + * @context: task or local context for record
> > + * @op: contid string description
> > + */
> > +int audit_log_contid(struct task_struct *tsk,
> > + struct audit_context *context, char *op)
> > +{
> > + struct audit_buffer *ab;
> > +
> > + if (!audit_contid_set(tsk))
> > + return 0;
> > + /* Generate AUDIT_CONTAINER record with container ID */
> > + ab = audit_log_start(context, GFP_KERNEL, AUDIT_CONTAINER);
> > + if (!ab)
> > + return -ENOMEM;
> > + audit_log_format(ab, "op=%s contid=%llu",
> > + op, audit_get_contid(tsk));
> > + audit_log_end(ab);
> > + return 0;
> > +}
> > +EXPORT_SYMBOL(audit_log_contid);
>
> As discussed in the previous iteration of the patch, I prefer
> AUDIT_CONTAINER_ID here over AUDIT_CONTAINER. If you feel strongly
> about keeping it as-is with AUDIT_CONTAINER I suppose I could live
> with that, but it is isn't my first choice.

I don't have a strong opinion on this one, mildly preferring the shorter
one only because it is shorter.

Steve? Can you comment on this one way or the other?

> However, I do care about the "op" field in this record. It just
> doesn't make any sense; the way you are using it it is more of a
> context field than an operations field, and even then why is the
> context important from a logging and/or security perspective? Drop it
> please.

I'll rename it to whatever you like. I'd suggest "ref=". The reason I
think it is important is there are multiple sources that aren't always
obvious from the other records to which it is associated. In the case
of ptrace and signals, there can be many target tasks listed (OBJ_PID)
with no other way to distinguish the matching audit container identifier
records all for one event. This is in addition to the default syscall
container identifier record. I'm not currently happy with the text
content to link the two, but that should be solvable (most obvious is
taret PID). Throwing away this information seems shortsighted.

> paul moore

- RGB

--
Richard Guy Briggs <[email protected]>
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

2018-10-24 20:56:34

by Paul Moore

[permalink] [raw]
Subject: Re: [PATCH ghak90 (was ghak32) V4 03/10] audit: log container info of syscalls

On Wed, Oct 24, 2018 at 11:15 AM Richard Guy Briggs <[email protected]> wrote:
> On 2018-10-19 19:16, Paul Moore wrote:
> > On Sun, Aug 5, 2018 at 4:32 AM Richard Guy Briggs <[email protected]> wrote:
> > > Create a new audit record AUDIT_CONTAINER 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=0000000000000000 cap_fi=0000000000000000 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=0000000000000000 cap_fi=0000000000000000 cap_fe=0 cap_fver=0
> > > type=PROCTITLE msg=audit(1519924845.499:257): proctitle=62617368002D6300736C65657020313B206563686F2074657374203E202F746D702F746D70636F6E7461696E65726964
> > > type=CONTAINER msg=audit(1519924845.499:257): op=task 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 <[email protected]>
> > > Acked-by: Serge Hallyn <[email protected]>
> > > Acked-by: Steve Grubb <[email protected]>
> > > ---
> > > include/linux/audit.h | 7 +++++++
> > > include/uapi/linux/audit.h | 1 +
> > > kernel/audit.c | 24 ++++++++++++++++++++++++
> > > kernel/auditsc.c | 3 +++
> > > 4 files changed, 35 insertions(+)
> >
> > ...
> >
> > > @@ -2045,6 +2045,30 @@ 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
> > > + * @tsk: task to be recorded
> > > + * @context: task or local context for record
> > > + * @op: contid string description
> > > + */
> > > +int audit_log_contid(struct task_struct *tsk,
> > > + struct audit_context *context, char *op)
> > > +{
> > > + struct audit_buffer *ab;
> > > +
> > > + if (!audit_contid_set(tsk))
> > > + return 0;
> > > + /* Generate AUDIT_CONTAINER record with container ID */
> > > + ab = audit_log_start(context, GFP_KERNEL, AUDIT_CONTAINER);
> > > + if (!ab)
> > > + return -ENOMEM;
> > > + audit_log_format(ab, "op=%s contid=%llu",
> > > + op, audit_get_contid(tsk));
> > > + audit_log_end(ab);
> > > + return 0;
> > > +}
> > > +EXPORT_SYMBOL(audit_log_contid);
> >
> > As discussed in the previous iteration of the patch, I prefer
> > AUDIT_CONTAINER_ID here over AUDIT_CONTAINER. If you feel strongly
> > about keeping it as-is with AUDIT_CONTAINER I suppose I could live
> > with that, but it is isn't my first choice.
>
> I don't have a strong opinion on this one, mildly preferring the shorter
> one only because it is shorter.

We already have multiple AUDIT_CONTAINER* record types, so it seems as
though we should use "AUDIT_CONTAINER" as a prefix of sorts, rather
than a type itself.

> > However, I do care about the "op" field in this record. It just
> > doesn't make any sense; the way you are using it it is more of a
> > context field than an operations field, and even then why is the
> > context important from a logging and/or security perspective? Drop it
> > please.
>
> I'll rename it to whatever you like. I'd suggest "ref=". The reason I
> think it is important is there are multiple sources that aren't always
> obvious from the other records to which it is associated. In the case
> of ptrace and signals, there can be many target tasks listed (OBJ_PID)
> with no other way to distinguish the matching audit container identifier
> records all for one event. This is in addition to the default syscall
> container identifier record. I'm not currently happy with the text
> content to link the two, but that should be solvable (most obvious is
> taret PID). Throwing away this information seems shortsighted.

It would be helpful if you could generate real audit events
demonstrating the problems you are describing, as well as a more
standard syscall event, so we can discuss some possible solutions.

--
paul moore
http://www.paul-moore.com

2018-10-25 00:45:14

by Richard Guy Briggs

[permalink] [raw]
Subject: Re: [PATCH ghak90 (was ghak32) V4 03/10] audit: log container info of syscalls

On 2018-10-24 16:55, Paul Moore wrote:
> On Wed, Oct 24, 2018 at 11:15 AM Richard Guy Briggs <[email protected]> wrote:
> > On 2018-10-19 19:16, Paul Moore wrote:
> > > On Sun, Aug 5, 2018 at 4:32 AM Richard Guy Briggs <[email protected]> wrote:
> > > > Create a new audit record AUDIT_CONTAINER 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=0000000000000000 cap_fi=0000000000000000 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=0000000000000000 cap_fi=0000000000000000 cap_fe=0 cap_fver=0
> > > > type=PROCTITLE msg=audit(1519924845.499:257): proctitle=62617368002D6300736C65657020313B206563686F2074657374203E202F746D702F746D70636F6E7461696E65726964
> > > > type=CONTAINER msg=audit(1519924845.499:257): op=task 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 <[email protected]>
> > > > Acked-by: Serge Hallyn <[email protected]>
> > > > Acked-by: Steve Grubb <[email protected]>
> > > > ---
> > > > include/linux/audit.h | 7 +++++++
> > > > include/uapi/linux/audit.h | 1 +
> > > > kernel/audit.c | 24 ++++++++++++++++++++++++
> > > > kernel/auditsc.c | 3 +++
> > > > 4 files changed, 35 insertions(+)
> > >
> > > ...
> > >
> > > > @@ -2045,6 +2045,30 @@ 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
> > > > + * @tsk: task to be recorded
> > > > + * @context: task or local context for record
> > > > + * @op: contid string description
> > > > + */
> > > > +int audit_log_contid(struct task_struct *tsk,
> > > > + struct audit_context *context, char *op)
> > > > +{
> > > > + struct audit_buffer *ab;
> > > > +
> > > > + if (!audit_contid_set(tsk))
> > > > + return 0;
> > > > + /* Generate AUDIT_CONTAINER record with container ID */
> > > > + ab = audit_log_start(context, GFP_KERNEL, AUDIT_CONTAINER);
> > > > + if (!ab)
> > > > + return -ENOMEM;
> > > > + audit_log_format(ab, "op=%s contid=%llu",
> > > > + op, audit_get_contid(tsk));
> > > > + audit_log_end(ab);
> > > > + return 0;
> > > > +}
> > > > +EXPORT_SYMBOL(audit_log_contid);
> > >
> > > As discussed in the previous iteration of the patch, I prefer
> > > AUDIT_CONTAINER_ID here over AUDIT_CONTAINER. If you feel strongly
> > > about keeping it as-is with AUDIT_CONTAINER I suppose I could live
> > > with that, but it is isn't my first choice.
> >
> > I don't have a strong opinion on this one, mildly preferring the shorter
> > one only because it is shorter.
>
> We already have multiple AUDIT_CONTAINER* record types, so it seems as
> though we should use "AUDIT_CONTAINER" as a prefix of sorts, rather
> than a type itself.

I'm fine with that. I'd still like to hear Steve's input. He had
stronger opinions than me.

> > > However, I do care about the "op" field in this record. It just
> > > doesn't make any sense; the way you are using it it is more of a
> > > context field than an operations field, and even then why is the
> > > context important from a logging and/or security perspective? Drop it
> > > please.
> >
> > I'll rename it to whatever you like. I'd suggest "ref=". The reason I
> > think it is important is there are multiple sources that aren't always
> > obvious from the other records to which it is associated. In the case
> > of ptrace and signals, there can be many target tasks listed (OBJ_PID)
> > with no other way to distinguish the matching audit container identifier
> > records all for one event. This is in addition to the default syscall
> > container identifier record. I'm not currently happy with the text
> > content to link the two, but that should be solvable (most obvious is
> > taret PID). Throwing away this information seems shortsighted.
>
> It would be helpful if you could generate real audit events
> demonstrating the problems you are describing, as well as a more
> standard syscall event, so we can discuss some possible solutions.

If the auditted process is in a container and it ptraces or signals
another process in a container, there will be two AUDIT_CONTAINER
records for the same event that won't be identified as to which record
belongs to which process or other record (SYSCALL vs 1+ OBJ_PID
records). There could be many signals recorded, each with their own
OBJ_PID record. The first is stored in the audit context and additional
ones are stored in a chained struct that can accommodate 16 entries each.

(See audit_signal_info(), __audit_ptrace().)

(As a side note, on code inspection it appears that a signal target
would get overwritten by a ptrace action if they were to happen in that
order.)

> paul moore

- RGB

--
Richard Guy Briggs <[email protected]>
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

2018-10-25 06:07:31

by Steve Grubb

[permalink] [raw]
Subject: Re: [PATCH ghak90 (was ghak32) V4 03/10] audit: log container info of syscalls

On Wed, 24 Oct 2018 20:42:55 -0400
Richard Guy Briggs <[email protected]> wrote:

> On 2018-10-24 16:55, Paul Moore wrote:
> > On Wed, Oct 24, 2018 at 11:15 AM Richard Guy Briggs
> > <[email protected]> wrote:
> > > On 2018-10-19 19:16, Paul Moore wrote:
> > > > On Sun, Aug 5, 2018 at 4:32 AM Richard Guy Briggs
> > > > <[email protected]> wrote:
> > > > > Create a new audit record AUDIT_CONTAINER 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=0000000000000000 cap_fi=0000000000000000 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=0000000000000000 cap_fi=0000000000000000 cap_fe=0
> > > > > cap_fver=0 type=PROCTITLE msg=audit(1519924845.499:257):
> > > > > proctitle=62617368002D6300736C65657020313B206563686F2074657374203E202F746D702F746D70636F6E7461696E65726964
> > > > > type=CONTAINER msg=audit(1519924845.499:257): op=task
> > > > > 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 <[email protected]> Acked-by:
> > > > > Serge Hallyn <[email protected]> Acked-by: Steve Grubb
> > > > > <[email protected]> ---
> > > > > include/linux/audit.h | 7 +++++++
> > > > > include/uapi/linux/audit.h | 1 +
> > > > > kernel/audit.c | 24 ++++++++++++++++++++++++
> > > > > kernel/auditsc.c | 3 +++
> > > > > 4 files changed, 35 insertions(+)
> > > >
> > > > ...
> > > >
> > > > > @@ -2045,6 +2045,30 @@ 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
> > > > > + * @tsk: task to be recorded
> > > > > + * @context: task or local context for record
> > > > > + * @op: contid string description
> > > > > + */
> > > > > +int audit_log_contid(struct task_struct *tsk,
> > > > > + struct audit_context *context,
> > > > > char *op) +{
> > > > > + struct audit_buffer *ab;
> > > > > +
> > > > > + if (!audit_contid_set(tsk))
> > > > > + return 0;
> > > > > + /* Generate AUDIT_CONTAINER record with container ID
> > > > > */
> > > > > + ab = audit_log_start(context, GFP_KERNEL,
> > > > > AUDIT_CONTAINER);
> > > > > + if (!ab)
> > > > > + return -ENOMEM;
> > > > > + audit_log_format(ab, "op=%s contid=%llu",
> > > > > + op, audit_get_contid(tsk));
> > > > > + audit_log_end(ab);
> > > > > + return 0;
> > > > > +}
> > > > > +EXPORT_SYMBOL(audit_log_contid);
> > > >
> > > > As discussed in the previous iteration of the patch, I prefer
> > > > AUDIT_CONTAINER_ID here over AUDIT_CONTAINER. If you feel
> > > > strongly about keeping it as-is with AUDIT_CONTAINER I suppose
> > > > I could live with that, but it is isn't my first choice.
> > >
> > > I don't have a strong opinion on this one, mildly preferring the
> > > shorter one only because it is shorter.
> >
> > We already have multiple AUDIT_CONTAINER* record types, so it seems
> > as though we should use "AUDIT_CONTAINER" as a prefix of sorts,
> > rather than a type itself.
>
> I'm fine with that. I'd still like to hear Steve's input. He had
> stronger opinions than me.

The creation event should be separate and distinct from the continuing
use when its used as a supplemental record. IOW, binding the ID to a
container is part of the lifecycle and needs to be kept distinct.

-Steve

> > > > However, I do care about the "op" field in this record. It just
> > > > doesn't make any sense; the way you are using it it is more of a
> > > > context field than an operations field, and even then why is the
> > > > context important from a logging and/or security perspective?
> > > > Drop it please.
> > >
> > > I'll rename it to whatever you like. I'd suggest "ref=". The
> > > reason I think it is important is there are multiple sources that
> > > aren't always obvious from the other records to which it is
> > > associated. In the case of ptrace and signals, there can be many
> > > target tasks listed (OBJ_PID) with no other way to distinguish
> > > the matching audit container identifier records all for one
> > > event. This is in addition to the default syscall container
> > > identifier record. I'm not currently happy with the text content
> > > to link the two, but that should be solvable (most obvious is
> > > taret PID). Throwing away this information seems shortsighted.
> >
> > It would be helpful if you could generate real audit events
> > demonstrating the problems you are describing, as well as a more
> > standard syscall event, so we can discuss some possible solutions.
>
> If the auditted process is in a container and it ptraces or signals
> another process in a container, there will be two AUDIT_CONTAINER
> records for the same event that won't be identified as to which record
> belongs to which process or other record (SYSCALL vs 1+ OBJ_PID
> records). There could be many signals recorded, each with their own
> OBJ_PID record. The first is stored in the audit context and
> additional ones are stored in a chained struct that can accommodate
> 16 entries each.
>
> (See audit_signal_info(), __audit_ptrace().)
>
> (As a side note, on code inspection it appears that a signal target
> would get overwritten by a ptrace action if they were to happen in
> that order.)
>
> > paul moore
>
> - RGB
>
> --
> Richard Guy Briggs <[email protected]>
> 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
>
> --
> Linux-audit mailing list
> [email protected]
> https://www.redhat.com/mailman/listinfo/linux-audit


2018-10-25 06:13:51

by Paul Moore

[permalink] [raw]
Subject: Re: [PATCH ghak90 (was ghak32) V4 03/10] audit: log container info of syscalls

On October 25, 2018 1:43:16 AM Richard Guy Briggs <[email protected]> wrote:
> On 2018-10-24 16:55, Paul Moore wrote:
>> On Wed, Oct 24, 2018 at 11:15 AM Richard Guy Briggs <[email protected]> wrote:
>>> On 2018-10-19 19:16, Paul Moore wrote:
>>>> On Sun, Aug 5, 2018 at 4:32 AM Richard Guy Briggs <[email protected]> wrote:
>

...

>
>>>> However, I do care about the "op" field in this record. It just
>>>> doesn't make any sense; the way you are using it it is more of a
>>>> context field than an operations field, and even then why is the
>>>> context important from a logging and/or security perspective? Drop it
>>>> please.
>>>
>>> I'll rename it to whatever you like. I'd suggest "ref=". The reason I
>>> think it is important is there are multiple sources that aren't always
>>> obvious from the other records to which it is associated. In the case
>>> of ptrace and signals, there can be many target tasks listed (OBJ_PID)
>>> with no other way to distinguish the matching audit container identifier
>>> records all for one event. This is in addition to the default syscall
>>> container identifier record. I'm not currently happy with the text
>>> content to link the two, but that should be solvable (most obvious is
>>> taret PID). Throwing away this information seems shortsighted.
>>
>> It would be helpful if you could generate real audit events
>> demonstrating the problems you are describing, as well as a more
>> standard syscall event, so we can discuss some possible solutions.
>
> If the auditted process is in a container and it ptraces or signals
> another process in a container, there will be two AUDIT_CONTAINER
> records for the same event that won't be identified as to which record
> belongs to which process or other record (SYSCALL vs 1+ OBJ_PID
> records). There could be many signals recorded, each with their own
> OBJ_PID record. The first is stored in the audit context and additional
> ones are stored in a chained struct that can accommodate 16 entries each.
>
> (See audit_signal_info(), __audit_ptrace().)
>
> (As a side note, on code inspection it appears that a signal target
> would get overwritten by a ptrace action if they were to happen in that
> order.)

As requested above, please respond with real audit events generated by this patchset so that we can discuss possible solutions.

--
paul moore
http://www.paul-moore.com




2018-10-25 10:50:45

by Paul Moore

[permalink] [raw]
Subject: Re: [PATCH ghak90 (was ghak32) V4 03/10] audit: log container info of syscalls

On Thu, Oct 25, 2018 at 2:06 AM Steve Grubb <[email protected]> wrote:
> On Wed, 24 Oct 2018 20:42:55 -0400
> Richard Guy Briggs <[email protected]> wrote:
> > On 2018-10-24 16:55, Paul Moore wrote:
> > > On Wed, Oct 24, 2018 at 11:15 AM Richard Guy Briggs
> > > <[email protected]> wrote:
> > > > On 2018-10-19 19:16, Paul Moore wrote:
> > > > > On Sun, Aug 5, 2018 at 4:32 AM Richard Guy Briggs
> > > > > <[email protected]> wrote:

...

> > > > > > +/*
> > > > > > + * audit_log_contid - report container info
> > > > > > + * @tsk: task to be recorded
> > > > > > + * @context: task or local context for record
> > > > > > + * @op: contid string description
> > > > > > + */
> > > > > > +int audit_log_contid(struct task_struct *tsk,
> > > > > > + struct audit_context *context,
> > > > > > char *op) +{
> > > > > > + struct audit_buffer *ab;
> > > > > > +
> > > > > > + if (!audit_contid_set(tsk))
> > > > > > + return 0;
> > > > > > + /* Generate AUDIT_CONTAINER record with container ID
> > > > > > */
> > > > > > + ab = audit_log_start(context, GFP_KERNEL,
> > > > > > AUDIT_CONTAINER);
> > > > > > + if (!ab)
> > > > > > + return -ENOMEM;
> > > > > > + audit_log_format(ab, "op=%s contid=%llu",
> > > > > > + op, audit_get_contid(tsk));
> > > > > > + audit_log_end(ab);
> > > > > > + return 0;
> > > > > > +}
> > > > > > +EXPORT_SYMBOL(audit_log_contid);
> > > > >
> > > > > As discussed in the previous iteration of the patch, I prefer
> > > > > AUDIT_CONTAINER_ID here over AUDIT_CONTAINER. If you feel
> > > > > strongly about keeping it as-is with AUDIT_CONTAINER I suppose
> > > > > I could live with that, but it is isn't my first choice.
> > > >
> > > > I don't have a strong opinion on this one, mildly preferring the
> > > > shorter one only because it is shorter.
> > >
> > > We already have multiple AUDIT_CONTAINER* record types, so it seems
> > > as though we should use "AUDIT_CONTAINER" as a prefix of sorts,
> > > rather than a type itself.
> >
> > I'm fine with that. I'd still like to hear Steve's input. He had
> > stronger opinions than me.
>
> The creation event should be separate and distinct from the continuing
> use when its used as a supplemental record. IOW, binding the ID to a
> container is part of the lifecycle and needs to be kept distinct.

Steve's comment is pretty ambiguous when it comes to AUDIT_CONTAINER
vs AUDIT_CONTAINER_ID, but one could argue that AUDIT_CONTAINER_ID
helps distinguish the audit container id marking record and gets to
what I believe is the spirit of Steve's comment. Taking this in
context with my previous remarks, let's switch to using
AUDIT_CONTAINER_ID.

--
paul moore
http://www.paul-moore.com

2018-10-25 12:24:46

by Richard Guy Briggs

[permalink] [raw]
Subject: Re: [PATCH ghak90 (was ghak32) V4 03/10] audit: log container info of syscalls

On 2018-10-25 07:13, Paul Moore wrote:
> On October 25, 2018 1:43:16 AM Richard Guy Briggs <[email protected]> wrote:
> > On 2018-10-24 16:55, Paul Moore wrote:
> >> On Wed, Oct 24, 2018 at 11:15 AM Richard Guy Briggs <[email protected]> wrote:
> >>> On 2018-10-19 19:16, Paul Moore wrote:
> >>>> On Sun, Aug 5, 2018 at 4:32 AM Richard Guy Briggs <[email protected]> wrote:
> >
>
> ...
>
> >
> >>>> However, I do care about the "op" field in this record. It just
> >>>> doesn't make any sense; the way you are using it it is more of a
> >>>> context field than an operations field, and even then why is the
> >>>> context important from a logging and/or security perspective? Drop it
> >>>> please.
> >>>
> >>> I'll rename it to whatever you like. I'd suggest "ref=". The reason I
> >>> think it is important is there are multiple sources that aren't always
> >>> obvious from the other records to which it is associated. In the case
> >>> of ptrace and signals, there can be many target tasks listed (OBJ_PID)
> >>> with no other way to distinguish the matching audit container identifier
> >>> records all for one event. This is in addition to the default syscall
> >>> container identifier record. I'm not currently happy with the text
> >>> content to link the two, but that should be solvable (most obvious is
> >>> taret PID). Throwing away this information seems shortsighted.
> >>
> >> It would be helpful if you could generate real audit events
> >> demonstrating the problems you are describing, as well as a more
> >> standard syscall event, so we can discuss some possible solutions.
> >
> > If the auditted process is in a container and it ptraces or signals
> > another process in a container, there will be two AUDIT_CONTAINER
> > records for the same event that won't be identified as to which record
> > belongs to which process or other record (SYSCALL vs 1+ OBJ_PID
> > records). There could be many signals recorded, each with their own
> > OBJ_PID record. The first is stored in the audit context and additional
> > ones are stored in a chained struct that can accommodate 16 entries each.
> >
> > (See audit_signal_info(), __audit_ptrace().)
> >
> > (As a side note, on code inspection it appears that a signal target
> > would get overwritten by a ptrace action if they were to happen in that
> > order.)
>
> As requested above, please respond with real audit events generated by
> this patchset so that we can discuss possible solutions.

Ok, then we should be developping a test to test ptrace and signal
auditting in general since we don't have current experience/evidence
that those even work (or rip them out if not).

> paul moore

- RGB

--
Richard Guy Briggs <[email protected]>
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

2018-10-25 12:28:35

by Richard Guy Briggs

[permalink] [raw]
Subject: Re: [PATCH ghak90 (was ghak32) V4 03/10] audit: log container info of syscalls

On 2018-10-25 06:49, Paul Moore wrote:
> On Thu, Oct 25, 2018 at 2:06 AM Steve Grubb <[email protected]> wrote:
> > On Wed, 24 Oct 2018 20:42:55 -0400
> > Richard Guy Briggs <[email protected]> wrote:
> > > On 2018-10-24 16:55, Paul Moore wrote:
> > > > On Wed, Oct 24, 2018 at 11:15 AM Richard Guy Briggs
> > > > <[email protected]> wrote:
> > > > > On 2018-10-19 19:16, Paul Moore wrote:
> > > > > > On Sun, Aug 5, 2018 at 4:32 AM Richard Guy Briggs
> > > > > > <[email protected]> wrote:
>
> ...
>
> > > > > > > +/*
> > > > > > > + * audit_log_contid - report container info
> > > > > > > + * @tsk: task to be recorded
> > > > > > > + * @context: task or local context for record
> > > > > > > + * @op: contid string description
> > > > > > > + */
> > > > > > > +int audit_log_contid(struct task_struct *tsk,
> > > > > > > + struct audit_context *context,
> > > > > > > char *op) +{
> > > > > > > + struct audit_buffer *ab;
> > > > > > > +
> > > > > > > + if (!audit_contid_set(tsk))
> > > > > > > + return 0;
> > > > > > > + /* Generate AUDIT_CONTAINER record with container ID
> > > > > > > */
> > > > > > > + ab = audit_log_start(context, GFP_KERNEL,
> > > > > > > AUDIT_CONTAINER);
> > > > > > > + if (!ab)
> > > > > > > + return -ENOMEM;
> > > > > > > + audit_log_format(ab, "op=%s contid=%llu",
> > > > > > > + op, audit_get_contid(tsk));
> > > > > > > + audit_log_end(ab);
> > > > > > > + return 0;
> > > > > > > +}
> > > > > > > +EXPORT_SYMBOL(audit_log_contid);
> > > > > >
> > > > > > As discussed in the previous iteration of the patch, I prefer
> > > > > > AUDIT_CONTAINER_ID here over AUDIT_CONTAINER. If you feel
> > > > > > strongly about keeping it as-is with AUDIT_CONTAINER I suppose
> > > > > > I could live with that, but it is isn't my first choice.
> > > > >
> > > > > I don't have a strong opinion on this one, mildly preferring the
> > > > > shorter one only because it is shorter.
> > > >
> > > > We already have multiple AUDIT_CONTAINER* record types, so it seems
> > > > as though we should use "AUDIT_CONTAINER" as a prefix of sorts,
> > > > rather than a type itself.
> > >
> > > I'm fine with that. I'd still like to hear Steve's input. He had
> > > stronger opinions than me.
> >
> > The creation event should be separate and distinct from the continuing
> > use when its used as a supplemental record. IOW, binding the ID to a
> > container is part of the lifecycle and needs to be kept distinct.
>
> Steve's comment is pretty ambiguous when it comes to AUDIT_CONTAINER
> vs AUDIT_CONTAINER_ID, but one could argue that AUDIT_CONTAINER_ID
> helps distinguish the audit container id marking record and gets to
> what I believe is the spirit of Steve's comment. Taking this in
> context with my previous remarks, let's switch to using
> AUDIT_CONTAINER_ID.

I suspect Steve is mixing up AUDIT_CONTAINER_OP with AUDIT_CONTAINER_ID,
confusing the fact that they are two seperate records. As a summary,
the suggested records are:
CONTAINER_OP audit container identifier creation
CONTAINER audit container identifier aux record to an event

and what Paul is suggesting (which is fine by me) is:
CONTAINER_OP audit container identifier creation event
CONTAINER_ID audit container identifier aux record to an event

Steve, please indicate you are fine with this.

> paul moore

- RGB

--
Richard Guy Briggs <[email protected]>
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

2018-10-25 16:00:30

by Steve Grubb

[permalink] [raw]
Subject: Re: [PATCH ghak90 (was ghak32) V4 03/10] audit: log container info of syscalls

On Thu, 25 Oct 2018 08:27:32 -0400
Richard Guy Briggs <[email protected]> wrote:

> On 2018-10-25 06:49, Paul Moore wrote:
> > On Thu, Oct 25, 2018 at 2:06 AM Steve Grubb <[email protected]>
> > wrote:
> > > On Wed, 24 Oct 2018 20:42:55 -0400
> > > Richard Guy Briggs <[email protected]> wrote:
> > > > On 2018-10-24 16:55, Paul Moore wrote:
> > > > > On Wed, Oct 24, 2018 at 11:15 AM Richard Guy Briggs
> > > > > <[email protected]> wrote:
> > > > > > On 2018-10-19 19:16, Paul Moore wrote:
> > > > > > > On Sun, Aug 5, 2018 at 4:32 AM Richard Guy Briggs
> > > > > > > <[email protected]> wrote:
> >
> > ...
> >
> > > > > > > > +/*
> > > > > > > > + * audit_log_contid - report container info
> > > > > > > > + * @tsk: task to be recorded
> > > > > > > > + * @context: task or local context for record
> > > > > > > > + * @op: contid string description
> > > > > > > > + */
> > > > > > > > +int audit_log_contid(struct task_struct *tsk,
> > > > > > > > + struct audit_context
> > > > > > > > *context, char *op) +{
> > > > > > > > + struct audit_buffer *ab;
> > > > > > > > +
> > > > > > > > + if (!audit_contid_set(tsk))
> > > > > > > > + return 0;
> > > > > > > > + /* Generate AUDIT_CONTAINER record with
> > > > > > > > container ID */
> > > > > > > > + ab = audit_log_start(context, GFP_KERNEL,
> > > > > > > > AUDIT_CONTAINER);
> > > > > > > > + if (!ab)
> > > > > > > > + return -ENOMEM;
> > > > > > > > + audit_log_format(ab, "op=%s contid=%llu",
> > > > > > > > + op, audit_get_contid(tsk));
> > > > > > > > + audit_log_end(ab);
> > > > > > > > + return 0;
> > > > > > > > +}
> > > > > > > > +EXPORT_SYMBOL(audit_log_contid);
> > > > > > >
> > > > > > > As discussed in the previous iteration of the patch, I
> > > > > > > prefer AUDIT_CONTAINER_ID here over AUDIT_CONTAINER. If
> > > > > > > you feel strongly about keeping it as-is with
> > > > > > > AUDIT_CONTAINER I suppose I could live with that, but it
> > > > > > > is isn't my first choice.
> > > > > >
> > > > > > I don't have a strong opinion on this one, mildly
> > > > > > preferring the shorter one only because it is shorter.
> > > > >
> > > > > We already have multiple AUDIT_CONTAINER* record types, so it
> > > > > seems as though we should use "AUDIT_CONTAINER" as a prefix
> > > > > of sorts, rather than a type itself.
> > > >
> > > > I'm fine with that. I'd still like to hear Steve's input. He
> > > > had stronger opinions than me.
> > >
> > > The creation event should be separate and distinct from the
> > > continuing use when its used as a supplemental record. IOW,
> > > binding the ID to a container is part of the lifecycle and needs
> > > to be kept distinct.
> >
> > Steve's comment is pretty ambiguous when it comes to AUDIT_CONTAINER
> > vs AUDIT_CONTAINER_ID, but one could argue that AUDIT_CONTAINER_ID
> > helps distinguish the audit container id marking record and gets to
> > what I believe is the spirit of Steve's comment. Taking this in
> > context with my previous remarks, let's switch to using
> > AUDIT_CONTAINER_ID.
>
> I suspect Steve is mixing up AUDIT_CONTAINER_OP with
> AUDIT_CONTAINER_ID, confusing the fact that they are two seperate
> records. As a summary, the suggested records are:
> CONTAINER_OP audit container identifier creation
> CONTAINER audit container identifier aux record to an
> event
>
> and what Paul is suggesting (which is fine by me) is:
> CONTAINER_OP audit container identifier creation event
> CONTAINER_ID audit container identifier aux record to
> an event
>
> Steve, please indicate you are fine with this.

I thought it was:

CONTAINER_ID audit container identifier creation event
CONTAINER audit container identifier aux record to an event

Or vice versa. Don't mix up creation of the identifier with operations.

-Steve

2018-10-25 17:39:31

by Richard Guy Briggs

[permalink] [raw]
Subject: Re: [PATCH ghak90 (was ghak32) V4 03/10] audit: log container info of syscalls

On 2018-10-25 17:57, Steve Grubb wrote:
> On Thu, 25 Oct 2018 08:27:32 -0400
> Richard Guy Briggs <[email protected]> wrote:
>
> > On 2018-10-25 06:49, Paul Moore wrote:
> > > On Thu, Oct 25, 2018 at 2:06 AM Steve Grubb <[email protected]>
> > > wrote:
> > > > On Wed, 24 Oct 2018 20:42:55 -0400
> > > > Richard Guy Briggs <[email protected]> wrote:
> > > > > On 2018-10-24 16:55, Paul Moore wrote:
> > > > > > On Wed, Oct 24, 2018 at 11:15 AM Richard Guy Briggs
> > > > > > <[email protected]> wrote:
> > > > > > > On 2018-10-19 19:16, Paul Moore wrote:
> > > > > > > > On Sun, Aug 5, 2018 at 4:32 AM Richard Guy Briggs
> > > > > > > > <[email protected]> wrote:
> > >
> > > ...
> > >
> > > > > > > > > +/*
> > > > > > > > > + * audit_log_contid - report container info
> > > > > > > > > + * @tsk: task to be recorded
> > > > > > > > > + * @context: task or local context for record
> > > > > > > > > + * @op: contid string description
> > > > > > > > > + */
> > > > > > > > > +int audit_log_contid(struct task_struct *tsk,
> > > > > > > > > + struct audit_context
> > > > > > > > > *context, char *op) +{
> > > > > > > > > + struct audit_buffer *ab;
> > > > > > > > > +
> > > > > > > > > + if (!audit_contid_set(tsk))
> > > > > > > > > + return 0;
> > > > > > > > > + /* Generate AUDIT_CONTAINER record with
> > > > > > > > > container ID */
> > > > > > > > > + ab = audit_log_start(context, GFP_KERNEL,
> > > > > > > > > AUDIT_CONTAINER);
> > > > > > > > > + if (!ab)
> > > > > > > > > + return -ENOMEM;
> > > > > > > > > + audit_log_format(ab, "op=%s contid=%llu",
> > > > > > > > > + op, audit_get_contid(tsk));
> > > > > > > > > + audit_log_end(ab);
> > > > > > > > > + return 0;
> > > > > > > > > +}
> > > > > > > > > +EXPORT_SYMBOL(audit_log_contid);
> > > > > > > >
> > > > > > > > As discussed in the previous iteration of the patch, I
> > > > > > > > prefer AUDIT_CONTAINER_ID here over AUDIT_CONTAINER. If
> > > > > > > > you feel strongly about keeping it as-is with
> > > > > > > > AUDIT_CONTAINER I suppose I could live with that, but it
> > > > > > > > is isn't my first choice.
> > > > > > >
> > > > > > > I don't have a strong opinion on this one, mildly
> > > > > > > preferring the shorter one only because it is shorter.
> > > > > >
> > > > > > We already have multiple AUDIT_CONTAINER* record types, so it
> > > > > > seems as though we should use "AUDIT_CONTAINER" as a prefix
> > > > > > of sorts, rather than a type itself.
> > > > >
> > > > > I'm fine with that. I'd still like to hear Steve's input. He
> > > > > had stronger opinions than me.
> > > >
> > > > The creation event should be separate and distinct from the
> > > > continuing use when its used as a supplemental record. IOW,
> > > > binding the ID to a container is part of the lifecycle and needs
> > > > to be kept distinct.
> > >
> > > Steve's comment is pretty ambiguous when it comes to AUDIT_CONTAINER
> > > vs AUDIT_CONTAINER_ID, but one could argue that AUDIT_CONTAINER_ID
> > > helps distinguish the audit container id marking record and gets to
> > > what I believe is the spirit of Steve's comment. Taking this in
> > > context with my previous remarks, let's switch to using
> > > AUDIT_CONTAINER_ID.
> >
> > I suspect Steve is mixing up AUDIT_CONTAINER_OP with
> > AUDIT_CONTAINER_ID, confusing the fact that they are two seperate
> > records. As a summary, the suggested records are:
> > CONTAINER_OP audit container identifier creation
> > CONTAINER audit container identifier aux record to an
> > event
> >
> > and what Paul is suggesting (which is fine by me) is:
> > CONTAINER_OP audit container identifier creation event
> > CONTAINER_ID audit container identifier aux record to
> > an event
> >
> > Steve, please indicate you are fine with this.
>
> I thought it was:

It *was*. It was changed at Paul's request in this v3 thread:
https://www.redhat.com/archives/linux-audit/2018-July/msg00087.html

And listed in the examples and changelog to this v4 patchset:
https://www.redhat.com/archives/linux-audit/2018-July/msg00178.html

It is also listed in this userspace patchset update v4 (which should
also have had a changelog added to it, note to self...):
https://www.redhat.com/archives/linux-audit/2018-July/msg00189.html

I realize it is hard to keep up with all the detail changes in these
patchsets...

> CONTAINER_ID audit container identifier creation event
> CONTAINER audit container identifier aux record to an event
>
> Or vice versa. Don't mix up creation of the identifier with operations.

Exactly what I'm trying to avoid... Worded another way: "Don't mix up
the creation operation with routine reporting of the identifier in
events." Steve, can you and Paul discuss and agree on what they should
be called? I don't have a horse in this race, but I need to record the
result of that run. ;-)

> -Steve

- RGB

--
Richard Guy Briggs <[email protected]>
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

2018-10-25 20:42:32

by Paul Moore

[permalink] [raw]
Subject: Re: [PATCH ghak90 (was ghak32) V4 03/10] audit: log container info of syscalls

On Thu, Oct 25, 2018 at 1:38 PM Richard Guy Briggs <[email protected]> wrote:
> On 2018-10-25 17:57, Steve Grubb wrote:
> > On Thu, 25 Oct 2018 08:27:32 -0400
> > Richard Guy Briggs <[email protected]> wrote:
> >
> > > On 2018-10-25 06:49, Paul Moore wrote:
> > > > On Thu, Oct 25, 2018 at 2:06 AM Steve Grubb <[email protected]>
> > > > wrote:
> > > > > On Wed, 24 Oct 2018 20:42:55 -0400
> > > > > Richard Guy Briggs <[email protected]> wrote:
> > > > > > On 2018-10-24 16:55, Paul Moore wrote:
> > > > > > > On Wed, Oct 24, 2018 at 11:15 AM Richard Guy Briggs
> > > > > > > <[email protected]> wrote:
> > > > > > > > On 2018-10-19 19:16, Paul Moore wrote:
> > > > > > > > > On Sun, Aug 5, 2018 at 4:32 AM Richard Guy Briggs
> > > > > > > > > <[email protected]> wrote:
> > > >
> > > > ...
> > > >
> > > > > > > > > > +/*
> > > > > > > > > > + * audit_log_contid - report container info
> > > > > > > > > > + * @tsk: task to be recorded
> > > > > > > > > > + * @context: task or local context for record
> > > > > > > > > > + * @op: contid string description
> > > > > > > > > > + */
> > > > > > > > > > +int audit_log_contid(struct task_struct *tsk,
> > > > > > > > > > + struct audit_context
> > > > > > > > > > *context, char *op) +{
> > > > > > > > > > + struct audit_buffer *ab;
> > > > > > > > > > +
> > > > > > > > > > + if (!audit_contid_set(tsk))
> > > > > > > > > > + return 0;
> > > > > > > > > > + /* Generate AUDIT_CONTAINER record with
> > > > > > > > > > container ID */
> > > > > > > > > > + ab = audit_log_start(context, GFP_KERNEL,
> > > > > > > > > > AUDIT_CONTAINER);
> > > > > > > > > > + if (!ab)
> > > > > > > > > > + return -ENOMEM;
> > > > > > > > > > + audit_log_format(ab, "op=%s contid=%llu",
> > > > > > > > > > + op, audit_get_contid(tsk));
> > > > > > > > > > + audit_log_end(ab);
> > > > > > > > > > + return 0;
> > > > > > > > > > +}
> > > > > > > > > > +EXPORT_SYMBOL(audit_log_contid);
> > > > > > > > >
> > > > > > > > > As discussed in the previous iteration of the patch, I
> > > > > > > > > prefer AUDIT_CONTAINER_ID here over AUDIT_CONTAINER. If
> > > > > > > > > you feel strongly about keeping it as-is with
> > > > > > > > > AUDIT_CONTAINER I suppose I could live with that, but it
> > > > > > > > > is isn't my first choice.
> > > > > > > >
> > > > > > > > I don't have a strong opinion on this one, mildly
> > > > > > > > preferring the shorter one only because it is shorter.
> > > > > > >
> > > > > > > We already have multiple AUDIT_CONTAINER* record types, so it
> > > > > > > seems as though we should use "AUDIT_CONTAINER" as a prefix
> > > > > > > of sorts, rather than a type itself.
> > > > > >
> > > > > > I'm fine with that. I'd still like to hear Steve's input. He
> > > > > > had stronger opinions than me.
> > > > >
> > > > > The creation event should be separate and distinct from the
> > > > > continuing use when its used as a supplemental record. IOW,
> > > > > binding the ID to a container is part of the lifecycle and needs
> > > > > to be kept distinct.
> > > >
> > > > Steve's comment is pretty ambiguous when it comes to AUDIT_CONTAINER
> > > > vs AUDIT_CONTAINER_ID, but one could argue that AUDIT_CONTAINER_ID
> > > > helps distinguish the audit container id marking record and gets to
> > > > what I believe is the spirit of Steve's comment. Taking this in
> > > > context with my previous remarks, let's switch to using
> > > > AUDIT_CONTAINER_ID.
> > >
> > > I suspect Steve is mixing up AUDIT_CONTAINER_OP with
> > > AUDIT_CONTAINER_ID, confusing the fact that they are two seperate
> > > records. As a summary, the suggested records are:
> > > CONTAINER_OP audit container identifier creation
> > > CONTAINER audit container identifier aux record to an
> > > event
> > >
> > > and what Paul is suggesting (which is fine by me) is:
> > > CONTAINER_OP audit container identifier creation event
> > > CONTAINER_ID audit container identifier aux record to
> > > an event
> > >
> > > Steve, please indicate you are fine with this.
> >
> > I thought it was:
>
> It *was*. It was changed at Paul's request in this v3 thread:
> https://www.redhat.com/archives/linux-audit/2018-July/msg00087.html
>
> And listed in the examples and changelog to this v4 patchset:
> https://www.redhat.com/archives/linux-audit/2018-July/msg00178.html
>
> It is also listed in this userspace patchset update v4 (which should
> also have had a changelog added to it, note to self...):
> https://www.redhat.com/archives/linux-audit/2018-July/msg00189.html
>
> I realize it is hard to keep up with all the detail changes in these
> patchsets...
>
> > CONTAINER_ID audit container identifier creation event
> > CONTAINER audit container identifier aux record to an event
> >
> > Or vice versa. Don't mix up creation of the identifier with operations.
>
> Exactly what I'm trying to avoid... Worded another way: "Don't mix up
> the creation operation with routine reporting of the identifier in
> events." Steve, can you and Paul discuss and agree on what they should
> be called? I don't have a horse in this race, but I need to record the
> result of that run. ;-)

See my previous comments, I think I've been pretty clear on what I
would like to see.

--
paul moore
http://www.paul-moore.com

2018-10-25 21:58:16

by Steve Grubb

[permalink] [raw]
Subject: Re: [PATCH ghak90 (was ghak32) V4 03/10] audit: log container info of syscalls

On Thu, 25 Oct 2018 16:40:19 -0400
Paul Moore <[email protected]> wrote:

> On Thu, Oct 25, 2018 at 1:38 PM Richard Guy Briggs <[email protected]>
> wrote:
> > On 2018-10-25 17:57, Steve Grubb wrote:
> > > On Thu, 25 Oct 2018 08:27:32 -0400
> > > Richard Guy Briggs <[email protected]> wrote:
> > >
> > > > On 2018-10-25 06:49, Paul Moore wrote:
> > > > > On Thu, Oct 25, 2018 at 2:06 AM Steve Grubb
> > > > > <[email protected]> wrote:
> > > > > > On Wed, 24 Oct 2018 20:42:55 -0400
> > > > > > Richard Guy Briggs <[email protected]> wrote:
> > > > > > > On 2018-10-24 16:55, Paul Moore wrote:
> > > > > > > > On Wed, Oct 24, 2018 at 11:15 AM Richard Guy Briggs
> > > > > > > > <[email protected]> wrote:
> > > > > > > > > On 2018-10-19 19:16, Paul Moore wrote:
> > > > > > > > > > On Sun, Aug 5, 2018 at 4:32 AM Richard Guy Briggs
> > > > > > > > > > <[email protected]> wrote:
> > > > >
> > > > > ...
> > > > >
> > > > > > > > > > > +/*
> > > > > > > > > > > + * audit_log_contid - report container info
> > > > > > > > > > > + * @tsk: task to be recorded
> > > > > > > > > > > + * @context: task or local context for record
> > > > > > > > > > > + * @op: contid string description
> > > > > > > > > > > + */
> > > > > > > > > > > +int audit_log_contid(struct task_struct *tsk,
> > > > > > > > > > > + struct audit_context
> > > > > > > > > > > *context, char *op) +{
> > > > > > > > > > > + struct audit_buffer *ab;
> > > > > > > > > > > +
> > > > > > > > > > > + if (!audit_contid_set(tsk))
> > > > > > > > > > > + return 0;
> > > > > > > > > > > + /* Generate AUDIT_CONTAINER record with
> > > > > > > > > > > container ID */
> > > > > > > > > > > + ab = audit_log_start(context, GFP_KERNEL,
> > > > > > > > > > > AUDIT_CONTAINER);
> > > > > > > > > > > + if (!ab)
> > > > > > > > > > > + return -ENOMEM;
> > > > > > > > > > > + audit_log_format(ab, "op=%s contid=%llu",
> > > > > > > > > > > + op,
> > > > > > > > > > > audit_get_contid(tsk));
> > > > > > > > > > > + audit_log_end(ab);
> > > > > > > > > > > + return 0;
> > > > > > > > > > > +}
> > > > > > > > > > > +EXPORT_SYMBOL(audit_log_contid);
> > > > > > > > > >
> > > > > > > > > > As discussed in the previous iteration of the
> > > > > > > > > > patch, I prefer AUDIT_CONTAINER_ID here over
> > > > > > > > > > AUDIT_CONTAINER. If you feel strongly about
> > > > > > > > > > keeping it as-is with AUDIT_CONTAINER I suppose I
> > > > > > > > > > could live with that, but it is isn't my first
> > > > > > > > > > choice.
> > > > > > > > >
> > > > > > > > > I don't have a strong opinion on this one, mildly
> > > > > > > > > preferring the shorter one only because it is
> > > > > > > > > shorter.
> > > > > > > >
> > > > > > > > We already have multiple AUDIT_CONTAINER* record types,
> > > > > > > > so it seems as though we should use "AUDIT_CONTAINER"
> > > > > > > > as a prefix of sorts, rather than a type itself.
> > > > > > >
> > > > > > > I'm fine with that. I'd still like to hear Steve's
> > > > > > > input. He had stronger opinions than me.
> > > > > >
> > > > > > The creation event should be separate and distinct from the
> > > > > > continuing use when its used as a supplemental record. IOW,
> > > > > > binding the ID to a container is part of the lifecycle and
> > > > > > needs to be kept distinct.
> > > > >
> > > > > Steve's comment is pretty ambiguous when it comes to
> > > > > AUDIT_CONTAINER vs AUDIT_CONTAINER_ID, but one could argue
> > > > > that AUDIT_CONTAINER_ID helps distinguish the audit container
> > > > > id marking record and gets to what I believe is the spirit of
> > > > > Steve's comment. Taking this in context with my previous
> > > > > remarks, let's switch to using AUDIT_CONTAINER_ID.
> > > >
> > > > I suspect Steve is mixing up AUDIT_CONTAINER_OP with
> > > > AUDIT_CONTAINER_ID, confusing the fact that they are two
> > > > seperate records. As a summary, the suggested records are:
> > > > CONTAINER_OP audit container identifier creation
> > > > CONTAINER audit container identifier aux record to an
> > > > event
> > > >
> > > > and what Paul is suggesting (which is fine by me) is:
> > > > CONTAINER_OP audit container identifier creation event
> > > > CONTAINER_ID audit container identifier aux record to
> > > > an event
> > > >
> > > > Steve, please indicate you are fine with this.
> > >
> > > I thought it was:
> >
> > It *was*. It was changed at Paul's request in this v3 thread:
> > https://www.redhat.com/archives/linux-audit/2018-July/msg00087.html
> >
> > And listed in the examples and changelog to this v4 patchset:
> > https://www.redhat.com/archives/linux-audit/2018-July/msg00178.html
> >
> > It is also listed in this userspace patchset update v4 (which should
> > also have had a changelog added to it, note to self...):
> > https://www.redhat.com/archives/linux-audit/2018-July/msg00189.html
> >
> > I realize it is hard to keep up with all the detail changes in these
> > patchsets...
> >
> > > CONTAINER_ID audit container identifier creation event
> > > event. CONTAINER audit container identifier aux record to an
> > > event
> > >
> > > Or vice versa. Don't mix up creation of the identifier with
> > > operations.
> >
> > Exactly what I'm trying to avoid... Worded another way: "Don't mix
> > up the creation operation with routine reporting of the identifier
> > in events." Steve, can you and Paul discuss and agree on what they
> > should be called? I don't have a horse in this race, but I need to
> > record the result of that run. ;-)
>
> See my previous comments, I think I've been pretty clear on what I
> would like to see.

And historically speaking setting audit loginuid produces a LOGIN
event, so it only makes sense to consider binding container ID to
container as a CONTAINER event. For other supplemental records, we name
things what they are: PATH, CWD, SOCKADDR, etc. So, CONTAINER_ID makes
sense. CONTAINER_OP sounds like its for operations on a container. Do
we have any operations on a container?

-Steve

2018-10-26 08:15:59

by Casey Schaufler

[permalink] [raw]
Subject: Re: [PATCH ghak90 (was ghak32) V4 03/10] audit: log container info of syscalls

On 10/25/2018 2:55 PM, Steve Grubb wrote:
> ...
> And historically speaking setting audit loginuid produces a LOGIN
> event, so it only makes sense to consider binding container ID to
> container as a CONTAINER event. For other supplemental records, we name
> things what they are: PATH, CWD, SOCKADDR, etc. So, CONTAINER_ID makes
> sense. CONTAINER_OP sounds like its for operations on a container. Do
> we have any operations on a container?

The answer has to be "no", because containers are, by emphatic assertion,
not kernel constructs. Any CONTAINER_OP event has to come from user space.
I think.


2018-10-28 07:55:29

by Paul Moore

[permalink] [raw]
Subject: Re: [PATCH ghak90 (was ghak32) V4 03/10] audit: log container info of syscalls

On Fri, Oct 26, 2018 at 4:13 AM Casey Schaufler <[email protected]> wrote:
> On 10/25/2018 2:55 PM, Steve Grubb wrote:
> > ...
> > And historically speaking setting audit loginuid produces a LOGIN
> > event, so it only makes sense to consider binding container ID to
> > container as a CONTAINER event. For other supplemental records, we name
> > things what they are: PATH, CWD, SOCKADDR, etc. So, CONTAINER_ID makes
> > sense. CONTAINER_OP sounds like its for operations on a container. Do
> > we have any operations on a container?
>
> The answer has to be "no", because containers are, by emphatic assertion,
> not kernel constructs. Any CONTAINER_OP event has to come from user space.
> I think.

It is very important that we do not confuse operations on the audit
container id with operations on the containers themselves. Of course
at a higher level, e.g. audit log analysis, we want to equate the two,
and if the container runtime which manages the audit container id is
sane that should be a reasonable assumption, but in this particular
patchset AUDIT_CONTAINER_OP is referring to operations involving just
the audit container id.

If there is a need for additional container operation auditing (note
well that I did not say audit container id here) then those audit
records can, and should, be generated by the container runtime itself,
similar to what we do with libvirt for virtualization.

--
paul moore
http://www.paul-moore.com

2018-10-31 19:31:41

by Richard Guy Briggs

[permalink] [raw]
Subject: Re: [PATCH ghak90 (was ghak32) V4 09/10] audit: NETFILTER_PKT: record each container ID associated with a netNS

On 2018-10-19 19:18, Paul Moore wrote:
> On Sun, Aug 5, 2018 at 4:33 AM Richard Guy Briggs <[email protected]> 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 <[email protected]>
> > ---
> > include/linux/audit.h | 5 +++++
> > kernel/audit.c | 26 ++++++++++++++++++++++++++
> > net/netfilter/xt_AUDIT.c | 12 ++++++++++--
> > 3 files changed, 41 insertions(+), 2 deletions(-)
>
> ...
>
> > diff --git a/include/linux/audit.h b/include/linux/audit.h
> > index 9a02095..8755f4d 100644
> > --- a/include/linux/audit.h
> > +++ b/include/linux/audit.h
> > @@ -169,6 +169,8 @@ extern int audit_log_contid(struct audit_context *context,
> > 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 void audit_log_netns_contid_list(struct net *net,
> > + struct audit_context *context);
> >
> > extern int audit_update_lsm_rules(void);
> >
> > @@ -228,6 +230,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 c5fed3b..b23711c 100644
> > --- a/kernel/audit.c
> > +++ b/kernel/audit.c
> > @@ -392,6 +392,32 @@ void audit_switch_task_namespaces(struct nsproxy *ns, struct task_struct *p)
> > audit_netns_contid_add(new->net_ns, contid);
> > }
> >
> > +void audit_log_netns_contid_list(struct net *net, struct audit_context *context)
> > +{
> > + spinlock_t *lock = audit_get_netns_contid_list_lock(net);
> > + struct audit_buffer *ab;
> > + struct audit_contid *cont;
> > + bool first = true;
> > +
> > + /* Generate AUDIT_CONTAINER record with container ID CSV list */
> > + ab = audit_log_start(context, GFP_ATOMIC, AUDIT_CONTAINER);
> > + if (!ab) {
> > + audit_log_lost("out of memory in audit_log_netns_contid_list");
> > + return;
> > + }
> > + audit_log_format(ab, "contid=");
> > + spin_lock(lock);
> > + list_for_each_entry(cont, audit_get_netns_contid_list(net), list) {
> > + if (!first)
> > + audit_log_format(ab, ",");
> > + audit_log_format(ab, "%llu", cont->id);
> > + first = false;
> > + }
> > + spin_unlock(lock);
>
> This is looking like potentially a lot of work to be doing under a
> spinlock, not to mention a single spinlock that is shared across CPUs.
> Considering that I expect changes to the list to be somewhat
> infrequent, this might be a good candidate for a RCU based locking
> scheme.

Would something like this look reasonable?
(This is on top of a patch to make contid list lock and unlock
functions.)

diff --git a/include/linux/audit.h b/include/linux/audit.h
index be5d6eb..9428fc3 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -92,6 +92,7 @@ struct audit_contid {
struct list_head list;
u64 id;
refcount_t refcount;
+ struct rcu_head rcu;
};

extern int is_audit_feature_set(int which);
diff --git a/kernel/audit.c b/kernel/audit.c
index d5b58163..6f84c25 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -106,7 +106,6 @@
struct audit_net {
struct sock *sk;
struct list_head contid_list;
- spinlock_t contid_list_lock;
};

/**
@@ -327,26 +326,6 @@ struct list_head *audit_get_netns_contid_list(const struct net *net)
return &aunet->contid_list;
}

-static int audit_netns_contid_lock(const struct net *net)
-{
- struct audit_net *aunet = net_generic(net, audit_net_id);
-
- if (!aunet)
- return -EINVAL;
- spin_lock(aunet->contid_list_lock);
- return 0;
-}
-
-static int audit_netns_contid_unlock(const struct net *net)
-{
- struct audit_net *aunet = net_generic(net, audit_net_id);
-
- if (!aunet)
- return -EINVAL;
- spin_unlock(aunet->contid_list_lock);
- return 0;
-}
-
void audit_netns_contid_add(struct net *net, u64 contid)
{
struct list_head *contid_list = audit_get_netns_contid_list(net);
@@ -354,10 +333,9 @@ void audit_netns_contid_add(struct net *net, u64 contid)

if (!audit_contid_valid(contid))
return;
- if (audit_netns_contid_lock(net))
- return;
+ rcu_read_lock();
if (!list_empty(contid_list))
- list_for_each_entry(cont, contid_list, list)
+ list_for_each_entry_rcu(cont, contid_list, list)
if (cont->id == contid) {
refcount_inc(&cont->refcount);
goto out;
@@ -367,10 +345,16 @@ void audit_netns_contid_add(struct net *net, u64 contid)
INIT_LIST_HEAD(&cont->list);
cont->id = contid;
refcount_set(&cont->refcount, 1);
- list_add(&cont->list, contid_list);
+ list_add_rcu(&cont->list, contid_list);
}
out:
- audit_netns_contid_unlock(net);
+ rcu_read_unlock();
+}
+
+audit_free_contid_rcu(struct rcu_head *head) {
+ struct audit_contid *contid = container_of(head, struct audit_contid, rcu);
+
+ kfree(contid);
}

void audit_netns_contid_del(struct net *net, u64 contid)
@@ -380,17 +364,16 @@ void audit_netns_contid_del(struct net *net, u64 contid)

if (!audit_contid_valid(contid))
return;
- if (audit_netns_contid_lock(net))
- return;
+ rcu_read_lock();
if (!list_empty(contid_list))
- list_for_each_entry(cont, contid_list, list)
+ list_for_each_entry_rcu(cont, contid_list, list)
if (cont->id == contid) {
- list_del(&cont->list);
+ list_del_rcu(&cont->list);
if (refcount_dec_and_test(&cont->refcount))
- kfree(cont);
+ call_rcu(&cont->rcu, audit_free_contid_rcu);
break;
}
- audit_netns_contid_unlock(net);
+ rcu_read_unlock();
}

void audit_switch_task_namespaces(struct nsproxy *ns, struct task_struct *p)
@@ -418,15 +401,14 @@ void audit_log_netns_contid_list(struct net *net, struct audit_context *context)
return;
}
audit_log_format(ab, "ref=net contid=");
- if (audit_netns_contid_lock(net))
- return;
- list_for_each_entry(cont, audit_get_netns_contid_list(net), list) {
+ rcu_read_lock();
+ list_for_each_entry_rcu(cont, audit_get_netns_contid_list(net), list) {
if (!first)
audit_log_format(ab, ",");
audit_log_format(ab, "%llu", cont->id);
first = false;
}
- audit_netns_contid_unlock(net);
+ rcu_read_unlock();
audit_log_end(ab);
}
EXPORT_SYMBOL(audit_log_netns_contid_list);
@@ -1674,7 +1656,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);
@@ -1684,8 +1665,6 @@ static int __net_init audit_net_init(struct net *net)
}
aunet->sk->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT;
INIT_LIST_HEAD(&aunet->contid_list);
- spin_lock_init(&aunet->contid_list_lock);
-
return 0;
}

>
> > + audit_log_end(ab);
> > +}
> > +EXPORT_SYMBOL(audit_log_netns_contid_list);
> >
> > void audit_panic(const char *message)
> > {
> > switch (audit_failure) {
> > diff --git a/net/netfilter/xt_AUDIT.c b/net/netfilter/xt_AUDIT.c
> > index af883f1..44fac3f 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,12 @@ 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;
> > }
> >
>
> --
> paul moore
> http://www.paul-moore.com

- RGB

--
Richard Guy Briggs <[email protected]>
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

2018-10-31 21:19:46

by Richard Guy Briggs

[permalink] [raw]
Subject: Re: [PATCH ghak90 (was ghak32) V4 06/10] audit: add containerid support for tty_audit

On 2018-10-19 19:17, Paul Moore wrote:
> On Sun, Aug 5, 2018 at 4:33 AM Richard Guy Briggs <[email protected]> wrote:
> > Add audit container identifier auxiliary record to tty logging rule
> > event standalone records.
> >
> > Signed-off-by: Richard Guy Briggs <[email protected]>
> > Acked-by: Serge Hallyn <[email protected]>
> > ---
> > drivers/tty/tty_audit.c | 5 ++++-
> > 1 file changed, 4 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/tty/tty_audit.c b/drivers/tty/tty_audit.c
> > index 50f567b..3e21477 100644
> > --- a/drivers/tty/tty_audit.c
> > +++ b/drivers/tty/tty_audit.c
> > @@ -66,8 +66,9 @@ static void tty_audit_log(const char *description, dev_t dev,
> > uid_t uid = from_kuid(&init_user_ns, task_uid(tsk));
> > uid_t loginuid = from_kuid(&init_user_ns, audit_get_loginuid(tsk));
> > unsigned int sessionid = audit_get_sessionid(tsk);
> > + struct audit_context *context = audit_alloc_local(GFP_KERNEL);
> >
> > - ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_TTY);
> > + ab = audit_log_start(context, GFP_KERNEL, AUDIT_TTY);
> > if (ab) {
> > char name[sizeof(tsk->comm)];
> >
> > @@ -80,6 +81,8 @@ static void tty_audit_log(const char *description, dev_t dev,
> > audit_log_n_hex(ab, data, size);
> > audit_log_end(ab);
> > }
> > + audit_log_contid(context, "tty", audit_get_contid(tsk));
> > + audit_free_context(context);
> > }
>
> Since I never polished up my task_struct/current fix patch enough to
> get it past RFC status during this development window (new job, stolen
> laptop, etc.) *and* it looks like you are going to need at least one
> more respin of this patchset, go ahead and fix this patch to use
> current instead of generating a local context. I'll deal with the
> merge fallout if/when it happens.

Sure, I will switch it to current in the call to audit_get_contid().

The local context is a distinct issue. Like USER records, I prefer
local due to potential record volume, it is already trackable as far as
Steve is concerned, and if it is to be connected with the syscall
record, it should be linked to syscall records in a seperate new github
issue with its own patch. It accumulates events until the buffer is
flushed to a record, so the timestamp only represents the flush (usually
user "CR/enter").

> Local contexts are a last resort. If you ever find yourself writing
> code that generates a local context, you should first be 100% certain
> that the event is not the the result of a process initiated action (in
> which case it should take from the task's context).

Well, I'm 100% certain it is linked to a process, but so are USER
records that are already being discussed as the exception. This is
basically a keystroke logger (that has a flag to omit passwords).

> paul moore

- RGB

--
Richard Guy Briggs <[email protected]>
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

2018-11-01 18:51:11

by Richard Guy Briggs

[permalink] [raw]
Subject: Re: [PATCH ghak90 (was ghak32) V4 05/10] audit: add support for non-syscall auxiliary records

On 2018-10-19 19:17, Paul Moore wrote:
> On Sun, Aug 5, 2018 at 4:33 AM Richard Guy Briggs <[email protected]> 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 <[email protected]>
> > Acked-by: Serge Hallyn <[email protected]>
> > ---
> > include/linux/audit.h | 8 ++++++++
> > kernel/audit.h | 1 +
> > kernel/auditsc.c | 33 ++++++++++++++++++++++++++++-----
> > 3 files changed, 37 insertions(+), 5 deletions(-)
>
> I'm not in love with the local flag, and the whole local context in
> general, but that's a larger discussion and not something I want to
> force on this patchset; we can fix it later.

I understand your reasoning to combine it so that if one patch gets
backported then both do, or if one gets reverted both do, but I really
prefer them seperate for similar reasons if there is more than one user.

> I think this patch looks fine, but it seems a bit odd standalone; it's
> almost always better to include new capabilities/functions in the same
> patch as the user. Since the only user is the networking bits, it
> might make more sense to fold this patch into that one.

It was kept seperate due to tty_audit usage. See my reasoning for patch
6, but I'm willing to negotiate if that merits an exception like the
USER records do.

> > diff --git a/include/linux/audit.h b/include/linux/audit.h
> > index 4f514ed..1f340ad 100644
> > --- a/include/linux/audit.h
> > +++ b/include/linux/audit.h
> > @@ -234,7 +234,9 @@ struct audit_task_info {
> > extern struct audit_task_info init_struct_audit;
> > extern void __init audit_task_init(void);
> > extern int audit_alloc(struct task_struct *task);
> > +extern struct audit_context *audit_alloc_local(gfp_t gfpflags);
> > extern void audit_free(struct task_struct *task);
> > +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);
> > @@ -495,6 +497,12 @@ static inline int audit_alloc(struct task_struct *task)
> > {
> > return 0;
> > }
> > +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_free(struct task_struct *task)
> > { }
> > static inline void audit_syscall_entry(int major, unsigned long a0,
> > diff --git a/kernel/audit.h b/kernel/audit.h
> > index 1cf1c35..a6d00a5 100644
> > --- a/kernel/audit.h
> > +++ b/kernel/audit.h
> > @@ -110,6 +110,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 cdb24cf..7627f21 100644
> > --- a/kernel/auditsc.c
> > +++ b/kernel/auditsc.c
> > @@ -913,11 +913,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;
> > @@ -970,7 +972,8 @@ int audit_alloc(struct task_struct *tsk)
> > return 0;
> > }
> >
> > - if (!(context = audit_alloc_context(state))) {
> > + context = audit_alloc_context(state, GFP_KERNEL);
> > + if (!(context)) {
> > tsk->audit = NULL;
> > kmem_cache_free(audit_task_cache, info);
> > kfree(key);
> > @@ -991,8 +994,27 @@ struct audit_task_info init_struct_audit = {
> > .ctx = NULL,
> > };
> >
> > -static inline void audit_free_context(struct audit_context *context)
> > +struct audit_context *audit_alloc_local(gfp_t gfpflags)
> > {
> > + struct audit_context *context;
> > +
> > + if (!audit_ever_enabled)
> > + return NULL; /* Return if not auditing. */
> > +
> > + context = audit_alloc_context(AUDIT_RECORD_CONTEXT, gfpflags);
> > + if (!context)
> > + return NULL;
> > + context->serial = audit_serial();
> > + context->ctime = current_kernel_time64();
> > + context->local = true;
> > + 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);
> > @@ -1002,6 +1024,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,
> > @@ -2024,7 +2047,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();
>
> --
> paul moore
> http://www.paul-moore.com

- RGB

--
Richard Guy Briggs <[email protected]>
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

2018-11-01 22:09:04

by Richard Guy Briggs

[permalink] [raw]
Subject: Re: [PATCH ghak90 (was ghak32) V4 01/10] audit: collect audit task parameters

On 2018-10-19 19:15, Paul Moore wrote:
> On Sun, Aug 5, 2018 at 4:32 AM Richard Guy Briggs <[email protected]> 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.
> >
> > See: https://github.com/linux-audit/audit-kernel/issues/81
> >
> > Signed-off-by: Richard Guy Briggs <[email protected]>
> > ---
> > include/linux/audit.h | 34 ++++++++++++++++++++++++----------
> > include/linux/sched.h | 5 +----
> > init/init_task.c | 3 +--
> > init/main.c | 2 ++
> > kernel/auditsc.c | 51 ++++++++++++++++++++++++++++++++++++++++++---------
> > kernel/fork.c | 4 +++-
> > 6 files changed, 73 insertions(+), 26 deletions(-)
>
> ...
>
> > diff --git a/include/linux/audit.h b/include/linux/audit.h
> > index 9334fbe..8964332 100644
> > --- a/include/linux/audit.h
> > +++ b/include/linux/audit.h
> > @@ -219,8 +219,15 @@ static inline void audit_log_task_info(struct audit_buffer *ab,
> >
> > /* These are defined in auditsc.c */
> > /* Public API */
> > +struct audit_task_info {
> > + kuid_t loginuid;
> > + unsigned int sessionid;
> > + struct audit_context *ctx;
> > +};
>
> ...
>
> > diff --git a/include/linux/sched.h b/include/linux/sched.h
> > index 87bf02d..e117272 100644
> > --- a/include/linux/sched.h
> > +++ b/include/linux/sched.h
> > @@ -873,10 +872,8 @@ struct task_struct {
> >
> > struct callback_head *task_works;
> >
> > - struct audit_context *audit_context;
> > #ifdef CONFIG_AUDITSYSCALL
> > - kuid_t loginuid;
> > - unsigned int sessionid;
> > + struct audit_task_info *audit;
> > #endif
> > struct seccomp seccomp;
>
> Prior to this patch audit_context was available regardless of
> CONFIG_AUDITSYSCALL, after this patch the corresponding audit_context
> is only available when CONFIG_AUDITSYSCALL is defined.

This was intentional since audit_context is not used when AUDITSYSCALL is
disabled. audit_alloc() was stubbed in that case to return 0. audit_context()
returned NULL.

The fact that audit_context was still present in struct task_struct was an
oversight in the two patches already accepted:
("audit: use inline function to get audit context")
("audit: use inline function to get audit context")
that failed to hide or remove it from struct task_struct when it was no longer
relevant.

The 0-day kbuildbot was happy and it tests many configs.

On further digging, loginuid and sessionid (and audit_log_session_info) should
be part of CONFIG_AUDIT scope and not CONFIG_AUDITSYSCALL since it is used in
CONFIG_CHANGE, ANOM_LINK, FEATURE_CHANGE(, INTEGRITY_RULE), none of which are
otherwise dependent on AUDITSYSCALL.

Looking ahead, contid should be treated like loginuid and sessionid, which are
currently only available when syscall auditting is.

Converting records from standalone to syscall and checking audit_dummy_context
changes the nature of CONFIG_AUDIT/!CONFIG_AUDITSYSCALL separation.
eg: ANOM_LINK accompanied by PATH record (which needed CWD addition to be
complete anyways)

> > diff --git a/init/main.c b/init/main.c
> > index 3b4ada1..6aba171 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>
> > @@ -721,6 +722,7 @@ asmlinkage __visible void __init start_kernel(void)
> > nsfs_init();
> > cpuset_init();
> > cgroup_init();
> > + audit_task_init();
> > taskstats_init_early();
> > delayacct_init();
>
> It seems like we would need either init_struct_audit or
> audit_task_init(), but not both, yes?

One sets initial values of init task via an included struct, other makes a call
to create the kmem cache. Both seem appropriate to me unless we move the
initialization from a struct to assignments in audit_task_init(), but I'm not
that comfortable separating the audit init values from the rest of the
task_struct init task initializers (though there are other subsystems that need
to do so dynamically).

> > diff --git a/kernel/auditsc.c b/kernel/auditsc.c
> > index fb20746..88779a7 100644
> > --- a/kernel/auditsc.c
> > +++ b/kernel/auditsc.c
> > @@ -841,7 +841,7 @@ static inline struct audit_context *audit_take_context(struct task_struct *tsk,
> > int return_valid,
> > long return_code)
> > {
> > - struct audit_context *context = tsk->audit_context;
> > + struct audit_context *context = tsk->audit->ctx;
> >
> > if (!context)
> > return NULL;
> > @@ -926,6 +926,15 @@ static inline struct audit_context *audit_alloc_context(enum audit_state state)
> > return context;
> > }
> >
> > +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);
> > +}
>
> This is somewhat related to the CONFIG_AUDITSYSCALL comment above, but
> since the audit_task_info contains generic audit state (not just
> syscall related state), it seems like this, and the audit_task_info
> accessors/helpers, should live in kernel/audit.c.

Well, in fact it was only containing syscall related state.

> There are probably a few other things that should move to
> kernel/audit.c too, e.g. audit_alloc(). Have you verified that this
> builds/runs correctly on architectures that define CONFIG_AUDIT but
> not CONFIG_AUDITSYSCALL?

I was under the mistaken impression that all this went away and wondered why
not just rip out the AUDITSYSCALL config option, but that was not completely
solved by cb74ed278f80 ("audit: always enable syscall auditing when supported
and audit is enabled").
I vaguely knew that AUDITSYSCALL was not implemented on all platforms but that
a number were expunged recently from mainline. It turns out that 5-10+ remain.

> > /**
> > * audit_alloc - allocate an audit context block for a task
> > * @tsk: task
> > @@ -940,17 +949,28 @@ int audit_alloc(struct task_struct *tsk)
> > struct audit_context *context;
> > enum audit_state state;
> > char *key = NULL;
> > + struct audit_task_info *info;
> > +
> > + info = kmem_cache_zalloc(audit_task_cache, GFP_KERNEL);
> > + if (!info)
> > + return -ENOMEM;
> > + info->loginuid = audit_get_loginuid(current);
> > + info->sessionid = audit_get_sessionid(current);
> > + tsk->audit = info;
> >
> > if (likely(!audit_ever_enabled))
> > return 0; /* Return if not auditing. */
>
> I don't view this as necessary for initial acceptance, and
> synchronization/locking might render this undesirable, but it would be
> curious to see if we could do something clever with refcnts and
> copy-on-write to minimize the number of kmem_cache objects in use in
> the !audit_ever_enabled (and possibly the AUDIT_DISABLED) case.
>
> > state = audit_filter_task(tsk, &key);
> > if (state == AUDIT_DISABLED) {
> > + audit_set_context(tsk, NULL);
>
> It's already NULL, isn't it?

Yes, holdover from copying audit_task_info as a struct from the parent task.
Fixed.

> > clear_tsk_thread_flag(tsk, TIF_SYSCALL_AUDIT);
> > return 0;
> > }
> >
> > if (!(context = audit_alloc_context(state))) {
> > + tsk->audit = NULL;
> > + kmem_cache_free(audit_task_cache, info);
> > kfree(key);
> > audit_log_lost("out of memory in audit_alloc");
> > return -ENOMEM;
> > @@ -962,6 +982,12 @@ int audit_alloc(struct task_struct *tsk)
> > return 0;
> > }
> >
> > +struct audit_task_info init_struct_audit = {
> > + .loginuid = INVALID_UID,
> > + .sessionid = AUDIT_SID_UNSET,
> > + .ctx = NULL,
> > +};
> > +
> > static inline void audit_free_context(struct audit_context *context)
> > {
> > audit_free_names(context);
>
> paul moore

- RGB

--
Richard Guy Briggs <[email protected]>
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

2018-12-28 01:37:30

by Richard Guy Briggs

[permalink] [raw]
Subject: Re: [PATCH ghak90 (was ghak32) V4 09/10] audit: NETFILTER_PKT: record each container ID associated with a netNS

On 2018-10-31 15:30, Richard Guy Briggs wrote:
> On 2018-10-19 19:18, Paul Moore wrote:
> > On Sun, Aug 5, 2018 at 4:33 AM Richard Guy Briggs <[email protected]> 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 <[email protected]>
> > > ---
> > > include/linux/audit.h | 5 +++++
> > > kernel/audit.c | 26 ++++++++++++++++++++++++++
> > > net/netfilter/xt_AUDIT.c | 12 ++++++++++--
> > > 3 files changed, 41 insertions(+), 2 deletions(-)
> >
> > ...
> >
> > > diff --git a/include/linux/audit.h b/include/linux/audit.h
> > > index 9a02095..8755f4d 100644
> > > --- a/include/linux/audit.h
> > > +++ b/include/linux/audit.h
> > > @@ -169,6 +169,8 @@ extern int audit_log_contid(struct audit_context *context,
> > > 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 void audit_log_netns_contid_list(struct net *net,
> > > + struct audit_context *context);
> > >
> > > extern int audit_update_lsm_rules(void);
> > >
> > > @@ -228,6 +230,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 c5fed3b..b23711c 100644
> > > --- a/kernel/audit.c
> > > +++ b/kernel/audit.c
> > > @@ -392,6 +392,32 @@ void audit_switch_task_namespaces(struct nsproxy *ns, struct task_struct *p)
> > > audit_netns_contid_add(new->net_ns, contid);
> > > }
> > >
> > > +void audit_log_netns_contid_list(struct net *net, struct audit_context *context)
> > > +{
> > > + spinlock_t *lock = audit_get_netns_contid_list_lock(net);
> > > + struct audit_buffer *ab;
> > > + struct audit_contid *cont;
> > > + bool first = true;
> > > +
> > > + /* Generate AUDIT_CONTAINER record with container ID CSV list */
> > > + ab = audit_log_start(context, GFP_ATOMIC, AUDIT_CONTAINER);
> > > + if (!ab) {
> > > + audit_log_lost("out of memory in audit_log_netns_contid_list");
> > > + return;
> > > + }
> > > + audit_log_format(ab, "contid=");
> > > + spin_lock(lock);
> > > + list_for_each_entry(cont, audit_get_netns_contid_list(net), list) {
> > > + if (!first)
> > > + audit_log_format(ab, ",");
> > > + audit_log_format(ab, "%llu", cont->id);
> > > + first = false;
> > > + }
> > > + spin_unlock(lock);
> >
> > This is looking like potentially a lot of work to be doing under a
> > spinlock, not to mention a single spinlock that is shared across CPUs.
> > Considering that I expect changes to the list to be somewhat
> > infrequent, this might be a good candidate for a RCU based locking
> > scheme.
>
> Would something like this look reasonable?
> (This is on top of a patch to make contid list lock and unlock
> functions.)

Paul, could I please get your review on this locking approach I proposed
almost two months ago so I can be more reassured that it won't be an
issue in v5? Thanks!

> diff --git a/include/linux/audit.h b/include/linux/audit.h
> index be5d6eb..9428fc3 100644
> --- a/include/linux/audit.h
> +++ b/include/linux/audit.h
> @@ -92,6 +92,7 @@ struct audit_contid {
> struct list_head list;
> u64 id;
> refcount_t refcount;
> + struct rcu_head rcu;
> };
>
> extern int is_audit_feature_set(int which);
> diff --git a/kernel/audit.c b/kernel/audit.c
> index d5b58163..6f84c25 100644
> --- a/kernel/audit.c
> +++ b/kernel/audit.c
> @@ -106,7 +106,6 @@
> struct audit_net {
> struct sock *sk;
> struct list_head contid_list;
> - spinlock_t contid_list_lock;
> };
>
> /**
> @@ -327,26 +326,6 @@ struct list_head *audit_get_netns_contid_list(const struct net *net)
> return &aunet->contid_list;
> }
>
> -static int audit_netns_contid_lock(const struct net *net)
> -{
> - struct audit_net *aunet = net_generic(net, audit_net_id);
> -
> - if (!aunet)
> - return -EINVAL;
> - spin_lock(aunet->contid_list_lock);
> - return 0;
> -}
> -
> -static int audit_netns_contid_unlock(const struct net *net)
> -{
> - struct audit_net *aunet = net_generic(net, audit_net_id);
> -
> - if (!aunet)
> - return -EINVAL;
> - spin_unlock(aunet->contid_list_lock);
> - return 0;
> -}
> -
> void audit_netns_contid_add(struct net *net, u64 contid)
> {
> struct list_head *contid_list = audit_get_netns_contid_list(net);
> @@ -354,10 +333,9 @@ void audit_netns_contid_add(struct net *net, u64 contid)
>
> if (!audit_contid_valid(contid))
> return;
> - if (audit_netns_contid_lock(net))
> - return;
> + rcu_read_lock();
> if (!list_empty(contid_list))
> - list_for_each_entry(cont, contid_list, list)
> + list_for_each_entry_rcu(cont, contid_list, list)
> if (cont->id == contid) {
> refcount_inc(&cont->refcount);
> goto out;
> @@ -367,10 +345,16 @@ void audit_netns_contid_add(struct net *net, u64 contid)
> INIT_LIST_HEAD(&cont->list);
> cont->id = contid;
> refcount_set(&cont->refcount, 1);
> - list_add(&cont->list, contid_list);
> + list_add_rcu(&cont->list, contid_list);
> }
> out:
> - audit_netns_contid_unlock(net);
> + rcu_read_unlock();
> +}
> +
> +audit_free_contid_rcu(struct rcu_head *head) {
> + struct audit_contid *contid = container_of(head, struct audit_contid, rcu);
> +
> + kfree(contid);
> }
>
> void audit_netns_contid_del(struct net *net, u64 contid)
> @@ -380,17 +364,16 @@ void audit_netns_contid_del(struct net *net, u64 contid)
>
> if (!audit_contid_valid(contid))
> return;
> - if (audit_netns_contid_lock(net))
> - return;
> + rcu_read_lock();
> if (!list_empty(contid_list))
> - list_for_each_entry(cont, contid_list, list)
> + list_for_each_entry_rcu(cont, contid_list, list)
> if (cont->id == contid) {
> - list_del(&cont->list);
> + list_del_rcu(&cont->list);
> if (refcount_dec_and_test(&cont->refcount))
> - kfree(cont);
> + call_rcu(&cont->rcu, audit_free_contid_rcu);
> break;
> }
> - audit_netns_contid_unlock(net);
> + rcu_read_unlock();
> }
>
> void audit_switch_task_namespaces(struct nsproxy *ns, struct task_struct *p)
> @@ -418,15 +401,14 @@ void audit_log_netns_contid_list(struct net *net, struct audit_context *context)
> return;
> }
> audit_log_format(ab, "ref=net contid=");
> - if (audit_netns_contid_lock(net))
> - return;
> - list_for_each_entry(cont, audit_get_netns_contid_list(net), list) {
> + rcu_read_lock();
> + list_for_each_entry_rcu(cont, audit_get_netns_contid_list(net), list) {
> if (!first)
> audit_log_format(ab, ",");
> audit_log_format(ab, "%llu", cont->id);
> first = false;
> }
> - audit_netns_contid_unlock(net);
> + rcu_read_unlock();
> audit_log_end(ab);
> }
> EXPORT_SYMBOL(audit_log_netns_contid_list);
> @@ -1674,7 +1656,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);
> @@ -1684,8 +1665,6 @@ static int __net_init audit_net_init(struct net *net)
> }
> aunet->sk->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT;
> INIT_LIST_HEAD(&aunet->contid_list);
> - spin_lock_init(&aunet->contid_list_lock);
> -
> return 0;
> }
>
> >
> > > + audit_log_end(ab);
> > > +}
> > > +EXPORT_SYMBOL(audit_log_netns_contid_list);
> > >
> > > void audit_panic(const char *message)
> > > {
> > > switch (audit_failure) {
> > > diff --git a/net/netfilter/xt_AUDIT.c b/net/netfilter/xt_AUDIT.c
> > > index af883f1..44fac3f 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,12 @@ 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;
> > > }
> > >
> >
> > --
> > paul moore
> > http://www.paul-moore.com
>
> - RGB
>
> --
> Richard Guy Briggs <[email protected]>
> 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
>
> --
> Linux-audit mailing list
> [email protected]
> https://www.redhat.com/mailman/listinfo/linux-audit

- RGB

--
Richard Guy Briggs <[email protected]>
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

2018-12-28 08:31:42

by Paul Moore

[permalink] [raw]
Subject: Re: [PATCH ghak90 (was ghak32) V4 09/10] audit: NETFILTER_PKT: record each container ID associated with a netNS

On Thu, Dec 27, 2018 at 10:34 AM Richard Guy Briggs <[email protected]> wrote:
> On 2018-10-31 15:30, Richard Guy Briggs wrote:
> > On 2018-10-19 19:18, Paul Moore wrote:
> > > On Sun, Aug 5, 2018 at 4:33 AM Richard Guy Briggs <[email protected]> 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 <[email protected]>
> > > > ---
> > > > include/linux/audit.h | 5 +++++
> > > > kernel/audit.c | 26 ++++++++++++++++++++++++++
> > > > net/netfilter/xt_AUDIT.c | 12 ++++++++++--
> > > > 3 files changed, 41 insertions(+), 2 deletions(-)
> > >
> > > ...
> > >
> > > > diff --git a/include/linux/audit.h b/include/linux/audit.h
> > > > index 9a02095..8755f4d 100644
> > > > --- a/include/linux/audit.h
> > > > +++ b/include/linux/audit.h
> > > > @@ -169,6 +169,8 @@ extern int audit_log_contid(struct audit_context *context,
> > > > 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 void audit_log_netns_contid_list(struct net *net,
> > > > + struct audit_context *context);
> > > >
> > > > extern int audit_update_lsm_rules(void);
> > > >
> > > > @@ -228,6 +230,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 c5fed3b..b23711c 100644
> > > > --- a/kernel/audit.c
> > > > +++ b/kernel/audit.c
> > > > @@ -392,6 +392,32 @@ void audit_switch_task_namespaces(struct nsproxy *ns, struct task_struct *p)
> > > > audit_netns_contid_add(new->net_ns, contid);
> > > > }
> > > >
> > > > +void audit_log_netns_contid_list(struct net *net, struct audit_context *context)
> > > > +{
> > > > + spinlock_t *lock = audit_get_netns_contid_list_lock(net);
> > > > + struct audit_buffer *ab;
> > > > + struct audit_contid *cont;
> > > > + bool first = true;
> > > > +
> > > > + /* Generate AUDIT_CONTAINER record with container ID CSV list */
> > > > + ab = audit_log_start(context, GFP_ATOMIC, AUDIT_CONTAINER);
> > > > + if (!ab) {
> > > > + audit_log_lost("out of memory in audit_log_netns_contid_list");
> > > > + return;
> > > > + }
> > > > + audit_log_format(ab, "contid=");
> > > > + spin_lock(lock);
> > > > + list_for_each_entry(cont, audit_get_netns_contid_list(net), list) {
> > > > + if (!first)
> > > > + audit_log_format(ab, ",");
> > > > + audit_log_format(ab, "%llu", cont->id);
> > > > + first = false;
> > > > + }
> > > > + spin_unlock(lock);
> > >
> > > This is looking like potentially a lot of work to be doing under a
> > > spinlock, not to mention a single spinlock that is shared across CPUs.
> > > Considering that I expect changes to the list to be somewhat
> > > infrequent, this might be a good candidate for a RCU based locking
> > > scheme.
> >
> > Would something like this look reasonable?
> > (This is on top of a patch to make contid list lock and unlock
> > functions.)
>
> Paul, could I please get your review on this locking approach I proposed
> almost two months ago so I can be more reassured that it won't be an
> issue in v5? Thanks!

I see that not much was learned from our last exchange. This is disappointing.

At this point you've exhausted my goodwill, and the "This is on top of
a patch to make contid list lock and unlock
functions" comment isn't clear to me at this moment so I'm going to
suggest you just post it as part of your next patchset revision so it
can be seen in the proper context. Based on a quick inspection it
doesn't seems like there is any mutual exclusion for the writers, but
perhaps this is part of the of "... on top of a patch ..." hand
waving; another reason to see the patch in proper context.

If you've read and understand everything under Documentation/RCU (the
checklist.txt can be helpful), it should be fine. If you haven't, you
should do so before posting the next iteration.

> > diff --git a/include/linux/audit.h b/include/linux/audit.h
> > index be5d6eb..9428fc3 100644
> > --- a/include/linux/audit.h
> > +++ b/include/linux/audit.h
> > @@ -92,6 +92,7 @@ struct audit_contid {
> > struct list_head list;
> > u64 id;
> > refcount_t refcount;
> > + struct rcu_head rcu;
> > };
> >
> > extern int is_audit_feature_set(int which);
> > diff --git a/kernel/audit.c b/kernel/audit.c
> > index d5b58163..6f84c25 100644
> > --- a/kernel/audit.c
> > +++ b/kernel/audit.c
> > @@ -106,7 +106,6 @@
> > struct audit_net {
> > struct sock *sk;
> > struct list_head contid_list;
> > - spinlock_t contid_list_lock;
> > };
> >
> > /**
> > @@ -327,26 +326,6 @@ struct list_head *audit_get_netns_contid_list(const struct net *net)
> > return &aunet->contid_list;
> > }
> >
> > -static int audit_netns_contid_lock(const struct net *net)
> > -{
> > - struct audit_net *aunet = net_generic(net, audit_net_id);
> > -
> > - if (!aunet)
> > - return -EINVAL;
> > - spin_lock(aunet->contid_list_lock);
> > - return 0;
> > -}
> > -
> > -static int audit_netns_contid_unlock(const struct net *net)
> > -{
> > - struct audit_net *aunet = net_generic(net, audit_net_id);
> > -
> > - if (!aunet)
> > - return -EINVAL;
> > - spin_unlock(aunet->contid_list_lock);
> > - return 0;
> > -}
> > -
> > void audit_netns_contid_add(struct net *net, u64 contid)
> > {
> > struct list_head *contid_list = audit_get_netns_contid_list(net);
> > @@ -354,10 +333,9 @@ void audit_netns_contid_add(struct net *net, u64 contid)
> >
> > if (!audit_contid_valid(contid))
> > return;
> > - if (audit_netns_contid_lock(net))
> > - return;
> > + rcu_read_lock();
> > if (!list_empty(contid_list))
> > - list_for_each_entry(cont, contid_list, list)
> > + list_for_each_entry_rcu(cont, contid_list, list)
> > if (cont->id == contid) {
> > refcount_inc(&cont->refcount);
> > goto out;
> > @@ -367,10 +345,16 @@ void audit_netns_contid_add(struct net *net, u64 contid)
> > INIT_LIST_HEAD(&cont->list);
> > cont->id = contid;
> > refcount_set(&cont->refcount, 1);
> > - list_add(&cont->list, contid_list);
> > + list_add_rcu(&cont->list, contid_list);
> > }
> > out:
> > - audit_netns_contid_unlock(net);
> > + rcu_read_unlock();
> > +}
> > +
> > +audit_free_contid_rcu(struct rcu_head *head) {
> > + struct audit_contid *contid = container_of(head, struct audit_contid, rcu);
> > +
> > + kfree(contid);
> > }
> >
> > void audit_netns_contid_del(struct net *net, u64 contid)
> > @@ -380,17 +364,16 @@ void audit_netns_contid_del(struct net *net, u64 contid)
> >
> > if (!audit_contid_valid(contid))
> > return;
> > - if (audit_netns_contid_lock(net))
> > - return;
> > + rcu_read_lock();
> > if (!list_empty(contid_list))
> > - list_for_each_entry(cont, contid_list, list)
> > + list_for_each_entry_rcu(cont, contid_list, list)
> > if (cont->id == contid) {
> > - list_del(&cont->list);
> > + list_del_rcu(&cont->list);
> > if (refcount_dec_and_test(&cont->refcount))
> > - kfree(cont);
> > + call_rcu(&cont->rcu, audit_free_contid_rcu);
> > break;
> > }
> > - audit_netns_contid_unlock(net);
> > + rcu_read_unlock();
> > }
> >
> > void audit_switch_task_namespaces(struct nsproxy *ns, struct task_struct *p)
> > @@ -418,15 +401,14 @@ void audit_log_netns_contid_list(struct net *net, struct audit_context *context)
> > return;
> > }
> > audit_log_format(ab, "ref=net contid=");
> > - if (audit_netns_contid_lock(net))
> > - return;
> > - list_for_each_entry(cont, audit_get_netns_contid_list(net), list) {
> > + rcu_read_lock();
> > + list_for_each_entry_rcu(cont, audit_get_netns_contid_list(net), list) {
> > if (!first)
> > audit_log_format(ab, ",");
> > audit_log_format(ab, "%llu", cont->id);
> > first = false;
> > }
> > - audit_netns_contid_unlock(net);
> > + rcu_read_unlock();
> > audit_log_end(ab);
> > }
> > EXPORT_SYMBOL(audit_log_netns_contid_list);
> > @@ -1674,7 +1656,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);
> > @@ -1684,8 +1665,6 @@ static int __net_init audit_net_init(struct net *net)
> > }
> > aunet->sk->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT;
> > INIT_LIST_HEAD(&aunet->contid_list);
> > - spin_lock_init(&aunet->contid_list_lock);
> > -
> > return 0;
> > }
> >
> > >
> > > > + audit_log_end(ab);
> > > > +}
> > > > +EXPORT_SYMBOL(audit_log_netns_contid_list);
> > > >
> > > > void audit_panic(const char *message)
> > > > {
> > > > switch (audit_failure) {
> > > > diff --git a/net/netfilter/xt_AUDIT.c b/net/netfilter/xt_AUDIT.c
> > > > index af883f1..44fac3f 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,12 @@ 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;
> > > > }
> > > >
> > >
> > > --
> > > paul moore
> > > http://www.paul-moore.com
> >
> > - RGB
> >
> > --
> > Richard Guy Briggs <[email protected]>
> > 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
> >
> > --
> > Linux-audit mailing list
> > [email protected]
> > https://www.redhat.com/mailman/listinfo/linux-audit
>
> - RGB
>
> --
> Richard Guy Briggs <[email protected]>
> 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



--
paul moore
http://www.paul-moore.com

2019-01-03 22:12:28

by Guenter Roeck

[permalink] [raw]
Subject: Re: [PATCH ghak90 (was ghak32) V4 00/10] audit: implement container identifier

Hi,

On Tue, Jul 31, 2018 at 04:07:35PM -0400, Richard Guy Briggs wrote:
> Implement kernel audit container identifier.
>

I don't see a follow-up submission of this patch series. Has it been abandoned,
or do I use the wrong search terms ?

Thanks,
Guenter

> This patchset is a fourth based on the proposal document (V3)
> posted:
> https://www.redhat.com/archives/linux-audit/2018-January/msg00014.html
>
> The first patch is the last patch from ghak81 that is included here as a
> convenience.
>
> 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 the auxiliary record AUDIT_CONTAINER if an
> audit container identifier is identifiable with an event. This patch
> requires userspace support for proper type display.
>
> The 4th adds signal and ptrace support.
>
> The 5th creates a local audit context to be able to bind a standalone
> record with a locally created auxiliary record.
>
> The 6th patch adds audit container identifier records to the tty
> standalone record.
>
> The 7th 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 8th adds network namespace audit container identifier labelling
> based on member tasks' audit container identifier labels.
>
> The 9th adds audit container identifier support to standalone netfilter
> records that don't have a task context and lists each container to which
> that net namespace belongs.
>
> The 10th implements reading the audit container identifier from the proc
> filesystem for debugging. This patch isn't planned for upstream
> inclusion.
>
>
> Example: Set an audit container identifier of 123456 to the "sleep" task:
>
> sleep 2&
> child=$!
> echo 123456 > /proc/$child/audit_containerid; echo $?
> ausearch -ts recent -m container
> echo child:$child contid:$( cat /proc/$child/audit_containerid)
>
> This should produce a record such as:
>
> type=CONTAINER_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 msg=audit(2018-06-06 12:46:31.707:26953) : op=task contid=123459
> type=PROCTITLE msg=audit(2018-06-06 12:46:31.707:26953) : proctitle=perl -e sleep 1; open(my $tmpfile, '>', "/tmp/tmpcontainerid"); close($tmpfile);
> type=PATH msg=audit(2018-06-06 12:46:31.707:26953) : item=1 name=/tmp/tmpcontainerid inode=25656 dev=00:26 mode=file,644 ouid=root ogid=root rdev=00:00 obj=unconfined_u:object_r:user_tmp_t:s0 nametype=CREATE cap_fp=none cap_fi=none cap_fe=0 cap_fver=0
> type=PATH msg=audit(2018-06-06 12:46:31.707:26953) : item=0 name=/tmp/ inode=8985 dev=00:26 mode=dir,sticky,777 ouid=root ogid=root rdev=00:00 obj=system_u:object_r:tmp_t:s0 nametype=PARENT cap_fp=none cap_fi=none cap_fe=0 cap_fver=0
> type=CWD msg=audit(2018-06-06 12:46:31.707:26953) : cwd=/root
> type=SYSCALL msg=audit(2018-06-06 12:46:31.707:26953) : arch=x86_64 syscall=openat success=yes exit=3 a0=0xffffffffffffff9c a1=0x5621f2b81900 a2=O_WRONLY|O_CREAT|O_TRUNC a3=0x1b6 items=2 ppid=628 pid=2232 auid=root uid=root gid=root euid=root suid=root fsuid=root egid=root sgid=root fsgid=root tty=ttyS0 ses=1 comm=perl exe=/usr/bin/perl subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 key=tmpcontainerid
>
>
> Includes: https://github.com/linux-audit/audit-kernel/issues/81
> See: https://github.com/linux-audit/audit-kernel/issues/90
> See: https://github.com/linux-audit/audit-userspace/issues/40
> See: https://github.com/linux-audit/audit-testsuite/issues/64
> See: https://github.com/linux-audit/audit-kernel/wiki/RFE-Audit-Container-ID
>
> Changelog:
>
> 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: log container info of syscalls
> audit: add containerid support for ptrace and signals
> audit: add support for non-syscall auxiliary records
> audit: add containerid support for tty_audit
> audit: add containerid filtering
> audit: add support for containerid to network namespaces
> audit: NETFILTER_PKT: record each container ID associated with a netNS
> debug audit: read container ID of a process
>
> drivers/tty/tty_audit.c | 5 +-
> fs/proc/base.c | 56 ++++++++++++++
> include/linux/audit.h | 95 ++++++++++++++++++++---
> include/linux/sched.h | 5 +-
> include/uapi/linux/audit.h | 8 +-
> init/init_task.c | 3 +-
> init/main.c | 2 +
> kernel/audit.c | 137 +++++++++++++++++++++++++++++++++
> kernel/audit.h | 4 +
> kernel/auditfilter.c | 47 ++++++++++++
> kernel/auditsc.c | 183 ++++++++++++++++++++++++++++++++++++++++-----
> kernel/fork.c | 4 +-
> kernel/nsproxy.c | 4 +
> net/netfilter/xt_AUDIT.c | 12 ++-
> 14 files changed, 526 insertions(+), 39 deletions(-)
>
> --
> 1.8.3.1
>

2019-01-03 23:39:35

by Richard Guy Briggs

[permalink] [raw]
Subject: Re: [PATCH ghak90 (was ghak32) V4 00/10] audit: implement container identifier

On 2019-01-03 08:15, Guenter Roeck wrote:
> Hi,
>
> On Tue, Jul 31, 2018 at 04:07:35PM -0400, Richard Guy Briggs wrote:
> > Implement kernel audit container identifier.
>
> I don't see a follow-up submission of this patch series. Has it been abandoned,
> or do I use the wrong search terms ?

Guenter, thanks for your interest in this patchset. I haven't
abandoned it. I've pushed some updates to my own (ill-publicized)
public git repo. This effort has been going on more than 5 years with 8
previous revisions trying to document task namespaces and deciding that
was insufficient.

For this patchset I waited 11.5 weeks (80 days, Jules Verne anyone?)
before the primary intended maintainer did the first review, then I
responded within 2 weeks with further questions and a followup patch
proposal and then waited another 8 weeks for any response before adding
another query for that followup patch proposal review at which point I
got a rude answer saying I had disappointed and exhausted the
maintainer's goodwill with some hints at how to proceed just before new
year's.

I'd be delighted with other upstream review to get other angles and to
take some of the load and responsibility off the primary maintainer.

I expect to submit a v5 within a week without having had those questions
directly answered, but with some ideas of what to check and verify
before I resubmit. Most of the changes have been sitting in that branch
for two months, already rebased one kernel version and will need
updating again.

> Thanks,
> Guenter
>
> > This patchset is a fourth based on the proposal document (V3)
> > posted:
> > https://www.redhat.com/archives/linux-audit/2018-January/msg00014.html
> >
> > The first patch is the last patch from ghak81 that is included here as a
> > convenience.
> >
> > 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 the auxiliary record AUDIT_CONTAINER if an
> > audit container identifier is identifiable with an event. This patch
> > requires userspace support for proper type display.
> >
> > The 4th adds signal and ptrace support.
> >
> > The 5th creates a local audit context to be able to bind a standalone
> > record with a locally created auxiliary record.
> >
> > The 6th patch adds audit container identifier records to the tty
> > standalone record.
> >
> > The 7th 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 8th adds network namespace audit container identifier labelling
> > based on member tasks' audit container identifier labels.
> >
> > The 9th adds audit container identifier support to standalone netfilter
> > records that don't have a task context and lists each container to which
> > that net namespace belongs.
> >
> > The 10th implements reading the audit container identifier from the proc
> > filesystem for debugging. This patch isn't planned for upstream
> > inclusion.
> >
> >
> > Example: Set an audit container identifier of 123456 to the "sleep" task:
> >
> > sleep 2&
> > child=$!
> > echo 123456 > /proc/$child/audit_containerid; echo $?
> > ausearch -ts recent -m container
> > echo child:$child contid:$( cat /proc/$child/audit_containerid)
> >
> > This should produce a record such as:
> >
> > type=CONTAINER_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 msg=audit(2018-06-06 12:46:31.707:26953) : op=task contid=123459
> > type=PROCTITLE msg=audit(2018-06-06 12:46:31.707:26953) : proctitle=perl -e sleep 1; open(my $tmpfile, '>', "/tmp/tmpcontainerid"); close($tmpfile);
> > type=PATH msg=audit(2018-06-06 12:46:31.707:26953) : item=1 name=/tmp/tmpcontainerid inode=25656 dev=00:26 mode=file,644 ouid=root ogid=root rdev=00:00 obj=unconfined_u:object_r:user_tmp_t:s0 nametype=CREATE cap_fp=none cap_fi=none cap_fe=0 cap_fver=0
> > type=PATH msg=audit(2018-06-06 12:46:31.707:26953) : item=0 name=/tmp/ inode=8985 dev=00:26 mode=dir,sticky,777 ouid=root ogid=root rdev=00:00 obj=system_u:object_r:tmp_t:s0 nametype=PARENT cap_fp=none cap_fi=none cap_fe=0 cap_fver=0
> > type=CWD msg=audit(2018-06-06 12:46:31.707:26953) : cwd=/root
> > type=SYSCALL msg=audit(2018-06-06 12:46:31.707:26953) : arch=x86_64 syscall=openat success=yes exit=3 a0=0xffffffffffffff9c a1=0x5621f2b81900 a2=O_WRONLY|O_CREAT|O_TRUNC a3=0x1b6 items=2 ppid=628 pid=2232 auid=root uid=root gid=root euid=root suid=root fsuid=root egid=root sgid=root fsgid=root tty=ttyS0 ses=1 comm=perl exe=/usr/bin/perl subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 key=tmpcontainerid
> >
> >
> > Includes: https://github.com/linux-audit/audit-kernel/issues/81
> > See: https://github.com/linux-audit/audit-kernel/issues/90
> > See: https://github.com/linux-audit/audit-userspace/issues/40
> > See: https://github.com/linux-audit/audit-testsuite/issues/64
> > See: https://github.com/linux-audit/audit-kernel/wiki/RFE-Audit-Container-ID
> >
> > Changelog:
> >
> > 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: log container info of syscalls
> > audit: add containerid support for ptrace and signals
> > audit: add support for non-syscall auxiliary records
> > audit: add containerid support for tty_audit
> > audit: add containerid filtering
> > audit: add support for containerid to network namespaces
> > audit: NETFILTER_PKT: record each container ID associated with a netNS
> > debug audit: read container ID of a process
> >
> > drivers/tty/tty_audit.c | 5 +-
> > fs/proc/base.c | 56 ++++++++++++++
> > include/linux/audit.h | 95 ++++++++++++++++++++---
> > include/linux/sched.h | 5 +-
> > include/uapi/linux/audit.h | 8 +-
> > init/init_task.c | 3 +-
> > init/main.c | 2 +
> > kernel/audit.c | 137 +++++++++++++++++++++++++++++++++
> > kernel/audit.h | 4 +
> > kernel/auditfilter.c | 47 ++++++++++++
> > kernel/auditsc.c | 183 ++++++++++++++++++++++++++++++++++++++++-----
> > kernel/fork.c | 4 +-
> > kernel/nsproxy.c | 4 +
> > net/netfilter/xt_AUDIT.c | 12 ++-
> > 14 files changed, 526 insertions(+), 39 deletions(-)
> >
> > --
> > 1.8.3.1
> >

- RGB

--
Richard Guy Briggs <[email protected]>
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

2019-01-03 23:58:49

by Guenter Roeck

[permalink] [raw]
Subject: Re: [PATCH ghak90 (was ghak32) V4 00/10] audit: implement container identifier

Hi Richard,

On Thu, Jan 03, 2019 at 12:36:13PM -0500, Richard Guy Briggs wrote:
> On 2019-01-03 08:15, Guenter Roeck wrote:
> > Hi,
> >
> > On Tue, Jul 31, 2018 at 04:07:35PM -0400, Richard Guy Briggs wrote:
> > > Implement kernel audit container identifier.
> >
> > I don't see a follow-up submission of this patch series. Has it been abandoned,
> > or do I use the wrong search terms ?
>
> Guenter, thanks for your interest in this patchset. I haven't
> abandoned it. I've pushed some updates to my own (ill-publicized)
> public git repo. This effort has been going on more than 5 years with 8

Oh man :-(. Not sure if I would be that patient.

Can you point me to your repository ?

> previous revisions trying to document task namespaces and deciding that
> was insufficient.
>

My interest is mostly thanks to having some of the patches of your series
in my incoming code review queue:

https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/1379654/3

As background, some of the patches in the series are needed by GCP (Google
Cloud Platform) as a prerequisite for some security features. Having to
maintain out-of-tree code is always a pain, even more so in a subsystem
related to security. So it would be quite useful to understand if we are
going to be stuck with this forever or if there is a change for the code
to find its way upstream. Also, it would be useful to know if there are
some upcoming changes/improvements which should be included in our version.

Thanks,
Guenter

> For this patchset I waited 11.5 weeks (80 days, Jules Verne anyone?)
> before the primary intended maintainer did the first review, then I
> responded within 2 weeks with further questions and a followup patch
> proposal and then waited another 8 weeks for any response before adding
> another query for that followup patch proposal review at which point I
> got a rude answer saying I had disappointed and exhausted the
> maintainer's goodwill with some hints at how to proceed just before new
> year's.
>
> I'd be delighted with other upstream review to get other angles and to
> take some of the load and responsibility off the primary maintainer.
>
> I expect to submit a v5 within a week without having had those questions
> directly answered, but with some ideas of what to check and verify
> before I resubmit. Most of the changes have been sitting in that branch
> for two months, already rebased one kernel version and will need
> updating again.
>
> > Thanks,
> > Guenter
> >
> > > This patchset is a fourth based on the proposal document (V3)
> > > posted:
> > > https://www.redhat.com/archives/linux-audit/2018-January/msg00014.html
> > >
> > > The first patch is the last patch from ghak81 that is included here as a
> > > convenience.
> > >
> > > 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 the auxiliary record AUDIT_CONTAINER if an
> > > audit container identifier is identifiable with an event. This patch
> > > requires userspace support for proper type display.
> > >
> > > The 4th adds signal and ptrace support.
> > >
> > > The 5th creates a local audit context to be able to bind a standalone
> > > record with a locally created auxiliary record.
> > >
> > > The 6th patch adds audit container identifier records to the tty
> > > standalone record.
> > >
> > > The 7th 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 8th adds network namespace audit container identifier labelling
> > > based on member tasks' audit container identifier labels.
> > >
> > > The 9th adds audit container identifier support to standalone netfilter
> > > records that don't have a task context and lists each container to which
> > > that net namespace belongs.
> > >
> > > The 10th implements reading the audit container identifier from the proc
> > > filesystem for debugging. This patch isn't planned for upstream
> > > inclusion.
> > >
> > >
> > > Example: Set an audit container identifier of 123456 to the "sleep" task:
> > >
> > > sleep 2&
> > > child=$!
> > > echo 123456 > /proc/$child/audit_containerid; echo $?
> > > ausearch -ts recent -m container
> > > echo child:$child contid:$( cat /proc/$child/audit_containerid)
> > >
> > > This should produce a record such as:
> > >
> > > type=CONTAINER_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 msg=audit(2018-06-06 12:46:31.707:26953) : op=task contid=123459
> > > type=PROCTITLE msg=audit(2018-06-06 12:46:31.707:26953) : proctitle=perl -e sleep 1; open(my $tmpfile, '>', "/tmp/tmpcontainerid"); close($tmpfile);
> > > type=PATH msg=audit(2018-06-06 12:46:31.707:26953) : item=1 name=/tmp/tmpcontainerid inode=25656 dev=00:26 mode=file,644 ouid=root ogid=root rdev=00:00 obj=unconfined_u:object_r:user_tmp_t:s0 nametype=CREATE cap_fp=none cap_fi=none cap_fe=0 cap_fver=0
> > > type=PATH msg=audit(2018-06-06 12:46:31.707:26953) : item=0 name=/tmp/ inode=8985 dev=00:26 mode=dir,sticky,777 ouid=root ogid=root rdev=00:00 obj=system_u:object_r:tmp_t:s0 nametype=PARENT cap_fp=none cap_fi=none cap_fe=0 cap_fver=0
> > > type=CWD msg=audit(2018-06-06 12:46:31.707:26953) : cwd=/root
> > > type=SYSCALL msg=audit(2018-06-06 12:46:31.707:26953) : arch=x86_64 syscall=openat success=yes exit=3 a0=0xffffffffffffff9c a1=0x5621f2b81900 a2=O_WRONLY|O_CREAT|O_TRUNC a3=0x1b6 items=2 ppid=628 pid=2232 auid=root uid=root gid=root euid=root suid=root fsuid=root egid=root sgid=root fsgid=root tty=ttyS0 ses=1 comm=perl exe=/usr/bin/perl subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 key=tmpcontainerid
> > >
> > >
> > > Includes: https://github.com/linux-audit/audit-kernel/issues/81
> > > See: https://github.com/linux-audit/audit-kernel/issues/90
> > > See: https://github.com/linux-audit/audit-userspace/issues/40
> > > See: https://github.com/linux-audit/audit-testsuite/issues/64
> > > See: https://github.com/linux-audit/audit-kernel/wiki/RFE-Audit-Container-ID
> > >
> > > Changelog:
> > >
> > > 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: log container info of syscalls
> > > audit: add containerid support for ptrace and signals
> > > audit: add support for non-syscall auxiliary records
> > > audit: add containerid support for tty_audit
> > > audit: add containerid filtering
> > > audit: add support for containerid to network namespaces
> > > audit: NETFILTER_PKT: record each container ID associated with a netNS
> > > debug audit: read container ID of a process
> > >
> > > drivers/tty/tty_audit.c | 5 +-
> > > fs/proc/base.c | 56 ++++++++++++++
> > > include/linux/audit.h | 95 ++++++++++++++++++++---
> > > include/linux/sched.h | 5 +-
> > > include/uapi/linux/audit.h | 8 +-
> > > init/init_task.c | 3 +-
> > > init/main.c | 2 +
> > > kernel/audit.c | 137 +++++++++++++++++++++++++++++++++
> > > kernel/audit.h | 4 +
> > > kernel/auditfilter.c | 47 ++++++++++++
> > > kernel/auditsc.c | 183 ++++++++++++++++++++++++++++++++++++++++-----
> > > kernel/fork.c | 4 +-
> > > kernel/nsproxy.c | 4 +
> > > net/netfilter/xt_AUDIT.c | 12 ++-
> > > 14 files changed, 526 insertions(+), 39 deletions(-)
> > >
> > > --
> > > 1.8.3.1
> > >
>
> - RGB
>
> --
> Richard Guy Briggs <[email protected]>
> 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

2019-01-04 00:24:44

by Paul Moore

[permalink] [raw]
Subject: Re: [PATCH ghak90 (was ghak32) V4 01/10] audit: collect audit task parameters

On Thu, Nov 1, 2018 at 6:07 PM Richard Guy Briggs <[email protected]> wrote:
&gt; On 2018-10-19 19:15, Paul Moore wrote:
&gt; &gt; On Sun, Aug 5, 2018 at 4:32 AM Richard Guy Briggs
<[email protected]> wrote:
&gt; &gt; &gt; The audit-related parameters in struct task_struct
should ideally be
&gt; &gt; &gt; collected together and accessed through a standard audit API.
&gt; &gt; &gt;
&gt; &gt; &gt; Collect the existing loginuid, sessionid and
audit_context together in a
&gt; &gt; &gt; new struct audit_task_info called "audit" in struct task_struct.
&gt; &gt; &gt;
&gt; &gt; &gt; Use kmem_cache to manage this pool of memory.
&gt; &gt; &gt; Un-inline audit_free() to be able to always recover that memory.
&gt; &gt; &gt;
&gt; &gt; &gt; See: https://github.com/linux-audit/audit-kernel/issues/81
&gt; &gt; &gt;
&gt; &gt; &gt; Signed-off-by: Richard Guy Briggs <[email protected]>
&gt; &gt; &gt; ---
&gt; &gt; &gt; include/linux/audit.h | 34 ++++++++++++++++++++++++----------
&gt; &gt; &gt; include/linux/sched.h | 5 +----
&gt; &gt; &gt; init/init_task.c | 3 +--
&gt; &gt; &gt; init/main.c | 2 ++
&gt; &gt; &gt; kernel/auditsc.c | 51
++++++++++++++++++++++++++++++++++++++++++---------
&gt; &gt; &gt; kernel/fork.c | 4 +++-
&gt; &gt; &gt; 6 files changed, 73 insertions(+), 26 deletions(-)
&gt; &gt;
&gt; &gt; ...
&gt; &gt;
&gt; &gt; &gt; diff --git a/include/linux/sched.h b/include/linux/sched.h
&gt; &gt; &gt; index 87bf02d..e117272 100644
&gt; &gt; &gt; --- a/include/linux/sched.h
&gt; &gt; &gt; +++ b/include/linux/sched.h
&gt; &gt; &gt; @@ -873,10 +872,8 @@ struct task_struct {
&gt; &gt; &gt;
&gt; &gt; &gt; struct callback_head *task_works;
&gt; &gt; &gt;
&gt; &gt; &gt; - struct audit_context *audit_context;
&gt; &gt; &gt; #ifdef CONFIG_AUDITSYSCALL
&gt; &gt; &gt; - kuid_t loginuid;
&gt; &gt; &gt; - unsigned int sessionid;
&gt; &gt; &gt; + struct audit_task_info *audit;
&gt; &gt; &gt; #endif
&gt; &gt; &gt; struct seccomp seccomp;
&gt; &gt;
&gt; &gt; Prior to this patch audit_context was available regardless of
&gt; &gt; CONFIG_AUDITSYSCALL, after this patch the corresponding audit_context
&gt; &gt; is only available when CONFIG_AUDITSYSCALL is defined.
&gt;
&gt; This was intentional since audit_context is not used when AUDITSYSCALL is
&gt; disabled. audit_alloc() was stubbed in that case to return 0.
audit_context()
&gt; returned NULL.
&gt;
&gt; The fact that audit_context was still present in struct task_struct was an
&gt; oversight in the two patches already accepted:
&gt; ("audit: use inline function to get audit context")
&gt; ("audit: use inline function to get audit context")
&gt; that failed to hide or remove it from struct task_struct when it
was no longer
&gt; relevant.

Okay, in that case let's pull this out and fix this separately from
the audit container ID patchset.

&gt; On further digging, loginuid and sessionid (and
audit_log_session_info) should
&gt; be part of CONFIG_AUDIT scope and not CONFIG_AUDITSYSCALL since
it is used in
&gt; CONFIG_CHANGE, ANOM_LINK, FEATURE_CHANGE(, INTEGRITY_RULE), none
of which are
&gt; otherwise dependent on AUDITSYSCALL.

This looks like something else we should fix independently from this patchset.

&gt; Looking ahead, contid should be treated like loginuid and
sessionid, which are
&gt; currently only available when syscall auditting is.

That seems reasonable. Eventually it would be great if we got rid of
CONFIG_AUDITSYSCALL, but that is a separate issue, and something that
is going to require work from the different arch/ABI folks to ensure
everything is working properly.

&gt; Converting records from standalone to syscall and checking
audit_dummy_context
&gt; changes the nature of CONFIG_AUDIT/!CONFIG_AUDITSYSCALL separation.
&gt; eg: ANOM_LINK accompanied by PATH record (which needed CWD addition to be
&gt; complete anyways)
&gt;
&gt; &gt; &gt; diff --git a/init/main.c b/init/main.c
&gt; &gt; &gt; index 3b4ada1..6aba171 100644
&gt; &gt; &gt; --- a/init/main.c
&gt; &gt; &gt; +++ b/init/main.c
&gt; &gt; &gt; @@ -92,6 +92,7 @@
&gt; &gt; &gt; #include <linux rodata_test.h="">
&gt; &gt; &gt; #include <linux jump_label.h="">
&gt; &gt; &gt; #include <linux mem_encrypt.h="">
&gt; &gt; &gt; +#include <linux audit.h="">
&gt; &gt; &gt;
&gt; &gt; &gt; #include <asm io.h="">
&gt; &gt; &gt; #include <asm bugs.h="">
&gt; &gt; &gt; @@ -721,6 +722,7 @@ asmlinkage __visible void __init
start_kernel(void)
&gt; &gt; &gt; nsfs_init();
&gt; &gt; &gt; cpuset_init();
&gt; &gt; &gt; cgroup_init();
&gt; &gt; &gt; + audit_task_init();
&gt; &gt; &gt; taskstats_init_early();
&gt; &gt; &gt; delayacct_init();
&gt; &gt;
&gt; &gt; It seems like we would need either init_struct_audit or
&gt; &gt; audit_task_init(), but not both, yes?
&gt;
&gt; One sets initial values of init task via an included struct,
other makes a call
&gt; to create the kmem cache. Both seem appropriate to me unless we move the
&gt; initialization from a struct to assignments in audit_task_init(),
but I'm not
&gt; that comfortable separating the audit init values from the rest of the
&gt; task_struct init task initializers (though there are other
subsystems that need
&gt; to do so dynamically).

My original thinking was focused on the use of init_struct_audit as an
initializer when audit_task_init() was already creating a kmem_cache
pool and a zero'd/init'd audit_task_info could be obtained via the
usual kmem_cache functions. Alternatively, although I don't believe
it would be recommended for this case, would be to use
init_struct_audit as an init helper if we included the audit_task_info
struct directly in the task_struct, as opposed to a pointer. What I
missed was the simple fact that you're only using init_struct_audit
for the init_task, which pretty much makes my original question rather
silly :)

--
paul moore
http://www.paul-moore.com

2019-01-04 00:26:20

by Paul Moore

[permalink] [raw]
Subject: Re: [PATCH ghak90 (was ghak32) V4 05/10] audit: add support for non-syscall auxiliary records

On Thu, Nov 1, 2018 at 2:49 PM Richard Guy Briggs <[email protected]> wrote:
&gt; On 2018-10-19 19:17, Paul Moore wrote:
&gt; &gt; On Sun, Aug 5, 2018 at 4:33 AM Richard Guy Briggs
<[email protected]> wrote:
&gt; &gt; &gt; Standalone audit records have the timestamp and serial
number generated
&gt; &gt; &gt; on the fly and as such are unique, making them
standalone. This new
&gt; &gt; &gt; function audit_alloc_local() generates a local audit
context that will
&gt; &gt; &gt; be used only for a standalone record and its auxiliary
record(s). The
&gt; &gt; &gt; context is discarded immediately after the local
associated records are
&gt; &gt; &gt; produced.
&gt; &gt; &gt;
&gt; &gt; &gt; Signed-off-by: Richard Guy Briggs <[email protected]>
&gt; &gt; &gt; Acked-by: Serge Hallyn <[email protected]>
&gt; &gt; &gt; ---
&gt; &gt; &gt; include/linux/audit.h | 8 ++++++++
&gt; &gt; &gt; kernel/audit.h | 1 +
&gt; &gt; &gt; kernel/auditsc.c | 33 ++++++++++++++++++++++++++++-----
&gt; &gt; &gt; 3 files changed, 37 insertions(+), 5 deletions(-)
&gt; &gt;
&gt; &gt; I'm not in love with the local flag, and the whole local context in
&gt; &gt; general, but that's a larger discussion and not something I want to
&gt; &gt; force on this patchset; we can fix it later.
&gt;
&gt; I understand your reasoning to combine it so that if one patch gets
&gt; backported then both do, or if one gets reverted both do, but I really
&gt; prefer them seperate for similar reasons if there is more than one user.

The key is "more than one user". As I mentioned below, assuming that
the only user is the networking bits (we can continue to discuss the
tty caller in the tty patch), this should live with the networking
bits; it makes no sense to keep it separate in that case. Of course,
if there is more than one user, then keeping this change separate is
reasonable.

> > I think this patch looks fine, but it seems a bit odd standalone; it's
> > almost always better to include new capabilities/functions in the same
> > patch as the user. Since the only user is the networking bits, it
> > might make more sense to fold this patch into that one.
>
> It was kept seperate due to tty_audit usage. See my reasoning for patch
> 6, but I'm willing to negotiate if that merits an exception like the
> USER records do.

--
paul moore
http://www.paul-moore.com

2019-01-04 00:30:16

by Paul Moore

[permalink] [raw]
Subject: Re: [PATCH ghak90 (was ghak32) V4 06/10] audit: add containerid support for tty_audit

On Wed, Oct 31, 2018 at 5:17 PM Richard Guy Briggs <[email protected]> wrote:
&gt; On 2018-10-19 19:17, Paul Moore wrote:
&gt; &gt; On Sun, Aug 5, 2018 at 4:33 AM Richard Guy Briggs
<[email protected]> wrote:
&gt; &gt; &gt; Add audit container identifier auxiliary record to tty
logging rule
&gt; &gt; &gt; event standalone records.
&gt; &gt; &gt;
&gt; &gt; &gt; Signed-off-by: Richard Guy Briggs <[email protected]>
&gt; &gt; &gt; Acked-by: Serge Hallyn <[email protected]>
&gt; &gt; &gt; ---
&gt; &gt; &gt; drivers/tty/tty_audit.c | 5 ++++-
&gt; &gt; &gt; 1 file changed, 4 insertions(+), 1 deletion(-)
&gt; &gt; &gt;
&gt; &gt; &gt; diff --git a/drivers/tty/tty_audit.c b/drivers/tty/tty_audit.c
&gt; &gt; &gt; index 50f567b..3e21477 100644
&gt; &gt; &gt; --- a/drivers/tty/tty_audit.c
&gt; &gt; &gt; +++ b/drivers/tty/tty_audit.c
&gt; &gt; &gt; @@ -66,8 +66,9 @@ static void tty_audit_log(const char
*description, dev_t dev,
&gt; &gt; &gt; uid_t uid = from_kuid(&amp;init_user_ns, task_uid(tsk));
&gt; &gt; &gt; uid_t loginuid = from_kuid(&amp;init_user_ns,
audit_get_loginuid(tsk));
&gt; &gt; &gt; unsigned int sessionid = audit_get_sessionid(tsk);
&gt; &gt; &gt; + struct audit_context *context =
audit_alloc_local(GFP_KERNEL);
&gt; &gt; &gt;
&gt; &gt; &gt; - ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_TTY);
&gt; &gt; &gt; + ab = audit_log_start(context, GFP_KERNEL, AUDIT_TTY);
&gt; &gt; &gt; if (ab) {
&gt; &gt; &gt; char name[sizeof(tsk-&gt;comm)];
&gt; &gt; &gt;
&gt; &gt; &gt; @@ -80,6 +81,8 @@ static void tty_audit_log(const char
*description, dev_t dev,
&gt; &gt; &gt; audit_log_n_hex(ab, data, size);
&gt; &gt; &gt; audit_log_end(ab);
&gt; &gt; &gt; }
&gt; &gt; &gt; + audit_log_contid(context, "tty", audit_get_contid(tsk));
&gt; &gt; &gt; + audit_free_context(context);
&gt; &gt; &gt; }
&gt; &gt;
&gt; &gt; Since I never polished up my task_struct/current fix patch enough to
&gt; &gt; get it past RFC status during this development window (new job, stolen
&gt; &gt; laptop, etc.) *and* it looks like you are going to need at least one
&gt; &gt; more respin of this patchset, go ahead and fix this patch to use
&gt; &gt; current instead of generating a local context. I'll deal with the
&gt; &gt; merge fallout if/when it happens.
&gt;
&gt; Sure, I will switch it to current in the call to audit_get_contid().
&gt;
&gt; The local context is a distinct issue. Like USER records, I prefer
&gt; local due to potential record volume, it is already trackable as far as
&gt; Steve is concerned, and if it is to be connected with the syscall
&gt; record, it should be linked to syscall records in a seperate new github
&gt; issue with its own patch. It accumulates events until the buffer is
&gt; flushed to a record, so the timestamp only represents the flush (usually
&gt; user "CR/enter").

Generally, yes, associating records is a separate issue, but in this
particular case you are changing this record by making it a "local"
record, which as we've discussed before, I view as a necessary evil
and something that must be minimized. A quick look at the
tty_audit_log() callers shows tty_audit_tiocsti() which is an ioctl
handler (and thus current should be valid and correct), and
tty_audit_buf_push() whose callers all seem have valid and correct
current values; if you find that not to be the case please let me
know.

> > Local contexts are a last resort. If you ever find yourself writing
> > code that generates a local context, you should first be 100% certain
> > that the event is not the the result of a process initiated action (in
> > which case it should take from the task's context).
>
> Well, I'm 100% certain it is linked to a process, but so are USER
> records that are already being discussed as the exception. This is
> basically a keystroke logger (that has a flag to omit passwords).

--
paul moore
http://www.paul-moore.com

2019-01-04 00:30:33

by Paul Moore

[permalink] [raw]
Subject: Re: [PATCH ghak90 (was ghak32) V4 00/10] audit: implement container identifier

On Thu, Jan 3, 2019 at 12:36 PM Richard Guy Briggs <[email protected]> wrote:
> On 2019-01-03 08:15, Guenter Roeck wrote:
> > Hi,
> >
> > On Tue, Jul 31, 2018 at 04:07:35PM -0400, Richard Guy Briggs wrote:
> > > Implement kernel audit container identifier.
> >
> > I don't see a follow-up submission of this patch series. Has it been abandoned,
> > or do I use the wrong search terms ?
>
> Guenter, thanks for your interest in this patchset. I haven't
> abandoned it. I've pushed some updates to my own (ill-publicized)
> public git repo. This effort has been going on more than 5 years with 8
> previous revisions trying to document task namespaces and deciding that
> was insufficient.
>
> For this patchset I waited 11.5 weeks (80 days, Jules Verne anyone?)
> before the primary intended maintainer did the first review, then I
> responded within 2 weeks with further questions and a followup patch
> proposal and then waited another 8 weeks for any response before adding
> another query for that followup patch proposal review at which point I
> got a rude answer saying I had disappointed and exhausted the
> maintainer's goodwill with some hints at how to proceed just before new
> year's.

For what it is worth, I've found your emails to me to be rather "rude"
as well (to borrow the term), and I responded with what I felt was
appropriate. Perhaps our interactions may have been seen as overly,
or quickly, harsh but I would remind those that we have several years
of history that extends far beyond the lists which obviously affects
how we interact. Our expectations for each other are clearly higher
than either of us are delivering, so I'm going to suggest what I've
suggested before, albeit privately: let's stick to the code, that's
where we can find common ground.

There were only a few outstanding threads/questions from your last
posting, you should have responses to those sitting in your inbox now.

> I'd be delighted with other upstream review to get other angles and to
> take some of the load and responsibility off the primary maintainer.
>
> I expect to submit a v5 within a week without having had those questions
> directly answered, but with some ideas of what to check and verify
> before I resubmit. Most of the changes have been sitting in that branch
> for two months, already rebased one kernel version and will need
> updating again.

--
paul moore
http://www.paul-moore.com

2019-01-04 00:36:27

by Richard Guy Briggs

[permalink] [raw]
Subject: Re: [PATCH ghak90 (was ghak32) V4 00/10] audit: implement container identifier

On 2019-01-03 10:58, Guenter Roeck wrote:
> Hi Richard,
>
> On Thu, Jan 03, 2019 at 12:36:13PM -0500, Richard Guy Briggs wrote:
> > On 2019-01-03 08:15, Guenter Roeck wrote:
> > > Hi,
> > >
> > > On Tue, Jul 31, 2018 at 04:07:35PM -0400, Richard Guy Briggs wrote:
> > > > Implement kernel audit container identifier.
> > >
> > > I don't see a follow-up submission of this patch series. Has it been abandoned,
> > > or do I use the wrong search terms ?
> >
> > Guenter, thanks for your interest in this patchset. I haven't
> > abandoned it. I've pushed some updates to my own (ill-publicized)
> > public git repo. This effort has been going on more than 5 years with 8
>
> Oh man :-(. Not sure if I would be that patient.

Patience, subbornness, unjustified optimism, tenacity, inflexibility, who knows...

Are you talking about sticking with this particular problem, or delay
before checking in on a particular patch review?

> Can you point me to your repository ?

Sure. It hasn't been squashed and will be rebased.
git://toccata2.tricolour.ca/linux-2.6-rgb.git

I still have some write locks to check and work on.

> > previous revisions trying to document task namespaces and deciding that
> > was insufficient.
>
> My interest is mostly thanks to having some of the patches of your series
> in my incoming code review queue:
>
> https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/1379654/3

Ok, interesting. Michael Halcrow had approached me in Vancouver at LSS
at the end of August and I regret not having had enough time to talk
with him further about it.

> As background, some of the patches in the series are needed by GCP (Google
> Cloud Platform) as a prerequisite for some security features. Having to
> maintain out-of-tree code is always a pain, even more so in a subsystem
> related to security. So it would be quite useful to understand if we are
> going to be stuck with this forever or if there is a change for the code
> to find its way upstream. Also, it would be useful to know if there are
> some upcoming changes/improvements which should be included in our version.

There are likely more changes coming, but I don't expect them to be
that drastic a departure from the original design. There were some
changes in the implementation based on unforseen issues raised once
coding started (which is part of the process). Upstream patch review
would be the most helpful in keeping this stuff moving.

David Howells also had some interesting ideas and patches to try to
address some of these problems and he's still working on a prerequisite
patchset to get it upstream before returning to his container identifier
patchset. It is moving slowly.

> Thanks,
> Guenter
>
> > For this patchset I waited 11.5 weeks (80 days, Jules Verne anyone?)
> > before the primary intended maintainer did the first review, then I
> > responded within 2 weeks with further questions and a followup patch
> > proposal and then waited another 8 weeks for any response before adding
> > another query for that followup patch proposal review at which point I
> > got a rude answer saying I had disappointed and exhausted the
> > maintainer's goodwill with some hints at how to proceed just before new
> > year's.
> >
> > I'd be delighted with other upstream review to get other angles and to
> > take some of the load and responsibility off the primary maintainer.
> >
> > I expect to submit a v5 within a week without having had those questions
> > directly answered, but with some ideas of what to check and verify
> > before I resubmit. Most of the changes have been sitting in that branch
> > for two months, already rebased one kernel version and will need
> > updating again.
> >
> > > Thanks,
> > > Guenter
> > >
> > > > This patchset is a fourth based on the proposal document (V3)
> > > > posted:
> > > > https://www.redhat.com/archives/linux-audit/2018-January/msg00014.html
> > > >
> > > > The first patch is the last patch from ghak81 that is included here as a
> > > > convenience.
> > > >
> > > > 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 the auxiliary record AUDIT_CONTAINER if an
> > > > audit container identifier is identifiable with an event. This patch
> > > > requires userspace support for proper type display.
> > > >
> > > > The 4th adds signal and ptrace support.
> > > >
> > > > The 5th creates a local audit context to be able to bind a standalone
> > > > record with a locally created auxiliary record.
> > > >
> > > > The 6th patch adds audit container identifier records to the tty
> > > > standalone record.
> > > >
> > > > The 7th 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 8th adds network namespace audit container identifier labelling
> > > > based on member tasks' audit container identifier labels.
> > > >
> > > > The 9th adds audit container identifier support to standalone netfilter
> > > > records that don't have a task context and lists each container to which
> > > > that net namespace belongs.
> > > >
> > > > The 10th implements reading the audit container identifier from the proc
> > > > filesystem for debugging. This patch isn't planned for upstream
> > > > inclusion.
> > > >
> > > >
> > > > Example: Set an audit container identifier of 123456 to the "sleep" task:
> > > >
> > > > sleep 2&
> > > > child=$!
> > > > echo 123456 > /proc/$child/audit_containerid; echo $?
> > > > ausearch -ts recent -m container
> > > > echo child:$child contid:$( cat /proc/$child/audit_containerid)
> > > >
> > > > This should produce a record such as:
> > > >
> > > > type=CONTAINER_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 msg=audit(2018-06-06 12:46:31.707:26953) : op=task contid=123459
> > > > type=PROCTITLE msg=audit(2018-06-06 12:46:31.707:26953) : proctitle=perl -e sleep 1; open(my $tmpfile, '>', "/tmp/tmpcontainerid"); close($tmpfile);
> > > > type=PATH msg=audit(2018-06-06 12:46:31.707:26953) : item=1 name=/tmp/tmpcontainerid inode=25656 dev=00:26 mode=file,644 ouid=root ogid=root rdev=00:00 obj=unconfined_u:object_r:user_tmp_t:s0 nametype=CREATE cap_fp=none cap_fi=none cap_fe=0 cap_fver=0
> > > > type=PATH msg=audit(2018-06-06 12:46:31.707:26953) : item=0 name=/tmp/ inode=8985 dev=00:26 mode=dir,sticky,777 ouid=root ogid=root rdev=00:00 obj=system_u:object_r:tmp_t:s0 nametype=PARENT cap_fp=none cap_fi=none cap_fe=0 cap_fver=0
> > > > type=CWD msg=audit(2018-06-06 12:46:31.707:26953) : cwd=/root
> > > > type=SYSCALL msg=audit(2018-06-06 12:46:31.707:26953) : arch=x86_64 syscall=openat success=yes exit=3 a0=0xffffffffffffff9c a1=0x5621f2b81900 a2=O_WRONLY|O_CREAT|O_TRUNC a3=0x1b6 items=2 ppid=628 pid=2232 auid=root uid=root gid=root euid=root suid=root fsuid=root egid=root sgid=root fsgid=root tty=ttyS0 ses=1 comm=perl exe=/usr/bin/perl subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 key=tmpcontainerid
> > > >
> > > >
> > > > Includes: https://github.com/linux-audit/audit-kernel/issues/81
> > > > See: https://github.com/linux-audit/audit-kernel/issues/90
> > > > See: https://github.com/linux-audit/audit-userspace/issues/40
> > > > See: https://github.com/linux-audit/audit-testsuite/issues/64
> > > > See: https://github.com/linux-audit/audit-kernel/wiki/RFE-Audit-Container-ID
> > > >
> > > > Changelog:
> > > >
> > > > 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: log container info of syscalls
> > > > audit: add containerid support for ptrace and signals
> > > > audit: add support for non-syscall auxiliary records
> > > > audit: add containerid support for tty_audit
> > > > audit: add containerid filtering
> > > > audit: add support for containerid to network namespaces
> > > > audit: NETFILTER_PKT: record each container ID associated with a netNS
> > > > debug audit: read container ID of a process
> > > >
> > > > drivers/tty/tty_audit.c | 5 +-
> > > > fs/proc/base.c | 56 ++++++++++++++
> > > > include/linux/audit.h | 95 ++++++++++++++++++++---
> > > > include/linux/sched.h | 5 +-
> > > > include/uapi/linux/audit.h | 8 +-
> > > > init/init_task.c | 3 +-
> > > > init/main.c | 2 +
> > > > kernel/audit.c | 137 +++++++++++++++++++++++++++++++++
> > > > kernel/audit.h | 4 +
> > > > kernel/auditfilter.c | 47 ++++++++++++
> > > > kernel/auditsc.c | 183 ++++++++++++++++++++++++++++++++++++++++-----
> > > > kernel/fork.c | 4 +-
> > > > kernel/nsproxy.c | 4 +
> > > > net/netfilter/xt_AUDIT.c | 12 ++-
> > > > 14 files changed, 526 insertions(+), 39 deletions(-)
> > > >
> > > > --
> > > > 1.8.3.1
> > > >
> >
> > - RGB
> >
> > --
> > Richard Guy Briggs <[email protected]>
> > 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

- RGB

--
Richard Guy Briggs <[email protected]>
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

2019-01-04 02:38:12

by Richard Guy Briggs

[permalink] [raw]
Subject: Re: [PATCH ghak90 (was ghak32) V4 01/10] audit: collect audit task parameters

I'm not sure what's going on here, but it looks like HTML-encoded reply
quoting making the quoted text very difficult to read. All the previous
">" have been converted to the HTML "&gt;" encoding. Your most recent
reply text looks mostly fine.

On 2019-01-03 15:10, Paul Moore wrote:
> On Thu, Nov 1, 2018 at 6:07 PM Richard Guy Briggs <[email protected]> wrote:
> &gt; On 2018-10-19 19:15, Paul Moore wrote:
> &gt; &gt; On Sun, Aug 5, 2018 at 4:32 AM Richard Guy Briggs
> <[email protected]> wrote:
> &gt; &gt; &gt; The audit-related parameters in struct task_struct
> should ideally be
> &gt; &gt; &gt; collected together and accessed through a standard audit API.
> &gt; &gt; &gt;
> &gt; &gt; &gt; Collect the existing loginuid, sessionid and
> audit_context together in a
> &gt; &gt; &gt; new struct audit_task_info called "audit" in struct task_struct.
> &gt; &gt; &gt;
> &gt; &gt; &gt; Use kmem_cache to manage this pool of memory.
> &gt; &gt; &gt; Un-inline audit_free() to be able to always recover that memory.
> &gt; &gt; &gt;
> &gt; &gt; &gt; See: https://github.com/linux-audit/audit-kernel/issues/81
> &gt; &gt; &gt;
> &gt; &gt; &gt; Signed-off-by: Richard Guy Briggs <[email protected]>
> &gt; &gt; &gt; ---
> &gt; &gt; &gt; include/linux/audit.h | 34 ++++++++++++++++++++++++----------
> &gt; &gt; &gt; include/linux/sched.h | 5 +----
> &gt; &gt; &gt; init/init_task.c | 3 +--
> &gt; &gt; &gt; init/main.c | 2 ++
> &gt; &gt; &gt; kernel/auditsc.c | 51
> ++++++++++++++++++++++++++++++++++++++++++---------
> &gt; &gt; &gt; kernel/fork.c | 4 +++-
> &gt; &gt; &gt; 6 files changed, 73 insertions(+), 26 deletions(-)
> &gt; &gt;
> &gt; &gt; ...
> &gt; &gt;
> &gt; &gt; &gt; diff --git a/include/linux/sched.h b/include/linux/sched.h
> &gt; &gt; &gt; index 87bf02d..e117272 100644
> &gt; &gt; &gt; --- a/include/linux/sched.h
> &gt; &gt; &gt; +++ b/include/linux/sched.h
> &gt; &gt; &gt; @@ -873,10 +872,8 @@ struct task_struct {
> &gt; &gt; &gt;
> &gt; &gt; &gt; struct callback_head *task_works;
> &gt; &gt; &gt;
> &gt; &gt; &gt; - struct audit_context *audit_context;
> &gt; &gt; &gt; #ifdef CONFIG_AUDITSYSCALL
> &gt; &gt; &gt; - kuid_t loginuid;
> &gt; &gt; &gt; - unsigned int sessionid;
> &gt; &gt; &gt; + struct audit_task_info *audit;
> &gt; &gt; &gt; #endif
> &gt; &gt; &gt; struct seccomp seccomp;
> &gt; &gt;
> &gt; &gt; Prior to this patch audit_context was available regardless of
> &gt; &gt; CONFIG_AUDITSYSCALL, after this patch the corresponding audit_context
> &gt; &gt; is only available when CONFIG_AUDITSYSCALL is defined.
> &gt;
> &gt; This was intentional since audit_context is not used when AUDITSYSCALL is
> &gt; disabled. audit_alloc() was stubbed in that case to return 0.
> audit_context()
> &gt; returned NULL.
> &gt;
> &gt; The fact that audit_context was still present in struct task_struct was an
> &gt; oversight in the two patches already accepted:
> &gt; ("audit: use inline function to get audit context")
> &gt; ("audit: use inline function to get audit context")
> &gt; that failed to hide or remove it from struct task_struct when it
> was no longer
> &gt; relevant.
>
> Okay, in that case let's pull this out and fix this separately from
> the audit container ID patchset.
>
> &gt; On further digging, loginuid and sessionid (and
> audit_log_session_info) should
> &gt; be part of CONFIG_AUDIT scope and not CONFIG_AUDITSYSCALL since
> it is used in
> &gt; CONFIG_CHANGE, ANOM_LINK, FEATURE_CHANGE(, INTEGRITY_RULE), none
> of which are
> &gt; otherwise dependent on AUDITSYSCALL.
>
> This looks like something else we should fix independently from this patchset.
>
> &gt; Looking ahead, contid should be treated like loginuid and
> sessionid, which are
> &gt; currently only available when syscall auditting is.
>
> That seems reasonable. Eventually it would be great if we got rid of
> CONFIG_AUDITSYSCALL, but that is a separate issue, and something that
> is going to require work from the different arch/ABI folks to ensure
> everything is working properly.
>
> &gt; Converting records from standalone to syscall and checking
> audit_dummy_context
> &gt; changes the nature of CONFIG_AUDIT/!CONFIG_AUDITSYSCALL separation.
> &gt; eg: ANOM_LINK accompanied by PATH record (which needed CWD addition to be
> &gt; complete anyways)
> &gt;
> &gt; &gt; &gt; diff --git a/init/main.c b/init/main.c
> &gt; &gt; &gt; index 3b4ada1..6aba171 100644
> &gt; &gt; &gt; --- a/init/main.c
> &gt; &gt; &gt; +++ b/init/main.c
> &gt; &gt; &gt; @@ -92,6 +92,7 @@
> &gt; &gt; &gt; #include <linux rodata_test.h="">
> &gt; &gt; &gt; #include <linux jump_label.h="">
> &gt; &gt; &gt; #include <linux mem_encrypt.h="">
> &gt; &gt; &gt; +#include <linux audit.h="">
> &gt; &gt; &gt;
> &gt; &gt; &gt; #include <asm io.h="">
> &gt; &gt; &gt; #include <asm bugs.h="">
> &gt; &gt; &gt; @@ -721,6 +722,7 @@ asmlinkage __visible void __init
> start_kernel(void)
> &gt; &gt; &gt; nsfs_init();
> &gt; &gt; &gt; cpuset_init();
> &gt; &gt; &gt; cgroup_init();
> &gt; &gt; &gt; + audit_task_init();
> &gt; &gt; &gt; taskstats_init_early();
> &gt; &gt; &gt; delayacct_init();
> &gt; &gt;
> &gt; &gt; It seems like we would need either init_struct_audit or
> &gt; &gt; audit_task_init(), but not both, yes?
> &gt;
> &gt; One sets initial values of init task via an included struct,
> other makes a call
> &gt; to create the kmem cache. Both seem appropriate to me unless we move the
> &gt; initialization from a struct to assignments in audit_task_init(),
> but I'm not
> &gt; that comfortable separating the audit init values from the rest of the
> &gt; task_struct init task initializers (though there are other
> subsystems that need
> &gt; to do so dynamically).
>
> My original thinking was focused on the use of init_struct_audit as an
> initializer when audit_task_init() was already creating a kmem_cache
> pool and a zero'd/init'd audit_task_info could be obtained via the
> usual kmem_cache functions. Alternatively, although I don't believe
> it would be recommended for this case, would be to use
> init_struct_audit as an init helper if we included the audit_task_info
> struct directly in the task_struct, as opposed to a pointer. What I
> missed was the simple fact that you're only using init_struct_audit
> for the init_task, which pretty much makes my original question rather
> silly :)
>
> --
> paul moore
> http://www.paul-moore.com

- RGB

--
Richard Guy Briggs <[email protected]>
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

2019-01-04 02:45:20

by Paul Moore

[permalink] [raw]
Subject: Re: [PATCH ghak90 (was ghak32) V4 01/10] audit: collect audit task parameters

On Thu, Jan 3, 2019 at 3:29 PM Richard Guy Briggs <[email protected]> wrote:
> I'm not sure what's going on here, but it looks like HTML-encoded reply
> quoting making the quoted text very difficult to read. All the previous
> ">" have been converted to the HTML "&gt;" encoding. Your most recent
> reply text looks mostly fine.

Not sure what happened either, I suspect gmail did something odd when
I saved them as drafts, but it has never done that before. FWIW, I
generally batch up individual review comments for complex patchsets as
one often needs to review the entire set first before commenting.

The most recent reply to patch 0/10 wasn't saved as a draft before sending.

> On 2019-01-03 15:10, Paul Moore wrote:
> > On Thu, Nov 1, 2018 at 6:07 PM Richard Guy Briggs <[email protected]> wrote:
> > &gt; On 2018-10-19 19:15, Paul Moore wrote:
> > &gt; &gt; On Sun, Aug 5, 2018 at 4:32 AM Richard Guy Briggs
> > <[email protected]> wrote:
> > &gt; &gt; &gt; The audit-related parameters in struct task_struct
> > should ideally be
> > &gt; &gt; &gt; collected together and accessed through a standard audit API.
> > &gt; &gt; &gt;
> > &gt; &gt; &gt; Collect the existing loginuid, sessionid and
> > audit_context together in a
> > &gt; &gt; &gt; new struct audit_task_info called "audit" in struct task_struct.
> > &gt; &gt; &gt;
> > &gt; &gt; &gt; Use kmem_cache to manage this pool of memory.
> > &gt; &gt; &gt; Un-inline audit_free() to be able to always recover that memory.
> > &gt; &gt; &gt;
> > &gt; &gt; &gt; See: https://github.com/linux-audit/audit-kernel/issues/81
> > &gt; &gt; &gt;
> > &gt; &gt; &gt; Signed-off-by: Richard Guy Briggs <[email protected]>
> > &gt; &gt; &gt; ---
> > &gt; &gt; &gt; include/linux/audit.h | 34 ++++++++++++++++++++++++----------
> > &gt; &gt; &gt; include/linux/sched.h | 5 +----
> > &gt; &gt; &gt; init/init_task.c | 3 +--
> > &gt; &gt; &gt; init/main.c | 2 ++
> > &gt; &gt; &gt; kernel/auditsc.c | 51
> > ++++++++++++++++++++++++++++++++++++++++++---------
> > &gt; &gt; &gt; kernel/fork.c | 4 +++-
> > &gt; &gt; &gt; 6 files changed, 73 insertions(+), 26 deletions(-)
> > &gt; &gt;
> > &gt; &gt; ...
> > &gt; &gt;
> > &gt; &gt; &gt; diff --git a/include/linux/sched.h b/include/linux/sched.h
> > &gt; &gt; &gt; index 87bf02d..e117272 100644
> > &gt; &gt; &gt; --- a/include/linux/sched.h
> > &gt; &gt; &gt; +++ b/include/linux/sched.h
> > &gt; &gt; &gt; @@ -873,10 +872,8 @@ struct task_struct {
> > &gt; &gt; &gt;
> > &gt; &gt; &gt; struct callback_head *task_works;
> > &gt; &gt; &gt;
> > &gt; &gt; &gt; - struct audit_context *audit_context;
> > &gt; &gt; &gt; #ifdef CONFIG_AUDITSYSCALL
> > &gt; &gt; &gt; - kuid_t loginuid;
> > &gt; &gt; &gt; - unsigned int sessionid;
> > &gt; &gt; &gt; + struct audit_task_info *audit;
> > &gt; &gt; &gt; #endif
> > &gt; &gt; &gt; struct seccomp seccomp;
> > &gt; &gt;
> > &gt; &gt; Prior to this patch audit_context was available regardless of
> > &gt; &gt; CONFIG_AUDITSYSCALL, after this patch the corresponding audit_context
> > &gt; &gt; is only available when CONFIG_AUDITSYSCALL is defined.
> > &gt;
> > &gt; This was intentional since audit_context is not used when AUDITSYSCALL is
> > &gt; disabled. audit_alloc() was stubbed in that case to return 0.
> > audit_context()
> > &gt; returned NULL.
> > &gt;
> > &gt; The fact that audit_context was still present in struct task_struct was an
> > &gt; oversight in the two patches already accepted:
> > &gt; ("audit: use inline function to get audit context")
> > &gt; ("audit: use inline function to get audit context")
> > &gt; that failed to hide or remove it from struct task_struct when it
> > was no longer
> > &gt; relevant.
> >
> > Okay, in that case let's pull this out and fix this separately from
> > the audit container ID patchset.
> >
> > &gt; On further digging, loginuid and sessionid (and
> > audit_log_session_info) should
> > &gt; be part of CONFIG_AUDIT scope and not CONFIG_AUDITSYSCALL since
> > it is used in
> > &gt; CONFIG_CHANGE, ANOM_LINK, FEATURE_CHANGE(, INTEGRITY_RULE), none
> > of which are
> > &gt; otherwise dependent on AUDITSYSCALL.
> >
> > This looks like something else we should fix independently from this patchset.
> >
> > &gt; Looking ahead, contid should be treated like loginuid and
> > sessionid, which are
> > &gt; currently only available when syscall auditting is.
> >
> > That seems reasonable. Eventually it would be great if we got rid of
> > CONFIG_AUDITSYSCALL, but that is a separate issue, and something that
> > is going to require work from the different arch/ABI folks to ensure
> > everything is working properly.
> >
> > &gt; Converting records from standalone to syscall and checking
> > audit_dummy_context
> > &gt; changes the nature of CONFIG_AUDIT/!CONFIG_AUDITSYSCALL separation.
> > &gt; eg: ANOM_LINK accompanied by PATH record (which needed CWD addition to be
> > &gt; complete anyways)
> > &gt;
> > &gt; &gt; &gt; diff --git a/init/main.c b/init/main.c
> > &gt; &gt; &gt; index 3b4ada1..6aba171 100644
> > &gt; &gt; &gt; --- a/init/main.c
> > &gt; &gt; &gt; +++ b/init/main.c
> > &gt; &gt; &gt; @@ -92,6 +92,7 @@
> > &gt; &gt; &gt; #include <linux rodata_test.h="">
> > &gt; &gt; &gt; #include <linux jump_label.h="">
> > &gt; &gt; &gt; #include <linux mem_encrypt.h="">
> > &gt; &gt; &gt; +#include <linux audit.h="">
> > &gt; &gt; &gt;
> > &gt; &gt; &gt; #include <asm io.h="">
> > &gt; &gt; &gt; #include <asm bugs.h="">
> > &gt; &gt; &gt; @@ -721,6 +722,7 @@ asmlinkage __visible void __init
> > start_kernel(void)
> > &gt; &gt; &gt; nsfs_init();
> > &gt; &gt; &gt; cpuset_init();
> > &gt; &gt; &gt; cgroup_init();
> > &gt; &gt; &gt; + audit_task_init();
> > &gt; &gt; &gt; taskstats_init_early();
> > &gt; &gt; &gt; delayacct_init();
> > &gt; &gt;
> > &gt; &gt; It seems like we would need either init_struct_audit or
> > &gt; &gt; audit_task_init(), but not both, yes?
> > &gt;
> > &gt; One sets initial values of init task via an included struct,
> > other makes a call
> > &gt; to create the kmem cache. Both seem appropriate to me unless we move the
> > &gt; initialization from a struct to assignments in audit_task_init(),
> > but I'm not
> > &gt; that comfortable separating the audit init values from the rest of the
> > &gt; task_struct init task initializers (though there are other
> > subsystems that need
> > &gt; to do so dynamically).
> >
> > My original thinking was focused on the use of init_struct_audit as an
> > initializer when audit_task_init() was already creating a kmem_cache
> > pool and a zero'd/init'd audit_task_info could be obtained via the
> > usual kmem_cache functions. Alternatively, although I don't believe
> > it would be recommended for this case, would be to use
> > init_struct_audit as an init helper if we included the audit_task_info
> > struct directly in the task_struct, as opposed to a pointer. What I
> > missed was the simple fact that you're only using init_struct_audit
> > for the init_task, which pretty much makes my original question rather
> > silly :)
> >
> > --
> > paul moore
> > http://www.paul-moore.com
>
> - RGB
>
> --
> Richard Guy Briggs <[email protected]>
> 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



--
paul moore
http://www.paul-moore.com

2019-01-04 02:45:20

by Richard Guy Briggs

[permalink] [raw]
Subject: Re: [PATCH ghak90 (was ghak32) V4 01/10] audit: collect audit task parameters

On 2019-01-03 15:33, Paul Moore wrote:
> On Thu, Jan 3, 2019 at 3:29 PM Richard Guy Briggs <[email protected]> wrote:
> > I'm not sure what's going on here, but it looks like HTML-encoded reply
> > quoting making the quoted text very difficult to read. All the previous
> > ">" have been converted to the HTML "&gt;" encoding. Your most recent
> > reply text looks mostly fine.
>
> Not sure what happened either, I suspect gmail did something odd when
> I saved them as drafts, but it has never done that before. FWIW, I
> generally batch up individual review comments for complex patchsets as
> one often needs to review the entire set first before commenting.
>
> The most recent reply to patch 0/10 wasn't saved as a draft before sending.

Yeah, I noticed the last one was fine and wondered why it was different.

/me <3 mutt...

> > On 2019-01-03 15:10, Paul Moore wrote:
> > > On Thu, Nov 1, 2018 at 6:07 PM Richard Guy Briggs <[email protected]> wrote:
> > > &gt; On 2018-10-19 19:15, Paul Moore wrote:
> > > &gt; &gt; On Sun, Aug 5, 2018 at 4:32 AM Richard Guy Briggs
> > > <[email protected]> wrote:
> > > &gt; &gt; &gt; The audit-related parameters in struct task_struct
> > > should ideally be
> > > &gt; &gt; &gt; collected together and accessed through a standard audit API.
> > > &gt; &gt; &gt;
> > > &gt; &gt; &gt; Collect the existing loginuid, sessionid and
> > > audit_context together in a
> > > &gt; &gt; &gt; new struct audit_task_info called "audit" in struct task_struct.
> > > &gt; &gt; &gt;
> > > &gt; &gt; &gt; Use kmem_cache to manage this pool of memory.
> > > &gt; &gt; &gt; Un-inline audit_free() to be able to always recover that memory.
> > > &gt; &gt; &gt;
> > > &gt; &gt; &gt; See: https://github.com/linux-audit/audit-kernel/issues/81
> > > &gt; &gt; &gt;
> > > &gt; &gt; &gt; Signed-off-by: Richard Guy Briggs <[email protected]>
> > > &gt; &gt; &gt; ---
> > > &gt; &gt; &gt; include/linux/audit.h | 34 ++++++++++++++++++++++++----------
> > > &gt; &gt; &gt; include/linux/sched.h | 5 +----
> > > &gt; &gt; &gt; init/init_task.c | 3 +--
> > > &gt; &gt; &gt; init/main.c | 2 ++
> > > &gt; &gt; &gt; kernel/auditsc.c | 51
> > > ++++++++++++++++++++++++++++++++++++++++++---------
> > > &gt; &gt; &gt; kernel/fork.c | 4 +++-
> > > &gt; &gt; &gt; 6 files changed, 73 insertions(+), 26 deletions(-)
> > > &gt; &gt;
> > > &gt; &gt; ...
> > > &gt; &gt;
> > > &gt; &gt; &gt; diff --git a/include/linux/sched.h b/include/linux/sched.h
> > > &gt; &gt; &gt; index 87bf02d..e117272 100644
> > > &gt; &gt; &gt; --- a/include/linux/sched.h
> > > &gt; &gt; &gt; +++ b/include/linux/sched.h
> > > &gt; &gt; &gt; @@ -873,10 +872,8 @@ struct task_struct {
> > > &gt; &gt; &gt;
> > > &gt; &gt; &gt; struct callback_head *task_works;
> > > &gt; &gt; &gt;
> > > &gt; &gt; &gt; - struct audit_context *audit_context;
> > > &gt; &gt; &gt; #ifdef CONFIG_AUDITSYSCALL
> > > &gt; &gt; &gt; - kuid_t loginuid;
> > > &gt; &gt; &gt; - unsigned int sessionid;
> > > &gt; &gt; &gt; + struct audit_task_info *audit;
> > > &gt; &gt; &gt; #endif
> > > &gt; &gt; &gt; struct seccomp seccomp;
> > > &gt; &gt;
> > > &gt; &gt; Prior to this patch audit_context was available regardless of
> > > &gt; &gt; CONFIG_AUDITSYSCALL, after this patch the corresponding audit_context
> > > &gt; &gt; is only available when CONFIG_AUDITSYSCALL is defined.
> > > &gt;
> > > &gt; This was intentional since audit_context is not used when AUDITSYSCALL is
> > > &gt; disabled. audit_alloc() was stubbed in that case to return 0.
> > > audit_context()
> > > &gt; returned NULL.
> > > &gt;
> > > &gt; The fact that audit_context was still present in struct task_struct was an
> > > &gt; oversight in the two patches already accepted:
> > > &gt; ("audit: use inline function to get audit context")
> > > &gt; ("audit: use inline function to get audit context")
> > > &gt; that failed to hide or remove it from struct task_struct when it
> > > was no longer
> > > &gt; relevant.
> > >
> > > Okay, in that case let's pull this out and fix this separately from
> > > the audit container ID patchset.
> > >
> > > &gt; On further digging, loginuid and sessionid (and
> > > audit_log_session_info) should
> > > &gt; be part of CONFIG_AUDIT scope and not CONFIG_AUDITSYSCALL since
> > > it is used in
> > > &gt; CONFIG_CHANGE, ANOM_LINK, FEATURE_CHANGE(, INTEGRITY_RULE), none
> > > of which are
> > > &gt; otherwise dependent on AUDITSYSCALL.
> > >
> > > This looks like something else we should fix independently from this patchset.
> > >
> > > &gt; Looking ahead, contid should be treated like loginuid and
> > > sessionid, which are
> > > &gt; currently only available when syscall auditting is.
> > >
> > > That seems reasonable. Eventually it would be great if we got rid of
> > > CONFIG_AUDITSYSCALL, but that is a separate issue, and something that
> > > is going to require work from the different arch/ABI folks to ensure
> > > everything is working properly.
> > >
> > > &gt; Converting records from standalone to syscall and checking
> > > audit_dummy_context
> > > &gt; changes the nature of CONFIG_AUDIT/!CONFIG_AUDITSYSCALL separation.
> > > &gt; eg: ANOM_LINK accompanied by PATH record (which needed CWD addition to be
> > > &gt; complete anyways)
> > > &gt;
> > > &gt; &gt; &gt; diff --git a/init/main.c b/init/main.c
> > > &gt; &gt; &gt; index 3b4ada1..6aba171 100644
> > > &gt; &gt; &gt; --- a/init/main.c
> > > &gt; &gt; &gt; +++ b/init/main.c
> > > &gt; &gt; &gt; @@ -92,6 +92,7 @@
> > > &gt; &gt; &gt; #include <linux rodata_test.h="">
> > > &gt; &gt; &gt; #include <linux jump_label.h="">
> > > &gt; &gt; &gt; #include <linux mem_encrypt.h="">
> > > &gt; &gt; &gt; +#include <linux audit.h="">
> > > &gt; &gt; &gt;
> > > &gt; &gt; &gt; #include <asm io.h="">
> > > &gt; &gt; &gt; #include <asm bugs.h="">
> > > &gt; &gt; &gt; @@ -721,6 +722,7 @@ asmlinkage __visible void __init
> > > start_kernel(void)
> > > &gt; &gt; &gt; nsfs_init();
> > > &gt; &gt; &gt; cpuset_init();
> > > &gt; &gt; &gt; cgroup_init();
> > > &gt; &gt; &gt; + audit_task_init();
> > > &gt; &gt; &gt; taskstats_init_early();
> > > &gt; &gt; &gt; delayacct_init();
> > > &gt; &gt;
> > > &gt; &gt; It seems like we would need either init_struct_audit or
> > > &gt; &gt; audit_task_init(), but not both, yes?
> > > &gt;
> > > &gt; One sets initial values of init task via an included struct,
> > > other makes a call
> > > &gt; to create the kmem cache. Both seem appropriate to me unless we move the
> > > &gt; initialization from a struct to assignments in audit_task_init(),
> > > but I'm not
> > > &gt; that comfortable separating the audit init values from the rest of the
> > > &gt; task_struct init task initializers (though there are other
> > > subsystems that need
> > > &gt; to do so dynamically).
> > >
> > > My original thinking was focused on the use of init_struct_audit as an
> > > initializer when audit_task_init() was already creating a kmem_cache
> > > pool and a zero'd/init'd audit_task_info could be obtained via the
> > > usual kmem_cache functions. Alternatively, although I don't believe
> > > it would be recommended for this case, would be to use
> > > init_struct_audit as an init helper if we included the audit_task_info
> > > struct directly in the task_struct, as opposed to a pointer. What I
> > > missed was the simple fact that you're only using init_struct_audit
> > > for the init_task, which pretty much makes my original question rather
> > > silly :)
> > >
> > > --
> > > paul moore
> > > http://www.paul-moore.com
> >
> > - RGB
> >
> > --
> > Richard Guy Briggs <[email protected]>
> > 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
>
>
>
> --
> paul moore
> http://www.paul-moore.com

- RGB

--
Richard Guy Briggs <[email protected]>
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

2019-01-04 06:10:03

by Guenter Roeck

[permalink] [raw]
Subject: Re: [PATCH ghak90 (was ghak32) V4 01/10] audit: collect audit task parameters

Hi Richard,

On Tue, Jul 31, 2018 at 04:07:36PM -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.
>
> See: https://github.com/linux-audit/audit-kernel/issues/81
>
> Signed-off-by: Richard Guy Briggs <[email protected]>

Overall I am not sure if keeping task_struct a bit smaller is worth
the added complexity, but I guess that is just me.

Anyway, couple of nitpicks. Please feel free to ignore, and my apologies
if some of all of the comments are duplicates.

Guenter

> ---
> include/linux/audit.h | 34 ++++++++++++++++++++++++----------
> include/linux/sched.h | 5 +----
> init/init_task.c | 3 +--
> init/main.c | 2 ++
> kernel/auditsc.c | 51 ++++++++++++++++++++++++++++++++++++++++++---------
> kernel/fork.c | 4 +++-
> 6 files changed, 73 insertions(+), 26 deletions(-)
>
> diff --git a/include/linux/audit.h b/include/linux/audit.h
> index 9334fbe..8964332 100644
> --- a/include/linux/audit.h
> +++ b/include/linux/audit.h
> @@ -219,8 +219,15 @@ static inline void audit_log_task_info(struct audit_buffer *ab,
>
> /* These are defined in auditsc.c */
> /* Public API */

Not sure if the structure below belongs after "Public API".
Is it part of the public API ?

> +struct audit_task_info {
> + kuid_t loginuid;
> + unsigned int sessionid;
> + struct audit_context *ctx;
> +};

Add empty line ?

> +extern struct audit_task_info init_struct_audit;
> +extern void __init audit_task_init(void);
> extern int audit_alloc(struct task_struct *task);
> -extern void __audit_free(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);
> @@ -242,12 +249,15 @@ 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 current->audit->ctx;
> + else
> + return NULL;

Unnecessary else (and static checkers may complain).

> }
>
> static inline bool audit_dummy_context(void)
> @@ -255,11 +265,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)
> @@ -331,12 +337,18 @@ extern int auditsc_get_stamp(struct audit_context *ctx,
>
> static inline kuid_t audit_get_loginuid(struct task_struct *tsk)
> {
> - return tsk->loginuid;
> + if (tsk->audit)
> + return tsk->audit->loginuid;
> + else
> + return INVALID_UID;

Unnecessary else.

> }
>
> static inline unsigned int audit_get_sessionid(struct task_struct *tsk)
> {
> - return tsk->sessionid;
> + if (tsk->audit)
> + return tsk->audit->sessionid;
> + else
> + return AUDIT_SID_UNSET;

Unnecessary else.

> }
>
> extern void __audit_ipc_obj(struct kern_ipc_perm *ipcp);
> @@ -461,6 +473,8 @@ static inline void audit_fanotify(unsigned int response)
> extern int audit_n_rules;
> extern int audit_signals;
> #else /* CONFIG_AUDITSYSCALL */
> +static inline void __init audit_task_init(void)
> +{ }
> static inline int audit_alloc(struct task_struct *task)
> {
> return 0;
> diff --git a/include/linux/sched.h b/include/linux/sched.h
> index 87bf02d..e117272 100644
> --- a/include/linux/sched.h
> +++ b/include/linux/sched.h
> @@ -30,7 +30,6 @@
> #include <linux/rseq.h>
>
> /* task_struct member predeclarations (sorted alphabetically): */
> -struct audit_context;
> struct backing_dev_info;
> struct bio_list;
> struct blk_plug;
> @@ -873,10 +872,8 @@ struct task_struct {
>
> struct callback_head *task_works;
>
> - struct audit_context *audit_context;
> #ifdef CONFIG_AUDITSYSCALL
> - 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 74f60ba..4058840 100644
> --- a/init/init_task.c
> +++ b/init/init_task.c
> @@ -119,8 +119,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_AUDITSYSCALL
> - .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 3b4ada1..6aba171 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>
> @@ -721,6 +722,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/auditsc.c b/kernel/auditsc.c
> index fb20746..88779a7 100644
> --- a/kernel/auditsc.c
> +++ b/kernel/auditsc.c
> @@ -841,7 +841,7 @@ static inline struct audit_context *audit_take_context(struct task_struct *tsk,
> int return_valid,
> long return_code)
> {
> - struct audit_context *context = tsk->audit_context;
> + struct audit_context *context = tsk->audit->ctx;
>
> if (!context)
> return NULL;
> @@ -926,6 +926,15 @@ static inline struct audit_context *audit_alloc_context(enum audit_state state)
> return context;
> }
>
> +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 context block for a task
> * @tsk: task
> @@ -940,17 +949,28 @@ int audit_alloc(struct task_struct *tsk)
> struct audit_context *context;
> enum audit_state state;
> char *key = NULL;
> + struct audit_task_info *info;
> +
> + info = kmem_cache_zalloc(audit_task_cache, GFP_KERNEL);
> + if (!info)
> + return -ENOMEM;
> + info->loginuid = audit_get_loginuid(current);
> + info->sessionid = audit_get_sessionid(current);
> + tsk->audit = info;
>
> if (likely(!audit_ever_enabled))
> return 0; /* Return if not auditing. */
>
> state = audit_filter_task(tsk, &key);
> if (state == AUDIT_DISABLED) {
> + audit_set_context(tsk, NULL);
> clear_tsk_thread_flag(tsk, TIF_SYSCALL_AUDIT);
> return 0;
> }
>
> if (!(context = audit_alloc_context(state))) {
> + tsk->audit = NULL;
> + kmem_cache_free(audit_task_cache, info);
> kfree(key);
> audit_log_lost("out of memory in audit_alloc");
> return -ENOMEM;
> @@ -962,6 +982,12 @@ int audit_alloc(struct task_struct *tsk)
> return 0;
> }
>
> +struct audit_task_info init_struct_audit = {
> + .loginuid = INVALID_UID,
> + .sessionid = AUDIT_SID_UNSET,
> + .ctx = NULL,
> +};
> +
> static inline void audit_free_context(struct audit_context *context)
> {
> audit_free_names(context);
> @@ -1469,26 +1495,33 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
> }
>
> /**
> - * __audit_free - free a per-task audit context
> + * audit_free - free a per-task audit context
> * @tsk: task whose audit context block to free
> *
> * Called from copy_process and do_exit
> */
> -void __audit_free(struct task_struct *tsk)
> +void audit_free(struct task_struct *tsk)
> {
> struct audit_context *context;
> + struct audit_task_info *info;
>
> context = audit_take_context(tsk, 0, 0);
> - if (!context)
> - return;
> -
> /* Check for system calls that do not go through the exit
> * function (e.g., exit_group), then free context block.
> * We use GFP_ATOMIC here because we might be doing this
> * in the context of the idle thread */
> /* that can happen only if we are called from do_exit() */
> - if (context->in_syscall && context->current_state == AUDIT_RECORD_CONTEXT)
> + if (context && context->in_syscall &&
> + context->current_state == AUDIT_RECORD_CONTEXT)
> audit_log_exit(context, 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);
> + if (!context)
> + return;
> if (!list_empty(&context->killed_trees))
> audit_kill_trees(&context->killed_trees);

Looks kind of terrible with the repeated check if context is NULL.
Maybe reorder ?

context = audit_take_context(tsk, 0, 0);
if (context) {
/* do all the context work */
}
kmem_cache_free(audit_task_cache, tsk->audit);
tsk->audit = NULL; // is that even necessary ?

If "info" is really needed, ie if tsk (and tsk->audit) can be accessed
from another thread in parallel, I'd be a bit concerned about the lack
of sync() or similar after clearing tsk->audit.

Another option might have been to separate audit_free() into
audit_free_context() and audit_free_info().

>
> @@ -2071,8 +2104,8 @@ int audit_set_loginuid(kuid_t loginuid)
> sessionid = (unsigned int)atomic_inc_return(&session_id);
> }
>
> - task->sessionid = sessionid;
> - task->loginuid = loginuid;
> + task->audit->sessionid = sessionid;
> + task->audit->loginuid = loginuid;
> out:
> audit_log_set_loginuid(oldloginuid, loginuid, oldsessionid, sessionid, rc);
> return rc;
> diff --git a/kernel/fork.c b/kernel/fork.c
> index 9440d61..1bfb0ff 100644
> --- a/kernel/fork.c
> +++ b/kernel/fork.c
> @@ -1721,7 +1721,9 @@ 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);
> +#ifdef CONFIG_AUDITSYSCALL
> + p->audit = NULL;
> +#endif /* CONFIG_AUDITSYSCALL */

audit_alloc() is called a bit later and sets p->audit, so I don't think
this is really necessary.

> cgroup_fork(p);
> #ifdef CONFIG_NUMA
> p->mempolicy = mpol_dup(p->mempolicy);

2019-01-04 17:25:15

by Richard Guy Briggs

[permalink] [raw]
Subject: Re: [PATCH ghak90 (was ghak32) V4 01/10] audit: collect audit task parameters

On 2019-01-03 18:50, Guenter Roeck wrote:
> Hi Richard,
>
> On Tue, Jul 31, 2018 at 04:07:36PM -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.
> >
> > See: https://github.com/linux-audit/audit-kernel/issues/81
> >
> > Signed-off-by: Richard Guy Briggs <[email protected]>
>
> Overall I am not sure if keeping task_struct a bit smaller is worth
> the added complexity, but I guess that is just me.

The motivation was to consolidate all the audit bits into one pointer,
isolating them from the rest of the kernel, restricting access only to
helper functions to prevent abuse by other subsystems and trying to
reduce kABI issues in the future. I agree it is a bit more complex. It
was provoked by the need to add contid which seemed to make the most
sense as a peer to loginuid and sessionid, and adding it to task_struct
would have made it a bit too generic and available.

This is addressed at some length by Paul Moore here in v2:
https://lkml.org/lkml/2018/4/18/759

> Anyway, couple of nitpicks. Please feel free to ignore, and my apologies
> if some of all of the comments are duplicates.

Noted. They all look like reasonable improvements, particulaly the
unnecessary else and default return. Thanks. The double context check
may go away anyways based on the removal of audit_take_context() in
Paul's 2a1fe215e730 ("audit: use current whenever possible") which has
yet to be incorporated.

> Guenter
>
> > ---
> > include/linux/audit.h | 34 ++++++++++++++++++++++++----------
> > include/linux/sched.h | 5 +----
> > init/init_task.c | 3 +--
> > init/main.c | 2 ++
> > kernel/auditsc.c | 51 ++++++++++++++++++++++++++++++++++++++++++---------
> > kernel/fork.c | 4 +++-
> > 6 files changed, 73 insertions(+), 26 deletions(-)
> >
> > diff --git a/include/linux/audit.h b/include/linux/audit.h
> > index 9334fbe..8964332 100644
> > --- a/include/linux/audit.h
> > +++ b/include/linux/audit.h
> > @@ -219,8 +219,15 @@ static inline void audit_log_task_info(struct audit_buffer *ab,
> >
> > /* These are defined in auditsc.c */
> > /* Public API */
>
> Not sure if the structure below belongs after "Public API".
> Is it part of the public API ?
>
> > +struct audit_task_info {
> > + kuid_t loginuid;
> > + unsigned int sessionid;
> > + struct audit_context *ctx;
> > +};
>
> Add empty line ?
>
> > +extern struct audit_task_info init_struct_audit;
> > +extern void __init audit_task_init(void);
> > extern int audit_alloc(struct task_struct *task);
> > -extern void __audit_free(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);
> > @@ -242,12 +249,15 @@ 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 current->audit->ctx;
> > + else
> > + return NULL;
>
> Unnecessary else (and static checkers may complain).
>
> > }
> >
> > static inline bool audit_dummy_context(void)
> > @@ -255,11 +265,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)
> > @@ -331,12 +337,18 @@ extern int auditsc_get_stamp(struct audit_context *ctx,
> >
> > static inline kuid_t audit_get_loginuid(struct task_struct *tsk)
> > {
> > - return tsk->loginuid;
> > + if (tsk->audit)
> > + return tsk->audit->loginuid;
> > + else
> > + return INVALID_UID;
>
> Unnecessary else.
>
> > }
> >
> > static inline unsigned int audit_get_sessionid(struct task_struct *tsk)
> > {
> > - return tsk->sessionid;
> > + if (tsk->audit)
> > + return tsk->audit->sessionid;
> > + else
> > + return AUDIT_SID_UNSET;
>
> Unnecessary else.
>
> > }
> >
> > extern void __audit_ipc_obj(struct kern_ipc_perm *ipcp);
> > @@ -461,6 +473,8 @@ static inline void audit_fanotify(unsigned int response)
> > extern int audit_n_rules;
> > extern int audit_signals;
> > #else /* CONFIG_AUDITSYSCALL */
> > +static inline void __init audit_task_init(void)
> > +{ }
> > static inline int audit_alloc(struct task_struct *task)
> > {
> > return 0;
> > diff --git a/include/linux/sched.h b/include/linux/sched.h
> > index 87bf02d..e117272 100644
> > --- a/include/linux/sched.h
> > +++ b/include/linux/sched.h
> > @@ -30,7 +30,6 @@
> > #include <linux/rseq.h>
> >
> > /* task_struct member predeclarations (sorted alphabetically): */
> > -struct audit_context;
> > struct backing_dev_info;
> > struct bio_list;
> > struct blk_plug;
> > @@ -873,10 +872,8 @@ struct task_struct {
> >
> > struct callback_head *task_works;
> >
> > - struct audit_context *audit_context;
> > #ifdef CONFIG_AUDITSYSCALL
> > - 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 74f60ba..4058840 100644
> > --- a/init/init_task.c
> > +++ b/init/init_task.c
> > @@ -119,8 +119,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_AUDITSYSCALL
> > - .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 3b4ada1..6aba171 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>
> > @@ -721,6 +722,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/auditsc.c b/kernel/auditsc.c
> > index fb20746..88779a7 100644
> > --- a/kernel/auditsc.c
> > +++ b/kernel/auditsc.c
> > @@ -841,7 +841,7 @@ static inline struct audit_context *audit_take_context(struct task_struct *tsk,
> > int return_valid,
> > long return_code)
> > {
> > - struct audit_context *context = tsk->audit_context;
> > + struct audit_context *context = tsk->audit->ctx;
> >
> > if (!context)
> > return NULL;
> > @@ -926,6 +926,15 @@ static inline struct audit_context *audit_alloc_context(enum audit_state state)
> > return context;
> > }
> >
> > +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 context block for a task
> > * @tsk: task
> > @@ -940,17 +949,28 @@ int audit_alloc(struct task_struct *tsk)
> > struct audit_context *context;
> > enum audit_state state;
> > char *key = NULL;
> > + struct audit_task_info *info;
> > +
> > + info = kmem_cache_zalloc(audit_task_cache, GFP_KERNEL);
> > + if (!info)
> > + return -ENOMEM;
> > + info->loginuid = audit_get_loginuid(current);
> > + info->sessionid = audit_get_sessionid(current);
> > + tsk->audit = info;
> >
> > if (likely(!audit_ever_enabled))
> > return 0; /* Return if not auditing. */
> >
> > state = audit_filter_task(tsk, &key);
> > if (state == AUDIT_DISABLED) {
> > + audit_set_context(tsk, NULL);
> > clear_tsk_thread_flag(tsk, TIF_SYSCALL_AUDIT);
> > return 0;
> > }
> >
> > if (!(context = audit_alloc_context(state))) {
> > + tsk->audit = NULL;
> > + kmem_cache_free(audit_task_cache, info);
> > kfree(key);
> > audit_log_lost("out of memory in audit_alloc");
> > return -ENOMEM;
> > @@ -962,6 +982,12 @@ int audit_alloc(struct task_struct *tsk)
> > return 0;
> > }
> >
> > +struct audit_task_info init_struct_audit = {
> > + .loginuid = INVALID_UID,
> > + .sessionid = AUDIT_SID_UNSET,
> > + .ctx = NULL,
> > +};
> > +
> > static inline void audit_free_context(struct audit_context *context)
> > {
> > audit_free_names(context);
> > @@ -1469,26 +1495,33 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
> > }
> >
> > /**
> > - * __audit_free - free a per-task audit context
> > + * audit_free - free a per-task audit context
> > * @tsk: task whose audit context block to free
> > *
> > * Called from copy_process and do_exit
> > */
> > -void __audit_free(struct task_struct *tsk)
> > +void audit_free(struct task_struct *tsk)
> > {
> > struct audit_context *context;
> > + struct audit_task_info *info;
> >
> > context = audit_take_context(tsk, 0, 0);
> > - if (!context)
> > - return;
> > -
> > /* Check for system calls that do not go through the exit
> > * function (e.g., exit_group), then free context block.
> > * We use GFP_ATOMIC here because we might be doing this
> > * in the context of the idle thread */
> > /* that can happen only if we are called from do_exit() */
> > - if (context->in_syscall && context->current_state == AUDIT_RECORD_CONTEXT)
> > + if (context && context->in_syscall &&
> > + context->current_state == AUDIT_RECORD_CONTEXT)
> > audit_log_exit(context, 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);
> > + if (!context)
> > + return;
> > if (!list_empty(&context->killed_trees))
> > audit_kill_trees(&context->killed_trees);
>
> Looks kind of terrible with the repeated check if context is NULL.
> Maybe reorder ?
>
> context = audit_take_context(tsk, 0, 0);
> if (context) {
> /* do all the context work */
> }
> kmem_cache_free(audit_task_cache, tsk->audit);
> tsk->audit = NULL; // is that even necessary ?
>
> If "info" is really needed, ie if tsk (and tsk->audit) can be accessed
> from another thread in parallel, I'd be a bit concerned about the lack
> of sync() or similar after clearing tsk->audit.
>
> Another option might have been to separate audit_free() into
> audit_free_context() and audit_free_info().
>
> >
> > @@ -2071,8 +2104,8 @@ int audit_set_loginuid(kuid_t loginuid)
> > sessionid = (unsigned int)atomic_inc_return(&session_id);
> > }
> >
> > - task->sessionid = sessionid;
> > - task->loginuid = loginuid;
> > + task->audit->sessionid = sessionid;
> > + task->audit->loginuid = loginuid;
> > out:
> > audit_log_set_loginuid(oldloginuid, loginuid, oldsessionid, sessionid, rc);
> > return rc;
> > diff --git a/kernel/fork.c b/kernel/fork.c
> > index 9440d61..1bfb0ff 100644
> > --- a/kernel/fork.c
> > +++ b/kernel/fork.c
> > @@ -1721,7 +1721,9 @@ 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);
> > +#ifdef CONFIG_AUDITSYSCALL
> > + p->audit = NULL;
> > +#endif /* CONFIG_AUDITSYSCALL */
>
> audit_alloc() is called a bit later and sets p->audit, so I don't think
> this is really necessary.
>
> > cgroup_fork(p);
> > #ifdef CONFIG_NUMA
> > p->mempolicy = mpol_dup(p->mempolicy);

- RGB

--
Richard Guy Briggs <[email protected]>
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

2019-01-04 22:27:49

by Guenter Roeck

[permalink] [raw]
Subject: Re: [PATCH ghak90 (was ghak32) V4 01/10] audit: collect audit task parameters

On Fri, Jan 04, 2019 at 09:57:35AM -0500, Richard Guy Briggs wrote:
> On 2019-01-03 18:50, Guenter Roeck wrote:
> > Hi Richard,
> >
> > On Tue, Jul 31, 2018 at 04:07:36PM -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.
> > >
> > > See: https://github.com/linux-audit/audit-kernel/issues/81
> > >
> > > Signed-off-by: Richard Guy Briggs <[email protected]>
> >
> > Overall I am not sure if keeping task_struct a bit smaller is worth
> > the added complexity, but I guess that is just me.
>
> The motivation was to consolidate all the audit bits into one pointer,
> isolating them from the rest of the kernel, restricting access only to
> helper functions to prevent abuse by other subsystems and trying to
> reduce kABI issues in the future. I agree it is a bit more complex. It
> was provoked by the need to add contid which seemed to make the most
> sense as a peer to loginuid and sessionid, and adding it to task_struct
> would have made it a bit too generic and available.
>
> This is addressed at some length by Paul Moore here in v2:
> https://lkml.org/lkml/2018/4/18/759
>
That makes sense. Thanks a lot for the clarification.

Guenter

2019-01-11 02:31:14

by Richard Guy Briggs

[permalink] [raw]
Subject: Re: [PATCH ghak90 (was ghak32) V4 06/10] audit: add containerid support for tty_audit

On 2019-01-03 15:11, Paul Moore wrote:
> On Wed, Oct 31, 2018 at 5:17 PM Richard Guy Briggs <[email protected]> wrote:
> > On 2018-10-19 19:17, Paul Moore wrote:
> > > On Sun, Aug 5, 2018 at 4:33 AM Richard Guy Briggs
> <[email protected]> wrote:
> > > > Add audit container identifier auxiliary record to tty logging rule
> > > > event standalone records.
> > > >
> > > > Signed-off-by: Richard Guy Briggs <[email protected]>
> > > > Acked-by: Serge Hallyn <[email protected]>
> > > > ---
> > > > drivers/tty/tty_audit.c | 5 ++++-
> > > > 1 file changed, 4 insertions(+), 1 deletion(-)
> > > >
> > > > diff --git a/drivers/tty/tty_audit.c b/drivers/tty/tty_audit.c
> > > > index 50f567b..3e21477 100644
> > > > --- a/drivers/tty/tty_audit.c
> > > > +++ b/drivers/tty/tty_audit.c
> > > > @@ -66,8 +66,9 @@ static void tty_audit_log(const char *description, dev_t dev,
> > > > uid_t uid = from_kuid(&amp;init_user_ns, task_uid(tsk));
> > > > uid_t loginuid = from_kuid(&amp;init_user_ns, audit_get_loginuid(tsk));
> > > > unsigned int sessionid = audit_get_sessionid(tsk);
> > > > + struct audit_context *context = audit_alloc_local(GFP_KERNEL);
> > > >
> > > > - ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_TTY);
> > > > + ab = audit_log_start(context, GFP_KERNEL, AUDIT_TTY);
> > > > if (ab) {
> > > > char name[sizeof(tsk->comm)];
> > > >
> > > > @@ -80,6 +81,8 @@ static void tty_audit_log(const char *description, dev_t dev,
> > > > audit_log_n_hex(ab, data, size);
> > > > audit_log_end(ab);
> > > > }
> > > > + audit_log_contid(context, "tty", audit_get_contid(tsk));
> > > > + audit_free_context(context);
> > > > }
> > >
> > > Since I never polished up my task_struct/current fix patch enough to
> > > get it past RFC status during this development window (new job, stolen
> > > laptop, etc.) *and* it looks like you are going to need at least one
> > > more respin of this patchset, go ahead and fix this patch to use
> > > current instead of generating a local context. I'll deal with the
> > > merge fallout if/when it happens.
> >
> > Sure, I will switch it to current in the call to audit_get_contid().
> >
> > The local context is a distinct issue. Like USER records, I prefer
> > local due to potential record volume, it is already trackable as far as
> > Steve is concerned, and if it is to be connected with the syscall
> > record, it should be linked to syscall records in a seperate new github
> > issue with its own patch. It accumulates events until the buffer is
> > flushed to a record, so the timestamp only represents the flush (usually
> > user "CR/enter").
>
> Generally, yes, associating records is a separate issue, but in this
> particular case you are changing this record by making it a "local"
> record, which as we've discussed before, I view as a necessary evil
> and something that must be minimized. A quick look at the
> tty_audit_log() callers shows tty_audit_tiocsti() which is an ioctl
> handler (and thus current should be valid and correct), and
> tty_audit_buf_push() whose callers all seem have valid and correct
> current values; if you find that not to be the case please let me
> know.

Unless I'm misunderstanding what "local" means, it already had a local
context by virtue of having a NULL context since it was never previously
connected to syscall events, so changing it to a local context doesn't
change that other than making it possible to associate an auxiliary
audit container identifier record.

The reasoning I'm also applying here is that the contents of this record
don't all come from this one syscall, but most likely came in from an
entire line of individual keystrokes, so the syscall information is only
from the last one of those syscalls, though that syscall information
other than the timestamp should be the same.

Reading your reply above it isn't clear to me that I had made these two
points clear previously. If you still think this record should be
associated to a syscall despite my reasoning above, I'm willing to
connect it, but will do so in a seperate issue/patch.

> > > Local contexts are a last resort. If you ever find yourself writing
> > > code that generates a local context, you should first be 100% certain
> > > that the event is not the the result of a process initiated action (in
> > > which case it should take from the task's context).
> >
> > Well, I'm 100% certain it is linked to a process, but so are USER
> > records that are already being discussed as the exception. This is
> > basically a keystroke logger (that has a flag to omit passwords).
>
> --
> paul moore

- RGB

--
Richard Guy Briggs <[email protected]>
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

2019-01-11 03:49:27

by Paul Moore

[permalink] [raw]
Subject: Re: [PATCH ghak90 (was ghak32) V4 06/10] audit: add containerid support for tty_audit

On Thu, Jan 10, 2019 at 5:59 PM Richard Guy Briggs <[email protected]> wrote:
> On 2019-01-03 15:11, Paul Moore wrote:
> > On Wed, Oct 31, 2018 at 5:17 PM Richard Guy Briggs <[email protected]> wrote:
> > > On 2018-10-19 19:17, Paul Moore wrote:
> > > > On Sun, Aug 5, 2018 at 4:33 AM Richard Guy Briggs
> > <[email protected]> wrote:
> > > > > Add audit container identifier auxiliary record to tty logging rule
> > > > > event standalone records.
> > > > >
> > > > > Signed-off-by: Richard Guy Briggs <[email protected]>
> > > > > Acked-by: Serge Hallyn <[email protected]>
> > > > > ---
> > > > > drivers/tty/tty_audit.c | 5 ++++-
> > > > > 1 file changed, 4 insertions(+), 1 deletion(-)
> > > > >
> > > > > diff --git a/drivers/tty/tty_audit.c b/drivers/tty/tty_audit.c
> > > > > index 50f567b..3e21477 100644
> > > > > --- a/drivers/tty/tty_audit.c
> > > > > +++ b/drivers/tty/tty_audit.c
> > > > > @@ -66,8 +66,9 @@ static void tty_audit_log(const char *description, dev_t dev,
> > > > > uid_t uid = from_kuid(&amp;init_user_ns, task_uid(tsk));
> > > > > uid_t loginuid = from_kuid(&amp;init_user_ns, audit_get_loginuid(tsk));
> > > > > unsigned int sessionid = audit_get_sessionid(tsk);
> > > > > + struct audit_context *context = audit_alloc_local(GFP_KERNEL);
> > > > >
> > > > > - ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_TTY);
> > > > > + ab = audit_log_start(context, GFP_KERNEL, AUDIT_TTY);
> > > > > if (ab) {
> > > > > char name[sizeof(tsk->comm)];
> > > > >
> > > > > @@ -80,6 +81,8 @@ static void tty_audit_log(const char *description, dev_t dev,
> > > > > audit_log_n_hex(ab, data, size);
> > > > > audit_log_end(ab);
> > > > > }
> > > > > + audit_log_contid(context, "tty", audit_get_contid(tsk));
> > > > > + audit_free_context(context);
> > > > > }
> > > >
> > > > Since I never polished up my task_struct/current fix patch enough to
> > > > get it past RFC status during this development window (new job, stolen
> > > > laptop, etc.) *and* it looks like you are going to need at least one
> > > > more respin of this patchset, go ahead and fix this patch to use
> > > > current instead of generating a local context. I'll deal with the
> > > > merge fallout if/when it happens.
> > >
> > > Sure, I will switch it to current in the call to audit_get_contid().
> > >
> > > The local context is a distinct issue. Like USER records, I prefer
> > > local due to potential record volume, it is already trackable as far as
> > > Steve is concerned, and if it is to be connected with the syscall
> > > record, it should be linked to syscall records in a seperate new github
> > > issue with its own patch. It accumulates events until the buffer is
> > > flushed to a record, so the timestamp only represents the flush (usually
> > > user "CR/enter").
> >
> > Generally, yes, associating records is a separate issue, but in this
> > particular case you are changing this record by making it a "local"
> > record, which as we've discussed before, I view as a necessary evil
> > and something that must be minimized. A quick look at the
> > tty_audit_log() callers shows tty_audit_tiocsti() which is an ioctl
> > handler (and thus current should be valid and correct), and
> > tty_audit_buf_push() whose callers all seem have valid and correct
> > current values; if you find that not to be the case please let me
> > know.
>
> Unless I'm misunderstanding what "local" means, it already had a local
> context by virtue of having a NULL context since it was never previously
> connected to syscall events, so changing it to a local context doesn't
> change that other than making it possible to associate an auxiliary
> audit container identifier record.
>
> The reasoning I'm also applying here is that the contents of this record
> don't all come from this one syscall, but most likely came in from an
> entire line of individual keystrokes, so the syscall information is only
> from the last one of those syscalls, though that syscall information
> other than the timestamp should be the same.

Looking at the callers to tty_audit_log(), I think we can all agree
that in the tty_audit_tiocsti() case it is correct to associate the
tty record with current, as it is the current task which sent the
ioctl with the data. Do you not agree?

With tty_audit_buf_push() we need to do a bit more work to track down
all the callers. Looking quickly it appears that all of the
tty_audit_add_data() callers are copying data to/from userspace, so
associating these tty records with their syscall would seem
appropriate. With tty_audit_push() it either appears to be
tty_audit_tiocsti() (again) or more userspace copy routines. I didn't
bother looking at tty_audit_exit() because that seemed pretty clear to
be something worth associating with a syscall. You may find that if
you dig deeper into the call stacks things fall apart and there are
cases where the records shouldn't be associated with the current
syscall, but based on what I'm seeing right now that doesn't appear to
be the case.

> Reading your reply above it isn't clear to me that I had made these two
> points clear previously. If you still think this record should be
> associated to a syscall despite my reasoning above, I'm willing to
> connect it, but will do so in a seperate issue/patch.

--
paul moore
http://www.paul-moore.com

2019-01-11 05:23:43

by Richard Guy Briggs

[permalink] [raw]
Subject: Re: [PATCH ghak90 (was ghak32) V4 06/10] audit: add containerid support for tty_audit

On 2019-01-10 20:12, Paul Moore wrote:
> On Thu, Jan 10, 2019 at 5:59 PM Richard Guy Briggs <[email protected]> wrote:
> > On 2019-01-03 15:11, Paul Moore wrote:
> > > On Wed, Oct 31, 2018 at 5:17 PM Richard Guy Briggs <[email protected]> wrote:
> > > > On 2018-10-19 19:17, Paul Moore wrote:
> > > > > On Sun, Aug 5, 2018 at 4:33 AM Richard Guy Briggs
> > > <[email protected]> wrote:
> > > > > > Add audit container identifier auxiliary record to tty logging rule
> > > > > > event standalone records.
> > > > > >
> > > > > > Signed-off-by: Richard Guy Briggs <[email protected]>
> > > > > > Acked-by: Serge Hallyn <[email protected]>
> > > > > > ---
> > > > > > drivers/tty/tty_audit.c | 5 ++++-
> > > > > > 1 file changed, 4 insertions(+), 1 deletion(-)
> > > > > >
> > > > > > diff --git a/drivers/tty/tty_audit.c b/drivers/tty/tty_audit.c
> > > > > > index 50f567b..3e21477 100644
> > > > > > --- a/drivers/tty/tty_audit.c
> > > > > > +++ b/drivers/tty/tty_audit.c
> > > > > > @@ -66,8 +66,9 @@ static void tty_audit_log(const char *description, dev_t dev,
> > > > > > uid_t uid = from_kuid(&amp;init_user_ns, task_uid(tsk));
> > > > > > uid_t loginuid = from_kuid(&amp;init_user_ns, audit_get_loginuid(tsk));
> > > > > > unsigned int sessionid = audit_get_sessionid(tsk);
> > > > > > + struct audit_context *context = audit_alloc_local(GFP_KERNEL);
> > > > > >
> > > > > > - ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_TTY);
> > > > > > + ab = audit_log_start(context, GFP_KERNEL, AUDIT_TTY);
> > > > > > if (ab) {
> > > > > > char name[sizeof(tsk->comm)];
> > > > > >
> > > > > > @@ -80,6 +81,8 @@ static void tty_audit_log(const char *description, dev_t dev,
> > > > > > audit_log_n_hex(ab, data, size);
> > > > > > audit_log_end(ab);
> > > > > > }
> > > > > > + audit_log_contid(context, "tty", audit_get_contid(tsk));
> > > > > > + audit_free_context(context);
> > > > > > }
> > > > >
> > > > > Since I never polished up my task_struct/current fix patch enough to
> > > > > get it past RFC status during this development window (new job, stolen
> > > > > laptop, etc.) *and* it looks like you are going to need at least one
> > > > > more respin of this patchset, go ahead and fix this patch to use
> > > > > current instead of generating a local context. I'll deal with the
> > > > > merge fallout if/when it happens.
> > > >
> > > > Sure, I will switch it to current in the call to audit_get_contid().
> > > >
> > > > The local context is a distinct issue. Like USER records, I prefer
> > > > local due to potential record volume, it is already trackable as far as
> > > > Steve is concerned, and if it is to be connected with the syscall
> > > > record, it should be linked to syscall records in a seperate new github
> > > > issue with its own patch. It accumulates events until the buffer is
> > > > flushed to a record, so the timestamp only represents the flush (usually
> > > > user "CR/enter").
> > >
> > > Generally, yes, associating records is a separate issue, but in this
> > > particular case you are changing this record by making it a "local"
> > > record, which as we've discussed before, I view as a necessary evil
> > > and something that must be minimized. A quick look at the
> > > tty_audit_log() callers shows tty_audit_tiocsti() which is an ioctl
> > > handler (and thus current should be valid and correct), and
> > > tty_audit_buf_push() whose callers all seem have valid and correct
> > > current values; if you find that not to be the case please let me
> > > know.
> >
> > Unless I'm misunderstanding what "local" means, it already had a local
> > context by virtue of having a NULL context since it was never previously
> > connected to syscall events, so changing it to a local context doesn't
> > change that other than making it possible to associate an auxiliary
> > audit container identifier record.
> >
> > The reasoning I'm also applying here is that the contents of this record
> > don't all come from this one syscall, but most likely came in from an
> > entire line of individual keystrokes, so the syscall information is only
> > from the last one of those syscalls, though that syscall information
> > other than the timestamp should be the same.
>
> Looking at the callers to tty_audit_log(), I think we can all agree
> that in the tty_audit_tiocsti() case it is correct to associate the
> tty record with current, as it is the current task which sent the
> ioctl with the data. Do you not agree?

I'm fine with that, yes.

> With tty_audit_buf_push() we need to do a bit more work to track down
> all the callers. Looking quickly it appears that all of the
> tty_audit_add_data() callers are copying data to/from userspace, so
> associating these tty records with their syscall would seem
> appropriate. With tty_audit_push() it either appears to be
> tty_audit_tiocsti() (again) or more userspace copy routines. I didn't
> bother looking at tty_audit_exit() because that seemed pretty clear to
> be something worth associating with a syscall. You may find that if
> you dig deeper into the call stacks things fall apart and there are
> cases where the records shouldn't be associated with the current
> syscall, but based on what I'm seeing right now that doesn't appear to
> be the case.

Ok. Except that it might be multiple subsequent calls that assemble
that data, only flushed to an audit record on exceeding N_TTY_BUF_SIZE
(4k) or that task switching device and flushing the previous device or
that task switching icanon mode.

> > Reading your reply above it isn't clear to me that I had made these two
> > points clear previously. If you still think this record should be
> > associated to a syscall despite my reasoning above, I'm willing to
> > connect it, but will do so in a seperate issue/patch.

So can I conclude that you are fine with the buffering of the data from
multiple syscalls being associated with the output of that buffer to one
audit record with the last of those syscalls?

> paul moore

- RGB

--
Richard Guy Briggs <[email protected]>
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

2019-01-11 23:19:15

by Paul Moore

[permalink] [raw]
Subject: Re: [PATCH ghak90 (was ghak32) V4 06/10] audit: add containerid support for tty_audit

On Thu, Jan 10, 2019 at 10:39 PM Richard Guy Briggs <[email protected]> wrote:
> On 2019-01-10 20:12, Paul Moore wrote:
> > On Thu, Jan 10, 2019 at 5:59 PM Richard Guy Briggs <[email protected]> wrote:
> > > On 2019-01-03 15:11, Paul Moore wrote:
> > > > On Wed, Oct 31, 2018 at 5:17 PM Richard Guy Briggs <[email protected]> wrote:
> > > > > On 2018-10-19 19:17, Paul Moore wrote:
> > > > > > On Sun, Aug 5, 2018 at 4:33 AM Richard Guy Briggs
> > > > <[email protected]> wrote:
> > > > > > > Add audit container identifier auxiliary record to tty logging rule
> > > > > > > event standalone records.
> > > > > > >
> > > > > > > Signed-off-by: Richard Guy Briggs <[email protected]>
> > > > > > > Acked-by: Serge Hallyn <[email protected]>
> > > > > > > ---
> > > > > > > drivers/tty/tty_audit.c | 5 ++++-
> > > > > > > 1 file changed, 4 insertions(+), 1 deletion(-)
> > > > > > >
> > > > > > > diff --git a/drivers/tty/tty_audit.c b/drivers/tty/tty_audit.c
> > > > > > > index 50f567b..3e21477 100644
> > > > > > > --- a/drivers/tty/tty_audit.c
> > > > > > > +++ b/drivers/tty/tty_audit.c
> > > > > > > @@ -66,8 +66,9 @@ static void tty_audit_log(const char *description, dev_t dev,
> > > > > > > uid_t uid = from_kuid(&amp;init_user_ns, task_uid(tsk));
> > > > > > > uid_t loginuid = from_kuid(&amp;init_user_ns, audit_get_loginuid(tsk));
> > > > > > > unsigned int sessionid = audit_get_sessionid(tsk);
> > > > > > > + struct audit_context *context = audit_alloc_local(GFP_KERNEL);
> > > > > > >
> > > > > > > - ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_TTY);
> > > > > > > + ab = audit_log_start(context, GFP_KERNEL, AUDIT_TTY);
> > > > > > > if (ab) {
> > > > > > > char name[sizeof(tsk->comm)];
> > > > > > >
> > > > > > > @@ -80,6 +81,8 @@ static void tty_audit_log(const char *description, dev_t dev,
> > > > > > > audit_log_n_hex(ab, data, size);
> > > > > > > audit_log_end(ab);
> > > > > > > }
> > > > > > > + audit_log_contid(context, "tty", audit_get_contid(tsk));
> > > > > > > + audit_free_context(context);
> > > > > > > }
> > > > > >
> > > > > > Since I never polished up my task_struct/current fix patch enough to
> > > > > > get it past RFC status during this development window (new job, stolen
> > > > > > laptop, etc.) *and* it looks like you are going to need at least one
> > > > > > more respin of this patchset, go ahead and fix this patch to use
> > > > > > current instead of generating a local context. I'll deal with the
> > > > > > merge fallout if/when it happens.
> > > > >
> > > > > Sure, I will switch it to current in the call to audit_get_contid().
> > > > >
> > > > > The local context is a distinct issue. Like USER records, I prefer
> > > > > local due to potential record volume, it is already trackable as far as
> > > > > Steve is concerned, and if it is to be connected with the syscall
> > > > > record, it should be linked to syscall records in a seperate new github
> > > > > issue with its own patch. It accumulates events until the buffer is
> > > > > flushed to a record, so the timestamp only represents the flush (usually
> > > > > user "CR/enter").
> > > >
> > > > Generally, yes, associating records is a separate issue, but in this
> > > > particular case you are changing this record by making it a "local"
> > > > record, which as we've discussed before, I view as a necessary evil
> > > > and something that must be minimized. A quick look at the
> > > > tty_audit_log() callers shows tty_audit_tiocsti() which is an ioctl
> > > > handler (and thus current should be valid and correct), and
> > > > tty_audit_buf_push() whose callers all seem have valid and correct
> > > > current values; if you find that not to be the case please let me
> > > > know.
> > >
> > > Unless I'm misunderstanding what "local" means, it already had a local
> > > context by virtue of having a NULL context since it was never previously
> > > connected to syscall events, so changing it to a local context doesn't
> > > change that other than making it possible to associate an auxiliary
> > > audit container identifier record.
> > >
> > > The reasoning I'm also applying here is that the contents of this record
> > > don't all come from this one syscall, but most likely came in from an
> > > entire line of individual keystrokes, so the syscall information is only
> > > from the last one of those syscalls, though that syscall information
> > > other than the timestamp should be the same.
> >
> > Looking at the callers to tty_audit_log(), I think we can all agree
> > that in the tty_audit_tiocsti() case it is correct to associate the
> > tty record with current, as it is the current task which sent the
> > ioctl with the data. Do you not agree?
>
> I'm fine with that, yes.
>
> > With tty_audit_buf_push() we need to do a bit more work to track down
> > all the callers. Looking quickly it appears that all of the
> > tty_audit_add_data() callers are copying data to/from userspace, so
> > associating these tty records with their syscall would seem
> > appropriate. With tty_audit_push() it either appears to be
> > tty_audit_tiocsti() (again) or more userspace copy routines. I didn't
> > bother looking at tty_audit_exit() because that seemed pretty clear to
> > be something worth associating with a syscall. You may find that if
> > you dig deeper into the call stacks things fall apart and there are
> > cases where the records shouldn't be associated with the current
> > syscall, but based on what I'm seeing right now that doesn't appear to
> > be the case.
>
> Ok. Except that it might be multiple subsequent calls that assemble
> that data, only flushed to an audit record on exceeding N_TTY_BUF_SIZE
> (4k) or that task switching device and flushing the previous device or
> that task switching icanon mode.

It seems just as reasonable to associate it with that final triggering
syscall just as much as it seems reasonable to log the buffered tty
data via the audit subsystem. If for some reason we need to
dissociate the tty data from the syscall data I don't see why we can't
make that change in the future.

> > > Reading your reply above it isn't clear to me that I had made these two
> > > points clear previously. If you still think this record should be
> > > associated to a syscall despite my reasoning above, I'm willing to
> > > connect it, but will do so in a seperate issue/patch.
>
> So can I conclude that you are fine with the buffering of the data from
> multiple syscalls being associated with the output of that buffer to one
> audit record with the last of those syscalls?

--
paul moore
http://www.paul-moore.com

2019-01-24 20:37:20

by Richard Guy Briggs

[permalink] [raw]
Subject: Re: [PATCH ghak90 (was ghak32) V4 01/10] audit: collect audit task parameters

On 2019-01-03 15:10, Paul Moore wrote:
> On Thu, Nov 1, 2018 at 6:07 PM Richard Guy Briggs <[email protected]> wrote:
> > On 2018-10-19 19:15, Paul Moore wrote:
> > > On Sun, Aug 5, 2018 at 4:32 AM Richard Guy Briggs <[email protected]> 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.
> > > >
> > > > See: https://github.com/linux-audit/audit-kernel/issues/81
> > > >
> > > > Signed-off-by: Richard Guy Briggs <[email protected]>
> > > > ---
> > > > include/linux/audit.h | 34 ++++++++++++++++++++++++----------
> > > > include/linux/sched.h | 5 +----
> > > > init/init_task.c | 3 +--
> > > > init/main.c | 2 ++
> > > > kernel/auditsc.c | 51 ++++++++++++++++++++++++++++++++++++++++++---------
> > > > kernel/fork.c | 4 +++-
> > > > 6 files changed, 73 insertions(+), 26 deletions(-)
> > >
> > > ...
> > >
> > > > diff --git a/include/linux/sched.h b/include/linux/sched.h
> > > > index 87bf02d..e117272 100644
> > > > --- a/include/linux/sched.h
> > > > +++ b/include/linux/sched.h
> > > > @@ -873,10 +872,8 @@ struct task_struct {
> > > >
> > > > struct callback_head *task_works;
> > > >
> > > > - struct audit_context *audit_context;
> > > > #ifdef CONFIG_AUDITSYSCALL
> > > > - kuid_t loginuid;
> > > > - unsigned int sessionid;
> > > > + struct audit_task_info *audit;
> > > > #endif
> > > > struct seccomp seccomp;
> > >
> > > Prior to this patch audit_context was available regardless of
> > > CONFIG_AUDITSYSCALL, after this patch the corresponding audit_context
> > > is only available when CONFIG_AUDITSYSCALL is defined.
> >
> > This was intentional since audit_context is not used when AUDITSYSCALL is
> > disabled. audit_alloc() was stubbed in that case to return 0. audit_context()
> > returned NULL.
> >
> > The fact that audit_context was still present in struct task_struct was an
> > oversight in the two patches already accepted:
> > ("audit: use inline function to get audit context")
> > ("audit: use inline function to get audit context")
> > that failed to hide or remove it from struct task_struct when it was no longer
> > relevant.
>
> Okay, in that case let's pull this out and fix this separately from
> the audit container ID patchset.

Ok, that should be addressed by ghak104.

> > On further digging, loginuid and sessionid (and audit_log_session_info) should
> > be part of CONFIG_AUDIT scope and not CONFIG_AUDITSYSCALL since it is used in
> > CONFIG_CHANGE, ANOM_LINK, FEATURE_CHANGE(, INTEGRITY_RULE), none of which are
> > otherwise dependent on AUDITSYSCALL.
>
> This looks like something else we should fix independently from this patchset.

Ok, this should be addressed by ghak105.

> > Looking ahead, contid should be treated like loginuid and sessionid, which are
> > currently only available when syscall auditting is.
>
> That seems reasonable. Eventually it would be great if we got rid of
> CONFIG_AUDITSYSCALL, but that is a separate issue, and something that
> is going to require work from the different arch/ABI folks to ensure
> everything is working properly.

So I'll plan to rebase on ghak104 and ghak105 once they are upstreamed.
I'll address the locking issues in the netns list and audit_sig_cid...

> > Converting records from standalone to syscall and checking audit_dummy_context
> > changes the nature of CONFIG_AUDIT/!CONFIG_AUDITSYSCALL separation.
> > eg: ANOM_LINK accompanied by PATH record (which needed CWD addition to be
> > complete anyways)

This has been addressed in ghak105, moving ANOM_LINK to auditsc.

> paul moore

- RGB

--
Richard Guy Briggs <[email protected]>
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