audit: implement container identifier
Subsystems (10)
v5 cover audit: implement container identifier
Implement kernel audit container identifier.
This patchset is a fifth based on the proposal document (V3) posted:
https://www.redhat.com/archives/linux-audit/2018-January/msg00014.html
The first patch was the last patch from ghak81 that was absorbed into this patchset since its primary justification is the rest of this patchset.
The second patch implements the proc fs write to set the audit container identifier of a process, emitting an AUDIT_CONTAINER_OP record to announce the registration of that audit container identifier on that process. This patch requires userspace support for record acceptance and proper type display.
The third implements reading the audit container identifier from the proc filesystem for debugging. This patch wasn't planned for upstream inclusion but is starting to become more likely.
The fourth implements the auxiliary record AUDIT_CONTAINER if an audit container identifier is associated with an event. This patch requires userspace support for proper type display.
The 5th adds signal and ptrace support.
The 6th creates a local audit context to be able to bind a standalone record with a locally created auxiliary record.
The 7th patch adds audit container identifier records to the user standalone records.
The 8th adds audit container identifier filtering to the exit, exclude and user lists. This patch adds the AUDIT_CONTID field and requires auditctl userspace support for the --contid option.
The 9th adds network namespace audit container identifier labelling based on member tasks' audit container identifier labels.
The 10th adds audit container identifier support to standalone netfilter records that don't have a task context and lists each container to which that net namespace belongs.
Example: Set an audit container identifier of 123456 to the "sleep" task:
sleep 2&
child=$!
echo 123456 > /proc/$child/audit_containerid; echo $? ausearch -ts recent -m container_op
echo child:$child contid:$( cat /proc/$child/audit_containerid)
This should produce a record such as:
type=CONTAINER_OP msg=audit(2018-06-06 12:39:29.636:26949) : op=set opid=2209 old-contid=18446744073709551615 contid=123456 pid=628 auid=root uid=root tty=ttyS0 ses=1 subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 comm=bash exe=/usr/bin/bash res=yes
Example: Set a filter on an audit container identifier 123459 on /tmp/tmpcontainerid:
contid=123459
key=tmpcontainerid
auditctl -a exit,always -F dir=/tmp -F perm=wa -F contid=$contid -F key=$key perl -e "sleep 1; open(my \$tmpfile, '>', \"/tmp/$key\"); close(\$tmpfile);" & child=$!
echo $contid > /proc/$child/audit_containerid
sleep 2
ausearch -i -ts recent -k $key
auditctl -d exit,always -F dir=/tmp -F perm=wa -F contid=$contid -F key=$key rm -f /tmp/$key
This should produce an event such as:
type=CONTAINER_ID msg=audit(2018-06-06 12:46:31.707:26953) : contid=123459 type=PROCTITLE msg=audit(2018-06-06 12:46:31.707:26953) : proctitle=perl -e sleep 1; open(my $tmpfile, '>', "/tmp/tmpcontainerid"); close($tmpfile); type=PATH msg=audit(2018-06-06 12:46:31.707:26953) : item=1 name=/tmp/tmpcontainerid inode=25656 dev=00:26 mode=file,644 ouid=root ogid=root rdev=00:00 obj=unconfined_u:object_r:user_tmp_t:s0 nametype=CREATE cap_fp=none cap_fi=none cap_fe=0 cap_fver=0 type=PATH msg=audit(2018-06-06 12:46:31.707:26953) : item=0 name=/tmp/ inode=8985 dev=00:26 mode=dir,sticky,777 ouid=root ogid=root rdev=00:00 obj=system_u:object_r:tmp_t:s0 nametype=PARENT cap_fp=none cap_fi=none cap_fe=0 cap_fver=0 type=CWD msg=audit(2018-06-06 12:46:31.707:26953) : cwd=/root type=SYSCALL msg=audit(2018-06-06 12:46:31.707:26953) : arch=x86_64 syscall=openat success=yes exit=3 a0=0xffffffffffffff9c a1=0x5621f2b81900 a2=O_WRONLY|O_CREAT|O_TRUNC a3=0x1b6 items=2 ppid=628 pid=2232 auid=root uid=root gid=root euid=root suid=root fsuid=root egid=root sgid=root fsgid=root tty=ttyS0 ses=1 comm=perl exe=/usr/bin/perl subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 key=tmpcontainerid
Example: Test multiple containers on one netns:
sleep 5 & child1=$! containerid1=123451 echo $containerid1 > /proc/$child1/audit_containerid sleep 5 & child2=$! containerid2=123452 echo $containerid2 > /proc/$child2/audit_containerid iptables -I INPUT -i lo -p icmp --icmp-type echo-request -j AUDIT --type accept iptables -I INPUT -t mangle -i lo -p icmp --icmp-type echo-request -j MARK --set-mark 0x12345555 sleep 1; bash -c "ping -q -c 1 127.0.0.1 >/dev/null 2>&1" sleep 1; ausearch -i -m NETFILTER_PKT -ts boot|grep mark=0x12345555 ausearch -i -m NETFILTER_PKT -ts boot|grep contid=|grep $containerid1|grep $containerid2
This should produce an event such as:
type=NETFILTER_PKT msg=audit(03/15/2019 14:16:13.369:244) : mark=0x12345555 saddr=127.0.0.1 daddr=127.0.0.1 proto=icmp type=CONTAINER_ID msg=audit(03/15/2019 14:16:13.369:244) : contid=123452,123451
Includes the last patch of https://github.com/linux-audit/audit-kernel/issues/81
See the github issue for the kernel code https://github.com/linux-audit/audit-kernel/issues/90
See: https://github.com/linux-audit/audit-userspace/issues/40
See: https://github.com/linux-audit/audit-testsuite/issues/64
See: https://github.com/linux-audit/audit-kernel/wiki/RFE-Audit-Container-ID
Changelog:
v5
- address loginuid and sessionid syscall scope in ghak104
- address audit_context in CONFIG_AUDIT vs CONFIG_AUDITSYSCALL in ghak105
- remove tty patch, addressed in ghak106
- rebase on audit/next v5.0-rc1 w/ghak59/ghak104/ghak103/ghak100/ghak107/ghak105/ghak106/ghak105sup
- update CONTAINER_ID to CONTAINER_OP in patch description
- move audit_context in audit_task_info to CONFIG_AUDITSYSCALL
- move audit_alloc() and audit_free() out of CONFIG_AUDITSYSCALL and into CONFIG_AUDIT and create audit_{alloc,free}_syscall
- use plain kmem_cache_alloc() rather than kmem_cache_zalloc() in audit_alloc()
- fix audit_get_contid() declaration type error
- move audit_set_contid() from auditsc.c to audit.c
- audit_log_contid() returns void
- audit_log_contid() handed contid rather than tsk
- switch from AUDIT_CONTAINER to AUDIT_CONTAINER_ID for aux record
- move audit_log_contid(tsk/contid) & audit_contid_set(tsk)/audit_contid_valid(contid)
- switch from tsk to current
- audit_alloc_local() calls audit_log_lost() on failure to allocate a context
- add AUDIT_USER* non-syscall contid record
- cosmetic cleanup double parens, goto out on err
- ditch audit_get_ns_contid_list_lock(), fix aunet lock race
- switch from all-cpu read spinlock to rcu, keep spinlock for write
- update audit_alloc_local() to use ktime_get_coarse_real_ts64()
- add nft_log support
- add call from do_exit() in audit_free() to remove contid from netns
- relegate AUDIT_CONTAINER ref= field (was op=) to debug patch
v4
- preface set with ghak81:"collect audit task parameters"
- add shallyn and sgrubb acks
- rename feature bitmap macro
- rename cid_valid() to audit_contid_valid()
- rename AUDIT_CONTAINER_ID to AUDIT_CONTAINER_OP
- delete audit_get_contid_list() from headers
- move work into inner if, delete "found"
- change netns contid list function names
- move exports for audit_log_contid audit_alloc_local audit_free_context to non-syscall patch
- list contids CSV
- pass in gfp flags to audit_alloc_local() (fix audit_alloc_context callers)
- use "local" in lieu of abusing in_syscall for auditsc_get_stamp()
- read_lock(&tasklist_lock) around children and thread check
- task_lock(tsk) should be taken before first check of tsk->audit
- add spin lock to contid list in aunet
- restrict /proc read to CAP_AUDIT_CONTROL
- remove set again prohibition and inherited flag
- delete contidion spelling fix from patchset, send to netdev/linux-wireless
v3
- switched from containerid in task_struct to audit_task_info (depends on ghak81)
- drop INVALID_CID in favour of only AUDIT_CID_UNSET
- check for !audit_task_info, throw -ENOPROTOOPT on set
- changed -EPERM to -EEXIST for parent check
- return AUDIT_CID_UNSET if !audit_enabled
- squash child/thread check patch into AUDIT_CONTAINER_ID patch
- changed -EPERM to -EBUSY for child check
- separate child and thread checks, use -EALREADY for latter
- move addition of op= from ptrace/signal patch to AUDIT_CONTAINER patch
- fix && to || bashism in ptrace/signal patch
- uninline and export function for audit_free_context()
- drop CONFIG_CHANGE, FEATURE_CHANGE, ANOM_ABEND, ANOM_SECCOMP patches
- move audit_enabled check (xt_AUDIT)
- switched from containerid list in struct net to net_generic's struct audit_net
- move containerid list iteration into audit (xt_AUDIT)
- create function to move namespace switch into audit
- switched /proc/PID/ entry from containerid to audit_containerid
- call kzalloc with GFP_ATOMIC on in_atomic() in audit_alloc_context()
- call kzalloc with GFP_ATOMIC on in_atomic() in audit_log_container_info()
- use xt_net(par) instead of sock_net(skb->sk) to get net
- switched record and field names: initial CONTAINER_ID, aux CONTAINER, field CONTID
- allow to set own contid
- open code audit_set_containerid
- add contid inherited flag
- ccontainerid and pcontainerid eliminated due to inherited flag
- change name of container list funcitons
- rename containerid to contid
- convert initial container record to syscall aux
- fix spelling mistake of contidion in net/rfkill/core.c to avoid contid name collision
v2
- add check for children and threads
- add network namespace container identifier list
- add NETFILTER_PKT audit container identifier logging
- patch description and documentation clean-up and example
- reap unused ppid
Richard Guy Briggs (10):
audit: collect audit task parameters
audit: add container id
audit: read container ID of a process
audit: log container info of syscalls
audit: add containerid support for ptrace and signals
audit: add support for non-syscall auxiliary records
audit: add containerid support for user records
audit: add containerid filtering
audit: add support for containerid to network namespaces
audit: NETFILTER_PKT: record each container ID associated with a netNS
fs/proc/base.c | 55 +++++++++ include/linux/audit.h | 107 +++++++++++++--- include/linux/sched.h | 7 +- include/uapi/linux/audit.h | 8 +- init/init_task.c | 3 +- init/main.c | 2 + kernel/audit.c | 300 +++++++++++++++++++++++++++++++++++++++++++-- kernel/audit.h | 9 ++ kernel/auditfilter.c | 47 +++++++ kernel/auditsc.c | 89 ++++++++++---- kernel/fork.c | 1 - kernel/nsproxy.c | 4 + net/netfilter/nft_log.c | 11 +- net/netfilter/xt_AUDIT.c | 11 +- 14 files changed, 592 insertions(+), 62 deletions(-)
Signature · 1 line
1.8.3.1
PATCH v5 1/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.
Please see the upstream github issue
https://github.com/linux-audit/audit-kernel/issues/81
but that issue has been closed with this patch included with
https://github.com/linux-audit/audit-kernel/issues/90
--- include/linux/audit.h | 49 +++++++++++++++++++++++------------ include/linux/sched.h | 7 +---- init/init_task.c | 3 +-- init/main.c | 2 ++ kernel/audit.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++-- kernel/audit.h | 5 ++++ kernel/auditsc.c | 26 ++++++++++--------- kernel/fork.c | 1 - 8 files changed, 124 insertions(+), 40 deletions(-)
include/linux/audit.h +32 -17
@@ -86,6 +86,16 @@ struct audit_field {u32 op; }; +struct audit_task_info { +kuid_t loginuid; +unsigned int sessionid; +#ifdef CONFIG_AUDITSYSCALL +struct audit_context *ctx; +#endif +}; + +extern struct audit_task_info init_struct_audit; +extern int is_audit_feature_set (int which);extern int __init audit_register_class (int class,unsigned *list);
@@ -122,6 +132,9 @@ struct audit_field {#ifdef CONFIG_AUDIT /* These are defined in audit.c */ /* Public API */ +extern int audit_alloc (struct task_struct *task); +extern void audit_free (struct task_struct *task); +extern void __init audit_task_init (void ); extern __printf(4, 5) void audit_log(struct audit_context *ctx, gfp_t gfp_mask, int type, const char *fmt, ...);
@@ -164,16 +177,28 @@ extern void audit_log_key(struct audit_buffer *ab,static inline kuid_t audit_get_loginuid (struct task_struct *tsk) { -return tsk->loginuid; +if (!tsk->audit) +return INVALID_UID ; +return tsk->audit->loginuid; }static inline unsigned int audit_get_sessionid (struct task_struct *tsk) { -return tsk->sessionid; +if (!tsk->audit) +return AUDIT_SID_UNSET ; +return tsk->audit->sessionid; }extern u32 audit_enabled;#else /* CONFIG_AUDIT */ +static inline int audit_alloc (struct task_struct *task) +{ +return 0 ; +} +static inline void audit_free (struct task_struct *task) +{ } +static inline void __init audit_task_init (void ) +{ } static inline __printf(4, 5) void audit_log(struct audit_context *ctx, gfp_t gfp_mask, int type, const char *fmt, ...)
@@ -239,8 +264,6 @@ static inline unsigned int audit_get_sessionid(struct task_struct *tsk)/* These are defined in auditsc.c */ /* Public API */ -extern int audit_alloc (struct task_struct *task); -extern void __audit_free (struct task_struct *task);extern void __audit_syscall_entry (int major,unsigned long a0,unsigned long a1,unsigned long a2,unsigned long a3);extern void __audit_syscall_exit (int ret_success,long ret_value);
@@ -263,12 +286,14 @@ extern void audit_seccomp_actions_logged(const char *names,static inline void audit_set_context (struct task_struct *task,struct audit_context *ctx) { - task->audit_context = ctx; + task->audit->ctx = ctx; }static inline struct audit_context *audit_context (void ) { -return current->audit_context; +if (!current->audit) +return NULL ; +return current->audit->ctx; }static inline bool audit_dummy_context (void )
@@ -276,11 +301,7 @@ static inline bool audit_dummy_context(void)void *p =audit_context ();return !p || *(int *)p; } -static inline void audit_free (struct task_struct *task) -{ -if (unlikely (task->audit_context)) -__audit_free (task); -} +static inline void audit_syscall_entry (int major,unsigned long a0,unsigned long a1,unsigned long a2,unsigned long a3)
@@ -470,12 +491,6 @@ static inline void audit_fanotify(unsigned int response)extern int audit_n_rules;extern int audit_signals;#else /* CONFIG_AUDITSYSCALL */ -static inline int audit_alloc (struct task_struct *task) -{ -return 0 ; -} -static inline void audit_free (struct task_struct *task) -{ }static inline void audit_syscall_entry (int major,unsigned long a0,unsigned long a1,unsigned long a2,unsigned long a3)
include/linux/sched.h +1 -6
@@ -31,7 +31,6 @@#include <linux/rseq.h> /* task_struct member predeclarations (sorted alphabetically): */ -struct audit_context ;struct backing_dev_info ;struct bio_list ;struct blk_plug ;
@@ -886,11 +885,7 @@ struct task_struct {struct callback_head *task_works;#ifdef CONFIG_AUDIT -#ifdef CONFIG_AUDITSYSCALL -struct audit_context *audit_context; -#endif -kuid_t loginuid; -unsigned int sessionid; +struct audit_task_info *audit;#endif struct seccomp seccomp;
init/init_task.c +1 -2
@@ -122,8 +122,7 @@ struct task_struct init_task .thread_group = LIST_HEAD_INIT(init_task.thread_group), .thread_node = LIST_HEAD_INIT(init_signals.thread_head),#ifdef CONFIG_AUDIT - .loginuid = INVALID_UID, - .sessionid = AUDIT_SID_UNSET, + .audit = &init_struct_audit,#endif #ifdef CONFIG_PERF_EVENTS .perf_event_mutex = __MUTEX_INITIALIZER(init_task.perf_event_mutex),
init/main.c +2 -0
@@ -92,6 +92,7 @@#include <linux/rodata_test.h> #include <linux/jump_label.h> #include <linux/mem_encrypt.h> +#include <linux/audit.h> #include <asm/io.h> #include <asm/bugs.h>
@@ -727,6 +728,7 @@ asmlinkage __visible void __init start_kernel(void)nsfs_init ();cpuset_init ();cgroup_init (); +audit_task_init ();taskstats_init_early ();delayacct_init ();
kernel/audit.c +69 -2
83 lines not on this page · raw message
kernel/audit.h +5 -0
@@ -264,6 +264,8 @@ extern void audit_log_d_path_exe(struct audit_buffer *ab,extern unsigned int audit_serial (void );extern int auditsc_get_stamp (struct audit_context *ctx,struct timespec64 *t,unsigned int *serial); +extern int audit_alloc_syscall (struct task_struct *tsk); +extern void audit_free_syscall (struct task_struct *tsk);extern void audit_put_watch (struct audit_watch *watch);extern void audit_get_watch (struct audit_watch *watch);
@@ -305,6 +307,9 @@ extern void audit_filter_inodes(struct task_struct *tsk,extern struct list_head *audit_killed_trees (void );#else /* CONFIG_AUDITSYSCALL */ #define auditsc_get_stamp (c, t, s) 0 +#define audit_alloc_syscall (t) 0 +#define audit_free_syscall (t) {} +#define audit_put_watch (w) {}#define audit_get_watch (w) {}#define audit_to_watch (k, p, l, o) (-EINVAL)
kernel/auditsc.c +14 -12
@@ -885,23 +885,25 @@ static inline struct audit_context *audit_alloc_context(enum audit_state state)return context; } -/** -* audit_alloc - allocate an audit context block for a task +/* +* audit_alloc_syscall - allocate an audit context block for a task * @tsk: task * * Filter on the task information and allocate a per-task audit context * if necessary. Doing so turns on system call auditing for the -* specified task. This is called from copy_process, so no lock is -* needed. +* specified task. This is called from copy_process via audit_alloc, so +* no lock is needed. */ -int audit_alloc (struct task_struct *tsk) +int audit_alloc_syscall (struct task_struct *tsk) {struct audit_context *context;enum audit_state state;char *key =NULL ; -if (likely (!audit_ever_enabled)) +if (likely (!audit_ever_enabled)) { +audit_set_context (tsk,NULL );return 0 ;/* Return if not auditing. */ + } state =audit_filter_task (tsk, &key);if (state ==AUDIT_DISABLED ) {
@@ -911,7 +913,7 @@ int audit_alloc(struct task_struct *tsk)if (!(context =audit_alloc_context (state))) {kfree (key); -audit_log_lost ("out of memory in audit_alloc" ); +audit_log_lost ("out of memory in audit_alloc_syscall" );return -ENOMEM ; } context->filterkey = key;
@@ -1555,14 +1557,15 @@ static void audit_log_exit(void) }/** -* __audit_free - free a per-task audit context +* audit_free_syscall - free per-task audit context info * @tsk: task whose audit context block to free * -* Called from copy_process and do_exit +* Called from audit_free */ -void __audit_free (struct task_struct *tsk) +void audit_free_syscall (struct task_struct *tsk) { -struct audit_context *context = tsk->audit_context; +struct audit_task_info *info = tsk->audit; +struct audit_context *context = info->ctx;if (!context)return ;
@@ -1585,7 +1588,6 @@ void __audit_free(struct task_struct *tsk)if (context->current_state ==AUDIT_RECORD_CONTEXT )audit_log_exit (); } -audit_set_context (tsk,NULL );audit_free_context (context); }
kernel/fork.c +0 -1
@@ -1836,7 +1836,6 @@ static __latent_entropy struct task_struct *copy_process( p->start_time =ktime_get_ns (); p->real_start_time =ktime_get_boot_ns (); p->io_context =NULL ; -audit_set_context (p,NULL );cgroup_fork (p);#ifdef CONFIG_NUMA p->mempolicy =mpol_dup (p->mempolicy);
Signature · 1 line
1.8.3.1
Re: [PATCH ghak90 V5 01/10] audit: collect audit task parameters
Quoted 400 lines · Richard Guy Briggs
The audit-related parameters in struct
task_structshould ideally be collected together and accessed through a standard audit API.Collect the existing loginuid, sessionid and
audit_contexttogether in a new structaudit_task_infocalled "audit" in structtask_struct.Use
kmem_cacheto manage this pool of memory. Un-inlineaudit_free()to be able to always recover that memory.Please see the upstream github issue
https://github.com/linux-audit/audit-kernel/issues/81
but that issue has been closed with this patch included with
https://github.com/linux-audit/audit-kernel/issues/90Signed-off-by Richard Guy Briggs <[email protected]>--- include/linux/audit.h | 49 +++++++++++++++++++++++------------ include/linux/sched.h | 7 +---- init/init_task.c | 3 +-- init/main.c | 2 ++ kernel/audit.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++-- kernel/audit.h | 5 ++++ kernel/auditsc.c | 26 ++++++++++--------- kernel/fork.c | 1 - 8 files changed, 124 insertions(+), 40 deletions(-)include/linux/audit.h +32
-17@@ -86,6 +86,16 @@ struct audit_field {u32 op; }; +struct audit_task_info { +kuid_t loginuid; +unsigned int sessionid; +#ifdef CONFIG_AUDITSYSCALL +struct audit_context *ctx; +#endif +}; + +extern struct audit_task_info init_struct_audit; +extern int is_audit_feature_set (int which);extern int __init audit_register_class (int class,unsigned *list);@@ -122,6 +132,9 @@ struct audit_field {#ifdef CONFIG_AUDIT /* These are defined in audit.c */ /* Public API */ +extern int audit_alloc (struct task_struct *task); +extern void audit_free (struct task_struct *task); +extern void __init audit_task_init (void ); extern __printf(4, 5) void audit_log(struct audit_context *ctx, gfp_t gfp_mask, int type, const char *fmt, ...);@@ -164,16 +177,28 @@ extern void audit_log_key(struct audit_buffer *ab,static inline kuid_t audit_get_loginuid (struct task_struct *tsk) { -return tsk->loginuid; +if (!tsk->audit) +return INVALID_UID ; +return tsk->audit->loginuid; }static inline unsigned int audit_get_sessionid (struct task_struct *tsk) { -return tsk->sessionid; +if (!tsk->audit) +return AUDIT_SID_UNSET ; +return tsk->audit->sessionid; }extern u32 audit_enabled;#else /* CONFIG_AUDIT */ +static inline int audit_alloc (struct task_struct *task) +{ +return 0 ; +} +static inline void audit_free (struct task_struct *task) +{ } +static inline void __init audit_task_init (void ) +{ } static inline __printf(4, 5) void audit_log(struct audit_context *ctx, gfp_t gfp_mask, int type, const char *fmt, ...)@@ -239,8 +264,6 @@ static inline unsigned int audit_get_sessionid(struct task_struct *tsk)/* These are defined in auditsc.c */ /* Public API */ -extern int audit_alloc (struct task_struct *task); -extern void __audit_free (struct task_struct *task);extern void __audit_syscall_entry (int major,unsigned long a0,unsigned long a1,unsigned long a2,unsigned long a3);extern void __audit_syscall_exit (int ret_success,long ret_value);@@ -263,12 +286,14 @@ extern void audit_seccomp_actions_logged(const char *names,static inline void audit_set_context (struct task_struct *task,struct audit_context *ctx) { - task->audit_context = ctx; + task->audit->ctx = ctx; }static inline struct audit_context *audit_context (void ) { -return current->audit_context; +if (!current->audit) +return NULL ; +return current->audit->ctx; }static inline bool audit_dummy_context (void )@@ -276,11 +301,7 @@ static inline bool audit_dummy_context(void)void *p =audit_context ();return !p || *(int *)p; } -static inline void audit_free (struct task_struct *task) -{ -if (unlikely (task->audit_context)) -__audit_free (task); -} +static inline void audit_syscall_entry (int major,unsigned long a0,unsigned long a1,unsigned long a2,unsigned long a3)@@ -470,12 +491,6 @@ static inline void audit_fanotify(unsigned int response)extern int audit_n_rules;extern int audit_signals;#else /* CONFIG_AUDITSYSCALL */ -static inline int audit_alloc (struct task_struct *task) -{ -return 0 ; -} -static inline void audit_free (struct task_struct *task) -{ }static inline void audit_syscall_entry (int major,unsigned long a0,unsigned long a1,unsigned long a2,unsigned long a3)include/linux/sched.h +1
-6@@ -31,7 +31,6 @@#include <linux/rseq.h> /* task_struct member predeclarations (sorted alphabetically): */ -struct audit_context ;struct backing_dev_info ;struct bio_list ;struct blk_plug ;@@ -886,11 +885,7 @@ struct task_struct {struct callback_head *task_works;#ifdef CONFIG_AUDIT -#ifdef CONFIG_AUDITSYSCALL -struct audit_context *audit_context; -#endif -kuid_t loginuid; -unsigned int sessionid; +struct audit_task_info *audit;#endif struct seccomp seccomp;init/init_task.c +1
-2@@ -122,8 +122,7 @@ struct task_struct init_task .thread_group = LIST_HEAD_INIT(init_task.thread_group), .thread_node = LIST_HEAD_INIT(init_signals.thread_head),#ifdef CONFIG_AUDIT - .loginuid = INVALID_UID, - .sessionid = AUDIT_SID_UNSET, + .audit = &init_struct_audit,#endif #ifdef CONFIG_PERF_EVENTS .perf_event_mutex = __MUTEX_INITIALIZER(init_task.perf_event_mutex),init/main.c +2
-0@@ -92,6 +92,7 @@#include <linux/rodata_test.h> #include <linux/jump_label.h> #include <linux/mem_encrypt.h> +#include <linux/audit.h> #include <asm/io.h> #include <asm/bugs.h> @@ -727,6 +728,7 @@ asmlinkage __visible void __init start_kernel(void)nsfs_init ();cpuset_init ();cgroup_init (); +audit_task_init ();taskstats_init_early ();delayacct_init ();kernel/audit.c +69
-2@@ -215,6 +215,73 @@ struct audit_reply {struct sk_buff *skb; }; +static struct kmem_cache *audit_task_cache; + +void __init audit_task_init (void ) +{ + audit_task_cache =kmem_cache_create ("audit_task" , +sizeof (struct audit_task_info ), +0 ,SLAB_PANIC ,NULL ); +} + +/** +* audit_alloc - allocate an audit info block for a task +* @tsk: task +* +* Call audit_alloc_syscall to filter on the task information and +* allocate a per-task audit context if necessary. This is called from +* copy_process, so no lock is needed. +*/ +int audit_alloc (struct task_struct *tsk) +{ +int ret =0 ; +struct audit_task_info *info; + + info =kmem_cache_alloc (audit_task_cache,GFP_KERNEL ); +if (!info) { + ret = -ENOMEM ; + goto out; + } + info->loginuid =audit_get_loginuid (current); + info->sessionid =audit_get_sessionid (current); + tsk->audit = info; + + ret =audit_alloc_syscall (tsk); +if (ret) { + tsk->audit =NULL ; +kmem_cache_free (audit_task_cache, info); + } +out: +return ret; +} + +struct audit_task_info init_struct_audit = { + .loginuid =INVALID_UID , + .sessionid =AUDIT_SID_UNSET , +#ifdef CONFIG_AUDITSYSCALL + .ctx =NULL , +#endif +}; + +/** +* audit_free - free per-task audit info +* @tsk: task whose audit info block to free +* +* Called from copy_process and do_exit +*/ +void audit_free (struct task_struct *tsk) +{ +struct audit_task_info *info = tsk->audit; + +audit_free_syscall (tsk); +/* Freeing the audit_task_info struct must be performed after +* audit_log_exit() due to need for loginuid and sessionid. +*/ + info = tsk->audit; + tsk->audit =NULL ; +kmem_cache_free (audit_task_cache, info); +} +/** * auditd_test_task - Check to see if a given task is an audit daemon * @task: the task to check @@ -2266,8 +2333,8 @@ int audit_set_loginuid(kuid_t loginuid) sessionid = (unsigned int )atomic_inc_return (&session_id); } - current->sessionid = sessionid; - current->loginuid = loginuid; + current->audit->sessionid = sessionid; + current->audit->loginuid = loginuid; out:audit_log_set_loginuid (oldloginuid, loginuid, oldsessionid, sessionid, rc);return rc;kernel/audit.h +5
-0@@ -264,6 +264,8 @@ extern void audit_log_d_path_exe(struct audit_buffer *ab,extern unsigned int audit_serial (void );extern int auditsc_get_stamp (struct audit_context *ctx,struct timespec64 *t,unsigned int *serial); +extern int audit_alloc_syscall (struct task_struct *tsk); +extern void audit_free_syscall (struct task_struct *tsk);extern void audit_put_watch (struct audit_watch *watch);extern void audit_get_watch (struct audit_watch *watch);@@ -305,6 +307,9 @@ extern void audit_filter_inodes(struct task_struct *tsk,extern struct list_head *audit_killed_trees (void );#else /* CONFIG_AUDITSYSCALL */ #define auditsc_get_stamp (c, t, s) 0 +#define audit_alloc_syscall (t) 0 +#define audit_free_syscall (t) {} +#define audit_put_watch (w) {}#define audit_get_watch (w) {}#define audit_to_watch (k, p, l, o) (-EINVAL)kernel/auditsc.c +14
-12@@ -885,23 +885,25 @@ static inline struct audit_context *audit_alloc_context(enum audit_state state)return context; } -/** -* audit_alloc - allocate an audit context block for a task +/* +* audit_alloc_syscall - allocate an audit context block for a task * @tsk: task * * Filter on the task information and allocate a per-task audit context * if necessary. Doing so turns on system call auditing for the -* specified task. This is called from copy_process, so no lock is -* needed. +* specified task. This is called from copy_process via audit_alloc, so +* no lock is needed. */ -int audit_alloc (struct task_struct *tsk) +int audit_alloc_syscall (struct task_struct *tsk) {struct audit_context *context;enum audit_state state;char *key =NULL ; -if (likely (!audit_ever_enabled)) +if (likely (!audit_ever_enabled)) { +audit_set_context (tsk,NULL );return 0 ;/* Return if not auditing. */ + } state =audit_filter_task (tsk, &key);if (state ==AUDIT_DISABLED ) {@@ -911,7 +913,7 @@ int audit_alloc(struct task_struct *tsk)if (!(context =audit_alloc_context (state))) {kfree (key); -audit_log_lost ("out of memory in audit_alloc" ); +audit_log_lost ("out of memory in audit_alloc_syscall" );return -ENOMEM ; } context->filterkey = key;@@ -1555,14 +1557,15 @@ static void audit_log_exit(void) }/** -* __audit_free - free a per-task audit context +* audit_free_syscall - free per-task audit context info * @tsk: task whose audit context block to free * -* Called from copy_process and do_exit +* Called from audit_free */ -void __audit_free (struct task_struct *tsk) +void audit_free_syscall (struct task_struct *tsk) { -struct audit_context *context = tsk->audit_context; +struct audit_task_info *info = tsk->audit; +struct audit_context *context = info->ctx;if (!context)return ;@@ -1585,7 +1588,6 @@ void __audit_free(struct task_struct *tsk)if (context->current_state ==AUDIT_RECORD_CONTEXT )audit_log_exit (); } -audit_set_context (tsk,NULL );audit_free_context (context); }kernel/fork.c +0
-1@@ -1836,7 +1836,6 @@ static __latent_entropy struct task_struct *copy_process( p->start_time =ktime_get_ns (); p->real_start_time =ktime_get_boot_ns (); p->io_context =NULL ; -audit_set_context (p,NULL );cgroup_fork (p);#ifdef CONFIG_NUMA p->mempolicy =mpol_dup (p->mempolicy);Signature · 1 line
1.8.3.1
Re: [PATCH ghak90 V5 01/10] audit: collect audit task parameters
In reply to Richard Guy BriggsQuoted 9 lines · Richard Guy Briggs
The audit-related parameters in struct
task_structshould ideally be collected together and accessed through a standard audit API.Collect the existing loginuid, sessionid and
audit_contexttogether in a new structaudit_task_infocalled "audit" in structtask_struct.Use
kmem_cacheto manage this pool of memory. Un-inlineaudit_free()to be able to always recover that memory.
Quoted 6 lines
Please see the upstream github issue
https://github.com/linux-audit/audit-kernel/issues/81
but that issue has been closed with this patch included with
https://github.com/linux-audit/audit-kernel/issues/90Signed-off-by Richard Guy Briggs <[email protected]>
Quoted 382 lines
--- include/linux/audit.h | 49 +++++++++++++++++++++++------------ include/linux/sched.h | 7 +---- init/init_task.c | 3 +-- init/main.c | 2 ++ kernel/audit.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++-- kernel/audit.h | 5 ++++ kernel/auditsc.c | 26 ++++++++++--------- kernel/fork.c | 1 - 8 files changed, 124 insertions(+), 40 deletions(-)include/linux/audit.h +32
-17@@ -86,6 +86,16 @@ struct audit_field {u32 op; }; +struct audit_task_info { +kuid_t loginuid; +unsigned int sessionid; +#ifdef CONFIG_AUDITSYSCALL +struct audit_context *ctx; +#endif +}; + +extern struct audit_task_info init_struct_audit; +extern int is_audit_feature_set (int which);extern int __init audit_register_class (int class,unsigned *list);@@ -122,6 +132,9 @@ struct audit_field {#ifdef CONFIG_AUDIT /* These are defined in audit.c */ /* Public API */ +extern int audit_alloc (struct task_struct *task); +extern void audit_free (struct task_struct *task); +extern void __init audit_task_init (void ); extern __printf(4, 5) void audit_log(struct audit_context *ctx, gfp_t gfp_mask, int type, const char *fmt, ...);@@ -164,16 +177,28 @@ extern void audit_log_key(struct audit_buffer *ab,static inline kuid_t audit_get_loginuid (struct task_struct *tsk) { -return tsk->loginuid; +if (!tsk->audit) +return INVALID_UID ; +return tsk->audit->loginuid; }static inline unsigned int audit_get_sessionid (struct task_struct *tsk) { -return tsk->sessionid; +if (!tsk->audit) +return AUDIT_SID_UNSET ; +return tsk->audit->sessionid; }extern u32 audit_enabled;#else /* CONFIG_AUDIT */ +static inline int audit_alloc (struct task_struct *task) +{ +return 0 ; +} +static inline void audit_free (struct task_struct *task) +{ } +static inline void __init audit_task_init (void ) +{ } static inline __printf(4, 5) void audit_log(struct audit_context *ctx, gfp_t gfp_mask, int type, const char *fmt, ...)@@ -239,8 +264,6 @@ static inline unsigned int audit_get_sessionid(struct task_struct *tsk)/* These are defined in auditsc.c */ /* Public API */ -extern int audit_alloc (struct task_struct *task); -extern void __audit_free (struct task_struct *task);extern void __audit_syscall_entry (int major,unsigned long a0,unsigned long a1,unsigned long a2,unsigned long a3);extern void __audit_syscall_exit (int ret_success,long ret_value);@@ -263,12 +286,14 @@ extern void audit_seccomp_actions_logged(const char *names,static inline void audit_set_context (struct task_struct *task,struct audit_context *ctx) { - task->audit_context = ctx; + task->audit->ctx = ctx; }static inline struct audit_context *audit_context (void ) { -return current->audit_context; +if (!current->audit) +return NULL ; +return current->audit->ctx; }static inline bool audit_dummy_context (void )@@ -276,11 +301,7 @@ static inline bool audit_dummy_context(void)void *p =audit_context ();return !p || *(int *)p; } -static inline void audit_free (struct task_struct *task) -{ -if (unlikely (task->audit_context)) -__audit_free (task); -} +static inline void audit_syscall_entry (int major,unsigned long a0,unsigned long a1,unsigned long a2,unsigned long a3)@@ -470,12 +491,6 @@ static inline void audit_fanotify(unsigned int response)extern int audit_n_rules;extern int audit_signals;#else /* CONFIG_AUDITSYSCALL */ -static inline int audit_alloc (struct task_struct *task) -{ -return 0 ; -} -static inline void audit_free (struct task_struct *task) -{ }static inline void audit_syscall_entry (int major,unsigned long a0,unsigned long a1,unsigned long a2,unsigned long a3)include/linux/sched.h +1
-6@@ -31,7 +31,6 @@#include <linux/rseq.h> /* task_struct member predeclarations (sorted alphabetically): */ -struct audit_context ;struct backing_dev_info ;struct bio_list ;struct blk_plug ;@@ -886,11 +885,7 @@ struct task_struct {struct callback_head *task_works;#ifdef CONFIG_AUDIT -#ifdef CONFIG_AUDITSYSCALL -struct audit_context *audit_context; -#endif -kuid_t loginuid; -unsigned int sessionid; +struct audit_task_info *audit;#endif struct seccomp seccomp;init/init_task.c +1
-2@@ -122,8 +122,7 @@ struct task_struct init_task .thread_group = LIST_HEAD_INIT(init_task.thread_group), .thread_node = LIST_HEAD_INIT(init_signals.thread_head),#ifdef CONFIG_AUDIT - .loginuid = INVALID_UID, - .sessionid = AUDIT_SID_UNSET, + .audit = &init_struct_audit,#endif #ifdef CONFIG_PERF_EVENTS .perf_event_mutex = __MUTEX_INITIALIZER(init_task.perf_event_mutex),init/main.c +2
-0@@ -92,6 +92,7 @@#include <linux/rodata_test.h> #include <linux/jump_label.h> #include <linux/mem_encrypt.h> +#include <linux/audit.h> #include <asm/io.h> #include <asm/bugs.h> @@ -727,6 +728,7 @@ asmlinkage __visible void __init start_kernel(void)nsfs_init ();cpuset_init ();cgroup_init (); +audit_task_init ();taskstats_init_early ();delayacct_init ();kernel/audit.c +69
-2@@ -215,6 +215,73 @@ struct audit_reply {struct sk_buff *skb; }; +static struct kmem_cache *audit_task_cache; + +void __init audit_task_init (void ) +{ + audit_task_cache =kmem_cache_create ("audit_task" , +sizeof (struct audit_task_info ), +0 ,SLAB_PANIC ,NULL ); +} + +/** +* audit_alloc - allocate an audit info block for a task +* @tsk: task +* +* Call audit_alloc_syscall to filter on the task information and +* allocate a per-task audit context if necessary. This is called from +* copy_process, so no lock is needed. +*/ +int audit_alloc (struct task_struct *tsk) +{ +int ret =0 ; +struct audit_task_info *info; + + info =kmem_cache_alloc (audit_task_cache,GFP_KERNEL ); +if (!info) { + ret = -ENOMEM ; + goto out; + } + info->loginuid =audit_get_loginuid (current); + info->sessionid =audit_get_sessionid (current); + tsk->audit = info; + + ret =audit_alloc_syscall (tsk); +if (ret) { + tsk->audit =NULL ; +kmem_cache_free (audit_task_cache, info); + } +out: +return ret; +} + +struct audit_task_info init_struct_audit = { + .loginuid =INVALID_UID , + .sessionid =AUDIT_SID_UNSET , +#ifdef CONFIG_AUDITSYSCALL + .ctx =NULL , +#endif +}; + +/** +* audit_free - free per-task audit info +* @tsk: task whose audit info block to free +* +* Called from copy_process and do_exit +*/ +void audit_free (struct task_struct *tsk) +{ +struct audit_task_info *info = tsk->audit; + +audit_free_syscall (tsk); +/* Freeing the audit_task_info struct must be performed after +* audit_log_exit() due to need for loginuid and sessionid. +*/ + info = tsk->audit; + tsk->audit =NULL ; +kmem_cache_free (audit_task_cache, info); +} +/** * auditd_test_task - Check to see if a given task is an audit daemon * @task: the task to check @@ -2266,8 +2333,8 @@ int audit_set_loginuid(kuid_t loginuid) sessionid = (unsigned int )atomic_inc_return (&session_id); } - current->sessionid = sessionid; - current->loginuid = loginuid; + current->audit->sessionid = sessionid; + current->audit->loginuid = loginuid; out:audit_log_set_loginuid (oldloginuid, loginuid, oldsessionid, sessionid, rc);return rc;kernel/audit.h +5
-0@@ -264,6 +264,8 @@ extern void audit_log_d_path_exe(struct audit_buffer *ab,extern unsigned int audit_serial (void );extern int auditsc_get_stamp (struct audit_context *ctx,struct timespec64 *t,unsigned int *serial); +extern int audit_alloc_syscall (struct task_struct *tsk); +extern void audit_free_syscall (struct task_struct *tsk);extern void audit_put_watch (struct audit_watch *watch);extern void audit_get_watch (struct audit_watch *watch);@@ -305,6 +307,9 @@ extern void audit_filter_inodes(struct task_struct *tsk,extern struct list_head *audit_killed_trees (void );#else /* CONFIG_AUDITSYSCALL */ #define auditsc_get_stamp (c, t, s) 0 +#define audit_alloc_syscall (t) 0 +#define audit_free_syscall (t) {} +#define audit_put_watch (w) {}#define audit_get_watch (w) {}#define audit_to_watch (k, p, l, o) (-EINVAL)kernel/auditsc.c +14
-12@@ -885,23 +885,25 @@ static inline struct audit_context *audit_alloc_context(enum audit_state state)return context; } -/** -* audit_alloc - allocate an audit context block for a task +/* +* audit_alloc_syscall - allocate an audit context block for a task * @tsk: task * * Filter on the task information and allocate a per-task audit context * if necessary. Doing so turns on system call auditing for the -* specified task. This is called from copy_process, so no lock is -* needed. +* specified task. This is called from copy_process via audit_alloc, so +* no lock is needed. */ -int audit_alloc (struct task_struct *tsk) +int audit_alloc_syscall (struct task_struct *tsk) {struct audit_context *context;enum audit_state state;char *key =NULL ; -if (likely (!audit_ever_enabled)) +if (likely (!audit_ever_enabled)) { +audit_set_context (tsk,NULL );return 0 ;/* Return if not auditing. */ + } state =audit_filter_task (tsk, &key);if (state ==AUDIT_DISABLED ) {@@ -911,7 +913,7 @@ int audit_alloc(struct task_struct *tsk)if (!(context =audit_alloc_context (state))) {kfree (key); -audit_log_lost ("out of memory in audit_alloc" ); +audit_log_lost ("out of memory in audit_alloc_syscall" );return -ENOMEM ; } context->filterkey = key;@@ -1555,14 +1557,15 @@ static void audit_log_exit(void) }/** -* __audit_free - free a per-task audit context +* audit_free_syscall - free per-task audit context info * @tsk: task whose audit context block to free * -* Called from copy_process and do_exit +* Called from audit_free */ -void __audit_free (struct task_struct *tsk) +void audit_free_syscall (struct task_struct *tsk) { -struct audit_context *context = tsk->audit_context; +struct audit_task_info *info = tsk->audit; +struct audit_context *context = info->ctx;if (!context)return ;@@ -1585,7 +1588,6 @@ void __audit_free(struct task_struct *tsk)if (context->current_state ==AUDIT_RECORD_CONTEXT )audit_log_exit (); } -audit_set_context (tsk,NULL );audit_free_context (context); }kernel/fork.c +0
-2@@ -1836,7 +1836,6 @@ static __latent_entropy struct task_struct *copy_process( p->start_time =ktime_get_ns (); p->real_start_time =ktime_get_boot_ns (); p->io_context =NULL ; -audit_set_context (p,NULL );cgroup_fork (p);#ifdef CONFIG_NUMA p->mempolicy =mpol_dup (p->mempolicy); --
Quoted 2 lines
1.8.3.1
--
Ondrej Mosnacek <omosnace at redhat dot com>
Software Engineer, Security Technologies
Red Hat, Inc.
PATCH v5 2/10 audit: add container id
In reply to Richard Guy BriggsImplement the proc fs write to set the audit container identifier of a process, emitting an AUDIT_CONTAINER_OP record to document the event.
This is a write from the container orchestrator task to a proc entry of the form /proc/PID/audit_containerid where PID is the process ID of the newly created task that is to become the first task in a container, or an additional task added to a container.
The write expects up to a u64 value (unset: 18446744073709551615).
The writer must have capability CAP_AUDIT_CONTROL.
This will produce a record such as this:
type=CONTAINER_OP msg=audit(2018-06-06 12:39:29.636:26949) : op=set opid=2209 old-contid=18446744073709551615 contid=123456 pid=628 auid=root uid=root tty=ttyS0 ses=1 subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 comm=bash exe=/usr/bin/bash res=yes
The "op" field indicates an initial set. The "pid" to "ses" fields are the orchestrator while the "opid" field is the object's PID, the process being "contained". Old and new audit container identifier values are given in the "contid" fields, while res indicates its success.
It is not permitted to unset the audit container identifier. A child inherits its parent's audit container identifier.
See: https://github.com/linux-audit/audit-kernel/issues/90
See: https://github.com/linux-audit/audit-userspace/issues/51
See: https://github.com/linux-audit/audit-testsuite/issues/64
See: https://github.com/linux-audit/audit-kernel/wiki/RFE-Audit-Container-ID
--- fs/proc/base.c | 36 ++++++++++++++++++++++++ include/linux/audit.h | 25 +++++++++++++++++ include/uapi/linux/audit.h | 2 ++ kernel/audit.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 131 insertions(+)
fs/proc/base.c +36 -0
@@ -1294,6 +1294,40 @@ static ssize_t proc_sessionid_read(struct file * file, char __user * buf, .read = proc_sessionid_read, .llseek = generic_file_llseek, }; + +static ssize_t proc_contid_write (struct file *file,const char __user *buf, +size_t count,loff_t *ppos) +{ +struct inode *inode =file_inode (file); +u64 contid; +int rv; +struct task_struct *task =get_proc_task (inode); + +if (!task) +return -ESRCH ; +if (*ppos !=0 ) { +/* No partial writes. */ +put_task_struct (task); +return -EINVAL ; + } + + rv =kstrtou64_from_user (buf, count,10 , &contid); +if (rv <0 ) { +put_task_struct (task); +return rv; + } + + rv =audit_set_contid (task, contid); +put_task_struct (task); +if (rv <0 ) +return rv; +return count; +} + +static const struct file_operations proc_contid_operations = { + .write = proc_contid_write, + .llseek = generic_file_llseek, +};#endif #ifdef CONFIG_FAULT_INJECTION
@@ -3005,6 +3039,7 @@ static int proc_stack_depth(struct seq_file *m, struct pid_namespace *ns,#ifdef CONFIG_AUDIT REG ("loginuid" ,S_IWUSR |S_IRUGO , proc_loginuid_operations),REG ("sessionid" ,S_IRUGO , proc_sessionid_operations), +REG ("audit_containerid" ,S_IWUSR , proc_contid_operations), #endif #ifdef CONFIG_FAULT_INJECTION REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations),
@@ -3393,6 +3428,7 @@ static int proc_tid_comm_permission(struct inode *inode, int mask)#ifdef CONFIG_AUDIT REG ("loginuid" ,S_IWUSR |S_IRUGO , proc_loginuid_operations),REG ("sessionid" ,S_IRUGO , proc_sessionid_operations), +REG ("audit_containerid" ,S_IWUSR , proc_contid_operations), #endif #ifdef CONFIG_FAULT_INJECTION REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations),
include/linux/audit.h +25 -0
@@ -89,6 +89,7 @@ struct audit_field {struct audit_task_info {kuid_t loginuid;unsigned int sessionid; +u64 contid;#ifdef CONFIG_AUDITSYSCALL struct audit_context *ctx;#endif
@@ -189,6 +190,15 @@ static inline unsigned int audit_get_sessionid(struct task_struct *tsk) return tsk->audit->sessionid; } +extern int audit_set_contid (struct task_struct *tsk,u64 contid); + +static inline u64 audit_get_contid (struct task_struct *tsk) +{ +if (!tsk->audit) +return AUDIT_CID_UNSET ; +return tsk->audit->contid; +} +extern u32 audit_enabled;#else /* CONFIG_AUDIT */ static inline int audit_alloc (struct task_struct *task)
@@ -250,6 +260,11 @@ static inline unsigned int audit_get_sessionid(struct task_struct *tsk) return AUDIT_SID_UNSET; } +static inline u64 audit_get_contid (struct task_struct *tsk) +{ +return AUDIT_CID_UNSET ; +} +#define audit_enabled AUDIT_OFF#endif /* CONFIG_AUDIT */
@@ -606,6 +621,16 @@ static inline bool audit_loginuid_set(struct task_struct *tsk)return uid_valid (audit_get_loginuid (tsk)); } +static inline bool audit_contid_valid (u64 contid) +{ +return contid !=AUDIT_CID_UNSET ; +} + +static inline bool audit_contid_set (struct task_struct *tsk) +{ +return audit_contid_valid (audit_get_contid (tsk)); +} +static inline void audit_log_string (struct audit_buffer *ab,const char *buf) {audit_log_n_string (ab, buf,strlen (buf));
include/uapi/linux/audit.h +2 -0
@@ -71,6 +71,7 @@#define AUDIT_TTY_SET 1017/* Set TTY auditing status */ #define AUDIT_SET_FEATURE 1018/* Turn an audit feature on or off */ #define AUDIT_GET_FEATURE 1019/* Get which features are enabled */ +#define AUDIT_CONTAINER_OP 1020/* Define the container id and information */ #define AUDIT_FIRST_USER_MSG 1100/* Userspace messages mostly uninteresting to kernel */ #define AUDIT_USER_AVC 1107/* We filter this differently */
@@ -471,6 +472,7 @@ struct audit_tty_status {#define AUDIT_UID_UNSET (unsigned int)-1#define AUDIT_SID_UNSET ((unsigned int)-1) +#define AUDIT_CID_UNSET ((u64)-1)/* audit_rule_data supports filter rules with both integer and string * fields. It corresponds with AUDIT_ADD_RULE, AUDIT_DEL_RULE and
kernel/audit.c +68 -0
86 lines not on this page · raw message
Signature · 1 line
1.8.3.1
Re: [PATCH ghak90 V5 02/10] audit: add container id
Quoted 274 lines · Richard Guy Briggs
Implement the proc fs write to set the audit container identifier of a process, emitting an
AUDIT_CONTAINER_OPrecord to document the event.This is a write from the container orchestrator task to a proc entry of the form
/proc/PID/audit_containeridwhere PID is the process ID of the newly created task that is to become the first task in a container, or an additional task added to a container.The write expects up to a u64 value (unset: 18446744073709551615).
The writer must have capability
CAP_AUDIT_CONTROL.This will produce a record such as this:
type=CONTAINER_OP msg=audit(2018-06-06 12:39:29.636:26949) : op=set opid=2209 old-contid=18446744073709551615 contid=123456 pid=628 auid=root uid=root tty=ttyS0 ses=1 subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 comm=bash exe=/usr/bin/bash res=yesThe "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-IDSigned-off-by Richard Guy Briggs <[email protected]>Acked-by Serge Hallyn <[email protected]>Acked-by Steve Grubb <[email protected]>Signed-off-by Richard Guy Briggs <[email protected]>--- fs/proc/base.c | 36 ++++++++++++++++++++++++ include/linux/audit.h | 25 +++++++++++++++++ include/uapi/linux/audit.h | 2 ++ kernel/audit.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 131 insertions(+)fs/proc/base.c +36
-0@@ -1294,6 +1294,40 @@ static ssize_t proc_sessionid_read(struct file * file, char __user * buf, .read = proc_sessionid_read, .llseek = generic_file_llseek, }; + +static ssize_t proc_contid_write (struct file *file,const char __user *buf, +size_t count,loff_t *ppos) +{ +struct inode *inode =file_inode (file); +u64 contid; +int rv; +struct task_struct *task =get_proc_task (inode); + +if (!task) +return -ESRCH ; +if (*ppos !=0 ) { +/* No partial writes. */ +put_task_struct (task); +return -EINVAL ; + } + + rv =kstrtou64_from_user (buf, count,10 , &contid); +if (rv <0 ) { +put_task_struct (task); +return rv; + } + + rv =audit_set_contid (task, contid); +put_task_struct (task); +if (rv <0 ) +return rv; +return count; +} + +static const struct file_operations proc_contid_operations = { + .write = proc_contid_write, + .llseek = generic_file_llseek, +};#endif #ifdef CONFIG_FAULT_INJECTION @@ -3005,6 +3039,7 @@ static int proc_stack_depth(struct seq_file *m, struct pid_namespace *ns,#ifdef CONFIG_AUDIT REG ("loginuid" ,S_IWUSR |S_IRUGO , proc_loginuid_operations),REG ("sessionid" ,S_IRUGO , proc_sessionid_operations), +REG ("audit_containerid" ,S_IWUSR , proc_contid_operations), #endif #ifdef CONFIG_FAULT_INJECTION REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations),@@ -3393,6 +3428,7 @@ static int proc_tid_comm_permission(struct inode *inode, int mask)#ifdef CONFIG_AUDIT REG ("loginuid" ,S_IWUSR |S_IRUGO , proc_loginuid_operations),REG ("sessionid" ,S_IRUGO , proc_sessionid_operations), +REG ("audit_containerid" ,S_IWUSR , proc_contid_operations), #endif #ifdef CONFIG_FAULT_INJECTION REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations),include/linux/audit.h +25
-0@@ -89,6 +89,7 @@ struct audit_field {struct audit_task_info {kuid_t loginuid;unsigned int sessionid; +u64 contid;#ifdef CONFIG_AUDITSYSCALL struct audit_context *ctx;#endif @@ -189,6 +190,15 @@ static inline unsigned int audit_get_sessionid(struct task_struct *tsk) return tsk->audit->sessionid; } +extern int audit_set_contid (struct task_struct *tsk,u64 contid); + +static inline u64 audit_get_contid (struct task_struct *tsk) +{ +if (!tsk->audit) +return AUDIT_CID_UNSET ; +return tsk->audit->contid; +} +extern u32 audit_enabled;#else /* CONFIG_AUDIT */ static inline int audit_alloc (struct task_struct *task)@@ -250,6 +260,11 @@ static inline unsigned int audit_get_sessionid(struct task_struct *tsk) return AUDIT_SID_UNSET; } +static inline u64 audit_get_contid (struct task_struct *tsk) +{ +return AUDIT_CID_UNSET ; +} +#define audit_enabled AUDIT_OFF#endif /* CONFIG_AUDIT */ @@ -606,6 +621,16 @@ static inline bool audit_loginuid_set(struct task_struct *tsk)return uid_valid (audit_get_loginuid (tsk)); } +static inline bool audit_contid_valid (u64 contid) +{ +return contid !=AUDIT_CID_UNSET ; +} + +static inline bool audit_contid_set (struct task_struct *tsk) +{ +return audit_contid_valid (audit_get_contid (tsk)); +} +static inline void audit_log_string (struct audit_buffer *ab,const char *buf) {audit_log_n_string (ab, buf,strlen (buf));include/uapi/linux/audit.h +2
-0@@ -71,6 +71,7 @@#define AUDIT_TTY_SET 1017/* Set TTY auditing status */ #define AUDIT_SET_FEATURE 1018/* Turn an audit feature on or off */ #define AUDIT_GET_FEATURE 1019/* Get which features are enabled */ +#define AUDIT_CONTAINER_OP 1020/* Define the container id and information */ #define AUDIT_FIRST_USER_MSG 1100/* Userspace messages mostly uninteresting to kernel */ #define AUDIT_USER_AVC 1107/* We filter this differently */ @@ -471,6 +472,7 @@ struct audit_tty_status {#define AUDIT_UID_UNSET (unsigned int)-1#define AUDIT_SID_UNSET ((unsigned int)-1) +#define AUDIT_CID_UNSET ((u64)-1)/* audit_rule_data supports filter rules with both integer and string * fields. It corresponds with AUDIT_ADD_RULE, AUDIT_DEL_RULE and kernel/audit.c +68
-0@@ -244,6 +244,7 @@ int audit_alloc(struct task_struct *tsk) } info->loginuid =audit_get_loginuid (current); info->sessionid =audit_get_sessionid (current); + info->contid =audit_get_contid (current); tsk->audit = info; ret =audit_alloc_syscall (tsk);@@ -258,6 +259,7 @@ int audit_alloc(struct task_struct *tsk)struct audit_task_info init_struct_audit = { .loginuid =INVALID_UID , .sessionid =AUDIT_SID_UNSET , + .contid =AUDIT_CID_UNSET , #ifdef CONFIG_AUDITSYSCALL .ctx =NULL , #endif@@ -2341,6 +2343,72 @@ int audit_set_loginuid(kuid_t loginuid) }/** +* audit_set_contid - set current task's audit contid +* @contid: contid value +* +* Returns 0 on success, -EPERM on permission failure. +* +* Called (set) from fs/proc/base.c::proc_contid_write(). +*/ +int audit_set_contid (struct task_struct *task,u64 contid) +{ +u64 oldcontid; +int rc =0 ; +struct audit_buffer *ab; +uid_t uid; +struct tty_struct *tty; +char comm[sizeof (current->comm)]; + +task_lock (task); +/* Can't set if audit disabled */ +if (!task->audit) { +task_unlock (task); +return -ENOPROTOOPT ; + } + oldcontid =audit_get_contid (task); +read_lock (&tasklist_lock); +/* Don't allow the audit containerid to be unset */ +if (!audit_contid_valid (contid)) + rc = -EINVAL ; +/* if we don't have caps, reject */ +else if (!capable (CAP_AUDIT_CONTROL )) + rc = -EPERM ; +/* if task has children or is not single-threaded, deny */ +else if (!list_empty (&task->children)) + rc = -EBUSY ; +else if (!(thread_group_leader (task) &&thread_group_empty (task))) + rc = -EALREADY ; +read_unlock (&tasklist_lock); +if (!rc) + task->audit->contid = contid; +task_unlock (task); + +if (!audit_enabled) +return rc; + + ab =audit_log_start (audit_context (),GFP_KERNEL ,AUDIT_CONTAINER_OP ); +if (!ab) +return rc; + + uid =from_kuid (&init_user_ns,task_uid (current)); + tty =audit_get_tty (); +audit_log_format (ab,"op=set opid=%d old-contid=%llu contid=%llu pid=%d uid=%u auid=%u tty=%s ses=%u" , +task_tgid_nr (task), oldcontid, contid, +task_tgid_nr (current), uid, +from_kuid (&init_user_ns,audit_get_loginuid (current)), + tty ?tty_name (tty) :"(none)" , +audit_get_sessionid (current)); +audit_put_tty (tty); +audit_log_task_context (ab); +audit_log_format (ab," comm=" ); +audit_log_untrustedstring (ab,get_task_comm (comm, current)); +audit_log_d_path_exe (ab, current->mm); +audit_log_format (ab," res=%d" , !rc); +audit_log_end (ab); +return rc; +} + +/** * audit_log_end - end one audit record * @ab: the audit_buffer * Signature · 1 line
1.8.3.1
Re: [PATCH ghak90 V5 02/10] audit: add container id
In reply to Richard Guy BriggsQuoted 28 lines · Richard Guy Briggs
Implement the proc fs write to set the audit container identifier of a process, emitting an
AUDIT_CONTAINER_OPrecord to document the event.This is a write from the container orchestrator task to a proc entry of the form
/proc/PID/audit_containeridwhere PID is the process ID of the newly created task that is to become the first task in a container, or an additional task added to a container.The write expects up to a u64 value (unset: 18446744073709551615).
The writer must have capability
CAP_AUDIT_CONTROL.This will produce a record such as this:
type=CONTAINER_OP msg=audit(2018-06-06 12:39:29.636:26949) : op=set opid=2209 old-contid=18446744073709551615 contid=123456 pid=628 auid=root uid=root tty=ttyS0 ses=1 subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 comm=bash exe=/usr/bin/bash res=yesThe "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
Quoted 4 lines
Signed-off-by Richard Guy Briggs <[email protected]>Acked-by Serge Hallyn <[email protected]>Acked-by Steve Grubb <[email protected]>Signed-off-by Richard Guy Briggs <[email protected]>
Note that you have duplicate Signed-off here ^^
Took me a while to understand the flow in audit_set_contid(), but once understood it all made perfect sense, so:
Quoted 239 lines
--- fs/proc/base.c | 36 ++++++++++++++++++++++++ include/linux/audit.h | 25 +++++++++++++++++ include/uapi/linux/audit.h | 2 ++ kernel/audit.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 131 insertions(+)fs/proc/base.c +36
-0@@ -1294,6 +1294,40 @@ static ssize_t proc_sessionid_read(struct file * file, char __user * buf, .read = proc_sessionid_read, .llseek = generic_file_llseek, }; + +static ssize_t proc_contid_write (struct file *file,const char __user *buf, +size_t count,loff_t *ppos) +{ +struct inode *inode =file_inode (file); +u64 contid; +int rv; +struct task_struct *task =get_proc_task (inode); + +if (!task) +return -ESRCH ; +if (*ppos !=0 ) { +/* No partial writes. */ +put_task_struct (task); +return -EINVAL ; + } + + rv =kstrtou64_from_user (buf, count,10 , &contid); +if (rv <0 ) { +put_task_struct (task); +return rv; + } + + rv =audit_set_contid (task, contid); +put_task_struct (task); +if (rv <0 ) +return rv; +return count; +} + +static const struct file_operations proc_contid_operations = { + .write = proc_contid_write, + .llseek = generic_file_llseek, +};#endif #ifdef CONFIG_FAULT_INJECTION @@ -3005,6 +3039,7 @@ static int proc_stack_depth(struct seq_file *m, struct pid_namespace *ns,#ifdef CONFIG_AUDIT REG ("loginuid" ,S_IWUSR |S_IRUGO , proc_loginuid_operations),REG ("sessionid" ,S_IRUGO , proc_sessionid_operations), +REG ("audit_containerid" ,S_IWUSR , proc_contid_operations), #endif #ifdef CONFIG_FAULT_INJECTION REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations),@@ -3393,6 +3428,7 @@ static int proc_tid_comm_permission(struct inode *inode, int mask)#ifdef CONFIG_AUDIT REG ("loginuid" ,S_IWUSR |S_IRUGO , proc_loginuid_operations),REG ("sessionid" ,S_IRUGO , proc_sessionid_operations), +REG ("audit_containerid" ,S_IWUSR , proc_contid_operations), #endif #ifdef CONFIG_FAULT_INJECTION REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations),include/linux/audit.h +25
-0@@ -89,6 +89,7 @@ struct audit_field {struct audit_task_info {kuid_t loginuid;unsigned int sessionid; +u64 contid;#ifdef CONFIG_AUDITSYSCALL struct audit_context *ctx;#endif @@ -189,6 +190,15 @@ static inline unsigned int audit_get_sessionid(struct task_struct *tsk) return tsk->audit->sessionid; } +extern int audit_set_contid (struct task_struct *tsk,u64 contid); + +static inline u64 audit_get_contid (struct task_struct *tsk) +{ +if (!tsk->audit) +return AUDIT_CID_UNSET ; +return tsk->audit->contid; +} +extern u32 audit_enabled;#else /* CONFIG_AUDIT */ static inline int audit_alloc (struct task_struct *task)@@ -250,6 +260,11 @@ static inline unsigned int audit_get_sessionid(struct task_struct *tsk) return AUDIT_SID_UNSET; } +static inline u64 audit_get_contid (struct task_struct *tsk) +{ +return AUDIT_CID_UNSET ; +} +#define audit_enabled AUDIT_OFF#endif /* CONFIG_AUDIT */ @@ -606,6 +621,16 @@ static inline bool audit_loginuid_set(struct task_struct *tsk)return uid_valid (audit_get_loginuid (tsk)); } +static inline bool audit_contid_valid (u64 contid) +{ +return contid !=AUDIT_CID_UNSET ; +} + +static inline bool audit_contid_set (struct task_struct *tsk) +{ +return audit_contid_valid (audit_get_contid (tsk)); +} +static inline void audit_log_string (struct audit_buffer *ab,const char *buf) {audit_log_n_string (ab, buf,strlen (buf));include/uapi/linux/audit.h +2
-0@@ -71,6 +71,7 @@#define AUDIT_TTY_SET 1017/* Set TTY auditing status */ #define AUDIT_SET_FEATURE 1018/* Turn an audit feature on or off */ #define AUDIT_GET_FEATURE 1019/* Get which features are enabled */ +#define AUDIT_CONTAINER_OP 1020/* Define the container id and information */ #define AUDIT_FIRST_USER_MSG 1100/* Userspace messages mostly uninteresting to kernel */ #define AUDIT_USER_AVC 1107/* We filter this differently */ @@ -471,6 +472,7 @@ struct audit_tty_status {#define AUDIT_UID_UNSET (unsigned int)-1#define AUDIT_SID_UNSET ((unsigned int)-1) +#define AUDIT_CID_UNSET ((u64)-1)/* audit_rule_data supports filter rules with both integer and string * fields. It corresponds with AUDIT_ADD_RULE, AUDIT_DEL_RULE and kernel/audit.c +68
-1@@ -244,6 +244,7 @@ int audit_alloc(struct task_struct *tsk) } info->loginuid =audit_get_loginuid (current); info->sessionid =audit_get_sessionid (current); + info->contid =audit_get_contid (current); tsk->audit = info; ret =audit_alloc_syscall (tsk);@@ -258,6 +259,7 @@ int audit_alloc(struct task_struct *tsk)struct audit_task_info init_struct_audit = { .loginuid =INVALID_UID , .sessionid =AUDIT_SID_UNSET , + .contid =AUDIT_CID_UNSET , #ifdef CONFIG_AUDITSYSCALL .ctx =NULL , #endif@@ -2341,6 +2343,72 @@ int audit_set_loginuid(kuid_t loginuid) }/** +* audit_set_contid - set current task's audit contid +* @contid: contid value +* +* Returns 0 on success, -EPERM on permission failure. +* +* Called (set) from fs/proc/base.c::proc_contid_write(). +*/ +int audit_set_contid (struct task_struct *task,u64 contid) +{ +u64 oldcontid; +int rc =0 ; +struct audit_buffer *ab; +uid_t uid; +struct tty_struct *tty; +char comm[sizeof (current->comm)]; + +task_lock (task); +/* Can't set if audit disabled */ +if (!task->audit) { +task_unlock (task); +return -ENOPROTOOPT ; + } + oldcontid =audit_get_contid (task); +read_lock (&tasklist_lock); +/* Don't allow the audit containerid to be unset */ +if (!audit_contid_valid (contid)) + rc = -EINVAL ; +/* if we don't have caps, reject */ +else if (!capable (CAP_AUDIT_CONTROL )) + rc = -EPERM ; +/* if task has children or is not single-threaded, deny */ +else if (!list_empty (&task->children)) + rc = -EBUSY ; +else if (!(thread_group_leader (task) &&thread_group_empty (task))) + rc = -EALREADY ; +read_unlock (&tasklist_lock); +if (!rc) + task->audit->contid = contid; +task_unlock (task); + +if (!audit_enabled) +return rc; + + ab =audit_log_start (audit_context (),GFP_KERNEL ,AUDIT_CONTAINER_OP ); +if (!ab) +return rc; + + uid =from_kuid (&init_user_ns,task_uid (current)); + tty =audit_get_tty (); +audit_log_format (ab,"op=set opid=%d old-contid=%llu contid=%llu pid=%d uid=%u auid=%u tty=%s ses=%u" , +task_tgid_nr (task), oldcontid, contid, +task_tgid_nr (current), uid, +from_kuid (&init_user_ns,audit_get_loginuid (current)), + tty ?tty_name (tty) :"(none)" , +audit_get_sessionid (current)); +audit_put_tty (tty); +audit_log_task_context (ab); +audit_log_format (ab," comm=" ); +audit_log_untrustedstring (ab,get_task_comm (comm, current)); +audit_log_d_path_exe (ab, current->mm); +audit_log_format (ab," res=%d" , !rc); +audit_log_end (ab); +return rc; +} + +/** * audit_log_end - end one audit record * @ab: the audit_buffer * --
Quoted 2 lines
1.8.3.1
--
Ondrej Mosnacek <omosnace at redhat dot com>
Software Engineer, Security Technologies
Red Hat, Inc.
Re: [PATCH ghak90 V5 02/10] audit: add container id
Quoted 29 lines · Ondrej Mosnacek
Quoted 28 lines · Richard Guy Briggs
Implement the proc fs write to set the audit container identifier of a process, emitting an
AUDIT_CONTAINER_OPrecord to document the event.This is a write from the container orchestrator task to a proc entry of the form
/proc/PID/audit_containeridwhere PID is the process ID of the newly created task that is to become the first task in a container, or an additional task added to a container.The write expects up to a u64 value (unset: 18446744073709551615).
The writer must have capability
CAP_AUDIT_CONTROL.This will produce a record such as this:
type=CONTAINER_OP msg=audit(2018-06-06 12:39:29.636:26949) : op=set opid=2209 old-contid=18446744073709551615 contid=123456 pid=628 auid=root uid=root tty=ttyS0 ses=1 subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 comm=bash exe=/usr/bin/bash res=yesThe "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
Quoted 6 lines
Quoted 4 lines
Signed-off-by Richard Guy Briggs <[email protected]>Acked-by Serge Hallyn <[email protected]>Acked-by Steve Grubb <[email protected]>Signed-off-by Richard Guy Briggs <[email protected]>Note that you have duplicate Signed-off here ^^
Yeah, I caught a few of those for v6 and a number of other formatting issues.
Quoted 244 lines
Took me a while to understand the flow in
audit_set_contid(), but once understood it all made perfect sense, so:Reviewed-by Ondrej Mosnacek <[email protected]>Quoted 238 lines
--- fs/proc/base.c | 36 ++++++++++++++++++++++++ include/linux/audit.h | 25 +++++++++++++++++ include/uapi/linux/audit.h | 2 ++ kernel/audit.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 131 insertions(+)fs/proc/base.c +36
-0@@ -1294,6 +1294,40 @@ static ssize_t proc_sessionid_read(struct file * file, char __user * buf, .read = proc_sessionid_read, .llseek = generic_file_llseek, }; + +static ssize_t proc_contid_write (struct file *file,const char __user *buf, +size_t count,loff_t *ppos) +{ +struct inode *inode =file_inode (file); +u64 contid; +int rv; +struct task_struct *task =get_proc_task (inode); + +if (!task) +return -ESRCH ; +if (*ppos !=0 ) { +/* No partial writes. */ +put_task_struct (task); +return -EINVAL ; + } + + rv =kstrtou64_from_user (buf, count,10 , &contid); +if (rv <0 ) { +put_task_struct (task); +return rv; + } + + rv =audit_set_contid (task, contid); +put_task_struct (task); +if (rv <0 ) +return rv; +return count; +} + +static const struct file_operations proc_contid_operations = { + .write = proc_contid_write, + .llseek = generic_file_llseek, +};#endif #ifdef CONFIG_FAULT_INJECTION @@ -3005,6 +3039,7 @@ static int proc_stack_depth(struct seq_file *m, struct pid_namespace *ns,#ifdef CONFIG_AUDIT REG ("loginuid" ,S_IWUSR |S_IRUGO , proc_loginuid_operations),REG ("sessionid" ,S_IRUGO , proc_sessionid_operations), +REG ("audit_containerid" ,S_IWUSR , proc_contid_operations), #endif #ifdef CONFIG_FAULT_INJECTION REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations),@@ -3393,6 +3428,7 @@ static int proc_tid_comm_permission(struct inode *inode, int mask)#ifdef CONFIG_AUDIT REG ("loginuid" ,S_IWUSR |S_IRUGO , proc_loginuid_operations),REG ("sessionid" ,S_IRUGO , proc_sessionid_operations), +REG ("audit_containerid" ,S_IWUSR , proc_contid_operations), #endif #ifdef CONFIG_FAULT_INJECTION REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations),include/linux/audit.h +25
-0@@ -89,6 +89,7 @@ struct audit_field {struct audit_task_info {kuid_t loginuid;unsigned int sessionid; +u64 contid;#ifdef CONFIG_AUDITSYSCALL struct audit_context *ctx;#endif @@ -189,6 +190,15 @@ static inline unsigned int audit_get_sessionid(struct task_struct *tsk) return tsk->audit->sessionid; } +extern int audit_set_contid (struct task_struct *tsk,u64 contid); + +static inline u64 audit_get_contid (struct task_struct *tsk) +{ +if (!tsk->audit) +return AUDIT_CID_UNSET ; +return tsk->audit->contid; +} +extern u32 audit_enabled;#else /* CONFIG_AUDIT */ static inline int audit_alloc (struct task_struct *task)@@ -250,6 +260,11 @@ static inline unsigned int audit_get_sessionid(struct task_struct *tsk) return AUDIT_SID_UNSET; } +static inline u64 audit_get_contid (struct task_struct *tsk) +{ +return AUDIT_CID_UNSET ; +} +#define audit_enabled AUDIT_OFF#endif /* CONFIG_AUDIT */ @@ -606,6 +621,16 @@ static inline bool audit_loginuid_set(struct task_struct *tsk)return uid_valid (audit_get_loginuid (tsk)); } +static inline bool audit_contid_valid (u64 contid) +{ +return contid !=AUDIT_CID_UNSET ; +} + +static inline bool audit_contid_set (struct task_struct *tsk) +{ +return audit_contid_valid (audit_get_contid (tsk)); +} +static inline void audit_log_string (struct audit_buffer *ab,const char *buf) {audit_log_n_string (ab, buf,strlen (buf));include/uapi/linux/audit.h +2
-0@@ -71,6 +71,7 @@#define AUDIT_TTY_SET 1017/* Set TTY auditing status */ #define AUDIT_SET_FEATURE 1018/* Turn an audit feature on or off */ #define AUDIT_GET_FEATURE 1019/* Get which features are enabled */ +#define AUDIT_CONTAINER_OP 1020/* Define the container id and information */ #define AUDIT_FIRST_USER_MSG 1100/* Userspace messages mostly uninteresting to kernel */ #define AUDIT_USER_AVC 1107/* We filter this differently */ @@ -471,6 +472,7 @@ struct audit_tty_status {#define AUDIT_UID_UNSET (unsigned int)-1#define AUDIT_SID_UNSET ((unsigned int)-1) +#define AUDIT_CID_UNSET ((u64)-1)/* audit_rule_data supports filter rules with both integer and string * fields. It corresponds with AUDIT_ADD_RULE, AUDIT_DEL_RULE and kernel/audit.c +68
-0@@ -244,6 +244,7 @@ int audit_alloc(struct task_struct *tsk) } info->loginuid =audit_get_loginuid (current); info->sessionid =audit_get_sessionid (current); + info->contid =audit_get_contid (current); tsk->audit = info; ret =audit_alloc_syscall (tsk);@@ -258,6 +259,7 @@ int audit_alloc(struct task_struct *tsk)struct audit_task_info init_struct_audit = { .loginuid =INVALID_UID , .sessionid =AUDIT_SID_UNSET , + .contid =AUDIT_CID_UNSET , #ifdef CONFIG_AUDITSYSCALL .ctx =NULL , #endif@@ -2341,6 +2343,72 @@ int audit_set_loginuid(kuid_t loginuid) }/** +* audit_set_contid - set current task's audit contid +* @contid: contid value +* +* Returns 0 on success, -EPERM on permission failure. +* +* Called (set) from fs/proc/base.c::proc_contid_write(). +*/ +int audit_set_contid (struct task_struct *task,u64 contid) +{ +u64 oldcontid; +int rc =0 ; +struct audit_buffer *ab; +uid_t uid; +struct tty_struct *tty; +char comm[sizeof (current->comm)]; + +task_lock (task); +/* Can't set if audit disabled */ +if (!task->audit) { +task_unlock (task); +return -ENOPROTOOPT ; + } + oldcontid =audit_get_contid (task); +read_lock (&tasklist_lock); +/* Don't allow the audit containerid to be unset */ +if (!audit_contid_valid (contid)) + rc = -EINVAL ; +/* if we don't have caps, reject */ +else if (!capable (CAP_AUDIT_CONTROL )) + rc = -EPERM ; +/* if task has children or is not single-threaded, deny */ +else if (!list_empty (&task->children)) + rc = -EBUSY ; +else if (!(thread_group_leader (task) &&thread_group_empty (task))) + rc = -EALREADY ; +read_unlock (&tasklist_lock); +if (!rc) + task->audit->contid = contid; +task_unlock (task); + +if (!audit_enabled) +return rc; + + ab =audit_log_start (audit_context (),GFP_KERNEL ,AUDIT_CONTAINER_OP ); +if (!ab) +return rc; + + uid =from_kuid (&init_user_ns,task_uid (current)); + tty =audit_get_tty (); +audit_log_format (ab,"op=set opid=%d old-contid=%llu contid=%llu pid=%d uid=%u auid=%u tty=%s ses=%u" , +task_tgid_nr (task), oldcontid, contid, +task_tgid_nr (current), uid, +from_kuid (&init_user_ns,audit_get_loginuid (current)), + tty ?tty_name (tty) :"(none)" , +audit_get_sessionid (current)); +audit_put_tty (tty); +audit_log_task_context (ab); +audit_log_format (ab," comm=" ); +audit_log_untrustedstring (ab,get_task_comm (comm, current)); +audit_log_d_path_exe (ab, current->mm); +audit_log_format (ab," res=%d" , !rc); +audit_log_end (ab); +return rc; +} + +/** * audit_log_end - end one audit record * @ab: the audit_buffer *
Quoted 8 lines
Quoted 3 lines
--
1.8.3.1--
Ondrej Mosnacek <omosnace at redhat dot com>
Software Engineer, Security Technologies
Red Hat, Inc.
- 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
PATCH v5 3/10 audit: read container ID of a process
In reply to Richard Guy BriggsAdd 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.
--- fs/proc/base.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-)
fs/proc/base.c +21 -2
@@ -1295,6 +1295,24 @@ static ssize_t proc_sessionid_read(struct file * file, char __user * buf, .llseek = generic_file_llseek, }; +static ssize_t proc_contid_read (struct file *file,char __user *buf, +size_t count,loff_t *ppos) +{ +struct inode *inode =file_inode (file); +struct task_struct *task =get_proc_task (inode); +ssize_t length; +char tmpbuf[TMPBUFLEN *2 ]; + +if (!task) +return -ESRCH ; +/* if we don't have caps, reject */ +if (!capable (CAP_AUDIT_CONTROL )) +return -EPERM ; + length =scnprintf (tmpbuf,TMPBUFLEN *2 ,"%llu" ,audit_get_contid (task)); +put_task_struct (task); +return simple_read_from_buffer (buf, count, ppos, tmpbuf, length); +} +static ssize_t proc_contid_write (struct file *file,const char __user *buf,size_t count,loff_t *ppos) {
@@ -1325,6 +1343,7 @@ static ssize_t proc_contid_write(struct file *file, const char __user *buf, }static const struct file_operations proc_contid_operations = { + .read = proc_contid_read, .write = proc_contid_write, .llseek = generic_file_llseek, };
@@ -3039,7 +3058,7 @@ static int proc_stack_depth(struct seq_file *m, struct pid_namespace *ns,#ifdef CONFIG_AUDIT REG ("loginuid" ,S_IWUSR |S_IRUGO , proc_loginuid_operations),REG ("sessionid" ,S_IRUGO , proc_sessionid_operations), -REG ("audit_containerid" ,S_IWUSR , proc_contid_operations), +REG ("audit_containerid" ,S_IWUSR |S_IRUSR , proc_contid_operations), #endif #ifdef CONFIG_FAULT_INJECTION REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations),
@@ -3428,7 +3447,7 @@ static int proc_tid_comm_permission(struct inode *inode, int mask)#ifdef CONFIG_AUDIT REG ("loginuid" ,S_IWUSR |S_IRUGO , proc_loginuid_operations),REG ("sessionid" ,S_IRUGO , proc_sessionid_operations), -REG ("audit_containerid" ,S_IWUSR , proc_contid_operations), +REG ("audit_containerid" ,S_IWUSR |S_IRUSR , proc_contid_operations), #endif #ifdef CONFIG_FAULT_INJECTION REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations),
Signature · 1 line
1.8.3.1
Re: [PATCH ghak90 V5 03/10] audit: read container ID of a process
Quoted 23 lines · Richard Guy Briggs
Add support for reading the audit container identifier from the proc filesystem.
This is a read from the proc entry of the form
/proc/PID/audit_containeridwhere 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(-)fs/proc/base.c +0
-0@@ -1295,6 +1295,24 @@ static ssize_t proc_sessionid_read(struct file * file, char __user * buf, .llseek = generic_file_llseek,
fs/proc/base.c static ssize_t proc_sessionid_read(struct file * file, char __user * buf, · line 1305
Quoted 10 lines
fs/proc/base.c +8
-0}; +static ssize_t proc_contid_read (struct file *file,char __user *buf, +size_t count,loff_t *ppos) +{ +struct inode *inode =file_inode (file); +struct task_struct *task =get_proc_task (inode); +ssize_t length; +char tmpbuf[TMPBUFLEN *2 ]; +
Sorry, didn't notice this previously, but..
Why *2 here? Its not wrong per-se, but would it be better to just change TMPBUFLEN to be 22 bytes unilaterally? Its only ever used on stack calls that arent that deep, and then you won't have to think about adjusting this call site if you ever change the value of TMPBUFLEN in the future.
I'm fine with doing this in another patch later, but it seems like a worthwhile cleanup
functionality looks good beyond that nit.
Quoted 43 lines
fs/proc/base.c +13
-2+if (!task) +return -ESRCH ; +/* if we don't have caps, reject */ +if (!capable (CAP_AUDIT_CONTROL )) +return -EPERM ; + length =scnprintf (tmpbuf,TMPBUFLEN *2 ,"%llu" ,audit_get_contid (task)); +put_task_struct (task); +return simple_read_from_buffer (buf, count, ppos, tmpbuf, length); +} +static ssize_t proc_contid_write (struct file *file,const char __user *buf,size_t count,loff_t *ppos) {@@ -1325,6 +1343,7 @@ static ssize_t proc_contid_write(struct file *file, const char __user *buf, }static const struct file_operations proc_contid_operations = { + .read = proc_contid_read, .write = proc_contid_write, .llseek = generic_file_llseek, };@@ -3039,7 +3058,7 @@ static int proc_stack_depth(struct seq_file *m, struct pid_namespace *ns,#ifdef CONFIG_AUDIT REG ("loginuid" ,S_IWUSR |S_IRUGO , proc_loginuid_operations),REG ("sessionid" ,S_IRUGO , proc_sessionid_operations), -REG ("audit_containerid" ,S_IWUSR , proc_contid_operations), +REG ("audit_containerid" ,S_IWUSR |S_IRUSR , proc_contid_operations), #endif #ifdef CONFIG_FAULT_INJECTION REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations),@@ -3428,7 +3447,7 @@ static int proc_tid_comm_permission(struct inode *inode, int mask)#ifdef CONFIG_AUDIT REG ("loginuid" ,S_IWUSR |S_IRUGO , proc_loginuid_operations),REG ("sessionid" ,S_IRUGO , proc_sessionid_operations), -REG ("audit_containerid" ,S_IWUSR , proc_contid_operations), +REG ("audit_containerid" ,S_IWUSR |S_IRUSR , proc_contid_operations), #endif #ifdef CONFIG_FAULT_INJECTION REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations),Signature · 1 line
1.8.3.1
Re: [PATCH ghak90 V5 03/10] audit: read container ID of a process
Quoted 26 lines · Neil Horman
Quoted 25 lines · Richard Guy Briggs
Add support for reading the audit container identifier from the proc filesystem.
This is a read from the proc entry of the form
/proc/PID/audit_containeridwhere 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(-)fs/proc/base.c +0
-0@@ -1295,6 +1295,24 @@ static ssize_t proc_sessionid_read(struct file * file, char __user * buf, .llseek = generic_file_llseek, };
Quoted 13 lines
fs/proc/base.c static ssize_t proc_sessionid_read(struct file * file, char __user * buf, · line 1305
Quoted 8 lines
fs/proc/base.c +8
-0+static ssize_t proc_contid_read (struct file *file,char __user *buf, +size_t count,loff_t *ppos) +{ +struct inode *inode =file_inode (file); +struct task_struct *task =get_proc_task (inode); +ssize_t length; +char tmpbuf[TMPBUFLEN *2 ]; +Sorry, didn't notice this previously, but..
Why *2 here? Its not wrong per-se, but would it be better to just change TMPBUFLEN to be 22 bytes unilaterally? Its only ever used on stack calls that arent that deep, and then you won't have to think about adjusting this call site if you ever change the value of TMPBUFLEN in the future.
TMPBUFLEN is 11 to accomodate a decimal representation of a u32 with terminating NULL. Since the contid is a u64, it was least disruptive and made sense to me to just double it. I could define a TMPBUFLEN2 to be 21 if you prefer?
Quoted 41 lines
I'm fine with doing this in another patch later, but it seems like a worthwhile cleanup
functionality looks good beyond that nit.
Quoted 36 lines
fs/proc/base.c +13
-2+if (!task) +return -ESRCH ; +/* if we don't have caps, reject */ +if (!capable (CAP_AUDIT_CONTROL )) +return -EPERM ; + length =scnprintf (tmpbuf,TMPBUFLEN *2 ,"%llu" ,audit_get_contid (task)); +put_task_struct (task); +return simple_read_from_buffer (buf, count, ppos, tmpbuf, length); +} +static ssize_t proc_contid_write (struct file *file,const char __user *buf,size_t count,loff_t *ppos) {@@ -1325,6 +1343,7 @@ static ssize_t proc_contid_write(struct file *file, const char __user *buf, }static const struct file_operations proc_contid_operations = { + .read = proc_contid_read, .write = proc_contid_write, .llseek = generic_file_llseek, };@@ -3039,7 +3058,7 @@ static int proc_stack_depth(struct seq_file *m, struct pid_namespace *ns,#ifdef CONFIG_AUDIT REG ("loginuid" ,S_IWUSR |S_IRUGO , proc_loginuid_operations),REG ("sessionid" ,S_IRUGO , proc_sessionid_operations), -REG ("audit_containerid" ,S_IWUSR , proc_contid_operations), +REG ("audit_containerid" ,S_IWUSR |S_IRUSR , proc_contid_operations), #endif #ifdef CONFIG_FAULT_INJECTION REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations),@@ -3428,7 +3447,7 @@ static int proc_tid_comm_permission(struct inode *inode, int mask)#ifdef CONFIG_AUDIT REG ("loginuid" ,S_IWUSR |S_IRUGO , proc_loginuid_operations),REG ("sessionid" ,S_IRUGO , proc_sessionid_operations), - REG("audit_containerid", S_IWUSR, proc_contid_operations), + REG("audit_containerid", S_IWUSR|S_IRUSR, proc_contid_operations),
Quoted 9 lines
Quoted 7 lines
fs/proc/base.c +0
-0#endif #ifdef CONFIG_FAULT_INJECTION REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations),Signature · 1 line
1.8.3.1Acked-by Neil Horman <[email protected]>
- 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
Re: [PATCH ghak90 V5 03/10] audit: read container ID of a process
Quoted 41 lines · Richard Guy Briggs
Quoted 26 lines · Neil Horman
Quoted 25 lines · Richard Guy Briggs
Add support for reading the audit container identifier from the proc filesystem.
This is a read from the proc entry of the form
/proc/PID/audit_containeridwhere 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(-)fs/proc/base.c +0
-0@@ -1295,6 +1295,24 @@ static ssize_t proc_sessionid_read(struct file * file, char __user * buf, .llseek = generic_file_llseek, };Quoted 13 lines
fs/proc/base.c static ssize_t proc_sessionid_read(struct file * file, char __user * buf, · line 1305
Quoted 8 lines
fs/proc/base.c +8
-0+static ssize_t proc_contid_read (struct file *file,char __user *buf, +size_t count,loff_t *ppos) +{ +struct inode *inode =file_inode (file); +struct task_struct *task =get_proc_task (inode); +ssize_t length; +char tmpbuf[TMPBUFLEN *2 ]; +Sorry, didn't notice this previously, but..
Why *2 here? Its not wrong per-se, but would it be better to just change TMPBUFLEN to be 22 bytes unilaterally? Its only ever used on stack calls that arent that deep, and then you won't have to think about adjusting this call site if you ever change the value of TMPBUFLEN in the future.
Quoted 5 lines
TMPBUFLEN is 11 to accomodate a decimal representation of a u32 with terminating NULL. Since the contid is a u64, it was least disruptive and made sense to me to just double it. I could define a TMPBUFLEN2 to be 21 if you prefer?
I'm not adamant on any particular change, just noticing the inconsistency. I usually write macro buffer sizes to accomodate the largest string I plan to hold, so it can be used ubiquitously when the overage is small and transiently allocated, but if you feel like the space would be better conserved a TMPBUFLEN/ TMPBUFLEN2 approach would be fine (or a TMPBUFLENU32 / TMPBUFLENU64 macro set).
Its not anything that needs fixing now, just an observation for clean up at some future point.
Neil
Quoted 60 lines
Quoted 41 lines
I'm fine with doing this in another patch later, but it seems like a worthwhile cleanup
functionality looks good beyond that nit.
Quoted 36 lines
fs/proc/base.c +13
-2+if (!task) +return -ESRCH ; +/* if we don't have caps, reject */ +if (!capable (CAP_AUDIT_CONTROL )) +return -EPERM ; + length =scnprintf (tmpbuf,TMPBUFLEN *2 ,"%llu" ,audit_get_contid (task)); +put_task_struct (task); +return simple_read_from_buffer (buf, count, ppos, tmpbuf, length); +} +static ssize_t proc_contid_write (struct file *file,const char __user *buf,size_t count,loff_t *ppos) {@@ -1325,6 +1343,7 @@ static ssize_t proc_contid_write(struct file *file, const char __user *buf, }static const struct file_operations proc_contid_operations = { + .read = proc_contid_read, .write = proc_contid_write, .llseek = generic_file_llseek, };@@ -3039,7 +3058,7 @@ static int proc_stack_depth(struct seq_file *m, struct pid_namespace *ns,#ifdef CONFIG_AUDIT REG ("loginuid" ,S_IWUSR |S_IRUGO , proc_loginuid_operations),REG ("sessionid" ,S_IRUGO , proc_sessionid_operations), -REG ("audit_containerid" ,S_IWUSR , proc_contid_operations), +REG ("audit_containerid" ,S_IWUSR |S_IRUSR , proc_contid_operations), #endif #ifdef CONFIG_FAULT_INJECTION REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations),@@ -3428,7 +3447,7 @@ static int proc_tid_comm_permission(struct inode *inode, int mask)#ifdef CONFIG_AUDIT REG ("loginuid" ,S_IWUSR |S_IRUGO , proc_loginuid_operations),REG ("sessionid" ,S_IRUGO , proc_sessionid_operations), - REG("audit_containerid", S_IWUSR, proc_contid_operations), + REG("audit_containerid", S_IWUSR|S_IRUSR, proc_contid_operations),Quoted 9 lines
Quoted 7 lines
fs/proc/base.c +0
-0#endif #ifdef CONFIG_FAULT_INJECTION REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations),Signature · 1 line
1.8.3.1Acked-by Neil Horman <[email protected]>- 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
Re: [PATCH ghak90 V5 03/10] audit: read container ID of a process
Quoted 47 lines · Neil Horman
Quoted 41 lines · Richard Guy Briggs
Quoted 26 lines · Neil Horman
Quoted 25 lines · Richard Guy Briggs
Add support for reading the audit container identifier from the proc filesystem.
This is a read from the proc entry of the form
/proc/PID/audit_containeridwhere 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(-)fs/proc/base.c +0
-0@@ -1295,6 +1295,24 @@ static ssize_t proc_sessionid_read(struct file * file, char __user * buf, .llseek = generic_file_llseek, };Quoted 13 lines
fs/proc/base.c static ssize_t proc_sessionid_read(struct file * file, char __user * buf, · line 1305
Quoted 8 lines
fs/proc/base.c +8
-0+static ssize_t proc_contid_read (struct file *file,char __user *buf, +size_t count,loff_t *ppos) +{ +struct inode *inode =file_inode (file); +struct task_struct *task =get_proc_task (inode); +ssize_t length; +char tmpbuf[TMPBUFLEN *2 ]; +Sorry, didn't notice this previously, but..
Why *2 here? Its not wrong per-se, but would it be better to just change TMPBUFLEN to be 22 bytes unilaterally? Its only ever used on stack calls that arent that deep, and then you won't have to think about adjusting this call site if you ever change the value of TMPBUFLEN in the future.Quoted 5 lines
TMPBUFLEN is 11 to accomodate a decimal representation of a u32 with terminating NULL. Since the contid is a u64, it was least disruptive and made sense to me to just double it. I could define a TMPBUFLEN2 to be 21 if you prefer?
Quoted 5 lines
I'm not adamant on any particular change, just noticing the inconsistency. I usually write macro buffer sizes to accomodate the largest string I plan to hold, so it can be used ubiquitously when the overage is small and transiently allocated, but if you feel like the space would be better conserved a TMPBUFLEN/ TMPBUFLEN2 approach would be fine (or a TMPBUFLENU32 / TMPBUFLENU64 macro set).
Ok, I see your point about it being transient. I'll fix it up if there is a respin.
Quoted 54 lines
Its not anything that needs fixing now, just an observation for clean up at some future point.
NeilQuoted 50 lines
Quoted 40 lines
I'm fine with doing this in another patch later, but it seems like a worthwhile cleanup
functionality looks good beyond that nit.
Quoted 35 lines
fs/proc/base.c +12
-2+if (!task) +return -ESRCH ; +/* if we don't have caps, reject */ +if (!capable (CAP_AUDIT_CONTROL )) +return -EPERM ; + length =scnprintf (tmpbuf,TMPBUFLEN *2 ,"%llu" ,audit_get_contid (task)); +put_task_struct (task); +return simple_read_from_buffer (buf, count, ppos, tmpbuf, length); +} +static ssize_t proc_contid_write (struct file *file,const char __user *buf,size_t count,loff_t *ppos) {@@ -1325,6 +1343,7 @@ static ssize_t proc_contid_write(struct file *file, const char __user *buf, }static const struct file_operations proc_contid_operations = { + .read = proc_contid_read, .write = proc_contid_write, .llseek = generic_file_llseek, };@@ -3039,7 +3058,7 @@ static int proc_stack_depth(struct seq_file *m, struct pid_namespace *ns,#ifdef CONFIG_AUDIT REG ("loginuid" ,S_IWUSR |S_IRUGO , proc_loginuid_operations),REG ("sessionid" ,S_IRUGO , proc_sessionid_operations), -REG ("audit_containerid" ,S_IWUSR , proc_contid_operations), +REG ("audit_containerid" ,S_IWUSR |S_IRUSR , proc_contid_operations), #endif #ifdef CONFIG_FAULT_INJECTION REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations),@@ -3428,7 +3447,7 @@ static int proc_tid_comm_permission(struct inode *inode, int mask)#ifdef CONFIG_AUDIT REG ("loginuid" ,S_IWUSR |S_IRUGO , proc_loginuid_operations), REG("sessionid", S_IRUGO, proc_sessionid_operations), - REG("audit_containerid", S_IWUSR, proc_contid_operations),Quoted 8 lines
Quoted 7 lines
fs/proc/base.c +1
-0+ 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),Signature · 1 line
1.8.3.1Acked-by Neil Horman <[email protected]>- RGB
- RGB
Re: [PATCH ghak90 V5 03/10] audit: read container ID of a process
In reply to Richard Guy BriggsQuoted 7 lines · Richard Guy Briggs
Add support for reading the audit container identifier from the proc filesystem.
This is a read from the proc entry of the form
/proc/PID/audit_containeridwhere PID is the process ID of the task whose audit container identifier is sought.
Quoted 6 lines
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]>
Quoted 62 lines
--- fs/proc/base.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-)fs/proc/base.c +21
-3@@ -1295,6 +1295,24 @@ static ssize_t proc_sessionid_read(struct file * file, char __user * buf, .llseek = generic_file_llseek, }; +static ssize_t proc_contid_read (struct file *file,char __user *buf, +size_t count,loff_t *ppos) +{ +struct inode *inode =file_inode (file); +struct task_struct *task =get_proc_task (inode); +ssize_t length; +char tmpbuf[TMPBUFLEN *2 ]; + +if (!task) +return -ESRCH ; +/* if we don't have caps, reject */ +if (!capable (CAP_AUDIT_CONTROL )) +return -EPERM ; + length =scnprintf (tmpbuf,TMPBUFLEN *2 ,"%llu" ,audit_get_contid (task)); +put_task_struct (task); +return simple_read_from_buffer (buf, count, ppos, tmpbuf, length); +} +static ssize_t proc_contid_write (struct file *file,const char __user *buf,size_t count,loff_t *ppos) {@@ -1325,6 +1343,7 @@ static ssize_t proc_contid_write(struct file *file, const char __user *buf, }static const struct file_operations proc_contid_operations = { + .read = proc_contid_read, .write = proc_contid_write, .llseek = generic_file_llseek, };@@ -3039,7 +3058,7 @@ static int proc_stack_depth(struct seq_file *m, struct pid_namespace *ns,#ifdef CONFIG_AUDIT REG ("loginuid" ,S_IWUSR |S_IRUGO , proc_loginuid_operations),REG ("sessionid" ,S_IRUGO , proc_sessionid_operations), -REG ("audit_containerid" ,S_IWUSR , proc_contid_operations), +REG ("audit_containerid" ,S_IWUSR |S_IRUSR , proc_contid_operations), #endif #ifdef CONFIG_FAULT_INJECTION REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations),@@ -3428,7 +3447,7 @@ static int proc_tid_comm_permission(struct inode *inode, int mask)#ifdef CONFIG_AUDIT REG ("loginuid" ,S_IWUSR |S_IRUGO , proc_loginuid_operations),REG ("sessionid" ,S_IRUGO , proc_sessionid_operations), -REG ("audit_containerid" ,S_IWUSR , proc_contid_operations), +REG ("audit_containerid" ,S_IWUSR |S_IRUSR , proc_contid_operations), #endif #ifdef CONFIG_FAULT_INJECTION REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations), --1.8.3.1
Signature · 3 lines
Ondrej Mosnacek <omosnace at redhat dot com> Software Engineer, Security Technologies Red Hat, Inc.
PATCH v5 4/10 audit: log container info of syscalls
In reply to Richard Guy BriggsCreate a new audit record AUDIT_CONTAINER_ID to document the audit container identifier of a process if it is present.
Called from audit_log_exit(), syscalls are covered.
A sample raw event:
type=SYSCALL msg=audit(1519924845.499:257): arch=c000003e syscall=257 success=yes exit=3 a0=ffffff9c a1=56374e1cef30 a2=241 a3=1b6 items=2 ppid=606 pid=635 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts0 ses=3 comm="bash" exe="/usr/bin/bash" subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 key="tmpcontainerid" type=CWD msg=audit(1519924845.499:257): cwd="/root"
type=PATH msg=audit(1519924845.499:257): item=0 name="/tmp/" inode=13863 dev=00:27 mode=041777 ouid=0 ogid=0 rdev=00:00 obj=system_u:object_r:tmp_t:s0 nametype= PARENT cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0
type=PATH msg=audit(1519924845.499:257): item=1 name="/tmp/tmpcontainerid" inode=17729 dev=00:27 mode=0100644 ouid=0 ogid=0 rdev=00:00 obj=unconfined_u:object_r:user_tmp_t:s0 nametype=CREATE cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0
type=PROCTITLE msg=audit(1519924845.499:257): proctitle=62617368002D6300736C65657020313B206563686F2074657374203E202F746D702F746D70636F6E7461696E65726964
type=CONTAINER_ID msg=audit(1519924845.499:257): contid=123458
See: https://github.com/linux-audit/audit-kernel/issues/90
See: https://github.com/linux-audit/audit-userspace/issues/51
See: https://github.com/linux-audit/audit-testsuite/issues/64
See: https://github.com/linux-audit/audit-kernel/wiki/RFE-Audit-Container-ID
--- include/linux/audit.h | 5 +++++ include/uapi/linux/audit.h | 1 + kernel/audit.c | 21 +++++++++++++++++++++ kernel/auditsc.c | 2 ++ 4 files changed, 29 insertions(+)
include/linux/audit.h +5 -0
@@ -199,6 +199,8 @@ static inline u64 audit_get_contid(struct task_struct *tsk) return tsk->audit->contid; } +extern void audit_log_contid (struct audit_context *context,u64 contid); +extern u32 audit_enabled;#else /* CONFIG_AUDIT */ static inline int audit_alloc (struct task_struct *task)
@@ -265,6 +267,9 @@ static inline u64 audit_get_contid(struct task_struct *tsk) return AUDIT_CID_UNSET; } +static inline void audit_log_contid (struct audit_context *context,u64 contid) +{ } +#define audit_enabled AUDIT_OFF#endif /* CONFIG_AUDIT */
include/uapi/linux/audit.h +1 -0
@@ -115,6 +115,7 @@#define AUDIT_REPLACE 1329/* Replace auditd if this packet unanswerd */ #define AUDIT_KERN_MODULE 1330/* Kernel Module events */ #define AUDIT_FANOTIFY 1331/* Fanotify access decision */ +#define AUDIT_CONTAINER_ID 1332/* Container ID */ #define AUDIT_AVC 1400/* SE Linux avc denial or grant */ #define AUDIT_SELINUX_ERR 1401/* Internal SE Linux Errors */
kernel/audit.c +21 -0
@@ -2127,6 +2127,27 @@ void audit_log_session_info(struct audit_buffer *ab)audit_log_format (ab,"auid=%u ses=%u" , auid, sessionid); } +/* +* audit_log_contid - report container info +* @context: task or local context for record +* @contid: container ID to report +*/ +void audit_log_contid (struct audit_context *context,u64 contid) +{ +struct audit_buffer *ab; + +if (!audit_contid_valid (contid)) +return ; +/* Generate AUDIT_CONTAINER_ID record with container ID */ + ab =audit_log_start (context,GFP_KERNEL ,AUDIT_CONTAINER_ID ); +if (!ab) +return ; +audit_log_format (ab,"contid=%llu" , contid); +audit_log_end (ab); +return ; +} +EXPORT_SYMBOL (audit_log_contid); +void audit_log_key (struct audit_buffer *ab,char *key) {audit_log_format (ab," key=" );
kernel/auditsc.c +2 -0
@@ -1548,6 +1548,8 @@ static void audit_log_exit(void)audit_log_proctitle (); +audit_log_contid (context,audit_get_contid (current)); +/* Send end of event record to help user space know we are finished */ ab =audit_log_start (context,GFP_KERNEL ,AUDIT_EOE );if (ab)
Signature · 1 line
1.8.3.1
Re: [PATCH ghak90 V5 04/10] audit: log container info of syscalls
Quoted 112 lines · Richard Guy Briggs
Create a new audit record
AUDIT_CONTAINER_IDto document the audit container identifier of a process if it is present.Called from
audit_log_exit(), syscalls are covered.A sample raw event:
type=SYSCALL msg=audit(1519924845.499:257): arch=c000003e syscall=257 success=yes exit=3 a0=ffffff9c a1=56374e1cef30 a2=241 a3=1b6 items=2 ppid=606 pid=635 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts0 ses=3 comm="bash" exe="/usr/bin/bash" subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 key="tmpcontainerid" type=CWD msg=audit(1519924845.499:257): cwd="/root"
type=PATH msg=audit(1519924845.499:257): item=0 name="/tmp/" inode=13863 dev=00:27 mode=041777 ouid=0 ogid=0 rdev=00:00 obj=system_u:object_r:tmp_t:s0 nametype= PARENT cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0
type=PATH msg=audit(1519924845.499:257): item=1 name="/tmp/tmpcontainerid" inode=17729 dev=00:27 mode=0100644 ouid=0 ogid=0 rdev=00:00 obj=unconfined_u:object_r:user_tmp_t:s0 nametype=CREATE cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0
type=PROCTITLE msg=audit(1519924845.499:257): proctitle=62617368002D6300736C65657020313B206563686F2074657374203E202F746D702F746D70636F6E7461696E65726964
type=CONTAINER_ID msg=audit(1519924845.499:257): contid=123458See: 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-IDSigned-off-by Richard Guy Briggs <[email protected]>Acked-by Serge Hallyn <[email protected]>Acked-by Steve Grubb <[email protected]>Signed-off-by Richard Guy Briggs <[email protected]>--- include/linux/audit.h | 5 +++++ include/uapi/linux/audit.h | 1 + kernel/audit.c | 21 +++++++++++++++++++++ kernel/auditsc.c | 2 ++ 4 files changed, 29 insertions(+)include/linux/audit.h +5
-0@@ -199,6 +199,8 @@ static inline u64 audit_get_contid(struct task_struct *tsk) return tsk->audit->contid; } +extern void audit_log_contid (struct audit_context *context,u64 contid); +extern u32 audit_enabled;#else /* CONFIG_AUDIT */ static inline int audit_alloc (struct task_struct *task)@@ -265,6 +267,9 @@ static inline u64 audit_get_contid(struct task_struct *tsk) return AUDIT_CID_UNSET; } +static inline void audit_log_contid (struct audit_context *context,u64 contid) +{ } +#define audit_enabled AUDIT_OFF#endif /* CONFIG_AUDIT */ include/uapi/linux/audit.h +1
-0@@ -115,6 +115,7 @@#define AUDIT_REPLACE 1329/* Replace auditd if this packet unanswerd */ #define AUDIT_KERN_MODULE 1330/* Kernel Module events */ #define AUDIT_FANOTIFY 1331/* Fanotify access decision */ +#define AUDIT_CONTAINER_ID 1332/* Container ID */ #define AUDIT_AVC 1400/* SE Linux avc denial or grant */ #define AUDIT_SELINUX_ERR 1401/* Internal SE Linux Errors */ kernel/audit.c +21
-0@@ -2127,6 +2127,27 @@ void audit_log_session_info(struct audit_buffer *ab)audit_log_format (ab,"auid=%u ses=%u" , auid, sessionid); } +/* +* audit_log_contid - report container info +* @context: task or local context for record +* @contid: container ID to report +*/ +void audit_log_contid (struct audit_context *context,u64 contid) +{ +struct audit_buffer *ab; + +if (!audit_contid_valid (contid)) +return ; +/* Generate AUDIT_CONTAINER_ID record with container ID */ + ab =audit_log_start (context,GFP_KERNEL ,AUDIT_CONTAINER_ID ); +if (!ab) +return ; +audit_log_format (ab,"contid=%llu" , contid); +audit_log_end (ab); +return ; +} +EXPORT_SYMBOL (audit_log_contid); +void audit_log_key (struct audit_buffer *ab,char *key) {audit_log_format (ab," key=" );kernel/auditsc.c +2
-0@@ -1548,6 +1548,8 @@ static void audit_log_exit(void)audit_log_proctitle (); +audit_log_contid (context,audit_get_contid (current)); +/* Send end of event record to help user space know we are finished */ ab =audit_log_start (context,GFP_KERNEL ,AUDIT_EOE );if (ab)Signature · 1 line
1.8.3.1
Re: [PATCH ghak90 V5 04/10] audit: log container info of syscalls
In reply to Richard Guy BriggsQuoted 13 lines · Richard Guy Briggs
Create a new audit record
AUDIT_CONTAINER_IDto document the audit container identifier of a process if it is present.Called from
audit_log_exit(), syscalls are covered.A sample raw event:
type=SYSCALL msg=audit(1519924845.499:257): arch=c000003e syscall=257 success=yes exit=3 a0=ffffff9c a1=56374e1cef30 a2=241 a3=1b6 items=2 ppid=606 pid=635 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts0 ses=3 comm="bash" exe="/usr/bin/bash" subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 key="tmpcontainerid" type=CWD msg=audit(1519924845.499:257): cwd="/root"
type=PATH msg=audit(1519924845.499:257): item=0 name="/tmp/" inode=13863 dev=00:27 mode=041777 ouid=0 ogid=0 rdev=00:00 obj=system_u:object_r:tmp_t:s0 nametype= PARENT cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0
type=PATH msg=audit(1519924845.499:257): item=1 name="/tmp/tmpcontainerid" inode=17729 dev=00:27 mode=0100644 ouid=0 ogid=0 rdev=00:00 obj=unconfined_u:object_r:user_tmp_t:s0 nametype=CREATE cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0
type=PROCTITLE msg=audit(1519924845.499:257): proctitle=62617368002D6300736C65657020313B206563686F2074657374203E202F746D702F746D70636F6E7461696E65726964
type=CONTAINER_ID msg=audit(1519924845.499:257): contid=123458
Quoted 8 lines
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-IDSigned-off-by Richard Guy Briggs <[email protected]>Acked-by Serge Hallyn <[email protected]>Acked-by Steve Grubb <[email protected]>Signed-off-by Richard Guy Briggs <[email protected]>
Barring one minor nit below,
Quoted 56 lines
--- include/linux/audit.h | 5 +++++ include/uapi/linux/audit.h | 1 + kernel/audit.c | 21 +++++++++++++++++++++ kernel/auditsc.c | 2 ++ 4 files changed, 29 insertions(+)include/linux/audit.h +5
-0@@ -199,6 +199,8 @@ static inline u64 audit_get_contid(struct task_struct *tsk) return tsk->audit->contid; } +extern void audit_log_contid (struct audit_context *context,u64 contid); +extern u32 audit_enabled;#else /* CONFIG_AUDIT */ static inline int audit_alloc (struct task_struct *task)@@ -265,6 +267,9 @@ static inline u64 audit_get_contid(struct task_struct *tsk) return AUDIT_CID_UNSET; } +static inline void audit_log_contid (struct audit_context *context,u64 contid) +{ } +#define audit_enabled AUDIT_OFF#endif /* CONFIG_AUDIT */ include/uapi/linux/audit.h +1
-0@@ -115,6 +115,7 @@#define AUDIT_REPLACE 1329/* Replace auditd if this packet unanswerd */ #define AUDIT_KERN_MODULE 1330/* Kernel Module events */ #define AUDIT_FANOTIFY 1331/* Fanotify access decision */ +#define AUDIT_CONTAINER_ID 1332/* Container ID */ #define AUDIT_AVC 1400/* SE Linux avc denial or grant */ #define AUDIT_SELINUX_ERR 1401/* Internal SE Linux Errors */ kernel/audit.c +6
-0@@ -2127,6 +2127,27 @@ void audit_log_session_info(struct audit_buffer *ab)audit_log_format (ab,"auid=%u ses=%u" , auid, sessionid); } +/* +* audit_log_contid - report container info +* @context: task or local context for record +* @contid: container ID to report +*/ +void audit_log_contid (struct audit_context *context,u64 contid)
kernel/audit.c void audit_log_session_info(struct audit_buffer *ab) · line 2145
Quoted 10 lines
kernel/audit.c +10
-0+{ +struct audit_buffer *ab; + +if (!audit_contid_valid (contid)) +return ; +/* Generate AUDIT_CONTAINER_ID record with container ID */ + ab =audit_log_start (context,GFP_KERNEL ,AUDIT_CONTAINER_ID ); +if (!ab) +return ; +audit_log_format (ab,"contid=%llu" , contid);
Just realized that you *might* get a compiler/static checker warning since u64 could technically be something else than unsigned long long on some arches... maybe this is not case in the kernel, but might be safer to cast it to unsigned long long before passing to audit_log_format(). Possibly there are similar occurrences in previous (later) patches that I didn't (won't) notice.
Quoted 24 lines
kernel/audit.c +5
-0+audit_log_end (ab); +return ; +} +EXPORT_SYMBOL (audit_log_contid); +void audit_log_key (struct audit_buffer *ab,char *key) {audit_log_format (ab," key=" );kernel/auditsc.c +2
-1@@ -1548,6 +1548,8 @@ static void audit_log_exit(void)audit_log_proctitle (); +audit_log_contid (context,audit_get_contid (current)); +/* Send end of event record to help user space know we are finished */ ab =audit_log_start (context,GFP_KERNEL ,AUDIT_EOE );if (ab) --1.8.3.1
Signature · 3 lines
Ondrej Mosnacek <omosnace at redhat dot com> Software Engineer, Security Technologies Red Hat, Inc.
Re: [PATCH ghak90 V5 04/10] audit: log container info of syscalls
Quoted 92 lines · Ondrej Mosnacek
Quoted 13 lines · Richard Guy Briggs
Create a new audit record
AUDIT_CONTAINER_IDto document the audit container identifier of a process if it is present.Called from
audit_log_exit(), syscalls are covered.A sample raw event:
type=SYSCALL msg=audit(1519924845.499:257): arch=c000003e syscall=257 success=yes exit=3 a0=ffffff9c a1=56374e1cef30 a2=241 a3=1b6 items=2 ppid=606 pid=635 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts0 ses=3 comm="bash" exe="/usr/bin/bash" subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 key="tmpcontainerid" type=CWD msg=audit(1519924845.499:257): cwd="/root"
type=PATH msg=audit(1519924845.499:257): item=0 name="/tmp/" inode=13863 dev=00:27 mode=041777 ouid=0 ogid=0 rdev=00:00 obj=system_u:object_r:tmp_t:s0 nametype= PARENT cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0
type=PATH msg=audit(1519924845.499:257): item=1 name="/tmp/tmpcontainerid" inode=17729 dev=00:27 mode=0100644 ouid=0 ogid=0 rdev=00:00 obj=unconfined_u:object_r:user_tmp_t:s0 nametype=CREATE cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0
type=PROCTITLE msg=audit(1519924845.499:257): proctitle=62617368002D6300736C65657020313B206563686F2074657374203E202F746D702F746D70636F6E7461696E65726964
type=CONTAINER_ID msg=audit(1519924845.499:257): contid=123458Quoted 8 lines
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-IDSigned-off-by Richard Guy Briggs <[email protected]>Acked-by Serge Hallyn <[email protected]>Acked-by Steve Grubb <[email protected]>Signed-off-by Richard Guy Briggs <[email protected]>Barring one minor nit below,
Reviewed-by Ondrej Mosnacek <[email protected]>Quoted 65 lines
--- include/linux/audit.h | 5 +++++ include/uapi/linux/audit.h | 1 + kernel/audit.c | 21 +++++++++++++++++++++ kernel/auditsc.c | 2 ++ 4 files changed, 29 insertions(+)include/linux/audit.h +5
-0@@ -199,6 +199,8 @@ static inline u64 audit_get_contid(struct task_struct *tsk) return tsk->audit->contid; } +extern void audit_log_contid (struct audit_context *context,u64 contid); +extern u32 audit_enabled;#else /* CONFIG_AUDIT */ static inline int audit_alloc (struct task_struct *task)@@ -265,6 +267,9 @@ static inline u64 audit_get_contid(struct task_struct *tsk) return AUDIT_CID_UNSET; } +static inline void audit_log_contid (struct audit_context *context,u64 contid) +{ } +#define audit_enabled AUDIT_OFF#endif /* CONFIG_AUDIT */ include/uapi/linux/audit.h +1
-0@@ -115,6 +115,7 @@#define AUDIT_REPLACE 1329/* Replace auditd if this packet unanswerd */ #define AUDIT_KERN_MODULE 1330/* Kernel Module events */ #define AUDIT_FANOTIFY 1331/* Fanotify access decision */ +#define AUDIT_CONTAINER_ID 1332/* Container ID */ #define AUDIT_AVC 1400/* SE Linux avc denial or grant */ #define AUDIT_SELINUX_ERR 1401/* Internal SE Linux Errors */ kernel/audit.c +15
-0@@ -2127,6 +2127,27 @@ void audit_log_session_info(struct audit_buffer *ab)audit_log_format (ab,"auid=%u ses=%u" , auid, sessionid); } +/* +* audit_log_contid - report container info +* @context: task or local context for record +* @contid: container ID to report +*/ +void audit_log_contid (struct audit_context *context,u64 contid) +{ +struct audit_buffer *ab; + +if (!audit_contid_valid (contid)) +return ; +/* Generate AUDIT_CONTAINER_ID record with container ID */ + ab =audit_log_start (context,GFP_KERNEL ,AUDIT_CONTAINER_ID ); +if (!ab) +return ;
Quoted 8 lines
kernel/audit.c void audit_log_session_info(struct audit_buffer *ab) · line 2145
Quoted 1 line
kernel/audit.c +1
-0+audit_log_format (ab,"contid=%llu" , contid);Just realized that you *might* get a compiler/static checker warning since u64 could technically be something else than unsigned long long on some arches... maybe this is not case in the kernel, but might be safer to cast it to unsigned long long before passing to
audit_log_format(). Possibly there are similar occurrences in previous (later) patches that I didn't (won't) notice.
Ok, since it is guaranteed to be at least 64 bits, a cast won't truncate it.
Quoted 16 lines
Quoted 16 lines
kernel/audit.c +5
-0+audit_log_end (ab); +return ; +} +EXPORT_SYMBOL (audit_log_contid); +void audit_log_key (struct audit_buffer *ab,char *key) {audit_log_format (ab," key=" );kernel/auditsc.c +0
-0@@ -1548,6 +1548,8 @@ static void audit_log_exit(void)audit_log_proctitle ();
Quoted 7 lines
kernel/auditsc.c static void audit_log_exit(void) · line 1555
Quoted 5 lines
kernel/auditsc.c +2
-0+audit_log_contid (context,audit_get_contid (current)); +/* Send end of event record to help user space know we are finished */ ab =audit_log_start (context,GFP_KERNEL ,AUDIT_EOE );if (ab)Ondrej Mosnacek <omosnace at redhat dot com>
- RGB
--
Richard Guy Briggs <[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
PATCH v5 5/10 audit: add containerid support for ptrace and signals
In reply to Richard Guy BriggsAdd audit container identifier support to ptrace and signals. In particular, the "ref" field provides a way to label the auxiliary record to which it is associated.
--- include/linux/audit.h | 1 + kernel/audit.c | 2 ++ kernel/audit.h | 2 ++ kernel/auditsc.c | 23 +++++++++++++++++------ 4 files changed, 22 insertions(+), 6 deletions(-)
include/linux/audit.h +1 -0
@@ -35,6 +35,7 @@ struct audit_sig_info {uid_t uid;pid_t pid;char ctx[0 ]; +u64 cid; };struct audit_buffer ;
kernel/audit.c +2 -0
@@ -138,6 +138,7 @@ struct audit_net {kuid_t audit_sig_uid =INVALID_UID ;pid_t audit_sig_pid =-1 ;u32 audit_sig_sid =0 ; +u64 audit_sig_cid =AUDIT_CID_UNSET ;/* Records can be lost in several ways: 0) [suppressed in audit_alloc]
@@ -1515,6 +1516,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)memcpy (sig_data->ctx, ctx, len);security_release_secctx (ctx, len); } + sig_data->cid = audit_sig_cid;audit_send_reply (skb, seq,AUDIT_SIGNAL_INFO ,0 ,0 , sig_data,sizeof (*sig_data) + len);kfree (sig_data);
kernel/audit.h +2 -0
@@ -148,6 +148,7 @@ struct audit_context {kuid_t target_uid;unsigned int target_sessionid;u32 target_sid; +u64 target_cid;char target_comm[TASK_COMM_LEN ];struct audit_tree_refs *trees, *first_trees;
@@ -344,6 +345,7 @@ extern void audit_filter_inodes(struct task_struct *tsk,extern pid_t audit_sig_pid;extern kuid_t audit_sig_uid;extern u32 audit_sig_sid; +extern u64 audit_sig_cid;extern int audit_filter (int msgtype,unsigned int listtype);
kernel/auditsc.c +17 -6
@@ -113,6 +113,7 @@ struct audit_aux_data_pids {kuid_t target_uid[AUDIT_AUX_PIDS ];unsigned int target_sessionid[AUDIT_AUX_PIDS ];u32 target_sid[AUDIT_AUX_PIDS ]; +u64 target_cid[AUDIT_AUX_PIDS ];char target_comm[AUDIT_AUX_PIDS ][TASK_COMM_LEN ];int pid_count; };
@@ -1514,7 +1515,7 @@ static void audit_log_exit(void)for (aux = context->aux_pids; aux; aux = aux->next) {struct audit_aux_data_pids *axs = (void *)aux; -for (i =0 ; i < axs->pid_count; i++) +for (i =0 ; i < axs->pid_count; i++) { if (audit_log_pid_context(context, axs->target_pid[i], axs->target_auid[i], axs->target_uid[i],
@@ -1522,14 +1523,20 @@ static void audit_log_exit(void) axs->target_sid[i], axs->target_comm[i])) call_panic =1 ; +audit_log_contid (context, axs->target_cid[i]); + } } -if (context->target_pid && -audit_log_pid_context (context, context->target_pid, - context->target_auid, context->target_uid, - context->target_sessionid, - context->target_sid, context->target_comm)) +if (context->target_pid) { +if (audit_log_pid_context (context, context->target_pid, + context->target_auid, + context->target_uid, + context->target_sessionid, + context->target_sid, + context->target_comm)) call_panic =1 ; +audit_log_contid (context, context->target_cid); + }if (context->pwd.dentry && context->pwd.mnt) { ab =audit_log_start (context,GFP_KERNEL ,AUDIT_CWD );
@@ -2360,6 +2367,7 @@ void __audit_ptrace(struct task_struct *t) context->target_uid =task_uid (t); context->target_sessionid =audit_get_sessionid (t);security_task_getsecid (t, &context->target_sid); + context->target_cid =audit_get_contid (t);memcpy (context->target_comm, t->comm,TASK_COMM_LEN ); }
@@ -2387,6 +2395,7 @@ int audit_signal_info(int sig, struct task_struct *t)else audit_sig_uid = uid;security_task_getsecid (current, &audit_sig_sid); + audit_sig_cid =audit_get_contid (current); }if (!audit_signals ||audit_dummy_context ())
@@ -2400,6 +2409,7 @@ int audit_signal_info(int sig, struct task_struct *t) ctx->target_uid = t_uid; ctx->target_sessionid =audit_get_sessionid (t);security_task_getsecid (t, &ctx->target_sid); + ctx->target_cid =audit_get_contid (t);memcpy (ctx->target_comm, t->comm,TASK_COMM_LEN );return 0 ; }
@@ -2421,6 +2431,7 @@ int audit_signal_info(int sig, struct task_struct *t) axp->target_uid[axp->pid_count] = t_uid; axp->target_sessionid[axp->pid_count] =audit_get_sessionid (t);security_task_getsecid (t, &axp->target_sid[axp->pid_count]); + axp->target_cid[axp->pid_count] =audit_get_contid (t);memcpy (axp->target_comm[axp->pid_count], t->comm,TASK_COMM_LEN ); axp->pid_count++;
Signature · 1 line
1.8.3.1
Re: [PATCH ghak90 V5 05/10] audit: add containerid support for ptrace and signals
Quoted 19 lines · Richard Guy Briggs
Add audit container identifier support to ptrace and signals. In particular, the "ref" field provides a way to label the auxiliary record to which it is associated.
Signed-off-by Richard Guy Briggs <[email protected]>Acked-by Serge Hallyn <[email protected]>Signed-off-by Richard Guy Briggs <[email protected]>--- include/linux/audit.h | 1 + kernel/audit.c | 2 ++ kernel/audit.h | 2 ++ kernel/auditsc.c | 23 +++++++++++++++++------ 4 files changed, 22 insertions(+), 6 deletions(-)include/linux/audit.h +0
-0
include/linux/audit.h struct audit_sig_info { · line 39
Quoted 5 lines
include/linux/audit.h +1
-0@@ -35,6 +35,7 @@ struct audit_sig_info {uid_t uid;pid_t pid;char ctx[0 ]; +u64 cid; };
Sorry, just noticed this. How does this work? Given that ctx[] is a variable length array, one assumes that the receiver of this message (userspace applications by the looks of it, presume that the ctx data occupies the skb from the byte following pid to the end of the transmitted buffer. How are they to know that the last byte is actually the cid value? Wouldn't it be better to move cid above ctx[0], so that the semantics of the variable length data are preserved?
Or am I missing something?
otherwise this looks ok to me.
Neil
Quoted 125 lines
include/linux/audit.h +0
-0struct audit_buffer ;kernel/audit.c +2
-0@@ -138,6 +138,7 @@ struct audit_net {kuid_t audit_sig_uid =INVALID_UID ;pid_t audit_sig_pid =-1 ;u32 audit_sig_sid =0 ; +u64 audit_sig_cid =AUDIT_CID_UNSET ;/* Records can be lost in several ways: 0) [suppressed in audit_alloc] @@ -1515,6 +1516,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)memcpy (sig_data->ctx, ctx, len);security_release_secctx (ctx, len); } + sig_data->cid = audit_sig_cid;audit_send_reply (skb, seq,AUDIT_SIGNAL_INFO ,0 ,0 , sig_data,sizeof (*sig_data) + len);kfree (sig_data);kernel/audit.h +2
-0@@ -148,6 +148,7 @@ struct audit_context {kuid_t target_uid;unsigned int target_sessionid;u32 target_sid; +u64 target_cid;char target_comm[TASK_COMM_LEN ];struct audit_tree_refs *trees, *first_trees;@@ -344,6 +345,7 @@ extern void audit_filter_inodes(struct task_struct *tsk,extern pid_t audit_sig_pid;extern kuid_t audit_sig_uid;extern u32 audit_sig_sid; +extern u64 audit_sig_cid;extern int audit_filter (int msgtype,unsigned int listtype);kernel/auditsc.c +17
-6@@ -113,6 +113,7 @@ struct audit_aux_data_pids {kuid_t target_uid[AUDIT_AUX_PIDS ];unsigned int target_sessionid[AUDIT_AUX_PIDS ];u32 target_sid[AUDIT_AUX_PIDS ]; +u64 target_cid[AUDIT_AUX_PIDS ];char target_comm[AUDIT_AUX_PIDS ][TASK_COMM_LEN ];int pid_count; };@@ -1514,7 +1515,7 @@ static void audit_log_exit(void)for (aux = context->aux_pids; aux; aux = aux->next) {struct audit_aux_data_pids *axs = (void *)aux; -for (i =0 ; i < axs->pid_count; i++) +for (i =0 ; i < axs->pid_count; i++) { if (audit_log_pid_context(context, axs->target_pid[i], axs->target_auid[i], axs->target_uid[i],@@ -1522,14 +1523,20 @@ static void audit_log_exit(void) axs->target_sid[i], axs->target_comm[i])) call_panic =1 ; +audit_log_contid (context, axs->target_cid[i]); + } } -if (context->target_pid && -audit_log_pid_context (context, context->target_pid, - context->target_auid, context->target_uid, - context->target_sessionid, - context->target_sid, context->target_comm)) +if (context->target_pid) { +if (audit_log_pid_context (context, context->target_pid, + context->target_auid, + context->target_uid, + context->target_sessionid, + context->target_sid, + context->target_comm)) call_panic =1 ; +audit_log_contid (context, context->target_cid); + }if (context->pwd.dentry && context->pwd.mnt) { ab =audit_log_start (context,GFP_KERNEL ,AUDIT_CWD );@@ -2360,6 +2367,7 @@ void __audit_ptrace(struct task_struct *t) context->target_uid =task_uid (t); context->target_sessionid =audit_get_sessionid (t);security_task_getsecid (t, &context->target_sid); + context->target_cid =audit_get_contid (t);memcpy (context->target_comm, t->comm,TASK_COMM_LEN ); }@@ -2387,6 +2395,7 @@ int audit_signal_info(int sig, struct task_struct *t)else audit_sig_uid = uid;security_task_getsecid (current, &audit_sig_sid); + audit_sig_cid =audit_get_contid (current); }if (!audit_signals ||audit_dummy_context ())@@ -2400,6 +2409,7 @@ int audit_signal_info(int sig, struct task_struct *t) ctx->target_uid = t_uid; ctx->target_sessionid =audit_get_sessionid (t);security_task_getsecid (t, &ctx->target_sid); + ctx->target_cid =audit_get_contid (t);memcpy (ctx->target_comm, t->comm,TASK_COMM_LEN );return 0 ; }@@ -2421,6 +2431,7 @@ int audit_signal_info(int sig, struct task_struct *t) axp->target_uid[axp->pid_count] = t_uid; axp->target_sessionid[axp->pid_count] =audit_get_sessionid (t);security_task_getsecid (t, &axp->target_sid[axp->pid_count]); + axp->target_cid[axp->pid_count] =audit_get_contid (t);memcpy (axp->target_comm[axp->pid_count], t->comm,TASK_COMM_LEN ); axp->pid_count++;Signature · 1 line
1.8.3.1
Re: [PATCH ghak90 V5 05/10] audit: add containerid support for ptrace and signals
Quoted 33 lines · Neil Horman
Quoted 19 lines · Richard Guy Briggs
Add audit container identifier support to ptrace and signals. In particular, the "ref" field provides a way to label the auxiliary record to which it is associated.
Signed-off-by Richard Guy Briggs <[email protected]>Acked-by Serge Hallyn <[email protected]>Signed-off-by Richard Guy Briggs <[email protected]>--- include/linux/audit.h | 1 + kernel/audit.c | 2 ++ kernel/audit.h | 2 ++ kernel/auditsc.c | 23 +++++++++++++++++------ 4 files changed, 22 insertions(+), 6 deletions(-)include/linux/audit.h +0
-0include/linux/audit.h struct audit_sig_info { · line 39
Quoted 5 lines
include/linux/audit.h +1
-0@@ -35,6 +35,7 @@ struct audit_sig_info {uid_t uid;pid_t pid;char ctx[0 ]; +u64 cid; };Sorry, just noticed this. How does this work? Given that ctx[] is a variable length array, one assumes that the receiver of this message (userspace applications by the looks of it, presume that the ctx data occupies the skb from the byte following pid to the end of the transmitted buffer. How are they to know that the last byte is actually the cid value? Wouldn't it be better to move cid above ctx[0], so that the semantics of the variable length data are preserved?
Quoted 1 line
Or am I missing something?
Nope you're not missing anything, but I am! That's a bug. Thanks for spotting that!
Quoted 124 lines
otherwise this looks ok to me.
NeilQuoted 121 lines
include/linux/audit.h +0
-0struct audit_buffer ;kernel/audit.c +2
-0@@ -138,6 +138,7 @@ struct audit_net {kuid_t audit_sig_uid =INVALID_UID ;pid_t audit_sig_pid =-1 ;u32 audit_sig_sid =0 ; +u64 audit_sig_cid =AUDIT_CID_UNSET ;/* Records can be lost in several ways: 0) [suppressed in audit_alloc] @@ -1515,6 +1516,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)memcpy (sig_data->ctx, ctx, len);security_release_secctx (ctx, len); } + sig_data->cid = audit_sig_cid;audit_send_reply (skb, seq,AUDIT_SIGNAL_INFO ,0 ,0 , sig_data,sizeof (*sig_data) + len);kfree (sig_data);kernel/audit.h +2
-0@@ -148,6 +148,7 @@ struct audit_context {kuid_t target_uid;unsigned int target_sessionid;u32 target_sid; +u64 target_cid;char target_comm[TASK_COMM_LEN ];struct audit_tree_refs *trees, *first_trees;@@ -344,6 +345,7 @@ extern void audit_filter_inodes(struct task_struct *tsk,extern pid_t audit_sig_pid;extern kuid_t audit_sig_uid;extern u32 audit_sig_sid; +extern u64 audit_sig_cid;extern int audit_filter (int msgtype,unsigned int listtype);kernel/auditsc.c +17
-6@@ -113,6 +113,7 @@ struct audit_aux_data_pids {kuid_t target_uid[AUDIT_AUX_PIDS ];unsigned int target_sessionid[AUDIT_AUX_PIDS ];u32 target_sid[AUDIT_AUX_PIDS ]; +u64 target_cid[AUDIT_AUX_PIDS ];char target_comm[AUDIT_AUX_PIDS ][TASK_COMM_LEN ];int pid_count; };@@ -1514,7 +1515,7 @@ static void audit_log_exit(void)for (aux = context->aux_pids; aux; aux = aux->next) {struct audit_aux_data_pids *axs = (void *)aux; -for (i =0 ; i < axs->pid_count; i++) +for (i =0 ; i < axs->pid_count; i++) { if (audit_log_pid_context(context, axs->target_pid[i], axs->target_auid[i], axs->target_uid[i],@@ -1522,14 +1523,20 @@ static void audit_log_exit(void) axs->target_sid[i], axs->target_comm[i])) call_panic =1 ; +audit_log_contid (context, axs->target_cid[i]); + } } -if (context->target_pid && -audit_log_pid_context (context, context->target_pid, - context->target_auid, context->target_uid, - context->target_sessionid, - context->target_sid, context->target_comm)) +if (context->target_pid) { +if (audit_log_pid_context (context, context->target_pid, + context->target_auid, + context->target_uid, + context->target_sessionid, + context->target_sid, + context->target_comm)) call_panic =1 ; +audit_log_contid (context, context->target_cid); + }if (context->pwd.dentry && context->pwd.mnt) { ab =audit_log_start (context,GFP_KERNEL ,AUDIT_CWD );@@ -2360,6 +2367,7 @@ void __audit_ptrace(struct task_struct *t) context->target_uid =task_uid (t); context->target_sessionid =audit_get_sessionid (t);security_task_getsecid (t, &context->target_sid); + context->target_cid =audit_get_contid (t);memcpy (context->target_comm, t->comm,TASK_COMM_LEN ); }@@ -2387,6 +2395,7 @@ int audit_signal_info(int sig, struct task_struct *t)else audit_sig_uid = uid;security_task_getsecid (current, &audit_sig_sid); + audit_sig_cid =audit_get_contid (current); }if (!audit_signals ||audit_dummy_context ())@@ -2400,6 +2409,7 @@ int audit_signal_info(int sig, struct task_struct *t) ctx->target_uid = t_uid; ctx->target_sessionid =audit_get_sessionid (t);security_task_getsecid (t, &ctx->target_sid); + ctx->target_cid =audit_get_contid (t);memcpy (ctx->target_comm, t->comm,TASK_COMM_LEN );return 0 ; }@@ -2421,6 +2431,7 @@ int audit_signal_info(int sig, struct task_struct *t) axp->target_uid[axp->pid_count] = t_uid; axp->target_sessionid[axp->pid_count] =audit_get_sessionid (t);security_task_getsecid (t, &axp->target_sid[axp->pid_count]); + axp->target_cid[axp->pid_count] =audit_get_contid (t);memcpy (axp->target_comm[axp->pid_count], t->comm,TASK_COMM_LEN ); axp->pid_count++;
Quoted 4 lines
Quoted 4 lines
Signature · 1 line
1.8.3.1
- RGB
Re: [PATCH ghak90 V5 05/10] audit: add containerid support for ptrace and signals
In reply to Richard Guy BriggsQuoted 19 lines · Richard Guy Briggs
Add audit container identifier support to ptrace and signals. In particular, the "ref" field provides a way to label the auxiliary record to which it is associated.
Signed-off-by Richard Guy Briggs <[email protected]>Acked-by Serge Hallyn <[email protected]>Signed-off-by Richard Guy Briggs <[email protected]>--- include/linux/audit.h | 1 + kernel/audit.c | 2 ++ kernel/audit.h | 2 ++ kernel/auditsc.c | 23 +++++++++++++++++------ 4 files changed, 22 insertions(+), 6 deletions(-)include/linux/audit.h +0
-0
include/linux/audit.h struct audit_sig_info { · line 39
Quoted 5 lines
include/linux/audit.h +1
-0@@ -35,6 +35,7 @@ struct audit_sig_info {uid_t uid;pid_t pid;char ctx[0 ]; +u64 cid; };
It seems like this structure implicitly defines the format of some message that is sent to userspace... If so, how will userspace detect that a new format (including the cid) is being used? Even assuming the fixed order as pointed out by Neil, the message still seems to be variable-sized so userspace cannot even use the length to infer that. Am I missing something here? (I hope I am :)
Quoted 124 lines
include/linux/audit.h +0
-0struct audit_buffer ;kernel/audit.c +2
-0@@ -138,6 +138,7 @@ struct audit_net {kuid_t audit_sig_uid =INVALID_UID ;pid_t audit_sig_pid =-1 ;u32 audit_sig_sid =0 ; +u64 audit_sig_cid =AUDIT_CID_UNSET ;/* Records can be lost in several ways: 0) [suppressed in audit_alloc] @@ -1515,6 +1516,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)memcpy (sig_data->ctx, ctx, len);security_release_secctx (ctx, len); } + sig_data->cid = audit_sig_cid;audit_send_reply (skb, seq,AUDIT_SIGNAL_INFO ,0 ,0 , sig_data,sizeof (*sig_data) + len);kfree (sig_data);kernel/audit.h +2
-0@@ -148,6 +148,7 @@ struct audit_context {kuid_t target_uid;unsigned int target_sessionid;u32 target_sid; +u64 target_cid;char target_comm[TASK_COMM_LEN ];struct audit_tree_refs *trees, *first_trees;@@ -344,6 +345,7 @@ extern void audit_filter_inodes(struct task_struct *tsk,extern pid_t audit_sig_pid;extern kuid_t audit_sig_uid;extern u32 audit_sig_sid; +extern u64 audit_sig_cid;extern int audit_filter (int msgtype,unsigned int listtype);kernel/auditsc.c +17
-7@@ -113,6 +113,7 @@ struct audit_aux_data_pids {kuid_t target_uid[AUDIT_AUX_PIDS ];unsigned int target_sessionid[AUDIT_AUX_PIDS ];u32 target_sid[AUDIT_AUX_PIDS ]; +u64 target_cid[AUDIT_AUX_PIDS ];char target_comm[AUDIT_AUX_PIDS ][TASK_COMM_LEN ];int pid_count; };@@ -1514,7 +1515,7 @@ static void audit_log_exit(void)for (aux = context->aux_pids; aux; aux = aux->next) {struct audit_aux_data_pids *axs = (void *)aux; -for (i =0 ; i < axs->pid_count; i++) +for (i =0 ; i < axs->pid_count; i++) { if (audit_log_pid_context(context, axs->target_pid[i], axs->target_auid[i], axs->target_uid[i],@@ -1522,14 +1523,20 @@ static void audit_log_exit(void) axs->target_sid[i], axs->target_comm[i])) call_panic =1 ; +audit_log_contid (context, axs->target_cid[i]); + } } -if (context->target_pid && -audit_log_pid_context (context, context->target_pid, - context->target_auid, context->target_uid, - context->target_sessionid, - context->target_sid, context->target_comm)) +if (context->target_pid) { +if (audit_log_pid_context (context, context->target_pid, + context->target_auid, + context->target_uid, + context->target_sessionid, + context->target_sid, + context->target_comm)) call_panic =1 ; +audit_log_contid (context, context->target_cid); + }if (context->pwd.dentry && context->pwd.mnt) { ab =audit_log_start (context,GFP_KERNEL ,AUDIT_CWD );@@ -2360,6 +2367,7 @@ void __audit_ptrace(struct task_struct *t) context->target_uid =task_uid (t); context->target_sessionid =audit_get_sessionid (t);security_task_getsecid (t, &context->target_sid); + context->target_cid =audit_get_contid (t);memcpy (context->target_comm, t->comm,TASK_COMM_LEN ); }@@ -2387,6 +2395,7 @@ int audit_signal_info(int sig, struct task_struct *t)else audit_sig_uid = uid;security_task_getsecid (current, &audit_sig_sid); + audit_sig_cid =audit_get_contid (current); }if (!audit_signals ||audit_dummy_context ())@@ -2400,6 +2409,7 @@ int audit_signal_info(int sig, struct task_struct *t) ctx->target_uid = t_uid; ctx->target_sessionid =audit_get_sessionid (t);security_task_getsecid (t, &ctx->target_sid); + ctx->target_cid =audit_get_contid (t);memcpy (ctx->target_comm, t->comm,TASK_COMM_LEN );return 0 ; }@@ -2421,6 +2431,7 @@ int audit_signal_info(int sig, struct task_struct *t) axp->target_uid[axp->pid_count] = t_uid; axp->target_sessionid[axp->pid_count] =audit_get_sessionid (t);security_task_getsecid (t, &axp->target_sid[axp->pid_count]); + axp->target_cid[axp->pid_count] =audit_get_contid (t);memcpy (axp->target_comm[axp->pid_count], t->comm,TASK_COMM_LEN ); axp->pid_count++; --1.8.3.1
Signature · 3 lines
Ondrej Mosnacek <omosnace at redhat dot com> Software Engineer, Security Technologies Red Hat, Inc.
Re: [PATCH ghak90 V5 05/10] audit: add containerid support for ptrace and signals
Quoted 24 lines · Ondrej Mosnacek
Quoted 23 lines · Richard Guy Briggs
Add audit container identifier support to ptrace and signals. In particular, the "ref" field provides a way to label the auxiliary record to which it is associated.
Signed-off-by Richard Guy Briggs <[email protected]>Acked-by Serge Hallyn <[email protected]>Signed-off-by Richard Guy Briggs <[email protected]>--- include/linux/audit.h | 1 + kernel/audit.c | 2 ++ kernel/audit.h | 2 ++ kernel/auditsc.c | 23 +++++++++++++++++------ 4 files changed, 22 insertions(+), 6 deletions(-)include/linux/audit.h +1
-0@@ -35,6 +35,7 @@ struct audit_sig_info {uid_t uid;pid_t pid;char ctx[0 ]; +u64 cid;
Quoted 8 lines
include/linux/audit.h struct audit_sig_info { · line 39
Quoted 1 line
include/linux/audit.h +0
-0};It seems like this structure implicitly defines the format of some message that is sent to userspace... If so, how will userspace detect that a new format (including the cid) is being used? Even assuming the fixed order as pointed out by Neil, the message still seems to be variable-sized so userspace cannot even use the length to infer that. Am I missing something here? (I hope I am :)
How humble of you again. No, you're not missing something. This ends up being an api change... That can be fixed in userspace by checking for AUDIT_FEATURE_BITMAP_CONTAINERID, but how do we make a newer kernel not break an older userspace... I think this was the original rationale for adding it after the ctx but totally missing the fact that the latter is a variable-length field.
This patch really should be split into audit_sig_cid changes in a patch by itself and target_cid changes which could go with the second and fourth patches.
Quoted 120 lines
Quoted 120 lines
include/linux/audit.h +0
-0struct audit_buffer ;kernel/audit.c +2
-0@@ -138,6 +138,7 @@ struct audit_net {kuid_t audit_sig_uid =INVALID_UID ;pid_t audit_sig_pid =-1 ;u32 audit_sig_sid =0 ; +u64 audit_sig_cid =AUDIT_CID_UNSET ;/* Records can be lost in several ways: 0) [suppressed in audit_alloc] @@ -1515,6 +1516,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)memcpy (sig_data->ctx, ctx, len);security_release_secctx (ctx, len); } + sig_data->cid = audit_sig_cid;audit_send_reply (skb, seq,AUDIT_SIGNAL_INFO ,0 ,0 , sig_data,sizeof (*sig_data) + len);kfree (sig_data);kernel/audit.h +2
-0@@ -148,6 +148,7 @@ struct audit_context {kuid_t target_uid;unsigned int target_sessionid;u32 target_sid; +u64 target_cid;char target_comm[TASK_COMM_LEN ];struct audit_tree_refs *trees, *first_trees;@@ -344,6 +345,7 @@ extern void audit_filter_inodes(struct task_struct *tsk,extern pid_t audit_sig_pid;extern kuid_t audit_sig_uid;extern u32 audit_sig_sid; +extern u64 audit_sig_cid;extern int audit_filter (int msgtype,unsigned int listtype);kernel/auditsc.c +17
-6@@ -113,6 +113,7 @@ struct audit_aux_data_pids {kuid_t target_uid[AUDIT_AUX_PIDS ];unsigned int target_sessionid[AUDIT_AUX_PIDS ];u32 target_sid[AUDIT_AUX_PIDS ]; +u64 target_cid[AUDIT_AUX_PIDS ];char target_comm[AUDIT_AUX_PIDS ][TASK_COMM_LEN ];int pid_count; };@@ -1514,7 +1515,7 @@ static void audit_log_exit(void)for (aux = context->aux_pids; aux; aux = aux->next) {struct audit_aux_data_pids *axs = (void *)aux; -for (i =0 ; i < axs->pid_count; i++) +for (i =0 ; i < axs->pid_count; i++) { if (audit_log_pid_context(context, axs->target_pid[i], axs->target_auid[i], axs->target_uid[i],@@ -1522,14 +1523,20 @@ static void audit_log_exit(void) axs->target_sid[i], axs->target_comm[i])) call_panic =1 ; +audit_log_contid (context, axs->target_cid[i]); + } } -if (context->target_pid && -audit_log_pid_context (context, context->target_pid, - context->target_auid, context->target_uid, - context->target_sessionid, - context->target_sid, context->target_comm)) +if (context->target_pid) { +if (audit_log_pid_context (context, context->target_pid, + context->target_auid, + context->target_uid, + context->target_sessionid, + context->target_sid, + context->target_comm)) call_panic =1 ; +audit_log_contid (context, context->target_cid); + }if (context->pwd.dentry && context->pwd.mnt) { ab =audit_log_start (context,GFP_KERNEL ,AUDIT_CWD );@@ -2360,6 +2367,7 @@ void __audit_ptrace(struct task_struct *t) context->target_uid =task_uid (t); context->target_sessionid =audit_get_sessionid (t);security_task_getsecid (t, &context->target_sid); + context->target_cid =audit_get_contid (t);memcpy (context->target_comm, t->comm,TASK_COMM_LEN ); }@@ -2387,6 +2395,7 @@ int audit_signal_info(int sig, struct task_struct *t)else audit_sig_uid = uid;security_task_getsecid (current, &audit_sig_sid); + audit_sig_cid =audit_get_contid (current); }if (!audit_signals ||audit_dummy_context ())@@ -2400,6 +2409,7 @@ int audit_signal_info(int sig, struct task_struct *t) ctx->target_uid = t_uid; ctx->target_sessionid =audit_get_sessionid (t);security_task_getsecid (t, &ctx->target_sid); + ctx->target_cid =audit_get_contid (t);memcpy (ctx->target_comm, t->comm,TASK_COMM_LEN );return 0 ; }@@ -2421,6 +2431,7 @@ int audit_signal_info(int sig, struct task_struct *t) axp->target_uid[axp->pid_count] = t_uid; axp->target_sessionid[axp->pid_count] =audit_get_sessionid (t);security_task_getsecid (t, &axp->target_sid[axp->pid_count]); + axp->target_cid[axp->pid_count] =audit_get_contid (t);memcpy (axp->target_comm[axp->pid_count], t->comm,TASK_COMM_LEN ); axp->pid_count++;
Quoted 9 lines
Quoted 3 lines
--
1.8.3.1Signature · 3 lines
Ondrej Mosnacek <omosnace at redhat dot com> Software Engineer, Security Technologies Red Hat, Inc.
- 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
Re: [PATCH ghak90 V5 05/10] audit: add containerid support for ptrace and signals
Quoted 34 lines · Richard Guy Briggs
Quoted 24 lines · Ondrej Mosnacek
Quoted 23 lines · Richard Guy Briggs
Add audit container identifier support to ptrace and signals. In particular, the "ref" field provides a way to label the auxiliary record to which it is associated.
Signed-off-by Richard Guy Briggs <[email protected]>Acked-by Serge Hallyn <[email protected]>Signed-off-by Richard Guy Briggs <[email protected]>--- include/linux/audit.h | 1 + kernel/audit.c | 2 ++ kernel/audit.h | 2 ++ kernel/auditsc.c | 23 +++++++++++++++++------ 4 files changed, 22 insertions(+), 6 deletions(-)include/linux/audit.h +1
-0@@ -35,6 +35,7 @@ struct audit_sig_info {uid_t uid;pid_t pid;char ctx[0 ]; +u64 cid;Quoted 8 lines
include/linux/audit.h struct audit_sig_info { · line 39
Quoted 1 line
include/linux/audit.h +0
-0};It seems like this structure implicitly defines the format of some message that is sent to userspace... If so, how will userspace detect that a new format (including the cid) is being used? Even assuming the fixed order as pointed out by Neil, the message still seems to be variable-sized so userspace cannot even use the length to infer that. Am I missing something here? (I hope I am :)
Quoted 6 lines
How humble of you again. No, you're not missing something. This ends up being an api change... That can be fixed in userspace by checking for
AUDIT_FEATURE_BITMAP_CONTAINERID, but how do we make a newer kernel not break an older userspace... I think this was the original rationale for adding it after the ctx but totally missing the fact that the latter is a variable-length field.
The way to address this on Steve Grubb's advice is to create a new message type that incorporates a new struct with the structure above, leaving the old one with the old message type deprecated. I've coded this up along with userspace support.
Quoted 3 lines
This patch really should be split into
audit_sig_cidchanges in a patch by itself andtarget_cidchanges which could go with the second and fourth patches.
I've also done this which Paul had already asked for, not quite in this form.
I believe this addresses all the outstanding issues.
Quoted 123 lines
Quoted 114 lines
Quoted 114 lines
include/linux/audit.h +0
-0struct audit_buffer ;kernel/audit.c +2
-0@@ -138,6 +138,7 @@ struct audit_net {kuid_t audit_sig_uid =INVALID_UID ;pid_t audit_sig_pid =-1 ;u32 audit_sig_sid =0 ; +u64 audit_sig_cid =AUDIT_CID_UNSET ;/* Records can be lost in several ways: 0) [suppressed in audit_alloc] @@ -1515,6 +1516,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)memcpy (sig_data->ctx, ctx, len);security_release_secctx (ctx, len); } + sig_data->cid = audit_sig_cid;audit_send_reply (skb, seq,AUDIT_SIGNAL_INFO ,0 ,0 , sig_data,sizeof (*sig_data) + len);kfree (sig_data);kernel/audit.h +2
-0@@ -148,6 +148,7 @@ struct audit_context {kuid_t target_uid;unsigned int target_sessionid;u32 target_sid; +u64 target_cid;char target_comm[TASK_COMM_LEN ];struct audit_tree_refs *trees, *first_trees;@@ -344,6 +345,7 @@ extern void audit_filter_inodes(struct task_struct *tsk,extern pid_t audit_sig_pid;extern kuid_t audit_sig_uid;extern u32 audit_sig_sid; +extern u64 audit_sig_cid;extern int audit_filter (int msgtype,unsigned int listtype);kernel/auditsc.c +16
-6@@ -113,6 +113,7 @@ struct audit_aux_data_pids {kuid_t target_uid[AUDIT_AUX_PIDS ];unsigned int target_sessionid[AUDIT_AUX_PIDS ];u32 target_sid[AUDIT_AUX_PIDS ]; +u64 target_cid[AUDIT_AUX_PIDS ];char target_comm[AUDIT_AUX_PIDS ][TASK_COMM_LEN ];int pid_count; };@@ -1514,7 +1515,7 @@ static void audit_log_exit(void)for (aux = context->aux_pids; aux; aux = aux->next) {struct audit_aux_data_pids *axs = (void *)aux; -for (i =0 ; i < axs->pid_count; i++) +for (i =0 ; i < axs->pid_count; i++) { if (audit_log_pid_context(context, axs->target_pid[i], axs->target_auid[i], axs->target_uid[i],@@ -1522,14 +1523,20 @@ static void audit_log_exit(void) axs->target_sid[i], axs->target_comm[i])) call_panic =1 ; +audit_log_contid (context, axs->target_cid[i]); + } } -if (context->target_pid && -audit_log_pid_context (context, context->target_pid, - context->target_auid, context->target_uid, - context->target_sessionid, - context->target_sid, context->target_comm)) +if (context->target_pid) { +if (audit_log_pid_context (context, context->target_pid, + context->target_auid, + context->target_uid, + context->target_sessionid, + context->target_sid, + context->target_comm)) call_panic =1 ; +audit_log_contid (context, context->target_cid); + }if (context->pwd.dentry && context->pwd.mnt) { ab =audit_log_start (context,GFP_KERNEL ,AUDIT_CWD );@@ -2360,6 +2367,7 @@ void __audit_ptrace(struct task_struct *t) context->target_uid =task_uid (t); context->target_sessionid =audit_get_sessionid (t);security_task_getsecid (t, &context->target_sid); + context->target_cid =audit_get_contid (t);memcpy (context->target_comm, t->comm,TASK_COMM_LEN ); }@@ -2387,6 +2395,7 @@ int audit_signal_info(int sig, struct task_struct *t)else audit_sig_uid = uid;security_task_getsecid (current, &audit_sig_sid); + audit_sig_cid =audit_get_contid (current); }if (!audit_signals ||audit_dummy_context ())@@ -2400,6 +2409,7 @@ int audit_signal_info(int sig, struct task_struct *t) ctx->target_uid = t_uid; ctx->target_sessionid =audit_get_sessionid (t);security_task_getsecid (t, &ctx->target_sid); + ctx->target_cid =audit_get_contid (t);memcpy (ctx->target_comm, t->comm,TASK_COMM_LEN );return 0 ; }@@ -2421,6 +2431,7 @@ int audit_signal_info(int sig, struct task_struct *t) axp->target_uid[axp->pid_count] = t_uid;Quoted 8 lines
kernel/auditsc.c int audit_signal_info(int sig, struct task_struct *t) · line 2437
Quoted 6 lines
kernel/auditsc.c +1
-0axp->target_sessionid[axp->pid_count] =audit_get_sessionid (t);security_task_getsecid (t, &axp->target_sid[axp->pid_count]); + axp->target_cid[axp->pid_count] =audit_get_contid (t);memcpy (axp->target_comm[axp->pid_count], t->comm,TASK_COMM_LEN ); axp->pid_count++;Ondrej Mosnacek <omosnace at redhat dot com>
Quoted 1 line
- RGB
- 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
PATCH v5 6/10 audit: add support for non-syscall auxiliary records
In reply to Richard Guy BriggsStandalone 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.
--- include/linux/audit.h | 8 ++++++++ kernel/audit.h | 1 + kernel/auditsc.c | 35 ++++++++++++++++++++++++++++++----- 3 files changed, 39 insertions(+), 5 deletions(-)
include/linux/audit.h +8 -0
@@ -285,6 +285,8 @@ static inline void audit_log_contid(struct audit_context *context, u64 contid)/* These are defined in auditsc.c */ /* Public API */ +extern struct audit_context *audit_alloc_local (gfp_t gfpflags); +extern void audit_free_context (struct audit_context *context);extern void __audit_syscall_entry (int major,unsigned long a0,unsigned long a1,unsigned long a2,unsigned long a3);extern void __audit_syscall_exit (int ret_success,long ret_value);
@@ -512,6 +514,12 @@ static inline void audit_fanotify(unsigned int response)extern int audit_n_rules;extern int audit_signals;#else /* CONFIG_AUDITSYSCALL */ +static inline struct audit_context *audit_alloc_local (gfp_t gfpflags) +{ +return NULL ; +} +static inline void audit_free_context (struct audit_context *context) +{ }static inline void audit_syscall_entry (int major,unsigned long a0,unsigned long a1,unsigned long a2,unsigned long a3)
kernel/audit.h +1 -0
@@ -111,6 +111,7 @@ struct audit_proctitle {struct audit_context {int dummy;/* must be the first element */ int in_syscall;/* 1 if task is in a syscall */ +bool local;/* local context needed */ enum audit_state state, current_state;unsigned int serial;/* serial number for record */ int major;/* syscall number */
kernel/auditsc.c +30 -5
@@ -872,11 +872,13 @@ static inline void audit_free_aux(struct audit_context *context) } } -static inline struct audit_context *audit_alloc_context (enum audit_state state) +static inline struct audit_context *audit_alloc_context (enum audit_state state, +gfp_t gfpflags) {struct audit_context *context; - context =kzalloc (sizeof (*context),GFP_KERNEL ); +/* We can be called in atomic context via audit_tg() */ + context =kzalloc (sizeof (*context), gfpflags);if (!context)return NULL ; context->state = state;
@@ -912,7 +914,8 @@ int audit_alloc_syscall(struct task_struct *tsk)return 0 ; } -if (!(context =audit_alloc_context (state))) { + context =audit_alloc_context (state,GFP_KERNEL ); +if (!context) {kfree (key);audit_log_lost ("out of memory in audit_alloc_syscall" );return -ENOMEM ;
@@ -924,8 +927,29 @@ int audit_alloc_syscall(struct task_struct *tsk)return 0 ; } -static inline void audit_free_context (struct audit_context *context) +struct audit_context *audit_alloc_local (gfp_t gfpflags) { +struct audit_context *context =NULL ; + +if (!audit_ever_enabled) + goto out;/* Return if not auditing. */ + context =audit_alloc_context (AUDIT_RECORD_CONTEXT , gfpflags); +if (!context) { +audit_log_lost ("out of memory in audit_alloc_local" ); + goto out; + } + context->serial =audit_serial (); +ktime_get_coarse_real_ts64 (&context->ctime); + context->local = true; +out: +return context; +} +EXPORT_SYMBOL (audit_alloc_local); + +void audit_free_context (struct audit_context *context) +{ +if (!context) +return ;audit_free_names (context);unroll_tree_refs (context,NULL ,0 );free_tree_refs (context);
@@ -935,6 +959,7 @@ static inline void audit_free_context(struct audit_context *context)audit_proctitle_free (context);kfree (context); } +EXPORT_SYMBOL (audit_free_context); static int audit_log_pid_context(struct audit_context *context, pid_t pid, kuid_t auid, kuid_t uid, unsigned int sessionid,
@@ -2163,7 +2188,7 @@ void __audit_inode_child(struct inode *parent,int auditsc_get_stamp (struct audit_context *ctx,struct timespec64 *t,unsigned int *serial) { -if (!ctx->in_syscall) +if (!ctx->in_syscall && !ctx->local)return 0 ;if (!ctx->serial) ctx->serial =audit_serial ();
Signature · 1 line
1.8.3.1
Re: [PATCH ghak90 V5 06/10] audit: add support for non-syscall auxiliary records
Quoted 135 lines · Richard Guy Briggs
Standalone audit records have the timestamp and serial number generated on the fly and as such are unique, making them standalone. This new function
audit_alloc_local()generates a local audit context that will be used only for a standalone record and its auxiliary record(s). The context is discarded immediately after the local associated records are produced.Signed-off-by Richard Guy Briggs <[email protected]>Acked-by Serge Hallyn <[email protected]>--- include/linux/audit.h | 8 ++++++++ kernel/audit.h | 1 + kernel/auditsc.c | 35 ++++++++++++++++++++++++++++++----- 3 files changed, 39 insertions(+), 5 deletions(-)include/linux/audit.h +8
-0@@ -285,6 +285,8 @@ static inline void audit_log_contid(struct audit_context *context, u64 contid)/* These are defined in auditsc.c */ /* Public API */ +extern struct audit_context *audit_alloc_local (gfp_t gfpflags); +extern void audit_free_context (struct audit_context *context);extern void __audit_syscall_entry (int major,unsigned long a0,unsigned long a1,unsigned long a2,unsigned long a3);extern void __audit_syscall_exit (int ret_success,long ret_value);@@ -512,6 +514,12 @@ static inline void audit_fanotify(unsigned int response)extern int audit_n_rules;extern int audit_signals;#else /* CONFIG_AUDITSYSCALL */ +static inline struct audit_context *audit_alloc_local (gfp_t gfpflags) +{ +return NULL ; +} +static inline void audit_free_context (struct audit_context *context) +{ }static inline void audit_syscall_entry (int major,unsigned long a0,unsigned long a1,unsigned long a2,unsigned long a3)kernel/audit.h +1
-0@@ -111,6 +111,7 @@ struct audit_proctitle {struct audit_context {int dummy;/* must be the first element */ int in_syscall;/* 1 if task is in a syscall */ +bool local;/* local context needed */ enum audit_state state, current_state;unsigned int serial;/* serial number for record */ int major;/* syscall number */ kernel/auditsc.c +30
-5@@ -872,11 +872,13 @@ static inline void audit_free_aux(struct audit_context *context) } } -static inline struct audit_context *audit_alloc_context (enum audit_state state) +static inline struct audit_context *audit_alloc_context (enum audit_state state, +gfp_t gfpflags) {struct audit_context *context; - context =kzalloc (sizeof (*context),GFP_KERNEL ); +/* We can be called in atomic context via audit_tg() */ + context =kzalloc (sizeof (*context), gfpflags);if (!context)return NULL ; context->state = state;@@ -912,7 +914,8 @@ int audit_alloc_syscall(struct task_struct *tsk)return 0 ; } -if (!(context =audit_alloc_context (state))) { + context =audit_alloc_context (state,GFP_KERNEL ); +if (!context) {kfree (key);audit_log_lost ("out of memory in audit_alloc_syscall" );return -ENOMEM ;@@ -924,8 +927,29 @@ int audit_alloc_syscall(struct task_struct *tsk)return 0 ; } -static inline void audit_free_context (struct audit_context *context) +struct audit_context *audit_alloc_local (gfp_t gfpflags) { +struct audit_context *context =NULL ; + +if (!audit_ever_enabled) + goto out;/* Return if not auditing. */ + context =audit_alloc_context (AUDIT_RECORD_CONTEXT , gfpflags); +if (!context) { +audit_log_lost ("out of memory in audit_alloc_local" ); + goto out; + } + context->serial =audit_serial (); +ktime_get_coarse_real_ts64 (&context->ctime); + context->local = true; +out: +return context; +} +EXPORT_SYMBOL (audit_alloc_local); + +void audit_free_context (struct audit_context *context) +{ +if (!context) +return ;audit_free_names (context);unroll_tree_refs (context,NULL ,0 );free_tree_refs (context);@@ -935,6 +959,7 @@ static inline void audit_free_context(struct audit_context *context)audit_proctitle_free (context);kfree (context); } +EXPORT_SYMBOL (audit_free_context); static int audit_log_pid_context(struct audit_context *context, pid_t pid, kuid_t auid, kuid_t uid, unsigned int sessionid,@@ -2163,7 +2188,7 @@ void __audit_inode_child(struct inode *parent,int auditsc_get_stamp (struct audit_context *ctx,struct timespec64 *t,unsigned int *serial) { -if (!ctx->in_syscall) +if (!ctx->in_syscall && !ctx->local)return 0 ;if (!ctx->serial) ctx->serial =audit_serial ();Signature · 1 line
1.8.3.1
Re: [PATCH ghak90 V5 06/10] audit: add support for non-syscall auxiliary records
In reply to Richard Guy BriggsQuoted 9 lines · Richard Guy Briggs
Standalone audit records have the timestamp and serial number generated on the fly and as such are unique, making them standalone. This new function
audit_alloc_local()generates a local audit context that will be used only for a standalone record and its auxiliary record(s). The context is discarded immediately after the local associated records are produced.Signed-off-by Richard Guy Briggs <[email protected]>Acked-by Serge Hallyn <[email protected]>
Quoted 125 lines
--- include/linux/audit.h | 8 ++++++++ kernel/audit.h | 1 + kernel/auditsc.c | 35 ++++++++++++++++++++++++++++++----- 3 files changed, 39 insertions(+), 5 deletions(-)include/linux/audit.h +8
-0@@ -285,6 +285,8 @@ static inline void audit_log_contid(struct audit_context *context, u64 contid)/* These are defined in auditsc.c */ /* Public API */ +extern struct audit_context *audit_alloc_local (gfp_t gfpflags); +extern void audit_free_context (struct audit_context *context);extern void __audit_syscall_entry (int major,unsigned long a0,unsigned long a1,unsigned long a2,unsigned long a3);extern void __audit_syscall_exit (int ret_success,long ret_value);@@ -512,6 +514,12 @@ static inline void audit_fanotify(unsigned int response)extern int audit_n_rules;extern int audit_signals;#else /* CONFIG_AUDITSYSCALL */ +static inline struct audit_context *audit_alloc_local (gfp_t gfpflags) +{ +return NULL ; +} +static inline void audit_free_context (struct audit_context *context) +{ }static inline void audit_syscall_entry (int major,unsigned long a0,unsigned long a1,unsigned long a2,unsigned long a3)kernel/audit.h +1
-0@@ -111,6 +111,7 @@ struct audit_proctitle {struct audit_context {int dummy;/* must be the first element */ int in_syscall;/* 1 if task is in a syscall */ +bool local;/* local context needed */ enum audit_state state, current_state;unsigned int serial;/* serial number for record */ int major;/* syscall number */ kernel/auditsc.c +30
-6@@ -872,11 +872,13 @@ static inline void audit_free_aux(struct audit_context *context) } } -static inline struct audit_context *audit_alloc_context (enum audit_state state) +static inline struct audit_context *audit_alloc_context (enum audit_state state, +gfp_t gfpflags) {struct audit_context *context; - context =kzalloc (sizeof (*context),GFP_KERNEL ); +/* We can be called in atomic context via audit_tg() */ + context =kzalloc (sizeof (*context), gfpflags);if (!context)return NULL ; context->state = state;@@ -912,7 +914,8 @@ int audit_alloc_syscall(struct task_struct *tsk)return 0 ; } -if (!(context =audit_alloc_context (state))) { + context =audit_alloc_context (state,GFP_KERNEL ); +if (!context) {kfree (key);audit_log_lost ("out of memory in audit_alloc_syscall" );return -ENOMEM ;@@ -924,8 +927,29 @@ int audit_alloc_syscall(struct task_struct *tsk)return 0 ; } -static inline void audit_free_context (struct audit_context *context) +struct audit_context *audit_alloc_local (gfp_t gfpflags) { +struct audit_context *context =NULL ; + +if (!audit_ever_enabled) + goto out;/* Return if not auditing. */ + context =audit_alloc_context (AUDIT_RECORD_CONTEXT , gfpflags); +if (!context) { +audit_log_lost ("out of memory in audit_alloc_local" ); + goto out; + } + context->serial =audit_serial (); +ktime_get_coarse_real_ts64 (&context->ctime); + context->local = true; +out: +return context; +} +EXPORT_SYMBOL (audit_alloc_local); + +void audit_free_context (struct audit_context *context) +{ +if (!context) +return ;audit_free_names (context);unroll_tree_refs (context,NULL ,0 );free_tree_refs (context);@@ -935,6 +959,7 @@ static inline void audit_free_context(struct audit_context *context)audit_proctitle_free (context);kfree (context); } +EXPORT_SYMBOL (audit_free_context); static int audit_log_pid_context(struct audit_context *context, pid_t pid, kuid_t auid, kuid_t uid, unsigned int sessionid,@@ -2163,7 +2188,7 @@ void __audit_inode_child(struct inode *parent,int auditsc_get_stamp (struct audit_context *ctx,struct timespec64 *t,unsigned int *serial) { -if (!ctx->in_syscall) +if (!ctx->in_syscall && !ctx->local)return 0 ;if (!ctx->serial) ctx->serial =audit_serial (); --1.8.3.1
Signature · 3 lines
Ondrej Mosnacek <omosnace at redhat dot com> Software Engineer, Security Technologies Red Hat, Inc.
Paul Moore
maintainerRe: [PATCH ghak90 V5 06/10] audit: add support for non-syscall auxiliary records
In reply to Richard Guy BriggsQuoted 14 lines · Richard Guy Briggs
Standalone audit records have the timestamp and serial number generated on the fly and as such are unique, making them standalone. This new function
audit_alloc_local()generates a local audit context that will be used only for a standalone record and its auxiliary record(s). The context is discarded immediately after the local associated records are produced.Signed-off-by Richard Guy Briggs <[email protected]>Acked-by Serge Hallyn <[email protected]>--- include/linux/audit.h | 8 ++++++++ kernel/audit.h | 1 + kernel/auditsc.c | 35 ++++++++++++++++++++++++++++++----- 3 files changed, 39 insertions(+), 5 deletions(-)
...
Quoted 31 lines
include/linux/audit.h +8
-0@@ -285,6 +285,8 @@ static inline void audit_log_contid(struct audit_context *context, u64 contid)/* These are defined in auditsc.c */ /* Public API */ +extern struct audit_context *audit_alloc_local (gfp_t gfpflags); +extern void audit_free_context (struct audit_context *context);extern void __audit_syscall_entry (int major,unsigned long a0,unsigned long a1,unsigned long a2,unsigned long a3);extern void __audit_syscall_exit (int ret_success,long ret_value);@@ -512,6 +514,12 @@ static inline void audit_fanotify(unsigned int response)extern int audit_n_rules;extern int audit_signals;#else /* CONFIG_AUDITSYSCALL */ +static inline struct audit_context *audit_alloc_local (gfp_t gfpflags) +{ +return NULL ; +} +static inline void audit_free_context (struct audit_context *context) +{ }static inline void audit_syscall_entry (int major,unsigned long a0,unsigned long a1,unsigned long a2,unsigned long a3)kernel/audit.h +0
-0
kernel/audit.h struct audit_proctitle { · line 114
Quoted 4 lines
kernel/audit.h +1
-0@@ -111,6 +111,7 @@ struct audit_proctitle {struct audit_context {int dummy;/* must be the first element */ int in_syscall;/* 1 if task is in a syscall */ +bool local;/* local context needed */
It's very possible I've missed it, but "local" never gets used in any meaningful way in this patchset does it?
Quoted 3 lines
kernel/audit.h +0
-0enum audit_state state, current_state;unsigned int serial;/* serial number for record */ int major;/* syscall number */
Signature · 2 lines
paul moore www.paul-moore.com
Re: [PATCH ghak90 V5 06/10] audit: add support for non-syscall auxiliary records
Quoted 48 lines · Paul Moore
Quoted 14 lines · Richard Guy Briggs
Standalone audit records have the timestamp and serial number generated on the fly and as such are unique, making them standalone. This new function
audit_alloc_local()generates a local audit context that will be used only for a standalone record and its auxiliary record(s). The context is discarded immediately after the local associated records are produced.Signed-off-by Richard Guy Briggs <[email protected]>Acked-by Serge Hallyn <[email protected]>--- include/linux/audit.h | 8 ++++++++ kernel/audit.h | 1 + kernel/auditsc.c | 35 ++++++++++++++++++++++++++++++----- 3 files changed, 39 insertions(+), 5 deletions(-)...
Quoted 30 lines
include/linux/audit.h +8
-0@@ -285,6 +285,8 @@ static inline void audit_log_contid(struct audit_context *context, u64 contid)/* These are defined in auditsc.c */ /* Public API */ +extern struct audit_context *audit_alloc_local (gfp_t gfpflags); +extern void audit_free_context (struct audit_context *context);extern void __audit_syscall_entry (int major,unsigned long a0,unsigned long a1,unsigned long a2,unsigned long a3);extern void __audit_syscall_exit (int ret_success,long ret_value);@@ -512,6 +514,12 @@ static inline void audit_fanotify(unsigned int response)extern int audit_n_rules;extern int audit_signals;#else /* CONFIG_AUDITSYSCALL */ +static inline struct audit_context *audit_alloc_local (gfp_t gfpflags) +{ +return NULL ; +} +static inline void audit_free_context (struct audit_context *context) +{ }static inline void audit_syscall_entry (int major,unsigned long a0,unsigned long a1,unsigned long a2,unsigned long a3)kernel/audit.h +0
-0
Quoted 8 lines
kernel/audit.h struct audit_proctitle { · line 114
Quoted 5 lines
kernel/audit.h +1
-0@@ -111,6 +111,7 @@ struct audit_proctitle {struct audit_context {int dummy;/* must be the first element */ int in_syscall;/* 1 if task is in a syscall */ +bool local;/* local context needed */ It's very possible I've missed it, but "local" never gets used in any meaningful way in this patchset does it?
It is used in audit_alloc_local() to signal to audit_get_stamp() that in absence of a syscall flag, check for a local flag to continue rather than return.
Quoted 5 lines
kernel/audit.h struct audit_proctitle { · line 117
Quoted 3 lines
kernel/audit.h +0
-0enum audit_state state, current_state;unsigned int serial;/* serial number for record */ int major;/* syscall number */ paul moore
- RGB
Paul Moore
maintainerRe: [PATCH ghak90 V5 06/10] audit: add support for non-syscall auxiliary records
Quoted 58 lines · Richard Guy Briggs
Quoted 48 lines · Paul Moore
Quoted 14 lines · Richard Guy Briggs
Standalone audit records have the timestamp and serial number generated on the fly and as such are unique, making them standalone. This new function
audit_alloc_local()generates a local audit context that will be used only for a standalone record and its auxiliary record(s). The context is discarded immediately after the local associated records are produced.Signed-off-by Richard Guy Briggs <[email protected]>Acked-by Serge Hallyn <[email protected]>--- include/linux/audit.h | 8 ++++++++ kernel/audit.h | 1 + kernel/auditsc.c | 35 ++++++++++++++++++++++++++++++----- 3 files changed, 39 insertions(+), 5 deletions(-)...
Quoted 30 lines
include/linux/audit.h +8
-0@@ -285,6 +285,8 @@ static inline void audit_log_contid(struct audit_context *context, u64 contid)/* These are defined in auditsc.c */ /* Public API */ +extern struct audit_context *audit_alloc_local (gfp_t gfpflags); +extern void audit_free_context (struct audit_context *context);extern void __audit_syscall_entry (int major,unsigned long a0,unsigned long a1,unsigned long a2,unsigned long a3);extern void __audit_syscall_exit (int ret_success,long ret_value);@@ -512,6 +514,12 @@ static inline void audit_fanotify(unsigned int response)extern int audit_n_rules;extern int audit_signals;#else /* CONFIG_AUDITSYSCALL */ +static inline struct audit_context *audit_alloc_local (gfp_t gfpflags) +{ +return NULL ; +} +static inline void audit_free_context (struct audit_context *context) +{ }static inline void audit_syscall_entry (int major,unsigned long a0,unsigned long a1,unsigned long a2,unsigned long a3)kernel/audit.h +0
-0Quoted 8 lines
kernel/audit.h struct audit_proctitle { · line 114
Quoted 5 lines
kernel/audit.h +1
-0@@ -111,6 +111,7 @@ struct audit_proctitle {struct audit_context {int dummy;/* must be the first element */ int in_syscall;/* 1 if task is in a syscall */ +bool local;/* local context needed */ It's very possible I've missed it, but "local" never gets used in any meaningful way in this patchset does it?
Quoted 3 lines
It is used in
audit_alloc_local()to signal toaudit_get_stamp()that in absence of a syscall flag, check for a local flag to continue rather than return.
I'm guessing you meant auditsc_get_stamp()? If so, okay.
Signature · 2 lines
paul moore www.paul-moore.com
Re: [PATCH ghak90 V5 06/10] audit: add support for non-syscall auxiliary records
Quoted 59 lines · Paul Moore
Quoted 58 lines · Richard Guy Briggs
Quoted 56 lines · Paul Moore
Quoted 14 lines · Richard Guy Briggs
Standalone audit records have the timestamp and serial number generated on the fly and as such are unique, making them standalone. This new function
audit_alloc_local()generates a local audit context that will be used only for a standalone record and its auxiliary record(s). The context is discarded immediately after the local associated records are produced.Signed-off-by Richard Guy Briggs <[email protected]>Acked-by Serge Hallyn <[email protected]>--- include/linux/audit.h | 8 ++++++++ kernel/audit.h | 1 + kernel/auditsc.c | 35 ++++++++++++++++++++++++++++++----- 3 files changed, 39 insertions(+), 5 deletions(-)...
Quoted 31 lines
include/linux/audit.h +8
-0@@ -285,6 +285,8 @@ static inline void audit_log_contid(struct audit_context *context, u64 contid)/* These are defined in auditsc.c */ /* Public API */ +extern struct audit_context *audit_alloc_local (gfp_t gfpflags); +extern void audit_free_context (struct audit_context *context);extern void __audit_syscall_entry (int major,unsigned long a0,unsigned long a1,unsigned long a2,unsigned long a3);extern void __audit_syscall_exit (int ret_success,long ret_value);@@ -512,6 +514,12 @@ static inline void audit_fanotify(unsigned int response)extern int audit_n_rules;extern int audit_signals;#else /* CONFIG_AUDITSYSCALL */ +static inline struct audit_context *audit_alloc_local (gfp_t gfpflags) +{ +return NULL ; +} +static inline void audit_free_context (struct audit_context *context) +{ }static inline void audit_syscall_entry (int major,unsigned long a0,unsigned long a1,unsigned long a2,unsigned long a3)kernel/audit.h +0
-0kernel/audit.h struct audit_proctitle { · line 114
Quoted 4 lines
kernel/audit.h +1
-0@@ -111,6 +111,7 @@ struct audit_proctitle {struct audit_context {int dummy;/* must be the first element */ int in_syscall;/* 1 if task is in a syscall */ +bool local;/* local context needed */ It's very possible I've missed it, but "local" never gets used in any meaningful way in this patchset does it?
Quoted 5 lines
Quoted 3 lines
It is used in
audit_alloc_local()to signal toaudit_get_stamp()that in absence of a syscall flag, check for a local flag to continue rather than return.I'm guessing you meant
auditsc_get_stamp()? If so, okay.
Yes. (I thought I remembered typing "auditsc...".)
Quoted 1 line
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
PATCH v5 7/10 audit: add containerid support for user records
In reply to Richard Guy BriggsAdd audit container identifier auxiliary record to user event standalone records.
--- kernel/audit.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-)
kernel/audit.c +6 -7
@@ -1142,12 +1142,6 @@ static void audit_log_common_recv_msg(struct audit_context *context,audit_log_task_context (*ab); } -static inline void audit_log_user_recv_msg (struct audit_buffer **ab, -u16 msg_type) -{ -audit_log_common_recv_msg (NULL , ab, msg_type); -} -int is_audit_feature_set (int i) {return af.features &AUDIT_FEATURE_TO_MASK (i);
@@ -1409,13 +1403,16 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) err =audit_filter (msg_type,AUDIT_FILTER_USER );if (err ==1 ) {/* match or error */ +struct audit_context *context; + err =0 ;if (msg_type ==AUDIT_USER_TTY ) { err =tty_audit_push ();if (err)break ; } -audit_log_user_recv_msg (&ab, msg_type); + context =audit_alloc_local (GFP_KERNEL ); +audit_log_common_recv_msg (context, &ab, msg_type);if (msg_type !=AUDIT_USER_TTY ) audit_log_format(ab, " msg='%.*s'", AUDIT_MESSAGE_TEXT_MAX,
@@ -1431,6 +1428,8 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)audit_log_n_untrustedstring (ab, data, size); }audit_log_end (ab); +audit_log_contid (context,audit_get_contid (current)); +audit_free_context (context); }break ;case AUDIT_ADD_RULE :
Signature · 1 line
1.8.3.1
Re: [PATCH ghak90 V5 07/10] audit: add containerid support for user records
Quoted 56 lines · Richard Guy Briggs
Add audit container identifier auxiliary record to user event standalone records.
Signed-off-by Richard Guy Briggs <[email protected]>--- kernel/audit.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-)kernel/audit.c +6
-7@@ -1142,12 +1142,6 @@ static void audit_log_common_recv_msg(struct audit_context *context,audit_log_task_context (*ab); } -static inline void audit_log_user_recv_msg (struct audit_buffer **ab, -u16 msg_type) -{ -audit_log_common_recv_msg (NULL , ab, msg_type); -} -int is_audit_feature_set (int i) {return af.features &AUDIT_FEATURE_TO_MASK (i);@@ -1409,13 +1403,16 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) err =audit_filter (msg_type,AUDIT_FILTER_USER );if (err ==1 ) {/* match or error */ +struct audit_context *context; + err =0 ;if (msg_type ==AUDIT_USER_TTY ) { err =tty_audit_push ();if (err)break ; } -audit_log_user_recv_msg (&ab, msg_type); + context =audit_alloc_local (GFP_KERNEL ); +audit_log_common_recv_msg (context, &ab, msg_type);if (msg_type !=AUDIT_USER_TTY ) audit_log_format(ab, " msg='%.*s'", AUDIT_MESSAGE_TEXT_MAX,@@ -1431,6 +1428,8 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)audit_log_n_untrustedstring (ab, data, size); }audit_log_end (ab); +audit_log_contid (context,audit_get_contid (current)); +audit_free_context (context); }break ;case AUDIT_ADD_RULE :Signature · 1 line
1.8.3.1
Re: [PATCH ghak90 V5 07/10] audit: add containerid support for user records
In reply to Richard Guy BriggsQuoted 4 lines · Richard Guy Briggs
Add audit container identifier auxiliary record to user event standalone records.
Signed-off-by Richard Guy Briggs <[email protected]>
Quoted 51 lines
--- kernel/audit.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-)kernel/audit.c +6
-8@@ -1142,12 +1142,6 @@ static void audit_log_common_recv_msg(struct audit_context *context,audit_log_task_context (*ab); } -static inline void audit_log_user_recv_msg (struct audit_buffer **ab, -u16 msg_type) -{ -audit_log_common_recv_msg (NULL , ab, msg_type); -} -int is_audit_feature_set (int i) {return af.features &AUDIT_FEATURE_TO_MASK (i);@@ -1409,13 +1403,16 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) err =audit_filter (msg_type,AUDIT_FILTER_USER );if (err ==1 ) {/* match or error */ +struct audit_context *context; + err =0 ;if (msg_type ==AUDIT_USER_TTY ) { err =tty_audit_push ();if (err)break ; } -audit_log_user_recv_msg (&ab, msg_type); + context =audit_alloc_local (GFP_KERNEL ); +audit_log_common_recv_msg (context, &ab, msg_type);if (msg_type !=AUDIT_USER_TTY ) audit_log_format(ab, " msg='%.*s'", AUDIT_MESSAGE_TEXT_MAX,@@ -1431,6 +1428,8 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)audit_log_n_untrustedstring (ab, data, size); }audit_log_end (ab); +audit_log_contid (context,audit_get_contid (current)); +audit_free_context (context); }break ;case AUDIT_ADD_RULE : --1.8.3.1
Signature · 3 lines
Ondrej Mosnacek <omosnace at redhat dot com> Software Engineer, Security Technologies Red Hat, Inc.
PATCH v5 8/10 audit: add containerid filtering
In reply to Richard Guy BriggsImplement 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
--- 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(-)
include/linux/audit.h +1 -0
@@ -77,6 +77,7 @@ struct audit_field {u32 type;union {u32 val; +u64 val64;kuid_t uid;kgid_t gid;struct {
include/uapi/linux/audit.h +4 -1
@@ -265,6 +265,7 @@#define AUDIT_LOGINUID_SET 24#define AUDIT_SESSIONID 25/* Session ID */ #define AUDIT_FSTYPE 26/* FileSystem Type */ +#define AUDIT_CONTID 27/* Container ID */ /* These are ONLY useful when checking * at syscall exit time (AUDIT_AT_EXIT). */
@@ -345,6 +346,7 @@ enum {#define AUDIT_FEATURE_BITMAP_SESSIONID_FILTER 0x00000010#define AUDIT_FEATURE_BITMAP_LOST_RESET 0x00000020#define AUDIT_FEATURE_BITMAP_FILTER_FS 0x00000040 +#define AUDIT_FEATURE_BITMAP_CONTAINERID 0x00000080#define AUDIT_FEATURE_BITMAP_ALL (AUDIT_FEATURE_BITMAP_BACKLOG_LIMIT | \ AUDIT_FEATURE_BITMAP_BACKLOG_WAIT_TIME | \
@@ -352,7 +354,8 @@ enum { AUDIT_FEATURE_BITMAP_EXCLUDE_EXTEND | \ AUDIT_FEATURE_BITMAP_SESSIONID_FILTER | \ AUDIT_FEATURE_BITMAP_LOST_RESET | \ - AUDIT_FEATURE_BITMAP_FILTER_FS) + AUDIT_FEATURE_BITMAP_FILTER_FS | \ + AUDIT_FEATURE_BITMAP_CONTAINERID)/* deprecated: AUDIT_VERSION_* */ #define AUDIT_VERSION_LATEST AUDIT_FEATURE_BITMAP_ALL
kernel/audit.h +1 -0
@@ -230,6 +230,7 @@ static inline int audit_hash_ino(u32 ino)extern int audit_match_class (int class,unsigned syscall);extern int audit_comparator (const u32 left,const u32 op,const u32 right); +extern int audit_comparator64 (const u64 left,const u32 op,const u64 right);extern int audit_uid_comparator (kuid_t left,u32 op,kuid_t right);extern int audit_gid_comparator (kgid_t left,u32 op,kgid_t right);extern int parent_len (const char *path);
kernel/auditfilter.c +47 -0
83 lines not on this page · raw message
kernel/auditsc.c +3 -0
@@ -616,6 +616,9 @@ static int audit_filter_rules(struct task_struct *tsk,case AUDIT_LOGINUID_SET : result =audit_comparator (audit_loginuid_set (tsk), f->op, f->val);break ; +case AUDIT_CONTID : + result =audit_comparator64 (audit_get_contid (tsk), f->op, f->val64); +break ;case AUDIT_SUBJ_USER :case AUDIT_SUBJ_ROLE :case AUDIT_SUBJ_TYPE :
Signature · 1 line
1.8.3.1
Re: [PATCH ghak90 V5 08/10] audit: add containerid filtering
Quoted 106 lines · Richard Guy Briggs
Implement audit container identifier filtering using the
AUDIT_CONTIDfield 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-IDSigned-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(-)include/linux/audit.h +1
-0@@ -77,6 +77,7 @@ struct audit_field {u32 type;union {u32 val; +u64 val64;kuid_t uid;kgid_t gid;struct {include/uapi/linux/audit.h +4
-1@@ -265,6 +265,7 @@#define AUDIT_LOGINUID_SET 24#define AUDIT_SESSIONID 25/* Session ID */ #define AUDIT_FSTYPE 26/* FileSystem Type */ +#define AUDIT_CONTID 27/* Container ID */ /* These are ONLY useful when checking * at syscall exit time (AUDIT_AT_EXIT). */ @@ -345,6 +346,7 @@ enum {#define AUDIT_FEATURE_BITMAP_SESSIONID_FILTER 0x00000010#define AUDIT_FEATURE_BITMAP_LOST_RESET 0x00000020#define AUDIT_FEATURE_BITMAP_FILTER_FS 0x00000040 +#define AUDIT_FEATURE_BITMAP_CONTAINERID 0x00000080#define AUDIT_FEATURE_BITMAP_ALL (AUDIT_FEATURE_BITMAP_BACKLOG_LIMIT | \ AUDIT_FEATURE_BITMAP_BACKLOG_WAIT_TIME | \@@ -352,7 +354,8 @@ enum {AUDIT_FEATURE_BITMAP_EXCLUDE_EXTEND | \AUDIT_FEATURE_BITMAP_SESSIONID_FILTER | \AUDIT_FEATURE_BITMAP_LOST_RESET | \ - AUDIT_FEATURE_BITMAP_FILTER_FS) +AUDIT_FEATURE_BITMAP_FILTER_FS | \ + AUDIT_FEATURE_BITMAP_CONTAINERID) /* deprecated: AUDIT_VERSION_* */ #define AUDIT_VERSION_LATEST AUDIT_FEATURE_BITMAP_ALLkernel/audit.h +1
-0@@ -230,6 +230,7 @@ static inline int audit_hash_ino(u32 ino)extern int audit_match_class (int class,unsigned syscall);extern int audit_comparator (const u32 left,const u32 op,const u32 right); +extern int audit_comparator64 (const u64 left,const u32 op,const u64 right);extern int audit_uid_comparator (kuid_t left,u32 op,kuid_t right);extern int audit_gid_comparator (kgid_t left,u32 op,kgid_t right);extern int parent_len (const char *path);kernel/auditfilter.c +9
-0@@ -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 ; } }
kernel/auditfilter.c static struct audit_rule_data *audit_krule_to_data(struct audit_krule *krule) · line 679
Quoted 7 lines
kernel/auditfilter.c +4
-0@@ -664,6 +673,11 @@ static struct audit_rule_data *audit_krule_to_data(struct audit_krule *krule) data->buflen += data->values[i] =audit_pack_string (&bufp,audit_mark_path (krule->exe));break ; +case AUDIT_CONTID : + data->buflen += data->values[i] =sizeof (u64); +for (i =0 ; i <sizeof (u64); i++) + ((char *)bufp)[i] = ((char *)&f->val64)[i];
How about just:
memcpy(bufp, &f->val64, sizeof(u64));
instead of the awkward for loop? It is simpler and also more in line with the code in audit_pack_string().
Also, doesn't this loop interfere with the outer loop that also uses 'i' as the control variable?
Quoted 75 lines
kernel/auditfilter.c +34
-0+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 ;kernel/auditsc.c +3
-1@@ -616,6 +616,9 @@ static int audit_filter_rules(struct task_struct *tsk,case AUDIT_LOGINUID_SET : result =audit_comparator (audit_loginuid_set (tsk), f->op, f->val);break ; +case AUDIT_CONTID : + result =audit_comparator64 (audit_get_contid (tsk), f->op, f->val64); +break ;case AUDIT_SUBJ_USER :case AUDIT_SUBJ_ROLE :case AUDIT_SUBJ_TYPE : --1.8.3.1
Signature · 3 lines
Ondrej Mosnacek <omosnace at redhat dot com> Associate Software Engineer, Security Technologies Red Hat, Inc.
Re: [PATCH ghak90 V5 08/10] audit: add containerid filtering
Quoted 117 lines · Ondrej Mosnacek
Quoted 106 lines · Richard Guy Briggs
Implement audit container identifier filtering using the
AUDIT_CONTIDfield 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-IDSigned-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(-)include/linux/audit.h +1
-0@@ -77,6 +77,7 @@ struct audit_field {u32 type;union {u32 val; +u64 val64;kuid_t uid;kgid_t gid;struct {include/uapi/linux/audit.h +4
-1@@ -265,6 +265,7 @@#define AUDIT_LOGINUID_SET 24#define AUDIT_SESSIONID 25/* Session ID */ #define AUDIT_FSTYPE 26/* FileSystem Type */ +#define AUDIT_CONTID 27/* Container ID */ /* These are ONLY useful when checking * at syscall exit time (AUDIT_AT_EXIT). */ @@ -345,6 +346,7 @@ enum {#define AUDIT_FEATURE_BITMAP_SESSIONID_FILTER 0x00000010#define AUDIT_FEATURE_BITMAP_LOST_RESET 0x00000020#define AUDIT_FEATURE_BITMAP_FILTER_FS 0x00000040 +#define AUDIT_FEATURE_BITMAP_CONTAINERID 0x00000080#define AUDIT_FEATURE_BITMAP_ALL (AUDIT_FEATURE_BITMAP_BACKLOG_LIMIT | \ AUDIT_FEATURE_BITMAP_BACKLOG_WAIT_TIME | \@@ -352,7 +354,8 @@ enum {AUDIT_FEATURE_BITMAP_EXCLUDE_EXTEND | \AUDIT_FEATURE_BITMAP_SESSIONID_FILTER | \AUDIT_FEATURE_BITMAP_LOST_RESET | \ - AUDIT_FEATURE_BITMAP_FILTER_FS) +AUDIT_FEATURE_BITMAP_FILTER_FS | \ + AUDIT_FEATURE_BITMAP_CONTAINERID) /* deprecated: AUDIT_VERSION_* */ #define AUDIT_VERSION_LATEST AUDIT_FEATURE_BITMAP_ALLkernel/audit.h +1
-0@@ -230,6 +230,7 @@ static inline int audit_hash_ino(u32 ino)extern int audit_match_class (int class,unsigned syscall);extern int audit_comparator (const u32 left,const u32 op,const u32 right); +extern int audit_comparator64 (const u64 left,const u32 op,const u64 right);extern int audit_uid_comparator (kuid_t left,u32 op,kuid_t right);extern int audit_gid_comparator (kgid_t left,u32 op,kgid_t right);extern int parent_len (const char *path);kernel/auditfilter.c +9
-0@@ -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 ; } }kernel/auditfilter.c static struct audit_rule_data *audit_krule_to_data(struct audit_krule *krule) · line 679
Quoted 7 lines
kernel/auditfilter.c +4
-0@@ -664,6 +673,11 @@ static struct audit_rule_data *audit_krule_to_data(struct audit_krule *krule) data->buflen += data->values[i] =audit_pack_string (&bufp,audit_mark_path (krule->exe));break ; +case AUDIT_CONTID : + data->buflen += data->values[i] =sizeof (u64); +for (i =0 ; i <sizeof (u64); i++) + ((char *)bufp)[i] = ((char *)&f->val64)[i];How about just:
Quoted 4 lines
memcpy(bufp, &f->val64, sizeof(u64));instead of the awkward for loop? It is simpler and also more in line with the code in
audit_pack_string().
I'll grant you that. I'll use that instead.
Quoted 2 lines
Also, doesn't this loop interfere with the outer loop that also uses 'i' as the control variable?
Yes, it does. Thank you for catching that. Doing a auditctl -l reveals this.
Quoted 67 lines
Quoted 67 lines
kernel/auditfilter.c +34
-0+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 ;kernel/auditsc.c +1
-0@@ -616,6 +616,9 @@ static int audit_filter_rules(struct task_struct *tsk,case AUDIT_LOGINUID_SET : result =audit_comparator (audit_loginuid_set (tsk), f->op, f->val);break ; +case AUDIT_CONTID :
Quoted 14 lines
Quoted 8 lines
kernel/auditsc.c +2
-1+ 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
Signature · 3 lines
Ondrej Mosnacek <omosnace at redhat dot com> Associate Software Engineer, Security Technologies Red Hat, Inc.
- 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
Ondrej Mosnacek
Reviewed-byRe: [PATCH ghak90 V5 08/10] audit: add containerid filtering
Quoted 118 lines · Richard Guy Briggs
Quoted 117 lines · Ondrej Mosnacek
Quoted 106 lines · Richard Guy Briggs
Implement audit container identifier filtering using the
AUDIT_CONTIDfield 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-IDSigned-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(-)include/linux/audit.h +1
-0@@ -77,6 +77,7 @@ struct audit_field {u32 type;union {u32 val; +u64 val64;kuid_t uid;kgid_t gid;struct {include/uapi/linux/audit.h +4
-1@@ -265,6 +265,7 @@#define AUDIT_LOGINUID_SET 24#define AUDIT_SESSIONID 25/* Session ID */ #define AUDIT_FSTYPE 26/* FileSystem Type */ +#define AUDIT_CONTID 27/* Container ID */ /* These are ONLY useful when checking * at syscall exit time (AUDIT_AT_EXIT). */ @@ -345,6 +346,7 @@ enum {#define AUDIT_FEATURE_BITMAP_SESSIONID_FILTER 0x00000010#define AUDIT_FEATURE_BITMAP_LOST_RESET 0x00000020#define AUDIT_FEATURE_BITMAP_FILTER_FS 0x00000040 +#define AUDIT_FEATURE_BITMAP_CONTAINERID 0x00000080#define AUDIT_FEATURE_BITMAP_ALL (AUDIT_FEATURE_BITMAP_BACKLOG_LIMIT | \ AUDIT_FEATURE_BITMAP_BACKLOG_WAIT_TIME | \@@ -352,7 +354,8 @@ enum {AUDIT_FEATURE_BITMAP_EXCLUDE_EXTEND | \AUDIT_FEATURE_BITMAP_SESSIONID_FILTER | \AUDIT_FEATURE_BITMAP_LOST_RESET | \ - AUDIT_FEATURE_BITMAP_FILTER_FS) +AUDIT_FEATURE_BITMAP_FILTER_FS | \ + AUDIT_FEATURE_BITMAP_CONTAINERID) /* deprecated: AUDIT_VERSION_* */ #define AUDIT_VERSION_LATEST AUDIT_FEATURE_BITMAP_ALLkernel/audit.h +1
-0@@ -230,6 +230,7 @@ static inline int audit_hash_ino(u32 ino)extern int audit_match_class (int class,unsigned syscall);extern int audit_comparator (const u32 left,const u32 op,const u32 right); +extern int audit_comparator64 (const u64 left,const u32 op,const u64 right);extern int audit_uid_comparator (kuid_t left,u32 op,kuid_t right);extern int audit_gid_comparator (kgid_t left,u32 op,kgid_t right);extern int parent_len (const char *path);kernel/auditfilter.c +9
-0@@ -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 ; } }kernel/auditfilter.c static struct audit_rule_data *audit_krule_to_data(struct audit_krule *krule) · line 679
Quoted 7 lines
kernel/auditfilter.c +4
-0@@ -664,6 +673,11 @@ static struct audit_rule_data *audit_krule_to_data(struct audit_krule *krule) data->buflen += data->values[i] =audit_pack_string (&bufp,audit_mark_path (krule->exe));break ; +case AUDIT_CONTID : + data->buflen += data->values[i] =sizeof (u64); +for (i =0 ; i <sizeof (u64); i++) + ((char *)bufp)[i] = ((char *)&f->val64)[i];How about just:
Quoted 6 lines
Quoted 4 lines
memcpy(bufp, &f->val64, sizeof(u64));instead of the awkward for loop? It is simpler and also more in line with the code in
audit_pack_string().I'll grant you that. I'll use that instead.
Assuming the above tweak will be done, you can add:
Quoted 97 lines
Quoted 3 lines
Also, doesn't this loop interfere with the outer loop that also uses 'i' as the control variable?
Yes, it does. Thank you for catching that. Doing a auditctl -l reveals this.
Quoted 73 lines
Quoted 73 lines
kernel/auditfilter.c +34
-0+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 ;kernel/auditsc.c +3
-1@@ -616,6 +616,9 @@ static int audit_filter_rules(struct task_struct *tsk,case AUDIT_LOGINUID_SET : result =audit_comparator (audit_loginuid_set (tsk), f->op, f->val);break ; +case AUDIT_CONTID : + result =audit_comparator64 (audit_get_contid (tsk), f->op, f->val64); +break ;case AUDIT_SUBJ_USER :case AUDIT_SUBJ_ROLE :case AUDIT_SUBJ_TYPE : --Quoted 8 lines
Quoted 2 lines
1.8.3.1
--
Ondrej Mosnacek <omosnace at redhat dot com> Associate Software Engineer, Security Technologies Red Hat, Inc.- 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
Signature · 3 lines
Ondrej Mosnacek <omosnace at redhat dot com> Software Engineer, Security Technologies Red Hat, Inc.
Re: [PATCH ghak90 V5 08/10] audit: add containerid filtering
Quoted 121 lines · Ondrej Mosnacek
Quoted 120 lines · Richard Guy Briggs
Quoted 119 lines · Ondrej Mosnacek
Quoted 106 lines · Richard Guy Briggs
Implement audit container identifier filtering using the
AUDIT_CONTIDfield 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-IDSigned-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(-)include/linux/audit.h +1
-0@@ -77,6 +77,7 @@ struct audit_field {u32 type;union {u32 val; +u64 val64;kuid_t uid;kgid_t gid;struct {include/uapi/linux/audit.h +4
-1@@ -265,6 +265,7 @@#define AUDIT_LOGINUID_SET 24#define AUDIT_SESSIONID 25/* Session ID */ #define AUDIT_FSTYPE 26/* FileSystem Type */ +#define AUDIT_CONTID 27/* Container ID */ /* These are ONLY useful when checking * at syscall exit time (AUDIT_AT_EXIT). */ @@ -345,6 +346,7 @@ enum {#define AUDIT_FEATURE_BITMAP_SESSIONID_FILTER 0x00000010#define AUDIT_FEATURE_BITMAP_LOST_RESET 0x00000020#define AUDIT_FEATURE_BITMAP_FILTER_FS 0x00000040 +#define AUDIT_FEATURE_BITMAP_CONTAINERID 0x00000080#define AUDIT_FEATURE_BITMAP_ALL (AUDIT_FEATURE_BITMAP_BACKLOG_LIMIT | \ AUDIT_FEATURE_BITMAP_BACKLOG_WAIT_TIME | \@@ -352,7 +354,8 @@ enum {AUDIT_FEATURE_BITMAP_EXCLUDE_EXTEND | \AUDIT_FEATURE_BITMAP_SESSIONID_FILTER | \AUDIT_FEATURE_BITMAP_LOST_RESET | \ - AUDIT_FEATURE_BITMAP_FILTER_FS) +AUDIT_FEATURE_BITMAP_FILTER_FS | \ + AUDIT_FEATURE_BITMAP_CONTAINERID) /* deprecated: AUDIT_VERSION_* */ #define AUDIT_VERSION_LATEST AUDIT_FEATURE_BITMAP_ALLkernel/audit.h +1
-0@@ -230,6 +230,7 @@ static inline int audit_hash_ino(u32 ino)extern int audit_match_class (int class,unsigned syscall);extern int audit_comparator (const u32 left,const u32 op,const u32 right); +extern int audit_comparator64 (const u64 left,const u32 op,const u64 right);extern int audit_uid_comparator (kuid_t left,u32 op,kuid_t right);extern int audit_gid_comparator (kgid_t left,u32 op,kgid_t right);extern int parent_len (const char *path);kernel/auditfilter.c +9
-0@@ -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 ; } }kernel/auditfilter.c static struct audit_rule_data *audit_krule_to_data(struct audit_krule *krule) · line 679
Quoted 7 lines
kernel/auditfilter.c +4
-0@@ -664,6 +673,11 @@ static struct audit_rule_data *audit_krule_to_data(struct audit_krule *krule) data->buflen += data->values[i] =audit_pack_string (&bufp,audit_mark_path (krule->exe));break ; +case AUDIT_CONTID : + data->buflen += data->values[i] =sizeof (u64); +for (i =0 ; i <sizeof (u64); i++) + ((char *)bufp)[i] = ((char *)&f->val64)[i];How about just:
memcpy(bufp, &f->val64, sizeof(u64));
Quoted 8 lines
Quoted 4 lines
Quoted 2 lines
instead of the awkward for loop? It is simpler and also more in line with the code in
audit_pack_string().I'll grant you that. I'll use that instead.
Assuming the above tweak will be done, you can add:
Reviewed-by Ondrej Mosnacek <[email protected]>
Thanks. In the process of fixing that, I had also found a buffer pointer increment bug which has been fixed and a new test added to check for both.
Quoted 81 lines
Quoted 81 lines
Quoted 2 lines
Also, doesn't this loop interfere with the outer loop that also uses 'i' as the control variable?
Yes, it does. Thank you for catching that. Doing a auditctl -l reveals this.
Quoted 74 lines
Quoted 63 lines
kernel/auditfilter.c +34
-0+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 ;kernel/auditsc.c +0
-0kernel/auditsc.c static int audit_filter_rules(struct task_struct *tsk, · line 624
Quoted 9 lines
kernel/auditsc.c +3
-0@@ -616,6 +616,9 @@ static int audit_filter_rules(struct task_struct *tsk,case AUDIT_LOGINUID_SET : result =audit_comparator (audit_loginuid_set (tsk), f->op, f->val);break ; +case AUDIT_CONTID : + result =audit_comparator64 (audit_get_contid (tsk), f->op, f->val64); +break ;case AUDIT_SUBJ_USER :case AUDIT_SUBJ_ROLE :case AUDIT_SUBJ_TYPE :Ondrej Mosnacek <omosnace at redhat dot com>
Quoted 5 lines
Quoted 3 lines
- RGB
Richard Guy Briggs <[email protected]>
Ondrej Mosnacek <omosnace at redhat dot 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
Re: [PATCH ghak90 V5 08/10] audit: add containerid filtering
In reply to Richard Guy BriggsQuoted 188 lines · Richard Guy Briggs
Implement audit container identifier filtering using the
AUDIT_CONTIDfield 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-IDSigned-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(-)include/linux/audit.h +1
-0@@ -77,6 +77,7 @@ struct audit_field {u32 type;union {u32 val; +u64 val64;kuid_t uid;kgid_t gid;struct {include/uapi/linux/audit.h +4
-1@@ -265,6 +265,7 @@#define AUDIT_LOGINUID_SET 24#define AUDIT_SESSIONID 25/* Session ID */ #define AUDIT_FSTYPE 26/* FileSystem Type */ +#define AUDIT_CONTID 27/* Container ID */ /* These are ONLY useful when checking * at syscall exit time (AUDIT_AT_EXIT). */ @@ -345,6 +346,7 @@ enum {#define AUDIT_FEATURE_BITMAP_SESSIONID_FILTER 0x00000010#define AUDIT_FEATURE_BITMAP_LOST_RESET 0x00000020#define AUDIT_FEATURE_BITMAP_FILTER_FS 0x00000040 +#define AUDIT_FEATURE_BITMAP_CONTAINERID 0x00000080#define AUDIT_FEATURE_BITMAP_ALL (AUDIT_FEATURE_BITMAP_BACKLOG_LIMIT | \ AUDIT_FEATURE_BITMAP_BACKLOG_WAIT_TIME | \@@ -352,7 +354,8 @@ enum { AUDIT_FEATURE_BITMAP_EXCLUDE_EXTEND | \ AUDIT_FEATURE_BITMAP_SESSIONID_FILTER | \ AUDIT_FEATURE_BITMAP_LOST_RESET | \ - AUDIT_FEATURE_BITMAP_FILTER_FS) + AUDIT_FEATURE_BITMAP_FILTER_FS | \ + AUDIT_FEATURE_BITMAP_CONTAINERID)/* deprecated: AUDIT_VERSION_* */ #define AUDIT_VERSION_LATEST AUDIT_FEATURE_BITMAP_ALLkernel/audit.h +1
-0@@ -230,6 +230,7 @@ static inline int audit_hash_ino(u32 ino)extern int audit_match_class (int class,unsigned syscall);extern int audit_comparator (const u32 left,const u32 op,const u32 right); +extern int audit_comparator64 (const u64 left,const u32 op,const u64 right);extern int audit_uid_comparator (kuid_t left,u32 op,kuid_t right);extern int audit_gid_comparator (kgid_t left,u32 op,kgid_t right);extern int parent_len (const char *path);kernel/auditfilter.c +47
-0@@ -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 ;kernel/auditsc.c +3
-0@@ -616,6 +616,9 @@ static int audit_filter_rules(struct task_struct *tsk,case AUDIT_LOGINUID_SET : result =audit_comparator (audit_loginuid_set (tsk), f->op, f->val);break ; +case AUDIT_CONTID : + result =audit_comparator64 (audit_get_contid (tsk), f->op, f->val64); +break ;case AUDIT_SUBJ_USER :case AUDIT_SUBJ_ROLE :case AUDIT_SUBJ_TYPE :Signature · 1 line
1.8.3.1
PATCH v5 9/10 audit: add support for containerid to network namespaces
In reply to Richard Guy BriggsAudit events could happen in a network namespace outside of a task context due to packets received from the net that trigger an auditing rule prior to being associated with a running task. The network namespace could be in use by multiple containers by association to the tasks in that network namespace. We still want a way to attribute these events to any potential containers. Keep a list per network namespace to track these audit container identifiiers.
Add/increment the audit container identifier on:
- initial setting of the audit container identifier via /proc
- clone/fork call that inherits an audit container identifier
- unshare call that inherits an audit container identifier
- setns call that inherits an audit container identifier Delete/decrement the audit container identifier on:
- an inherited audit container identifier dropped when child set
- process exit
- unshare call that drops a net namespace
- setns call that drops a net namespace
See: https://github.com/linux-audit/audit-kernel/issues/92
See: https://github.com/linux-audit/audit-testsuite/issues/64
See: https://github.com/linux-audit/audit-kernel/wiki/RFE-Audit-Container-ID
--- include/linux/audit.h | 19 ++++++++++++ kernel/audit.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++-- kernel/nsproxy.c | 4 +++ 3 files changed, 106 insertions(+), 3 deletions(-)
include/linux/audit.h +19 -0
@@ -27,6 +27,7 @@#include <linux/ptrace.h> #include <linux/namei.h> /* LOOKUP_* */ #include <uapi/linux/audit.h> +#include <linux/refcount.h> #define AUDIT_INO_UNSET ((unsigned long)-1)#define AUDIT_DEV_UNSET ((dev_t)-1)
@@ -99,6 +100,13 @@ struct audit_task_info {extern struct audit_task_info init_struct_audit; +struct audit_contid { +struct list_head list; +u64 id; +refcount_t refcount; +struct rcu_head rcu; +}; +extern int is_audit_feature_set (int which);extern int __init audit_register_class (int class,unsigned *list);
@@ -202,6 +210,10 @@ static inline u64 audit_get_contid(struct task_struct *tsk) }extern void audit_log_contid (struct audit_context *context,u64 contid); +extern void audit_netns_contid_add (struct net *net,u64 contid); +extern void audit_netns_contid_del (struct net *net,u64 contid); +extern void audit_switch_task_namespaces (struct nsproxy *ns, +struct task_struct *p);extern u32 audit_enabled;#else /* CONFIG_AUDIT */
@@ -271,6 +283,13 @@ static inline u64 audit_get_contid(struct task_struct *tsk)static inline void audit_log_contid (struct audit_context *context,u64 contid) { } +static inline void audit_netns_contid_add (struct net *net,u64 contid) +{ } +static inline void audit_netns_contid_del (struct net *net,u64 contid) +{ } +static inline void audit_switch_task_namespaces (struct nsproxy *ns, +struct task_struct *p) +{ }#define audit_enabled AUDIT_OFF#endif /* CONFIG_AUDIT */
kernel/audit.c +83 -3
140 lines not on this page · raw message
kernel/nsproxy.c +4 -0
@@ -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);
Signature · 1 line
1.8.3.1
Re: [PATCH ghak90 V5 09/10] audit: add support for containerid to network namespaces
Quoted 272 lines · Richard Guy Briggs
Audit events could happen in a network namespace outside of a task context due to packets received from the net that trigger an auditing rule prior to being associated with a running task. The network namespace could be in use by multiple containers by association to the tasks in that network namespace. We still want a way to attribute these events to any potential containers. Keep a list per network namespace to track these audit container identifiiers.
Add/increment the audit container identifier on:
- initial setting of the audit container identifier via /proc
- clone/fork call that inherits an audit container identifier
- unshare call that inherits an audit container identifier
- setns call that inherits an audit container identifier Delete/decrement the audit container identifier on:
- an inherited audit container identifier dropped when child set
- process exit
- unshare call that drops a net namespace
- setns call that drops a net namespaceSee: 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-IDSigned-off-by Richard Guy Briggs <[email protected]>--- include/linux/audit.h | 19 ++++++++++++ kernel/audit.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++-- kernel/nsproxy.c | 4 +++ 3 files changed, 106 insertions(+), 3 deletions(-)include/linux/audit.h +19
-0@@ -27,6 +27,7 @@#include <linux/ptrace.h> #include <linux/namei.h> /* LOOKUP_* */ #include <uapi/linux/audit.h> +#include <linux/refcount.h> #define AUDIT_INO_UNSET ((unsigned long)-1)#define AUDIT_DEV_UNSET ((dev_t)-1)@@ -99,6 +100,13 @@ struct audit_task_info {extern struct audit_task_info init_struct_audit; +struct audit_contid { +struct list_head list; +u64 id; +refcount_t refcount; +struct rcu_head rcu; +}; +extern int is_audit_feature_set (int which);extern int __init audit_register_class (int class,unsigned *list);@@ -202,6 +210,10 @@ static inline u64 audit_get_contid(struct task_struct *tsk) }extern void audit_log_contid (struct audit_context *context,u64 contid); +extern void audit_netns_contid_add (struct net *net,u64 contid); +extern void audit_netns_contid_del (struct net *net,u64 contid); +extern void audit_switch_task_namespaces (struct nsproxy *ns, +struct task_struct *p);extern u32 audit_enabled;#else /* CONFIG_AUDIT */ @@ -271,6 +283,13 @@ static inline u64 audit_get_contid(struct task_struct *tsk)static inline void audit_log_contid (struct audit_context *context,u64 contid) { } +static inline void audit_netns_contid_add (struct net *net,u64 contid) +{ } +static inline void audit_netns_contid_del (struct net *net,u64 contid) +{ } +static inline void audit_switch_task_namespaces (struct nsproxy *ns, +struct task_struct *p) +{ }#define audit_enabled AUDIT_OFF#endif /* CONFIG_AUDIT */ kernel/audit.c +83
-3@@ -72,6 +72,7 @@#include <linux/freezer.h> #include <linux/pid_namespace.h> #include <net/netns/generic.h> +#include <net/net_namespace.h> #include "audit.h" @@ -99,9 +100,13 @@/** * struct audit_net - audit private network namespace data * @sk: communication socket +* @contid_list: audit container identifier list +* @contid_list_lock audit container identifier list lock */ struct audit_net {struct sock *sk; +struct list_head contid_list; +spinlock_t contid_list_lock; };/** @@ -275,8 +280,11 @@ struct audit_task_info init_struct_audit = {void audit_free (struct task_struct *tsk) {struct audit_task_info *info = tsk->audit; +struct nsproxy *ns = tsk->nsproxy;audit_free_syscall (tsk); +if (ns) +audit_netns_contid_del (ns->net_ns,audit_get_contid (tsk));/* Freeing the audit_task_info struct must be performed after * audit_log_exit() due to need for loginuid and sessionid. */ @@ -376,6 +384,73 @@ static struct sock *audit_get_sk(const struct net *net)return aunet->sk; } +void audit_netns_contid_add (struct net *net,u64 contid) +{ +struct audit_net *aunet =net_generic (net, audit_net_id); +struct list_head *contid_list = &aunet->contid_list; +struct audit_contid *cont; + +if (!audit_contid_valid (contid)) +return ; +if (!aunet) +return ; +spin_lock (&aunet->contid_list_lock); +if (!list_empty (contid_list)) +list_for_each_entry_rcu (cont, contid_list, list) +if (cont->id == contid) { +refcount_inc (&cont->refcount); + goto out; + } + cont =kmalloc (sizeof (struct audit_contid ),GFP_ATOMIC ); +if (cont) { +INIT_LIST_HEAD (&cont->list); + cont->id = contid; +refcount_set (&cont->refcount,1 ); +list_add_rcu (&cont->list, contid_list); + } +out: +spin_unlock (&aunet->contid_list_lock); +} + +void audit_netns_contid_del (struct net *net,u64 contid) +{ +struct audit_net *aunet; +struct list_head *contid_list; +struct audit_contid *cont =NULL ; + +if (!net) +return ; +if (!audit_contid_valid (contid)) +return ; + aunet =net_generic (net, audit_net_id); +if (!aunet) +return ; + contid_list = &aunet->contid_list; +spin_lock (&aunet->contid_list_lock); +if (!list_empty (contid_list)) +list_for_each_entry_rcu (cont, contid_list, list) +if (cont->id == contid) { +if (refcount_dec_and_test (&cont->refcount)) { +list_del_rcu (&cont->list); +kfree_rcu (cont, rcu); + } +break ; + } +spin_unlock (&aunet->contid_list_lock); +} + +void audit_switch_task_namespaces (struct nsproxy *ns,struct task_struct *p) +{ +u64 contid =audit_get_contid (p); +struct nsproxy *new = p->nsproxy; + +if (!audit_contid_valid (contid)) +return ; +audit_netns_contid_del (ns->net_ns, contid); +if (new) +audit_netns_contid_add (new->net_ns, contid); +} +void audit_panic (const char *message) {switch (audit_failure) {@@ -1619,7 +1694,6 @@ static int __net_init audit_net_init(struct net *net) .flags = NL_CFG_F_NONROOT_RECV, .groups = AUDIT_NLGRP_MAX, }; -struct audit_net *aunet =net_generic (net, audit_net_id); aunet->sk =netlink_kernel_create (net,NETLINK_AUDIT , &cfg);@@ -1628,7 +1702,8 @@ static int __net_init audit_net_init(struct net *net)return -ENOMEM ; } aunet->sk->sk_sndtimeo =MAX_SCHEDULE_TIMEOUT ; - +INIT_LIST_HEAD (&aunet->contid_list); +spin_lock_init (&aunet->contid_list_lock);return 0 ; }@@ -2380,6 +2455,7 @@ int audit_set_contid(struct task_struct *task, u64 contid)uid_t uid;struct tty_struct *tty;char comm[sizeof (current->comm)]; +struct net *net = task->nsproxy->net_ns;task_lock (task);/* Can't set if audit disabled */ @@ -2401,8 +2477,12 @@ int audit_set_contid(struct task_struct *task, u64 contid)else if (!(thread_group_leader (task) &&thread_group_empty (task))) rc = -EALREADY ;read_unlock (&tasklist_lock); -if (!rc) +if (!rc) { +if (audit_contid_valid (oldcontid)) +audit_netns_contid_del (net, oldcontid); task->audit->contid = contid; +audit_netns_contid_add (net, contid); + }task_unlock (task);if (!audit_enabled)kernel/nsproxy.c +4
-0@@ -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);Signature · 1 line
1.8.3.1
Re: [PATCH ghak90 V5 09/10] audit: add support for containerid to network namespaces
In reply to Richard Guy BriggsQuoted 42 lines · Richard Guy Briggs
Audit events could happen in a network namespace outside of a task context due to packets received from the net that trigger an auditing rule prior to being associated with a running task. The network namespace could be in use by multiple containers by association to the tasks in that network namespace. We still want a way to attribute these events to any potential containers. Keep a list per network namespace to track these audit container identifiiers.
Add/increment the audit container identifier on:
- initial setting of the audit container identifier via /proc
- clone/fork call that inherits an audit container identifier
- unshare call that inherits an audit container identifier
- setns call that inherits an audit container identifier Delete/decrement the audit container identifier on:
- an inherited audit container identifier dropped when child set
- process exit
- unshare call that drops a net namespace
- setns call that drops a net namespaceSee: 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-IDSigned-off-by Richard Guy Briggs <[email protected]>--- include/linux/audit.h | 19 ++++++++++++ kernel/audit.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++-- kernel/nsproxy.c | 4 +++ 3 files changed, 106 insertions(+), 3 deletions(-)include/linux/audit.h +1
-0@@ -27,6 +27,7 @@#include <linux/ptrace.h> #include <linux/namei.h> /* LOOKUP_* */ #include <uapi/linux/audit.h> +#include <linux/refcount.h> #define AUDIT_INO_UNSET ((unsigned long)-1)#define AUDIT_DEV_UNSET ((dev_t)-1)
include/linux/audit.h struct audit_task_info { · line 106
Quoted 7 lines
include/linux/audit.h +4
-0@@ -99,6 +100,13 @@ struct audit_task_info {extern struct audit_task_info init_struct_audit; +struct audit_contid { +struct list_head list; +u64 id; +refcount_t refcount;
Hm, since we only ever touch the refcount under a spinlock, I wonder if we could just make it a regular unsigned int (we don't need the atomicity guarantees). OTOH, refcount_t comes with some extra overflow checking, so it's probably better to leave it as is...
Quoted 212 lines
include/linux/audit.h +14
-0+struct rcu_head rcu; +}; +extern int is_audit_feature_set (int which);extern int __init audit_register_class (int class,unsigned *list);@@ -202,6 +210,10 @@ static inline u64 audit_get_contid(struct task_struct *tsk) }extern void audit_log_contid (struct audit_context *context,u64 contid); +extern void audit_netns_contid_add (struct net *net,u64 contid); +extern void audit_netns_contid_del (struct net *net,u64 contid); +extern void audit_switch_task_namespaces (struct nsproxy *ns, +struct task_struct *p);extern u32 audit_enabled;#else /* CONFIG_AUDIT */ @@ -271,6 +283,13 @@ static inline u64 audit_get_contid(struct task_struct *tsk)static inline void audit_log_contid (struct audit_context *context,u64 contid) { } +static inline void audit_netns_contid_add (struct net *net,u64 contid) +{ } +static inline void audit_netns_contid_del (struct net *net,u64 contid) +{ } +static inline void audit_switch_task_namespaces (struct nsproxy *ns, +struct task_struct *p) +{ }#define audit_enabled AUDIT_OFF#endif /* CONFIG_AUDIT */ kernel/audit.c +83
-3@@ -72,6 +72,7 @@#include <linux/freezer.h> #include <linux/pid_namespace.h> #include <net/netns/generic.h> +#include <net/net_namespace.h> #include "audit.h" @@ -99,9 +100,13 @@/** * struct audit_net - audit private network namespace data * @sk: communication socket +* @contid_list: audit container identifier list +* @contid_list_lock audit container identifier list lock */ struct audit_net {struct sock *sk; +struct list_head contid_list; +spinlock_t contid_list_lock; };/** @@ -275,8 +280,11 @@ struct audit_task_info init_struct_audit = {void audit_free (struct task_struct *tsk) {struct audit_task_info *info = tsk->audit; +struct nsproxy *ns = tsk->nsproxy;audit_free_syscall (tsk); +if (ns) +audit_netns_contid_del (ns->net_ns,audit_get_contid (tsk));/* Freeing the audit_task_info struct must be performed after * audit_log_exit() due to need for loginuid and sessionid. */ @@ -376,6 +384,73 @@ static struct sock *audit_get_sk(const struct net *net)return aunet->sk; } +void audit_netns_contid_add (struct net *net,u64 contid) +{ +struct audit_net *aunet =net_generic (net, audit_net_id); +struct list_head *contid_list = &aunet->contid_list; +struct audit_contid *cont; + +if (!audit_contid_valid (contid)) +return ; +if (!aunet) +return ; +spin_lock (&aunet->contid_list_lock); +if (!list_empty (contid_list)) +list_for_each_entry_rcu (cont, contid_list, list) +if (cont->id == contid) { +refcount_inc (&cont->refcount); + goto out; + } + cont =kmalloc (sizeof (struct audit_contid ),GFP_ATOMIC ); +if (cont) { +INIT_LIST_HEAD (&cont->list); + cont->id = contid; +refcount_set (&cont->refcount,1 ); +list_add_rcu (&cont->list, contid_list); + } +out: +spin_unlock (&aunet->contid_list_lock); +} + +void audit_netns_contid_del (struct net *net,u64 contid) +{ +struct audit_net *aunet; +struct list_head *contid_list; +struct audit_contid *cont =NULL ; + +if (!net) +return ; +if (!audit_contid_valid (contid)) +return ; + aunet =net_generic (net, audit_net_id); +if (!aunet) +return ; + contid_list = &aunet->contid_list; +spin_lock (&aunet->contid_list_lock); +if (!list_empty (contid_list)) +list_for_each_entry_rcu (cont, contid_list, list) +if (cont->id == contid) { +if (refcount_dec_and_test (&cont->refcount)) { +list_del_rcu (&cont->list); +kfree_rcu (cont, rcu); + } +break ; + } +spin_unlock (&aunet->contid_list_lock); +} + +void audit_switch_task_namespaces (struct nsproxy *ns,struct task_struct *p) +{ +u64 contid =audit_get_contid (p); +struct nsproxy *new = p->nsproxy; + +if (!audit_contid_valid (contid)) +return ; +audit_netns_contid_del (ns->net_ns, contid); +if (new) +audit_netns_contid_add (new->net_ns, contid); +} +void audit_panic (const char *message) {switch (audit_failure) {@@ -1619,7 +1694,6 @@ static int __net_init audit_net_init(struct net *net) .flags = NL_CFG_F_NONROOT_RECV, .groups = AUDIT_NLGRP_MAX, }; -struct audit_net *aunet =net_generic (net, audit_net_id); aunet->sk =netlink_kernel_create (net,NETLINK_AUDIT , &cfg);@@ -1628,7 +1702,8 @@ static int __net_init audit_net_init(struct net *net)return -ENOMEM ; } aunet->sk->sk_sndtimeo =MAX_SCHEDULE_TIMEOUT ; - +INIT_LIST_HEAD (&aunet->contid_list); +spin_lock_init (&aunet->contid_list_lock);return 0 ; }@@ -2380,6 +2455,7 @@ int audit_set_contid(struct task_struct *task, u64 contid)uid_t uid;struct tty_struct *tty;char comm[sizeof (current->comm)]; +struct net *net = task->nsproxy->net_ns;task_lock (task);/* Can't set if audit disabled */ @@ -2401,8 +2477,12 @@ int audit_set_contid(struct task_struct *task, u64 contid)else if (!(thread_group_leader (task) &&thread_group_empty (task))) rc = -EALREADY ;read_unlock (&tasklist_lock); -if (!rc) +if (!rc) { +if (audit_contid_valid (oldcontid)) +audit_netns_contid_del (net, oldcontid); task->audit->contid = contid; +audit_netns_contid_add (net, contid); + }task_unlock (task);if (!audit_enabled)kernel/nsproxy.c +3
-0@@ -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 ; }
kernel/nsproxy.c void switch_task_namespaces(struct task_struct *p, struct nsproxy *new) · line 230
Quoted 4 lines
kernel/nsproxy.c +1
-0@@ -224,6 +227,7 @@ void switch_task_namespaces(struct task_struct *p, struct nsproxy *new) ns = p->nsproxy; p->nsproxy = new;task_unlock (p); +audit_switch_task_namespaces (ns, p);
Since we call audit_switch_task_namespaces() after task_unlock(), could there be a potential race condition? I'm not going to dive too much into this now, because it's getting late here, but on first look it seems like p->nsproxy could change under our hands before we fetch it in audit_switch_task_namespaces()...
Quoted 6 lines
kernel/nsproxy.c +0
-1if (ns &&atomic_dec_and_test (&ns->count))free_nsproxy (ns); --1.8.3.1
Signature · 3 lines
Ondrej Mosnacek <omosnace at redhat dot com> Software Engineer, Security Technologies Red Hat, Inc.
Re: [PATCH ghak90 V5 09/10] audit: add support for containerid to network namespaces
Quoted 46 lines · Ondrej Mosnacek
Quoted 45 lines · Richard Guy Briggs
Audit events could happen in a network namespace outside of a task context due to packets received from the net that trigger an auditing rule prior to being associated with a running task. The network namespace could be in use by multiple containers by association to the tasks in that network namespace. We still want a way to attribute these events to any potential containers. Keep a list per network namespace to track these audit container identifiiers.
Add/increment the audit container identifier on:
- initial setting of the audit container identifier via /proc
- clone/fork call that inherits an audit container identifier
- unshare call that inherits an audit container identifier
- setns call that inherits an audit container identifier Delete/decrement the audit container identifier on:
- an inherited audit container identifier dropped when child set
- process exit
- unshare call that drops a net namespace
- setns call that drops a net namespaceSee: 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-IDSigned-off-by Richard Guy Briggs <[email protected]>--- include/linux/audit.h | 19 ++++++++++++ kernel/audit.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++-- kernel/nsproxy.c | 4 +++ 3 files changed, 106 insertions(+), 3 deletions(-)include/linux/audit.h +1
-0@@ -27,6 +27,7 @@#include <linux/ptrace.h> #include <linux/namei.h> /* LOOKUP_* */ #include <uapi/linux/audit.h> +#include <linux/refcount.h> #define AUDIT_INO_UNSET ((unsigned long)-1)#define AUDIT_DEV_UNSET ((dev_t)-1)@@ -99,6 +100,13 @@ struct audit_task_info {extern struct audit_task_info init_struct_audit;
Quoted 9 lines
include/linux/audit.h struct audit_task_info { · line 106
Quoted 4 lines
include/linux/audit.h +4
-0+struct audit_contid { +struct list_head list; +u64 id; +refcount_t refcount;Hm, since we only ever touch the refcount under a spinlock, I wonder if we could just make it a regular unsigned int (we don't need the atomicity guarantees). OTOH,
refcount_tcomes with some extra overflow checking, so it's probably better to leave it as is...
Since the update is done using rcu-safe methods, do we even need the spin_lock? Neil? Paul?
Quoted 211 lines
Quoted 211 lines
include/linux/audit.h +14
-0+struct rcu_head rcu; +}; +extern int is_audit_feature_set (int which);extern int __init audit_register_class (int class,unsigned *list);@@ -202,6 +210,10 @@ static inline u64 audit_get_contid(struct task_struct *tsk) }extern void audit_log_contid (struct audit_context *context,u64 contid); +extern void audit_netns_contid_add (struct net *net,u64 contid); +extern void audit_netns_contid_del (struct net *net,u64 contid); +extern void audit_switch_task_namespaces (struct nsproxy *ns, +struct task_struct *p);extern u32 audit_enabled;#else /* CONFIG_AUDIT */ @@ -271,6 +283,13 @@ static inline u64 audit_get_contid(struct task_struct *tsk)static inline void audit_log_contid (struct audit_context *context,u64 contid) { } +static inline void audit_netns_contid_add (struct net *net,u64 contid) +{ } +static inline void audit_netns_contid_del (struct net *net,u64 contid) +{ } +static inline void audit_switch_task_namespaces (struct nsproxy *ns, +struct task_struct *p) +{ }#define audit_enabled AUDIT_OFF#endif /* CONFIG_AUDIT */ kernel/audit.c +83
-3@@ -72,6 +72,7 @@#include <linux/freezer.h> #include <linux/pid_namespace.h> #include <net/netns/generic.h> +#include <net/net_namespace.h> #include "audit.h" @@ -99,9 +100,13 @@/** * struct audit_net - audit private network namespace data * @sk: communication socket +* @contid_list: audit container identifier list +* @contid_list_lock audit container identifier list lock */ struct audit_net {struct sock *sk; +struct list_head contid_list; +spinlock_t contid_list_lock; };/** @@ -275,8 +280,11 @@ struct audit_task_info init_struct_audit = {void audit_free (struct task_struct *tsk) {struct audit_task_info *info = tsk->audit; +struct nsproxy *ns = tsk->nsproxy;audit_free_syscall (tsk); +if (ns) +audit_netns_contid_del (ns->net_ns,audit_get_contid (tsk));/* Freeing the audit_task_info struct must be performed after * audit_log_exit() due to need for loginuid and sessionid. */ @@ -376,6 +384,73 @@ static struct sock *audit_get_sk(const struct net *net)return aunet->sk; } +void audit_netns_contid_add (struct net *net,u64 contid) +{ +struct audit_net *aunet =net_generic (net, audit_net_id); +struct list_head *contid_list = &aunet->contid_list; +struct audit_contid *cont; + +if (!audit_contid_valid (contid)) +return ; +if (!aunet) +return ; +spin_lock (&aunet->contid_list_lock); +if (!list_empty (contid_list)) +list_for_each_entry_rcu (cont, contid_list, list) +if (cont->id == contid) { +refcount_inc (&cont->refcount); + goto out; + } + cont =kmalloc (sizeof (struct audit_contid ),GFP_ATOMIC ); +if (cont) { +INIT_LIST_HEAD (&cont->list); + cont->id = contid; +refcount_set (&cont->refcount,1 ); +list_add_rcu (&cont->list, contid_list); + } +out: +spin_unlock (&aunet->contid_list_lock); +} + +void audit_netns_contid_del (struct net *net,u64 contid) +{ +struct audit_net *aunet; +struct list_head *contid_list; +struct audit_contid *cont =NULL ; + +if (!net) +return ; +if (!audit_contid_valid (contid)) +return ; + aunet =net_generic (net, audit_net_id); +if (!aunet) +return ; + contid_list = &aunet->contid_list; +spin_lock (&aunet->contid_list_lock); +if (!list_empty (contid_list)) +list_for_each_entry_rcu (cont, contid_list, list) +if (cont->id == contid) { +if (refcount_dec_and_test (&cont->refcount)) { +list_del_rcu (&cont->list); +kfree_rcu (cont, rcu); + } +break ; + } +spin_unlock (&aunet->contid_list_lock); +} + +void audit_switch_task_namespaces (struct nsproxy *ns,struct task_struct *p) +{ +u64 contid =audit_get_contid (p); +struct nsproxy *new = p->nsproxy; + +if (!audit_contid_valid (contid)) +return ; +audit_netns_contid_del (ns->net_ns, contid); +if (new) +audit_netns_contid_add (new->net_ns, contid); +} +void audit_panic (const char *message) {switch (audit_failure) {@@ -1619,7 +1694,6 @@ static int __net_init audit_net_init(struct net *net) .flags = NL_CFG_F_NONROOT_RECV, .groups = AUDIT_NLGRP_MAX, }; -struct audit_net *aunet =net_generic (net, audit_net_id); aunet->sk =netlink_kernel_create (net,NETLINK_AUDIT , &cfg);@@ -1628,7 +1702,8 @@ static int __net_init audit_net_init(struct net *net)return -ENOMEM ; } aunet->sk->sk_sndtimeo =MAX_SCHEDULE_TIMEOUT ; - +INIT_LIST_HEAD (&aunet->contid_list); +spin_lock_init (&aunet->contid_list_lock);return 0 ; }@@ -2380,6 +2455,7 @@ int audit_set_contid(struct task_struct *task, u64 contid)uid_t uid;struct tty_struct *tty;char comm[sizeof (current->comm)]; +struct net *net = task->nsproxy->net_ns;task_lock (task);/* Can't set if audit disabled */ @@ -2401,8 +2477,12 @@ int audit_set_contid(struct task_struct *task, u64 contid)else if (!(thread_group_leader (task) &&thread_group_empty (task))) rc = -EALREADY ;read_unlock (&tasklist_lock); -if (!rc) +if (!rc) { +if (audit_contid_valid (oldcontid)) +audit_netns_contid_del (net, oldcontid); task->audit->contid = contid; +audit_netns_contid_add (net, contid); + }task_unlock (task);if (!audit_enabled)kernel/nsproxy.c +3
-0@@ -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 ; }
Quoted 11 lines
kernel/nsproxy.c void switch_task_namespaces(struct task_struct *p, struct nsproxy *new) · line 230
Quoted 5 lines
kernel/nsproxy.c +1
-0@@ -224,6 +227,7 @@ void switch_task_namespaces(struct task_struct *p, struct nsproxy *new) ns = p->nsproxy; p->nsproxy = new;task_unlock (p); +audit_switch_task_namespaces (ns, p);Since we call
audit_switch_task_namespaces()aftertask_unlock(), could there be a potential race condition? I'm not going to dive too much into this now, because it's getting late here, but on first look it seems likep->nsproxycould change under our hands before we fetch it inaudit_switch_task_namespaces()...
The rules are defined in include/linux/nsproxy.h.
Since the callers (sys_setns, do_exit, copy_process error path) are all current or handing it a dead task and we are not writing nsproxy or its pointers, which is only allowed by current anyway, we don't need the lock.
Quoted 7 lines
Quoted 5 lines
kernel/nsproxy.c +0
-1if (ns &&atomic_dec_and_test (&ns->count))free_nsproxy (ns); --1.8.3.1
Ondrej Mosnacek <omosnace at redhat dot com>
- RGB
--
Richard Guy Briggs <[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
Ondrej Mosnacek
Reviewed-byRe: [PATCH ghak90 V5 09/10] audit: add support for containerid to network namespaces
Quoted 283 lines · Richard Guy Briggs
Quoted 46 lines · Ondrej Mosnacek
Quoted 45 lines · Richard Guy Briggs
Audit events could happen in a network namespace outside of a task context due to packets received from the net that trigger an auditing rule prior to being associated with a running task. The network namespace could be in use by multiple containers by association to the tasks in that network namespace. We still want a way to attribute these events to any potential containers. Keep a list per network namespace to track these audit container identifiiers.
Add/increment the audit container identifier on:
- initial setting of the audit container identifier via /proc
- clone/fork call that inherits an audit container identifier
- unshare call that inherits an audit container identifier
- setns call that inherits an audit container identifier Delete/decrement the audit container identifier on:
- an inherited audit container identifier dropped when child set
- process exit
- unshare call that drops a net namespace
- setns call that drops a net namespaceSee: 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-IDSigned-off-by Richard Guy Briggs <[email protected]>--- include/linux/audit.h | 19 ++++++++++++ kernel/audit.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++-- kernel/nsproxy.c | 4 +++ 3 files changed, 106 insertions(+), 3 deletions(-)include/linux/audit.h +1
-0@@ -27,6 +27,7 @@#include <linux/ptrace.h> #include <linux/namei.h> /* LOOKUP_* */ #include <uapi/linux/audit.h> +#include <linux/refcount.h> #define AUDIT_INO_UNSET ((unsigned long)-1)#define AUDIT_DEV_UNSET ((dev_t)-1)@@ -99,6 +100,13 @@ struct audit_task_info {extern struct audit_task_info init_struct_audit;Quoted 9 lines
include/linux/audit.h struct audit_task_info { · line 106
Quoted 4 lines
include/linux/audit.h +4
-0+struct audit_contid { +struct list_head list; +u64 id; +refcount_t refcount;Hm, since we only ever touch the refcount under a spinlock, I wonder if we could just make it a regular unsigned int (we don't need the atomicity guarantees). OTOH,
refcount_tcomes with some extra overflow checking, so it's probably better to leave it as is...Since the update is done using rcu-safe methods, do we even need the
spin_lock? Neil? Paul?Quoted 211 lines
Quoted 211 lines
include/linux/audit.h +14
-0+struct rcu_head rcu; +}; +extern int is_audit_feature_set (int which);extern int __init audit_register_class (int class,unsigned *list);@@ -202,6 +210,10 @@ static inline u64 audit_get_contid(struct task_struct *tsk) }extern void audit_log_contid (struct audit_context *context,u64 contid); +extern void audit_netns_contid_add (struct net *net,u64 contid); +extern void audit_netns_contid_del (struct net *net,u64 contid); +extern void audit_switch_task_namespaces (struct nsproxy *ns, +struct task_struct *p);extern u32 audit_enabled;#else /* CONFIG_AUDIT */ @@ -271,6 +283,13 @@ static inline u64 audit_get_contid(struct task_struct *tsk)static inline void audit_log_contid (struct audit_context *context,u64 contid) { } +static inline void audit_netns_contid_add (struct net *net,u64 contid) +{ } +static inline void audit_netns_contid_del (struct net *net,u64 contid) +{ } +static inline void audit_switch_task_namespaces (struct nsproxy *ns, +struct task_struct *p) +{ }#define audit_enabled AUDIT_OFF#endif /* CONFIG_AUDIT */ kernel/audit.c +83
-3@@ -72,6 +72,7 @@#include <linux/freezer.h> #include <linux/pid_namespace.h> #include <net/netns/generic.h> +#include <net/net_namespace.h> #include "audit.h" @@ -99,9 +100,13 @@/** * struct audit_net - audit private network namespace data * @sk: communication socket +* @contid_list: audit container identifier list +* @contid_list_lock audit container identifier list lock */ struct audit_net {struct sock *sk; +struct list_head contid_list; +spinlock_t contid_list_lock; };/** @@ -275,8 +280,11 @@ struct audit_task_info init_struct_audit = {void audit_free (struct task_struct *tsk) {struct audit_task_info *info = tsk->audit; +struct nsproxy *ns = tsk->nsproxy;audit_free_syscall (tsk); +if (ns) +audit_netns_contid_del (ns->net_ns,audit_get_contid (tsk));/* Freeing the audit_task_info struct must be performed after * audit_log_exit() due to need for loginuid and sessionid. */ @@ -376,6 +384,73 @@ static struct sock *audit_get_sk(const struct net *net)return aunet->sk; } +void audit_netns_contid_add (struct net *net,u64 contid) +{ +struct audit_net *aunet =net_generic (net, audit_net_id); +struct list_head *contid_list = &aunet->contid_list; +struct audit_contid *cont; + +if (!audit_contid_valid (contid)) +return ; +if (!aunet) +return ; +spin_lock (&aunet->contid_list_lock); +if (!list_empty (contid_list)) +list_for_each_entry_rcu (cont, contid_list, list) +if (cont->id == contid) { +refcount_inc (&cont->refcount); + goto out; + } + cont =kmalloc (sizeof (struct audit_contid ),GFP_ATOMIC ); +if (cont) { +INIT_LIST_HEAD (&cont->list); + cont->id = contid; +refcount_set (&cont->refcount,1 ); +list_add_rcu (&cont->list, contid_list); + } +out: +spin_unlock (&aunet->contid_list_lock); +} + +void audit_netns_contid_del (struct net *net,u64 contid) +{ +struct audit_net *aunet; +struct list_head *contid_list; +struct audit_contid *cont =NULL ; + +if (!net) +return ; +if (!audit_contid_valid (contid)) +return ; + aunet =net_generic (net, audit_net_id); +if (!aunet) +return ; + contid_list = &aunet->contid_list; +spin_lock (&aunet->contid_list_lock); +if (!list_empty (contid_list)) +list_for_each_entry_rcu (cont, contid_list, list) +if (cont->id == contid) { +if (refcount_dec_and_test (&cont->refcount)) { +list_del_rcu (&cont->list); +kfree_rcu (cont, rcu); + } +break ; + } +spin_unlock (&aunet->contid_list_lock); +} + +void audit_switch_task_namespaces (struct nsproxy *ns,struct task_struct *p) +{ +u64 contid =audit_get_contid (p); +struct nsproxy *new = p->nsproxy; + +if (!audit_contid_valid (contid)) +return ; +audit_netns_contid_del (ns->net_ns, contid); +if (new) +audit_netns_contid_add (new->net_ns, contid); +} +void audit_panic (const char *message) {switch (audit_failure) {@@ -1619,7 +1694,6 @@ static int __net_init audit_net_init(struct net *net) .flags = NL_CFG_F_NONROOT_RECV, .groups = AUDIT_NLGRP_MAX, }; -struct audit_net *aunet =net_generic (net, audit_net_id); aunet->sk =netlink_kernel_create (net,NETLINK_AUDIT , &cfg);@@ -1628,7 +1702,8 @@ static int __net_init audit_net_init(struct net *net)return -ENOMEM ; } aunet->sk->sk_sndtimeo =MAX_SCHEDULE_TIMEOUT ; - +INIT_LIST_HEAD (&aunet->contid_list); +spin_lock_init (&aunet->contid_list_lock);return 0 ; }@@ -2380,6 +2455,7 @@ int audit_set_contid(struct task_struct *task, u64 contid)uid_t uid;struct tty_struct *tty;char comm[sizeof (current->comm)]; +struct net *net = task->nsproxy->net_ns;task_lock (task);/* Can't set if audit disabled */ @@ -2401,8 +2477,12 @@ int audit_set_contid(struct task_struct *task, u64 contid)else if (!(thread_group_leader (task) &&thread_group_empty (task))) rc = -EALREADY ;read_unlock (&tasklist_lock); -if (!rc) +if (!rc) { +if (audit_contid_valid (oldcontid)) +audit_netns_contid_del (net, oldcontid); task->audit->contid = contid; +audit_netns_contid_add (net, contid); + }task_unlock (task);if (!audit_enabled)kernel/nsproxy.c +3
-0@@ -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 ; }Quoted 11 lines
kernel/nsproxy.c void switch_task_namespaces(struct task_struct *p, struct nsproxy *new) · line 230
Quoted 5 lines
kernel/nsproxy.c +1
-0@@ -224,6 +227,7 @@ void switch_task_namespaces(struct task_struct *p, struct nsproxy *new) ns = p->nsproxy; p->nsproxy = new;task_unlock (p); +audit_switch_task_namespaces (ns, p);Since we call
audit_switch_task_namespaces()aftertask_unlock(), could there be a potential race condition? I'm not going to dive too much into this now, because it's getting late here, but on first look it seems likep->nsproxycould change under our hands before we fetch it inaudit_switch_task_namespaces()...
Quoted 6 lines
The rules are defined in
include/linux/nsproxy.h.Since the callers (
sys_setns,do_exit,copy_processerror path) are all current or handing it a dead task and we are not writing nsproxy or its pointers, which is only allowed by current anyway, we don't need the lock.
I see, so the task lock is taken during the swap only to protect against races with other tasks reading this task's nsproxy... makes sense. Thanks for clarifying!
The refcount/spinlock issue is not blocking (and could be addressed in a follow-up patch later), so:
Quoted 17 lines
Quoted 8 lines
Quoted 6 lines
kernel/nsproxy.c +0
-1if (ns &&atomic_dec_and_test (&ns->count))free_nsproxy (ns); --1.8.3.1
Ondrej Mosnacek <omosnace at redhat dot com>
- RGB
--
Richard Guy Briggs <[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
maintainerRe: [PATCH ghak90 V5 09/10] audit: add support for containerid to network namespaces
In reply to Richard Guy BriggsQuoted 58 lines · Richard Guy Briggs
Quoted 46 lines · Ondrej Mosnacek
Quoted 45 lines · Richard Guy Briggs
Audit events could happen in a network namespace outside of a task context due to packets received from the net that trigger an auditing rule prior to being associated with a running task. The network namespace could be in use by multiple containers by association to the tasks in that network namespace. We still want a way to attribute these events to any potential containers. Keep a list per network namespace to track these audit container identifiiers.
Add/increment the audit container identifier on:
- initial setting of the audit container identifier via /proc
- clone/fork call that inherits an audit container identifier
- unshare call that inherits an audit container identifier
- setns call that inherits an audit container identifier Delete/decrement the audit container identifier on:
- an inherited audit container identifier dropped when child set
- process exit
- unshare call that drops a net namespace
- setns call that drops a net namespaceSee: 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-IDSigned-off-by Richard Guy Briggs <[email protected]>--- include/linux/audit.h | 19 ++++++++++++ kernel/audit.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++-- kernel/nsproxy.c | 4 +++ 3 files changed, 106 insertions(+), 3 deletions(-)include/linux/audit.h +1
-0@@ -27,6 +27,7 @@#include <linux/ptrace.h> #include <linux/namei.h> /* LOOKUP_* */ #include <uapi/linux/audit.h> +#include <linux/refcount.h> #define AUDIT_INO_UNSET ((unsigned long)-1)#define AUDIT_DEV_UNSET ((dev_t)-1)@@ -99,6 +100,13 @@ struct audit_task_info {extern struct audit_task_info init_struct_audit;Quoted 9 lines
include/linux/audit.h struct audit_task_info { · line 106
Quoted 4 lines
include/linux/audit.h +4
-0+struct audit_contid { +struct list_head list; +u64 id; +refcount_t refcount;Hm, since we only ever touch the refcount under a spinlock, I wonder if we could just make it a regular unsigned int (we don't need the atomicity guarantees). OTOH,
refcount_tcomes with some extra overflow checking, so it's probably better to leave it as is...
Quoted 2 lines
Since the update is done using rcu-safe methods, do we even need the
spin_lock? Neil? Paul?
As discussed, the refcount field is protected against simultaneous writes by the spinlock that protects additions/removals from the list as a whole so I don't believe the refcount_t atomicity is critical in this regard.
Where it gets tricky, and I can't say I'm 100% confident on my answer here, is if refcount was a regular int and we wanted to access it outside of a spinlock (to be clear, it doesn't look like this patch currently does this). With RCU, if refcount was a regular int (unsigned or otherwise), I believe it would be possible for different threads of execution to potentially see different values of refcount (assuming one thread was adding/removing from the list). Using a refcount_t would protect against this, alternatively, taking the spinlock should also protect against this.
As we all know, RCU can be tricky at times, so I may be off on the above; if I am, please provide an explanation so I (and likely others as well) can learn a little bit more. :)
Signature · 2 lines
paul moore www.paul-moore.com
Re: [PATCH ghak90 V5 09/10] audit: add support for containerid to network namespaces
Quoted 67 lines · Paul Moore
Quoted 58 lines · Richard Guy Briggs
Quoted 46 lines · Ondrej Mosnacek
Quoted 45 lines · Richard Guy Briggs
Audit events could happen in a network namespace outside of a task context due to packets received from the net that trigger an auditing rule prior to being associated with a running task. The network namespace could be in use by multiple containers by association to the tasks in that network namespace. We still want a way to attribute these events to any potential containers. Keep a list per network namespace to track these audit container identifiiers.
Add/increment the audit container identifier on:
- initial setting of the audit container identifier via /proc
- clone/fork call that inherits an audit container identifier
- unshare call that inherits an audit container identifier
- setns call that inherits an audit container identifier Delete/decrement the audit container identifier on:
- an inherited audit container identifier dropped when child set
- process exit
- unshare call that drops a net namespace
- setns call that drops a net namespaceSee: 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-IDSigned-off-by Richard Guy Briggs <[email protected]>--- include/linux/audit.h | 19 ++++++++++++ kernel/audit.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++-- kernel/nsproxy.c | 4 +++ 3 files changed, 106 insertions(+), 3 deletions(-)include/linux/audit.h +1
-0@@ -27,6 +27,7 @@#include <linux/ptrace.h> #include <linux/namei.h> /* LOOKUP_* */ #include <uapi/linux/audit.h> +#include <linux/refcount.h> #define AUDIT_INO_UNSET ((unsigned long)-1)#define AUDIT_DEV_UNSET ((dev_t)-1)@@ -99,6 +100,13 @@ struct audit_task_info {extern struct audit_task_info init_struct_audit;Quoted 9 lines
include/linux/audit.h struct audit_task_info { · line 106
Quoted 4 lines
include/linux/audit.h +4
-0+struct audit_contid { +struct list_head list; +u64 id; +refcount_t refcount;Hm, since we only ever touch the refcount under a spinlock, I wonder if we could just make it a regular unsigned int (we don't need the atomicity guarantees). OTOH,
refcount_tcomes with some extra overflow checking, so it's probably better to leave it as is...Quoted 2 lines
Since the update is done using rcu-safe methods, do we even need the
spin_lock? Neil? Paul?As discussed, the refcount field is protected against simultaneous writes by the spinlock that protects additions/removals from the list as a whole so I don't believe the
refcount_tatomicity is critical in this regard.
Quoted 9 lines
Where it gets tricky, and I can't say I'm 100% confident on my answer here, is if refcount was a regular int and we wanted to access it outside of a spinlock (to be clear, it doesn't look like this patch currently does this). With RCU, if refcount was a regular int (unsigned or otherwise), I believe it would be possible for different threads of execution to potentially see different values of refcount (assuming one thread was adding/removing from the list). Using a
refcount_twould protect against this, alternatively, taking the spinlock should also protect against this.
Ok, from the above it isn't clear to me if you are happy with the current code or would prefer any changes, or from below that you still need to work it through to make a pronouncement. It sounds to me you would be ok with *either* spinlock *or* refcount_t, but don't see the need for both.
Quoted 7 lines
As we all know, RCU can be tricky at times, so I may be off on the above; if I am, please provide an explanation so I (and likely others as well) can learn a little bit more. :)
Signature · 2 lines
paul moore 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
maintainerRe: [PATCH ghak90 V5 09/10] audit: add support for containerid to network namespaces
Quoted 78 lines · Richard Guy Briggs
Quoted 67 lines · Paul Moore
Quoted 58 lines · Richard Guy Briggs
Quoted 46 lines · Ondrej Mosnacek
Quoted 45 lines · Richard Guy Briggs
Audit events could happen in a network namespace outside of a task context due to packets received from the net that trigger an auditing rule prior to being associated with a running task. The network namespace could be in use by multiple containers by association to the tasks in that network namespace. We still want a way to attribute these events to any potential containers. Keep a list per network namespace to track these audit container identifiiers.
Add/increment the audit container identifier on:
- initial setting of the audit container identifier via /proc
- clone/fork call that inherits an audit container identifier
- unshare call that inherits an audit container identifier
- setns call that inherits an audit container identifier Delete/decrement the audit container identifier on:
- an inherited audit container identifier dropped when child set
- process exit
- unshare call that drops a net namespace
- setns call that drops a net namespaceSee: 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-IDSigned-off-by Richard Guy Briggs <[email protected]>--- include/linux/audit.h | 19 ++++++++++++ kernel/audit.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++-- kernel/nsproxy.c | 4 +++ 3 files changed, 106 insertions(+), 3 deletions(-)include/linux/audit.h +1
-0@@ -27,6 +27,7 @@#include <linux/ptrace.h> #include <linux/namei.h> /* LOOKUP_* */ #include <uapi/linux/audit.h> +#include <linux/refcount.h> #define AUDIT_INO_UNSET ((unsigned long)-1)#define AUDIT_DEV_UNSET ((dev_t)-1)@@ -99,6 +100,13 @@ struct audit_task_info {extern struct audit_task_info init_struct_audit;Quoted 9 lines
include/linux/audit.h struct audit_task_info { · line 106
Quoted 4 lines
include/linux/audit.h +4
-0+struct audit_contid { +struct list_head list; +u64 id; +refcount_t refcount;Hm, since we only ever touch the refcount under a spinlock, I wonder if we could just make it a regular unsigned int (we don't need the atomicity guarantees). OTOH,
refcount_tcomes with some extra overflow checking, so it's probably better to leave it as is...Quoted 2 lines
Since the update is done using rcu-safe methods, do we even need the
spin_lock? Neil? Paul?As discussed, the refcount field is protected against simultaneous writes by the spinlock that protects additions/removals from the list as a whole so I don't believe the
refcount_tatomicity is critical in this regard.Quoted 9 lines
Where it gets tricky, and I can't say I'm 100% confident on my answer here, is if refcount was a regular int and we wanted to access it outside of a spinlock (to be clear, it doesn't look like this patch currently does this). With RCU, if refcount was a regular int (unsigned or otherwise), I believe it would be possible for different threads of execution to potentially see different values of refcount (assuming one thread was adding/removing from the list). Using a
refcount_twould protect against this, alternatively, taking the spinlock should also protect against this.
Quoted 5 lines
Ok, from the above it isn't clear to me if you are happy with the current code or would prefer any changes, or from below that you still need to work it through to make a pronouncement. It sounds to me you would be ok with *either* spinlock *or*
refcount_t, but don't see the need for both.
To be fair you didn't ask if I was "happy" with the approach above, you asked if we needed the spinlock/refcount_t. I believe I answered that question as comprehensively as I could, but perhaps you wanted a hard yes or no? In that case, since refcount_t is obviously safer, I would stick with that for now just to limit the number of possible failures. If someone smarter than you or I comes along and definitively says you are 100% safe to use an int, then go ahead and use an int.
Beyond that, I'm still in the process of reviewing your patches, but I haven't finished yet, so no "pronouncement" or whatever you want to call it.
Signature · 2 lines
paul moore www.paul-moore.com
Re: [PATCH ghak90 V5 09/10] audit: add support for containerid to network namespaces
Quoted 94 lines · Paul Moore
Quoted 78 lines · Richard Guy Briggs
Quoted 67 lines · Paul Moore
Quoted 58 lines · Richard Guy Briggs
Quoted 46 lines · Ondrej Mosnacek
Quoted 45 lines · Richard Guy Briggs
Audit events could happen in a network namespace outside of a task context due to packets received from the net that trigger an auditing rule prior to being associated with a running task. The network namespace could be in use by multiple containers by association to the tasks in that network namespace. We still want a way to attribute these events to any potential containers. Keep a list per network namespace to track these audit container identifiiers.
Add/increment the audit container identifier on:
- initial setting of the audit container identifier via /proc
- clone/fork call that inherits an audit container identifier
- unshare call that inherits an audit container identifier
- setns call that inherits an audit container identifier Delete/decrement the audit container identifier on:
- an inherited audit container identifier dropped when child set
- process exit
- unshare call that drops a net namespace
- setns call that drops a net namespaceSee: 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-IDSigned-off-by Richard Guy Briggs <[email protected]>--- include/linux/audit.h | 19 ++++++++++++ kernel/audit.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++-- kernel/nsproxy.c | 4 +++ 3 files changed, 106 insertions(+), 3 deletions(-)include/linux/audit.h +1
-0@@ -27,6 +27,7 @@#include <linux/ptrace.h> #include <linux/namei.h> /* LOOKUP_* */ #include <uapi/linux/audit.h> +#include <linux/refcount.h> #define AUDIT_INO_UNSET ((unsigned long)-1)#define AUDIT_DEV_UNSET ((dev_t)-1)@@ -99,6 +100,13 @@ struct audit_task_info {extern struct audit_task_info init_struct_audit;Quoted 9 lines
include/linux/audit.h struct audit_task_info { · line 106
Quoted 4 lines
include/linux/audit.h +4
-0+struct audit_contid { +struct list_head list; +u64 id; +refcount_t refcount;Hm, since we only ever touch the refcount under a spinlock, I wonder if we could just make it a regular unsigned int (we don't need the atomicity guarantees). OTOH,
refcount_tcomes with some extra overflow checking, so it's probably better to leave it as is...Quoted 2 lines
Since the update is done using rcu-safe methods, do we even need the
spin_lock? Neil? Paul?As discussed, the refcount field is protected against simultaneous writes by the spinlock that protects additions/removals from the list as a whole so I don't believe the
refcount_tatomicity is critical in this regard.Quoted 9 lines
Where it gets tricky, and I can't say I'm 100% confident on my answer here, is if refcount was a regular int and we wanted to access it outside of a spinlock (to be clear, it doesn't look like this patch currently does this). With RCU, if refcount was a regular int (unsigned or otherwise), I believe it would be possible for different threads of execution to potentially see different values of refcount (assuming one thread was adding/removing from the list). Using a
refcount_twould protect against this, alternatively, taking the spinlock should also protect against this.Quoted 5 lines
Ok, from the above it isn't clear to me if you are happy with the current code or would prefer any changes, or from below that you still need to work it through to make a pronouncement. It sounds to me you would be ok with *either* spinlock *or*
refcount_t, but don't see the need for both.To be fair you didn't ask if I was "happy" with the approach above, you asked if we needed the spinlock/refcount_t. I believe I answered that question as comprehensively as I could, but perhaps you wanted a hard yes or no? In that case, since
refcount_tis obviously safer, I would stick with that for now just to limit the number of possible failures. If someone smarter than you or I comes along and definitively says you are 100% safe to use an int, then go ahead and use an int.
Quoted 4 lines
Beyond that, I'm still in the process of reviewing your patches, but I haven't finished yet, so no "pronouncement" or whatever you want to call it.
We definately need the spinlock, as its not meant to protect the refcount alterations, its meant to protect parallel modifications to the list pointers. Without the spinlock, the list can become corrupted (protecting the refcount is just a byproduct).
Because of that byproduct, the atomicity of the refcount isn't required, and so we could modify it to be an int or some other non-atomic ordinal type, but as I noted, I don't think thats a good idea. The refcount type helps denote clearly what the variable is used for, making it more readable, and given the relative non-performance critical path that the reference count is read/written in, and the relatively more expensive locking we are already doing there, I think there is more value in using the refcount to make the code legible than making marginally more performant by altering it to be an int type.
Neil
Quoted 4 lines
Signature · 2 lines
paul moore www.paul-moore.com
Re: [PATCH ghak90 V5 09/10] audit: add support for containerid to network namespaces
In reply to Richard Guy BriggsQuoted 78 lines · Richard Guy Briggs
Quoted 67 lines · Paul Moore
Quoted 58 lines · Richard Guy Briggs
Quoted 46 lines · Ondrej Mosnacek
Quoted 45 lines · Richard Guy Briggs
Audit events could happen in a network namespace outside of a task context due to packets received from the net that trigger an auditing rule prior to being associated with a running task. The network namespace could be in use by multiple containers by association to the tasks in that network namespace. We still want a way to attribute these events to any potential containers. Keep a list per network namespace to track these audit container identifiiers.
Add/increment the audit container identifier on:
- initial setting of the audit container identifier via /proc
- clone/fork call that inherits an audit container identifier
- unshare call that inherits an audit container identifier
- setns call that inherits an audit container identifier Delete/decrement the audit container identifier on:
- an inherited audit container identifier dropped when child set
- process exit
- unshare call that drops a net namespace
- setns call that drops a net namespaceSee: 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-IDSigned-off-by Richard Guy Briggs <[email protected]>--- include/linux/audit.h | 19 ++++++++++++ kernel/audit.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++-- kernel/nsproxy.c | 4 +++ 3 files changed, 106 insertions(+), 3 deletions(-)include/linux/audit.h +1
-0@@ -27,6 +27,7 @@#include <linux/ptrace.h> #include <linux/namei.h> /* LOOKUP_* */ #include <uapi/linux/audit.h> +#include <linux/refcount.h> #define AUDIT_INO_UNSET ((unsigned long)-1)#define AUDIT_DEV_UNSET ((dev_t)-1)@@ -99,6 +100,13 @@ struct audit_task_info {extern struct audit_task_info init_struct_audit;Quoted 9 lines
include/linux/audit.h struct audit_task_info { · line 106
Quoted 4 lines
include/linux/audit.h +4
-0+struct audit_contid { +struct list_head list; +u64 id; +refcount_t refcount;Hm, since we only ever touch the refcount under a spinlock, I wonder if we could just make it a regular unsigned int (we don't need the atomicity guarantees). OTOH,
refcount_tcomes with some extra overflow checking, so it's probably better to leave it as is...Quoted 2 lines
Since the update is done using rcu-safe methods, do we even need the
spin_lock? Neil? Paul?As discussed, the refcount field is protected against simultaneous writes by the spinlock that protects additions/removals from the list as a whole so I don't believe the
refcount_tatomicity is critical in this regard.Quoted 9 lines
Where it gets tricky, and I can't say I'm 100% confident on my answer here, is if refcount was a regular int and we wanted to access it outside of a spinlock (to be clear, it doesn't look like this patch currently does this). With RCU, if refcount was a regular int (unsigned or otherwise), I believe it would be possible for different threads of execution to potentially see different values of refcount (assuming one thread was adding/removing from the list). Using a
refcount_twould protect against this, alternatively, taking the spinlock should also protect against this.
Quoted 6 lines
Ok, from the above it isn't clear to me if you are happy with the current code or would prefer any changes, or from below that you still need to work it through to make a pronouncement. It sounds to me you would be ok with *either* spinlock *or*
refcount_t, but don't see the need for both.
I'll reiterate I think we should keep the refcount type just as it is, not for safetys sake, but for readability and convienience.
Because the refcount currently only is used on add and delete operations (implying it is only read in paths where its also modified), we need to guarantee atomicity against multiple parallel writes. We already have that guarantee because every path in which we call refcount_set/refcount_inc/refcount_dec_and_test occurs under the protection of the list spin lock, and so from that standpoint we don't need the additional guarantees offered by the refcount_t type.
However, if it were to be converted to an int type, we would have to replace the refcount_dec_and_test call with this:
if (x == 0)
warn_on_underflow
return
x -= 1;
if (x == 0)
preform_operations_to_free_list_entry
I find refcount_dec_and_test to be far easier to read and maintain, and you still have to do all of this under the protection of a spin lock, to protect against multiple writes. And if you ever find that you are adding a pure read side query of the refcount, you would need to hold the spin lock there as well, instead of just using the available refcount_read api call
Yeah, you would save a few cycles if you didn't use an atomic type here, but we're only talking about paths from user space making system calls executing here (no high volume per packet receive paths or anything), and these paths have already taken a few locks (the list lock, the task lock, etc), so eliminating this one atomic isn't going to amount to anything. Lets leave it as it is and buy ourselves the extra code readability.
Neil
Quoted 18 lines
Quoted 7 lines
As we all know, RCU can be tricky at times, so I may be off on the above; if I am, please provide an explanation so I (and likely others as well) can learn a little bit more. :)
Signature · 2 lines
paul moore 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
Re: [PATCH ghak90 V5 09/10] audit: add support for containerid to network namespaces
In reply to Richard Guy BriggsQuoted 57 lines · Richard Guy Briggs
Quoted 46 lines · Ondrej Mosnacek
Quoted 45 lines · Richard Guy Briggs
Audit events could happen in a network namespace outside of a task context due to packets received from the net that trigger an auditing rule prior to being associated with a running task. The network namespace could be in use by multiple containers by association to the tasks in that network namespace. We still want a way to attribute these events to any potential containers. Keep a list per network namespace to track these audit container identifiiers.
Add/increment the audit container identifier on:
- initial setting of the audit container identifier via /proc
- clone/fork call that inherits an audit container identifier
- unshare call that inherits an audit container identifier
- setns call that inherits an audit container identifier Delete/decrement the audit container identifier on:
- an inherited audit container identifier dropped when child set
- process exit
- unshare call that drops a net namespace
- setns call that drops a net namespaceSee: 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-IDSigned-off-by Richard Guy Briggs <[email protected]>--- include/linux/audit.h | 19 ++++++++++++ kernel/audit.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++-- kernel/nsproxy.c | 4 +++ 3 files changed, 106 insertions(+), 3 deletions(-)include/linux/audit.h +1
-0@@ -27,6 +27,7 @@#include <linux/ptrace.h> #include <linux/namei.h> /* LOOKUP_* */ #include <uapi/linux/audit.h> +#include <linux/refcount.h> #define AUDIT_INO_UNSET ((unsigned long)-1)#define AUDIT_DEV_UNSET ((dev_t)-1)@@ -99,6 +100,13 @@ struct audit_task_info {extern struct audit_task_info init_struct_audit;Quoted 9 lines
include/linux/audit.h struct audit_task_info { · line 106
Quoted 4 lines
include/linux/audit.h +4
-0+struct audit_contid { +struct list_head list; +u64 id; +refcount_t refcount;Hm, since we only ever touch the refcount under a spinlock, I wonder if we could just make it a regular unsigned int (we don't need the atomicity guarantees). OTOH,
refcount_tcomes with some extra overflow checking, so it's probably better to leave it as is...
Quoted 3 lines
Since the update is done using rcu-safe methods, do we even need the
spin_lock? Neil? Paul?
Yes, we do. Rcu-safe methods only apply to read side operations, we still need traditional mutual exclusion on the write side of the operation. That is to say we need to protect the list against multiple writers at the same time, and for that we need a spin lock.
Neil
Paul Moore
maintainerRe: [PATCH ghak90 V5 09/10] audit: add support for containerid to network namespaces
In reply to Richard Guy BriggsQuoted 28 lines · Richard Guy Briggs
Audit events could happen in a network namespace outside of a task context due to packets received from the net that trigger an auditing rule prior to being associated with a running task. The network namespace could be in use by multiple containers by association to the tasks in that network namespace. We still want a way to attribute these events to any potential containers. Keep a list per network namespace to track these audit container identifiiers.
Add/increment the audit container identifier on:
- initial setting of the audit container identifier via /proc
- clone/fork call that inherits an audit container identifier
- unshare call that inherits an audit container identifier
- setns call that inherits an audit container identifier Delete/decrement the audit container identifier on:
- an inherited audit container identifier dropped when child set
- process exit
- unshare call that drops a net namespace
- setns call that drops a net namespaceSee: 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-IDSigned-off-by Richard Guy Briggs <[email protected]>--- include/linux/audit.h | 19 ++++++++++++ kernel/audit.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++-- kernel/nsproxy.c | 4 +++ 3 files changed, 106 insertions(+), 3 deletions(-)
...
Quoted 42 lines
kernel/audit.c +8
-0@@ -72,6 +72,7 @@#include <linux/freezer.h> #include <linux/pid_namespace.h> #include <net/netns/generic.h> +#include <net/net_namespace.h> #include "audit.h" @@ -99,9 +100,13 @@/** * struct audit_net - audit private network namespace data * @sk: communication socket +* @contid_list: audit container identifier list +* @contid_list_lock audit container identifier list lock */ struct audit_net {struct sock *sk; +struct list_head contid_list; +spinlock_t contid_list_lock; };/** @@ -275,8 +280,11 @@ struct audit_task_info init_struct_audit = {void audit_free (struct task_struct *tsk) {struct audit_task_info *info = tsk->audit; +struct nsproxy *ns = tsk->nsproxy;audit_free_syscall (tsk); +if (ns) +audit_netns_contid_del (ns->net_ns,audit_get_contid (tsk));/* Freeing the audit_task_info struct must be performed after * audit_log_exit() due to need for loginuid and sessionid. */ @@ -376,6 +384,73 @@ static struct sock *audit_get_sk(const struct net *net)return aunet->sk; }
kernel/audit.c static struct sock *audit_get_sk(const struct net *net) · line 396
Quoted 10 lines
kernel/audit.c +10
-0+void audit_netns_contid_add (struct net *net,u64 contid) +{ +struct audit_net *aunet =net_generic (net, audit_net_id); +struct list_head *contid_list = &aunet->contid_list; +struct audit_contid *cont; + +if (!audit_contid_valid (contid)) +return ; +if (!aunet) +return ;
We should move the contid_list assignment below this check, or decide that aunet is always going to valid (?) and get rid of this check completely.
kernel/audit.c static struct sock *audit_get_sk(const struct net *net) · line 398
Quoted 2 lines
kernel/audit.c +2
-0+spin_lock (&aunet->contid_list_lock); +if (!list_empty (contid_list))
We don't need the list_empty() check here do we? I think we can just call list_for_each_entry_rcu(), yes?
kernel/audit.c static struct sock *audit_get_sk(const struct net *net) · line 404
Quoted 6 lines
kernel/audit.c +6
-0+list_for_each_entry_rcu (cont, contid_list, list) +if (cont->id == contid) { +refcount_inc (&cont->refcount); + goto out; + } + cont =kmalloc (sizeof (struct audit_contid ),GFP_ATOMIC );
If you had to guess, what do you think is going to be more common:
bumping the refcount of an existing entry in the list, or adding a new entry? I'm asking because I always get a little nervous when doing allocations while holding a spinlock. Yes, you are doing it with GFP_ATOMIC, but it still seems like something to try and avoid if this is going to approach 50%. However, if the new entry is rare then the extra work of always doing the allocation before taking the lock and then freeing it afterwards might be a bad tradeoff.
My gut feeling says we might do about as many allocations as refcount bumps, but I could be thinking about this wrong.
Moving the allocation outside the spinlock might also open the door to doing this as GFP_KERNEL, which is a good thing, but I haven't looked at the callers to see if that is possible (it may not be). That's an exercise left to the patch author (if he hasn't done that already).
kernel/audit.c static struct sock *audit_get_sk(const struct net *net) · line 406
Quoted 2 lines
kernel/audit.c +2
-0+if (cont) { +INIT_LIST_HEAD (&cont->list);
Unless there is some guidance that INIT_LIST_HEAD() should be used regardless, you shouldn't need to call this here since list_add_rcu() will take care of any list.h related initialization.
Quoted 7 lines
kernel/audit.c +7
-0+ cont->id = contid; +refcount_set (&cont->refcount,1 ); +list_add_rcu (&cont->list, contid_list); + } +out: +spin_unlock (&aunet->contid_list_lock); +}
Signature · 2 lines
paul moore www.paul-moore.com
Re: [PATCH ghak90 V5 09/10] audit: add support for containerid to network namespaces
Quoted 74 lines · Paul Moore
Quoted 28 lines · Richard Guy Briggs
Audit events could happen in a network namespace outside of a task context due to packets received from the net that trigger an auditing rule prior to being associated with a running task. The network namespace could be in use by multiple containers by association to the tasks in that network namespace. We still want a way to attribute these events to any potential containers. Keep a list per network namespace to track these audit container identifiiers.
Add/increment the audit container identifier on:
- initial setting of the audit container identifier via /proc
- clone/fork call that inherits an audit container identifier
- unshare call that inherits an audit container identifier
- setns call that inherits an audit container identifier Delete/decrement the audit container identifier on:
- an inherited audit container identifier dropped when child set
- process exit
- unshare call that drops a net namespace
- setns call that drops a net namespaceSee: 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-IDSigned-off-by Richard Guy Briggs <[email protected]>--- include/linux/audit.h | 19 ++++++++++++ kernel/audit.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++-- kernel/nsproxy.c | 4 +++ 3 files changed, 106 insertions(+), 3 deletions(-)...
Quoted 42 lines
kernel/audit.c +8
-0@@ -72,6 +72,7 @@#include <linux/freezer.h> #include <linux/pid_namespace.h> #include <net/netns/generic.h> +#include <net/net_namespace.h> #include "audit.h" @@ -99,9 +100,13 @@/** * struct audit_net - audit private network namespace data * @sk: communication socket +* @contid_list: audit container identifier list +* @contid_list_lock audit container identifier list lock */ struct audit_net {struct sock *sk; +struct list_head contid_list; +spinlock_t contid_list_lock; };/** @@ -275,8 +280,11 @@ struct audit_task_info init_struct_audit = {void audit_free (struct task_struct *tsk) {struct audit_task_info *info = tsk->audit; +struct nsproxy *ns = tsk->nsproxy;audit_free_syscall (tsk); +if (ns) +audit_netns_contid_del (ns->net_ns,audit_get_contid (tsk));/* Freeing the audit_task_info struct must be performed after * audit_log_exit() due to need for loginuid and sessionid. */ @@ -376,6 +384,73 @@ static struct sock *audit_get_sk(const struct net *net)return aunet->sk; }
Quoted 14 lines
kernel/audit.c static struct sock *audit_get_sk(const struct net *net) · line 396
Quoted 10 lines
kernel/audit.c +10
-0+void audit_netns_contid_add (struct net *net,u64 contid) +{ +struct audit_net *aunet =net_generic (net, audit_net_id); +struct list_head *contid_list = &aunet->contid_list; +struct audit_contid *cont; + +if (!audit_contid_valid (contid)) +return ; +if (!aunet) +return ;We should move the
contid_listassignment below this check, or decide that aunet is always going to valid (?) and get rid of this check completely.
Yes, we should move the contid_list assignment below the aunet check. At this point, testing has revlealed that audit_netns_contid_del() is being called very infrequently (very early) with invalid net or aunet which is why its code has been re-arranged to safeguard against it. So far, audit_netns_contid_add() has not had this problem, but I'd feel safer leaving the check in and to make that check relevant (rather than the contid_list assignment panicing) I'll move that assignment.
Quoted 5 lines
kernel/audit.c static struct sock *audit_get_sk(const struct net *net) · line 398
Quoted 2 lines
kernel/audit.c +2
-0+spin_lock (&aunet->contid_list_lock); +if (!list_empty (contid_list))We don't need the
list_empty()check here do we? I think we can just calllist_for_each_entry_rcu(), yes?
Yes, you appear to be correct. The examples in auditfilter.c and auditsc.c are stale since the original optimizations they were protecting are no longer present, but the practice was copied by several maintainers since. I'll fix this and address the others seperately.
Quoted 16 lines
kernel/audit.c static struct sock *audit_get_sk(const struct net *net) · line 404
Quoted 6 lines
kernel/audit.c +6
-0+list_for_each_entry_rcu (cont, contid_list, list) +if (cont->id == contid) { +refcount_inc (&cont->refcount); + goto out; + } + cont =kmalloc (sizeof (struct audit_contid ),GFP_ATOMIC );If you had to guess, what do you think is going to be more common:
bumping the refcount of an existing entry in the list, or adding a new entry? I'm asking because I always get a little nervous when doing allocations while holding a spinlock. Yes, you are doing it withGFP_ATOMIC, but it still seems like something to try and avoid if this is going to approach 50%. However, if the new entry is rare then the extra work of always doing the allocation before taking the lock and then freeing it afterwards might be a bad tradeoff.
Quoted 2 lines
My gut feeling says we might do about as many allocations as refcount bumps, but I could be thinking about this wrong.
I'm sure we could find extreme use cases in both directions. One extreme is one task per container. The other extreme is a distro container where all processes for an entire O/S running in a container just use the refcount. The former seems more likely at this point. We break even at two tasks per container.
I'm willing to switch this over to alloc/dealloc and use GFP_KERNEL which will inevitably make some kernel maintainers happier and others cringe. This could be a good candidate for kmem_cache since it is a fixed size.
Quoted 4 lines
Moving the allocation outside the spinlock might also open the door to doing this as
GFP_KERNEL, which is a good thing, but I haven't looked at the callers to see if that is possible (it may not be). That's an exercise left to the patch author (if he hasn't done that already).
Switching to GFP_KERNEL is certainly preferable. None of the callers will have a problem with that.
Quoted 6 lines
kernel/audit.c static struct sock *audit_get_sk(const struct net *net) · line 406
Quoted 2 lines
kernel/audit.c +2
-0+if (cont) { +INIT_LIST_HEAD (&cont->list);Unless there is some guidance that
INIT_LIST_HEAD()should be used regardless, you shouldn't need to call this here sincelist_add_rcu()will take care of anylist.hrelated initialization.
I see enough examples without that suggest it isn't necessary. I'll remove it.
Quoted 9 lines
kernel/audit.c static struct sock *audit_get_sk(const struct net *net) · line 413
Quoted 7 lines
kernel/audit.c +7
-0+ cont->id = contid; +refcount_set (&cont->refcount,1 ); +list_add_rcu (&cont->list, contid_list); + } +out: +spin_unlock (&aunet->contid_list_lock); +}paul moore
- RGB
--
Richard Guy Briggs <[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
Re: [PATCH ghak90 V5 09/10] audit: add support for containerid to network namespaces
In reply to Paul MooreQuoted 74 lines · Paul Moore
Quoted 28 lines · Richard Guy Briggs
Audit events could happen in a network namespace outside of a task context due to packets received from the net that trigger an auditing rule prior to being associated with a running task. The network namespace could be in use by multiple containers by association to the tasks in that network namespace. We still want a way to attribute these events to any potential containers. Keep a list per network namespace to track these audit container identifiiers.
Add/increment the audit container identifier on:
- initial setting of the audit container identifier via /proc
- clone/fork call that inherits an audit container identifier
- unshare call that inherits an audit container identifier
- setns call that inherits an audit container identifier Delete/decrement the audit container identifier on:
- an inherited audit container identifier dropped when child set
- process exit
- unshare call that drops a net namespace
- setns call that drops a net namespaceSee: 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-IDSigned-off-by Richard Guy Briggs <[email protected]>--- include/linux/audit.h | 19 ++++++++++++ kernel/audit.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++-- kernel/nsproxy.c | 4 +++ 3 files changed, 106 insertions(+), 3 deletions(-)...
Quoted 42 lines
kernel/audit.c +8
-0@@ -72,6 +72,7 @@#include <linux/freezer.h> #include <linux/pid_namespace.h> #include <net/netns/generic.h> +#include <net/net_namespace.h> #include "audit.h" @@ -99,9 +100,13 @@/** * struct audit_net - audit private network namespace data * @sk: communication socket +* @contid_list: audit container identifier list +* @contid_list_lock audit container identifier list lock */ struct audit_net {struct sock *sk; +struct list_head contid_list; +spinlock_t contid_list_lock; };/** @@ -275,8 +280,11 @@ struct audit_task_info init_struct_audit = {void audit_free (struct task_struct *tsk) {struct audit_task_info *info = tsk->audit; +struct nsproxy *ns = tsk->nsproxy;audit_free_syscall (tsk); +if (ns) +audit_netns_contid_del (ns->net_ns,audit_get_contid (tsk));/* Freeing the audit_task_info struct must be performed after * audit_log_exit() due to need for loginuid and sessionid. */ @@ -376,6 +384,73 @@ static struct sock *audit_get_sk(const struct net *net)return aunet->sk; }
Quoted 15 lines
kernel/audit.c static struct sock *audit_get_sk(const struct net *net) · line 396
Quoted 10 lines
kernel/audit.c +10
-0+void audit_netns_contid_add (struct net *net,u64 contid) +{ +struct audit_net *aunet =net_generic (net, audit_net_id); +struct list_head *contid_list = &aunet->contid_list; +struct audit_contid *cont; + +if (!audit_contid_valid (contid)) +return ; +if (!aunet) +return ;We should move the
contid_listassignment below this check, or decide that aunet is always going to valid (?) and get rid of this check completely.
I'm not sure why that would be needed. Finding the net_id list is an operation of a map relating net namespaces to lists, not contids to lists. We could do it, sure, but since they're unrelated operations, I don't think we experience any slowdowns from doing it this way.
Quoted 6 lines
kernel/audit.c static struct sock *audit_get_sk(const struct net *net) · line 398
Quoted 2 lines
kernel/audit.c +2
-0+spin_lock (&aunet->contid_list_lock); +if (!list_empty (contid_list))We don't need the
list_empty()check here do we? I think we can just calllist_for_each_entry_rcu(), yes?
This is true, the list_empty check is redundant, and the for loop will fall through if the list is empty.
Quoted 7 lines
kernel/audit.c static struct sock *audit_get_sk(const struct net *net) · line 404
Quoted 6 lines
kernel/audit.c +6
-0+list_for_each_entry_rcu (cont, contid_list, list) +if (cont->id == contid) { +refcount_inc (&cont->refcount); + goto out; + } + cont =kmalloc (sizeof (struct audit_contid ),GFP_ATOMIC );
Quoted 9 lines
If you had to guess, what do you think is going to be more common:
bumping the refcount of an existing entry in the list, or adding a new entry? I'm asking because I always get a little nervous when doing allocations while holding a spinlock. Yes, you are doing it withGFP_ATOMIC, but it still seems like something to try and avoid if this is going to approach 50%. However, if the new entry is rare then the extra work of always doing the allocation before taking the lock and then freeing it afterwards might be a bad tradeoff.
I think this is another way of asking, will multiple processes exist in the same network namespace? That is to say, will we expect a process to create a net namespace, and then have other processes enter that namespace (thereby triggering multiple calls to audit_netns_contid_add with the same net pointer and cont id). Given that the kubernetes notion of a pod is almost by definition multiple containers sharing a network namespace, I think the answer is that we will be strongly biased towards the refcount_inc case, rather than the kmalloc case. I could be wrong, but I think this is likely already in the optimized order.
Quoted 8 lines
My gut feeling says we might do about as many allocations as refcount bumps, but I could be thinking about this wrong.
Moving the allocation outside the spinlock might also open the door to doing this as
GFP_KERNEL, which is a good thing, but I haven't looked at the callers to see if that is possible (it may not be). That's an exercise left to the patch author (if he hasn't done that already).
Quoted 7 lines
kernel/audit.c static struct sock *audit_get_sk(const struct net *net) · line 406
Quoted 2 lines
kernel/audit.c +2
-0+if (cont) { +INIT_LIST_HEAD (&cont->list);Unless there is some guidance that
INIT_LIST_HEAD()should be used regardless, you shouldn't need to call this here sincelist_add_rcu()will take care of anylist.hrelated initialization.
There is a corner case that needs it. list_add_rcu has a check that gets called, __list_add_valid. Its a noop in the regular case, but if CONFIG_DEBUG_LIST is defined, its a check to ensure that the next and prev pointers getting passed in aren't set to detectable corrupt values. If we pass in garbage, we can get transient false positives on that check, so we need to set the list pointers to known good values before hand, either by using kzalloc, or INIT_LIST_HEAD, as has been done here. Given that we expressly set every field of this structure, I think this is the right approach, as it uses the list macro to expressly set the list values to their proper state.
Quoted 12 lines
Quoted 7 lines
kernel/audit.c +7
-0+ cont->id = contid; +refcount_set (&cont->refcount,1 ); +list_add_rcu (&cont->list, contid_list); + } +out: +spin_unlock (&aunet->contid_list_lock); +}Signature · 2 lines
paul moore www.paul-moore.com
Paul Moore
maintainerRe: [PATCH ghak90 V5 09/10] audit: add support for containerid to network namespaces
Quoted 90 lines · Neil Horman
Quoted 74 lines · Paul Moore
Quoted 28 lines · Richard Guy Briggs
Audit events could happen in a network namespace outside of a task context due to packets received from the net that trigger an auditing rule prior to being associated with a running task. The network namespace could be in use by multiple containers by association to the tasks in that network namespace. We still want a way to attribute these events to any potential containers. Keep a list per network namespace to track these audit container identifiiers.
Add/increment the audit container identifier on:
- initial setting of the audit container identifier via /proc
- clone/fork call that inherits an audit container identifier
- unshare call that inherits an audit container identifier
- setns call that inherits an audit container identifier Delete/decrement the audit container identifier on:
- an inherited audit container identifier dropped when child set
- process exit
- unshare call that drops a net namespace
- setns call that drops a net namespaceSee: 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-IDSigned-off-by Richard Guy Briggs <[email protected]>--- include/linux/audit.h | 19 ++++++++++++ kernel/audit.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++-- kernel/nsproxy.c | 4 +++ 3 files changed, 106 insertions(+), 3 deletions(-)...
Quoted 42 lines
kernel/audit.c +8
-0@@ -72,6 +72,7 @@#include <linux/freezer.h> #include <linux/pid_namespace.h> #include <net/netns/generic.h> +#include <net/net_namespace.h> #include "audit.h" @@ -99,9 +100,13 @@/** * struct audit_net - audit private network namespace data * @sk: communication socket +* @contid_list: audit container identifier list +* @contid_list_lock audit container identifier list lock */ struct audit_net {struct sock *sk; +struct list_head contid_list; +spinlock_t contid_list_lock; };/** @@ -275,8 +280,11 @@ struct audit_task_info init_struct_audit = {void audit_free (struct task_struct *tsk) {struct audit_task_info *info = tsk->audit; +struct nsproxy *ns = tsk->nsproxy;audit_free_syscall (tsk); +if (ns) +audit_netns_contid_del (ns->net_ns,audit_get_contid (tsk));/* Freeing the audit_task_info struct must be performed after * audit_log_exit() due to need for loginuid and sessionid. */ @@ -376,6 +384,73 @@ static struct sock *audit_get_sk(const struct net *net)return aunet->sk; }Quoted 15 lines
kernel/audit.c static struct sock *audit_get_sk(const struct net *net) · line 396
Quoted 10 lines
kernel/audit.c +10
-0+void audit_netns_contid_add (struct net *net,u64 contid) +{ +struct audit_net *aunet =net_generic (net, audit_net_id); +struct list_head *contid_list = &aunet->contid_list; +struct audit_contid *cont; + +if (!audit_contid_valid (contid)) +return ; +if (!aunet) +return ;We should move the
contid_listassignment below this check, or decide that aunet is always going to valid (?) and get rid of this check completely.
Quoted 4 lines
I'm not sure why that would be needed. Finding the
net_idlist is an operation of a map relating net namespaces to lists, not contids to lists. We could do it, sure, but since they're unrelated operations, I don't think we experience any slowdowns from doing it this way.
In the first line of the function, when aunet is declared, it is also assigned a value using net_generic():
struct audit_net *aunet = net_generic(net, audit_net_id);
Later in the function there is check to see if aunet is NULL, yet on the second line of the function (before the NULL check), there is this line of code:
struct list_head *contid_list = &aunet->contid_list;
... which could result in the dereference of a NULL pointer if aunet is NULL. My suggestion was either to move this assignment below the aunet-NULL check or decide that aunet was always going to be valid (e.g. non-NULL) and do away with the aunet-NULL check completely. Richard has since replied that the aunet-NULL check has been demonstrated to be necessary so the proper thing to do would be to move the assignment. I believe that is what Richard is planning on doing.
Quoted 7 lines
Quoted 6 lines
kernel/audit.c static struct sock *audit_get_sk(const struct net *net) · line 406
Quoted 2 lines
kernel/audit.c +2
-0+if (cont) { +INIT_LIST_HEAD (&cont->list);Unless there is some guidance that
INIT_LIST_HEAD()should be used regardless, you shouldn't need to call this here sincelist_add_rcu()will take care of anylist.hrelated initialization.
Quoted 9 lines
There is a corner case that needs it.
list_add_rcuhas a check that gets called,__list_add_valid. Its a noop in the regular case, but ifCONFIG_DEBUG_LISTis defined, its a check to ensure that the next and prev pointers getting passed in aren't set to detectable corrupt values. If we pass in garbage, we can get transient false positives on that check, so we need to set the list pointers to known good values before hand, either by using kzalloc, orINIT_LIST_HEAD, as has been done here. Given that we expressly set every field of this structure, I think this is the right approach, as it uses the list macro to expressly set the list values to their proper state.
Good to know, thanks.
Signature · 2 lines
paul moore www.paul-moore.com
Re: [PATCH ghak90 V5 09/10] audit: add support for containerid to network namespaces
Quoted 107 lines · Paul Moore
Quoted 90 lines · Neil Horman
Quoted 74 lines · Paul Moore
Quoted 28 lines · Richard Guy Briggs
Audit events could happen in a network namespace outside of a task context due to packets received from the net that trigger an auditing rule prior to being associated with a running task. The network namespace could be in use by multiple containers by association to the tasks in that network namespace. We still want a way to attribute these events to any potential containers. Keep a list per network namespace to track these audit container identifiiers.
Add/increment the audit container identifier on:
- initial setting of the audit container identifier via /proc
- clone/fork call that inherits an audit container identifier
- unshare call that inherits an audit container identifier
- setns call that inherits an audit container identifier Delete/decrement the audit container identifier on:
- an inherited audit container identifier dropped when child set
- process exit
- unshare call that drops a net namespace
- setns call that drops a net namespaceSee: 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-IDSigned-off-by Richard Guy Briggs <[email protected]>--- include/linux/audit.h | 19 ++++++++++++ kernel/audit.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++-- kernel/nsproxy.c | 4 +++ 3 files changed, 106 insertions(+), 3 deletions(-)...
Quoted 42 lines
kernel/audit.c +8
-0@@ -72,6 +72,7 @@#include <linux/freezer.h> #include <linux/pid_namespace.h> #include <net/netns/generic.h> +#include <net/net_namespace.h> #include "audit.h" @@ -99,9 +100,13 @@/** * struct audit_net - audit private network namespace data * @sk: communication socket +* @contid_list: audit container identifier list +* @contid_list_lock audit container identifier list lock */ struct audit_net {struct sock *sk; +struct list_head contid_list; +spinlock_t contid_list_lock; };/** @@ -275,8 +280,11 @@ struct audit_task_info init_struct_audit = {void audit_free (struct task_struct *tsk) {struct audit_task_info *info = tsk->audit; +struct nsproxy *ns = tsk->nsproxy;audit_free_syscall (tsk); +if (ns) +audit_netns_contid_del (ns->net_ns,audit_get_contid (tsk));/* Freeing the audit_task_info struct must be performed after * audit_log_exit() due to need for loginuid and sessionid. */ @@ -376,6 +384,73 @@ static struct sock *audit_get_sk(const struct net *net)return aunet->sk; }Quoted 15 lines
kernel/audit.c static struct sock *audit_get_sk(const struct net *net) · line 396
Quoted 10 lines
kernel/audit.c +10
-0+void audit_netns_contid_add (struct net *net,u64 contid) +{ +struct audit_net *aunet =net_generic (net, audit_net_id); +struct list_head *contid_list = &aunet->contid_list; +struct audit_contid *cont; + +if (!audit_contid_valid (contid)) +return ; +if (!aunet) +return ;We should move the
contid_listassignment below this check, or decide that aunet is always going to valid (?) and get rid of this check completely.Quoted 4 lines
I'm not sure why that would be needed. Finding the
net_idlist is an operation of a map relating net namespaces to lists, not contids to lists. We could do it, sure, but since they're unrelated operations, I don't think we experience any slowdowns from doing it this way.In the first line of the function, when aunet is declared, it is also assigned a value using
net_generic():struct audit_net *aunet = net_generic(net, audit_net_id);Later in the function there is check to see if aunet is NULL, yet on the second line of the function (before the NULL check), there is this line of code:
struct list_head *contid_list = &aunet->contid_list;
Quoted 9 lines
... which could result in the dereference of a NULL pointer if aunet is NULL. My suggestion was either to move this assignment below the aunet-NULL check or decide that aunet was always going to be valid (e.g. non-NULL) and do away with the aunet-NULL check completely. Richard has since replied that the aunet-NULL check has been demonstrated to be necessary so the proper thing to do would be to move the assignment. I believe that is what Richard is planning on doing.
oh, I'm sorry, you're right, I was looking at the contid tests not the list tests.
Neil
Quoted 23 lines
Quoted 7 lines
Quoted 6 lines
kernel/audit.c static struct sock *audit_get_sk(const struct net *net) · line 406
Quoted 2 lines
kernel/audit.c +2
-0+if (cont) { +INIT_LIST_HEAD (&cont->list);Unless there is some guidance that
INIT_LIST_HEAD()should be used regardless, you shouldn't need to call this here sincelist_add_rcu()will take care of anylist.hrelated initialization.Quoted 9 lines
There is a corner case that needs it.
list_add_rcuhas a check that gets called,__list_add_valid. Its a noop in the regular case, but ifCONFIG_DEBUG_LISTis defined, its a check to ensure that the next and prev pointers getting passed in aren't set to detectable corrupt values. If we pass in garbage, we can get transient false positives on that check, so we need to set the list pointers to known good values before hand, either by using kzalloc, orINIT_LIST_HEAD, as has been done here. Given that we expressly set every field of this structure, I think this is the right approach, as it uses the list macro to expressly set the list values to their proper state.Good to know, thanks.
Signature · 2 lines
paul moore www.paul-moore.com
Re: [PATCH ghak90 V5 09/10] audit: add support for containerid to network namespaces
In reply to Neil HormanQuoted 120 lines · Neil Horman
Quoted 74 lines · Paul Moore
Quoted 28 lines · Richard Guy Briggs
Audit events could happen in a network namespace outside of a task context due to packets received from the net that trigger an auditing rule prior to being associated with a running task. The network namespace could be in use by multiple containers by association to the tasks in that network namespace. We still want a way to attribute these events to any potential containers. Keep a list per network namespace to track these audit container identifiiers.
Add/increment the audit container identifier on:
- initial setting of the audit container identifier via /proc
- clone/fork call that inherits an audit container identifier
- unshare call that inherits an audit container identifier
- setns call that inherits an audit container identifier Delete/decrement the audit container identifier on:
- an inherited audit container identifier dropped when child set
- process exit
- unshare call that drops a net namespace
- setns call that drops a net namespaceSee: 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-IDSigned-off-by Richard Guy Briggs <[email protected]>--- include/linux/audit.h | 19 ++++++++++++ kernel/audit.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++-- kernel/nsproxy.c | 4 +++ 3 files changed, 106 insertions(+), 3 deletions(-)...
Quoted 42 lines
kernel/audit.c +8
-0@@ -72,6 +72,7 @@#include <linux/freezer.h> #include <linux/pid_namespace.h> #include <net/netns/generic.h> +#include <net/net_namespace.h> #include "audit.h" @@ -99,9 +100,13 @@/** * struct audit_net - audit private network namespace data * @sk: communication socket +* @contid_list: audit container identifier list +* @contid_list_lock audit container identifier list lock */ struct audit_net {struct sock *sk; +struct list_head contid_list; +spinlock_t contid_list_lock; };/** @@ -275,8 +280,11 @@ struct audit_task_info init_struct_audit = {void audit_free (struct task_struct *tsk) {struct audit_task_info *info = tsk->audit; +struct nsproxy *ns = tsk->nsproxy;audit_free_syscall (tsk); +if (ns) +audit_netns_contid_del (ns->net_ns,audit_get_contid (tsk));/* Freeing the audit_task_info struct must be performed after * audit_log_exit() due to need for loginuid and sessionid. */ @@ -376,6 +384,73 @@ static struct sock *audit_get_sk(const struct net *net)return aunet->sk; }Quoted 15 lines
kernel/audit.c static struct sock *audit_get_sk(const struct net *net) · line 396
Quoted 10 lines
kernel/audit.c +10
-0+void audit_netns_contid_add (struct net *net,u64 contid) +{ +struct audit_net *aunet =net_generic (net, audit_net_id); +struct list_head *contid_list = &aunet->contid_list; +struct audit_contid *cont; + +if (!audit_contid_valid (contid)) +return ; +if (!aunet) +return ;We should move the
contid_listassignment below this check, or decide that aunet is always going to valid (?) and get rid of this check completely.I'm not sure why that would be needed. Finding the
net_idlist is an operation of a map relating net namespaces to lists, not contids to lists. We could do it, sure, but since they're unrelated operations, I don't think we experience any slowdowns from doing it this way.Quoted 6 lines
kernel/audit.c static struct sock *audit_get_sk(const struct net *net) · line 398
Quoted 2 lines
kernel/audit.c +2
-0+spin_lock (&aunet->contid_list_lock); +if (!list_empty (contid_list))We don't need the
list_empty()check here do we? I think we can just calllist_for_each_entry_rcu(), yes?This is true, the
list_emptycheck is redundant, and the for loop will fall through if the list is empty.Quoted 7 lines
kernel/audit.c static struct sock *audit_get_sk(const struct net *net) · line 404
Quoted 6 lines
kernel/audit.c +6
-0+list_for_each_entry_rcu (cont, contid_list, list) +if (cont->id == contid) { +refcount_inc (&cont->refcount); + goto out; + } + cont =kmalloc (sizeof (struct audit_contid ),GFP_ATOMIC );Quoted 9 lines
If you had to guess, what do you think is going to be more common:
bumping the refcount of an existing entry in the list, or adding a new entry? I'm asking because I always get a little nervous when doing allocations while holding a spinlock. Yes, you are doing it withGFP_ATOMIC, but it still seems like something to try and avoid if this is going to approach 50%. However, if the new entry is rare then the extra work of always doing the allocation before taking the lock and then freeing it afterwards might be a bad tradeoff.
Quoted 9 lines
I think this is another way of asking, will multiple processes exist in the same network namespace? That is to say, will we expect a process to create a net namespace, and then have other processes enter that namespace (thereby triggering multiple calls to
audit_netns_contid_addwith the same net pointer and cont id). Given that the kubernetes notion of a pod is almost by definition multiple containers sharing a network namespace, I think the answer is that we will be strongly biased towards therefcount_inccase, rather than the kmalloc case. I could be wrong, but I think this is likely already in the optimized order.
I had a stab at doing a GFP_KERNEL alloc before the spinlock and releasing it after if it wasn't needed (in Patch#1 below). I also went one step further and converted it to kmem_cache (in Patch#2 below).
Quoted 7 lines
Quoted 7 lines
My gut feeling says we might do about as many allocations as refcount bumps, but I could be thinking about this wrong.
Moving the allocation outside the spinlock might also open the door to doing this as
GFP_KERNEL, which is a good thing, but I haven't looked at the callers to see if that is possible (it may not be). That's an exercise left to the patch author (if he hasn't done that already).
Both appear to work, but after successfully running both the contid test and audit_testsuite, once I start to push that test system a bit harder I end up with a deadlock warning.
I am having trouble understanding why since it happens both without and with the kmem_cache options, so it must be another part of the code that is triggering it. The task_lock is being held at this point in audit_set_contid(). I haven't tried changing this alloc over to a GFP_ATOMIC to see if that prevents it, just as a debugging check...
At this point, I'm inclined to leave it as it was without these two patches since it works and there doesn't seem to be an obvious best way given the uncertainty of the potential workloads.
======================================================
WARNING: possible circular locking dependency detected 5.1.0-rc1-ghak90-audit-containerID.v6.3+ #80 Not tainted
------------------------------------------------------
kswapd0/41 is trying to acquire lock:0000000006a8c88b (&(&p->alloc_lock)->rlock){+.+.}, at: create_task_io_context+0xe9/0x150
but task is already holding lock:0000000010aadb74 (fs_reclaim){+.+.}, at: __fs_reclaim_acquire+0x5/0x40
which lock already depends on the new lock.
the existing dependency chain (in reverse order) is:
-> #1 (fs_reclaim){+.+.}:
__fs_reclaim_acquire+0x2c/0x40
kmem_cache_alloc_trace+0x30/0x230
audit_netns_contid_add.part.12+0xcf/0x210
audit_set_contid+0x18f/0x480
proc_contid_write+0x74/0x110
vfs_write+0xad/0x1b0
ksys_write+0x55/0xc0
do_syscall_64+0x60/0x210
entry_SYSCALL_64_after_hwframe+0x49/0xbe-> #0 (&(&p->alloc_lock)->rlock){+.+.}:
lock_acquire+0xd4/0x1c0
_raw_spin_lock+0x2e/0x40
create_task_io_context+0xe9/0x150
generic_make_request_checks+0x8b4/0x970
generic_make_request+0xbb/0x570
submit_bio+0x6e/0x130
__swap_writepage+0x281/0x420
shmem_writepage+0x1d3/0x350
pageout.isra.54+0x1e9/0x3f0
shrink_page_list+0xa9f/0xe60
shrink_inactive_list+0x263/0x6e0
shrink_node_memcg+0x376/0x7c0
shrink_node+0xdd/0x470
balance_pgdat+0x26c/0x570
kswapd+0x191/0x4f0
kthread+0xf8/0x130
ret_from_fork+0x3a/0x50other info that might help us debug this:
Possible unsafe locking scenario:
CPU0 CPU1
---- ----
lock(fs_reclaim);
lock(&(&p->alloc_lock)->rlock);
lock(fs_reclaim);lock(&(&p->alloc_lock)->rlock);
*** DEADLOCK ***
1 lock held by kswapd0/41:
#0: 0000000010aadb74 (fs_reclaim){+.+.}, at: __fs_reclaim_acquire+0x5/0x40
Quoted 1 line
Quoted 1 line
paul moore
Patch#1:
kernel/audit.c +8 -7
@@ -388,7 +388,7 @@ void audit_netns_contid_add(struct net *net, u64 contid) {struct audit_net *aunet;struct list_head *contid_list; -struct audit_contid *cont; +struct audit_contid *cont, *newcont;if (!net)return ;
@@ -398,18 +398,19 @@ void audit_netns_contid_add(struct net *net, u64 contid)if (!aunet)return ; contid_list = &aunet->contid_list; + newcont =kmalloc (sizeof (struct audit_contid ),GFP_KERNEL );spin_lock (&aunet->contid_list_lock);list_for_each_entry_rcu (cont, contid_list, list)if (cont->id == contid) {refcount_inc (&cont->refcount); +kfree (newcont); goto out; } - cont =kmalloc (sizeof (struct audit_contid ),GFP_ATOMIC ); -if (cont) { -INIT_LIST_HEAD (&cont->list); - cont->id = contid; -refcount_set (&cont->refcount,1 ); -list_add_rcu (&cont->list, contid_list); +if (newcont) { +INIT_LIST_HEAD (&newcont->list); + newcont->id = contid; +refcount_set (&newcont->refcount,1 ); +list_add_rcu (&newcont->list, contid_list); } out:spin_unlock (&aunet->contid_list_lock);
Patch#2:
kernel/audit.c +21 -8
@@ -222,12 +222,16 @@ struct audit_reply { };static struct kmem_cache *audit_task_cache; +static struct kmem_cache *audit_contid_cache;void __init audit_task_init (void ) { audit_task_cache =kmem_cache_create ("audit_task" ,sizeof (struct audit_task_info ),0 ,SLAB_PANIC ,NULL ); + audit_contid_cache =kmem_cache_create ("audit_contid" , +sizeof (struct audit_contid ), +0 ,SLAB_PANIC ,NULL ); }/**
@@ -388,7 +392,7 @@ void audit_netns_contid_add(struct net *net, u64 contid) {struct audit_net *aunet;struct list_head *contid_list; -struct audit_contid *cont; +struct audit_contid *cont, *newcont;if (!net)return ;
@@ -398,23 +402,32 @@ void audit_netns_contid_add(struct net *net, u64 contid)if (!aunet)return ; contid_list = &aunet->contid_list; + newcont =kmem_cache_alloc (audit_contid_cache,GFP_KERNEL );spin_lock (&aunet->contid_list_lock);list_for_each_entry_rcu (cont, contid_list, list)if (cont->id == contid) {refcount_inc (&cont->refcount); +kmem_cache_free (audit_contid_cache, newcont); goto out; } - cont =kmalloc (sizeof (struct audit_contid ),GFP_ATOMIC ); -if (cont) { -INIT_LIST_HEAD (&cont->list); - cont->id = contid; -refcount_set (&cont->refcount,1 ); -list_add_rcu (&cont->list, contid_list); +if (newcont) { +INIT_LIST_HEAD (&newcont->list); + newcont->id = contid; +refcount_set (&newcont->refcount,1 ); +list_add_rcu (&newcont->list, contid_list); } out:spin_unlock (&aunet->contid_list_lock); } +static void audit_contid_free (struct rcu_head *rcu) +{ +struct audit_contid *cont; + + cont = container_of(rcu, struct audit_contid, rcu); +kmem_cache_free (audit_contid_cache, cont); +} +void audit_netns_contid_del (struct net *net,u64 contid) {struct audit_net *aunet;
@@ -434,7 +447,7 @@ void audit_netns_contid_del(struct net *net, u64 contid)if (cont->id == contid) {if (refcount_dec_and_test (&cont->refcount)) {list_del_rcu (&cont->list); -kfree_rcu (cont, rcu); +call_rcu (&cont->rcu, audit_contid_free); }break ; }
- RGB
--
Richard Guy Briggs <[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
maintainerRe: [PATCH ghak90 V5 09/10] audit: add support for containerid to network namespaces
Quoted 31 lines · Richard Guy Briggs
Quoted 30 lines · Neil Horman
Quoted 29 lines · Paul Moore
Quoted 28 lines · Richard Guy Briggs
Audit events could happen in a network namespace outside of a task context due to packets received from the net that trigger an auditing rule prior to being associated with a running task. The network namespace could be in use by multiple containers by association to the tasks in that network namespace. We still want a way to attribute these events to any potential containers. Keep a list per network namespace to track these audit container identifiiers.
Add/increment the audit container identifier on:
- initial setting of the audit container identifier via /proc
- clone/fork call that inherits an audit container identifier
- unshare call that inherits an audit container identifier
- setns call that inherits an audit container identifier Delete/decrement the audit container identifier on:
- an inherited audit container identifier dropped when child set
- process exit
- unshare call that drops a net namespace
- setns call that drops a net namespaceSee: 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-IDSigned-off-by Richard Guy Briggs <[email protected]>--- include/linux/audit.h | 19 ++++++++++++ kernel/audit.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++-- kernel/nsproxy.c | 4 +++ 3 files changed, 106 insertions(+), 3 deletions(-)
...
Quoted 42 lines
Quoted 16 lines
Quoted 7 lines
Review
Quoted 6 lines
(quoted diff) +6
-0+ list_for_each_entry_rcu(cont, contid_list, list) + if (cont->id == contid) { + refcount_inc(&cont->refcount); + goto out; + } + cont = kmalloc(sizeof(struct audit_contid), GFP_ATOMIC);Quoted 9 lines
If you had to guess, what do you think is going to be more common:
bumping the refcount of an existing entry in the list, or adding a new entry? I'm asking because I always get a little nervous when doing allocations while holding a spinlock. Yes, you are doing it withGFP_ATOMIC, but it still seems like something to try and avoid if this is going to approach 50%. However, if the new entry is rare then the extra work of always doing the allocation before taking the lock and then freeing it afterwards might be a bad tradeoff.Quoted 9 lines
I think this is another way of asking, will multiple processes exist in the same network namespace? That is to say, will we expect a process to create a net namespace, and then have other processes enter that namespace (thereby triggering multiple calls to
audit_netns_contid_addwith the same net pointer and cont id). Given that the kubernetes notion of a pod is almost by definition multiple containers sharing a network namespace, I think the answer is that we will be strongly biased towards therefcount_inccase, rather than the kmalloc case. I could be wrong, but I think this is likely already in the optimized order.I had a stab at doing a
GFP_KERNELalloc before the spinlock and releasing it after if it wasn't needed (in Patch#1 below). I also went one step further and converted it tokmem_cache(in Patch#2 below).Quoted 7 lines
Quoted 7 lines
My gut feeling says we might do about as many allocations as refcount bumps, but I could be thinking about this wrong.
Moving the allocation outside the spinlock might also open the door to doing this as
GFP_KERNEL, which is a good thing, but I haven't looked at the callers to see if that is possible (it may not be). That's an exercise left to the patch author (if he hasn't done that already).Both appear to work, but after successfully running both the contid test and
audit_testsuite, once I start to push that test system a bit harder I end up with a deadlock warning.
Quoted 8 lines
I am having trouble understanding why since it happens both without and with the
kmem_cacheoptions, so it must be another part of the code that is triggering it. Thetask_lockis being held at this point inaudit_set_contid(). I haven't tried changing this alloc over to aGFP_ATOMICto see if that prevents it, just as a debugging check...
At this point, I'm inclined to leave it as it was without these two patches since it works and there doesn't seem to be an obvious best way given the uncertainty of the potential workloads.
I'm definitely not a mm expert, but I wonder if you might be able to get this working using GFP_NOFS, but I see just now that they recommend you *not* use GFP_NOFS; even if this did solve the problem, it's probably not the right approach.
I'm okay with leaving it as-is with GFP_ATOMIC. My original response to this was more of a question about optimizing for a given use case, having something that works is far more important.
Signature · 2 lines
paul moore www.paul-moore.com
Re: [PATCH ghak90 V5 09/10] audit: add support for containerid to network namespaces
In reply to Richard Guy BriggsQuoted 147 lines · Richard Guy Briggs
Quoted 120 lines · Neil Horman
Quoted 74 lines · Paul Moore
Quoted 28 lines · Richard Guy Briggs
Audit events could happen in a network namespace outside of a task context due to packets received from the net that trigger an auditing rule prior to being associated with a running task. The network namespace could be in use by multiple containers by association to the tasks in that network namespace. We still want a way to attribute these events to any potential containers. Keep a list per network namespace to track these audit container identifiiers.
Add/increment the audit container identifier on:
- initial setting of the audit container identifier via /proc
- clone/fork call that inherits an audit container identifier
- unshare call that inherits an audit container identifier
- setns call that inherits an audit container identifier Delete/decrement the audit container identifier on:
- an inherited audit container identifier dropped when child set
- process exit
- unshare call that drops a net namespace
- setns call that drops a net namespaceSee: 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-IDSigned-off-by Richard Guy Briggs <[email protected]>--- include/linux/audit.h | 19 ++++++++++++ kernel/audit.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++-- kernel/nsproxy.c | 4 +++ 3 files changed, 106 insertions(+), 3 deletions(-)...
Quoted 42 lines
kernel/audit.c +8
-0@@ -72,6 +72,7 @@#include <linux/freezer.h> #include <linux/pid_namespace.h> #include <net/netns/generic.h> +#include <net/net_namespace.h> #include "audit.h" @@ -99,9 +100,13 @@/** * struct audit_net - audit private network namespace data * @sk: communication socket +* @contid_list: audit container identifier list +* @contid_list_lock audit container identifier list lock */ struct audit_net {struct sock *sk; +struct list_head contid_list; +spinlock_t contid_list_lock; };/** @@ -275,8 +280,11 @@ struct audit_task_info init_struct_audit = {void audit_free (struct task_struct *tsk) {struct audit_task_info *info = tsk->audit; +struct nsproxy *ns = tsk->nsproxy;audit_free_syscall (tsk); +if (ns) +audit_netns_contid_del (ns->net_ns,audit_get_contid (tsk));/* Freeing the audit_task_info struct must be performed after * audit_log_exit() due to need for loginuid and sessionid. */ @@ -376,6 +384,73 @@ static struct sock *audit_get_sk(const struct net *net)return aunet->sk; }Quoted 15 lines
kernel/audit.c static struct sock *audit_get_sk(const struct net *net) · line 396
Quoted 10 lines
kernel/audit.c +10
-0+void audit_netns_contid_add (struct net *net,u64 contid) +{ +struct audit_net *aunet =net_generic (net, audit_net_id); +struct list_head *contid_list = &aunet->contid_list; +struct audit_contid *cont; + +if (!audit_contid_valid (contid)) +return ; +if (!aunet) +return ;We should move the
contid_listassignment below this check, or decide that aunet is always going to valid (?) and get rid of this check completely.I'm not sure why that would be needed. Finding the
net_idlist is an operation of a map relating net namespaces to lists, not contids to lists. We could do it, sure, but since they're unrelated operations, I don't think we experience any slowdowns from doing it this way.Quoted 6 lines
kernel/audit.c static struct sock *audit_get_sk(const struct net *net) · line 398
Quoted 2 lines
kernel/audit.c +2
-0+spin_lock (&aunet->contid_list_lock); +if (!list_empty (contid_list))We don't need the
list_empty()check here do we? I think we can just calllist_for_each_entry_rcu(), yes?This is true, the
list_emptycheck is redundant, and the for loop will fall through if the list is empty.Quoted 7 lines
kernel/audit.c static struct sock *audit_get_sk(const struct net *net) · line 404
Quoted 6 lines
kernel/audit.c +6
-0+list_for_each_entry_rcu (cont, contid_list, list) +if (cont->id == contid) { +refcount_inc (&cont->refcount); + goto out; + } + cont =kmalloc (sizeof (struct audit_contid ),GFP_ATOMIC );Quoted 9 lines
If you had to guess, what do you think is going to be more common:
bumping the refcount of an existing entry in the list, or adding a new entry? I'm asking because I always get a little nervous when doing allocations while holding a spinlock. Yes, you are doing it withGFP_ATOMIC, but it still seems like something to try and avoid if this is going to approach 50%. However, if the new entry is rare then the extra work of always doing the allocation before taking the lock and then freeing it afterwards might be a bad tradeoff.Quoted 9 lines
I think this is another way of asking, will multiple processes exist in the same network namespace? That is to say, will we expect a process to create a net namespace, and then have other processes enter that namespace (thereby triggering multiple calls to
audit_netns_contid_addwith the same net pointer and cont id). Given that the kubernetes notion of a pod is almost by definition multiple containers sharing a network namespace, I think the answer is that we will be strongly biased towards therefcount_inccase, rather than the kmalloc case. I could be wrong, but I think this is likely already in the optimized order.I had a stab at doing a
GFP_KERNELalloc before the spinlock and releasing it after if it wasn't needed (in Patch#1 below). I also went one step further and converted it tokmem_cache(in Patch#2 below).Quoted 7 lines
Quoted 7 lines
My gut feeling says we might do about as many allocations as refcount bumps, but I could be thinking about this wrong.
Moving the allocation outside the spinlock might also open the door to doing this as
GFP_KERNEL, which is a good thing, but I haven't looked at the callers to see if that is possible (it may not be). That's an exercise left to the patch author (if he hasn't done that already).Both appear to work, but after successfully running both the contid test and
audit_testsuite, once I start to push that test system a bit harder I end up with a deadlock warning.
Quoted 9 lines
I am having trouble understanding why since it happens both without and with the
kmem_cacheoptions, so it must be another part of the code that is triggering it. Thetask_lockis being held at this point inaudit_set_contid(). I haven't tried changing this alloc over to aGFP_ATOMICto see if that prevents it, just as a debugging check...
At this point, I'm inclined to leave it as it was without these two patches since it works and there doesn't seem to be an obvious best way given the uncertainty of the potential workloads.
I would agree. The trace below says that, when you use GFP_KERNEL, you are allowing the memory subsystem to block the memory allocating task on memory reclaim operations (effectively to sleep until kswapd reclaims sufficient memory to grant the allocation), but kswapd wants to lock the task that is doing the allocation with task_lock, which the task calling kmalloc(...,GFP_KEREL) already holds, ergo, deadlock.
In short, you can't hold a tasks lock while preforming a sleeping operation involving memory allocation. You either need to use GFP_ATOMIC, or release the tasks lock before allocating memory with GFP_KERNEL. Given the possible race conditions surrounding releasing and re-aquiring the lock, I'm inclined to say just use GFP_ATOMIC
Neil
Quoted 190 lines
======================================================
WARNING: possible circular locking dependency detected 5.1.0-rc1-ghak90-audit-containerID.v6.3+ #80 Not tainted
------------------------------------------------------
kswapd0/41 is trying to acquire lock:0000000006a8c88b(&(&p->alloc_lock)->rlock){+.+.}, at:create_task_io_context+0xe9/0x150but task is already holding lock:
0000000010aadb74(fs_reclaim){+.+.}, at:__fs_reclaim_acquire+0x5/0x40which lock already depends on the new lock.
the existing dependency chain (in reverse order) is:
-> #1 (fs_reclaim){+.+.}:
__fs_reclaim_acquire+0x2c/0x40 kmem_cache_alloc_trace+0x30/0x230 audit_netns_contid_add.part.12+0xcf/0x210 audit_set_contid+0x18f/0x480 proc_contid_write+0x74/0x110 vfs_write+0xad/0x1b0 ksys_write+0x55/0xc0 do_syscall_64+0x60/0x210 entry_SYSCALL_64_after_hwframe+0x49/0xbe-> #0 (&(&p->alloc_lock)->rlock){+.+.}:
lock_acquire+0xd4/0x1c0 _raw_spin_lock+0x2e/0x40 create_task_io_context+0xe9/0x150 generic_make_request_checks+0x8b4/0x970 generic_make_request+0xbb/0x570 submit_bio+0x6e/0x130 __swap_writepage+0x281/0x420 shmem_writepage+0x1d3/0x350 pageout.isra.54+0x1e9/0x3f0 shrink_page_list+0xa9f/0xe60 shrink_inactive_list+0x263/0x6e0 shrink_node_memcg+0x376/0x7c0 shrink_node+0xdd/0x470 balance_pgdat+0x26c/0x570 kswapd+0x191/0x4f0 kthread+0xf8/0x130 ret_from_fork+0x3a/0x50other info that might help us debug this:
Possible unsafe locking scenario:CPU0 CPU1 ---- ---- lock(fs_reclaim); lock(&(&p->alloc_lock)->rlock); lock(fs_reclaim);lock(&(&p->alloc_lock)->rlock);
*** DEADLOCK ***
1 lock held by kswapd0/41:
#0:0000000010aadb74(fs_reclaim){+.+.}, at:__fs_reclaim_acquire+0x5/0x40Quoted 1 line
Quoted 1 line
paul moore
Patch#1:
kernel/audit.c +8
-7@@ -388,7 +388,7 @@ void audit_netns_contid_add(struct net *net, u64 contid) {struct audit_net *aunet;struct list_head *contid_list; -struct audit_contid *cont; +struct audit_contid *cont, *newcont;if (!net)return ;@@ -398,18 +398,19 @@ void audit_netns_contid_add(struct net *net, u64 contid)if (!aunet)return ; contid_list = &aunet->contid_list; + newcont =kmalloc (sizeof (struct audit_contid ),GFP_KERNEL );spin_lock (&aunet->contid_list_lock);list_for_each_entry_rcu (cont, contid_list, list)if (cont->id == contid) {refcount_inc (&cont->refcount); +kfree (newcont); goto out; } - cont =kmalloc (sizeof (struct audit_contid ),GFP_ATOMIC ); -if (cont) { -INIT_LIST_HEAD (&cont->list); - cont->id = contid; -refcount_set (&cont->refcount,1 ); -list_add_rcu (&cont->list, contid_list); +if (newcont) { +INIT_LIST_HEAD (&newcont->list); + newcont->id = contid; +refcount_set (&newcont->refcount,1 ); +list_add_rcu (&newcont->list, contid_list); } out:spin_unlock (&aunet->contid_list_lock);Patch#2:
kernel/audit.c +21
-10@@ -222,12 +222,16 @@ struct audit_reply { };static struct kmem_cache *audit_task_cache; +static struct kmem_cache *audit_contid_cache;void __init audit_task_init (void ) { audit_task_cache =kmem_cache_create ("audit_task" ,sizeof (struct audit_task_info ),0 ,SLAB_PANIC ,NULL ); + audit_contid_cache =kmem_cache_create ("audit_contid" , +sizeof (struct audit_contid ), +0 ,SLAB_PANIC ,NULL ); }/** @@ -388,7 +392,7 @@ void audit_netns_contid_add(struct net *net, u64 contid) {struct audit_net *aunet;struct list_head *contid_list; -struct audit_contid *cont; +struct audit_contid *cont, *newcont;if (!net)return ;@@ -398,23 +402,32 @@ void audit_netns_contid_add(struct net *net, u64 contid)if (!aunet)return ; contid_list = &aunet->contid_list; + newcont =kmem_cache_alloc (audit_contid_cache,GFP_KERNEL );spin_lock (&aunet->contid_list_lock);list_for_each_entry_rcu (cont, contid_list, list)if (cont->id == contid) {refcount_inc (&cont->refcount); +kmem_cache_free (audit_contid_cache, newcont); goto out; } - cont =kmalloc (sizeof (struct audit_contid ),GFP_ATOMIC ); -if (cont) { -INIT_LIST_HEAD (&cont->list); - cont->id = contid; -refcount_set (&cont->refcount,1 ); -list_add_rcu (&cont->list, contid_list); +if (newcont) { +INIT_LIST_HEAD (&newcont->list); + newcont->id = contid; +refcount_set (&newcont->refcount,1 ); +list_add_rcu (&newcont->list, contid_list); } out:spin_unlock (&aunet->contid_list_lock); } +static void audit_contid_free (struct rcu_head *rcu) +{ +struct audit_contid *cont; + + cont = container_of(rcu, struct audit_contid, rcu); +kmem_cache_free (audit_contid_cache, cont); +} +void audit_netns_contid_del (struct net *net,u64 contid) {struct audit_net *aunet;@@ -434,7 +447,7 @@ void audit_netns_contid_del(struct net *net, u64 contid)if (cont->id == contid) {if (refcount_dec_and_test (&cont->refcount)) {list_del_rcu (&cont->list); -kfree_rcu (cont, rcu); +call_rcu (&cont->rcu, audit_contid_free); }break ; } -RGB --Richard Guy Briggs <[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
PATCH v5 10/10 audit: NETFILTER_PKT: record each container ID associated with a netNS
In reply to Richard Guy BriggsAdd audit container identifier auxiliary record(s) to NETFILTER_PKT event standalone records. Iterate through all potential audit container identifiers associated with a network namespace.
--- include/linux/audit.h | 5 +++++ kernel/audit.c | 41 +++++++++++++++++++++++++++++++++++++++++ net/netfilter/nft_log.c | 11 +++++++++-- net/netfilter/xt_AUDIT.c | 11 +++++++++-- 4 files changed, 64 insertions(+), 4 deletions(-)
include/linux/audit.h +5 -0
@@ -214,6 +214,8 @@ static inline u64 audit_get_contid(struct task_struct *tsk)extern void audit_netns_contid_del (struct net *net,u64 contid);extern void audit_switch_task_namespaces (struct nsproxy *ns,struct task_struct *p); +extern void audit_log_netns_contid_list (struct net *net, +struct audit_context *context);extern u32 audit_enabled;#else /* CONFIG_AUDIT */
@@ -290,6 +292,9 @@ static inline void audit_netns_contid_del(struct net *net, u64 contid)static inline void audit_switch_task_namespaces (struct nsproxy *ns,struct task_struct *p) { } +static inline void audit_log_netns_contid_list (struct net *net, +struct audit_context *context) +{ }#define audit_enabled AUDIT_OFF#endif /* CONFIG_AUDIT */
kernel/audit.c +41 -0
47 lines not on this page · raw message
net/netfilter/nft_log.c +9 -2
@@ -69,13 +69,16 @@ static void nft_log_eval_audit(const struct nft_pktinfo *pkt)struct sk_buff *skb = pkt->skb;struct audit_buffer *ab;int fam =-1 ; +struct audit_context *context; +struct net *net;if (!audit_enabled)return ; - ab =audit_log_start (NULL ,GFP_ATOMIC ,AUDIT_NETFILTER_PKT ); + context =audit_alloc_local (GFP_ATOMIC ); + ab =audit_log_start (context,GFP_ATOMIC ,AUDIT_NETFILTER_PKT );if (!ab) -return ; + goto errout;audit_log_format (ab,"mark=%#x" , skb->mark);
@@ -102,6 +105,10 @@ static void nft_log_eval_audit(const struct nft_pktinfo *pkt)audit_log_format (ab," saddr=? daddr=? proto=-1" );audit_log_end (ab); + net =xt_net (&pkt->xt); +audit_log_netns_contid_list (net, context); +errout: +audit_free_context (context); } static void nft_log_eval(const struct nft_expr *expr,
net/netfilter/xt_AUDIT.c +9 -2
@@ -71,10 +71,13 @@ static bool audit_ip6(struct audit_buffer *ab, struct sk_buff *skb) {struct audit_buffer *ab;int fam =-1 ; +struct audit_context *context; +struct net *net;if (audit_enabled ==AUDIT_OFF ) - goto errout; - ab =audit_log_start (NULL ,GFP_ATOMIC ,AUDIT_NETFILTER_PKT ); + goto out; + context =audit_alloc_local (GFP_ATOMIC ); + ab =audit_log_start (context,GFP_ATOMIC ,AUDIT_NETFILTER_PKT );if (ab ==NULL ) goto errout;
@@ -104,7 +107,11 @@ static bool audit_ip6(struct audit_buffer *ab, struct sk_buff *skb)audit_log_end (ab); + net =xt_net (par); +audit_log_netns_contid_list (net, context); errout: +audit_free_context (context); +out:return XT_CONTINUE ; }
Signature · 1 line
1.8.3.1
Re: [PATCH ghak90 V5 10/10] audit: NETFILTER_PKT: record each container ID associated with a netNS
Quoted 3 lines · Richard Guy Briggs
Add audit container identifier auxiliary record(s) to
NETFILTER_PKTevent standalone records. Iterate through all potential audit container identifiers associated with a network namespace.
Ugh, noticed a stray tailing whitespace below...
Quoted 60 lines
Signed-off-by Richard Guy Briggs <[email protected]>--- include/linux/audit.h | 5 +++++ kernel/audit.c | 41 +++++++++++++++++++++++++++++++++++++++++ net/netfilter/nft_log.c | 11 +++++++++-- net/netfilter/xt_AUDIT.c | 11 +++++++++-- 4 files changed, 64 insertions(+), 4 deletions(-)include/linux/audit.h +5
-0@@ -214,6 +214,8 @@ static inline u64 audit_get_contid(struct task_struct *tsk)extern void audit_netns_contid_del (struct net *net,u64 contid);extern void audit_switch_task_namespaces (struct nsproxy *ns,struct task_struct *p); +extern void audit_log_netns_contid_list (struct net *net, +struct audit_context *context);extern u32 audit_enabled;#else /* CONFIG_AUDIT */ @@ -290,6 +292,9 @@ static inline void audit_netns_contid_del(struct net *net, u64 contid)static inline void audit_switch_task_namespaces (struct nsproxy *ns,struct task_struct *p) { } +static inline void audit_log_netns_contid_list (struct net *net, +struct audit_context *context) +{ }#define audit_enabled AUDIT_OFF#endif /* CONFIG_AUDIT */ kernel/audit.c +21
-0@@ -451,6 +451,47 @@ void audit_switch_task_namespaces(struct nsproxy *ns, struct task_struct *p)audit_netns_contid_add (new->net_ns, contid); } +/** +* audit_log_netns_contid_list - List contids for the given network namespace +* @net: the network namespace of interest +* @context: the audit context to use +* +* Description: +* Issues a CONTAINER_ID record with a CSV list of contids associated +* with a network namespace to accompany a NETFILTER_PKT record. +*/ +void audit_log_netns_contid_list (struct net *net,struct audit_context *context) +{ +struct audit_buffer *ab =NULL ; +struct audit_contid *cont; +bool first = true; +struct audit_net *aunet; + +/* Generate AUDIT_CONTAINER_ID record with container ID CSV list */ +rcu_read_lock (); + aunet =net_generic (net, audit_net_id); +if (!aunet) + goto out;
kernel/audit.c void audit_switch_task_namespaces(struct nsproxy *ns, struct task_struct *p) · line 484
Quoted 10 lines
kernel/audit.c +10
-0+list_for_each_entry_rcu (cont, &aunet->contid_list, list) { +if (first) { + ab =audit_log_start (context,GFP_ATOMIC , +AUDIT_CONTAINER_ID ); +if (!ab) { +audit_log_lost ("out of memory in audit_log_netns_contid_list" ); + goto out; + } +audit_log_format (ab,"contid=" ); + }else
Ugh, I just noticed a stray trailing whitespace... That'll get caught by Perches' checkpatch...
Quoted 82 lines
kernel/audit.c +10
-0+audit_log_format (ab,"," ); +audit_log_format (ab,"%llu" , cont->id); + first = false; + } +audit_log_end (ab); +out: +rcu_read_unlock (); +} +EXPORT_SYMBOL (audit_log_netns_contid_list); +void audit_panic (const char *message) {switch (audit_failure) {net/netfilter/nft_log.c +9
-2@@ -69,13 +69,16 @@ static void nft_log_eval_audit(const struct nft_pktinfo *pkt)struct sk_buff *skb = pkt->skb;struct audit_buffer *ab;int fam =-1 ; +struct audit_context *context; +struct net *net;if (!audit_enabled)return ; - ab =audit_log_start (NULL ,GFP_ATOMIC ,AUDIT_NETFILTER_PKT ); + context =audit_alloc_local (GFP_ATOMIC ); + ab =audit_log_start (context,GFP_ATOMIC ,AUDIT_NETFILTER_PKT );if (!ab) -return ; + goto errout;audit_log_format (ab,"mark=%#x" , skb->mark);@@ -102,6 +105,10 @@ static void nft_log_eval_audit(const struct nft_pktinfo *pkt)audit_log_format (ab," saddr=? daddr=? proto=-1" );audit_log_end (ab); + net =xt_net (&pkt->xt); +audit_log_netns_contid_list (net, context); +errout: +audit_free_context (context); } static void nft_log_eval(const struct nft_expr *expr,net/netfilter/xt_AUDIT.c +9
-2@@ -71,10 +71,13 @@ static bool audit_ip6(struct audit_buffer *ab, struct sk_buff *skb) {struct audit_buffer *ab;int fam =-1 ; +struct audit_context *context; +struct net *net;if (audit_enabled ==AUDIT_OFF ) - goto errout; - ab =audit_log_start (NULL ,GFP_ATOMIC ,AUDIT_NETFILTER_PKT ); + goto out; + context =audit_alloc_local (GFP_ATOMIC ); + ab =audit_log_start (context,GFP_ATOMIC ,AUDIT_NETFILTER_PKT );if (ab ==NULL ) goto errout;@@ -104,7 +107,11 @@ static bool audit_ip6(struct audit_buffer *ab, struct sk_buff *skb)audit_log_end (ab); + net =xt_net (par); +audit_log_netns_contid_list (net, context); errout: +audit_free_context (context); +out:return XT_CONTINUE ; }Signature · 1 line
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
Re: [PATCH ghak90 V5 10/10] audit: NETFILTER_PKT: record each container ID associated with a netNS
In reply to Richard Guy BriggsQuoted 157 lines · Richard Guy Briggs
Add audit container identifier auxiliary record(s) to
NETFILTER_PKTevent 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 | 41 +++++++++++++++++++++++++++++++++++++++++ net/netfilter/nft_log.c | 11 +++++++++-- net/netfilter/xt_AUDIT.c | 11 +++++++++-- 4 files changed, 64 insertions(+), 4 deletions(-)include/linux/audit.h +5
-0@@ -214,6 +214,8 @@ static inline u64 audit_get_contid(struct task_struct *tsk)extern void audit_netns_contid_del (struct net *net,u64 contid);extern void audit_switch_task_namespaces (struct nsproxy *ns,struct task_struct *p); +extern void audit_log_netns_contid_list (struct net *net, +struct audit_context *context);extern u32 audit_enabled;#else /* CONFIG_AUDIT */ @@ -290,6 +292,9 @@ static inline void audit_netns_contid_del(struct net *net, u64 contid)static inline void audit_switch_task_namespaces (struct nsproxy *ns,struct task_struct *p) { } +static inline void audit_log_netns_contid_list (struct net *net, +struct audit_context *context) +{ }#define audit_enabled AUDIT_OFF#endif /* CONFIG_AUDIT */ kernel/audit.c +41
-0@@ -451,6 +451,47 @@ void audit_switch_task_namespaces(struct nsproxy *ns, struct task_struct *p)audit_netns_contid_add (new->net_ns, contid); } +/** +* audit_log_netns_contid_list - List contids for the given network namespace +* @net: the network namespace of interest +* @context: the audit context to use +* +* Description: +* Issues a CONTAINER_ID record with a CSV list of contids associated +* with a network namespace to accompany a NETFILTER_PKT record. +*/ +void audit_log_netns_contid_list (struct net *net,struct audit_context *context) +{ +struct audit_buffer *ab =NULL ; +struct audit_contid *cont; +bool first = true; +struct audit_net *aunet; + +/* Generate AUDIT_CONTAINER_ID record with container ID CSV list */ +rcu_read_lock (); + aunet =net_generic (net, audit_net_id); +if (!aunet) + goto out; +list_for_each_entry_rcu (cont, &aunet->contid_list, list) { +if (first) { + ab =audit_log_start (context,GFP_ATOMIC , +AUDIT_CONTAINER_ID ); +if (!ab) { +audit_log_lost ("out of memory in audit_log_netns_contid_list" ); + goto out; + } +audit_log_format (ab,"contid=" ); + }else +audit_log_format (ab,"," ); +audit_log_format (ab,"%llu" , cont->id); + first = false; + } +audit_log_end (ab); +out: +rcu_read_unlock (); +} +EXPORT_SYMBOL (audit_log_netns_contid_list); +void audit_panic (const char *message) {switch (audit_failure) {net/netfilter/nft_log.c +9
-2@@ -69,13 +69,16 @@ static void nft_log_eval_audit(const struct nft_pktinfo *pkt)struct sk_buff *skb = pkt->skb;struct audit_buffer *ab;int fam =-1 ; +struct audit_context *context; +struct net *net;if (!audit_enabled)return ; - ab =audit_log_start (NULL ,GFP_ATOMIC ,AUDIT_NETFILTER_PKT ); + context =audit_alloc_local (GFP_ATOMIC ); + ab =audit_log_start (context,GFP_ATOMIC ,AUDIT_NETFILTER_PKT );if (!ab) -return ; + goto errout;audit_log_format (ab,"mark=%#x" , skb->mark);@@ -102,6 +105,10 @@ static void nft_log_eval_audit(const struct nft_pktinfo *pkt)audit_log_format (ab," saddr=? daddr=? proto=-1" );audit_log_end (ab); + net =xt_net (&pkt->xt); +audit_log_netns_contid_list (net, context); +errout: +audit_free_context (context); } static void nft_log_eval(const struct nft_expr *expr,net/netfilter/xt_AUDIT.c +9
-2@@ -71,10 +71,13 @@ static bool audit_ip6(struct audit_buffer *ab, struct sk_buff *skb) {struct audit_buffer *ab;int fam =-1 ; +struct audit_context *context; +struct net *net;if (audit_enabled ==AUDIT_OFF ) - goto errout; - ab =audit_log_start (NULL ,GFP_ATOMIC ,AUDIT_NETFILTER_PKT ); + goto out; + context =audit_alloc_local (GFP_ATOMIC ); + ab =audit_log_start (context,GFP_ATOMIC ,AUDIT_NETFILTER_PKT );if (ab ==NULL ) goto errout;@@ -104,7 +107,11 @@ static bool audit_ip6(struct audit_buffer *ab, struct sk_buff *skb)audit_log_end (ab); + net =xt_net (par); +audit_log_netns_contid_list (net, context); errout: +audit_free_context (context); +out:return XT_CONTINUE ; }Signature · 1 line
1.8.3.1
minus the whitespace fix
Re: [PATCH ghak90 V5 10/10] audit: NETFILTER_PKT: record each container ID associated with a netNS
In reply to Richard Guy BriggsQuoted 5 lines · Richard Guy Briggs
Add audit container identifier auxiliary record(s) to
NETFILTER_PKTevent standalone records. Iterate through all potential audit container identifiers associated with a network namespace.Signed-off-by Richard Guy Briggs <[email protected]>
(Just note another "%llu"/u64 occurence, in case you plan to add the casts.)
Quoted 151 lines
--- include/linux/audit.h | 5 +++++ kernel/audit.c | 41 +++++++++++++++++++++++++++++++++++++++++ net/netfilter/nft_log.c | 11 +++++++++-- net/netfilter/xt_AUDIT.c | 11 +++++++++-- 4 files changed, 64 insertions(+), 4 deletions(-)include/linux/audit.h +5
-0@@ -214,6 +214,8 @@ static inline u64 audit_get_contid(struct task_struct *tsk)extern void audit_netns_contid_del (struct net *net,u64 contid);extern void audit_switch_task_namespaces (struct nsproxy *ns,struct task_struct *p); +extern void audit_log_netns_contid_list (struct net *net, +struct audit_context *context);extern u32 audit_enabled;#else /* CONFIG_AUDIT */ @@ -290,6 +292,9 @@ static inline void audit_netns_contid_del(struct net *net, u64 contid)static inline void audit_switch_task_namespaces (struct nsproxy *ns,struct task_struct *p) { } +static inline void audit_log_netns_contid_list (struct net *net, +struct audit_context *context) +{ }#define audit_enabled AUDIT_OFF#endif /* CONFIG_AUDIT */ kernel/audit.c +41
-0@@ -451,6 +451,47 @@ void audit_switch_task_namespaces(struct nsproxy *ns, struct task_struct *p)audit_netns_contid_add (new->net_ns, contid); } +/** +* audit_log_netns_contid_list - List contids for the given network namespace +* @net: the network namespace of interest +* @context: the audit context to use +* +* Description: +* Issues a CONTAINER_ID record with a CSV list of contids associated +* with a network namespace to accompany a NETFILTER_PKT record. +*/ +void audit_log_netns_contid_list (struct net *net,struct audit_context *context) +{ +struct audit_buffer *ab =NULL ; +struct audit_contid *cont; +bool first = true; +struct audit_net *aunet; + +/* Generate AUDIT_CONTAINER_ID record with container ID CSV list */ +rcu_read_lock (); + aunet =net_generic (net, audit_net_id); +if (!aunet) + goto out; +list_for_each_entry_rcu (cont, &aunet->contid_list, list) { +if (first) { + ab =audit_log_start (context,GFP_ATOMIC , +AUDIT_CONTAINER_ID ); +if (!ab) { +audit_log_lost ("out of memory in audit_log_netns_contid_list" ); + goto out; + } +audit_log_format (ab,"contid=" ); + }else +audit_log_format (ab,"," ); +audit_log_format (ab,"%llu" , cont->id); + first = false; + } +audit_log_end (ab); +out: +rcu_read_unlock (); +} +EXPORT_SYMBOL (audit_log_netns_contid_list); +void audit_panic (const char *message) {switch (audit_failure) {net/netfilter/nft_log.c +9
-2@@ -69,13 +69,16 @@ static void nft_log_eval_audit(const struct nft_pktinfo *pkt)struct sk_buff *skb = pkt->skb;struct audit_buffer *ab;int fam =-1 ; +struct audit_context *context; +struct net *net;if (!audit_enabled)return ; - ab =audit_log_start (NULL ,GFP_ATOMIC ,AUDIT_NETFILTER_PKT ); + context =audit_alloc_local (GFP_ATOMIC ); + ab =audit_log_start (context,GFP_ATOMIC ,AUDIT_NETFILTER_PKT );if (!ab) -return ; + goto errout;audit_log_format (ab,"mark=%#x" , skb->mark);@@ -102,6 +105,10 @@ static void nft_log_eval_audit(const struct nft_pktinfo *pkt)audit_log_format (ab," saddr=? daddr=? proto=-1" );audit_log_end (ab); + net =xt_net (&pkt->xt); +audit_log_netns_contid_list (net, context); +errout: +audit_free_context (context); } static void nft_log_eval(const struct nft_expr *expr,net/netfilter/xt_AUDIT.c +9
-3@@ -71,10 +71,13 @@ static bool audit_ip6(struct audit_buffer *ab, struct sk_buff *skb) {struct audit_buffer *ab;int fam =-1 ; +struct audit_context *context; +struct net *net;if (audit_enabled ==AUDIT_OFF ) - goto errout; - ab =audit_log_start (NULL ,GFP_ATOMIC ,AUDIT_NETFILTER_PKT ); + goto out; + context =audit_alloc_local (GFP_ATOMIC ); + ab =audit_log_start (context,GFP_ATOMIC ,AUDIT_NETFILTER_PKT );if (ab ==NULL ) goto errout;@@ -104,7 +107,11 @@ static bool audit_ip6(struct audit_buffer *ab, struct sk_buff *skb)audit_log_end (ab); + net =xt_net (par); +audit_log_netns_contid_list (net, context); errout: +audit_free_context (context); +out:return XT_CONTINUE ; } --1.8.3.1
Signature · 3 lines
Ondrej Mosnacek <omosnace at redhat dot com> Software Engineer, Security Technologies Red Hat, Inc.
Paul Moore
maintainerRe: [PATCH ghak90 V5 10/10] audit: NETFILTER_PKT: record each container ID associated with a netNS
In reply to Richard Guy BriggsQuoted 11 lines · Richard Guy Briggs
Add audit container identifier auxiliary record(s) to
NETFILTER_PKTevent 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 | 41 +++++++++++++++++++++++++++++++++++++++++ net/netfilter/nft_log.c | 11 +++++++++-- net/netfilter/xt_AUDIT.c | 11 +++++++++-- 4 files changed, 64 insertions(+), 4 deletions(-)
...
Quoted 21 lines
kernel/audit.c +13
-0@@ -451,6 +451,47 @@ void audit_switch_task_namespaces(struct nsproxy *ns, struct task_struct *p)audit_netns_contid_add (new->net_ns, contid); } +/** +* audit_log_netns_contid_list - List contids for the given network namespace +* @net: the network namespace of interest +* @context: the audit context to use +* +* Description: +* Issues a CONTAINER_ID record with a CSV list of contids associated +* with a network namespace to accompany a NETFILTER_PKT record. +*/ +void audit_log_netns_contid_list (struct net *net,struct audit_context *context) +{ +struct audit_buffer *ab =NULL ; +struct audit_contid *cont;
kernel/audit.c void audit_switch_task_namespaces(struct nsproxy *ns, struct task_struct *p) · line 476
Quoted 10 lines
kernel/audit.c +10
-0+bool first = true; +struct audit_net *aunet; + +/* Generate AUDIT_CONTAINER_ID record with container ID CSV list */ +rcu_read_lock (); + aunet =net_generic (net, audit_net_id); +if (!aunet) + goto out; +list_for_each_entry_rcu (cont, &aunet->contid_list, list) { +if (first) {
This is borderline nit-picky, but it seems like we could get rid of "first" and just check to see if "ab" is still NULL.
Quoted 17 lines
kernel/audit.c +17
-0+ ab =audit_log_start (context,GFP_ATOMIC , +AUDIT_CONTAINER_ID ); +if (!ab) { +audit_log_lost ("out of memory in audit_log_netns_contid_list" ); + goto out; + } +audit_log_format (ab,"contid=" ); + }else +audit_log_format (ab,"," ); +audit_log_format (ab,"%llu" , cont->id); + first = false; + } +audit_log_end (ab); +out: +rcu_read_unlock (); +} +EXPORT_SYMBOL (audit_log_netns_contid_list);
Signature · 2 lines
paul moore www.paul-moore.com
Re: [PATCH ghak90 V5 10/10] audit: NETFILTER_PKT: record each container ID associated with a netNS
Quoted 41 lines · Paul Moore
Quoted 11 lines · Richard Guy Briggs
Add audit container identifier auxiliary record(s) to
NETFILTER_PKTevent 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 | 41 +++++++++++++++++++++++++++++++++++++++++ net/netfilter/nft_log.c | 11 +++++++++-- net/netfilter/xt_AUDIT.c | 11 +++++++++-- 4 files changed, 64 insertions(+), 4 deletions(-)...
Quoted 26 lines
kernel/audit.c +18
-0@@ -451,6 +451,47 @@ void audit_switch_task_namespaces(struct nsproxy *ns, struct task_struct *p)audit_netns_contid_add (new->net_ns, contid); } +/** +* audit_log_netns_contid_list - List contids for the given network namespace +* @net: the network namespace of interest +* @context: the audit context to use +* +* Description: +* Issues a CONTAINER_ID record with a CSV list of contids associated +* with a network namespace to accompany a NETFILTER_PKT record. +*/ +void audit_log_netns_contid_list (struct net *net,struct audit_context *context) +{ +struct audit_buffer *ab =NULL ; +struct audit_contid *cont; +bool first = true; +struct audit_net *aunet; + +/* Generate AUDIT_CONTAINER_ID record with container ID CSV list */ +rcu_read_lock ();
Quoted 8 lines
kernel/audit.c void audit_switch_task_namespaces(struct nsproxy *ns, struct task_struct *p) · line 476
Quoted 5 lines
kernel/audit.c +5
-0+ aunet =net_generic (net, audit_net_id); +if (!aunet) + goto out; +list_for_each_entry_rcu (cont, &aunet->contid_list, list) { +if (first) {This is borderline nit-picky, but it seems like we could get rid of "first" and just check to see if "ab" is still NULL.
Yes, this is a better way, thank you.
Quoted 11 lines
Quoted 11 lines
kernel/audit.c +11
-0+ ab =audit_log_start (context,GFP_ATOMIC , +AUDIT_CONTAINER_ID ); +if (!ab) { +audit_log_lost ("out of memory in audit_log_netns_contid_list" ); + goto out; + } +audit_log_format (ab,"contid=" ); + }else +audit_log_format (ab,"," ); +audit_log_format (ab,"%llu" , cont->id); + first = false;
Quoted 8 lines
kernel/audit.c void audit_switch_task_namespaces(struct nsproxy *ns, struct task_struct *p) · line 493
Quoted 6 lines
kernel/audit.c +6
-0+ } +audit_log_end (ab); +out: +rcu_read_unlock (); +} +EXPORT_SYMBOL (audit_log_netns_contid_list);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
Quoted 20 lines · Richard Guy Briggs
Implement kernel audit container identifier.
This patchset is a fifth based on the proposal document (V3) posted:
https://www.redhat.com/archives/linux-audit/2018-January/msg00014.htmlThe first patch was the last patch from ghak81 that was absorbed into this patchset since its primary justification is the rest of this patchset.
The second patch implements the proc fs write to set the audit container identifier of a process, emitting an
AUDIT_CONTAINER_OPrecord to announce the registration of that audit container identifier on that process. This patch requires userspace support for record acceptance and proper type display.The third implements reading the audit container identifier from the proc filesystem for debugging. This patch wasn't planned for upstream inclusion but is starting to become more likely.
Quoted 8 lines
The fourth implements the auxiliary record
AUDIT_CONTAINERif an audit container identifier is associated with an event. This patch requires userspace support for proper type display.The 5th adds signal and ptrace support.
The 6th creates a local audit context to be able to bind a standalone record with a locally created auxiliary record.
Paul, we had discussed this briefly previously... Adding an auxiliary record to *any* audit event when CONFIG_AUDITSYSCALL is *not* enabled will cause those records to be detached and not associated as one event. Currently, CONFIG_AUDITSYSCALL is automatically enabled when CONFIG_AUDIT is enabled on any architecture that supports syscall auditing so the only time this is an issue is on an architecture that does not support syscall auditing. This is a known bug/tradeoff in architectures that don't support syscall auditing with audit container identifier records only at this point.
This affects the AUDIT_CONTAINER_ID record associated with AUDIT_NETFILTER_PKT, AUDIT_*USER* records and any other records that are issued regardless of the state of the audit syscall rules (AVCs, ANOM_*, etc...)
I had this contid patchset ready to post a couple of weeks ago, but I started investigating separating out the concept of an audit event from the audit context due to the issue raised above. The only thing required to tie records together in an event is the mesage timestamp and message serial number. The rest of the context is unnecessary.
This should not be necessary if audit events and syscall context are separated. I've been working on a patchset which was experimental looking to see if it would work. It is working so that contid is no longer dependant on audit syscall auditing, but the patches need a bit of cleanup to be presentable. This would solve the problem for architectures that don't support syscall auditing. This wasn't the motivation for doing this work, but more the desire to separate the concepts of audit events from audit context. audit_log_start() doesn't need audit context information, but only minimal audit event information. The very small hitch I've run into was how to define the start of an event. This is taken care of explicitly in AUDIT_*USER* and AUDIT_NETFILTER_PKT events by a local context/event allocation. It is taken care of in the syscall case in the call to __audit_syscall_entry(), but when auditing is not enabled for a task and an unconditional record such as AUDIT_AVC is issued, we still want the event information present. The timestamp function call of __audit_syscall_entry() could be moved to audit_syscall_entry() or another lighter function such as audit_event_entry() in kernel/audit.c to take care of only the event parameters and not context.
I acknowledge it was a risk to dive into it without explicit conversations and work items to proceed with it. I like the results, but I'd be curious what your outlook are on this general idea and approach. Hard to say, I know, without seeing actual code, but I'll keep poking at it. I like it because it finally makes a clear distinction between events and syscalls, which hasn't been much of a technical, and only a conceptual issue up until now.
Quoted 179 lines
The 7th patch adds audit container identifier records to the user standalone records.
The 8th adds audit container identifier filtering to the exit, exclude and user lists. This patch adds the
AUDIT_CONTIDfield and requires auditctl userspace support for the --contid option.The 9th adds network namespace audit container identifier labelling based on member tasks' audit container identifier labels.
The 10th adds audit container identifier support to standalone netfilter records that don't have a task context and lists each container to which that net namespace belongs.
Example: Set an audit container identifier of 123456 to the "sleep" task:
sleep 2&
child=$!
echo 123456 >/proc/$child/audit_containerid; echo $? ausearch -ts recent -mcontainer_op
echo child:$child contid:$( cat/proc/$child/audit_containerid)This should produce a record such as:
type=CONTAINER_OP msg=audit(2018-06-06 12:39:29.636:26949) : op=set opid=2209 old-contid=18446744073709551615 contid=123456 pid=628 auid=root uid=root tty=ttyS0 ses=1 subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 comm=bash exe=/usr/bin/bash res=yes
Example: Set a filter on an audit container identifier 123459 on
/tmp/tmpcontainerid:contid=123459
key=tmpcontainerid
auditctl -a exit,always -F dir=/tmp -F perm=wa -F contid=$contid -F key=$key perl -e "sleep 1;open(my \$tmpfile, '>', \"/tmp/$key\"); close(\$tmpfile);" & child=$!
echo $contid >/proc/$child/audit_containerid
sleep 2
ausearch -i -ts recent -k $key
auditctl -d exit,always -F dir=/tmp -F perm=wa -F contid=$contid -F key=$key rm -f/tmp/$keyThis should produce an event such as:
type=CONTAINER_ID msg=audit(2018-06-06 12:46:31.707:26953) : contid=123459 type=PROCTITLE msg=audit(2018-06-06 12:46:31.707:26953) : proctitle=perl -e sleep 1; open(my $tmpfile, '>', "/tmp/tmpcontainerid"); close($tmpfile); type=PATH msg=audit(2018-06-06 12:46:31.707:26953) : item=1 name=/tmp/tmpcontainerid inode=25656 dev=00:26 mode=file,644 ouid=root ogid=root rdev=00:00 obj=unconfined_u:object_r:user_tmp_t:s0 nametype=CREATE cap_fp=none cap_fi=none cap_fe=0 cap_fver=0 type=PATH msg=audit(2018-06-06 12:46:31.707:26953) : item=0 name=/tmp/ inode=8985 dev=00:26 mode=dir,sticky,777 ouid=root ogid=root rdev=00:00 obj=system_u:object_r:tmp_t:s0 nametype=PARENT cap_fp=none cap_fi=none cap_fe=0 cap_fver=0 type=CWD msg=audit(2018-06-06 12:46:31.707:26953) : cwd=/root type=SYSCALL msg=audit(2018-06-06 12:46:31.707:26953) : arch=x86_64 syscall=openat success=yes exit=3 a0=0xffffffffffffff9c a1=0x5621f2b81900 a2=O_WRONLY|O_CREAT|O_TRUNC a3=0x1b6 items=2 ppid=628 pid=2232 auid=root uid=root gid=root euid=root suid=root fsuid=root egid=root sgid=root fsgid=root tty=ttyS0 ses=1 comm=perl exe=/usr/bin/perl subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 key=tmpcontaineridExample: Test multiple containers on one netns:
sleep 5 & child1=$! containerid1=123451 echo $containerid1 > /proc/$child1/audit_containerid sleep 5 & child2=$! containerid2=123452 echo $containerid2 > /proc/$child2/audit_containerid iptables -I INPUT -i lo -p icmp --icmp-type echo-request -j AUDIT --type accept iptables -I INPUT -t mangle -i lo -p icmp --icmp-type echo-request -j MARK --set-mark 0x12345555 sleep 1; bash -c "ping -q -c 1 127.0.0.1 >/dev/null 2>&1" sleep 1; ausearch -i -m NETFILTER_PKT -ts boot|grep mark=0x12345555 ausearch -i -m NETFILTER_PKT -ts boot|grep contid=|grep $containerid1|grep $containerid2This should produce an event such as:
type=NETFILTER_PKT msg=audit(03/15/2019 14:16:13.369:244) : mark=0x12345555 saddr=127.0.0.1 daddr=127.0.0.1 proto=icmp type=CONTAINER_ID msg=audit(03/15/2019 14:16:13.369:244) : contid=123452,123451
Includes the last patch of https://github.com/linux-audit/audit-kernel/issues/81
See the github issue for the kernel code https://github.com/linux-audit/audit-kernel/issues/90
See: https://github.com/linux-audit/audit-userspace/issues/40
See: https://github.com/linux-audit/audit-testsuite/issues/64
See: https://github.com/linux-audit/audit-kernel/wiki/RFE-Audit-Container-IDChangelog:
v5
- address loginuid and sessionid syscall scope in ghak104
- addressaudit_contextinCONFIG_AUDITvsCONFIG_AUDITSYSCALLin ghak105
- remove tty patch, addressed in ghak106
- rebase on audit/next v5.0-rc1 w/ghak59/ghak104/ghak103/ghak100/ghak107/ghak105/ghak106/ghak105sup
- updateCONTAINER_IDtoCONTAINER_OPin patch description
- moveaudit_contextinaudit_task_infotoCONFIG_AUDITSYSCALL
- moveaudit_alloc()andaudit_free()out ofCONFIG_AUDITSYSCALLand intoCONFIG_AUDITand create audit_{alloc,free}_syscall
- use plainkmem_cache_alloc()rather thankmem_cache_zalloc()inaudit_alloc()
- fixaudit_get_contid()declaration type error
- moveaudit_set_contid()fromauditsc.ctoaudit.c
-audit_log_contid()returns void
-audit_log_contid()handed contid rather than tsk
- switch fromAUDIT_CONTAINERtoAUDIT_CONTAINER_IDfor aux record
- moveaudit_log_contid(tsk/contid)& audit_contid_set(tsk)/audit_contid_valid(contid)
- switch from tsk to current
-audit_alloc_local()callsaudit_log_lost()on failure to allocate a context
- add AUDIT_USER* non-syscall contid record
- cosmetic cleanup double parens, goto out on err
- ditchaudit_get_ns_contid_list_lock(), fix aunet lock race
- switch from all-cpu read spinlock to rcu, keep spinlock for write
- updateaudit_alloc_local()to usektime_get_coarse_real_ts64()
- addnft_logsupport
- add call fromdo_exit()inaudit_free()to remove contid from netns
- relegateAUDIT_CONTAINERref= field (was op=) to debug patchv4
- preface set with ghak81:"collect audit task parameters"
- add shallyn and sgrubb acks
- rename feature bitmap macro
- renamecid_valid()toaudit_contid_valid()
- renameAUDIT_CONTAINER_IDtoAUDIT_CONTAINER_OP
- deleteaudit_get_contid_list()from headers
- move work into inner if, delete "found"
- change netns contid list function names
- move exports foraudit_log_contidaudit_alloc_localaudit_free_contextto non-syscall patch
- list contids CSV
- pass in gfp flags toaudit_alloc_local()(fixaudit_alloc_contextcallers)
- use "local" in lieu of abusingin_syscallforauditsc_get_stamp()
-read_lock(&tasklist_lock)around children and thread check
-task_lock(tsk)should be taken before first check oftsk->audit
- add spin lock to contid list in aunet
- restrict /proc read toCAP_AUDIT_CONTROL
- remove set again prohibition and inherited flag
- delete contidion spelling fix from patchset, send to netdev/linux-wirelessv3
- switched from containerid intask_structtoaudit_task_info(depends on ghak81)
- dropINVALID_CIDin favour of onlyAUDIT_CID_UNSET
- check for !audit_task_info, throw-ENOPROTOOPTon set
- changed-EPERMto-EEXISTfor parent check
- returnAUDIT_CID_UNSETif !audit_enabled
- squash child/thread check patch intoAUDIT_CONTAINER_IDpatch
- changed-EPERMto-EBUSYfor child check
- separate child and thread checks, use-EALREADYfor latter
- move addition of op= from ptrace/signal patch toAUDIT_CONTAINERpatch
- fix && to || bashism in ptrace/signal patch
- uninline and export function foraudit_free_context()
- dropCONFIG_CHANGE,FEATURE_CHANGE,ANOM_ABEND,ANOM_SECCOMPpatches
- moveaudit_enabledcheck (xt_AUDIT)
- switched from containerid list in struct net to net_generic's structaudit_net
- move containerid list iteration into audit (xt_AUDIT)
- create function to move namespace switch into audit
- switched/proc/PID/entry from containerid toaudit_containerid
- call kzalloc withGFP_ATOMIConin_atomic()inaudit_alloc_context()
- call kzalloc withGFP_ATOMIConin_atomic()inaudit_log_container_info()
- usext_net(par)instead ofsock_net(skb->sk)to get net
- switched record and field names: initialCONTAINER_ID, aux CONTAINER, field CONTID
- allow to set own contid
- open codeaudit_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 innet/rfkill/core.cto avoid contid name collisionv2
- add check for children and threads
- add network namespace container identifier list
- addNETFILTER_PKTaudit container identifier logging
- patch description and documentation clean-up and example
- reap unused ppidRichard Guy Briggs (10):
audit: collect audit task parameters
audit: add container id
audit: read container ID of a process
audit: log container info of syscalls
audit: add containerid support for ptrace and signals
audit: add support for non-syscall auxiliary records
audit: add containerid support for user records
audit: add containerid filtering
audit: add support for containerid to network namespaces
audit:NETFILTER_PKT: record each container ID associated with a netNS
Quoted 23 lines
fs/proc/base.c | 55 +++++++++ include/linux/audit.h | 107 +++++++++++++--- include/linux/sched.h | 7 +- include/uapi/linux/audit.h | 8 +- init/init_task.c | 3 +- init/main.c | 2 + kernel/audit.c | 300 +++++++++++++++++++++++++++++++++++++++++++-- kernel/audit.h | 9 ++ kernel/auditfilter.c | 47 +++++++ kernel/auditsc.c | 89 ++++++++++---- kernel/fork.c | 1 - kernel/nsproxy.c | 4 + net/netfilter/nft_log.c | 11 +- net/netfilter/xt_AUDIT.c | 11 +- 14 files changed, 592 insertions(+), 62 deletions(-)Signature · 6 lines
1.8.3.1 -- 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