Re: [PATCH V6 05/10] audit: log creation and deletion of namespace instances
On 15/05/16, Paul Moore wrote: > On Sat, May 16, 2015 at 10:46 AM, Eric W. Biederman > wrote: > > Paul Moore writes: > >> On Sat, May 16, 2015 at 5:46 AM, Daniel J Walsh wrote: > >>> On 05/15/2015 05:05 PM, Paul Moore wrote: > >>>> On Thursday, May 14, 2015 11:23:09 PM Andy Lutomirski wrote: > >>>>> On Thu, May 14, 2015 at 7:32 PM, Richard Guy Briggs > >>>>> wrote: > >>>>>> On 15/05/14, Paul Moore wrote: > >>>>>>> * Look at our existing audit records to determine which records should > >>>>>>> have > >>>>>>> namespace and container ID tokens added. We may only want to add the > >>>>>>> additional fields in the case where the namespace/container ID tokens > >>>>>>> are > >>>>>>> not the init namespace. > >>>>>> If we have a record that ties a set of namespace IDs with a container > >>>>>> ID, then I expect we only need to list the containerID along with auid > >>>>>> and sessionID. > >>>>> The problem here is that the kernel has no concept of a "container", > >>>>> and I > >>>>> don't think it makes any sense to add one just for audit. "Container" > >>>>> is a > >>>>> marketing term used by some userspace tools. > >>>>> > >>>>> I can imagine that both audit could benefit from a concept of a > >>>>> namespace *path* that understands nesting (e.g. root/2/5/1 or > >>>>> something along those lines). Mapping these to "containers" belongs > >>>>> in userspace, I think. > >>>> It might be helpful to climb up a few levels in this thread ... > >>>> > >>>> I think we all agree that containers are not a kernel construct. I > >>>> further > >>>> believe that the kernel has no business generating container IDs, those > >>>> should > >>>> come from userspace and will likely be different depending on how you > >>>> define > >>>> "container". However, what is less clear to me at this point is how the > >>>> kernel should handle the setting, reporting, and general management of > >>>> this > >>>> container ID token. > >>>> > >>> Wouldn't the easiest thing be to just treat add a containerid to the > >>> process context like auid. > >> > >> I believe so. At least that was the point I was trying to get across > >> when I first jumped into this thread. > > > > It sounds nice but containers are not just a per process construct. > > Sometimes you might know anamespace but not which process instigated > > action to happen on that namespace. > > >From an auditing perspective I'm not sure we will ever hit those > cases; did you have a particular example in mind? The example that immediately came to mind when I first read Eric's comment was a packet coming in off a network in a particular network namespace. That could narrow it down to a subset of containers based on which network namespace it inhabits, but since it isn't associated with a particular task yet (other than a kernel thread) it will not be possible to select the precise nsproxy, let alone the container. > paul moore - RGB -- Richard Guy Briggs Senior Software Engineer, Kernel Security, AMER ENG Base Operating Systems, Red Hat Remote, Ottawa, Canada Voice: +1.647.777.2635, Internal: (81) 32635, Alt: +1.613.693.0684x3545 -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH V6 05/10] audit: log creation and deletion of namespace instances
Log the creation and deletion of namespace instances in all 6 types of namespaces. Twelve new audit message types have been introduced: AUDIT_NS_INIT_MNT 1330/* Record mount namespace instance creation */ AUDIT_NS_INIT_UTS 1331/* Record UTS namespace instance creation */ AUDIT_NS_INIT_IPC 1332/* Record IPC namespace instance creation */ AUDIT_NS_INIT_USER 1333/* Record USER namespace instance creation */ AUDIT_NS_INIT_PID 1334/* Record PID namespace instance creation */ AUDIT_NS_INIT_NET 1335/* Record NET namespace instance creation */ AUDIT_NS_DEL_MNT1336/* Record mount namespace instance deletion */ AUDIT_NS_DEL_UTS1337/* Record UTS namespace instance deletion */ AUDIT_NS_DEL_IPC1338/* Record IPC namespace instance deletion */ AUDIT_NS_DEL_USER 1339/* Record USER namespace instance deletion */ AUDIT_NS_DEL_PID1340/* Record PID namespace instance deletion */ AUDIT_NS_DEL_NET1341/* Record NET namespace instance deletion */ As suggested by Eric Paris, there are 12 message types, one for each of creation and deletion, one for each type of namespace so that text searches are easier in conjunction with the AUDIT_NS_INFO message type, being able to search for all records such as "netns=4 " and to avoid fields disappearing per message type to make ausearch more efficient. A typical startup would look roughly like: type=AUDIT_NS_INIT_UTS msg=audit(1408577534.868:5): pid=1 uid=0 auid=4294967295 ses=4294967295 subj=kernel dev=00:03 old_utsns=(none) utsns=-2 res=1 type=AUDIT_NS_INIT_USER msg=audit(1408577534.868:6): pid=1 uid=0 auid=4294967295 ses=4294967295 subj=kernel dev=00:03 old_userns=(none) userns=-3 res=1 type=AUDIT_NS_INIT_PID msg=audit(1408577534.868:7): pid=1 uid=0 auid=4294967295 ses=4294967295 subj=kernel dev=00:03 old_pidns=(none) pidns=-4 res=1 type=AUDIT_NS_INIT_MNT msg=audit(1408577534.868:8): pid=1 uid=0 auid=4294967295 ses=4294967295 subj=kernel dev=00:03 old_mntns=(none) mntns=0 res=1 type=AUDIT_NS_INIT_IPC msg=audit(1408577534.868:9): pid=1 uid=0 auid=4294967295 ses=4294967295 subj=kernel dev=00:03 old_ipcns=(none) ipcns=-1 res=1 type=AUDIT_NS_INIT_NET msg=audit(1408577533.500:10): pid=1 uid=0 auid=4294967295 ses=4294967295 subj=kernel dev=00:03 old_netns=(none) netns=2 res=1 And a CLONE action would result in: type=type=AUDIT_NS_INIT_NET msg=audit(1408577535.306:81): pid=481 uid=0 auid=4294967295 ses=4294967295 subj=system_u:system_r:init_t:s0 dev=00:03 old_netns=2 netns=3 res=1 While deleting a namespace would result in: type=type=AUDIT_NS_DEL_MNT msg=audit(1408577552.221:85): pid=481 uid=0 auid=4294967295 ses=4294967295 subj=system_u:system_r:init_t:s0 dev=00:03 mntns=4 res=1 If not "(none)", old_XXXns lists the namespace from which it was cloned. Signed-off-by: Richard Guy Briggs --- fs/namespace.c | 13 + include/linux/audit.h |8 + include/uapi/linux/audit.h | 12 ipc/namespace.c| 12 kernel/audit.c | 64 kernel/pid_namespace.c | 13 + kernel/user_namespace.c| 13 + kernel/utsname.c | 12 net/core/net_namespace.c | 12 9 files changed, 159 insertions(+), 0 deletions(-) diff --git a/fs/namespace.c b/fs/namespace.c index 182bc41..7b62543 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -24,6 +24,7 @@ #include #include #include +#include #include "pnode.h" #include "internal.h" @@ -2459,6 +2460,7 @@ dput_out: static void free_mnt_ns(struct mnt_namespace *ns) { + audit_log_ns_del(AUDIT_NS_DEL_MNT, ns->proc_inum); proc_free_inum(ns->proc_inum); put_user_ns(ns->user_ns); kfree(ns); @@ -2518,6 +2520,7 @@ struct mnt_namespace *copy_mnt_ns(unsigned long flags, struct mnt_namespace *ns, new_ns = alloc_mnt_ns(user_ns); if (IS_ERR(new_ns)) return new_ns; + audit_log_ns_init(AUDIT_NS_INIT_MNT, ns->proc_inum, new_ns->proc_inum); namespace_lock(); /* First pass: copy the tree topology */ @@ -2830,6 +2833,16 @@ static void __init init_mount_tree(void) set_fs_root(current->fs, &root); } +/* log the ID of init mnt namespace after audit service starts */ +static int __init mnt_ns_init_log(void) +{ + struct mnt_namespace *init_mnt_ns = init_task.nsproxy->mnt_ns; + + audit_log_ns_init(AUDIT_NS_INIT_MNT, 0, init_mnt_ns->proc_inum); + return 0; +} +late_initcall(mnt_ns_init_log); + void __init mnt_init(void) { unsigned u; diff --git a/include/linux/audit.h b/include/linux/audit.h index 71698ec..b28dfb0 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -484,6 +484,9 @@ extern void
Re: [RFC PATCH ghak32 V2 01/13] audit: add container id
On 2018-03-28 12:39, Jonathan Corbet wrote: > On Fri, 16 Mar 2018 05:00:28 -0400 > Richard Guy Briggs wrote: > > Implement the proc fs write to set the audit container ID of a process, > > emitting an AUDIT_CONTAINER record to document the event. > > A little detail, but still... I am understanding that you would prefer more context (as opposed to operational detail) in the description, laying out the use case for this patch(set)? > > +static int audit_set_containerid_perm(struct task_struct *task, u64 > > containerid) > > +{ > > + struct task_struct *parent; > > + u64 pcontainerid, ccontainerid; > > + > > + /* Don't allow to set our own containerid */ > > + if (current == task) > > + return -EPERM; > > + /* Don't allow the containerid to be unset */ > > + if (!cid_valid(containerid)) > > + return -EINVAL; > > I went looking for cid_valid(), but it turns out you don't add it until > patch 5. That, I expect, will not be good for bisectability (or patch > review). Nice catch, thanks Jon. That is very likely another victim of a git rebase to re-order afterthoughts in the right place. I'll need to be more careful of that class of bug, rethink my workflow, or script builds to verify each commit is compilable. > Thanks, > > jon - RGB -- Richard Guy Briggs 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: [RFC PATCH ghak32 V2 01/13] audit: add container id
On 2018-03-29 07:03, Jonathan Corbet wrote: > On Thu, 29 Mar 2018 05:01:32 -0400 > Richard Guy Briggs wrote: > > > > A little detail, but still... > > > > I am understanding that you would prefer more context (as opposed to > > operational detail) in the description, laying out the use case for this > > patch(set)? > > No, sorry, "a little detail" was referring to my comment. The use case, > I believe, has been well described. Ah! "A minor nit". :-) > jon - RGB -- Richard Guy Briggs 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: [RFC PATCH V1 01/12] audit: add container id
On 2018-04-18 14:45, Stefan Berger wrote: > On 03/15/2018 11:58 PM, Richard Guy Briggs wrote: > > On 2018-03-15 16:27, Stefan Berger wrote: > > > On 03/01/2018 02:41 PM, Richard Guy Briggs wrote: > > > > Implement the proc fs write to set the audit container ID of a process, > > > > emitting an AUDIT_CONTAINER record to document the event. > > > > > > > > This is a write from the container orchestrator task to a proc entry of > > > > the form /proc/PID/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). > > > > > > > > This will produce a record such as this: > > > > type=UNKNOWN[1333] msg=audit(1519903238.968:261): op=set pid=596 uid=0 > > > > subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 auid=0 > > > > tty=pts0 ses=1 opid=596 old-contid=18446744073709551615 contid=123455 > > > > res=0 > > > > > > > > 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 container ID values are given in the > > > > "contid" fields, while res indicates its success. > > > > > > > > It is not permitted to self-set, unset or re-set the container ID. A > > > > child inherits its parent's container ID, but then can be set only once > > > > after. > > > > > > > > See: https://github.com/linux-audit/audit-kernel/issues/32 > > > > > > > > > > > >/* audit_rule_data supports filter rules with both integer and string > > > > * fields. It corresponds with AUDIT_ADD_RULE, AUDIT_DEL_RULE and > > > > diff --git a/kernel/auditsc.c b/kernel/auditsc.c > > > > index 4e0a4ac..0ee1e59 100644 > > > > --- a/kernel/auditsc.c > > > > +++ b/kernel/auditsc.c > > > > @@ -2073,6 +2073,92 @@ int audit_set_loginuid(kuid_t loginuid) > > > > return rc; > > > >} > > > > > > > > +static int audit_set_containerid_perm(struct task_struct *task, u64 > > > > containerid) > > > > +{ > > > > + struct task_struct *parent; > > > > + u64 pcontainerid, ccontainerid; > > > > + pid_t ppid; > > > > + > > > > + /* Don't allow to set our own containerid */ > > > > + if (current == task) > > > > + return -EPERM; > > > > + /* Don't allow the containerid to be unset */ > > > > + if (!cid_valid(containerid)) > > > > + return -EINVAL; > > > > + /* if we don't have caps, reject */ > > > > + if (!capable(CAP_AUDIT_CONTROL)) > > > > + return -EPERM; > > > > + /* if containerid is unset, allow */ > > > > + if (!audit_containerid_set(task)) > > > > + return 0; > > > I am wondering whether there should be a check for the target process that > > > will receive the containerid to not have CAP_SYS_ADMIN that would > > > otherwise > > > allow it to arbitrarily unshare()/clone() and leave the set of namespaces > > > that may make up the container whose containerid we assign here? > > This is a reasonable question. This has been debated and I understood > > the conclusion was that without a clear definition of a "container", the > > task still remains in that container that just now has more > > sub-namespaces (in the case of hierarchical namespaces), we don't want > > to restrict it in such a way and that allows it to create nested > > containers. I see setns being more problematic if it could switch to > > another existing namespace that was set up by the orchestrator for a > > different container. The coming v2 patchset acknowledges this situation > > with the network namespace being potentially shared by multiple > > containers. > > Are you going to post v2 soon? We would like to build on top of it for IMA > namespacing and auditing inside of IMA namespaces. I don't know if it addresses your specific needs, but V2 was posted on March 16th along with userspace patches: https://www.redhat.com/archives/linux-audit/2018-March/msg00110.html https://www.redhat.com/archives/linux-audit/2018-March/msg00124.html V3 is pending. >Stefan - RGB -- Richard Guy Briggs 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: [RFC PATCH V1 01/12] audit: add container id
On 2018-04-18 15:39, Stefan Berger wrote: > On 04/18/2018 03:23 PM, Richard Guy Briggs wrote: > > On 2018-04-18 14:45, Stefan Berger wrote: > > > On 03/15/2018 11:58 PM, Richard Guy Briggs wrote: > > > > On 2018-03-15 16:27, Stefan Berger wrote: > > > > > On 03/01/2018 02:41 PM, Richard Guy Briggs wrote: > > > > > > Implement the proc fs write to set the audit container ID of a > > > > > > process, > > > > > > emitting an AUDIT_CONTAINER record to document the event. > > > > > > > > > > > > This is a write from the container orchestrator task to a proc > > > > > > entry of > > > > > > the form /proc/PID/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). > > > > > > > > > > > > This will produce a record such as this: > > > > > > type=UNKNOWN[1333] msg=audit(1519903238.968:261): op=set pid=596 > > > > > > uid=0 subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 > > > > > > auid=0 tty=pts0 ses=1 opid=596 old-contid=18446744073709551615 > > > > > > contid=123455 res=0 > > > > > > > > > > > > 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 container ID values are given in the > > > > > > "contid" fields, while res indicates its success. > > > > > > > > > > > > It is not permitted to self-set, unset or re-set the container ID. > > > > > > A > > > > > > child inherits its parent's container ID, but then can be set only > > > > > > once > > > > > > after. > > > > > > > > > > > > See: https://github.com/linux-audit/audit-kernel/issues/32 > > > > > > > > > > > > > > > > > > /* audit_rule_data supports filter rules with both integer and > > > > > > string > > > > > > * fields. It corresponds with AUDIT_ADD_RULE, AUDIT_DEL_RULE > > > > > > and > > > > > > diff --git a/kernel/auditsc.c b/kernel/auditsc.c > > > > > > index 4e0a4ac..0ee1e59 100644 > > > > > > --- a/kernel/auditsc.c > > > > > > +++ b/kernel/auditsc.c > > > > > > @@ -2073,6 +2073,92 @@ int audit_set_loginuid(kuid_t loginuid) > > > > > > return rc; > > > > > > } > > > > > > > > > > > > +static int audit_set_containerid_perm(struct task_struct *task, > > > > > > u64 containerid) > > > > > > +{ > > > > > > + struct task_struct *parent; > > > > > > + u64 pcontainerid, ccontainerid; > > > > > > + pid_t ppid; > > > > > > + > > > > > > + /* Don't allow to set our own containerid */ > > > > > > + if (current == task) > > > > > > + return -EPERM; > > > > > > + /* Don't allow the containerid to be unset */ > > > > > > + if (!cid_valid(containerid)) > > > > > > + return -EINVAL; > > > > > > + /* if we don't have caps, reject */ > > > > > > + if (!capable(CAP_AUDIT_CONTROL)) > > > > > > + return -EPERM; > > > > > > + /* if containerid is unset, allow */ > > > > > > + if (!audit_containerid_set(task)) > > > > > > + return 0; > > > > > I am wondering whether there should be a check for the target process > > > > > that > > > > > will receive the containerid to not have CAP_SYS_ADMIN that would > > > > > otherwise > > > > > allow it to arbitrarily unshare()/clone() and leave the set of > > > > > namespaces > > > > > that may make up the container w
Re: [RFC PATCH ghak32 V2 04/13] audit: add containerid filtering
On 2018-04-18 20:24, Paul Moore wrote: > On Fri, Mar 16, 2018 at 5:00 AM, Richard Guy Briggs wrote: > > Implement container ID filtering using the AUDIT_CONTAINERID 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. > > My only worry here is that you aren't really sending a string in the > ASCII sense, you are sending an 8 byte buffer (that better be NUL > terminated) that happens to be an unsigned 64-bit integer. To be > clear, I'm okay with that (it's protected by AUDIT_CONTAINERID), and > the code is okay with that, I just want us to pause for a minute and > make sure that is an okay thing to do long term. I already went through that process and warned of it 7 weeks ago. As already noted, That was preferable to two seperate u32 fields that depend on each other making comparisons more complicated. Using two seperate fields to configure the rule could be gated for validity, then the result stored in a special rule field, but I wasn't keen about that approach. > > The feature indicator is AUDIT_FEATURE_BITMAP_CONTAINERID_FILTER. > > > > This requires support from userspace to be useful. > > See: https://github.com/linux-audit/audit-userspace/issues/40 > > Signed-off-by: Richard Guy Briggs > > --- > > include/linux/audit.h | 1 + > > include/uapi/linux/audit.h | 5 - > > kernel/audit.h | 1 + > > kernel/auditfilter.c | 47 > > ++ > > kernel/auditsc.c | 3 +++ > > 5 files changed, 56 insertions(+), 1 deletion(-) > > > > diff --git a/include/linux/audit.h b/include/linux/audit.h > > index 3acbe9d..f10ca1b 100644 > > --- a/include/linux/audit.h > > +++ b/include/linux/audit.h > > @@ -76,6 +76,7 @@ struct audit_field { > > u32 type; > > union { > > u32 val; > > + u64 val64; > > kuid_t uid; > > kgid_t gid; > > struct { > > diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h > > index e83ccbd..8443a8f 100644 > > --- a/include/uapi/linux/audit.h > > +++ b/include/uapi/linux/audit.h > > @@ -262,6 +262,7 @@ > > #define AUDIT_LOGINUID_SET 24 > > #define AUDIT_SESSIONID25 /* Session ID */ > > #define AUDIT_FSTYPE 26 /* FileSystem Type */ > > +#define AUDIT_CONTAINERID 27 /* Container ID */ > > > > /* These are ONLY useful when checking > > * at syscall exit time (AUDIT_AT_EXIT). */ > > @@ -342,6 +343,7 @@ enum { > > #define AUDIT_FEATURE_BITMAP_SESSIONID_FILTER 0x0010 > > #define AUDIT_FEATURE_BITMAP_LOST_RESET0x0020 > > #define AUDIT_FEATURE_BITMAP_FILTER_FS 0x0040 > > +#define AUDIT_FEATURE_BITMAP_CONTAINERID_FILTER0x0080 > > > > #define AUDIT_FEATURE_BITMAP_ALL (AUDIT_FEATURE_BITMAP_BACKLOG_LIMIT | \ > > AUDIT_FEATURE_BITMAP_BACKLOG_WAIT_TIME | \ > > @@ -349,7 +351,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_FILTER) > > > > /* deprecated: AUDIT_VERSION_* */ > > #define AUDIT_VERSION_LATEST AUDIT_FEATURE_BITMAP_ALL > > diff --git a/kernel/audit.h b/kernel/audit.h > > index 214e149..aaa651a 100644 > > --- a/kernel/audit.h > > +++ b/kernel/audit.h > > @@ -234,6 +234,7 @@ static inline int audit_hash_ino(u32 ino) > > > > extern int audit_match_class(int class, unsigned syscall); > > extern int audit_comparator(const u32 left, const u32 op, const u32 right); > > +extern int audit_comparator64(const u64 left, const u32 op, const u64 > > right); > > extern int audit_uid_comparator(kuid_t left, u32 op, kuid_t right); > > extern int audit_gid_comparator(kgid_t left, u32 op, kgid_t right); > > extern int parent_len(const char *path); > > diff
Re: [RFC PATCH ghak32 V2 07/13] audit: add container aux record to watch/tree/mark
On 2018-04-18 20:42, Paul Moore wrote: > On Fri, Mar 16, 2018 at 5:00 AM, Richard Guy Briggs wrote: > > Add container ID auxiliary record to mark, watch and tree rule > > configuration standalone records. > > > > Signed-off-by: Richard Guy Briggs > > --- > > kernel/audit_fsnotify.c | 5 - > > kernel/audit_tree.c | 5 - > > kernel/audit_watch.c| 33 +++-- > > 3 files changed, 27 insertions(+), 16 deletions(-) > > > > diff --git a/kernel/audit_fsnotify.c b/kernel/audit_fsnotify.c > > index 52f368b..18c110d 100644 > > --- a/kernel/audit_fsnotify.c > > +++ b/kernel/audit_fsnotify.c > > @@ -124,10 +124,11 @@ static void audit_mark_log_rule_change(struct > > audit_fsnotify_mark *audit_mark, c > > { > > struct audit_buffer *ab; > > struct audit_krule *rule = audit_mark->rule; > > + struct audit_context *context = audit_alloc_local(); > > > > if (!audit_enabled) > > return; > > Move the audit_alloc_local() after the audit_enabled check. Already fixed in V3 as previously warned, by making all AUDIT_CONFIG_CHANGE records SYSCALL auxiliary records. > > - ab = audit_log_start(NULL, GFP_NOFS, AUDIT_CONFIG_CHANGE); > > + ab = audit_log_start(context, GFP_NOFS, AUDIT_CONFIG_CHANGE); > > if (unlikely(!ab)) > > return; > > audit_log_format(ab, "auid=%u ses=%u op=%s", > > @@ -138,6 +139,8 @@ static void audit_mark_log_rule_change(struct > > audit_fsnotify_mark *audit_mark, c > > audit_log_key(ab, rule->filterkey); > > audit_log_format(ab, " list=%d res=1", rule->listnr); > > audit_log_end(ab); > > + audit_log_container_info(context, "config", > > audit_get_containerid(current)); > > + audit_free_context(context); > > } > > > > void audit_remove_mark(struct audit_fsnotify_mark *audit_mark) > > diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c > > index 67e6956..7c085be 100644 > > --- a/kernel/audit_tree.c > > +++ b/kernel/audit_tree.c > > @@ -496,8 +496,9 @@ static int tag_chunk(struct inode *inode, struct > > audit_tree *tree) > > static void audit_tree_log_remove_rule(struct audit_krule *rule) > > { > > struct audit_buffer *ab; > > + struct audit_context *context = audit_alloc_local(); > > Sort of independent of the audit container ID work, but shouldn't we > have an audit_enabled check here? Same. > > - ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); > > + ab = audit_log_start(context, GFP_KERNEL, AUDIT_CONFIG_CHANGE); > > if (unlikely(!ab)) > > return; > > audit_log_format(ab, "op=remove_rule"); > > @@ -506,6 +507,8 @@ static void audit_tree_log_remove_rule(struct > > audit_krule *rule) > > audit_log_key(ab, rule->filterkey); > > audit_log_format(ab, " list=%d res=1", rule->listnr); > > audit_log_end(ab); > > + audit_log_container_info(context, "config", > > audit_get_containerid(current)); > > + audit_free_context(context); > > } > > > > static void kill_rules(struct audit_tree *tree) > > diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c > > index 9eb8b35..60d75a2 100644 > > --- a/kernel/audit_watch.c > > +++ b/kernel/audit_watch.c > > @@ -238,20 +238,25 @@ static struct audit_watch *audit_dupe_watch(struct > > audit_watch *old) > > > > static void audit_watch_log_rule_change(struct audit_krule *r, struct > > audit_watch *w, char *op) > > { > > - if (audit_enabled) { > > - struct audit_buffer *ab; > > - ab = audit_log_start(NULL, GFP_NOFS, AUDIT_CONFIG_CHANGE); > > - if (unlikely(!ab)) > > - return; > > - audit_log_format(ab, "auid=%u ses=%u op=%s", > > -from_kuid(&init_user_ns, > > audit_get_loginuid(current)), > > -audit_get_sessionid(current), op); > > - audit_log_format(ab, " path="); > > - audit_log_untrustedstring(ab, w->path); > > - audit_log_key(ab, r->filterkey); > > - audit_log_format(ab, " list=%d res=1", r->listnr); > > - audit_log_end(ab); > > - } > > + struct audit_buffer *ab; &g
Re: [RFC PATCH ghak32 V2 09/13] audit: add containerid support for config/feature/user records
On 2018-04-18 21:27, Paul Moore wrote: > On Fri, Mar 16, 2018 at 5:00 AM, Richard Guy Briggs wrote: > > Add container ID auxiliary records to configuration change, feature set > > change > > and user generated standalone records. > > > > Signed-off-by: Richard Guy Briggs > > --- > > kernel/audit.c | 50 > > -- > > kernel/auditfilter.c | 5 - > > 2 files changed, 44 insertions(+), 11 deletions(-) > > > > diff --git a/kernel/audit.c b/kernel/audit.c > > index b238be5..08662b4 100644 > > --- a/kernel/audit.c > > +++ b/kernel/audit.c > > @@ -400,8 +400,9 @@ static int audit_log_config_change(char *function_name, > > u32 new, u32 old, > > { > > struct audit_buffer *ab; > > int rc = 0; > > + struct audit_context *context = audit_alloc_local(); > > We should be able to use current->audit_context here right? If we > can't for every caller, perhaps we pass an audit_context as an > argument and only allocate a local context when the passed > audit_context is NULL. > > Also, if you're not comfortable always using current, just pass the > audit_context as you do with audit_log_common_recv_msg(). As mentioned in the tree/watch/mark patch, this is all obsoleted by making the AUDIT_CONFIG_CHANGE record a SYSCALL auxiliary record. This review would have been more helpful a month and a half ago. > > - ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); > > + ab = audit_log_start(context, GFP_KERNEL, AUDIT_CONFIG_CHANGE); > > if (unlikely(!ab)) > > return rc; > > audit_log_format(ab, "%s=%u old=%u", function_name, new, old); > > @@ -411,6 +412,8 @@ static int audit_log_config_change(char *function_name, > > u32 new, u32 old, > > allow_changes = 0; /* Something weird, deny request */ > > audit_log_format(ab, " res=%d", allow_changes); > > audit_log_end(ab); > > + audit_log_container_info(context, "config", > > audit_get_containerid(current)); > > + audit_free_context(context); > > return rc; > > } > > > > @@ -1058,7 +1061,8 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 > > msg_type) > > return err; > > } > > > > -static void audit_log_common_recv_msg(struct audit_buffer **ab, u16 > > msg_type) > > +static void audit_log_common_recv_msg(struct audit_context *context, > > + struct audit_buffer **ab, u16 > > msg_type) > > { > > uid_t uid = from_kuid(&init_user_ns, current_uid()); > > pid_t pid = task_tgid_nr(current); > > @@ -1068,7 +1072,7 @@ static void audit_log_common_recv_msg(struct > > audit_buffer **ab, u16 msg_type) > > return; > > } > > > > - *ab = audit_log_start(NULL, GFP_KERNEL, msg_type); > > + *ab = audit_log_start(context, GFP_KERNEL, msg_type); > > if (unlikely(!*ab)) > > return; > > audit_log_format(*ab, "pid=%d uid=%u", pid, uid); > > @@ -1097,11 +1101,12 @@ static void audit_log_feature_change(int which, u32 > > old_feature, u32 new_feature > > u32 old_lock, u32 new_lock, int res) > > { > > struct audit_buffer *ab; > > + struct audit_context *context = audit_alloc_local(); > > So I know based on the other patch we are currently discussing that we > can use current here ... > > > if (audit_enabled == AUDIT_OFF) > > return; > > > > - ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_FEATURE_CHANGE); > > + ab = audit_log_start(context, GFP_KERNEL, AUDIT_FEATURE_CHANGE); > > if (!ab) > > return; > > audit_log_task_info(ab, current); > > @@ -1109,6 +1114,8 @@ static void audit_log_feature_change(int which, u32 > > old_feature, u32 new_feature > > audit_feature_names[which], !!old_feature, > > !!new_feature, > > !!old_lock, !!new_lock, res); > > audit_log_end(ab); > > + audit_log_container_info(context, "feature", > > audit_get_containerid(current)); > > + audit_free_context(context); > > } > > > > static int audit_set_feature(struct sk_buff *skb) > > @@ -1337,13 +1344,15 @@ static int audit_receive_msg(struct sk_buff *skb, > >
Re: [RFC PATCH ghak32 V2 12/13] audit: NETFILTER_PKT: record each container ID associated with a netNS
On 2018-04-18 22:10, Paul Moore wrote: > On Fri, Mar 16, 2018 at 5:00 AM, Richard Guy Briggs wrote: > > Add container ID auxiliary record(s) to NETFILTER_PKT event standalone > > records. Iterate through all potential container IDs associated with a > > network namespace. > > > > Signed-off-by: Richard Guy Briggs > > --- > > kernel/audit.c | 1 + > > kernel/auditsc.c | 2 ++ > > net/netfilter/xt_AUDIT.c | 15 ++- > > 3 files changed, 17 insertions(+), 1 deletion(-) > > > > diff --git a/kernel/audit.c b/kernel/audit.c > > index 08662b4..3c77e47 100644 > > --- a/kernel/audit.c > > +++ b/kernel/audit.c > > @@ -2102,6 +2102,7 @@ int audit_log_container_info(struct audit_context > > *context, > > audit_log_end(ab); > > return 0; > > } > > +EXPORT_SYMBOL(audit_log_container_info); > > > > void audit_log_key(struct audit_buffer *ab, char *key) > > { > > diff --git a/kernel/auditsc.c b/kernel/auditsc.c > > index 208da962..af68d01 100644 > > --- a/kernel/auditsc.c > > +++ b/kernel/auditsc.c > > @@ -975,6 +975,7 @@ struct audit_context *audit_alloc_local(void) > > context->in_syscall = 1; > > return context; > > } > > +EXPORT_SYMBOL(audit_alloc_local); > > > > inline void audit_free_context(struct audit_context *context) > > { > > @@ -989,6 +990,7 @@ 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, > > diff --git a/net/netfilter/xt_AUDIT.c b/net/netfilter/xt_AUDIT.c > > index c502419..edaa456 100644 > > --- a/net/netfilter/xt_AUDIT.c > > +++ b/net/netfilter/xt_AUDIT.c > > @@ -71,10 +71,14 @@ static bool audit_ip6(struct audit_buffer *ab, struct > > sk_buff *skb) > > { > > struct audit_buffer *ab; > > int fam = -1; > > + struct audit_context *context = audit_alloc_local(); > > + struct audit_containerid *cont; > > + int i = 0; > > + struct net *net; > > > > if (audit_enabled == 0) > > goto errout; > > Do I need to say it? I probably should ... the allocation should > happen after the audit_enabled check. Already fixed in V3 in my tree a couple of weeks ago... More timely review please? > > - ab = audit_log_start(NULL, GFP_ATOMIC, AUDIT_NETFILTER_PKT); > > + ab = audit_log_start(context, GFP_ATOMIC, AUDIT_NETFILTER_PKT); > > if (ab == NULL) > > goto errout; > > > > @@ -104,7 +108,16 @@ static bool audit_ip6(struct audit_buffer *ab, struct > > sk_buff *skb) > > > > audit_log_end(ab); > > > > + net = sock_net(NETLINK_CB(skb).sk); > > + list_for_each_entry(cont, &net->audit_containerid, list) { > > + char buf[14]; > > + > > + sprintf(buf, "net%u", i++); > > + audit_log_container_info(context, buf, cont->id); > > + } > > It seems like this could (should?) be hidden inside an audit function, > e.g. audit_log_net_containers() or something like that. Perhaps... It was open-coded since at this point there are no other users. That'll make this tidier though. > > errout: > > + audit_free_context(context); > > return XT_CONTINUE; > > } > > -- > paul moore > www.paul-moore.com - RGB -- Richard Guy Briggs 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: [RFC PATCH ghak32 V2 10/13] audit: add containerid support for seccomp and anom_abend records
On 2018-04-18 21:31, Paul Moore wrote: > On Fri, Mar 16, 2018 at 5:00 AM, Richard Guy Briggs wrote: > > Add container ID auxiliary records to secure computing and abnormal end > > standalone records. > > > > Signed-off-by: Richard Guy Briggs > > --- > > kernel/auditsc.c | 10 -- > > 1 file changed, 8 insertions(+), 2 deletions(-) > > > > diff --git a/kernel/auditsc.c b/kernel/auditsc.c > > index 7103d23..2f02ed9 100644 > > --- a/kernel/auditsc.c > > +++ b/kernel/auditsc.c > > @@ -2571,6 +2571,7 @@ static void audit_log_task(struct audit_buffer *ab) > > void audit_core_dumps(long signr) > > { > > struct audit_buffer *ab; > > + struct audit_context *context = audit_alloc_local(); > > Looking quickly at do_coredump() I *believe* we can use current here. > > > if (!audit_enabled) > > return; > > @@ -2578,19 +2579,22 @@ void audit_core_dumps(long signr) > > if (signr == SIGQUIT) /* don't care for those */ > > return; > > > > - ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_ANOM_ABEND); > > + ab = audit_log_start(context, GFP_KERNEL, AUDIT_ANOM_ABEND); > > if (unlikely(!ab)) > > return; > > audit_log_task(ab); > > audit_log_format(ab, " sig=%ld res=1", signr); > > audit_log_end(ab); > > + audit_log_container_info(context, "abend", > > audit_get_containerid(current)); > > + audit_free_context(context); > > } > > > > void __audit_seccomp(unsigned long syscall, long signr, int code) > > { > > struct audit_buffer *ab; > > + struct audit_context *context = audit_alloc_local(); > > We can definitely use current here. Ok, so both syscall aux records. That elimintes this patch from the set, can go in independently. > > - ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_SECCOMP); > > + ab = audit_log_start(context, GFP_KERNEL, AUDIT_SECCOMP); > > if (unlikely(!ab)) > > return; > > audit_log_task(ab); > > @@ -2598,6 +2602,8 @@ void __audit_seccomp(unsigned long syscall, long > > signr, int code) > > signr, syscall_get_arch(), syscall, > > in_compat_syscall(), KSTK_EIP(current), code); > > audit_log_end(ab); > > + audit_log_container_info(context, "seccomp", > > audit_get_containerid(current)); > > + audit_free_context(context); > > } > > > > struct list_head *audit_killed_trees(void) > > -- > paul moore > www.paul-moore.com > > -- > Linux-audit mailing list > linux-au...@redhat.com > https://www.redhat.com/mailman/listinfo/linux-audit - RGB -- Richard Guy Briggs 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: [RFC PATCH ghak32 V2 05/13] audit: add containerid support for ptrace and signals
On 2018-04-18 20:32, Paul Moore wrote: > On Fri, Mar 16, 2018 at 5:00 AM, Richard Guy Briggs wrote: > > Add container ID support to ptrace and signals. In particular, the "op" > > field provides a way to label the auxiliary record to which it is > > associated. > > > > Signed-off-by: Richard Guy Briggs > > --- > > include/linux/audit.h | 16 +++- > > kernel/audit.c| 12 > > kernel/audit.h| 2 ++ > > kernel/auditsc.c | 19 +++ > > 4 files changed, 36 insertions(+), 13 deletions(-) > > ... > > > diff --git a/kernel/audit.c b/kernel/audit.c > > index a12f21f..b238be5 100644 > > --- a/kernel/audit.c > > +++ b/kernel/audit.c > > @@ -142,6 +142,7 @@ struct audit_net { > > kuid_t audit_sig_uid = INVALID_UID; > > pid_t audit_sig_pid = -1; > > u32audit_sig_sid = 0; > > +u64audit_sig_cid = INVALID_CID; > > > > /* Records can be lost in several ways: > > 0) [suppressed in audit_alloc] > > @@ -1438,6 +1439,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); > > @@ -2051,20 +2053,22 @@ void audit_log_session_info(struct audit_buffer *ab) > > > > /* > > * audit_log_container_info - report container info > > - * @tsk: task to be recorded > > * @context: task or local context for record > > + * @op: containerid string description > > + * @containerid: container ID to report > > */ > > -int audit_log_container_info(struct task_struct *tsk, struct audit_context > > *context) > > +int audit_log_container_info(struct audit_context *context, > > + char *op, u64 containerid) > > { > > struct audit_buffer *ab; > > > > - if (!audit_containerid_set(tsk)) > > + if (!cid_valid(containerid)) > > return 0; > > /* Generate AUDIT_CONTAINER_INFO with container ID */ > > ab = audit_log_start(context, GFP_KERNEL, AUDIT_CONTAINER_INFO); > > if (!ab) > > return -ENOMEM; > > - audit_log_format(ab, "contid=%llu", audit_get_containerid(tsk)); > > + audit_log_format(ab, "op=%s contid=%llu", op, containerid); > > audit_log_end(ab); > > return 0; > > } > > Let's get these changes into the first patch where > audit_log_container_info() is defined. Why? This inserts a new field > into the record which is a no-no. Yes, it is one single patchset, but > they are still separate patches and who knows which patches a given > distribution and/or tree may decide to backport. Fair enough. That first thought went through my mind... Would it be sufficient to move that field addition to the first patch and leave the rest here to support trace and signals? > > diff --git a/kernel/auditsc.c b/kernel/auditsc.c > > index 2bba324..2932ef1 100644 > > --- a/kernel/auditsc.c > > +++ b/kernel/auditsc.c > > @@ -113,6 +113,7 @@ struct audit_aux_data_pids { > > kuid_t target_uid[AUDIT_AUX_PIDS]; > > unsigned inttarget_sessionid[AUDIT_AUX_PIDS]; > > u32 target_sid[AUDIT_AUX_PIDS]; > > + u64 target_cid[AUDIT_AUX_PIDS]; > > chartarget_comm[AUDIT_AUX_PIDS][TASK_COMM_LEN]; > > int pid_count; > > }; > > @@ -1422,21 +1423,27 @@ static void audit_log_exit(struct audit_context > > *context, struct task_struct *ts > > for (aux = context->aux_pids; aux; aux = aux->next) { > > struct audit_aux_data_pids *axs = (void *)aux; > > > > - for (i = 0; i < axs->pid_count; i++) > > + for (i = 0; i < axs->pid_count; i++) { > > + char axsn[sizeof("aux0xN ")]; > > + > > + sprintf(axsn, "aux0x%x", i); > > if (audit_log_pid_context(context, > > axs->target_pid[i], > >
Re: [RFC PATCH ghak32 V2 06/13] audit: add support for non-syscall auxiliary records
On 2018-04-18 20:39, Paul Moore wrote: > On Fri, Mar 16, 2018 at 5:00 AM, Richard Guy Briggs wrote: > > Standalone audit records have the timestamp and serial number generated > > on the fly and as such are unique, making them standalone. This new > > function audit_alloc_local() generates a local audit context that will > > be used only for a standalone record and its auxiliary record(s). The > > context is discarded immediately after the local associated records are > > produced. > > > > Signed-off-by: Richard Guy Briggs > > --- > > include/linux/audit.h | 8 > > kernel/auditsc.c | 20 +++- > > 2 files changed, 27 insertions(+), 1 deletion(-) > > > > diff --git a/include/linux/audit.h b/include/linux/audit.h > > index ed16bb6..c0b83cb 100644 > > --- a/include/linux/audit.h > > +++ b/include/linux/audit.h > > @@ -227,7 +227,9 @@ static inline int audit_log_container_info(struct > > audit_context *context, > > /* These are defined in auditsc.c */ > > /* Public API */ > > extern int audit_alloc(struct task_struct *task); > > +extern struct audit_context *audit_alloc_local(void); > > extern void __audit_free(struct task_struct *task); > > +extern void audit_free_context(struct audit_context *context); > > extern void __audit_syscall_entry(int major, unsigned long a0, unsigned > > long a1, > > unsigned long a2, unsigned long a3); > > extern void __audit_syscall_exit(int ret_success, long ret_value); > > @@ -472,6 +474,12 @@ static inline int audit_alloc(struct task_struct *task) > > { > > return 0; > > } > > +static inline struct audit_context *audit_alloc_local(void) > > +{ > > + return NULL; > > +} > > +static inline void audit_free_context(struct audit_context *context) > > +{ } > > static inline void audit_free(struct task_struct *task) > > { } > > static inline void audit_syscall_entry(int major, unsigned long a0, > > diff --git a/kernel/auditsc.c b/kernel/auditsc.c > > index 2932ef1..7103d23 100644 > > --- a/kernel/auditsc.c > > +++ b/kernel/auditsc.c > > @@ -959,8 +959,26 @@ int audit_alloc(struct task_struct *tsk) > > return 0; > > } > > > > -static inline void audit_free_context(struct audit_context *context) > > +struct audit_context *audit_alloc_local(void) > > { > > + struct audit_context *context; > > + > > + if (!audit_ever_enabled) > > + return NULL; /* Return if not auditing. */ > > + > > + context = audit_alloc_context(AUDIT_RECORD_CONTEXT); > > + if (!context) > > + return NULL; > > + context->serial = audit_serial(); > > + context->ctime = current_kernel_time64(); > > + context->in_syscall = 1; > > + return context; > > +} > > + > > +inline 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); > > I'm reserving the option to comment on this idea further as I make my > way through the patchset, but audit_free_context() definitely > shouldn't be declared as an inline function. Ok, I think I follow. When it wasn't exported, inline was fine, but now that it has been exported, it should no longer be inlined, or should use an intermediate function name to export so that local uses of it can remain inline. > paul moore - RGB -- Richard Guy Briggs 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: [RFC PATCH ghak32 V2 11/13] audit: add support for containerid to network namespaces
On 2018-04-18 21:46, Paul Moore wrote: > On Fri, Mar 16, 2018 at 5:00 AM, Richard Guy Briggs wrote: > > Audit events could happen in a network namespace outside of a task > > context due to packets received from the net that trigger an auditing > > rule prior to being associated with a running task. The network > > namespace could 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 container identifiiers. > > > > Add/increment the container identifier on: > > - initial setting of the container id via /proc > > - clone/fork call that inherits a container identifier > > - unshare call that inherits a container identifier > > - setns call that inherits a container identifier > > Delete/decrement the container identifier on: > > - an inherited container id 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/32 > > See: https://github.com/linux-audit/audit-testsuite/issues/64 > > Signed-off-by: Richard Guy Briggs > > --- > > include/linux/audit.h | 7 +++ > > include/net/net_namespace.h | 12 > > kernel/auditsc.c| 9 ++--- > > kernel/nsproxy.c| 6 ++ > > net/core/net_namespace.c| 45 > > + > > 5 files changed, 76 insertions(+), 3 deletions(-) > > ... > > > diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h > > index 0490084..343a428 100644 > > --- a/include/net/net_namespace.h > > +++ b/include/net/net_namespace.h > > @@ -33,6 +33,7 @@ > > #include > > #include > > #include > > +#include > > > > struct user_namespace; > > struct proc_dir_entry; > > @@ -150,6 +151,7 @@ struct net { > > #endif > > struct sock *diag_nlsk; > > atomic_tfnhe_genid; > > + struct list_headaudit_containerid; > > } __randomize_layout; > > We talked about this briefly off-list, you should be using audit_net > and the net_generic mechanism instead of this. > > > #include > > @@ -301,6 +303,16 @@ static inline struct net *read_pnet(const > > possible_net_t *pnet) > > #define __net_initconst__initconst > > #endif > > > > +#ifdef CONFIG_NET_NS > > +void net_add_audit_containerid(struct net *net, u64 containerid); > > +void net_del_audit_containerid(struct net *net, u64 containerid); > > +#else > > +static inline void net_add_audit_containerid(struct net *, u64) > > +{ } > > +static inline void net_del_audit_containerid(struct net *, u64) > > +{ } > > +#endif > > + > > int peernet2id_alloc(struct net *net, struct net *peer); > > int peernet2id(struct net *net, struct net *peer); > > bool peernet_has_id(struct net *net, struct net *peer); > > diff --git a/kernel/auditsc.c b/kernel/auditsc.c > > index 2f02ed9..208da962 100644 > > --- a/kernel/auditsc.c > > +++ b/kernel/auditsc.c > > @@ -75,6 +75,7 @@ > > #include > > #include > > #include > > +#include > > > > #include "audit.h" > > > > @@ -2175,16 +2176,18 @@ static void audit_log_set_containerid(struct > > task_struct *task, u64 oldcontainer > > */ > > int audit_set_containerid(struct task_struct *task, u64 containerid) > > { > > - u64 oldcontainerid; > > + u64 oldcontainerid = audit_get_containerid(task); > > int rc; > > - > > - oldcontainerid = audit_get_containerid(task); > > + struct net *net = task->nsproxy->net_ns; > > > > rc = audit_set_containerid_perm(task, containerid); > > if (!rc) { > > + if (cid_valid(oldcontainerid)) > > + net_del_audit_containerid(net, oldcontainerid); > > Using audit_net we can handle this internal to audit, which is a Good Thing. No problem, done. > > task_lock(task); > > task->containerid = containerid; > > task_unlock(task); > > + net_add_audit_containerid(net, containerid); > > Same. > > > } > > > > audit_log_set_containerid(task, oldcontainerid, containerid, rc); > > diff --git a/k
Re: [RFC PATCH ghak32 V2 11/13] audit: add support for containerid to network namespaces
On 2018-04-20 16:22, Paul Moore wrote: > On Fri, Apr 20, 2018 at 4:02 PM, Richard Guy Briggs wrote: > > On 2018-04-18 21:46, Paul Moore wrote: > >> On Fri, Mar 16, 2018 at 5:00 AM, Richard Guy Briggs > >> wrote: > >> > Audit events could happen in a network namespace outside of a task > >> > context due to packets received from the net that trigger an auditing > >> > rule prior to being associated with a running task. The network > >> > namespace could 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 container identifiiers. > >> > > >> > Add/increment the container identifier on: > >> > - initial setting of the container id via /proc > >> > - clone/fork call that inherits a container identifier > >> > - unshare call that inherits a container identifier > >> > - setns call that inherits a container identifier > >> > Delete/decrement the container identifier on: > >> > - an inherited container id 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/32 > >> > See: https://github.com/linux-audit/audit-testsuite/issues/64 > >> > Signed-off-by: Richard Guy Briggs > >> > --- > >> > include/linux/audit.h | 7 +++ > >> > include/net/net_namespace.h | 12 > >> > kernel/auditsc.c| 9 ++--- > >> > kernel/nsproxy.c| 6 ++ > >> > net/core/net_namespace.c| 45 > >> > + > >> > 5 files changed, 76 insertions(+), 3 deletions(-) > > ... > > >> > diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c > >> > index f6c5d33..d9f1090 100644 > >> > --- a/kernel/nsproxy.c > >> > +++ b/kernel/nsproxy.c > >> > @@ -140,6 +140,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 containerid = audit_get_containerid(tsk); > >> > > >> > if (likely(!(flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC | > >> > CLONE_NEWPID | CLONE_NEWNET | > >> > @@ -167,6 +168,7 @@ int copy_namespaces(unsigned long flags, struct > >> > task_struct *tsk) > >> > return PTR_ERR(new_ns); > >> > > >> > tsk->nsproxy = new_ns; > >> > + net_add_audit_containerid(new_ns->net_ns, containerid); > >> > return 0; > >> > } > >> > >> Hopefully we can handle this in audit_net_init(), we just need to > >> figure out where we can get the correct task_struct for the audit > >> container ID (some backpointer in the net struct?). > > > > I don't follow. This needs to happen on every task startup. > > audit_net_init() is only called when a new network namespace starts up. > > Yep, sorry, my mistake. I must have confused myself when I was > looking at the code. > > I'm thinking out loud here, bear with me ... > > Assuming we move the netns/audit-container-ID tracking to audit_net, > and considering we already have an audit hook in copy_process() (it > calls audit_alloc()), would this be better handled by the > copy_process() hook? This ignores naming, audit_alloc() reuse, etc.; > those can be easily fixed. I'm just thinking of ways to limit our > impact on the core kernel and leverage our existing interaction > points. The new namespace hasn't been cloned yet and this is the only function where we have access to both namespaces, so I don't see how that could work... > paul moore - RGB -- Richard Guy Briggs 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: [RFC PATCH ghak32 V2 01/13] audit: add container id
On 2018-04-18 19:47, Paul Moore wrote: > On Fri, Mar 16, 2018 at 5:00 AM, Richard Guy Briggs wrote: > > Implement the proc fs write to set the audit container ID of a process, > > emitting an AUDIT_CONTAINER record to document the event. > > > > This is a write from the container orchestrator task to a proc entry of > > the form /proc/PID/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). > > > > This will produce a record such as this: > > type=CONTAINER msg=audit(1519903238.968:261): op=set pid=596 uid=0 > > subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 auid=0 tty=pts0 > > ses=1 opid=596 old-contid=18446744073709551615 contid=123455 res=0 > > > > 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 container ID values are given in the > > "contid" fields, while res indicates its success. > > > > It is not permitted to self-set, unset or re-set the container ID. A > > child inherits its parent's container ID, but then can be set only once > > after. > > > > See: https://github.com/linux-audit/audit-kernel/issues/32 > > > > Signed-off-by: Richard Guy Briggs > > --- > > fs/proc/base.c | 37 > > include/linux/audit.h | 16 + > > include/linux/init_task.h | 4 ++- > > include/linux/sched.h | 1 + > > include/uapi/linux/audit.h | 2 ++ > > kernel/auditsc.c | 84 > > ++ > > 6 files changed, 143 insertions(+), 1 deletion(-) > > > > diff --git a/fs/proc/base.c b/fs/proc/base.c > > index 60316b5..6ce4fbe 100644 > > --- a/fs/proc/base.c > > +++ b/fs/proc/base.c > > @@ -1299,6 +1299,41 @@ static ssize_t proc_sessionid_read(struct file * > > file, char __user * buf, > > .read = proc_sessionid_read, > > .llseek = generic_file_llseek, > > }; > > + > > +static ssize_t proc_containerid_write(struct file *file, const char __user > > *buf, > > + size_t count, loff_t *ppos) > > +{ > > + struct inode *inode = file_inode(file); > > + u64 containerid; > > + 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, &containerid); > > + if (rv < 0) { > > + put_task_struct(task); > > + return rv; > > + } > > + > > + rv = audit_set_containerid(task, containerid); > > + put_task_struct(task); > > + if (rv < 0) > > + return rv; > > + return count; > > +} > > + > > +static const struct file_operations proc_containerid_operations = { > > + .write = proc_containerid_write, > > + .llseek = generic_file_llseek, > > +}; > > + > > #endif > > > > #ifdef CONFIG_FAULT_INJECTION > > @@ -2961,6 +2996,7 @@ static int proc_pid_patch_state(struct seq_file *m, > > struct pid_namespace *ns, > > #ifdef CONFIG_AUDITSYSCALL > > REG("loginuid", S_IWUSR|S_IRUGO, proc_loginuid_operations), > > REG("sessionid", S_IRUGO, proc_sessionid_operations), > > + REG("containerid", S_IWUSR, proc_containerid_operations), > > #endif > > #ifdef CONFIG_FAULT_INJECTION > > REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations), > > @@ -3355,6 +3391,7 @@ static int proc_tid_comm_permission(struct inode > > *inode, int mask) > > #ifdef CONFIG_AUDITSYSCALL > > REG("loginuid", S_IWUSR|S_IRUGO, proc_loginuid_operations), > > REG("sessionid", S_IRUGO, proc_sessionid_operations), > > + REG("containerid", S_IWUSR, proc_containerid_operations), > > #endif > > #ifdef CONFIG_FAULT_INJECTION > > REG("mak
Re: [RFC PATCH ghak32 V2 01/13] audit: add container id
On 2018-04-23 19:15, Paul Moore wrote: > On Sat, Apr 21, 2018 at 10:34 AM, Richard Guy Briggs wrote: > > On 2018-04-18 19:47, Paul Moore wrote: > >> On Fri, Mar 16, 2018 at 5:00 AM, Richard Guy Briggs > >> wrote: > >> > Implement the proc fs write to set the audit container ID of a process, > >> > emitting an AUDIT_CONTAINER record to document the event. > >> > > >> > This is a write from the container orchestrator task to a proc entry of > >> > the form /proc/PID/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). > >> > > >> > This will produce a record such as this: > >> > type=CONTAINER msg=audit(1519903238.968:261): op=set pid=596 uid=0 > >> > subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 auid=0 > >> > tty=pts0 ses=1 opid=596 old-contid=18446744073709551615 contid=123455 > >> > res=0 > >> > > >> > 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 container ID values are given in the > >> > "contid" fields, while res indicates its success. > >> > > >> > It is not permitted to self-set, unset or re-set the container ID. A > >> > child inherits its parent's container ID, but then can be set only once > >> > after. > >> > > >> > See: https://github.com/linux-audit/audit-kernel/issues/32 > >> > > >> > Signed-off-by: Richard Guy Briggs > >> > --- > >> > fs/proc/base.c | 37 > >> > include/linux/audit.h | 16 + > >> > include/linux/init_task.h | 4 ++- > >> > include/linux/sched.h | 1 + > >> > include/uapi/linux/audit.h | 2 ++ > >> > kernel/auditsc.c | 84 > >> > ++ > >> > 6 files changed, 143 insertions(+), 1 deletion(-) > > ... > > >> > diff --git a/include/linux/sched.h b/include/linux/sched.h > >> > index d258826..1b82191 100644 > >> > --- a/include/linux/sched.h > >> > +++ b/include/linux/sched.h > >> > @@ -796,6 +796,7 @@ struct task_struct { > >> > #ifdef CONFIG_AUDITSYSCALL > >> > kuid_t loginuid; > >> > unsigned intsessionid; > >> > + u64 containerid; > >> > >> This one line addition to the task_struct scares me the most of > >> anything in this patchset. Why? It's a field named "containerid" in > >> a perhaps one of the most widely used core kernel structures; the > >> possibilities for abuse are endless, and it's foolish to think we > >> would ever be able to adequately police this. > > > > Fair enough. > > > >> Unfortunately, we can't add the field to audit_context as things > >> currently stand because we don't always allocate an audit_context, > >> it's dependent on the system's configuration, and we need to track the > >> audit container ID for a given process, regardless of the audit > >> configuration. Pretty much the same reason why loginuid and sessionid > >> are located directly in task_struct now. As I stressed during the > >> design phase, I really want to keep this as an *audit* container ID > >> and not a general purpose kernel wide container ID. If the kernel > >> ever grows a general purpose container ID token, I'll be the first in > >> line to convert the audit code, but I don't want audit to be that > >> general purpose mechanism ... audit is hated enough as-is ;) > > > > When would we need an audit container ID when audit is not enabled > > enough to have an audit_context? > > I'm thinking of the audit_alloc() case where audit_filter_task() > returns AUDIT_DISABLED. Ok, so a task could be marked as filtered but its children would still be auditable and inheriting its parent containerid (as well at its loginuid and sessionid)... > I believe this is the same reason why loginuid and sessionid live > direct
Re: [RFC PATCH ghak32 V2 01/13] audit: add container id
On 2018-04-24 15:01, Paul Moore wrote: > On Mon, Apr 23, 2018 at 10:02 PM, Richard Guy Briggs wrote: > > On 2018-04-23 19:15, Paul Moore wrote: > >> On Sat, Apr 21, 2018 at 10:34 AM, Richard Guy Briggs > >> wrote: > >> > On 2018-04-18 19:47, Paul Moore wrote: > >> >> On Fri, Mar 16, 2018 at 5:00 AM, Richard Guy Briggs > >> >> wrote: > >> >> > Implement the proc fs write to set the audit container ID of a > >> >> > process, > >> >> > emitting an AUDIT_CONTAINER record to document the event. > >> >> > > >> >> > This is a write from the container orchestrator task to a proc entry > >> >> > of > >> >> > the form /proc/PID/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). > >> >> > > >> >> > This will produce a record such as this: > >> >> > type=CONTAINER msg=audit(1519903238.968:261): op=set pid=596 uid=0 > >> >> > subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 auid=0 > >> >> > tty=pts0 ses=1 opid=596 old-contid=18446744073709551615 contid=123455 > >> >> > res=0 > >> >> > > >> >> > 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 container ID values are given in the > >> >> > "contid" fields, while res indicates its success. > >> >> > > >> >> > It is not permitted to self-set, unset or re-set the container ID. A > >> >> > child inherits its parent's container ID, but then can be set only > >> >> > once > >> >> > after. > >> >> > > >> >> > See: https://github.com/linux-audit/audit-kernel/issues/32 > >> >> > > >> >> > Signed-off-by: Richard Guy Briggs > >> >> > --- > >> >> > fs/proc/base.c | 37 > >> >> > include/linux/audit.h | 16 + > >> >> > include/linux/init_task.h | 4 ++- > >> >> > include/linux/sched.h | 1 + > >> >> > include/uapi/linux/audit.h | 2 ++ > >> >> > kernel/auditsc.c | 84 > >> >> > ++ > >> >> > 6 files changed, 143 insertions(+), 1 deletion(-) > > ... > > >> >> > /* audit_rule_data supports filter rules with both integer and string > >> >> > * fields. It corresponds with AUDIT_ADD_RULE, AUDIT_DEL_RULE and > >> >> > diff --git a/kernel/auditsc.c b/kernel/auditsc.c > >> >> > index 4e0a4ac..29c8482 100644 > >> >> > --- a/kernel/auditsc.c > >> >> > +++ b/kernel/auditsc.c > >> >> > @@ -2073,6 +2073,90 @@ int audit_set_loginuid(kuid_t loginuid) > >> >> > return rc; > >> >> > } > >> >> > > >> >> > +static int audit_set_containerid_perm(struct task_struct *task, u64 > >> >> > containerid) > >> >> > +{ > >> >> > + struct task_struct *parent; > >> >> > + u64 pcontainerid, ccontainerid; > >> >> > + > >> >> > + /* Don't allow to set our own containerid */ > >> >> > + if (current == task) > >> >> > + return -EPERM; > >> >> > >> >> Why not? Is there some obvious security concern that I missing? > >> > > >> > We then lose the distinction in the AUDIT_CONTAINER record between the > >> > initiating PID and the target PID. This was outlined in the proposal. > >> > >> I just went back and reread the v3 proposal and I still don't see a > >> good explanation of this. Why is this bad? What's the security > >> concern? > > > > I don't remember, specifically
[RFC PATCH V1 12/12] debug! audit: add container id
Debugging code for verbose output to aid in development. --- fs/proc/base.c | 10 ++ kernel/auditsc.c | 16 2 files changed, 26 insertions(+) diff --git a/fs/proc/base.c b/fs/proc/base.c index f66d1e2..63d1ca4 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -1309,9 +1309,13 @@ static ssize_t proc_containerid_read(struct file *file, char __user *buf, char tmpbuf[TMPBUFLEN*2]; if (!task) + { + pr_info("no inode owner"); return -ESRCH; + } length = scnprintf(tmpbuf, TMPBUFLEN*2, "%llu", audit_get_containerid(task)); put_task_struct(task); + pr_info("read: pid=%d opid=%d contid=%llu", pid_nr(task_tgid(current)), pid_nr(task_tgid(task)), audit_get_containerid(task)); return simple_read_from_buffer(buf, count, ppos, tmpbuf, length); } @@ -1324,14 +1328,19 @@ static ssize_t proc_containerid_write(struct file *file, const char __user *buf, struct task_struct *task = get_proc_task(inode); if (!task) + { + pr_info("no inode owner"); return -ESRCH; + } if (*ppos != 0) { /* No partial writes. */ put_task_struct(task); + pr_info("no partial writes"); return -EINVAL; } rv = kstrtou64_from_user(buf, count, 10, &containerid); + pr_info("write: pid=%d rv=%d count=%ld opid=%d contid=%llu", task_tgid_nr(current), rv, count, task_tgid_nr(task), containerid); if (rv < 0) { put_task_struct(task); return rv; @@ -1339,6 +1348,7 @@ static ssize_t proc_containerid_write(struct file *file, const char __user *buf, rv = audit_set_containerid(task, containerid); put_task_struct(task); + //pr_info("audit_set_containerid: rv=%d", rv); if (rv < 0) return rv; return count; diff --git a/kernel/auditsc.c b/kernel/auditsc.c index fcee34e..39e7dc10 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -2111,16 +2111,28 @@ static int audit_set_containerid_perm(struct task_struct *task, u64 containerid) /* Don't allow to set our own containerid */ if (current == task) + { + pr_info("pid=%d can't set own containerid", task_tgid_nr(task)); return -EPERM; + } /* Don't allow the containerid to be unset */ if (!cid_valid(containerid)) + { + pr_info("can't unset containerid"); return -EINVAL; + } /* if we don't have caps, reject */ if (!capable(CAP_AUDIT_CONTROL)) + { + pr_info("don't have CAP_AUDIT_CONTROL"); return -EPERM; + } /* if containerid is unset, allow */ if (!audit_containerid_set(task)) + { + //pr_info("unset, allow"); return 0; + } /* it is already set, and not inherited from the parent, reject */ ccontainerid = audit_get_containerid(task); rcu_read_lock(); @@ -2131,7 +2143,11 @@ static int audit_set_containerid_perm(struct task_struct *task, u64 containerid) ppid = task_tgid_nr(parent); task_unlock(parent); if (ccontainerid != pcontainerid) + { + pr_info("pid=%d already has contid=%llu set, not inherited from ppid=%d with contid=%llu, can't set containerid %llu", + task_tgid_nr(task), ccontainerid, ppid, pcontainerid, containerid); return -EPERM; + } return 0; } -- 1.8.3.1
[RFC PATCH V1 10/12] audit: add containerid support for seccomp and anom_abend records
Add container ID information to secure computing and abnormal end standalone records. Signed-off-by: Richard Guy Briggs --- kernel/auditsc.c | 10 -- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 0cbd762..fcee34e 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -2569,6 +2569,7 @@ static void audit_log_task(struct audit_buffer *ab) void audit_core_dumps(long signr) { struct audit_buffer *ab; + struct audit_context *context = audit_alloc_local(); if (!audit_enabled) return; @@ -2576,19 +2577,22 @@ void audit_core_dumps(long signr) if (signr == SIGQUIT) /* don't care for those */ return; - ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_ANOM_ABEND); + ab = audit_log_start(context, GFP_KERNEL, AUDIT_ANOM_ABEND); if (unlikely(!ab)) return; audit_log_task(ab); audit_log_format(ab, " sig=%ld res=1", signr); audit_log_end(ab); + audit_log_container_info(context, "abend", audit_get_containerid(current)); + audit_free_context(context); } void __audit_seccomp(unsigned long syscall, long signr, int code) { struct audit_buffer *ab; + struct audit_context *context = audit_alloc_local(); - ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_SECCOMP); + ab = audit_log_start(context, GFP_KERNEL, AUDIT_SECCOMP); if (unlikely(!ab)) return; audit_log_task(ab); @@ -2596,6 +2600,8 @@ void __audit_seccomp(unsigned long syscall, long signr, int code) signr, syscall_get_arch(), syscall, in_compat_syscall(), KSTK_EIP(current), code); audit_log_end(ab); + audit_log_container_info(context, "seccomp", audit_get_containerid(current)); + audit_free_context(context); } struct list_head *audit_killed_trees(void) -- 1.8.3.1
[RFC PATCH V1 11/12] debug audit: add container id
Switch from the 1000 range to the 1300 range for the prototype until it can be worked out why the former aren't showing up in the logs. --- include/uapi/linux/audit.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h index 8443a8f..c392b3b 100644 --- a/include/uapi/linux/audit.h +++ b/include/uapi/linux/audit.h @@ -71,7 +71,8 @@ #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_CONTAINER1020/* Define the container id and information */ +//#define AUDIT_CONTAINER 1020/* Define the container id and information */ +#define AUDIT_CONTAINER1333/* 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 */ -- 1.8.3.1
[RFC PATCH V1 08/12] audit: add containerid support for tty_audit
Add container ID information to tty logging rule standalone records. Signed-off-by: Richard Guy Briggs --- drivers/tty/tty_audit.c | 5 - 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/tty/tty_audit.c b/drivers/tty/tty_audit.c index e30aa6b..48ee4b7 100644 --- a/drivers/tty/tty_audit.c +++ b/drivers/tty/tty_audit.c @@ -66,8 +66,9 @@ static void tty_audit_log(const char *description, dev_t dev, uid_t uid = from_kuid(&init_user_ns, task_uid(tsk)); uid_t loginuid = from_kuid(&init_user_ns, audit_get_loginuid(tsk)); unsigned int sessionid = audit_get_sessionid(tsk); + struct audit_context *context = audit_alloc_local(); - ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_TTY); + ab = audit_log_start(context, GFP_KERNEL, AUDIT_TTY); if (ab) { char name[sizeof(tsk->comm)]; @@ -80,6 +81,8 @@ static void tty_audit_log(const char *description, dev_t dev, audit_log_n_hex(ab, data, size); audit_log_end(ab); } + audit_log_container_info(context, "tty", audit_get_containerid(tsk)); + audit_free_context(context); } /** -- 1.8.3.1
[RFC PATCH V1 09/12] audit: add containerid support for config/feature/user records
Add container ID information to configuration change, feature set change and user generated standalone records. Signed-off-by: Richard Guy Briggs --- kernel/audit.c | 50 -- kernel/auditfilter.c | 5 - 2 files changed, 44 insertions(+), 11 deletions(-) diff --git a/kernel/audit.c b/kernel/audit.c index f5cd0bc..a4c0bad 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -358,8 +358,9 @@ static int audit_log_config_change(char *function_name, u32 new, u32 old, { struct audit_buffer *ab; int rc = 0; + struct audit_context *context = audit_alloc_local(); - ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); + ab = audit_log_start(context, GFP_KERNEL, AUDIT_CONFIG_CHANGE); if (unlikely(!ab)) return rc; audit_log_format(ab, "%s=%u old=%u", function_name, new, old); @@ -369,6 +370,8 @@ static int audit_log_config_change(char *function_name, u32 new, u32 old, allow_changes = 0; /* Something weird, deny request */ audit_log_format(ab, " res=%d", allow_changes); audit_log_end(ab); + audit_log_container_info(context, "config", audit_get_containerid(current)); + audit_free_context(context); return rc; } @@ -1016,7 +1019,8 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type) return err; } -static void audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type) +static void audit_log_common_recv_msg(struct audit_context *context, + struct audit_buffer **ab, u16 msg_type) { uid_t uid = from_kuid(&init_user_ns, current_uid()); pid_t pid = task_tgid_nr(current); @@ -1026,7 +1030,7 @@ static void audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type) return; } - *ab = audit_log_start(NULL, GFP_KERNEL, msg_type); + *ab = audit_log_start(context, GFP_KERNEL, msg_type); if (unlikely(!*ab)) return; audit_log_format(*ab, "pid=%d uid=%u", pid, uid); @@ -1055,16 +1059,19 @@ static void audit_log_feature_change(int which, u32 old_feature, u32 new_feature u32 old_lock, u32 new_lock, int res) { struct audit_buffer *ab; + struct audit_context *context = audit_alloc_local(); if (audit_enabled == AUDIT_OFF) return; - ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_FEATURE_CHANGE); + ab = audit_log_start(context, GFP_KERNEL, AUDIT_FEATURE_CHANGE); audit_log_task_info(ab, current); audit_log_format(ab, " feature=%s old=%u new=%u old_lock=%u new_lock=%u res=%d", audit_feature_names[which], !!old_feature, !!new_feature, !!old_lock, !!new_lock, res); audit_log_end(ab); + audit_log_container_info(context, "feature", audit_get_containerid(current)); + audit_free_context(context); } static int audit_set_feature(struct sk_buff *skb) @@ -1293,13 +1300,15 @@ 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 = audit_alloc_local(); + err = 0; if (msg_type == AUDIT_USER_TTY) { err = tty_audit_push(); if (err) break; } - audit_log_common_recv_msg(&ab, msg_type); + 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, @@ -1315,6 +1324,9 @@ 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_container_info(context, "user", + audit_get_containerid(current)); + audit_free_context(context); } break; case AUDIT_ADD_RULE: @@ -1322,9 +1334,14 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) if (nlmsg_len(nlh) < sizeof(struct audit_rule_data)) return -EINVAL; if (audit_enabled == AUDIT_LOCKED) { - audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE); + struct audit_context *context
[RFC PATCH V1 07/12] audit: add container aux record to watch/tree/mark
Add container ID information to mark, watch and tree rule standalone records. Signed-off-by: Richard Guy Briggs --- kernel/audit_fsnotify.c | 5 - kernel/audit_tree.c | 5 - kernel/audit_watch.c| 33 +++-- 3 files changed, 27 insertions(+), 16 deletions(-) diff --git a/kernel/audit_fsnotify.c b/kernel/audit_fsnotify.c index 52f368b..18c110d 100644 --- a/kernel/audit_fsnotify.c +++ b/kernel/audit_fsnotify.c @@ -124,10 +124,11 @@ static void audit_mark_log_rule_change(struct audit_fsnotify_mark *audit_mark, c { struct audit_buffer *ab; struct audit_krule *rule = audit_mark->rule; + struct audit_context *context = audit_alloc_local(); if (!audit_enabled) return; - ab = audit_log_start(NULL, GFP_NOFS, AUDIT_CONFIG_CHANGE); + ab = audit_log_start(context, GFP_NOFS, AUDIT_CONFIG_CHANGE); if (unlikely(!ab)) return; audit_log_format(ab, "auid=%u ses=%u op=%s", @@ -138,6 +139,8 @@ static void audit_mark_log_rule_change(struct audit_fsnotify_mark *audit_mark, c audit_log_key(ab, rule->filterkey); audit_log_format(ab, " list=%d res=1", rule->listnr); audit_log_end(ab); + audit_log_container_info(context, "config", audit_get_containerid(current)); + audit_free_context(context); } void audit_remove_mark(struct audit_fsnotify_mark *audit_mark) diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c index fd35312..2ad85d4 100644 --- a/kernel/audit_tree.c +++ b/kernel/audit_tree.c @@ -496,8 +496,9 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree) static void audit_tree_log_remove_rule(struct audit_krule *rule) { struct audit_buffer *ab; + struct audit_context *context = audit_alloc_local(); - ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); + ab = audit_log_start(context, GFP_KERNEL, AUDIT_CONFIG_CHANGE); if (unlikely(!ab)) return; audit_log_format(ab, "op=remove_rule"); @@ -506,6 +507,8 @@ static void audit_tree_log_remove_rule(struct audit_krule *rule) audit_log_key(ab, rule->filterkey); audit_log_format(ab, " list=%d res=1", rule->listnr); audit_log_end(ab); + audit_log_container_info(context, "config", audit_get_containerid(current)); + audit_free_context(context); } static void kill_rules(struct audit_tree *tree) diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c index 9eb8b35..60d75a2 100644 --- a/kernel/audit_watch.c +++ b/kernel/audit_watch.c @@ -238,20 +238,25 @@ static struct audit_watch *audit_dupe_watch(struct audit_watch *old) static void audit_watch_log_rule_change(struct audit_krule *r, struct audit_watch *w, char *op) { - if (audit_enabled) { - struct audit_buffer *ab; - ab = audit_log_start(NULL, GFP_NOFS, AUDIT_CONFIG_CHANGE); - if (unlikely(!ab)) - return; - audit_log_format(ab, "auid=%u ses=%u op=%s", -from_kuid(&init_user_ns, audit_get_loginuid(current)), -audit_get_sessionid(current), op); - audit_log_format(ab, " path="); - audit_log_untrustedstring(ab, w->path); - audit_log_key(ab, r->filterkey); - audit_log_format(ab, " list=%d res=1", r->listnr); - audit_log_end(ab); - } + struct audit_buffer *ab; + struct audit_context *context = audit_alloc_local(); + + if (!audit_enabled) + return; + + ab = audit_log_start(context, GFP_NOFS, AUDIT_CONFIG_CHANGE); + if (unlikely(!ab)) + return; + audit_log_format(ab, "auid=%u ses=%u op=%s", +from_kuid(&init_user_ns, audit_get_loginuid(current)), +audit_get_sessionid(current), op); + audit_log_format(ab, " path="); + audit_log_untrustedstring(ab, w->path); + audit_log_key(ab, r->filterkey); + audit_log_format(ab, " list=%d res=1", r->listnr); + audit_log_end(ab); + audit_log_container_info(context, "config", audit_get_containerid(current)); + audit_free_context(context); } /* Update inode info in audit rules based on filesystem event. */ -- 1.8.3.1
[RFC PATCH V1 05/12] audit: add containerid support for ptrace and signals
Add container ID support to ptrace and signals. In particular, the "op" field provides a way to label the auxiliary record to which it is associated. Signed-off-by: Richard Guy Briggs --- include/linux/audit.h | 16 +++- kernel/audit.c| 12 kernel/audit.h| 2 ++ kernel/auditsc.c | 19 +++ 4 files changed, 36 insertions(+), 13 deletions(-) diff --git a/include/linux/audit.h b/include/linux/audit.h index f10ca1b..ed16bb6 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -35,6 +35,7 @@ struct audit_sig_info { uid_t uid; pid_t pid; charctx[0]; + u64 cid; }; struct audit_buffer; @@ -155,8 +156,8 @@ extern void audit_log_link_denied(const char *operation, extern int audit_log_task_context(struct audit_buffer *ab); extern void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk); -extern int audit_log_container_info(struct task_struct *tsk, -struct audit_context *context); +extern int audit_log_container_info(struct audit_context *context, +char *op, u64 containerid); extern int audit_update_lsm_rules(void); @@ -208,8 +209,8 @@ static inline int audit_log_task_context(struct audit_buffer *ab) static inline void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk) { } -static inline int audit_log_container_info(struct task_struct *tsk, - struct audit_context *context); +static inline int audit_log_container_info(struct audit_context *context, + char *op, u64 containerid); { } #define audit_enabled 0 #endif /* CONFIG_AUDIT */ @@ -598,9 +599,14 @@ static inline bool audit_loginuid_set(struct task_struct *tsk) return uid_valid(audit_get_loginuid(tsk)); } +static inline bool cid_valid(u64 containerid) +{ + return containerid != INVALID_CID; +} + static inline bool audit_containerid_set(struct task_struct *tsk) { - return audit_get_containerid(tsk) != INVALID_CID; + return cid_valid(audit_get_containerid(tsk)); } static inline void audit_log_string(struct audit_buffer *ab, const char *buf) diff --git a/kernel/audit.c b/kernel/audit.c index 8dc745f..f5cd0bc 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -142,6 +142,7 @@ struct audit_net { kuid_t audit_sig_uid = INVALID_UID; pid_t audit_sig_pid = -1; u32audit_sig_sid = 0; +u64audit_sig_cid = INVALID_CID; /* Records can be lost in several ways: 0) [suppressed in audit_alloc] @@ -1394,6 +1395,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); @@ -1998,20 +2000,22 @@ void audit_log_session_info(struct audit_buffer *ab) /* * audit_log_container_info - report container info - * @tsk: task to be recorded * @context: task or local context for record + * @op: containerid string description + * @containerid: container ID to report */ -int audit_log_container_info(struct task_struct *tsk, struct audit_context *context) +int audit_log_container_info(struct audit_context *context, + char *op, u64 containerid) { struct audit_buffer *ab; - if (!audit_containerid_set(tsk)) + if (!cid_valid(containerid)) return 0; /* Generate AUDIT_CONTAINER_INFO with container ID */ ab = audit_log_start(context, GFP_KERNEL, AUDIT_CONTAINER_INFO); if (!ab) return -ENOMEM; - audit_log_format(ab, "contid=%llu", audit_get_containerid(tsk)); + audit_log_format(ab, "op=%s contid=%llu", op, containerid); audit_log_end(ab); return 0; } diff --git a/kernel/audit.h b/kernel/audit.h index 683316a..abbabba 100644 --- a/kernel/audit.h +++ b/kernel/audit.h @@ -147,6 +147,7 @@ struct audit_context { kuid_t target_uid; unsigned inttarget_sessionid; u32 target_sid; + u64 target_cid; chartarget_comm[TASK_COMM_LEN]; struct audit_tree_refs *trees, *first_trees; @@ -330,6 +331,7 @@ extern void audit_log_d_path_exe(struct audit_buffer *ab, extern pid_t audit_sig_pid; extern kuid_t audit_sig_uid; extern u32 audit_sig_sid; +extern u64 audit_sig_cid; extern int audit_filter(int msgtype, unsigned int listtype
[RFC PATCH V1 06/12] audit: add support for non-syscall auxiliary records
Standalone audit records have the timestamp and serial number generated on the fly and as such are unique, making them standalone. This is a prototype of a method to generate a local audit context that will be used only for a standalone record and its auxiliary record. The context is discarded immediately after the local associated records are produced. Signed-off-by: Richard Guy Briggs --- include/linux/audit.h | 8 kernel/auditsc.c | 20 +++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/include/linux/audit.h b/include/linux/audit.h index ed16bb6..c0b83cb 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -227,7 +227,9 @@ static inline int audit_log_container_info(struct audit_context *context, /* These are defined in auditsc.c */ /* Public API */ extern int audit_alloc(struct task_struct *task); +extern struct audit_context *audit_alloc_local(void); extern void __audit_free(struct task_struct *task); +extern void audit_free_context(struct audit_context *context); extern void __audit_syscall_entry(int major, unsigned long a0, unsigned long a1, unsigned long a2, unsigned long a3); extern void __audit_syscall_exit(int ret_success, long ret_value); @@ -472,6 +474,12 @@ static inline int audit_alloc(struct task_struct *task) { return 0; } +static inline struct audit_context *audit_alloc_local(void) +{ + return NULL; +} +static inline void audit_free_context(struct audit_context *context) +{ } static inline void audit_free(struct task_struct *task) { } static inline void audit_syscall_entry(int major, unsigned long a0, diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 0e41884..0cbd762 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -959,8 +959,26 @@ int audit_alloc(struct task_struct *tsk) return 0; } -static inline void audit_free_context(struct audit_context *context) +struct audit_context *audit_alloc_local(void) { + struct audit_context *context; + + if (likely(!audit_ever_enabled)) + return NULL; /* Return if not auditing. */ + + context = audit_alloc_context(AUDIT_RECORD_CONTEXT); + if (!context) + return NULL; + context->serial = audit_serial(); + context->ctime = current_kernel_time64(); + context->in_syscall = 1; + return context; +} + +inline 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); -- 1.8.3.1
[RFC PATCH V1 04/12] audit: read container ID of a process
Add support for reading the container ID from the proc filesystem. This is a read from the proc entry of the form /proc/PID/containerid where PID is the process ID of the task whose container ID is sought. The read expects up to a u64 value (unset: 18446744073709551615). Signed-off-by: Richard Guy Briggs --- fs/proc/base.c | 20 ++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/fs/proc/base.c b/fs/proc/base.c index 6ce4fbe..f66d1e2 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -1300,6 +1300,21 @@ static ssize_t proc_sessionid_read(struct file * file, char __user * buf, .llseek = generic_file_llseek, }; +static ssize_t proc_containerid_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; + length = scnprintf(tmpbuf, TMPBUFLEN*2, "%llu", audit_get_containerid(task)); + put_task_struct(task); + return simple_read_from_buffer(buf, count, ppos, tmpbuf, length); +} + static ssize_t proc_containerid_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { @@ -1330,6 +1345,7 @@ static ssize_t proc_containerid_write(struct file *file, const char __user *buf, } static const struct file_operations proc_containerid_operations = { + .read = proc_containerid_read, .write = proc_containerid_write, .llseek = generic_file_llseek, }; @@ -2996,7 +3012,7 @@ static int proc_pid_patch_state(struct seq_file *m, struct pid_namespace *ns, #ifdef CONFIG_AUDITSYSCALL REG("loginuid", S_IWUSR|S_IRUGO, proc_loginuid_operations), REG("sessionid", S_IRUGO, proc_sessionid_operations), - REG("containerid", S_IWUSR, proc_containerid_operations), + REG("containerid", S_IWUSR|S_IRUSR, proc_containerid_operations), #endif #ifdef CONFIG_FAULT_INJECTION REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations), @@ -3391,7 +3407,7 @@ static int proc_tid_comm_permission(struct inode *inode, int mask) #ifdef CONFIG_AUDITSYSCALL REG("loginuid", S_IWUSR|S_IRUGO, proc_loginuid_operations), REG("sessionid", S_IRUGO, proc_sessionid_operations), - REG("containerid", S_IWUSR, proc_containerid_operations), + REG("containerid", S_IWUSR|S_IRUSR, proc_containerid_operations), #endif #ifdef CONFIG_FAULT_INJECTION REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations), -- 1.8.3.1
[RFC PATCH V1 03/12] audit: add containerid filtering
Implement container ID filtering using the AUDIT_CONTAINERID 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_FILTER. This requires support from userspace to be useful. See: https://github.com/linux-audit/audit-userspace/issues/40 Signed-off-by: Richard Guy Briggs --- include/linux/audit.h | 1 + include/uapi/linux/audit.h | 5 - kernel/audit.h | 1 + kernel/auditfilter.c | 47 ++ kernel/auditsc.c | 3 +++ 5 files changed, 56 insertions(+), 1 deletion(-) diff --git a/include/linux/audit.h b/include/linux/audit.h index 3acbe9d..f10ca1b 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -76,6 +76,7 @@ struct audit_field { u32 type; union { u32 val; + u64 val64; kuid_t uid; kgid_t gid; struct { diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h index e83ccbd..8443a8f 100644 --- a/include/uapi/linux/audit.h +++ b/include/uapi/linux/audit.h @@ -262,6 +262,7 @@ #define AUDIT_LOGINUID_SET 24 #define AUDIT_SESSIONID25 /* Session ID */ #define AUDIT_FSTYPE 26 /* FileSystem Type */ +#define AUDIT_CONTAINERID 27 /* Container ID */ /* These are ONLY useful when checking * at syscall exit time (AUDIT_AT_EXIT). */ @@ -342,6 +343,7 @@ enum { #define AUDIT_FEATURE_BITMAP_SESSIONID_FILTER 0x0010 #define AUDIT_FEATURE_BITMAP_LOST_RESET0x0020 #define AUDIT_FEATURE_BITMAP_FILTER_FS 0x0040 +#define AUDIT_FEATURE_BITMAP_CONTAINERID_FILTER0x0080 #define AUDIT_FEATURE_BITMAP_ALL (AUDIT_FEATURE_BITMAP_BACKLOG_LIMIT | \ AUDIT_FEATURE_BITMAP_BACKLOG_WAIT_TIME | \ @@ -349,7 +351,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_FILTER) /* deprecated: AUDIT_VERSION_* */ #define AUDIT_VERSION_LATEST AUDIT_FEATURE_BITMAP_ALL diff --git a/kernel/audit.h b/kernel/audit.h index af5bc59..683316a 100644 --- a/kernel/audit.h +++ b/kernel/audit.h @@ -234,6 +234,7 @@ static inline int audit_hash_ino(u32 ino) extern int audit_match_class(int class, unsigned syscall); extern int audit_comparator(const u32 left, const u32 op, const u32 right); +extern int audit_comparator64(const u64 left, const u32 op, const u64 right); extern int audit_uid_comparator(kuid_t left, u32 op, kuid_t right); extern int audit_gid_comparator(kgid_t left, u32 op, kgid_t right); extern int parent_len(const char *path); diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index d7a807e..c4c8746 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c @@ -410,6 +410,7 @@ static int audit_field_valid(struct audit_entry *entry, struct audit_field *f) /* FALL THROUGH */ case AUDIT_ARCH: case AUDIT_FSTYPE: + case AUDIT_CONTAINERID: if (f->op != Audit_not_equal && f->op != Audit_equal) return -EINVAL; break; @@ -584,6 +585,14 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, } entry->rule.exe = audit_mark; break; + case AUDIT_CONTAINERID: + 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; } } @@ -666,6 +675,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_CONTAINERID: + data->buflen += data->values[i] = sizeof(u64); + for (i = 0; i < sizeof(u64); i++) + ((char *)bufp)[i] = ((char *)&f->
[RFC PATCH V1 02/12] audit: log container info of syscalls
Create a new audit record AUDIT_CONTAINER_INFO to document the container ID 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=c03e syscall=257 success=yes exit=3 a0=ff9c 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= cap_fi= 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= cap_fi= cap_fe=0 cap_fver=0 type=PROCTITLE msg=audit(1519924845.499:257): proctitle=62617368002D6300736C65657020313B206563686F2074657374203E202F746D702F746D70636F6E7461696E65726964 type=UNKNOWN[1332] msg=audit(1519924845.499:257): op=task contid=123458 See: https://github.com/linux-audit/audit-kernel/issues/32 Signed-off-by: Richard Guy Briggs --- include/linux/audit.h | 5 + include/uapi/linux/audit.h | 1 + kernel/audit.c | 20 kernel/auditsc.c | 2 ++ 4 files changed, 28 insertions(+) diff --git a/include/linux/audit.h b/include/linux/audit.h index fe4ba3f..3acbe9d 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -154,6 +154,8 @@ extern void audit_log_link_denied(const char *operation, extern int audit_log_task_context(struct audit_buffer *ab); extern void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk); +extern int audit_log_container_info(struct task_struct *tsk, +struct audit_context *context); extern int audit_update_lsm_rules(void); @@ -205,6 +207,9 @@ static inline int audit_log_task_context(struct audit_buffer *ab) static inline void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk) { } +static inline int audit_log_container_info(struct task_struct *tsk, + struct audit_context *context); +{ } #define audit_enabled 0 #endif /* CONFIG_AUDIT */ diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h index 921a71f..e83ccbd 100644 --- a/include/uapi/linux/audit.h +++ b/include/uapi/linux/audit.h @@ -115,6 +115,7 @@ #define AUDIT_REPLACE 1329/* Replace auditd if this packet unanswerd */ #define AUDIT_KERN_MODULE 1330/* Kernel Module events */ #define AUDIT_FANOTIFY 1331/* Fanotify access decision */ +#define AUDIT_CONTAINER_INFO 1332/* Container ID information */ #define AUDIT_AVC 1400/* SE Linux avc denial or grant */ #define AUDIT_SELINUX_ERR 1401/* Internal SE Linux Errors */ diff --git a/kernel/audit.c b/kernel/audit.c index 5c25449..8dc745f 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -1996,6 +1996,26 @@ void audit_log_session_info(struct audit_buffer *ab) audit_log_format(ab, " auid=%u ses=%u", auid, sessionid); } +/* + * audit_log_container_info - report container info + * @tsk: task to be recorded + * @context: task or local context for record + */ +int audit_log_container_info(struct task_struct *tsk, struct audit_context *context) +{ + struct audit_buffer *ab; + + if (!audit_containerid_set(tsk)) + return 0; + /* Generate AUDIT_CONTAINER_INFO with container ID */ + ab = audit_log_start(context, GFP_KERNEL, AUDIT_CONTAINER_INFO); + if (!ab) + return -ENOMEM; + audit_log_format(ab, "contid=%llu", audit_get_containerid(tsk)); + audit_log_end(ab); + return 0; +} + void audit_log_key(struct audit_buffer *ab, char *key) { audit_log_format(ab, " key="); diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 0ee1e59..f015c25 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -1453,6 +1453,8 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts audit_log_proctitle(tsk, context); + audit_log_container_info(tsk, context); + /* 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
[RFC PATCH V1 00/12] audit: implement container id
Implement audit kernel container ID. This patchset is a preliminary RFC based on the proposal document (V3) posted: https://www.redhat.com/archives/linux-audit/2018-January/msg00014.html The first patch implements the proc fs write to set the audit container ID of a process, emitting an AUDIT_CONTAINER record. The second implements an auxiliary syscall record AUDIT_CONTAINER_INFO if a container ID is present on a task. The third adds filtering to the exit, exclude and user lists. The 4th, implements reading the container ID from the proc filesystem for debugging. This isn't planned for upstream inclusion. The 5th adds signal and ptrace support. The 6th attempts to create a local audit context to be able to bind a standalone record with the container ID record. The 7th, 8th, 9th, 10th patches add container ID records to standalone records. Some of these may end up being syscall auxiliary records and won't need this specific support since they'll be supported via syscalls. The 11th is a temporary workaround due to the AUDIT_CONTAINER records not showing up as do AUDIT_LOGIN records. I suspect this is due to its range (1000 vs 1300), but the intent is to solve it. The 12th adds debug information not intended for upstream for those brave souls wanting to tinker with it in this early state. Feedback please! Here's a quick and dirty test script: echo 123455 > /proc/$$/containerid; echo $? sleep 4& child=$!; sleep 1 echo 18446744073709551615 > /proc/$child/containerid; echo $? echo 123456 > /proc/$child/containerid; echo $? echo 123457 > /proc/$child/containerid; echo $? sleep 1 ausearch -ts recent |grep " contid=18446744073709551615"; echo $? ausearch -ts recent |grep " contid=123456"; echo $? ausearch -ts recent |grep " contid=123457"; echo $? echo self:$$ contid:$( cat /proc/$$/containerid) echo child:$child contid:$( cat /proc/$child/containerid) containerid=123458 key=tmpcontainerid auditctl -a exit,always -F dir=/tmp -F perm=wa -F containerid=$containerid -F key=$key || echo failed to add containerid filter rule bash -c "sleep 1; echo test > /tmp/$key"& child=$! echo $containerid > /proc/$child/containerid sleep 2 rm -f /tmp/$key ausearch -ts recent -k $key || echo failed to find CONTAINER_INFO record auditctl -d exit,always -F dir=/tmp -F perm=wa -F containerid=$containerid -F key=$key || echo failed to add containerid filter rule See: https://github.com/linux-audit/audit-kernel/issues/32 https://github.com/linux-audit/audit-userspace/issues/40 https://github.com/linux-audit/audit-testsuite/issues/64 Richard Guy Briggs (12): audit: add container id audit: log container info of syscalls audit: add containerid filtering audit: read container ID of a process audit: add containerid support for ptrace and signals audit: add support for non-syscall auxiliary records audit: add container aux record to watch/tree/mark audit: add containerid support for tty_audit audit: add containerid support for config/feature/user records audit: add containerid support for seccomp and anom_abend records debug audit: add container id debug! audit: add container id drivers/tty/tty_audit.c| 5 +- fs/proc/base.c | 63 +++ include/linux/audit.h | 36 +++ include/linux/init_task.h | 4 +- include/linux/sched.h | 1 + include/uapi/linux/audit.h | 9 ++- kernel/audit.c | 74 +++--- kernel/audit.h | 3 + kernel/audit_fsnotify.c| 5 +- kernel/audit_tree.c| 5 +- kernel/audit_watch.c | 33 +- kernel/auditfilter.c | 52 ++- kernel/auditsc.c | 154 +++-- 13 files changed, 408 insertions(+), 36 deletions(-) -- 1.8.3.1
[RFC PATCH V1 01/12] audit: add container id
Implement the proc fs write to set the audit container ID of a process, emitting an AUDIT_CONTAINER record to document the event. This is a write from the container orchestrator task to a proc entry of the form /proc/PID/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). This will produce a record such as this: type=UNKNOWN[1333] msg=audit(1519903238.968:261): op=set pid=596 uid=0 subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 auid=0 tty=pts0 ses=1 opid=596 old-contid=18446744073709551615 contid=123455 res=0 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 container ID values are given in the "contid" fields, while res indicates its success. It is not permitted to self-set, unset or re-set the container ID. A child inherits its parent's container ID, but then can be set only once after. See: https://github.com/linux-audit/audit-kernel/issues/32 Signed-off-by: Richard Guy Briggs --- fs/proc/base.c | 37 include/linux/audit.h | 16 + include/linux/init_task.h | 4 ++- include/linux/sched.h | 1 + include/uapi/linux/audit.h | 2 ++ kernel/auditsc.c | 86 ++ 6 files changed, 145 insertions(+), 1 deletion(-) diff --git a/fs/proc/base.c b/fs/proc/base.c index 60316b5..6ce4fbe 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -1299,6 +1299,41 @@ static ssize_t proc_sessionid_read(struct file * file, char __user * buf, .read = proc_sessionid_read, .llseek = generic_file_llseek, }; + +static ssize_t proc_containerid_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + struct inode *inode = file_inode(file); + u64 containerid; + 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, &containerid); + if (rv < 0) { + put_task_struct(task); + return rv; + } + + rv = audit_set_containerid(task, containerid); + put_task_struct(task); + if (rv < 0) + return rv; + return count; +} + +static const struct file_operations proc_containerid_operations = { + .write = proc_containerid_write, + .llseek = generic_file_llseek, +}; + #endif #ifdef CONFIG_FAULT_INJECTION @@ -2961,6 +2996,7 @@ static int proc_pid_patch_state(struct seq_file *m, struct pid_namespace *ns, #ifdef CONFIG_AUDITSYSCALL REG("loginuid", S_IWUSR|S_IRUGO, proc_loginuid_operations), REG("sessionid", S_IRUGO, proc_sessionid_operations), + REG("containerid", S_IWUSR, proc_containerid_operations), #endif #ifdef CONFIG_FAULT_INJECTION REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations), @@ -3355,6 +3391,7 @@ static int proc_tid_comm_permission(struct inode *inode, int mask) #ifdef CONFIG_AUDITSYSCALL REG("loginuid", S_IWUSR|S_IRUGO, proc_loginuid_operations), REG("sessionid", S_IRUGO, proc_sessionid_operations), + REG("containerid", S_IWUSR, proc_containerid_operations), #endif #ifdef CONFIG_FAULT_INJECTION REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations), diff --git a/include/linux/audit.h b/include/linux/audit.h index af410d9..fe4ba3f 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -29,6 +29,7 @@ #define AUDIT_INO_UNSET ((unsigned long)-1) #define AUDIT_DEV_UNSET ((dev_t)-1) +#define INVALID_CID AUDIT_CID_UNSET struct audit_sig_info { uid_t uid; @@ -321,6 +322,7 @@ static inline void audit_ptrace(struct task_struct *t) extern int auditsc_get_stamp(struct audit_context *ctx, struct timespec64 *t, unsigned int *serial); extern int audit_set_loginuid(kuid_t loginuid); +extern int audit_set_containerid(struct task_struct *tsk, u64 containerid); static inline kuid_t audit_get_loginuid(struct task_struct *tsk) { @@ -332,6 +334,11 @@ static inline unsigned int audit_get_sessionid(struct task_struct *tsk) return tsk->sessionid; } +static inline u64 audit_get_containerid(struct task_struct *tsk) +{ + return tsk->containerid; +} + extern void __audit_ipc_obj(struct kern_ipc_perm *ipcp); extern v
Re: [RFC PATCH V1 01/12] audit: add container id
On 2018-03-01 14:41, Richard Guy Briggs wrote: > Implement the proc fs write to set the audit container ID of a process, > emitting an AUDIT_CONTAINER record to document the event. > > This is a write from the container orchestrator task to a proc entry of > the form /proc/PID/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). > > This will produce a record such as this: > type=UNKNOWN[1333] msg=audit(1519903238.968:261): op=set pid=596 uid=0 > subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 auid=0 tty=pts0 > ses=1 opid=596 old-contid=18446744073709551615 contid=123455 res=0 > > 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 container ID values are given in the > "contid" fields, while res indicates its success. > > It is not permitted to self-set, unset or re-set the container ID. A > child inherits its parent's container ID, but then can be set only once > after. There are more restrictions coming later: - check that the child being set has no children or threads yet, or forcibly set them all to the same container ID (assuming they all pass the same tests). This will also prevent an orch from setting its parent and other tit-for-tat games to circumvent the basic checks. > See: https://github.com/linux-audit/audit-kernel/issues/32 > > Signed-off-by: Richard Guy Briggs > --- > fs/proc/base.c | 37 > include/linux/audit.h | 16 + > include/linux/init_task.h | 4 ++- > include/linux/sched.h | 1 + > include/uapi/linux/audit.h | 2 ++ > kernel/auditsc.c | 86 > ++ > 6 files changed, 145 insertions(+), 1 deletion(-) > > diff --git a/fs/proc/base.c b/fs/proc/base.c > index 60316b5..6ce4fbe 100644 > --- a/fs/proc/base.c > +++ b/fs/proc/base.c > @@ -1299,6 +1299,41 @@ static ssize_t proc_sessionid_read(struct file * file, > char __user * buf, > .read = proc_sessionid_read, > .llseek = generic_file_llseek, > }; > + > +static ssize_t proc_containerid_write(struct file *file, const char __user > *buf, > +size_t count, loff_t *ppos) > +{ > + struct inode *inode = file_inode(file); > + u64 containerid; > + 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, &containerid); > + if (rv < 0) { > + put_task_struct(task); > + return rv; > + } > + > + rv = audit_set_containerid(task, containerid); > + put_task_struct(task); > + if (rv < 0) > + return rv; > + return count; > +} > + > +static const struct file_operations proc_containerid_operations = { > + .write = proc_containerid_write, > + .llseek = generic_file_llseek, > +}; > + > #endif > > #ifdef CONFIG_FAULT_INJECTION > @@ -2961,6 +2996,7 @@ static int proc_pid_patch_state(struct seq_file *m, > struct pid_namespace *ns, > #ifdef CONFIG_AUDITSYSCALL > REG("loginuid", S_IWUSR|S_IRUGO, proc_loginuid_operations), > REG("sessionid", S_IRUGO, proc_sessionid_operations), > + REG("containerid", S_IWUSR, proc_containerid_operations), > #endif > #ifdef CONFIG_FAULT_INJECTION > REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations), > @@ -3355,6 +3391,7 @@ static int proc_tid_comm_permission(struct inode > *inode, int mask) > #ifdef CONFIG_AUDITSYSCALL > REG("loginuid", S_IWUSR|S_IRUGO, proc_loginuid_operations), > REG("sessionid", S_IRUGO, proc_sessionid_operations), > + REG("containerid", S_IWUSR, proc_containerid_operations), > #endif > #ifdef CONFIG_FAULT_INJECTION > REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations), > diff --git a/include/linux/audit.h b/include/linux/audit.h > index af410d9..fe4ba3f 100644 > --- a/include/linux/audit.h > +++ b/include/linux/audit.h > @@ -29,6 +29,7 @@ > > #define AUDIT_INO_UNSET ((unsigne
Re: [RFC PATCH V1 00/12] audit: implement container id
On 2018-03-04 16:55, Mimi Zohar wrote: > On Thu, 2018-03-01 at 14:41 -0500, Richard Guy Briggs wrote: > > Implement audit kernel container ID. > > > > This patchset is a preliminary RFC based on the proposal document (V3) > > posted: > > https://www.redhat.com/archives/linux-audit/2018-January/msg00014.html > > > > The first patch implements the proc fs write to set the audit container > > ID of a process, emitting an AUDIT_CONTAINER record. > > > > The second implements an auxiliary syscall record AUDIT_CONTAINER_INFO > > if a container ID is present on a task. > > > > The third adds filtering to the exit, exclude and user lists. > > > > The 4th, implements reading the container ID from the proc filesystem > > for debugging. This isn't planned for upstream inclusion. > > > > The 5th adds signal and ptrace support. > > > > The 6th attempts to create a local audit context to be able to bind a > > standalone record with the container ID record. > > > > The 7th, 8th, 9th, 10th patches add container ID records to standalone > > records. Some of these may end up being syscall auxiliary records and > > won't need this specific support since they'll be supported via > > syscalls. > > > > The 11th is a temporary workaround due to the AUDIT_CONTAINER records > > not showing up as do AUDIT_LOGIN records. I suspect this is due to its > > range (1000 vs 1300), but the intent is to solve it. > > > > The 12th adds debug information not intended for upstream for those > > brave souls wanting to tinker with it in this early state. > > > > Feedback please! > > Which tree can this patch set be applied to? git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/audit.git next > Mimi > > > Here's a quick and dirty test script: > > echo 123455 > /proc/$$/containerid; echo $? > > sleep 4& > > child=$!; sleep 1 > > echo 18446744073709551615 > /proc/$child/containerid; echo $? > > echo 123456 > /proc/$child/containerid; echo $? > > echo 123457 > /proc/$child/containerid; echo $? > > sleep 1 > > ausearch -ts recent |grep " contid=18446744073709551615"; echo $? > > ausearch -ts recent |grep " contid=123456"; echo $? > > ausearch -ts recent |grep " contid=123457"; echo $? > > echo self:$$ contid:$( cat /proc/$$/containerid) > > echo child:$child contid:$( cat /proc/$child/containerid) > > > > containerid=123458 > > key=tmpcontainerid > > auditctl -a exit,always -F dir=/tmp -F perm=wa -F containerid=$containerid > > -F key=$key || echo failed to add containerid filter rule > > bash -c "sleep 1; echo test > /tmp/$key"& > > child=$! > > echo $containerid > /proc/$child/containerid > > sleep 2 > > rm -f /tmp/$key > > ausearch -ts recent -k $key || echo failed to find CONTAINER_INFO record > > auditctl -d exit,always -F dir=/tmp -F perm=wa -F containerid=$containerid > > -F key=$key || echo failed to add containerid filter rule > > > > See: > > https://github.com/linux-audit/audit-kernel/issues/32 > > https://github.com/linux-audit/audit-userspace/issues/40 > > https://github.com/linux-audit/audit-testsuite/issues/64 > > > > Richard Guy Briggs (12): > > audit: add container id > > audit: log container info of syscalls > > audit: add containerid filtering > > audit: read container ID of a process > > audit: add containerid support for ptrace and signals > > audit: add support for non-syscall auxiliary records > > audit: add container aux record to watch/tree/mark > > audit: add containerid support for tty_audit > > audit: add containerid support for config/feature/user records > > audit: add containerid support for seccomp and anom_abend records > > debug audit: add container id > > debug! audit: add container id > > > > drivers/tty/tty_audit.c| 5 +- > > fs/proc/base.c | 63 +++ > > include/linux/audit.h | 36 +++ > > include/linux/init_task.h | 4 +- > > include/linux/sched.h | 1 + > > include/uapi/linux/audit.h | 9 ++- > > kernel/audit.c | 74 +++--- > > kernel/audit.h | 3 + > > kernel/audit_fsnotify.c| 5 +- > > kernel/audit_tree.c| 5 +- > > kernel/audit_watch.c | 33 +- > > kernel/auditfilter.c | 52 ++- > > kernel/auditsc.c | 154 > > +++-- > > 13 files changed, 408 insertions(+), 36 deletions(-) > > > - RGB -- Richard Guy Briggs 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
[RFC PATCH] auditctl: add support for containerid filter
A u64 container identifier has been added to the kernel view of tasks. This allows container orchestrators to label tasks with a unique tamperproof identifier that gets inherited by its children to be able to track the provenance of actions by a container. Add support to libaudit and auditctl for the containerid field to filter based on container identifier. Since it is a u64 and larger than any other numeric field, send it as a string but do the appropriate conversions on each end in each direction. See: https://github.com/linux-audit/audit-userspace/issues/40 See: https://github.com/linux-audit/audit-kernel/issues/32 See: https://github.com/linux-audit/audit-testsuite/issues/64 Signed-off-by: Richard Guy Briggs --- Note: This is a userspace patch for the audit utils to support the kernel RFC patchset, in optimism of kernel support acceptance. ausearch would also need support added. --- docs/auditctl.8| 3 +++ lib/fieldtab.h | 1 + lib/libaudit.c | 36 lib/libaudit.h | 7 +++ src/auditctl-listing.c | 21 + 5 files changed, 68 insertions(+) diff --git a/docs/auditctl.8 b/docs/auditctl.8 index 88466de..8bda43d 100644 --- a/docs/auditctl.8 +++ b/docs/auditctl.8 @@ -210,6 +210,9 @@ Parent's Process ID .B sessionid User's login session ID .TP +.B containerid +Process' container ID +.TP .B subj_user Program's SE Linux User .TP diff --git a/lib/fieldtab.h b/lib/fieldtab.h index c425d5b..755800a 100644 --- a/lib/fieldtab.h +++ b/lib/fieldtab.h @@ -47,6 +47,7 @@ _S(AUDIT_OBJ_TYPE, "obj_type" ) _S(AUDIT_OBJ_LEV_LOW, "obj_lev_low" ) _S(AUDIT_OBJ_LEV_HIGH, "obj_lev_high" ) _S(AUDIT_SESSIONID,"sessionid") +_S(AUDIT_CONTAINERID, "containerid" ) _S(AUDIT_DEVMAJOR, "devmajor" ) _S(AUDIT_DEVMINOR, "devminor" ) diff --git a/lib/libaudit.c b/lib/libaudit.c index aa8258c..2e01a22 100644 --- a/lib/libaudit.c +++ b/lib/libaudit.c @@ -1737,6 +1737,42 @@ int audit_rule_fieldpair_data(struct audit_rule_data **rulep, const char *pair, else if (strcmp(v, "unset") == 0) rule->values[rule->field_count] = 4294967295; break; + case AUDIT_CONTAINERID: { + unsigned long long val; + + if ((audit_get_features() & + AUDIT_FEATURE_BITMAP_CONTAINERID_FILTER) == 0) + return -EAU_FIELDNOSUPPORT; + if (flags != AUDIT_FILTER_EXCLUDE && + flags != AUDIT_FILTER_USER && + flags != AUDIT_FILTER_EXIT) + return -EAU_FIELDNOFILTER; + if (isdigit((char)*(v))) + val = strtoull(v, NULL, 0); + else if (strlen(v) >= 2 && *(v)=='-' && + (isdigit((char)*(v+1 + val = strtoll(v, NULL, 0); + else if (strcmp(v, "unset") == 0) + val = ULLONG_MAX; + else + return -EAU_FIELDVALNUM; + if (errno) + return -EAU_FIELDVALNUM; + vlen = sizeof(unsigned long long); + rule->values[rule->field_count] = vlen; + offset = rule->buflen; + rule->buflen += vlen; + *rulep = realloc(rule, sizeof(*rule) + rule->buflen); + if (*rulep == NULL) { + free(rule); + audit_msg(LOG_ERR, "Cannot realloc memory!\n"); + return -3; + } else { + rule = *rulep; + } + *(unsigned long long*)(&rule->buf[offset]) = val; + break; + } case AUDIT_DEVMAJOR...AUDIT_INODE: case AUDIT_SUCCESS: if (flags != AUDIT_FILTER_EXIT) diff --git a/lib/libaudit.h b/lib/libaudit.h index b681e8d..542ec62 100644 --- a/lib/libaudit.h +++ b/lib/libaudit.h @@ -320,6 +320,9 @@ extern "C" { #ifndef AUDIT_FEATURE_BITMAP_FILTER_FS #define AUDIT_FEATURE_BITMAP_FILTER_FS 0x0040 #endif +#ifndef AUDIT_FEATURE_BITMAP_CONTAINERID_FILTER +#define AUDIT_FEATURE_BITMAP_CONTAINERID_FILTER 0x0080 +#endif /* Defines for interfield comparison update */ #ifndef AUDIT_OBJ_UID @@ -343,6 +346,10 @@ extern "C" { #define AUDIT_FSTYPE 26 #endif +#ifndef AUD
Re: [RFC PATCH V1 01/12] audit: add container id
On 2018-03-04 10:01, Paul Moore wrote: > On Sat, Mar 3, 2018 at 4:19 AM, Serge E. Hallyn wrote: > > On Thu, Mar 01, 2018 at 02:41:04PM -0500, Richard Guy Briggs wrote: > > ... > >> +static inline bool audit_containerid_set(struct task_struct *tsk) > > > > Hi Richard, > > > > the calls to audit_containerid_set() confused me. Could you make it > > is_audit_containerid_set() or audit_containerid_isset()? > > I haven't gone through the entire patchset yet, but I wanted to > quickly comment on this ... I really dislike the > function-names-as-sentences approach and would would greatly prefer > audit_containerid_isset(). I'd be ok with this latter if necessary, but the naming mimics the existing loginuid naming convention. > >> +{ > >> + return audit_get_containerid(tsk) != INVALID_CID; > >> +} > > paul moore - RGB -- Richard Guy Briggs 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: [RFC PATCH V1 01/12] audit: add container id
On 2018-03-15 16:27, Stefan Berger wrote: > On 03/01/2018 02:41 PM, Richard Guy Briggs wrote: > > Implement the proc fs write to set the audit container ID of a process, > > emitting an AUDIT_CONTAINER record to document the event. > > > > This is a write from the container orchestrator task to a proc entry of > > the form /proc/PID/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). > > > > This will produce a record such as this: > > type=UNKNOWN[1333] msg=audit(1519903238.968:261): op=set pid=596 uid=0 > > subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 auid=0 tty=pts0 > > ses=1 opid=596 old-contid=18446744073709551615 contid=123455 res=0 > > > > 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 container ID values are given in the > > "contid" fields, while res indicates its success. > > > > It is not permitted to self-set, unset or re-set the container ID. A > > child inherits its parent's container ID, but then can be set only once > > after. > > > > See: https://github.com/linux-audit/audit-kernel/issues/32 > > > > > > /* audit_rule_data supports filter rules with both integer and string > >* fields. It corresponds with AUDIT_ADD_RULE, AUDIT_DEL_RULE and > > diff --git a/kernel/auditsc.c b/kernel/auditsc.c > > index 4e0a4ac..0ee1e59 100644 > > --- a/kernel/auditsc.c > > +++ b/kernel/auditsc.c > > @@ -2073,6 +2073,92 @@ int audit_set_loginuid(kuid_t loginuid) > > return rc; > > } > > > > +static int audit_set_containerid_perm(struct task_struct *task, u64 > > containerid) > > +{ > > + struct task_struct *parent; > > + u64 pcontainerid, ccontainerid; > > + pid_t ppid; > > + > > + /* Don't allow to set our own containerid */ > > + if (current == task) > > + return -EPERM; > > + /* Don't allow the containerid to be unset */ > > + if (!cid_valid(containerid)) > > + return -EINVAL; > > + /* if we don't have caps, reject */ > > + if (!capable(CAP_AUDIT_CONTROL)) > > + return -EPERM; > > + /* if containerid is unset, allow */ > > + if (!audit_containerid_set(task)) > > + return 0; > > I am wondering whether there should be a check for the target process that > will receive the containerid to not have CAP_SYS_ADMIN that would otherwise > allow it to arbitrarily unshare()/clone() and leave the set of namespaces > that may make up the container whose containerid we assign here? This is a reasonable question. This has been debated and I understood the conclusion was that without a clear definition of a "container", the task still remains in that container that just now has more sub-namespaces (in the case of hierarchical namespaces), we don't want to restrict it in such a way and that allows it to create nested containers. I see setns being more problematic if it could switch to another existing namespace that was set up by the orchestrator for a different container. The coming v2 patchset acknowledges this situation with the network namespace being potentially shared by multiple containers. This is the motivation for the code below that allows to set the containerid even if it is already inherited from its parent. > > + /* it is already set, and not inherited from the parent, reject */ > > + ccontainerid = audit_get_containerid(task); > > + rcu_read_lock(); > > + parent = rcu_dereference(task->real_parent); > > + rcu_read_unlock(); > > + task_lock(parent); > > + pcontainerid = audit_get_containerid(parent); > > + ppid = task_tgid_nr(parent); > > ppid not needed... Thanks for catching this. It was the vestige of a failed devel experiment that didn't flush that useless appendage. :-) > > + task_unlock(parent); > > + if (ccontainerid != pcontainerid) > > + return -EPERM; > > + return 0; > > +} > > + > > +static void audit_log_set_containerid(struct task_struct *task, u64 > > oldcontainerid, > > + u64 containerid, int rc) > > +{ > > + struct audit_buffer *ab; > > + uid_t uid; > > + struct tty_struct *tty; > > + > &g
[RFC PATCH ghak32 V2 04/13] audit: add containerid filtering
Implement container ID filtering using the AUDIT_CONTAINERID 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_FILTER. This requires support from userspace to be useful. See: https://github.com/linux-audit/audit-userspace/issues/40 Signed-off-by: Richard Guy Briggs --- include/linux/audit.h | 1 + include/uapi/linux/audit.h | 5 - kernel/audit.h | 1 + kernel/auditfilter.c | 47 ++ kernel/auditsc.c | 3 +++ 5 files changed, 56 insertions(+), 1 deletion(-) diff --git a/include/linux/audit.h b/include/linux/audit.h index 3acbe9d..f10ca1b 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -76,6 +76,7 @@ struct audit_field { u32 type; union { u32 val; + u64 val64; kuid_t uid; kgid_t gid; struct { diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h index e83ccbd..8443a8f 100644 --- a/include/uapi/linux/audit.h +++ b/include/uapi/linux/audit.h @@ -262,6 +262,7 @@ #define AUDIT_LOGINUID_SET 24 #define AUDIT_SESSIONID25 /* Session ID */ #define AUDIT_FSTYPE 26 /* FileSystem Type */ +#define AUDIT_CONTAINERID 27 /* Container ID */ /* These are ONLY useful when checking * at syscall exit time (AUDIT_AT_EXIT). */ @@ -342,6 +343,7 @@ enum { #define AUDIT_FEATURE_BITMAP_SESSIONID_FILTER 0x0010 #define AUDIT_FEATURE_BITMAP_LOST_RESET0x0020 #define AUDIT_FEATURE_BITMAP_FILTER_FS 0x0040 +#define AUDIT_FEATURE_BITMAP_CONTAINERID_FILTER0x0080 #define AUDIT_FEATURE_BITMAP_ALL (AUDIT_FEATURE_BITMAP_BACKLOG_LIMIT | \ AUDIT_FEATURE_BITMAP_BACKLOG_WAIT_TIME | \ @@ -349,7 +351,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_FILTER) /* deprecated: AUDIT_VERSION_* */ #define AUDIT_VERSION_LATEST AUDIT_FEATURE_BITMAP_ALL diff --git a/kernel/audit.h b/kernel/audit.h index 214e149..aaa651a 100644 --- a/kernel/audit.h +++ b/kernel/audit.h @@ -234,6 +234,7 @@ static inline int audit_hash_ino(u32 ino) extern int audit_match_class(int class, unsigned syscall); extern int audit_comparator(const u32 left, const u32 op, const u32 right); +extern int audit_comparator64(const u64 left, const u32 op, const u64 right); extern int audit_uid_comparator(kuid_t left, u32 op, kuid_t right); extern int audit_gid_comparator(kgid_t left, u32 op, kgid_t right); extern int parent_len(const char *path); diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index d7a807e..c4c8746 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c @@ -410,6 +410,7 @@ static int audit_field_valid(struct audit_entry *entry, struct audit_field *f) /* FALL THROUGH */ case AUDIT_ARCH: case AUDIT_FSTYPE: + case AUDIT_CONTAINERID: if (f->op != Audit_not_equal && f->op != Audit_equal) return -EINVAL; break; @@ -584,6 +585,14 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, } entry->rule.exe = audit_mark; break; + case AUDIT_CONTAINERID: + 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; } } @@ -666,6 +675,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_CONTAINERID: + data->buflen += data->values[i] = sizeof(u64); + for (i = 0; i < sizeof(u64); i++) + ((char *)bufp)[i] = ((char *)&f->
[RFC PATCH ghak32 V2 13/13] debug audit: read container ID of a process
Add support for reading the container ID from the proc filesystem. This is a read from the proc entry of the form /proc/PID/containerid where PID is the process ID of the task whose container ID is sought. The read expects up to a u64 value (unset: 18446744073709551615). Signed-off-by: Richard Guy Briggs --- fs/proc/base.c | 20 ++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/fs/proc/base.c b/fs/proc/base.c index 6ce4fbe..f66d1e2 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -1300,6 +1300,21 @@ static ssize_t proc_sessionid_read(struct file * file, char __user * buf, .llseek = generic_file_llseek, }; +static ssize_t proc_containerid_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; + length = scnprintf(tmpbuf, TMPBUFLEN*2, "%llu", audit_get_containerid(task)); + put_task_struct(task); + return simple_read_from_buffer(buf, count, ppos, tmpbuf, length); +} + static ssize_t proc_containerid_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { @@ -1330,6 +1345,7 @@ static ssize_t proc_containerid_write(struct file *file, const char __user *buf, } static const struct file_operations proc_containerid_operations = { + .read = proc_containerid_read, .write = proc_containerid_write, .llseek = generic_file_llseek, }; @@ -2996,7 +3012,7 @@ static int proc_pid_patch_state(struct seq_file *m, struct pid_namespace *ns, #ifdef CONFIG_AUDITSYSCALL REG("loginuid", S_IWUSR|S_IRUGO, proc_loginuid_operations), REG("sessionid", S_IRUGO, proc_sessionid_operations), - REG("containerid", S_IWUSR, proc_containerid_operations), + REG("containerid", S_IWUSR|S_IRUSR, proc_containerid_operations), #endif #ifdef CONFIG_FAULT_INJECTION REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations), @@ -3391,7 +3407,7 @@ static int proc_tid_comm_permission(struct inode *inode, int mask) #ifdef CONFIG_AUDITSYSCALL REG("loginuid", S_IWUSR|S_IRUGO, proc_loginuid_operations), REG("sessionid", S_IRUGO, proc_sessionid_operations), - REG("containerid", S_IWUSR, proc_containerid_operations), + REG("containerid", S_IWUSR|S_IRUSR, proc_containerid_operations), #endif #ifdef CONFIG_FAULT_INJECTION REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations), -- 1.8.3.1
[RFC PATCH ghak32 V2 12/13] audit: NETFILTER_PKT: record each container ID associated with a netNS
Add container ID auxiliary record(s) to NETFILTER_PKT event standalone records. Iterate through all potential container IDs associated with a network namespace. Signed-off-by: Richard Guy Briggs --- kernel/audit.c | 1 + kernel/auditsc.c | 2 ++ net/netfilter/xt_AUDIT.c | 15 ++- 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/kernel/audit.c b/kernel/audit.c index 08662b4..3c77e47 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -2102,6 +2102,7 @@ int audit_log_container_info(struct audit_context *context, audit_log_end(ab); return 0; } +EXPORT_SYMBOL(audit_log_container_info); void audit_log_key(struct audit_buffer *ab, char *key) { diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 208da962..af68d01 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -975,6 +975,7 @@ struct audit_context *audit_alloc_local(void) context->in_syscall = 1; return context; } +EXPORT_SYMBOL(audit_alloc_local); inline void audit_free_context(struct audit_context *context) { @@ -989,6 +990,7 @@ 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, diff --git a/net/netfilter/xt_AUDIT.c b/net/netfilter/xt_AUDIT.c index c502419..edaa456 100644 --- a/net/netfilter/xt_AUDIT.c +++ b/net/netfilter/xt_AUDIT.c @@ -71,10 +71,14 @@ static bool audit_ip6(struct audit_buffer *ab, struct sk_buff *skb) { struct audit_buffer *ab; int fam = -1; + struct audit_context *context = audit_alloc_local(); + struct audit_containerid *cont; + int i = 0; + struct net *net; if (audit_enabled == 0) goto errout; - ab = audit_log_start(NULL, GFP_ATOMIC, AUDIT_NETFILTER_PKT); + ab = audit_log_start(context, GFP_ATOMIC, AUDIT_NETFILTER_PKT); if (ab == NULL) goto errout; @@ -104,7 +108,16 @@ static bool audit_ip6(struct audit_buffer *ab, struct sk_buff *skb) audit_log_end(ab); + net = sock_net(NETLINK_CB(skb).sk); + list_for_each_entry(cont, &net->audit_containerid, list) { + char buf[14]; + + sprintf(buf, "net%u", i++); + audit_log_container_info(context, buf, cont->id); + } + errout: + audit_free_context(context); return XT_CONTINUE; } -- 1.8.3.1
[RFC PATCH ghak32 V2 09/13] audit: add containerid support for config/feature/user records
Add container ID auxiliary records to configuration change, feature set change and user generated standalone records. Signed-off-by: Richard Guy Briggs --- kernel/audit.c | 50 -- kernel/auditfilter.c | 5 - 2 files changed, 44 insertions(+), 11 deletions(-) diff --git a/kernel/audit.c b/kernel/audit.c index b238be5..08662b4 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -400,8 +400,9 @@ static int audit_log_config_change(char *function_name, u32 new, u32 old, { struct audit_buffer *ab; int rc = 0; + struct audit_context *context = audit_alloc_local(); - ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); + ab = audit_log_start(context, GFP_KERNEL, AUDIT_CONFIG_CHANGE); if (unlikely(!ab)) return rc; audit_log_format(ab, "%s=%u old=%u", function_name, new, old); @@ -411,6 +412,8 @@ static int audit_log_config_change(char *function_name, u32 new, u32 old, allow_changes = 0; /* Something weird, deny request */ audit_log_format(ab, " res=%d", allow_changes); audit_log_end(ab); + audit_log_container_info(context, "config", audit_get_containerid(current)); + audit_free_context(context); return rc; } @@ -1058,7 +1061,8 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type) return err; } -static void audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type) +static void audit_log_common_recv_msg(struct audit_context *context, + struct audit_buffer **ab, u16 msg_type) { uid_t uid = from_kuid(&init_user_ns, current_uid()); pid_t pid = task_tgid_nr(current); @@ -1068,7 +1072,7 @@ static void audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type) return; } - *ab = audit_log_start(NULL, GFP_KERNEL, msg_type); + *ab = audit_log_start(context, GFP_KERNEL, msg_type); if (unlikely(!*ab)) return; audit_log_format(*ab, "pid=%d uid=%u", pid, uid); @@ -1097,11 +1101,12 @@ static void audit_log_feature_change(int which, u32 old_feature, u32 new_feature u32 old_lock, u32 new_lock, int res) { struct audit_buffer *ab; + struct audit_context *context = audit_alloc_local(); if (audit_enabled == AUDIT_OFF) return; - ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_FEATURE_CHANGE); + ab = audit_log_start(context, GFP_KERNEL, AUDIT_FEATURE_CHANGE); if (!ab) return; audit_log_task_info(ab, current); @@ -1109,6 +1114,8 @@ static void audit_log_feature_change(int which, u32 old_feature, u32 new_feature audit_feature_names[which], !!old_feature, !!new_feature, !!old_lock, !!new_lock, res); audit_log_end(ab); + audit_log_container_info(context, "feature", audit_get_containerid(current)); + audit_free_context(context); } static int audit_set_feature(struct sk_buff *skb) @@ -1337,13 +1344,15 @@ 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 = audit_alloc_local(); + err = 0; if (msg_type == AUDIT_USER_TTY) { err = tty_audit_push(); if (err) break; } - audit_log_common_recv_msg(&ab, msg_type); + 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, @@ -1359,6 +1368,9 @@ 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_container_info(context, "user", + audit_get_containerid(current)); + audit_free_context(context); } break; case AUDIT_ADD_RULE: @@ -1366,9 +1378,14 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) if (nlmsg_len(nlh) < sizeof(struct audit_rule_data)) return -EINVAL; if (audit_enabled == AUDIT_LOCKED) { - audit_log_common_recv_msg(&
[RFC PATCH ghak32 V2 08/13] audit: add containerid support for tty_audit
Add container ID auxiliary record to tty logging rule event standalone records. Signed-off-by: Richard Guy Briggs --- drivers/tty/tty_audit.c | 5 - 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/tty/tty_audit.c b/drivers/tty/tty_audit.c index e30aa6b..48ee4b7 100644 --- a/drivers/tty/tty_audit.c +++ b/drivers/tty/tty_audit.c @@ -66,8 +66,9 @@ static void tty_audit_log(const char *description, dev_t dev, uid_t uid = from_kuid(&init_user_ns, task_uid(tsk)); uid_t loginuid = from_kuid(&init_user_ns, audit_get_loginuid(tsk)); unsigned int sessionid = audit_get_sessionid(tsk); + struct audit_context *context = audit_alloc_local(); - ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_TTY); + ab = audit_log_start(context, GFP_KERNEL, AUDIT_TTY); if (ab) { char name[sizeof(tsk->comm)]; @@ -80,6 +81,8 @@ static void tty_audit_log(const char *description, dev_t dev, audit_log_n_hex(ab, data, size); audit_log_end(ab); } + audit_log_container_info(context, "tty", audit_get_containerid(tsk)); + audit_free_context(context); } /** -- 1.8.3.1
[RFC PATCH ghak32 V2 11/13] audit: add support for containerid to network namespaces
Audit events could happen in a network namespace outside of a task context due to packets received from the net that trigger an auditing rule prior to being associated with a running task. The network namespace could in use by multiple containers by association to the tasks in that network namespace. We still want a way to attribute these events to any potential containers. Keep a list per network namespace to track these container identifiiers. Add/increment the container identifier on: - initial setting of the container id via /proc - clone/fork call that inherits a container identifier - unshare call that inherits a container identifier - setns call that inherits a container identifier Delete/decrement the container identifier on: - an inherited container id 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/32 See: https://github.com/linux-audit/audit-testsuite/issues/64 Signed-off-by: Richard Guy Briggs --- include/linux/audit.h | 7 +++ include/net/net_namespace.h | 12 kernel/auditsc.c| 9 ++--- kernel/nsproxy.c| 6 ++ net/core/net_namespace.c| 45 + 5 files changed, 76 insertions(+), 3 deletions(-) diff --git a/include/linux/audit.h b/include/linux/audit.h index c0b83cb..d9afb7d 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -26,6 +26,7 @@ #include #include #include +#include #define AUDIT_INO_UNSET ((unsigned long)-1) #define AUDIT_DEV_UNSET ((dev_t)-1) @@ -88,6 +89,12 @@ struct audit_field { u32 op; }; +struct audit_containerid { + struct list_headlist; + u64 id; + refcount_t refcount; +}; + extern int is_audit_feature_set(int which); extern int __init audit_register_class(int class, unsigned *list); diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h index 0490084..343a428 100644 --- a/include/net/net_namespace.h +++ b/include/net/net_namespace.h @@ -33,6 +33,7 @@ #include #include #include +#include struct user_namespace; struct proc_dir_entry; @@ -150,6 +151,7 @@ struct net { #endif struct sock *diag_nlsk; atomic_tfnhe_genid; + struct list_headaudit_containerid; } __randomize_layout; #include @@ -301,6 +303,16 @@ static inline struct net *read_pnet(const possible_net_t *pnet) #define __net_initconst__initconst #endif +#ifdef CONFIG_NET_NS +void net_add_audit_containerid(struct net *net, u64 containerid); +void net_del_audit_containerid(struct net *net, u64 containerid); +#else +static inline void net_add_audit_containerid(struct net *, u64) +{ } +static inline void net_del_audit_containerid(struct net *, u64) +{ } +#endif + int peernet2id_alloc(struct net *net, struct net *peer); int peernet2id(struct net *net, struct net *peer); bool peernet_has_id(struct net *net, struct net *peer); diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 2f02ed9..208da962 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -75,6 +75,7 @@ #include #include #include +#include #include "audit.h" @@ -2175,16 +2176,18 @@ static void audit_log_set_containerid(struct task_struct *task, u64 oldcontainer */ int audit_set_containerid(struct task_struct *task, u64 containerid) { - u64 oldcontainerid; + u64 oldcontainerid = audit_get_containerid(task); int rc; - - oldcontainerid = audit_get_containerid(task); + struct net *net = task->nsproxy->net_ns; rc = audit_set_containerid_perm(task, containerid); if (!rc) { + if (cid_valid(oldcontainerid)) + net_del_audit_containerid(net, oldcontainerid); task_lock(task); task->containerid = containerid; task_unlock(task); + net_add_audit_containerid(net, containerid); } audit_log_set_containerid(task, oldcontainerid, containerid, rc); diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c index f6c5d33..d9f1090 100644 --- a/kernel/nsproxy.c +++ b/kernel/nsproxy.c @@ -140,6 +140,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 containerid = audit_get_containerid(tsk); if (likely(!(flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC | CLONE_NEWPID | CLONE_NEWNET | @@ -167,6 +168,7 @@ int copy_namespaces(unsigned long flags, struct task_struct *tsk) return PTR_ERR(new_ns); tsk->nsproxy = new_ns; + net_add_audit_containerid(new_ns->net_ns
[RFC PATCH ghak32 V2 10/13] audit: add containerid support for seccomp and anom_abend records
Add container ID auxiliary records to secure computing and abnormal end standalone records. Signed-off-by: Richard Guy Briggs --- kernel/auditsc.c | 10 -- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 7103d23..2f02ed9 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -2571,6 +2571,7 @@ static void audit_log_task(struct audit_buffer *ab) void audit_core_dumps(long signr) { struct audit_buffer *ab; + struct audit_context *context = audit_alloc_local(); if (!audit_enabled) return; @@ -2578,19 +2579,22 @@ void audit_core_dumps(long signr) if (signr == SIGQUIT) /* don't care for those */ return; - ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_ANOM_ABEND); + ab = audit_log_start(context, GFP_KERNEL, AUDIT_ANOM_ABEND); if (unlikely(!ab)) return; audit_log_task(ab); audit_log_format(ab, " sig=%ld res=1", signr); audit_log_end(ab); + audit_log_container_info(context, "abend", audit_get_containerid(current)); + audit_free_context(context); } void __audit_seccomp(unsigned long syscall, long signr, int code) { struct audit_buffer *ab; + struct audit_context *context = audit_alloc_local(); - ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_SECCOMP); + ab = audit_log_start(context, GFP_KERNEL, AUDIT_SECCOMP); if (unlikely(!ab)) return; audit_log_task(ab); @@ -2598,6 +2602,8 @@ void __audit_seccomp(unsigned long syscall, long signr, int code) signr, syscall_get_arch(), syscall, in_compat_syscall(), KSTK_EIP(current), code); audit_log_end(ab); + audit_log_container_info(context, "seccomp", audit_get_containerid(current)); + audit_free_context(context); } struct list_head *audit_killed_trees(void) -- 1.8.3.1
[RFC PATCH ghak32 V2 07/13] audit: add container aux record to watch/tree/mark
Add container ID auxiliary record to mark, watch and tree rule configuration standalone records. Signed-off-by: Richard Guy Briggs --- kernel/audit_fsnotify.c | 5 - kernel/audit_tree.c | 5 - kernel/audit_watch.c| 33 +++-- 3 files changed, 27 insertions(+), 16 deletions(-) diff --git a/kernel/audit_fsnotify.c b/kernel/audit_fsnotify.c index 52f368b..18c110d 100644 --- a/kernel/audit_fsnotify.c +++ b/kernel/audit_fsnotify.c @@ -124,10 +124,11 @@ static void audit_mark_log_rule_change(struct audit_fsnotify_mark *audit_mark, c { struct audit_buffer *ab; struct audit_krule *rule = audit_mark->rule; + struct audit_context *context = audit_alloc_local(); if (!audit_enabled) return; - ab = audit_log_start(NULL, GFP_NOFS, AUDIT_CONFIG_CHANGE); + ab = audit_log_start(context, GFP_NOFS, AUDIT_CONFIG_CHANGE); if (unlikely(!ab)) return; audit_log_format(ab, "auid=%u ses=%u op=%s", @@ -138,6 +139,8 @@ static void audit_mark_log_rule_change(struct audit_fsnotify_mark *audit_mark, c audit_log_key(ab, rule->filterkey); audit_log_format(ab, " list=%d res=1", rule->listnr); audit_log_end(ab); + audit_log_container_info(context, "config", audit_get_containerid(current)); + audit_free_context(context); } void audit_remove_mark(struct audit_fsnotify_mark *audit_mark) diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c index 67e6956..7c085be 100644 --- a/kernel/audit_tree.c +++ b/kernel/audit_tree.c @@ -496,8 +496,9 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree) static void audit_tree_log_remove_rule(struct audit_krule *rule) { struct audit_buffer *ab; + struct audit_context *context = audit_alloc_local(); - ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); + ab = audit_log_start(context, GFP_KERNEL, AUDIT_CONFIG_CHANGE); if (unlikely(!ab)) return; audit_log_format(ab, "op=remove_rule"); @@ -506,6 +507,8 @@ static void audit_tree_log_remove_rule(struct audit_krule *rule) audit_log_key(ab, rule->filterkey); audit_log_format(ab, " list=%d res=1", rule->listnr); audit_log_end(ab); + audit_log_container_info(context, "config", audit_get_containerid(current)); + audit_free_context(context); } static void kill_rules(struct audit_tree *tree) diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c index 9eb8b35..60d75a2 100644 --- a/kernel/audit_watch.c +++ b/kernel/audit_watch.c @@ -238,20 +238,25 @@ static struct audit_watch *audit_dupe_watch(struct audit_watch *old) static void audit_watch_log_rule_change(struct audit_krule *r, struct audit_watch *w, char *op) { - if (audit_enabled) { - struct audit_buffer *ab; - ab = audit_log_start(NULL, GFP_NOFS, AUDIT_CONFIG_CHANGE); - if (unlikely(!ab)) - return; - audit_log_format(ab, "auid=%u ses=%u op=%s", -from_kuid(&init_user_ns, audit_get_loginuid(current)), -audit_get_sessionid(current), op); - audit_log_format(ab, " path="); - audit_log_untrustedstring(ab, w->path); - audit_log_key(ab, r->filterkey); - audit_log_format(ab, " list=%d res=1", r->listnr); - audit_log_end(ab); - } + struct audit_buffer *ab; + struct audit_context *context = audit_alloc_local(); + + if (!audit_enabled) + return; + + ab = audit_log_start(context, GFP_NOFS, AUDIT_CONFIG_CHANGE); + if (unlikely(!ab)) + return; + audit_log_format(ab, "auid=%u ses=%u op=%s", +from_kuid(&init_user_ns, audit_get_loginuid(current)), +audit_get_sessionid(current), op); + audit_log_format(ab, " path="); + audit_log_untrustedstring(ab, w->path); + audit_log_key(ab, r->filterkey); + audit_log_format(ab, " list=%d res=1", r->listnr); + audit_log_end(ab); + audit_log_container_info(context, "config", audit_get_containerid(current)); + audit_free_context(context); } /* Update inode info in audit rules based on filesystem event. */ -- 1.8.3.1
[RFC PATCH ghak32 V2 06/13] audit: add support for non-syscall auxiliary records
Standalone audit records have the timestamp and serial number generated on the fly and as such are unique, making them standalone. This new function audit_alloc_local() generates a local audit context that will be used only for a standalone record and its auxiliary record(s). The context is discarded immediately after the local associated records are produced. Signed-off-by: Richard Guy Briggs --- include/linux/audit.h | 8 kernel/auditsc.c | 20 +++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/include/linux/audit.h b/include/linux/audit.h index ed16bb6..c0b83cb 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -227,7 +227,9 @@ static inline int audit_log_container_info(struct audit_context *context, /* These are defined in auditsc.c */ /* Public API */ extern int audit_alloc(struct task_struct *task); +extern struct audit_context *audit_alloc_local(void); extern void __audit_free(struct task_struct *task); +extern void audit_free_context(struct audit_context *context); extern void __audit_syscall_entry(int major, unsigned long a0, unsigned long a1, unsigned long a2, unsigned long a3); extern void __audit_syscall_exit(int ret_success, long ret_value); @@ -472,6 +474,12 @@ static inline int audit_alloc(struct task_struct *task) { return 0; } +static inline struct audit_context *audit_alloc_local(void) +{ + return NULL; +} +static inline void audit_free_context(struct audit_context *context) +{ } static inline void audit_free(struct task_struct *task) { } static inline void audit_syscall_entry(int major, unsigned long a0, diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 2932ef1..7103d23 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -959,8 +959,26 @@ int audit_alloc(struct task_struct *tsk) return 0; } -static inline void audit_free_context(struct audit_context *context) +struct audit_context *audit_alloc_local(void) { + struct audit_context *context; + + if (!audit_ever_enabled) + return NULL; /* Return if not auditing. */ + + context = audit_alloc_context(AUDIT_RECORD_CONTEXT); + if (!context) + return NULL; + context->serial = audit_serial(); + context->ctime = current_kernel_time64(); + context->in_syscall = 1; + return context; +} + +inline 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); -- 1.8.3.1
[RFC PATCH ghak32 V2 05/13] audit: add containerid support for ptrace and signals
Add container ID support to ptrace and signals. In particular, the "op" field provides a way to label the auxiliary record to which it is associated. Signed-off-by: Richard Guy Briggs --- include/linux/audit.h | 16 +++- kernel/audit.c| 12 kernel/audit.h| 2 ++ kernel/auditsc.c | 19 +++ 4 files changed, 36 insertions(+), 13 deletions(-) diff --git a/include/linux/audit.h b/include/linux/audit.h index f10ca1b..ed16bb6 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -35,6 +35,7 @@ struct audit_sig_info { uid_t uid; pid_t pid; charctx[0]; + u64 cid; }; struct audit_buffer; @@ -155,8 +156,8 @@ extern void audit_log_link_denied(const char *operation, extern int audit_log_task_context(struct audit_buffer *ab); extern void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk); -extern int audit_log_container_info(struct task_struct *tsk, -struct audit_context *context); +extern int audit_log_container_info(struct audit_context *context, +char *op, u64 containerid); extern int audit_update_lsm_rules(void); @@ -208,8 +209,8 @@ static inline int audit_log_task_context(struct audit_buffer *ab) static inline void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk) { } -static inline int audit_log_container_info(struct task_struct *tsk, - struct audit_context *context); +static inline int audit_log_container_info(struct audit_context *context, + char *op, u64 containerid); { } #define audit_enabled 0 #endif /* CONFIG_AUDIT */ @@ -598,9 +599,14 @@ static inline bool audit_loginuid_set(struct task_struct *tsk) return uid_valid(audit_get_loginuid(tsk)); } +static inline bool cid_valid(u64 containerid) +{ + return containerid != INVALID_CID; +} + static inline bool audit_containerid_set(struct task_struct *tsk) { - return audit_get_containerid(tsk) != INVALID_CID; + return cid_valid(audit_get_containerid(tsk)); } static inline void audit_log_string(struct audit_buffer *ab, const char *buf) diff --git a/kernel/audit.c b/kernel/audit.c index a12f21f..b238be5 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -142,6 +142,7 @@ struct audit_net { kuid_t audit_sig_uid = INVALID_UID; pid_t audit_sig_pid = -1; u32audit_sig_sid = 0; +u64audit_sig_cid = INVALID_CID; /* Records can be lost in several ways: 0) [suppressed in audit_alloc] @@ -1438,6 +1439,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); @@ -2051,20 +2053,22 @@ void audit_log_session_info(struct audit_buffer *ab) /* * audit_log_container_info - report container info - * @tsk: task to be recorded * @context: task or local context for record + * @op: containerid string description + * @containerid: container ID to report */ -int audit_log_container_info(struct task_struct *tsk, struct audit_context *context) +int audit_log_container_info(struct audit_context *context, + char *op, u64 containerid) { struct audit_buffer *ab; - if (!audit_containerid_set(tsk)) + if (!cid_valid(containerid)) return 0; /* Generate AUDIT_CONTAINER_INFO with container ID */ ab = audit_log_start(context, GFP_KERNEL, AUDIT_CONTAINER_INFO); if (!ab) return -ENOMEM; - audit_log_format(ab, "contid=%llu", audit_get_containerid(tsk)); + audit_log_format(ab, "op=%s contid=%llu", op, containerid); audit_log_end(ab); return 0; } diff --git a/kernel/audit.h b/kernel/audit.h index aaa651a..743d445 100644 --- a/kernel/audit.h +++ b/kernel/audit.h @@ -147,6 +147,7 @@ struct audit_context { kuid_t target_uid; unsigned inttarget_sessionid; u32 target_sid; + u64 target_cid; chartarget_comm[TASK_COMM_LEN]; struct audit_tree_refs *trees, *first_trees; @@ -330,6 +331,7 @@ extern void audit_log_d_path_exe(struct audit_buffer *ab, extern pid_t audit_sig_pid; extern kuid_t audit_sig_uid; extern u32 audit_sig_sid; +extern u64 audit_sig_cid; extern int audit_filter(int msgtype, unsigned int listtype
[RFC PATCH ghak32 V2 01/13] audit: add container id
Implement the proc fs write to set the audit container ID of a process, emitting an AUDIT_CONTAINER record to document the event. This is a write from the container orchestrator task to a proc entry of the form /proc/PID/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). This will produce a record such as this: type=CONTAINER msg=audit(1519903238.968:261): op=set pid=596 uid=0 subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 auid=0 tty=pts0 ses=1 opid=596 old-contid=18446744073709551615 contid=123455 res=0 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 container ID values are given in the "contid" fields, while res indicates its success. It is not permitted to self-set, unset or re-set the container ID. A child inherits its parent's container ID, but then can be set only once after. See: https://github.com/linux-audit/audit-kernel/issues/32 Signed-off-by: Richard Guy Briggs --- fs/proc/base.c | 37 include/linux/audit.h | 16 + include/linux/init_task.h | 4 ++- include/linux/sched.h | 1 + include/uapi/linux/audit.h | 2 ++ kernel/auditsc.c | 84 ++ 6 files changed, 143 insertions(+), 1 deletion(-) diff --git a/fs/proc/base.c b/fs/proc/base.c index 60316b5..6ce4fbe 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -1299,6 +1299,41 @@ static ssize_t proc_sessionid_read(struct file * file, char __user * buf, .read = proc_sessionid_read, .llseek = generic_file_llseek, }; + +static ssize_t proc_containerid_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + struct inode *inode = file_inode(file); + u64 containerid; + 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, &containerid); + if (rv < 0) { + put_task_struct(task); + return rv; + } + + rv = audit_set_containerid(task, containerid); + put_task_struct(task); + if (rv < 0) + return rv; + return count; +} + +static const struct file_operations proc_containerid_operations = { + .write = proc_containerid_write, + .llseek = generic_file_llseek, +}; + #endif #ifdef CONFIG_FAULT_INJECTION @@ -2961,6 +2996,7 @@ static int proc_pid_patch_state(struct seq_file *m, struct pid_namespace *ns, #ifdef CONFIG_AUDITSYSCALL REG("loginuid", S_IWUSR|S_IRUGO, proc_loginuid_operations), REG("sessionid", S_IRUGO, proc_sessionid_operations), + REG("containerid", S_IWUSR, proc_containerid_operations), #endif #ifdef CONFIG_FAULT_INJECTION REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations), @@ -3355,6 +3391,7 @@ static int proc_tid_comm_permission(struct inode *inode, int mask) #ifdef CONFIG_AUDITSYSCALL REG("loginuid", S_IWUSR|S_IRUGO, proc_loginuid_operations), REG("sessionid", S_IRUGO, proc_sessionid_operations), + REG("containerid", S_IWUSR, proc_containerid_operations), #endif #ifdef CONFIG_FAULT_INJECTION REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations), diff --git a/include/linux/audit.h b/include/linux/audit.h index af410d9..fe4ba3f 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -29,6 +29,7 @@ #define AUDIT_INO_UNSET ((unsigned long)-1) #define AUDIT_DEV_UNSET ((dev_t)-1) +#define INVALID_CID AUDIT_CID_UNSET struct audit_sig_info { uid_t uid; @@ -321,6 +322,7 @@ static inline void audit_ptrace(struct task_struct *t) extern int auditsc_get_stamp(struct audit_context *ctx, struct timespec64 *t, unsigned int *serial); extern int audit_set_loginuid(kuid_t loginuid); +extern int audit_set_containerid(struct task_struct *tsk, u64 containerid); static inline kuid_t audit_get_loginuid(struct task_struct *tsk) { @@ -332,6 +334,11 @@ static inline unsigned int audit_get_sessionid(struct task_struct *tsk) return tsk->sessionid; } +static inline u64 audit_get_containerid(struct task_struct *tsk) +{ + return tsk->containerid; +} + extern void __audit_ipc_obj(struct kern_ipc_perm *ipcp); extern void __a
[RFC PATCH ghak32 V2 03/13] audit: log container info of syscalls
Create a new audit record AUDIT_CONTAINER_INFO to document the container ID 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=c03e syscall=257 success=yes exit=3 a0=ff9c 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= cap_fi= 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= cap_fi= cap_fe=0 cap_fver=0 type=PROCTITLE msg=audit(1519924845.499:257): proctitle=62617368002D6300736C65657020313B206563686F2074657374203E202F746D702F746D70636F6E7461696E65726964 type=CONTAINER_INFO msg=audit(1519924845.499:257): op=task contid=123458 See: https://github.com/linux-audit/audit-kernel/issues/32 Signed-off-by: Richard Guy Briggs --- include/linux/audit.h | 5 + include/uapi/linux/audit.h | 1 + kernel/audit.c | 20 kernel/auditsc.c | 2 ++ 4 files changed, 28 insertions(+) diff --git a/include/linux/audit.h b/include/linux/audit.h index fe4ba3f..3acbe9d 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -154,6 +154,8 @@ extern void audit_log_link_denied(const char *operation, extern int audit_log_task_context(struct audit_buffer *ab); extern void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk); +extern int audit_log_container_info(struct task_struct *tsk, +struct audit_context *context); extern int audit_update_lsm_rules(void); @@ -205,6 +207,9 @@ static inline int audit_log_task_context(struct audit_buffer *ab) static inline void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk) { } +static inline int audit_log_container_info(struct task_struct *tsk, + struct audit_context *context); +{ } #define audit_enabled 0 #endif /* CONFIG_AUDIT */ diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h index 921a71f..e83ccbd 100644 --- a/include/uapi/linux/audit.h +++ b/include/uapi/linux/audit.h @@ -115,6 +115,7 @@ #define AUDIT_REPLACE 1329/* Replace auditd if this packet unanswerd */ #define AUDIT_KERN_MODULE 1330/* Kernel Module events */ #define AUDIT_FANOTIFY 1331/* Fanotify access decision */ +#define AUDIT_CONTAINER_INFO 1332/* Container ID information */ #define AUDIT_AVC 1400/* SE Linux avc denial or grant */ #define AUDIT_SELINUX_ERR 1401/* Internal SE Linux Errors */ diff --git a/kernel/audit.c b/kernel/audit.c index 3f2f143..a12f21f 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -2049,6 +2049,26 @@ void audit_log_session_info(struct audit_buffer *ab) audit_log_format(ab, " auid=%u ses=%u", auid, sessionid); } +/* + * audit_log_container_info - report container info + * @tsk: task to be recorded + * @context: task or local context for record + */ +int audit_log_container_info(struct task_struct *tsk, struct audit_context *context) +{ + struct audit_buffer *ab; + + if (!audit_containerid_set(tsk)) + return 0; + /* Generate AUDIT_CONTAINER_INFO with container ID */ + ab = audit_log_start(context, GFP_KERNEL, AUDIT_CONTAINER_INFO); + if (!ab) + return -ENOMEM; + audit_log_format(ab, "contid=%llu", audit_get_containerid(tsk)); + audit_log_end(ab); + return 0; +} + void audit_log_key(struct audit_buffer *ab, char *key) { audit_log_format(ab, " key="); diff --git a/kernel/auditsc.c b/kernel/auditsc.c index a6b0a52..65be110 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -1453,6 +1453,8 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts audit_log_proctitle(tsk, context); + audit_log_container_info(tsk, context); + /* 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
[RFC PATCH ghak32 V2 00/13] audit: implement container id
Implement audit kernel container ID. This patchset is a second RFC based on the proposal document (V3) posted: https://www.redhat.com/archives/linux-audit/2018-January/msg00014.html The first patch implements the proc fs write to set the audit container ID of a process, emitting an AUDIT_CONTAINER record to announce the registration of that container ID on that process. This patch requires userspace support for record acceptance and proper type display. The second checks for children or co-threads and refuses to set the container ID if either are present. (This policy could be changed to set both with the same container ID provided they meet the rest of the requirements.) The third implements the auxiliary record AUDIT_CONTAINER_INFO if a container ID is identifiable with an event. This patch requires userspace support for proper type display. The fourth adds container ID filtering to the exit, exclude and user lists. This patch requires auditctil userspace support for the --containerid option. 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, 8th, 9th, 10th patches add container ID records to standalone records. Some of these may end up being syscall auxiliary records and won't need this specific support since they'll be supported via syscalls. The 11th adds network namespace container ID labelling based on member tasks' container ID labels. The 12th adds container ID support to standalone netfilter records that don't have a task context and lists each container to which that net namespace belongs. The 13th implements reading the container ID from the proc filesystem for debugging. This patch isn't planned for upstream inclusion. Feedback please! Example: Set a container ID of 123456 to the "sleep" task: sleep 2& child=$! echo 123456 > /proc/$child/containerid; echo $? ausearch -ts recent -m container echo child:$child contid:$( cat /proc/$child/containerid) This should produce a record such as: type=CONTAINER msg=audit(1521122590.315:222): op=set pid=689 uid=0 subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 auid=0 tty=pts0 ses=3 opid=707 old-contid=18446744073709551615 contid=123456 res=1 Example: Set a filter on a container ID 123459 on /tmp/tmpcontainerid: containerid=123459 key=tmpcontainerid auditctl -a exit,always -F dir=/tmp -F perm=wa -F containerid=$containerid -F key=$key perl -e "sleep 1; open(my \$tmpfile, '>', \"/tmp/$key\"); close(\$tmpfile);" & child=$! echo $containerid > /proc/$child/containerid sleep 2 ausearch -i -ts recent -k $key auditctl -d exit,always -F dir=/tmp -F perm=wa -F containerid=$containerid -F key=$key rm -f /tmp/$key This should produce an event such as: type=CONTAINER_INFO msg=audit(1521122591.614:227): op=task contid=123459 type=PROCTITLE msg=audit(1521122591.614:227): proctitle=7065726C002D6500736C65657020313B206F70656E286D792024746D7066696C652C20273E272C20222F746D702F746D70636F6E7461696E6572696422293B20636C6F73652824746D7066696C65293B type=PATH msg=audit(1521122591.614:227): item=1 name="/tmp/tmpcontainerid" inode=18427 dev=00:26 mode=0100644 ouid=0 ogid=0 rdev=00:00 obj=unconfined_u:object_r:user_tmp_t:s0 nametype=CREATE cap_fp= cap_fi= cap_fe=0 cap_fver=0 type=PATH msg=audit(1521122591.614:227): item=0 name="/tmp/" inode=13513 dev=00:26 mode=041777 ouid=0 ogid=0 rdev=00:00 obj=system_u:object_r:tmp_t:s0 nametype=PARENT cap_fp= cap_fi= cap_fe=0 cap_fver=0 type=CWD msg=audit(1521122591.614:227): cwd="/root" type=SYSCALL msg=audit(1521122591.614:227): arch=c03e syscall=257 success=yes exit=3 a0=ff9c a1=55db90a28900 a2=241 a3=1b6 items=2 ppid=689 pid=724 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts0 ses=3 comm="perl" exe="/usr/bin/perl" subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 key="tmpcontainerid" See: https://github.com/linux-audit/audit-kernel/issues/32 https://github.com/linux-audit/audit-userspace/issues/40 https://github.com/linux-audit/audit-testsuite/issues/64 Richard Guy Briggs (13): audit: add container id audit: check children and threading before allowing containerid audit: log container info of syscalls audit: add containerid filtering audit: add containerid support for ptrace and signals audit: add support for non-syscall auxiliary records audit: add container aux record to watch/tree/mark audit: add containerid support for tty_audit audit: add containerid support for config/feature/user records audit
[RFC PATCH ghak32 V2 02/13] audit: check children and threading before allowing containerid
Check if a task has existing children or co-threads and refuse to set the container ID if either are present. Failure to check this could permit games where a child scratches its parent's back to work around inheritance and double-setting policy. Signed-off-by: Richard Guy Briggs --- kernel/auditsc.c | 4 1 file changed, 4 insertions(+) diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 29c8482..a6b0a52 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -2087,6 +2087,10 @@ static int audit_set_containerid_perm(struct task_struct *task, u64 containerid) /* if we don't have caps, reject */ if (!capable(CAP_AUDIT_CONTROL)) return -EPERM; + /* if task has children or is not single-threaded, deny */ + if (!list_empty(&task->children) || + !(thread_group_leader(task) && thread_group_empty(task))) + return -EPERM; /* if containerid is unset, allow */ if (!audit_containerid_set(task)) return 0; -- 1.8.3.1
[PATCH ghau40 v2 2/5] AUDIT_CONTAINER_INFO message type basic support
This defines the message number for the container ID info record should the kernel headers not be up to date and gives the record number a name for printing. Signed-off-by: Richard Guy Briggs --- lib/libaudit.h| 4 lib/msg_typetab.h | 1 + 2 files changed, 5 insertions(+) diff --git a/lib/libaudit.h b/lib/libaudit.h index 6d431b9..756a3b8 100644 --- a/lib/libaudit.h +++ b/lib/libaudit.h @@ -282,6 +282,10 @@ extern "C" { #define AUDIT_FANOTIFY 1331 /* Fanotify access decision */ #endif +#ifndef AUDIT_CONTAINER_INFO +#define AUDIT_CONTAINER_INFO1332 /* Container ID details */ +#endif + #ifndef AUDIT_ANOM_LINK #define AUDIT_ANOM_LINK1702 /* Suspicious use of file links */ #endif diff --git a/lib/msg_typetab.h b/lib/msg_typetab.h index e2fd536..5c4892a 100644 --- a/lib/msg_typetab.h +++ b/lib/msg_typetab.h @@ -124,6 +124,7 @@ _S(AUDIT_PROCTITLE, "PROCTITLE" ) _S(AUDIT_FEATURE_CHANGE, "FEATURE_CHANGE") _S(AUDIT_KERN_MODULE,"KERN_MODULE" ) _S(AUDIT_FANOTIFY, "FANOTIFY" ) +_S(AUDIT_CONTAINER_INFO, "CONTAINER_INFO") _S(AUDIT_AVC,"AVC" ) _S(AUDIT_SELINUX_ERR,"SELINUX_ERR" ) _S(AUDIT_AVC_PATH, "AVC_PATH" ) -- 1.8.3.1
[PATCH ghau40 v2 3/5] auditctl: add support for containerid filter
A u64 container identifier has been added to the kernel view of tasks. This allows container orchestrators to label tasks with a unique tamperproof identifier that gets inherited by its children to be able to track the provenance of actions by a container. Add support to libaudit and auditctl for the containerid field to filter based on container identifier. Since it is a u64 and larger than any other numeric field, send it as a string but do the appropriate conversions on each end in each direction. See: https://github.com/linux-audit/audit-userspace/issues/40 See: https://github.com/linux-audit/audit-kernel/issues/32 See: https://github.com/linux-audit/audit-testsuite/issues/64 Signed-off-by: Richard Guy Briggs --- docs/auditctl.8| 3 +++ lib/fieldtab.h | 1 + lib/libaudit.c | 36 lib/libaudit.h | 7 +++ src/auditctl-listing.c | 21 + 5 files changed, 68 insertions(+) diff --git a/docs/auditctl.8 b/docs/auditctl.8 index 88466de..8bda43d 100644 --- a/docs/auditctl.8 +++ b/docs/auditctl.8 @@ -210,6 +210,9 @@ Parent's Process ID .B sessionid User's login session ID .TP +.B containerid +Process' container ID +.TP .B subj_user Program's SE Linux User .TP diff --git a/lib/fieldtab.h b/lib/fieldtab.h index c425d5b..755800a 100644 --- a/lib/fieldtab.h +++ b/lib/fieldtab.h @@ -47,6 +47,7 @@ _S(AUDIT_OBJ_TYPE, "obj_type" ) _S(AUDIT_OBJ_LEV_LOW, "obj_lev_low" ) _S(AUDIT_OBJ_LEV_HIGH, "obj_lev_high" ) _S(AUDIT_SESSIONID,"sessionid") +_S(AUDIT_CONTAINERID, "containerid" ) _S(AUDIT_DEVMAJOR, "devmajor" ) _S(AUDIT_DEVMINOR, "devminor" ) diff --git a/lib/libaudit.c b/lib/libaudit.c index 331cdde..c45f366 100644 --- a/lib/libaudit.c +++ b/lib/libaudit.c @@ -1737,6 +1737,42 @@ int audit_rule_fieldpair_data(struct audit_rule_data **rulep, const char *pair, else if (strcmp(v, "unset") == 0) rule->values[rule->field_count] = UINT_MAX; break; + case AUDIT_CONTAINERID: { + unsigned long long val; + + if ((audit_get_features() & + AUDIT_FEATURE_BITMAP_CONTAINERID_FILTER) == 0) + return -EAU_FIELDNOSUPPORT; + if (flags != AUDIT_FILTER_EXCLUDE && + flags != AUDIT_FILTER_USER && + flags != AUDIT_FILTER_EXIT) + return -EAU_FIELDNOFILTER; + if (isdigit((char)*(v))) + val = strtoull(v, NULL, 0); + else if (strlen(v) >= 2 && *(v)=='-' && + (isdigit((char)*(v+1 + val = strtoll(v, NULL, 0); + else if (strcmp(v, "unset") == 0) + val = ULLONG_MAX; + else + return -EAU_FIELDVALNUM; + if (errno) + return -EAU_FIELDVALNUM; + vlen = sizeof(unsigned long long); + rule->values[rule->field_count] = vlen; + offset = rule->buflen; + rule->buflen += vlen; + *rulep = realloc(rule, sizeof(*rule) + rule->buflen); + if (*rulep == NULL) { + free(rule); + audit_msg(LOG_ERR, "Cannot realloc memory!\n"); + return -3; + } else { + rule = *rulep; + } + *(unsigned long long*)(&rule->buf[offset]) = val; + break; + } case AUDIT_DEVMAJOR...AUDIT_INODE: case AUDIT_SUCCESS: if (flags != AUDIT_FILTER_EXIT) diff --git a/lib/libaudit.h b/lib/libaudit.h index 756a3b8..cefe71d 100644 --- a/lib/libaudit.h +++ b/lib/libaudit.h @@ -328,6 +328,9 @@ extern "C" { #ifndef AUDIT_FEATURE_BITMAP_FILTER_FS #define AUDIT_FEATURE_BITMAP_FILTER_FS 0x0040 #endif +#ifndef AUDIT_FEATURE_BITMAP_CONTAINERID_FILTER +#define AUDIT_FEATURE_BITMAP_CONTAINERID_FILTER 0x0080 +#endif /* Defines for interfield comparison update */ #ifndef AUDIT_OBJ_UID @@ -351,6 +354,10 @@ extern "C" { #define AUDIT_FSTYPE 26 #endif +#ifndef AUDIT_CONTAINERID +#define AUDIT_CONTAINERID 27 +#endif + #ifndef AUDIT_COMPARE_UID_TO_OBJ_UID #define AUDIT_COMPARE_UID_TO_OBJ_UID 1 #endif diff --git a/src/auditc
[PATCH ghau40 v2 5/5] start normalization containerid support
Signed-off-by: Richard Guy Briggs --- auparse/normalize_record_map.h | 1 + 1 file changed, 1 insertion(+) diff --git a/auparse/normalize_record_map.h b/auparse/normalize_record_map.h index 1507bb5..c529e2e 100644 --- a/auparse/normalize_record_map.h +++ b/auparse/normalize_record_map.h @@ -25,6 +25,7 @@ _S(AUDIT_USER, "sent-message") _S(AUDIT_LOGIN, "changed-login-id-to") +_S(AUDIT_CONTAINER, "changed-container-id-to") _S(AUDIT_USER_AUTH, "authenticated") _S(AUDIT_USER_ACCT, "was-authorized") _S(AUDIT_USER_MGMT, "modified-user-account") -- 1.8.3.1
[PATCH ghau40 v2 4/5] add ausearch containerid support
Add support to ausearch for searching on the containerid field in records. Signed-off-by: Richard Guy Briggs --- src/aureport-options.c | 1 + src/ausearch-llist.c | 2 + src/ausearch-llist.h | 1 + src/ausearch-match.c | 3 + src/ausearch-options.c | 46 - src/ausearch-options.h | 1 + src/ausearch-parse.c | 171 + 7 files changed, 224 insertions(+), 1 deletion(-) diff --git a/src/aureport-options.c b/src/aureport-options.c index 9b914ed..436 100644 --- a/src/aureport-options.c +++ b/src/aureport-options.c @@ -62,6 +62,7 @@ const char *event_vmname = NULL; long long event_exit = 0; int event_exit_is_set = 0; int event_ppid = -1, event_session_id = -2; +unsigned long long int event_container_id = -2; int event_debug = 0, event_machine = -1; /* These are used by aureport */ diff --git a/src/ausearch-llist.c b/src/ausearch-llist.c index ef5503c..c910724 100644 --- a/src/ausearch-llist.c +++ b/src/ausearch-llist.c @@ -60,6 +60,7 @@ void list_create(llist *l) l->s.arch = 0; l->s.syscall = 0; l->s.session_id = -2; + l->s.container_id = -2; l->s.uuid = NULL; l->s.vmname = NULL; l->s.tuid = NULL; @@ -211,6 +212,7 @@ void list_clear(llist* l) l->s.arch = 0; l->s.syscall = 0; l->s.session_id = -2; + l->s.container_id = -2; free(l->s.uuid); l->s.uuid = NULL; free(l->s.vmname); diff --git a/src/ausearch-llist.h b/src/ausearch-llist.h index 64e4ee1..1c651c5 100644 --- a/src/ausearch-llist.h +++ b/src/ausearch-llist.h @@ -56,6 +56,7 @@ typedef struct int arch; // arch int syscall; // syscall uint32_t session_id; // Login session id + __u64 container_id;// Container id long long exit; // Syscall exit code int exit_is_set; // Syscall exit code is valid char *hostname; // remote hostname diff --git a/src/ausearch-match.c b/src/ausearch-match.c index 61a11d3..51dccb0 100644 --- a/src/ausearch-match.c +++ b/src/ausearch-match.c @@ -113,6 +113,9 @@ int match(llist *l) if ((event_session_id != -2) && (event_session_id != l->s.session_id)) return 0; + if ((event_container_id != -2) && + (event_container_id != l->s.container_id)) + return 0; if (event_exit_is_set) { if (l->s.exit_is_set == 0) return 0; diff --git a/src/ausearch-options.c b/src/ausearch-options.c index a3f08e7..1d095a7 100644 --- a/src/ausearch-options.c +++ b/src/ausearch-options.c @@ -60,6 +60,7 @@ int event_syscall = -1, event_machine = -1; int event_ua = 0, event_ga = 0, event_se = 0; int just_one = 0; uint32_t event_session_id = -2; +unsigned long long int event_container_id = -2; long long event_exit = 0; int event_exit_is_set = 0; int line_buffered = 0; @@ -88,7 +89,7 @@ struct nv_pair { enum { S_EVENT, S_COMM, S_FILENAME, S_ALL_GID, S_EFF_GID, S_GID, S_HELP, S_HOSTNAME, S_INTERP, S_INFILE, S_MESSAGE_TYPE, S_PID, S_SYSCALL, S_OSUCCESS, -S_TIME_END, S_TIME_START, S_TERMINAL, S_ALL_UID, S_EFF_UID, S_UID, S_LOGINID, +S_TIME_END, S_TIME_START, S_TERMINAL, S_ALL_UID, S_EFF_UID, S_UID, S_LOGINID, S_CONTAINERID, S_VERSION, S_EXACT_MATCH, S_EXECUTABLE, S_CONTEXT, S_SUBJECT, S_OBJECT, S_PPID, S_KEY, S_RAW, S_NODE, S_IN_LOGS, S_JUST_ONE, S_SESSION, S_EXIT, S_LINEBUFFERED, S_UUID, S_VMNAME, S_DEBUG, S_CHECKPOINT, S_ARCH, S_FORMAT, @@ -169,6 +170,7 @@ static struct nv_pair optiontab[] = { { S_UUID, "--uuid" }, { S_LOGINID, "-ul" }, { S_LOGINID, "--loginuid" }, + { S_CONTAINERID, "--containerid" }, { S_VERSION, "-v" }, { S_VERSION, "--version" }, { S_VMNAME, "-vm" }, @@ -1182,6 +1184,48 @@ int check_params(int count, char *vars[]) } c++; break; + case S_CONTAINERID: + if (!optarg) { + if ((c+1 < count) && vars[c+1]) + optarg = vars[c+1]; + else { + fprintf(stderr, + "Argument is required for %s\n", + vars[c]); + retval = -1; + break; + } + } +
[PATCH ghau40 v2 1/5] AUDIT_CONTAINER message type basic support
This defines the message number for the container ID registration record should the kernel headers not be up to date, gives the record number a name for printing and allows the record to be interpreted since it is in the 1000 range like AUDIT_LOGIN. Signed-off-by: Richard Guy Briggs --- lib/libaudit.h| 4 lib/msg_typetab.h | 1 + lib/netlink.c | 1 + 3 files changed, 6 insertions(+) diff --git a/lib/libaudit.h b/lib/libaudit.h index b681e8d..6d431b9 100644 --- a/lib/libaudit.h +++ b/lib/libaudit.h @@ -242,6 +242,10 @@ extern "C" { #define AUDIT_GET_FEATURE 1019/* Get which features are enabled */ #endif +#ifndef AUDIT_CONTAINER +#define AUDIT_CONTAINER 1020/* Container creation notice */ +#endif + #ifndef AUDIT_MMAP #define AUDIT_MMAP 1323 /* Descriptor and flags in mmap */ #endif diff --git a/lib/msg_typetab.h b/lib/msg_typetab.h index 966865f..e2fd536 100644 --- a/lib/msg_typetab.h +++ b/lib/msg_typetab.h @@ -44,6 +44,7 @@ _S(AUDIT_LOGIN, "LOGIN" ) //_S(AUDIT_TTY_SET,"TTY_SET" ) //_S(AUDIT_SET_FEATURE,"SET_FEATURE" ) //_S(AUDIT_GET_FEATURE,"GET_FEATURE" ) +_S(AUDIT_CONTAINER, "CONTAINER" ) _S(AUDIT_USER_AUTH, "USER_AUTH" ) _S(AUDIT_USER_ACCT, "USER_ACCT" ) _S(AUDIT_USER_MGMT, "USER_MGMT" ) diff --git a/lib/netlink.c b/lib/netlink.c index 5b2028f..8847875 100644 --- a/lib/netlink.c +++ b/lib/netlink.c @@ -184,6 +184,7 @@ static int adjust_reply(struct audit_reply *rep, int len) break; case AUDIT_USER: case AUDIT_LOGIN: + case AUDIT_CONTAINER: case AUDIT_KERNEL: case AUDIT_FIRST_USER_MSG...AUDIT_LAST_USER_MSG: case AUDIT_FIRST_USER_MSG2...AUDIT_LAST_USER_MSG2: -- 1.8.3.1
[PATCH ghau40 v2 0/5] add support for audit container ID
Add support for audit kernel container IDs to userspace tools. See: https://github.com/linux-audit/audit-userspace/issues/40 See: https://github.com/linux-audit/audit-kernel/issues/32 See: https://github.com/linux-audit/audit-testsuite/issues/64 Richard Guy Briggs (5): AUDIT_CONTAINER message type basic support AUDIT_CONTAINER_INFO message type basic support auditctl: add support for containerid filter add ausearch containerid support start normalization containerid support auparse/normalize_record_map.h | 1 + docs/auditctl.8| 3 + lib/fieldtab.h | 1 + lib/libaudit.c | 36 + lib/libaudit.h | 15 lib/msg_typetab.h | 2 + lib/netlink.c | 1 + src/auditctl-listing.c | 21 + src/aureport-options.c | 1 + src/ausearch-llist.c | 2 + src/ausearch-llist.h | 1 + src/ausearch-match.c | 3 + src/ausearch-options.c | 46 ++- src/ausearch-options.h | 1 + src/ausearch-parse.c | 171 + 15 files changed, 304 insertions(+), 1 deletion(-) -- 1.8.3.1
Re: RFC(v2): Audit Kernel Container IDs
On 2017-12-09 11:20, Mickaël Salaün wrote: > > On 12/10/2017 18:33, Casey Schaufler wrote: > > On 10/12/2017 7:14 AM, Richard Guy Briggs wrote: > >> Containers are a userspace concept. The kernel knows nothing of them. > >> > >> The Linux audit system needs a way to be able to track the container > >> provenance of events and actions. Audit needs the kernel's help to do > >> this. > >> > >> Since the concept of a container is entirely a userspace concept, a > >> registration from the userspace container orchestration system initiates > >> this. This will define a point in time and a set of resources > >> associated with a particular container with an audit container ID. > >> > >> The registration is a pseudo filesystem (proc, since PID tree already > >> exists) write of a u8[16] UUID representing the container ID to a file > >> representing a process that will become the first process in a new > >> container. This write might place restrictions on mount namespaces > >> required to define a container, or at least careful checking of > >> namespaces in the kernel to verify permissions of the orchestrator so it > >> can't change its own container ID. A bind mount of nsfs may be > >> necessary in the container orchestrator's mntNS. > >> Note: Use a 128-bit scalar rather than a string to make compares faster > >> and simpler. > >> > >> Require a new CAP_CONTAINER_ADMIN to be able to carry out the > >> registration. > > > > Hang on. If containers are a user space concept, how can > > you want CAP_CONTAINER_ANYTHING? If there's not such thing as > > a container, how can you be asking for a capability to manage > > them? > > > >> At that time, record the target container's user-supplied > >> container identifier along with the target container's first process > >> (which may become the target container's "init" process) process ID > >> (referenced from the initial PID namespace), all namespace IDs (in the > >> form of a nsfs device number and inode number tuple) in a new auxilliary > >> record AUDIT_CONTAINER with a qualifying op=$action field. > > Here is an idea to avoid privilege problems or the need for a new > capability: make it automatic. What makes a container a container seems > to be the use of at least a namespace. What about automatically create > and assign an ID to a process when it enters a namespace different than > one of its parent process? This delegates the (permission) > responsibility to the use of namespaces (e.g. /proc/sys/user/max_* limit). A container doesn't imply a namespace and vice versa. > One interesting side effect of this approach would be to be able to > identify which processes are in the same set of namespaces, even if not > spawn from the container but entered after its creation (i.e. using > setns), by creating container IDs as a (deterministic) checksum from the > /proc/self/ns/* IDs. This would be really helpful, but it isn't the case. > Since the concern is to identify a container, I think the ability to > audit the switch from one container ID to another is enough. I don't > think we need nested IDs. Since container namespace membership is arbitrary between container orchestrators, this needs a registration process and a way for the container orchestrator to know the ID. I completely agree with Casey here. > As a side note, you may want to take a look at the Linux-VServer's XID. > > Regards, > Mickaël - RGB -- Richard Guy Briggs 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
RFC(V3): Audit Kernel Container IDs
m all implicated namespaces upon the destruction of a container. This namespace information adds supporting information for tracking events not attributable to specific processes. Changelog: (Upstream V3) - switch back to u64 (from pmoore, can be expanded to u128 in future if need arises without breaking API. u32 was originally proposed, up to c36 discussed) - write-once, but children inherit audit container identifier and can then still be written once - switch to CAP_AUDIT_CONTROL - group namespace actions together, auxilliary records to namespace operations. (Upstream V2) - switch from u64 to u128 UUID - switch from "signal" and "trigger" to "register" - restrict registration to single process or force all threads and children into same container - RGB -- Richard Guy Briggs 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: RFC(V3): Audit Kernel Container IDs
On 2018-01-09 19:05, Eric W. Biederman wrote: > Please let's have a description of the problem you are trying to solve. I thought the first sentence of the second paragraph summed it up rather well. Here are the elaborated motivations: - Filter unwanted, irrelevant or unimportant messages before they fill queue so important messages don't get lost. This is a certification requirement. - Make security claims about containers, require tracking of actions within those containers to ensure compliance with established security policies. - Route messages from events to local audit daemon instance or host audit daemon instance - Tried nsIDs, but insufficient for efficient filtering, routing, tracking > A proposed solution without talking about the problem space is useless. > Any proposed solution could potentially work. > > I know to these exist. There is motivation for your work. > What is the motivation? > What problem are you trying to solve? > > In particular what information are you trying to get into logs that you > can not get into the logs today? > > I am going to try to give this the attention it deserves but right now I > am having to deal with half thought out patches for information leaks > from speculative code paths, so I won't be able to give this much > attention for a little bit. > > Eric - RGB -- Richard Guy Briggs 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: RFC(V3): Audit Kernel Container IDs
On 2018-01-09 11:18, Simo Sorce wrote: > On Tue, 2018-01-09 at 07:16 -0500, Richard Guy Briggs wrote: > > Containers are a userspace concept. The kernel knows nothing of them. > > > > The Linux audit system needs a way to be able to track the container > > provenance of events and actions. Audit needs the kernel's help to do > > this. > > > > Since the concept of a container is entirely a userspace concept, a > > registration from the userspace container orchestration system initiates > > this. This will define a point in time and a set of resources > > associated with a particular container with an audit container > > identifier. > > > > The registration is a u64 representing the audit container identifier > > written to a special file in a pseudo filesystem (proc, since PID tree > > already exists) representing a process that will become a parent process > > in that container. This write might place restrictions on mount > > namespaces required to define a container, or at least careful checking > > of namespaces in the kernel to verify permissions of the orchestrator so > > it can't change its own container ID. A bind mount of nsfs may be > > necessary in the container orchestrator's mount namespace. This write > > can only happen once per process. > > > > Note: The justification for using a u64 is that it minimizes the > > information printed in every audit record, reducing bandwidth and limits > > comparisons to a single u64 which will be faster and less error-prone. > > > > Require CAP_AUDIT_CONTROL to be able to carry out the registration. At > > that time, record the target container's user-supplied audit container > > identifier along with a target container's parent process (which may > > become the target container's "init" process) process ID (referenced > > from the initial PID namespace) in a new record AUDIT_CONTAINER with a > > qualifying op=$action field. > > > > Issue a new auxilliary record AUDIT_CONTAINER_INFO for each valid > > container ID present on an auditable action or event. > > > > Forked and cloned processes inherit their parent's audit container > > identifier, referenced in the process' task_struct. Since the audit > > container identifier is inherited rather than written, it can still be > > written once. This will prevent tampering while allowing nesting. > > (This can be implemented with an internal settable flag upon > > registration that does not get copied across a fork/clone.) > > > > Mimic setns(2) and return an error if the process has already initiated > > threading or forked since this registration should happen before the > > process execution is started by the orchestrator and hence should not > > yet have any threads or children. If this is deemed overly restrictive, > > switch all of the target's threads and children to the new containerID. > > > > Trust the orchestrator to judiciously use and restrict CAP_AUDIT_CONTROL. > > > > When a container ceases to exist because the last process in that > > container has exited log the fact to balance the registration action. > > (This is likely needed for certification accountability.) > > > > At this point it appears unnecessary to add a container session > > identifier since this is all tracked from loginuid and sessionid to > > communicate with the container orchestrator to spawn an additional > > session into an existing container which would be logged. It can be > > added at a later date without breaking API should it be deemed > > necessary. > > > > The following namespace logging actions are not needed for certification > > purposes at this point, but are helpful for tracking namespace activity. > > These are auxilliary records that are associated with namespace > > manipulation syscalls unshare(2), clone(2) and setns(2), so the records > > will only show up if explicit syscall rules have been added to document > > this activity. > > > > Log the creation of every namespace, inheriting/adding its spawning > > process' audit container identifier(s), if applicable. Include the > > spawning and spawned namespace IDs (device and inode number tuples). > > [AUDIT_NS_CREATE, AUDIT_NS_DESTROY] [clone(2), unshare(2), setns(2)] > > Note: At this point it appears only network namespaces may need to track > > container IDs apart from processes since incoming packets may cause an > > auditable event before being associated with a process. Since a > > namespace can be shar
[PATCH ghak81 RFC V1 5/5] 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 pointer called "audit" in struct task_struct. Use kmem_cache to manage this pool of memory. Un-inline audit_free() to be able to always recover that memory. See: https://github.com/linux-audit/audit-kernel/issues/81 Signed-off-by: Richard Guy Briggs --- MAINTAINERS| 2 +- include/linux/audit.h | 8 include/linux/audit_task.h | 31 +++ include/linux/sched.h | 6 ++ init/init_task.c | 8 ++-- kernel/auditsc.c | 4 ++-- 6 files changed, 46 insertions(+), 13 deletions(-) create mode 100644 include/linux/audit_task.h diff --git a/MAINTAINERS b/MAINTAINERS index 0a1410d..8c7992d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2510,7 +2510,7 @@ L:linux-au...@redhat.com (moderated for non-subscribers) W: https://github.com/linux-audit T: git git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/audit.git S: Supported -F: include/linux/audit.h +F: include/linux/audit*.h F: include/uapi/linux/audit.h F: kernel/audit* diff --git a/include/linux/audit.h b/include/linux/audit.h index dba0d45..1324969 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -237,11 +237,11 @@ extern void __audit_inode_child(struct inode *parent, 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(struct task_struct *task) { - return task->audit_context; + return task->audit.ctx; } static inline bool audit_dummy_context(void) { @@ -330,12 +330,12 @@ extern int auditsc_get_stamp(struct audit_context *ctx, static inline kuid_t audit_get_loginuid(struct task_struct *tsk) { - return tsk->loginuid; + return tsk->audit.loginuid; } static inline unsigned int audit_get_sessionid(struct task_struct *tsk) { - return tsk->sessionid; + return tsk->audit.sessionid; } extern void __audit_ipc_obj(struct kern_ipc_perm *ipcp); diff --git a/include/linux/audit_task.h b/include/linux/audit_task.h new file mode 100644 index 000..d4b3a20 --- /dev/null +++ b/include/linux/audit_task.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* audit_task.h -- definition of audit_task_info structure + * + * Copyright 2018 Red Hat Inc., Raleigh, North Carolina. + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Written by Richard Guy Briggs + * + */ + +#ifndef _LINUX_AUDIT_TASK_H_ +#define _LINUX_AUDIT_TASK_H_ + +struct audit_context; +struct audit_task_info { + kuid_t loginuid; + unsigned intsessionid; + struct audit_context*ctx; +}; + +#endif diff --git a/include/linux/sched.h b/include/linux/sched.h index b3d697f..b58eca0 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -27,9 +27,9 @@ #include #include #include +#include /* task_struct member predeclarations (sorted alphabetically): */ -struct audit_context; struct backing_dev_info; struct bio_list; struct blk_plug; @@ -832,10 +832,8 @@ struct task_struct { struct callback_head*task_works; - struct audit_context*audit_context; #ifdef CONFIG_AUDITSYSCALL - kuid_t loginuid; - unsigned intsessionid; + struct audit_task_info audit; #endif struct seccomp seccomp; diff --git a/init/init_task.c b/init/init_task.c index c788f91..d33260d 100644 --- a/init/init_task.c +++ b/init/init_task.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -118,8 +119,11 @@ struct task_struct init_task .thread_group = LIST_HEAD_INIT(init_task.thread_group), .thread_node= LIST_HEAD_INIT(init_signals.thread_head), #ifdef CONFIG_AUDITSYSCALL - .loginuid = INVALID_UID, - .sessionid = AUDIT_SID_UNSET, + .audit = { + .loginuid = INVALID_UID, + .sessionid = AUDIT_SID_UNSET, + .ctx= NULL, + }, #endif #ifdef CONFIG_PER
[PATCH ghak81 RFC V1 4/5] audit: use inline function to set audit context
Recognizing that the audit context is an internal audit value, use an access function to set the audit context pointer for the task rather than reaching directly into the task struct to set it. Signed-off-by: Richard Guy Briggs --- include/linux/audit.h | 8 kernel/auditsc.c | 6 +++--- kernel/fork.c | 2 +- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/include/linux/audit.h b/include/linux/audit.h index 93e4c61..dba0d45 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -235,6 +235,10 @@ extern void __audit_inode_child(struct inode *parent, extern void __audit_seccomp(unsigned long syscall, long signr, int code); extern void __audit_ptrace(struct task_struct *t); +static inline void audit_set_context(struct task_struct *task, struct audit_context *ctx) +{ + task->audit_context = ctx; +} static inline struct audit_context *audit_context(struct task_struct *task) { return task->audit_context; @@ -472,6 +476,10 @@ static inline bool audit_dummy_context(void) { return true; } +static inline void audit_set_context(struct task_struct *task, struct audit_context *ctx) +{ + task->audit_context = ctx; +} static inline struct audit_context *audit_context(struct task_struct *task) { return NULL; diff --git a/kernel/auditsc.c b/kernel/auditsc.c index a4bbdcc..f294e4a 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -865,7 +865,7 @@ static inline struct audit_context *audit_take_context(struct task_struct *tsk, audit_filter_inodes(tsk, context); } - tsk->audit_context = NULL; + audit_set_context(tsk, NULL); return context; } @@ -952,7 +952,7 @@ int audit_alloc(struct task_struct *tsk) } context->filterkey = key; - tsk->audit_context = context; + audit_set_context(tsk, context); set_tsk_thread_flag(tsk, TIF_SYSCALL_AUDIT); return 0; } @@ -1590,7 +1590,7 @@ void __audit_syscall_exit(int success, long return_code) kfree(context->filterkey); context->filterkey = NULL; } - tsk->audit_context = context; + audit_set_context(tsk, context); } static inline void handle_one(const struct inode *inode) diff --git a/kernel/fork.c b/kernel/fork.c index 242c8c9..cd18448 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -1713,7 +1713,7 @@ 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; - p->audit_context = NULL; + audit_set_context(p, NULL); cgroup_fork(p); #ifdef CONFIG_NUMA p->mempolicy = mpol_dup(p->mempolicy); -- 1.8.3.1
[PATCH ghak81 RFC V1 3/5] audit: use inline function to get audit context
Recognizing that the audit context is an internal audit value, use an access function to retrieve the audit context pointer for the task rather than reaching directly into the task struct to get it. Signed-off-by: Richard Guy Briggs --- include/linux/audit.h| 16 --- include/net/xfrm.h | 2 +- kernel/audit.c | 4 +-- kernel/audit_watch.c | 2 +- kernel/auditsc.c | 52 ++-- net/bridge/netfilter/ebtables.c | 2 +- net/core/dev.c | 2 +- net/netfilter/x_tables.c | 2 +- net/netlabel/netlabel_user.c | 2 +- security/integrity/ima/ima_api.c | 2 +- security/integrity/integrity_audit.c | 2 +- security/lsm_audit.c | 2 +- security/selinux/hooks.c | 4 +-- security/selinux/selinuxfs.c | 6 ++--- security/selinux/ss/services.c | 12 - 15 files changed, 60 insertions(+), 52 deletions(-) diff --git a/include/linux/audit.h b/include/linux/audit.h index 5f86f7c..93e4c61 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -235,26 +235,30 @@ extern void __audit_inode_child(struct inode *parent, extern void __audit_seccomp(unsigned long syscall, long signr, int code); extern void __audit_ptrace(struct task_struct *t); +static inline struct audit_context *audit_context(struct task_struct *task) +{ + return task->audit_context; +} static inline bool audit_dummy_context(void) { - void *p = current->audit_context; + void *p = audit_context(current); return !p || *(int *)p; } static inline void audit_free(struct task_struct *task) { - if (unlikely(task->audit_context)) + if (unlikely(audit_context(task))) __audit_free(task); } static inline void audit_syscall_entry(int major, unsigned long a0, unsigned long a1, unsigned long a2, unsigned long a3) { - if (unlikely(current->audit_context)) + if (unlikely(audit_context(current))) __audit_syscall_entry(major, a0, a1, a2, a3); } static inline void audit_syscall_exit(void *pt_regs) { - if (unlikely(current->audit_context)) { + if (unlikely(audit_context(current))) { int success = is_syscall_success(pt_regs); long return_code = regs_return_value(pt_regs); @@ -468,6 +472,10 @@ static inline bool audit_dummy_context(void) { return true; } +static inline struct audit_context *audit_context(struct task_struct *task) +{ + return NULL; +} static inline struct filename *audit_reusename(const __user char *name) { return NULL; diff --git a/include/net/xfrm.h b/include/net/xfrm.h index fcce8ee..2788332 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -736,7 +736,7 @@ static inline struct audit_buffer *xfrm_audit_start(const char *op) if (audit_enabled == 0) return NULL; - audit_buf = audit_log_start(current->audit_context, GFP_ATOMIC, + audit_buf = audit_log_start(audit_context(current), GFP_ATOMIC, AUDIT_MAC_IPSEC_EVENT); if (audit_buf == NULL) return NULL; diff --git a/kernel/audit.c b/kernel/audit.c index e9f9a90..9a03603 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -1099,7 +1099,7 @@ static void audit_log_feature_change(int which, u32 old_feature, u32 new_feature if (audit_enabled == AUDIT_OFF) return; - ab = audit_log_start(current->audit_context, + ab = audit_log_start(audit_context(current), GFP_KERNEL, AUDIT_FEATURE_CHANGE); if (!ab) return; @@ -2317,7 +2317,7 @@ void audit_log_link_denied(const char *operation) return; /* Generate AUDIT_ANOM_LINK with subject, operation, outcome. */ - ab = audit_log_start(current->audit_context, GFP_KERNEL, + ab = audit_log_start(audit_context(current), GFP_KERNEL, AUDIT_ANOM_LINK); if (!ab) return; diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c index 9eb8b35..8b596c4 100644 --- a/kernel/audit_watch.c +++ b/kernel/audit_watch.c @@ -274,7 +274,7 @@ static void audit_update_watch(struct audit_parent *parent, /* If the update involves invalidating rules, do the inode-based * filtering now, so we don't omit records. */ if (invalidating && !audit_dummy_context()) - audit_filter_inodes(current, current->audit_context); + audit_filter_inodes(current, audit_context(current)); /* updating ino will likely change which audit_hash_list we * are on so we need a new watch for the new list *
[PATCH ghak81 RFC V1 1/5] audit: normalize loginuid read access
Recognizing that the loginuid is an internal audit value, use an access function to retrieve the audit loginuid value for the task rather than reaching directly into the task struct to get it. Signed-off-by: Richard Guy Briggs --- kernel/auditsc.c | 16 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 479c031..f3817d0 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -374,7 +374,7 @@ static int audit_field_compare(struct task_struct *tsk, case AUDIT_COMPARE_EGID_TO_OBJ_GID: return audit_compare_gid(cred->egid, name, f, ctx); case AUDIT_COMPARE_AUID_TO_OBJ_UID: - return audit_compare_uid(tsk->loginuid, name, f, ctx); + return audit_compare_uid(audit_get_loginuid(tsk), name, f, ctx); case AUDIT_COMPARE_SUID_TO_OBJ_UID: return audit_compare_uid(cred->suid, name, f, ctx); case AUDIT_COMPARE_SGID_TO_OBJ_GID: @@ -385,7 +385,7 @@ static int audit_field_compare(struct task_struct *tsk, return audit_compare_gid(cred->fsgid, name, f, ctx); /* uid comparisons */ case AUDIT_COMPARE_UID_TO_AUID: - return audit_uid_comparator(cred->uid, f->op, tsk->loginuid); + return audit_uid_comparator(cred->uid, f->op, audit_get_loginuid(tsk)); case AUDIT_COMPARE_UID_TO_EUID: return audit_uid_comparator(cred->uid, f->op, cred->euid); case AUDIT_COMPARE_UID_TO_SUID: @@ -394,11 +394,11 @@ static int audit_field_compare(struct task_struct *tsk, return audit_uid_comparator(cred->uid, f->op, cred->fsuid); /* auid comparisons */ case AUDIT_COMPARE_AUID_TO_EUID: - return audit_uid_comparator(tsk->loginuid, f->op, cred->euid); + return audit_uid_comparator(audit_get_loginuid(tsk), f->op, cred->euid); case AUDIT_COMPARE_AUID_TO_SUID: - return audit_uid_comparator(tsk->loginuid, f->op, cred->suid); + return audit_uid_comparator(audit_get_loginuid(tsk), f->op, cred->suid); case AUDIT_COMPARE_AUID_TO_FSUID: - return audit_uid_comparator(tsk->loginuid, f->op, cred->fsuid); + return audit_uid_comparator(audit_get_loginuid(tsk), f->op, cred->fsuid); /* euid comparisons */ case AUDIT_COMPARE_EUID_TO_SUID: return audit_uid_comparator(cred->euid, f->op, cred->suid); @@ -611,7 +611,7 @@ static int audit_filter_rules(struct task_struct *tsk, result = match_tree_refs(ctx, rule->tree); break; case AUDIT_LOGINUID: - result = audit_uid_comparator(tsk->loginuid, f->op, f->uid); + result = audit_uid_comparator(audit_get_loginuid(tsk), f->op, f->uid); break; case AUDIT_LOGINUID_SET: result = audit_comparator(audit_loginuid_set(tsk), f->op, f->val); @@ -2287,8 +2287,8 @@ int audit_signal_info(int sig, struct task_struct *t) (sig == SIGTERM || sig == SIGHUP || sig == SIGUSR1 || sig == SIGUSR2)) { audit_sig_pid = task_tgid_nr(tsk); - if (uid_valid(tsk->loginuid)) - audit_sig_uid = tsk->loginuid; + if (uid_valid(audit_get_loginuid(tsk))) + audit_sig_uid = audit_get_loginuid(tsk); else audit_sig_uid = uid; security_task_getsecid(tsk, &audit_sig_sid); -- 1.8.3.1
[PATCH ghak81 RFC V1 2/5] audit: convert sessionid unset to a macro
Use a macro, "AUDIT_SID_UNSET", to replace each instance of initialization and comparison to an audit session ID. Signed-off-by: Richard Guy Briggs --- include/linux/audit.h | 2 +- include/net/xfrm.h | 2 +- include/uapi/linux/audit.h | 1 + init/init_task.c | 2 +- kernel/auditsc.c | 4 ++-- 5 files changed, 6 insertions(+), 5 deletions(-) diff --git a/include/linux/audit.h b/include/linux/audit.h index 75d5b03..5f86f7c 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -513,7 +513,7 @@ static inline kuid_t audit_get_loginuid(struct task_struct *tsk) } static inline unsigned int audit_get_sessionid(struct task_struct *tsk) { - return -1; + return AUDIT_SID_UNSET; } static inline void audit_ipc_obj(struct kern_ipc_perm *ipcp) { } diff --git a/include/net/xfrm.h b/include/net/xfrm.h index a872379..fcce8ee 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -751,7 +751,7 @@ static inline void xfrm_audit_helper_usrinfo(bool task_valid, audit_get_loginuid(current) : INVALID_UID); const unsigned int ses = task_valid ? audit_get_sessionid(current) : - (unsigned int) -1; + AUDIT_SID_UNSET; audit_log_format(audit_buf, " auid=%u ses=%u", auid, ses); audit_log_task_context(audit_buf); diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h index 4e61a9e..04f9bd2 100644 --- a/include/uapi/linux/audit.h +++ b/include/uapi/linux/audit.h @@ -465,6 +465,7 @@ struct audit_tty_status { }; #define AUDIT_UID_UNSET (unsigned int)-1 +#define AUDIT_SID_UNSET ((unsigned int)-1) /* audit_rule_data supports filter rules with both integer and string * fields. It corresponds with AUDIT_ADD_RULE, AUDIT_DEL_RULE and diff --git a/init/init_task.c b/init/init_task.c index 3ac6e75..c788f91 100644 --- a/init/init_task.c +++ b/init/init_task.c @@ -119,7 +119,7 @@ struct task_struct init_task .thread_node= LIST_HEAD_INIT(init_signals.thread_head), #ifdef CONFIG_AUDITSYSCALL .loginuid = INVALID_UID, - .sessionid = (unsigned int)-1, + .sessionid = AUDIT_SID_UNSET, #endif #ifdef CONFIG_PERF_EVENTS .perf_event_mutex = __MUTEX_INITIALIZER(init_task.perf_event_mutex), diff --git a/kernel/auditsc.c b/kernel/auditsc.c index f3817d0..6e3ceb9 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -2050,7 +2050,7 @@ static void audit_log_set_loginuid(kuid_t koldloginuid, kuid_t kloginuid, int audit_set_loginuid(kuid_t loginuid) { struct task_struct *task = current; - unsigned int oldsessionid, sessionid = (unsigned int)-1; + unsigned int oldsessionid, sessionid = AUDIT_SID_UNSET; kuid_t oldloginuid; int rc; @@ -2064,7 +2064,7 @@ int audit_set_loginuid(kuid_t loginuid) /* are we setting or clearing? */ if (uid_valid(loginuid)) { sessionid = (unsigned int)atomic_inc_return(&session_id); - if (unlikely(sessionid == (unsigned int)-1)) + if (unlikely(sessionid == AUDIT_SID_UNSET)) sessionid = (unsigned int)atomic_inc_return(&session_id); } -- 1.8.3.1
[PATCH ghak81 RFC V1 0/5] audit: group task params
Group the audit parameters for each task into one structure. In particular, remove the loginuid and sessionid values and the audit context pointer from the task structure, replacing them with an audit task information structure to contain them. Use access functions to access audit values. Note: Use static allocation of the audit task information structure initially. Dynamic allocation was considered and attempted, but isn't ready yet. Static allocation has the limitation that future audit task information structure changes would cause a visible change to the rest of the kernel, whereas dynamic allocation would mostly hide any future changes. The first four access normalization patches could stand alone. Passes audit-testsuite. Richard Guy Briggs (5): audit: normalize loginuid read access audit: convert sessionid unset to a macro audit: use inline function to get audit context audit: use inline function to set audit context audit: collect audit task parameters MAINTAINERS | 2 +- include/linux/audit.h| 30 ++--- include/linux/audit_task.h | 31 ++ include/linux/sched.h| 6 +-- include/net/xfrm.h | 4 +- include/uapi/linux/audit.h | 1 + init/init_task.c | 8 +++- kernel/audit.c | 4 +- kernel/audit_watch.c | 2 +- kernel/auditsc.c | 82 ++-- kernel/fork.c| 2 +- net/bridge/netfilter/ebtables.c | 2 +- net/core/dev.c | 2 +- net/netfilter/x_tables.c | 2 +- net/netlabel/netlabel_user.c | 2 +- security/integrity/ima/ima_api.c | 2 +- security/integrity/integrity_audit.c | 2 +- security/lsm_audit.c | 2 +- security/selinux/hooks.c | 4 +- security/selinux/selinuxfs.c | 6 +-- security/selinux/ss/services.c | 12 +++--- 21 files changed, 129 insertions(+), 79 deletions(-) create mode 100644 include/linux/audit_task.h -- 1.8.3.1
Re: [RFC PATCH ghak32 V2 01/13] audit: add container id
On 2018-04-18 19:47, Paul Moore wrote: > On Fri, Mar 16, 2018 at 5:00 AM, Richard Guy Briggs wrote: > > Implement the proc fs write to set the audit container ID of a process, > > emitting an AUDIT_CONTAINER record to document the event. > > > > This is a write from the container orchestrator task to a proc entry of > > the form /proc/PID/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). > > > > This will produce a record such as this: > > type=CONTAINER msg=audit(1519903238.968:261): op=set pid=596 uid=0 > > subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 auid=0 tty=pts0 > > ses=1 opid=596 old-contid=18446744073709551615 contid=123455 res=0 > > > > 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 container ID values are given in the > > "contid" fields, while res indicates its success. > > > > It is not permitted to self-set, unset or re-set the container ID. A > > child inherits its parent's container ID, but then can be set only once > > after. > > > > See: https://github.com/linux-audit/audit-kernel/issues/32 > > > > Signed-off-by: Richard Guy Briggs > > --- > > fs/proc/base.c | 37 > > include/linux/audit.h | 16 + > > include/linux/init_task.h | 4 ++- > > include/linux/sched.h | 1 + > > include/uapi/linux/audit.h | 2 ++ > > kernel/auditsc.c | 84 > > ++ > > 6 files changed, 143 insertions(+), 1 deletion(-) > > > > diff --git a/fs/proc/base.c b/fs/proc/base.c > > index 60316b5..6ce4fbe 100644 > > --- a/fs/proc/base.c > > +++ b/fs/proc/base.c > > @@ -1299,6 +1299,41 @@ static ssize_t proc_sessionid_read(struct file * > > file, char __user * buf, > > .read = proc_sessionid_read, > > .llseek = generic_file_llseek, > > }; > > + > > +static ssize_t proc_containerid_write(struct file *file, const char __user > > *buf, > > + size_t count, loff_t *ppos) > > +{ > > + struct inode *inode = file_inode(file); > > + u64 containerid; > > + 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, &containerid); > > + if (rv < 0) { > > + put_task_struct(task); > > + return rv; > > + } > > + > > + rv = audit_set_containerid(task, containerid); > > + put_task_struct(task); > > + if (rv < 0) > > + return rv; > > + return count; > > +} > > + > > +static const struct file_operations proc_containerid_operations = { > > + .write = proc_containerid_write, > > + .llseek = generic_file_llseek, > > +}; > > + > > #endif > > > > #ifdef CONFIG_FAULT_INJECTION > > @@ -2961,6 +2996,7 @@ static int proc_pid_patch_state(struct seq_file *m, > > struct pid_namespace *ns, > > #ifdef CONFIG_AUDITSYSCALL > > REG("loginuid", S_IWUSR|S_IRUGO, proc_loginuid_operations), > > REG("sessionid", S_IRUGO, proc_sessionid_operations), > > + REG("containerid", S_IWUSR, proc_containerid_operations), > > #endif > > #ifdef CONFIG_FAULT_INJECTION > > REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations), > > @@ -3355,6 +3391,7 @@ static int proc_tid_comm_permission(struct inode > > *inode, int mask) > > #ifdef CONFIG_AUDITSYSCALL > > REG("loginuid", S_IWUSR|S_IRUGO, proc_loginuid_operations), > > REG("sessionid", S_IRUGO, proc_sessionid_operations), > > + REG("containerid", S_IWUSR, proc_containerid_operations), > > #endif > > #ifdef CONFIG_FAULT_INJECTION > > REG(&qu
Re: [PATCH ghak81 RFC V1 2/5] audit: convert sessionid unset to a macro
On 2018-05-04 16:54, Richard Guy Briggs wrote: > Use a macro, "AUDIT_SID_UNSET", to replace each instance of > initialization and comparison to an audit session ID. > > Signed-off-by: Richard Guy Briggs There's a minor issue with this patch, adding a header include to init/init_task.c in this patch and removing it from patch 5. That'll be in the next revision. I have dynamic allocation working, so that has a good chance of appearing too. > --- > include/linux/audit.h | 2 +- > include/net/xfrm.h | 2 +- > include/uapi/linux/audit.h | 1 + > init/init_task.c | 2 +- > kernel/auditsc.c | 4 ++-- > 5 files changed, 6 insertions(+), 5 deletions(-) > > diff --git a/include/linux/audit.h b/include/linux/audit.h > index 75d5b03..5f86f7c 100644 > --- a/include/linux/audit.h > +++ b/include/linux/audit.h > @@ -513,7 +513,7 @@ static inline kuid_t audit_get_loginuid(struct > task_struct *tsk) > } > static inline unsigned int audit_get_sessionid(struct task_struct *tsk) > { > - return -1; > + return AUDIT_SID_UNSET; > } > static inline void audit_ipc_obj(struct kern_ipc_perm *ipcp) > { } > diff --git a/include/net/xfrm.h b/include/net/xfrm.h > index a872379..fcce8ee 100644 > --- a/include/net/xfrm.h > +++ b/include/net/xfrm.h > @@ -751,7 +751,7 @@ static inline void xfrm_audit_helper_usrinfo(bool > task_valid, > audit_get_loginuid(current) : > INVALID_UID); > const unsigned int ses = task_valid ? audit_get_sessionid(current) : > - (unsigned int) -1; > + AUDIT_SID_UNSET; > > audit_log_format(audit_buf, " auid=%u ses=%u", auid, ses); > audit_log_task_context(audit_buf); > diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h > index 4e61a9e..04f9bd2 100644 > --- a/include/uapi/linux/audit.h > +++ b/include/uapi/linux/audit.h > @@ -465,6 +465,7 @@ struct audit_tty_status { > }; > > #define AUDIT_UID_UNSET (unsigned int)-1 > +#define AUDIT_SID_UNSET ((unsigned int)-1) > > /* audit_rule_data supports filter rules with both integer and string > * fields. It corresponds with AUDIT_ADD_RULE, AUDIT_DEL_RULE and > diff --git a/init/init_task.c b/init/init_task.c > index 3ac6e75..c788f91 100644 > --- a/init/init_task.c > +++ b/init/init_task.c > @@ -119,7 +119,7 @@ struct task_struct init_task > .thread_node= LIST_HEAD_INIT(init_signals.thread_head), > #ifdef CONFIG_AUDITSYSCALL > .loginuid = INVALID_UID, > - .sessionid = (unsigned int)-1, > + .sessionid = AUDIT_SID_UNSET, > #endif > #ifdef CONFIG_PERF_EVENTS > .perf_event_mutex = __MUTEX_INITIALIZER(init_task.perf_event_mutex), > diff --git a/kernel/auditsc.c b/kernel/auditsc.c > index f3817d0..6e3ceb9 100644 > --- a/kernel/auditsc.c > +++ b/kernel/auditsc.c > @@ -2050,7 +2050,7 @@ static void audit_log_set_loginuid(kuid_t koldloginuid, > kuid_t kloginuid, > int audit_set_loginuid(kuid_t loginuid) > { > struct task_struct *task = current; > - unsigned int oldsessionid, sessionid = (unsigned int)-1; > + unsigned int oldsessionid, sessionid = AUDIT_SID_UNSET; > kuid_t oldloginuid; > int rc; > > @@ -2064,7 +2064,7 @@ int audit_set_loginuid(kuid_t loginuid) > /* are we setting or clearing? */ > if (uid_valid(loginuid)) { > sessionid = (unsigned int)atomic_inc_return(&session_id); > - if (unlikely(sessionid == (unsigned int)-1)) > + if (unlikely(sessionid == AUDIT_SID_UNSET)) > sessionid = (unsigned > int)atomic_inc_return(&session_id); > } > > -- > 1.8.3.1 > > -- > Linux-audit mailing list > linux-au...@redhat.com > https://www.redhat.com/mailman/listinfo/linux-audit - RGB -- Richard Guy Briggs 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 ghak81 RFC V1 4/5] audit: use inline function to set audit context
On 2018-05-09 12:07, Tobin C. Harding wrote: > On Fri, May 04, 2018 at 04:54:37PM -0400, Richard Guy Briggs wrote: > > Recognizing that the audit context is an internal audit value, use an > > access function to set the audit context pointer for the task > > rather than reaching directly into the task struct to set it. > > > > Signed-off-by: Richard Guy Briggs > > --- > > include/linux/audit.h | 8 > > kernel/auditsc.c | 6 +++--- > > kernel/fork.c | 2 +- > > 3 files changed, 12 insertions(+), 4 deletions(-) > > > > diff --git a/include/linux/audit.h b/include/linux/audit.h > > index 93e4c61..dba0d45 100644 > > --- a/include/linux/audit.h > > +++ b/include/linux/audit.h > > @@ -235,6 +235,10 @@ extern void __audit_inode_child(struct inode *parent, > > extern void __audit_seccomp(unsigned long syscall, long signr, int code); > > extern void __audit_ptrace(struct task_struct *t); > > > > +static inline void audit_set_context(struct task_struct *task, struct > > audit_context *ctx) > > +{ > > + task->audit_context = ctx; > > +} > > static inline struct audit_context *audit_context(struct task_struct *task) > > { > > return task->audit_context; > > @@ -472,6 +476,10 @@ static inline bool audit_dummy_context(void) > > { > > return true; > > } > > +static inline void audit_set_context(struct task_struct *task, struct > > audit_context *ctx) > > +{ > > + task->audit_context = ctx; > > +} > > If audit_context is an internal audit value why do we set it when > CONFIG_AUDITSYSCALL is not set? Agreed, that is unnecessary, but harmless since it won't be called, or will be called with a value of NULL. That has been fixed in my dynamic allocation patchset since not even the audit_task_info struct is available to assign the value. It is now an empty function like the rest. > Tobin. - RGB -- Richard Guy Briggs 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 ghak81 RFC V1 3/5] audit: use inline function to get audit context
On 2018-05-09 11:28, Paul Moore wrote: > On Fri, May 4, 2018 at 4:54 PM, Richard Guy Briggs wrote: > > Recognizing that the audit context is an internal audit value, use an > > access function to retrieve the audit context pointer for the task > > rather than reaching directly into the task struct to get it. > > > > Signed-off-by: Richard Guy Briggs > > --- > > include/linux/audit.h| 16 --- > > include/net/xfrm.h | 2 +- > > kernel/audit.c | 4 +-- > > kernel/audit_watch.c | 2 +- > > kernel/auditsc.c | 52 > > ++-- > > net/bridge/netfilter/ebtables.c | 2 +- > > net/core/dev.c | 2 +- > > net/netfilter/x_tables.c | 2 +- > > net/netlabel/netlabel_user.c | 2 +- > > security/integrity/ima/ima_api.c | 2 +- > > security/integrity/integrity_audit.c | 2 +- > > security/lsm_audit.c | 2 +- > > security/selinux/hooks.c | 4 +-- > > security/selinux/selinuxfs.c | 6 ++--- > > security/selinux/ss/services.c | 12 - > > 15 files changed, 60 insertions(+), 52 deletions(-) > > > > diff --git a/include/linux/audit.h b/include/linux/audit.h > > index 5f86f7c..93e4c61 100644 > > --- a/include/linux/audit.h > > +++ b/include/linux/audit.h > > @@ -235,26 +235,30 @@ extern void __audit_inode_child(struct inode *parent, > > extern void __audit_seccomp(unsigned long syscall, long signr, int code); > > extern void __audit_ptrace(struct task_struct *t); > > > > +static inline struct audit_context *audit_context(struct task_struct *task) > > +{ > > + return task->audit_context; > > +} > > Another case where I think I agree with everything here on principle, > especially when one considers it in the larger context of the audit > container ID work. However, I think we might be able to somply this a > bit by eliminating the parameter to the new audit_context() helper and > making it always reference the current task_struct. Based on this > patch it would appear that this change would work for all callers > except for audit_take_context() and __audit_syscall_entry(), both of > which are contained within the core audit code and are enough of a > special case that I think it is acceptable for them to access the > context directly. I'm trying to think of reasons why a non-audit > kernel subsystem would ever need to access the audit context of a > process other than current and I can't think of any ... removing the > task_struct pointer might help prevent mistakes/abuse in the future. As for __audit_syscall_{entry,exit}() and audit_signal_info(), they are using current. current is assigned to local variable tsk only to be used as the LHS in assignments and for locking. But, audit_take_context() and audit_log_exit() are both called also from __audit_free() which can have non-current handed to it by copy_process() cleaning up, while do_exit() appears to still be in current. So, Ok, ditch the parameter to audit_context() and use local access when needed. > > diff --git a/kernel/auditsc.c b/kernel/auditsc.c > > index 6e3ceb9..a4bbdcc 100644 > > --- a/kernel/auditsc.c > > +++ b/kernel/auditsc.c > > @@ -836,7 +836,7 @@ static inline struct audit_context > > *audit_take_context(struct task_struct *tsk, > > int return_valid, > > long return_code) > > { > > - struct audit_context *context = tsk->audit_context; > > + struct audit_context *context = audit_context(tsk); > > > > if (!context) > > return NULL; > > @@ -1510,7 +1510,7 @@ void __audit_syscall_entry(int major, unsigned long > > a1, unsigned long a2, > > unsigned long a3, unsigned long a4) > > { > > struct task_struct *tsk = current; > > - struct audit_context *context = tsk->audit_context; > > + struct audit_context *context = audit_context(tsk); > > enum audit_state state; > > > > if (!audit_enabled || !context) > > -- > paul moore > www.paul-moore.com - RGB -- Richard Guy Briggs 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 ghak81 RFC V1 1/5] audit: normalize loginuid read access
On 2018-05-09 11:13, Paul Moore wrote: > On Fri, May 4, 2018 at 4:54 PM, Richard Guy Briggs wrote: > > Recognizing that the loginuid is an internal audit value, use an access > > function to retrieve the audit loginuid value for the task rather than > > reaching directly into the task struct to get it. > > > > Signed-off-by: Richard Guy Briggs > > --- > > kernel/auditsc.c | 16 > > 1 file changed, 8 insertions(+), 8 deletions(-) > > > > diff --git a/kernel/auditsc.c b/kernel/auditsc.c > > index 479c031..f3817d0 100644 > > --- a/kernel/auditsc.c > > +++ b/kernel/auditsc.c > > @@ -374,7 +374,7 @@ static int audit_field_compare(struct task_struct *tsk, > > case AUDIT_COMPARE_EGID_TO_OBJ_GID: > > return audit_compare_gid(cred->egid, name, f, ctx); > > case AUDIT_COMPARE_AUID_TO_OBJ_UID: > > - return audit_compare_uid(tsk->loginuid, name, f, ctx); > > + return audit_compare_uid(audit_get_loginuid(tsk), name, f, > > ctx); > > case AUDIT_COMPARE_SUID_TO_OBJ_UID: > > return audit_compare_uid(cred->suid, name, f, ctx); > > case AUDIT_COMPARE_SGID_TO_OBJ_GID: > > @@ -385,7 +385,7 @@ static int audit_field_compare(struct task_struct *tsk, > > return audit_compare_gid(cred->fsgid, name, f, ctx); > > /* uid comparisons */ > > case AUDIT_COMPARE_UID_TO_AUID: > > - return audit_uid_comparator(cred->uid, f->op, > > tsk->loginuid); > > + return audit_uid_comparator(cred->uid, f->op, > > audit_get_loginuid(tsk)); > > case AUDIT_COMPARE_UID_TO_EUID: > > return audit_uid_comparator(cred->uid, f->op, cred->euid); > > case AUDIT_COMPARE_UID_TO_SUID: > > @@ -394,11 +394,11 @@ static int audit_field_compare(struct task_struct > > *tsk, > > return audit_uid_comparator(cred->uid, f->op, cred->fsuid); > > /* auid comparisons */ > > case AUDIT_COMPARE_AUID_TO_EUID: > > - return audit_uid_comparator(tsk->loginuid, f->op, > > cred->euid); > > + return audit_uid_comparator(audit_get_loginuid(tsk), f->op, > > cred->euid); > > case AUDIT_COMPARE_AUID_TO_SUID: > > - return audit_uid_comparator(tsk->loginuid, f->op, > > cred->suid); > > + return audit_uid_comparator(audit_get_loginuid(tsk), f->op, > > cred->suid); > > case AUDIT_COMPARE_AUID_TO_FSUID: > > - return audit_uid_comparator(tsk->loginuid, f->op, > > cred->fsuid); > > + return audit_uid_comparator(audit_get_loginuid(tsk), f->op, > > cred->fsuid); > > /* euid comparisons */ > > case AUDIT_COMPARE_EUID_TO_SUID: > > return audit_uid_comparator(cred->euid, f->op, cred->suid); > > @@ -611,7 +611,7 @@ static int audit_filter_rules(struct task_struct *tsk, > > result = match_tree_refs(ctx, rule->tree); > > break; > > case AUDIT_LOGINUID: > > - result = audit_uid_comparator(tsk->loginuid, f->op, > > f->uid); > > + result = > > audit_uid_comparator(audit_get_loginuid(tsk), f->op, f->uid); > > break; > > case AUDIT_LOGINUID_SET: > > result = audit_comparator(audit_loginuid_set(tsk), > > f->op, f->val); > > @@ -2287,8 +2287,8 @@ int audit_signal_info(int sig, struct task_struct *t) > > (sig == SIGTERM || sig == SIGHUP || > > sig == SIGUSR1 || sig == SIGUSR2)) { > > audit_sig_pid = task_tgid_nr(tsk); > > - if (uid_valid(tsk->loginuid)) > > - audit_sig_uid = tsk->loginuid; > > + if (uid_valid(audit_get_loginuid(tsk))) > > + audit_sig_uid = audit_get_loginuid(tsk); > > I realize this comment is a little silly given the nature of loginuid, > but if we are going to abstract away loginuid accesses (which I think > is good), we should probably access it once, store it in a local > variable, perform the validity check on the local variable, then > commit the local variable to audit_sig_uid. I realize a TOCTOU > problem is unlikely here, but with this new layer of abstraction it > seems that some additional safety might be a good thing. Ok, I'll just assign it to where it is going and check it there, holding the audit_ctl_lock the whole time, since it should have been done anyways for all of audit_sig_{pid,uid,sid} anyways to get a consistent view from the AUDIT_SIGNAL_INFO fetch. > > else > > audit_sig_uid = uid; > > security_task_getsecid(tsk, &audit_sig_sid); > paul moore - RGB -- Richard Guy Briggs 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 ghak81 RFC V1 5/5] audit: collect audit task parameters
On 2018-05-09 11:46, Paul Moore wrote: > On Fri, May 4, 2018 at 4:54 PM, Richard Guy Briggs wrote: > > The audit-related parameters in struct task_struct should ideally be > > collected together and accessed through a standard audit API. > > > > Collect the existing loginuid, sessionid and audit_context together in a > > new struct audit_task_info pointer called "audit" in struct task_struct. > > > > Use kmem_cache to manage this pool of memory. > > Un-inline audit_free() to be able to always recover that memory. > > > > See: https://github.com/linux-audit/audit-kernel/issues/81 > > > > Signed-off-by: Richard Guy Briggs > > --- > > MAINTAINERS| 2 +- > > include/linux/audit.h | 8 > > include/linux/audit_task.h | 31 +++ > > include/linux/sched.h | 6 ++ > > init/init_task.c | 8 ++-- > > kernel/auditsc.c | 4 ++-- > > 6 files changed, 46 insertions(+), 13 deletions(-) > > create mode 100644 include/linux/audit_task.h > > > > diff --git a/MAINTAINERS b/MAINTAINERS > > index 0a1410d..8c7992d 100644 > > --- a/MAINTAINERS > > +++ b/MAINTAINERS > > @@ -2510,7 +2510,7 @@ L:linux-au...@redhat.com (moderated for > > non-subscribers) > > W: https://github.com/linux-audit > > T: git git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/audit.git > > S: Supported > > -F: include/linux/audit.h > > +F: include/linux/audit*.h > > F: include/uapi/linux/audit.h > > F: kernel/audit* > > > > diff --git a/include/linux/audit.h b/include/linux/audit.h > > index dba0d45..1324969 100644 > > --- a/include/linux/audit.h > > +++ b/include/linux/audit.h > > @@ -237,11 +237,11 @@ extern void __audit_inode_child(struct inode *parent, > > > > 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(struct task_struct *task) > > { > > - return task->audit_context; > > + return task->audit.ctx; > > } > > static inline bool audit_dummy_context(void) > > { > > @@ -330,12 +330,12 @@ extern int auditsc_get_stamp(struct audit_context > > *ctx, > > > > static inline kuid_t audit_get_loginuid(struct task_struct *tsk) > > { > > - return tsk->loginuid; > > + return tsk->audit.loginuid; > > } > > > > static inline unsigned int audit_get_sessionid(struct task_struct *tsk) > > { > > - return tsk->sessionid; > > + return tsk->audit.sessionid; > > } > > > > extern void __audit_ipc_obj(struct kern_ipc_perm *ipcp); > > diff --git a/include/linux/audit_task.h b/include/linux/audit_task.h > > new file mode 100644 > > index 000..d4b3a20 > > --- /dev/null > > +++ b/include/linux/audit_task.h > > @@ -0,0 +1,31 @@ > > +/* SPDX-License-Identifier: GPL-2.0 */ > > +/* audit_task.h -- definition of audit_task_info structure > > + * > > + * Copyright 2018 Red Hat Inc., Raleigh, North Carolina. > > + * All Rights Reserved. > > + * > > + * This program is free software; you can redistribute it and/or modify > > + * it under the terms of the GNU General Public License as published by > > + * the Free Software Foundation; either version 2 of the License, or > > + * (at your option) any later version. > > + * > > + * This program is distributed in the hope that it will be useful, > > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > > + * GNU General Public License for more details. > > + * > > + * Written by Richard Guy Briggs > > + * > > + */ > > + > > +#ifndef _LINUX_AUDIT_TASK_H_ > > +#define _LINUX_AUDIT_TASK_H_ > > + > > +struct audit_context; > > +struct audit_task_info { > > + kuid_t loginuid; > > + unsigned intsessionid; > > + struct audit_context*ctx; > > +}; > > + > > +#endif > > diff --git a/include/linux/sched.h b/include/linux/sched.h > > index b3d697f..b58eca0 100644 > > --- a/include/linux/sched.h > > +++ b/include/linux/sched.h > > @@ -27,9 +27,9 @@ > > #include > > #include > > #include > > +#include &
Re: [PATCH ghak81 RFC V1 1/5] audit: normalize loginuid read access
On 2018-05-10 17:21, Richard Guy Briggs wrote: > On 2018-05-09 11:13, Paul Moore wrote: > > On Fri, May 4, 2018 at 4:54 PM, Richard Guy Briggs wrote: > > > Recognizing that the loginuid is an internal audit value, use an access > > > function to retrieve the audit loginuid value for the task rather than > > > reaching directly into the task struct to get it. > > > > > > Signed-off-by: Richard Guy Briggs > > > --- > > > kernel/auditsc.c | 16 > > > 1 file changed, 8 insertions(+), 8 deletions(-) > > > > > > diff --git a/kernel/auditsc.c b/kernel/auditsc.c > > > index 479c031..f3817d0 100644 > > > --- a/kernel/auditsc.c > > > +++ b/kernel/auditsc.c > > > @@ -374,7 +374,7 @@ static int audit_field_compare(struct task_struct > > > *tsk, > > > case AUDIT_COMPARE_EGID_TO_OBJ_GID: > > > return audit_compare_gid(cred->egid, name, f, ctx); > > > case AUDIT_COMPARE_AUID_TO_OBJ_UID: > > > - return audit_compare_uid(tsk->loginuid, name, f, ctx); > > > + return audit_compare_uid(audit_get_loginuid(tsk), name, > > > f, ctx); > > > case AUDIT_COMPARE_SUID_TO_OBJ_UID: > > > return audit_compare_uid(cred->suid, name, f, ctx); > > > case AUDIT_COMPARE_SGID_TO_OBJ_GID: > > > @@ -385,7 +385,7 @@ static int audit_field_compare(struct task_struct > > > *tsk, > > > return audit_compare_gid(cred->fsgid, name, f, ctx); > > > /* uid comparisons */ > > > case AUDIT_COMPARE_UID_TO_AUID: > > > - return audit_uid_comparator(cred->uid, f->op, > > > tsk->loginuid); > > > + return audit_uid_comparator(cred->uid, f->op, > > > audit_get_loginuid(tsk)); > > > case AUDIT_COMPARE_UID_TO_EUID: > > > return audit_uid_comparator(cred->uid, f->op, cred->euid); > > > case AUDIT_COMPARE_UID_TO_SUID: > > > @@ -394,11 +394,11 @@ static int audit_field_compare(struct task_struct > > > *tsk, > > > return audit_uid_comparator(cred->uid, f->op, > > > cred->fsuid); > > > /* auid comparisons */ > > > case AUDIT_COMPARE_AUID_TO_EUID: > > > - return audit_uid_comparator(tsk->loginuid, f->op, > > > cred->euid); > > > + return audit_uid_comparator(audit_get_loginuid(tsk), > > > f->op, cred->euid); > > > case AUDIT_COMPARE_AUID_TO_SUID: > > > - return audit_uid_comparator(tsk->loginuid, f->op, > > > cred->suid); > > > + return audit_uid_comparator(audit_get_loginuid(tsk), > > > f->op, cred->suid); > > > case AUDIT_COMPARE_AUID_TO_FSUID: > > > - return audit_uid_comparator(tsk->loginuid, f->op, > > > cred->fsuid); > > > + return audit_uid_comparator(audit_get_loginuid(tsk), > > > f->op, cred->fsuid); > > > /* euid comparisons */ > > > case AUDIT_COMPARE_EUID_TO_SUID: > > > return audit_uid_comparator(cred->euid, f->op, > > > cred->suid); > > > @@ -611,7 +611,7 @@ static int audit_filter_rules(struct task_struct *tsk, > > > result = match_tree_refs(ctx, rule->tree); > > > break; > > > case AUDIT_LOGINUID: > > > - result = audit_uid_comparator(tsk->loginuid, > > > f->op, f->uid); > > > + result = > > > audit_uid_comparator(audit_get_loginuid(tsk), f->op, f->uid); > > > break; > > > case AUDIT_LOGINUID_SET: > > > result = > > > audit_comparator(audit_loginuid_set(tsk), f->op, f->val); > > > @@ -2287,8 +2287,8 @@ int audit_signal_info(int sig, struct task_struct > > > *t) > > > (sig == SIGTERM || sig == SIGHUP || > > > sig == SIGUSR1 || sig == SIGUSR2)) { > > > audit_sig_pid = task_tgid_nr(tsk); > > > - if (uid_valid(tsk->loginuid)) > > > - audit_sig_uid = tsk->loginuid; > > > + if (uid_valid(audit_get_loginuid(tsk))) > > > + audit_sig_uid = audit
[PATCH ghak81 RFC V2 5/5] 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. See: https://github.com/linux-audit/audit-kernel/issues/81 Signed-off-by: Richard Guy Briggs --- MAINTAINERS| 2 +- include/linux/audit.h | 10 +- include/linux/audit_task.h | 31 +++ include/linux/sched.h | 6 ++ init/init_task.c | 7 +-- kernel/auditsc.c | 6 +++--- 6 files changed, 47 insertions(+), 15 deletions(-) create mode 100644 include/linux/audit_task.h diff --git a/MAINTAINERS b/MAINTAINERS index 0a1410d..8c7992d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2510,7 +2510,7 @@ L:linux-au...@redhat.com (moderated for non-subscribers) W: https://github.com/linux-audit T: git git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/audit.git S: Supported -F: include/linux/audit.h +F: include/linux/audit*.h F: include/uapi/linux/audit.h F: kernel/audit* diff --git a/include/linux/audit.h b/include/linux/audit.h index f7973e4..6d599b6 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -237,11 +237,11 @@ extern void __audit_inode_child(struct inode *parent, 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; + return current->audit.ctx; } static inline bool audit_dummy_context(void) { @@ -250,7 +250,7 @@ static inline bool audit_dummy_context(void) } static inline void audit_free(struct task_struct *task) { - if (unlikely(task->audit_context)) + if (unlikely(task->audit.ctx)) __audit_free(task); } static inline void audit_syscall_entry(int major, unsigned long a0, @@ -330,12 +330,12 @@ extern int auditsc_get_stamp(struct audit_context *ctx, static inline kuid_t audit_get_loginuid(struct task_struct *tsk) { - return tsk->loginuid; + return tsk->audit.loginuid; } static inline unsigned int audit_get_sessionid(struct task_struct *tsk) { - return tsk->sessionid; + return tsk->audit.sessionid; } extern void __audit_ipc_obj(struct kern_ipc_perm *ipcp); diff --git a/include/linux/audit_task.h b/include/linux/audit_task.h new file mode 100644 index 000..d4b3a20 --- /dev/null +++ b/include/linux/audit_task.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* audit_task.h -- definition of audit_task_info structure + * + * Copyright 2018 Red Hat Inc., Raleigh, North Carolina. + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Written by Richard Guy Briggs + * + */ + +#ifndef _LINUX_AUDIT_TASK_H_ +#define _LINUX_AUDIT_TASK_H_ + +struct audit_context; +struct audit_task_info { + kuid_t loginuid; + unsigned intsessionid; + struct audit_context*ctx; +}; + +#endif diff --git a/include/linux/sched.h b/include/linux/sched.h index b3d697f..b58eca0 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -27,9 +27,9 @@ #include #include #include +#include /* task_struct member predeclarations (sorted alphabetically): */ -struct audit_context; struct backing_dev_info; struct bio_list; struct blk_plug; @@ -832,10 +832,8 @@ struct task_struct { struct callback_head*task_works; - struct audit_context*audit_context; #ifdef CONFIG_AUDITSYSCALL - kuid_t loginuid; - unsigned intsessionid; + struct audit_task_info audit; #endif struct seccomp seccomp; diff --git a/init/init_task.c b/init/init_task.c index 74f60ba..d33260d 100644 --- a/init/init_task.c +++ b/init/init_task.c @@ -119,8 +119,11 @@ struct task_struct init_task .thread_group = LIST_HEAD_INIT(init_task.thread_group), .thread_node= LIST_HEAD_INIT(init_signals.thread_head), #ifdef CONFIG_AUDITSYSCALL - .loginuid = INVALID_UID, - .sessionid = AUDIT_SID_UNSET, + .audit = { + .loginuid = INVALID_UID, + .sessionid
[PATCH ghak81 RFC V2 1/5] audit: normalize loginuid read access
Recognizing that the loginuid is an internal audit value, use an access function to retrieve the audit loginuid value for the task rather than reaching directly into the task struct to get it. Signed-off-by: Richard Guy Briggs --- kernel/auditsc.c | 18 +- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 479c031..0d4e269 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -374,7 +374,7 @@ static int audit_field_compare(struct task_struct *tsk, case AUDIT_COMPARE_EGID_TO_OBJ_GID: return audit_compare_gid(cred->egid, name, f, ctx); case AUDIT_COMPARE_AUID_TO_OBJ_UID: - return audit_compare_uid(tsk->loginuid, name, f, ctx); + return audit_compare_uid(audit_get_loginuid(tsk), name, f, ctx); case AUDIT_COMPARE_SUID_TO_OBJ_UID: return audit_compare_uid(cred->suid, name, f, ctx); case AUDIT_COMPARE_SGID_TO_OBJ_GID: @@ -385,7 +385,7 @@ static int audit_field_compare(struct task_struct *tsk, return audit_compare_gid(cred->fsgid, name, f, ctx); /* uid comparisons */ case AUDIT_COMPARE_UID_TO_AUID: - return audit_uid_comparator(cred->uid, f->op, tsk->loginuid); + return audit_uid_comparator(cred->uid, f->op, audit_get_loginuid(tsk)); case AUDIT_COMPARE_UID_TO_EUID: return audit_uid_comparator(cred->uid, f->op, cred->euid); case AUDIT_COMPARE_UID_TO_SUID: @@ -394,11 +394,11 @@ static int audit_field_compare(struct task_struct *tsk, return audit_uid_comparator(cred->uid, f->op, cred->fsuid); /* auid comparisons */ case AUDIT_COMPARE_AUID_TO_EUID: - return audit_uid_comparator(tsk->loginuid, f->op, cred->euid); + return audit_uid_comparator(audit_get_loginuid(tsk), f->op, cred->euid); case AUDIT_COMPARE_AUID_TO_SUID: - return audit_uid_comparator(tsk->loginuid, f->op, cred->suid); + return audit_uid_comparator(audit_get_loginuid(tsk), f->op, cred->suid); case AUDIT_COMPARE_AUID_TO_FSUID: - return audit_uid_comparator(tsk->loginuid, f->op, cred->fsuid); + return audit_uid_comparator(audit_get_loginuid(tsk), f->op, cred->fsuid); /* euid comparisons */ case AUDIT_COMPARE_EUID_TO_SUID: return audit_uid_comparator(cred->euid, f->op, cred->suid); @@ -611,7 +611,7 @@ static int audit_filter_rules(struct task_struct *tsk, result = match_tree_refs(ctx, rule->tree); break; case AUDIT_LOGINUID: - result = audit_uid_comparator(tsk->loginuid, f->op, f->uid); + result = audit_uid_comparator(audit_get_loginuid(tsk), f->op, f->uid); break; case AUDIT_LOGINUID_SET: result = audit_comparator(audit_loginuid_set(tsk), f->op, f->val); @@ -2281,14 +2281,14 @@ int audit_signal_info(int sig, struct task_struct *t) struct audit_aux_data_pids *axp; struct task_struct *tsk = current; struct audit_context *ctx = tsk->audit_context; - kuid_t uid = current_uid(), t_uid = task_uid(t); + kuid_t uid = current_uid(), auid, t_uid = task_uid(t); if (auditd_test_task(t) && (sig == SIGTERM || sig == SIGHUP || sig == SIGUSR1 || sig == SIGUSR2)) { audit_sig_pid = task_tgid_nr(tsk); - if (uid_valid(tsk->loginuid)) - audit_sig_uid = tsk->loginuid; + if (uid_valid(auid = audit_get_loginuid(tsk))) + audit_sig_uid = auid; else audit_sig_uid = uid; security_task_getsecid(tsk, &audit_sig_sid); -- 1.8.3.1
[PATCH ghak81 RFC V2 2/5] audit: convert sessionid unset to a macro
Use a macro, "AUDIT_SID_UNSET", to replace each instance of initialization and comparison to an audit session ID. Signed-off-by: Richard Guy Briggs --- include/linux/audit.h | 2 +- include/net/xfrm.h | 2 +- include/uapi/linux/audit.h | 1 + init/init_task.c | 3 ++- kernel/auditsc.c | 4 ++-- 5 files changed, 7 insertions(+), 5 deletions(-) diff --git a/include/linux/audit.h b/include/linux/audit.h index 75d5b03..5f86f7c 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -513,7 +513,7 @@ static inline kuid_t audit_get_loginuid(struct task_struct *tsk) } static inline unsigned int audit_get_sessionid(struct task_struct *tsk) { - return -1; + return AUDIT_SID_UNSET; } static inline void audit_ipc_obj(struct kern_ipc_perm *ipcp) { } diff --git a/include/net/xfrm.h b/include/net/xfrm.h index a872379..fcce8ee 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -751,7 +751,7 @@ static inline void xfrm_audit_helper_usrinfo(bool task_valid, audit_get_loginuid(current) : INVALID_UID); const unsigned int ses = task_valid ? audit_get_sessionid(current) : - (unsigned int) -1; + AUDIT_SID_UNSET; audit_log_format(audit_buf, " auid=%u ses=%u", auid, ses); audit_log_task_context(audit_buf); diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h index 4e61a9e..04f9bd2 100644 --- a/include/uapi/linux/audit.h +++ b/include/uapi/linux/audit.h @@ -465,6 +465,7 @@ struct audit_tty_status { }; #define AUDIT_UID_UNSET (unsigned int)-1 +#define AUDIT_SID_UNSET ((unsigned int)-1) /* audit_rule_data supports filter rules with both integer and string * fields. It corresponds with AUDIT_ADD_RULE, AUDIT_DEL_RULE and diff --git a/init/init_task.c b/init/init_task.c index 3ac6e75..74f60ba 100644 --- a/init/init_task.c +++ b/init/init_task.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -119,7 +120,7 @@ struct task_struct init_task .thread_node= LIST_HEAD_INIT(init_signals.thread_head), #ifdef CONFIG_AUDITSYSCALL .loginuid = INVALID_UID, - .sessionid = (unsigned int)-1, + .sessionid = AUDIT_SID_UNSET, #endif #ifdef CONFIG_PERF_EVENTS .perf_event_mutex = __MUTEX_INITIALIZER(init_task.perf_event_mutex), diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 0d4e269..e157595 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -2050,7 +2050,7 @@ static void audit_log_set_loginuid(kuid_t koldloginuid, kuid_t kloginuid, int audit_set_loginuid(kuid_t loginuid) { struct task_struct *task = current; - unsigned int oldsessionid, sessionid = (unsigned int)-1; + unsigned int oldsessionid, sessionid = AUDIT_SID_UNSET; kuid_t oldloginuid; int rc; @@ -2064,7 +2064,7 @@ int audit_set_loginuid(kuid_t loginuid) /* are we setting or clearing? */ if (uid_valid(loginuid)) { sessionid = (unsigned int)atomic_inc_return(&session_id); - if (unlikely(sessionid == (unsigned int)-1)) + if (unlikely(sessionid == AUDIT_SID_UNSET)) sessionid = (unsigned int)atomic_inc_return(&session_id); } -- 1.8.3.1
[PATCH ghak81 RFC V2 4/5] audit: use inline function to set audit context
Recognizing that the audit context is an internal audit value, use an access function to set the audit context pointer for the task rather than reaching directly into the task struct to set it. Signed-off-by: Richard Guy Briggs --- include/linux/audit.h | 6 ++ kernel/auditsc.c | 7 +++ kernel/fork.c | 2 +- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/include/linux/audit.h b/include/linux/audit.h index 786aa8e..f7973e4 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -235,6 +235,10 @@ extern void __audit_inode_child(struct inode *parent, extern void __audit_seccomp(unsigned long syscall, long signr, int code); extern void __audit_ptrace(struct task_struct *t); +static inline void audit_set_context(struct task_struct *task, struct audit_context *ctx) +{ + task->audit_context = ctx; +} static inline struct audit_context *audit_context(void) { return current->audit_context; @@ -472,6 +476,8 @@ static inline bool audit_dummy_context(void) { return true; } +static inline void audit_set_context(struct task_struct *task, struct audit_context *ctx) +{ } static inline struct audit_context *audit_context(void) { return NULL; diff --git a/kernel/auditsc.c b/kernel/auditsc.c index ecc0c23..d441d68 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -865,7 +865,7 @@ static inline struct audit_context *audit_take_context(struct task_struct *tsk, audit_filter_inodes(tsk, context); } - tsk->audit_context = NULL; + audit_set_context(tsk, NULL); return context; } @@ -952,7 +952,7 @@ int audit_alloc(struct task_struct *tsk) } context->filterkey = key; - tsk->audit_context = context; + audit_set_context(tsk, context); set_tsk_thread_flag(tsk, TIF_SYSCALL_AUDIT); return 0; } @@ -1554,7 +1554,6 @@ void __audit_syscall_entry(int major, unsigned long a1, unsigned long a2, */ void __audit_syscall_exit(int success, long return_code) { - struct task_struct *tsk = current; struct audit_context *context; if (success) @@ -1589,7 +1588,7 @@ void __audit_syscall_exit(int success, long return_code) kfree(context->filterkey); context->filterkey = NULL; } - tsk->audit_context = context; + audit_set_context(current, context); } static inline void handle_one(const struct inode *inode) diff --git a/kernel/fork.c b/kernel/fork.c index 242c8c9..cd18448 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -1713,7 +1713,7 @@ 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; - p->audit_context = NULL; + audit_set_context(p, NULL); cgroup_fork(p); #ifdef CONFIG_NUMA p->mempolicy = mpol_dup(p->mempolicy); -- 1.8.3.1
[PATCH ghak81 RFC V2 3/5] audit: use inline function to get audit context
Recognizing that the audit context is an internal audit value, use an access function to retrieve the audit context pointer for the task rather than reaching directly into the task struct to get it. Signed-off-by: Richard Guy Briggs --- include/linux/audit.h| 14 ++-- include/net/xfrm.h | 2 +- kernel/audit.c | 6 ++-- kernel/audit_watch.c | 2 +- kernel/auditsc.c | 64 +--- net/bridge/netfilter/ebtables.c | 2 +- net/core/dev.c | 2 +- net/netfilter/x_tables.c | 2 +- net/netlabel/netlabel_user.c | 2 +- security/integrity/ima/ima_api.c | 2 +- security/integrity/integrity_audit.c | 2 +- security/lsm_audit.c | 2 +- security/selinux/hooks.c | 4 +-- security/selinux/selinuxfs.c | 6 ++-- security/selinux/ss/services.c | 12 +++ 15 files changed, 64 insertions(+), 60 deletions(-) diff --git a/include/linux/audit.h b/include/linux/audit.h index 5f86f7c..786aa8e 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -235,9 +235,13 @@ extern void __audit_inode_child(struct inode *parent, extern void __audit_seccomp(unsigned long syscall, long signr, int code); extern void __audit_ptrace(struct task_struct *t); +static inline struct audit_context *audit_context(void) +{ + return current->audit_context; +} static inline bool audit_dummy_context(void) { - void *p = current->audit_context; + void *p = audit_context(); return !p || *(int *)p; } static inline void audit_free(struct task_struct *task) @@ -249,12 +253,12 @@ static inline void audit_syscall_entry(int major, unsigned long a0, unsigned long a1, unsigned long a2, unsigned long a3) { - if (unlikely(current->audit_context)) + if (unlikely(audit_context())) __audit_syscall_entry(major, a0, a1, a2, a3); } static inline void audit_syscall_exit(void *pt_regs) { - if (unlikely(current->audit_context)) { + if (unlikely(audit_context())) { int success = is_syscall_success(pt_regs); long return_code = regs_return_value(pt_regs); @@ -468,6 +472,10 @@ static inline bool audit_dummy_context(void) { return true; } +static inline struct audit_context *audit_context(void) +{ + return NULL; +} static inline struct filename *audit_reusename(const __user char *name) { return NULL; diff --git a/include/net/xfrm.h b/include/net/xfrm.h index fcce8ee..7f2e31a 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -736,7 +736,7 @@ static inline struct audit_buffer *xfrm_audit_start(const char *op) if (audit_enabled == 0) return NULL; - audit_buf = audit_log_start(current->audit_context, GFP_ATOMIC, + audit_buf = audit_log_start(audit_context(), GFP_ATOMIC, AUDIT_MAC_IPSEC_EVENT); if (audit_buf == NULL) return NULL; diff --git a/kernel/audit.c b/kernel/audit.c index e9f9a90..e7478cb 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -1099,8 +1099,7 @@ static void audit_log_feature_change(int which, u32 old_feature, u32 new_feature if (audit_enabled == AUDIT_OFF) return; - ab = audit_log_start(current->audit_context, -GFP_KERNEL, AUDIT_FEATURE_CHANGE); + ab = audit_log_start(audit_context(), GFP_KERNEL, AUDIT_FEATURE_CHANGE); if (!ab) return; audit_log_task_info(ab, current); @@ -2317,8 +2316,7 @@ void audit_log_link_denied(const char *operation) return; /* Generate AUDIT_ANOM_LINK with subject, operation, outcome. */ - ab = audit_log_start(current->audit_context, GFP_KERNEL, -AUDIT_ANOM_LINK); + ab = audit_log_start(audit_context(), GFP_KERNEL, AUDIT_ANOM_LINK); if (!ab) return; audit_log_format(ab, "op=%s", operation); diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c index 9eb8b35..f1ba889 100644 --- a/kernel/audit_watch.c +++ b/kernel/audit_watch.c @@ -274,7 +274,7 @@ static void audit_update_watch(struct audit_parent *parent, /* If the update involves invalidating rules, do the inode-based * filtering now, so we don't omit records. */ if (invalidating && !audit_dummy_context()) - audit_filter_inodes(current, current->audit_context); + audit_filter_inodes(current, audit_context()); /* updating ino will likely change which audit_hash_list we * are on so we need a new watch for the new list */ diff --git a/kernel/auditsc.c b/kernel/audit
[PATCH ghak81 RFC V2 0/5] audit: group task params
Group the audit parameters for each task into one structure. In particular, remove the loginuid and sessionid values and the audit context pointer from the task structure, replacing them with an audit task information structure to contain them. Use access functions to access audit values. Note: Use static allocation of the audit task information structure initially. Dynamic allocation was considered and attempted, but isn't ready yet. Static allocation has the limitation that future audit task information structure changes would cause a visible change to the rest of the kernel, whereas dynamic allocation would mostly hide any future changes. The first four access normalization patches could stand alone. Passes audit-testsuite. Changelog: v2 - p2/5: add audit header to init/init_task.c to quiet kbuildbot - audit_signal_info(): fetch loginuid once - remove task_struct from audit_context() param list - remove extra task_struct local vars - do nothing on request to set audit context when audit is disabled Richard Guy Briggs (5): audit: normalize loginuid read access audit: convert sessionid unset to a macro audit: use inline function to get audit context audit: use inline function to set audit context audit: collect audit task parameters MAINTAINERS | 2 +- include/linux/audit.h| 28 --- include/linux/audit_task.h | 31 include/linux/sched.h| 6 +-- include/net/xfrm.h | 4 +- include/uapi/linux/audit.h | 1 + init/init_task.c | 8 ++- kernel/audit.c | 6 +-- kernel/audit_watch.c | 2 +- kernel/auditsc.c | 97 +--- kernel/fork.c| 2 +- net/bridge/netfilter/ebtables.c | 2 +- net/core/dev.c | 2 +- net/netfilter/x_tables.c | 2 +- net/netlabel/netlabel_user.c | 2 +- security/integrity/ima/ima_api.c | 2 +- security/integrity/integrity_audit.c | 2 +- security/lsm_audit.c | 2 +- security/selinux/hooks.c | 4 +- security/selinux/selinuxfs.c | 6 +-- security/selinux/ss/services.c | 12 ++--- 21 files changed, 133 insertions(+), 90 deletions(-) create mode 100644 include/linux/audit_task.h -- 1.8.3.1
Re: [PATCH ghak81 RFC V2 3/5] audit: use inline function to get audit context
On 2018-05-14 17:44, Paul Moore wrote: > On Sat, May 12, 2018 at 9:58 PM, Richard Guy Briggs wrote: > > Recognizing that the audit context is an internal audit value, use an > > access function to retrieve the audit context pointer for the task > > rather than reaching directly into the task struct to get it. > > > > Signed-off-by: Richard Guy Briggs > > --- > > include/linux/audit.h| 14 ++-- > > include/net/xfrm.h | 2 +- > > kernel/audit.c | 6 ++-- > > kernel/audit_watch.c | 2 +- > > kernel/auditsc.c | 64 > > +--- > > net/bridge/netfilter/ebtables.c | 2 +- > > net/core/dev.c | 2 +- > > net/netfilter/x_tables.c | 2 +- > > net/netlabel/netlabel_user.c | 2 +- > > security/integrity/ima/ima_api.c | 2 +- > > security/integrity/integrity_audit.c | 2 +- > > security/lsm_audit.c | 2 +- > > security/selinux/hooks.c | 4 +-- > > security/selinux/selinuxfs.c | 6 ++-- > > security/selinux/ss/services.c | 12 +++ > > 15 files changed, 64 insertions(+), 60 deletions(-) > > Merged, but there was some fuzz due to the missing 1/5 patch and a > handfull of checkpatch.pl fixes. Please take a look at the commit in > the audit/next branch and if anything looks awry please send a patch > to fix it. Some of that fuzz was due to the two patches (ghak46/47) that went through the xelinux tree... There will be a merge conflict. Otherwise, looks ok. > paul moore - RGB -- Richard Guy Briggs 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 ghak81 RFC V2 3/5] audit: use inline function to get audit context
On 2018-05-14 23:05, Richard Guy Briggs wrote: > On 2018-05-14 17:44, Paul Moore wrote: > > On Sat, May 12, 2018 at 9:58 PM, Richard Guy Briggs wrote: > > > Recognizing that the audit context is an internal audit value, use an > > > access function to retrieve the audit context pointer for the task > > > rather than reaching directly into the task struct to get it. > > > > > > Signed-off-by: Richard Guy Briggs > > > --- > > > include/linux/audit.h| 14 ++-- > > > include/net/xfrm.h | 2 +- > > > kernel/audit.c | 6 ++-- > > > kernel/audit_watch.c | 2 +- > > > kernel/auditsc.c | 64 > > > +--- > > > net/bridge/netfilter/ebtables.c | 2 +- > > > net/core/dev.c | 2 +- > > > net/netfilter/x_tables.c | 2 +- > > > net/netlabel/netlabel_user.c | 2 +- > > > security/integrity/ima/ima_api.c | 2 +- > > > security/integrity/integrity_audit.c | 2 +- > > > security/lsm_audit.c | 2 +- > > > security/selinux/hooks.c | 4 +-- > > > security/selinux/selinuxfs.c | 6 ++-- > > > security/selinux/ss/services.c | 12 +++ > > > 15 files changed, 64 insertions(+), 60 deletions(-) > > > > Merged, but there was some fuzz due to the missing 1/5 patch and a > > handfull of checkpatch.pl fixes. Please take a look at the commit in > > the audit/next branch and if anything looks awry please send a patch > > to fix it. > > Some of that fuzz was due to the two patches (ghak46/47) that went > through the xelinux tree... There will be a merge conflict. > > Otherwise, looks ok. Spoke too soon, missed one from the new seccomp actions_logged... Patch pending... > > paul moore > > - RGB - RGB -- Richard Guy Briggs 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 ghak81 V3 3/3] audit: collect audit task parameters
The audit-related parameters in struct task_struct should ideally be collected together and accessed through a standard audit API. Collect the existing loginuid, sessionid and audit_context together in a new struct audit_task_info called "audit" in struct task_struct. Use kmem_cache to manage this pool of memory. Un-inline audit_free() to be able to always recover that memory. See: https://github.com/linux-audit/audit-kernel/issues/81 Signed-off-by: Richard Guy Briggs --- include/linux/audit.h | 34 -- include/linux/sched.h | 5 + init/init_task.c | 3 +-- init/main.c | 2 ++ kernel/auditsc.c | 51 ++- kernel/fork.c | 2 +- 6 files changed, 71 insertions(+), 26 deletions(-) diff --git a/include/linux/audit.h b/include/linux/audit.h index 69c7847..4f824c4 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -216,8 +216,15 @@ static inline void audit_log_task_info(struct audit_buffer *ab, /* These are defined in auditsc.c */ /* Public API */ +struct audit_task_info { + kuid_t loginuid; + unsigned intsessionid; + struct audit_context*ctx; +}; +extern struct audit_task_info init_struct_audit; +extern void __init audit_task_init(void); extern int audit_alloc(struct task_struct *task); -extern void __audit_free(struct task_struct *task); +extern void audit_free(struct task_struct *task); extern void __audit_syscall_entry(int major, unsigned long a0, unsigned long a1, unsigned long a2, unsigned long a3); extern void __audit_syscall_exit(int ret_success, long ret_value); @@ -239,12 +246,15 @@ extern void audit_seccomp_actions_logged(const char *names, static inline void audit_set_context(struct task_struct *task, struct audit_context *ctx) { - task->audit_context = ctx; + task->audit->ctx = ctx; } static inline struct audit_context *audit_context(void) { - return current->audit_context; + if (current->audit) + return current->audit->ctx; + else + return NULL; } static inline bool audit_dummy_context(void) @@ -252,11 +262,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) @@ -328,12 +334,18 @@ extern int auditsc_get_stamp(struct audit_context *ctx, static inline kuid_t audit_get_loginuid(struct task_struct *tsk) { - return tsk->loginuid; + if (tsk->audit) + return tsk->audit->loginuid; + else + return INVALID_UID; } static inline unsigned int audit_get_sessionid(struct task_struct *tsk) { - return tsk->sessionid; + if (tsk->audit) + return tsk->audit->sessionid; + else + return AUDIT_SID_UNSET; } extern void __audit_ipc_obj(struct kern_ipc_perm *ipcp); @@ -458,6 +470,8 @@ static inline void audit_fanotify(unsigned int response) extern int audit_n_rules; extern int audit_signals; #else /* CONFIG_AUDITSYSCALL */ +static inline void __init audit_task_init(void) +{ } static inline int audit_alloc(struct task_struct *task) { return 0; diff --git a/include/linux/sched.h b/include/linux/sched.h index b3d697f..6a5db0e 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -29,7 +29,6 @@ #include /* task_struct member predeclarations (sorted alphabetically): */ -struct audit_context; struct backing_dev_info; struct bio_list; struct blk_plug; @@ -832,10 +831,8 @@ struct task_struct { struct callback_head*task_works; - struct audit_context*audit_context; #ifdef CONFIG_AUDITSYSCALL - kuid_t loginuid; - unsigned intsessionid; + struct audit_task_info *audit; #endif struct seccomp seccomp; diff --git a/init/init_task.c b/init/init_task.c index 74f60ba..4058840 100644 --- a/init/init_task.c +++ b/init/init_task.c @@ -119,8 +119,7 @@ struct task_struct init_task .thread_group = LIST_HEAD_INIT(init_task.thread_group), .thread_node= LIST_HEAD_INIT(init_signals.thread_head), #ifdef CONFIG_AUDITSYSCALL - .loginuid = INVALID_UID, - .sessionid = AUDIT_SID_UNSET, + .audit = &init_struct_audit, #endif #ifdef CONFIG_PERF_EVENTS .perf_event_mutex = __MUTEX_INITIALIZER(init_task.perf_event_mutex),
[PATCH ghak81 V3 2/3] audit: normalize loginuid read access
Recognizing that the loginuid is an internal audit value, use an access function to retrieve the audit loginuid value for the task rather than reaching directly into the task struct to get it. Signed-off-by: Richard Guy Briggs --- kernel/auditsc.c | 24 +++- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/kernel/auditsc.c b/kernel/auditsc.c index f3d3dc6..ef3e189 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -374,7 +374,7 @@ static int audit_field_compare(struct task_struct *tsk, case AUDIT_COMPARE_EGID_TO_OBJ_GID: return audit_compare_gid(cred->egid, name, f, ctx); case AUDIT_COMPARE_AUID_TO_OBJ_UID: - return audit_compare_uid(tsk->loginuid, name, f, ctx); + return audit_compare_uid(audit_get_loginuid(tsk), name, f, ctx); case AUDIT_COMPARE_SUID_TO_OBJ_UID: return audit_compare_uid(cred->suid, name, f, ctx); case AUDIT_COMPARE_SGID_TO_OBJ_GID: @@ -385,7 +385,8 @@ static int audit_field_compare(struct task_struct *tsk, return audit_compare_gid(cred->fsgid, name, f, ctx); /* uid comparisons */ case AUDIT_COMPARE_UID_TO_AUID: - return audit_uid_comparator(cred->uid, f->op, tsk->loginuid); + return audit_uid_comparator(cred->uid, f->op, + audit_get_loginuid(tsk)); case AUDIT_COMPARE_UID_TO_EUID: return audit_uid_comparator(cred->uid, f->op, cred->euid); case AUDIT_COMPARE_UID_TO_SUID: @@ -394,11 +395,14 @@ static int audit_field_compare(struct task_struct *tsk, return audit_uid_comparator(cred->uid, f->op, cred->fsuid); /* auid comparisons */ case AUDIT_COMPARE_AUID_TO_EUID: - return audit_uid_comparator(tsk->loginuid, f->op, cred->euid); + return audit_uid_comparator(audit_get_loginuid(tsk), f->op, + cred->euid); case AUDIT_COMPARE_AUID_TO_SUID: - return audit_uid_comparator(tsk->loginuid, f->op, cred->suid); + return audit_uid_comparator(audit_get_loginuid(tsk), f->op, + cred->suid); case AUDIT_COMPARE_AUID_TO_FSUID: - return audit_uid_comparator(tsk->loginuid, f->op, cred->fsuid); + return audit_uid_comparator(audit_get_loginuid(tsk), f->op, + cred->fsuid); /* euid comparisons */ case AUDIT_COMPARE_EUID_TO_SUID: return audit_uid_comparator(cred->euid, f->op, cred->suid); @@ -611,7 +615,8 @@ static int audit_filter_rules(struct task_struct *tsk, result = match_tree_refs(ctx, rule->tree); break; case AUDIT_LOGINUID: - result = audit_uid_comparator(tsk->loginuid, f->op, f->uid); + result = audit_uid_comparator(audit_get_loginuid(tsk), + f->op, f->uid); break; case AUDIT_LOGINUID_SET: result = audit_comparator(audit_loginuid_set(tsk), f->op, f->val); @@ -2278,14 +2283,15 @@ int audit_signal_info(int sig, struct task_struct *t) { struct audit_aux_data_pids *axp; struct audit_context *ctx = audit_context(); - kuid_t uid = current_uid(), t_uid = task_uid(t); + kuid_t uid = current_uid(), auid, t_uid = task_uid(t); if (auditd_test_task(t) && (sig == SIGTERM || sig == SIGHUP || sig == SIGUSR1 || sig == SIGUSR2)) { audit_sig_pid = task_tgid_nr(current); - if (uid_valid(current->loginuid)) - audit_sig_uid = current->loginuid; + auid = audit_get_loginuid(current); + if (uid_valid(auid)) + audit_sig_uid = auid; else audit_sig_uid = uid; security_task_getsecid(current, &audit_sig_sid); -- 1.8.3.1
[PATCH ghak81 V3 1/3] audit: use new audit_context access funciton for seccomp_actions_logged
On the rebase of the following commit on the new seccomp actions_logged function, one audit_context access was missed. commit cdfb6b341f0f2409aba24b84f3b4b2bba50be5c5 ("audit: use inline function to get audit context") Signed-off-by: Richard Guy Briggs --- kernel/auditsc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/auditsc.c b/kernel/auditsc.c index cbab0da..f3d3dc6 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -2497,7 +2497,7 @@ void audit_seccomp_actions_logged(const char *names, const char *old_names, if (!audit_enabled) return; - ab = audit_log_start(current->audit_context, GFP_KERNEL, + ab = audit_log_start(audit_context(), GFP_KERNEL, AUDIT_CONFIG_CHANGE); if (unlikely(!ab)) return; -- 1.8.3.1
[PATCH ghak81 V3 0/3] audit: group task params
Group the audit parameters for each task into one structure. In particular, remove the loginuid and sessionid values and the audit context pointer from the task structure, replacing them with an audit task information structure to contain them. Use access functions to access audit values. Use dynamic allocation of the audit task information structure employing kmem_cache. Static allocation has the limitation that future audit task information structure changes would cause a visible change to the rest of the kernel, whereas dynamic allocation would mostly hide any future changes. Passes audit-testsuite. Changelog: v3 - drop patches 2, 3, 4 already merged. - fix for previous v2 patch 3 (seccomp get audit_context) - dynamic audit_task_info allocation from kmem_cache - fix assignment in if statement v2 patch 1 (normalize loginuid read) - fix a number of merge conflicts/checkpatch v2 - p2/5: add audit header to init/init_task.c to quiet kbuildbot - audit_signal_info(): fetch loginuid once - remove task_struct from audit_context() param list - remove extra task_struct local vars - do nothing on request to set audit context when audit is disabled Richard Guy Briggs (3): audit: use new audit_context access funciton for seccomp_actions_logged audit: normalize loginuid read access audit: collect audit task parameters include/linux/audit.h | 34 --- include/linux/sched.h | 5 +--- init/init_task.c | 3 +- init/main.c | 2 ++ kernel/auditsc.c | 77 ++- kernel/fork.c | 2 +- 6 files changed, 87 insertions(+), 36 deletions(-) -- 1.8.3.1
Re: [RFC PATCH ghak32 V2 03/13] audit: log container info of syscalls
On 2018-05-17 17:09, Steve Grubb wrote: > On Fri, 16 Mar 2018 05:00:30 -0400 > Richard Guy Briggs wrote: > > > Create a new audit record AUDIT_CONTAINER_INFO to document the > > container ID of a process if it is present. > > As mentioned in a previous email, I think AUDIT_CONTAINER is more > suitable for the container record. One more comment below... > > > Called from audit_log_exit(), syscalls are covered. > > > > A sample raw event: > > type=SYSCALL msg=audit(1519924845.499:257): arch=c03e syscall=257 > > success=yes exit=3 a0=ff9c 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= cap_fi= 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= cap_fi= > > cap_fe=0 cap_fver=0 type=PROCTITLE msg=audit(1519924845.499:257): > > proctitle=62617368002D6300736C65657020313B206563686F2074657374203E202F746D702F746D70636F6E7461696E65726964 > > type=CONTAINER_INFO msg=audit(1519924845.499:257): op=task > > contid=123458 > > > > See: https://github.com/linux-audit/audit-kernel/issues/32 > > Signed-off-by: Richard Guy Briggs > > --- > > include/linux/audit.h | 5 + > > include/uapi/linux/audit.h | 1 + > > kernel/audit.c | 20 > > kernel/auditsc.c | 2 ++ > > 4 files changed, 28 insertions(+) > > > > diff --git a/include/linux/audit.h b/include/linux/audit.h > > index fe4ba3f..3acbe9d 100644 > > --- a/include/linux/audit.h > > +++ b/include/linux/audit.h > > @@ -154,6 +154,8 @@ extern void > > audit_log_link_denied(const char *operation, extern int > > audit_log_task_context(struct audit_buffer *ab); extern void > > audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk); > > +extern int audit_log_container_info(struct task_struct *tsk, > > +struct audit_context *context); > > > > extern int audit_update_lsm_rules(void); > > > > @@ -205,6 +207,9 @@ static inline int audit_log_task_context(struct > > audit_buffer *ab) static inline void audit_log_task_info(struct > > audit_buffer *ab, struct task_struct *tsk) > > { } > > +static inline int audit_log_container_info(struct task_struct *tsk, > > + struct audit_context > > *context); +{ } > > #define audit_enabled 0 > > #endif /* CONFIG_AUDIT */ > > > > diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h > > index 921a71f..e83ccbd 100644 > > --- a/include/uapi/linux/audit.h > > +++ b/include/uapi/linux/audit.h > > @@ -115,6 +115,7 @@ > > #define AUDIT_REPLACE 1329/* Replace auditd > > if this packet unanswerd */ #define AUDIT_KERN_MODULE > > 1330/* Kernel Module events */ #define > > AUDIT_FANOTIFY 1331/* Fanotify access decision > > */ +#define AUDIT_CONTAINER_INFO1332/* Container ID > > information */ #define AUDIT_AVC1400/* SE > > Linux avc denial or grant */ #define AUDIT_SELINUX_ERR > > 1401/* Internal SE Linux Errors */ diff --git > > a/kernel/audit.c b/kernel/audit.c index 3f2f143..a12f21f 100644 > > --- a/kernel/audit.c > > +++ b/kernel/audit.c > > @@ -2049,6 +2049,26 @@ void audit_log_session_info(struct > > audit_buffer *ab) audit_log_format(ab, " auid=%u ses=%u", auid, > > sessionid); } > > > > +/* > > + * audit_log_container_info - report container info > > + * @tsk: task to be recorded > > + * @context: task or local context for record > > + */ > > +int audit_log_container_info(struct task_struct *tsk, struct > > audit_context *context) +{ > > + struct audit_buffer *ab; > > + > > + if (!audit_containerid_set(tsk)) > > + return 0; > > + /* Generate AUDIT_CONTAINER_INFO with
Re: [RFC PATCH ghak32 V2 01/13] audit: add container id
On 2018-05-17 17:00, Steve Grubb wrote: > On Fri, 16 Mar 2018 05:00:28 -0400 > Richard Guy Briggs wrote: > > > Implement the proc fs write to set the audit container ID of a > > process, emitting an AUDIT_CONTAINER record to document the event. > > > > This is a write from the container orchestrator task to a proc entry > > of the form /proc/PID/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). > > > > This will produce a record such as this: > > type=CONTAINER msg=audit(1519903238.968:261): op=set pid=596 uid=0 > > subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 auid=0 > > tty=pts0 ses=1 opid=596 old-contid=18446744073709551615 contid=123455 > > res=0 > > The was one thing I was wondering about. Currently when we set the > loginuid, the record is AUDIT_LOGINUID. The corollary is that when we > set the container id, the event should be AUDIT_CONTAINERID or > AUDIT_CONTAINER_ID. The record type is actually AUDIT_LOGIN. The field type is AUDIT_LOGINUID. Given that correction, I think we're fine and could potentially violently agree. The existing naming is consistent. > During syscall events, the path info is returned in a a record simply > called AUDIT_PATH, cwd info is returned in AUDIT_CWD. So, rather than > calling the record that gets attached to everything > AUDIT_CONTAINER_INFO, how about simply AUDIT_CONTAINER. Considering the container initiation record is different than the record to document the container involved in an otherwise normal syscall, we need two names. I don't have a strong opinion what they are. I'd prefer AUDIT_CONTAINER and AUDIT_CONTAINER_INFO so that the two are different enough to be visually distinct while leaving AUDIT_CONTAINERID for the field type in patch 4 ("audit: add containerid filtering") > > 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 container ID values are given > > in the "contid" fields, while res indicates its success. > > > > It is not permitted to self-set, unset or re-set the container ID. A > > child inherits its parent's container ID, but then can be set only > > once after. > > > > See: https://github.com/linux-audit/audit-kernel/issues/32 > > > > Signed-off-by: Richard Guy Briggs > > --- > > fs/proc/base.c | 37 > > include/linux/audit.h | 16 + > > include/linux/init_task.h | 4 ++- > > include/linux/sched.h | 1 + > > include/uapi/linux/audit.h | 2 ++ > > kernel/auditsc.c | 84 > > ++ 6 files changed, 143 > > insertions(+), 1 deletion(-) > > > > diff --git a/fs/proc/base.c b/fs/proc/base.c > > index 60316b5..6ce4fbe 100644 > > --- a/fs/proc/base.c > > +++ b/fs/proc/base.c > > @@ -1299,6 +1299,41 @@ static ssize_t proc_sessionid_read(struct file > > * file, char __user * buf, .read= proc_sessionid_read, > > .llseek = generic_file_llseek, > > }; > > + > > +static ssize_t proc_containerid_write(struct file *file, const char > > __user *buf, > > + size_t count, loff_t *ppos) > > +{ > > + struct inode *inode = file_inode(file); > > + u64 containerid; > > + 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, &containerid); > > + if (rv < 0) { > > + put_task_struct(task); > > + return rv; > > + } > > + > > + rv = audit_set_containerid(task, containerid); > > + put_task_struct(task); > > + if (rv < 0) > > + return rv; > > + return count; > > +} > > + > > +static const struct file_operations proc_containerid_operations = { > > + .write = proc_containerid_write, > > + .llseek = generic_file_llseek, > > +}; > > + > > #endif > > > > #ifdef CONFIG_FAULT_INJECTION > >
Re: [RFC PATCH ghak32 V2 01/13] audit: add container id
On 2018-05-18 09:56, Steve Grubb wrote: > On Thu, 17 May 2018 17:56:00 -0400 > Richard Guy Briggs wrote: > > > > During syscall events, the path info is returned in a a record > > > simply called AUDIT_PATH, cwd info is returned in AUDIT_CWD. So, > > > rather than calling the record that gets attached to everything > > > AUDIT_CONTAINER_INFO, how about simply AUDIT_CONTAINER. > > > > Considering the container initiation record is different than the > > record to document the container involved in an otherwise normal > > syscall, we need two names. I don't have a strong opinion what they > > are. > > > > I'd prefer AUDIT_CONTAIN and AUDIT_CONTAINER_INFO so that the two > > are different enough to be visually distinct while leaving > > AUDIT_CONTAINERID for the field type in patch 4 ("audit: add > > containerid filtering") (Sorry, I had intended AUDIT_CONTAINER for the first in that paragraph above.) > How about AUDIT_CONTAINER for the auxiliary record? The one that starts > the container, I don't have a strong opinion on. Could be > AUDIT_CONTAINER_INIT, AUDIT_CONTAINER_START, AUDIT_CONTAINERID, > AUDIT_CONTAINER_ID, or something else. The API call that sets the ID > for filtering could be AUDIT_CID or AUDIT_CONTID if that helps decide > what the initial event might be. Normally, it should match the field > being filtered. Ok, I had shortened the record field name to "contid=" to be unique enough while not using too much netlink bandwidth. I could have used "cid=" but that could be unobvious or ambiguous. I didn't want to use the full "containerid=" due to that. I suppose I could change the field name macro to AUDIT_CONTID. For the one that starts the container, I'd prefer to leave the name a bit more general than "_INIT", "_START", so maybe I'll swap them around and use AUDIT_CONTAINER_INFO for the startup record, and use AUDIT_CONTAINER for the syscall auxiliary record. Does that work? > -Steve - RGB -- Richard Guy Briggs 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: [RFC PATCH ghak32 V2 13/13] debug audit: read container ID of a process
On 2018-05-21 16:06, Paul Moore wrote: > On Mon, May 21, 2018 at 3:19 PM, Eric W. Biederman > wrote: > > Steve Grubb writes: > >> On Friday, March 16, 2018 5:00:40 AM EDT Richard Guy Briggs wrote: > >>> Add support for reading the container ID from the proc filesystem. > >> > >> I think this could be useful in general. Please consider this to be part of > >> the full patch set and not something merely used to debug the patches. > > > > Only with an audit specific name. > > > > As it is: > > > > Nacked-by: "Eric W. Biederman" > > > > The truth is the containerid name really stinks and is quite confusing > > and does not imply that the label applies only to audit. And little > > things like this make me extremely uncofortable with it. > > It also makes the audit container ID (notice how I *always* call it > the *audit* container ID? that is not an accident) available for > userspace applications to abuse. Perhaps in the future we can look at > ways to make this more available to applications, but this patch is > not the answer. Do you have a productive suggestion? > paul moore - RGB -- Richard Guy Briggs 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 (was ghak32) V4 03/10] audit: log container info of syscalls
On 2018-10-25 17:57, Steve Grubb wrote: > On Thu, 25 Oct 2018 08:27:32 -0400 > Richard Guy Briggs wrote: > > > On 2018-10-25 06:49, Paul Moore wrote: > > > On Thu, Oct 25, 2018 at 2:06 AM Steve Grubb > > > wrote: > > > > On Wed, 24 Oct 2018 20:42:55 -0400 > > > > Richard Guy Briggs wrote: > > > > > On 2018-10-24 16:55, Paul Moore wrote: > > > > > > On Wed, Oct 24, 2018 at 11:15 AM Richard Guy Briggs > > > > > > wrote: > > > > > > > On 2018-10-19 19:16, Paul Moore wrote: > > > > > > > > On Sun, Aug 5, 2018 at 4:32 AM Richard Guy Briggs > > > > > > > > wrote: > > > > > > ... > > > > > > > > > > > > +/* > > > > > > > > > + * audit_log_contid - report container info > > > > > > > > > + * @tsk: task to be recorded > > > > > > > > > + * @context: task or local context for record > > > > > > > > > + * @op: contid string description > > > > > > > > > + */ > > > > > > > > > +int audit_log_contid(struct task_struct *tsk, > > > > > > > > > +struct audit_context > > > > > > > > > *context, char *op) +{ > > > > > > > > > + struct audit_buffer *ab; > > > > > > > > > + > > > > > > > > > + if (!audit_contid_set(tsk)) > > > > > > > > > + return 0; > > > > > > > > > + /* Generate AUDIT_CONTAINER record with > > > > > > > > > container ID */ > > > > > > > > > + ab = audit_log_start(context, GFP_KERNEL, > > > > > > > > > AUDIT_CONTAINER); > > > > > > > > > + if (!ab) > > > > > > > > > + return -ENOMEM; > > > > > > > > > + audit_log_format(ab, "op=%s contid=%llu", > > > > > > > > > +op, audit_get_contid(tsk)); > > > > > > > > > + audit_log_end(ab); > > > > > > > > > + return 0; > > > > > > > > > +} > > > > > > > > > +EXPORT_SYMBOL(audit_log_contid); > > > > > > > > > > > > > > > > As discussed in the previous iteration of the patch, I > > > > > > > > prefer AUDIT_CONTAINER_ID here over AUDIT_CONTAINER. If > > > > > > > > you feel strongly about keeping it as-is with > > > > > > > > AUDIT_CONTAINER I suppose I could live with that, but it > > > > > > > > is isn't my first choice. > > > > > > > > > > > > > > I don't have a strong opinion on this one, mildly > > > > > > > preferring the shorter one only because it is shorter. > > > > > > > > > > > > We already have multiple AUDIT_CONTAINER* record types, so it > > > > > > seems as though we should use "AUDIT_CONTAINER" as a prefix > > > > > > of sorts, rather than a type itself. > > > > > > > > > > I'm fine with that. I'd still like to hear Steve's input. He > > > > > had stronger opinions than me. > > > > > > > > The creation event should be separate and distinct from the > > > > continuing use when its used as a supplemental record. IOW, > > > > binding the ID to a container is part of the lifecycle and needs > > > > to be kept distinct. > > > > > > Steve's comment is pretty ambiguous when it comes to AUDIT_CONTAINER > > > vs AUDIT_CONTAINER_ID, but one could argue that AUDIT_CONTAINER_ID > > > helps distinguish the audit container id marking record and gets to > > > what I believe is the spirit of Steve's comment. Taking this in > > > context with my previous remarks, let's switch to using > > > AUDIT_CONTAINER_ID. > > > > I suspect Steve is mixing up AUDIT_CONTAINER_OP with > > AUDIT_CONTAINER_ID, confusing the fact that they are two seperate > > records. As a summary, the suggested records are: > > CONTAINER_OPaudit container identifier creation > > CONTAINER audit container identifier aux rec
[PATCH] xfrm: fix header file comment reference to struct xfrm_replay_state_esn
Reported-by: Paul Wouters Signed-off-by: Richard Guy Briggs --- include/uapi/linux/xfrm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/uapi/linux/xfrm.h b/include/uapi/linux/xfrm.h index 1433389..1fc62b2 100644 --- a/include/uapi/linux/xfrm.h +++ b/include/uapi/linux/xfrm.h @@ -298,7 +298,7 @@ enum xfrm_attr_type_t { XFRMA_ALG_AUTH_TRUNC, /* struct xfrm_algo_auth */ XFRMA_MARK, /* struct xfrm_mark */ XFRMA_TFCPAD, /* __u32 */ - XFRMA_REPLAY_ESN_VAL, /* struct xfrm_replay_esn */ + XFRMA_REPLAY_ESN_VAL, /* struct xfrm_replay_state_esn */ XFRMA_SA_EXTRA_FLAGS, /* __u32 */ XFRMA_PROTO,/* __u8 */ XFRMA_ADDRESS_FILTER, /* struct xfrm_address_filter */ -- 2.1.4
Re: [PATCH] xfrm: fix header file comment reference to struct xfrm_replay_state_esn
On 16/09/08, Richard Guy Briggs wrote: > Reported-by: Paul Wouters Oops, this above should read "nohats.ca". > Signed-off-by: Richard Guy Briggs > --- > include/uapi/linux/xfrm.h | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/include/uapi/linux/xfrm.h b/include/uapi/linux/xfrm.h > index 1433389..1fc62b2 100644 > --- a/include/uapi/linux/xfrm.h > +++ b/include/uapi/linux/xfrm.h > @@ -298,7 +298,7 @@ enum xfrm_attr_type_t { > XFRMA_ALG_AUTH_TRUNC, /* struct xfrm_algo_auth */ > XFRMA_MARK, /* struct xfrm_mark */ > XFRMA_TFCPAD, /* __u32 */ > - XFRMA_REPLAY_ESN_VAL, /* struct xfrm_replay_esn */ > + XFRMA_REPLAY_ESN_VAL, /* struct xfrm_replay_state_esn */ > XFRMA_SA_EXTRA_FLAGS, /* __u32 */ > XFRMA_PROTO,/* __u8 */ > XFRMA_ADDRESS_FILTER, /* struct xfrm_address_filter */ > -- > 2.1.4 slainte mhath, RGB -- Richard Guy Briggs -- ~\-- ~\ -- \___ o \@ @ Ride yer bike! Ottawa, ON, CANADA -- Lo_>__M__\\/\%__\\/\% Vote! -- _GTVS6#790__(*)__(*)(*)(*)_
Re: netlink: GPF in sock_sndtimeo
On 2016-11-26 17:11, Cong Wang wrote: > On Sat, Nov 26, 2016 at 7:44 AM, Dmitry Vyukov wrote: > > Hello, Eric, thanks for the heads up on this. (more below...) > > The following program triggers GPF in sock_sndtimeo: > > https://gist.githubusercontent.com/dvyukov/c19cadd309791cf5cb9b2bf936d3f48d/raw/1743ba0211079a5465d039512b427bc6b59b1a76/gistfile1.txt > > > > On commit 16ae16c6e5616c084168740990fc508bda6655d4 (Nov 24). > > > > general protection fault: [#1] SMP DEBUG_PAGEALLOC KASAN > > Dumping ftrace buffer: > >(ftrace buffer empty) > > Modules linked in: > > CPU: 1 PID: 19950 Comm: syz-executor Not tainted 4.9.0-rc5+ #54 > > Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011 > > task: 88002a0d0840 task.stack: 88003692 > > RIP: 0010:[] [< inline >] sock_sndtimeo > > include/net/sock.h:2075 > > RIP: 0010:[] [] > > netlink_unicast+0xe1/0x730 net/netlink/af_netlink.c:1232 > > RSP: 0018:880036926f68 EFLAGS: 00010202 > > RAX: 0068 RBX: 880036927000 RCX: c900021d > > RDX: 0d63 RSI: 024000c0 RDI: 0340 > > RBP: 880036927028 R08: ed0006ea7aab R09: ed0006ea7aab > > R10: 0001 R11: ed0006ea7aaa R12: dc00 > > R13: R14: 880035de3400 R15: 880035de3400 > > FS: 7f90a2fc7700() GS:88003ed0() knlGS: > > CS: 0010 DS: ES: CR0: 80050033 > > CR2: 006de0c0 CR3: 35de6000 CR4: 06e0 > > Stack: > > 880035de3400 819f02a1 110006d24df4 0004 > > 4db40014 880036926fd8 41b58ab3 > > 89653c11 86cb3500 819f0345 880035de3400 > > Call Trace: > > [< inline >] audit_replace kernel/audit.c:817 > > [] audit_receive_msg+0x22c9/0x2ce0 kernel/audit.c:894 > > [< inline >] audit_receive_skb kernel/audit.c:1120 > > [] audit_receive+0x1dc/0x360 kernel/audit.c:1133 > > [< inline >] netlink_unicast_kernel net/netlink/af_netlink.c:1214 > > [] netlink_unicast+0x514/0x730 > > net/netlink/af_netlink.c:1240 > > [] netlink_sendmsg+0xaa4/0xe50 > > net/netlink/af_netlink.c:1786 > > [< inline >] sock_sendmsg_nosec net/socket.c:621 > > [] sock_sendmsg+0xcf/0x110 net/socket.c:631 > > [] sock_write_iter+0x32b/0x620 net/socket.c:829 > > [< inline >] new_sync_write fs/read_write.c:499 > > [] __vfs_write+0x4fe/0x830 fs/read_write.c:512 > > [] vfs_write+0x175/0x4e0 fs/read_write.c:560 > > [< inline >] SYSC_write fs/read_write.c:607 > > [] SyS_write+0x100/0x240 fs/read_write.c:599 > > [] do_syscall_64+0x2f4/0x940 arch/x86/entry/common.c:280 > > [] entry_SYSCALL64_slow_path+0x25/0x25 > > Code: fe 4c 89 f7 e8 31 16 ff ff 8b 8d 70 ff ff ff 49 89 c7 31 c0 85 > > c9 75 25 e8 7d 4a a3 fa 49 8d bd 40 03 00 00 48 89 f8 48 c1 e8 03 <42> > > 80 3c 20 00 0f 85 3a 06 00 00 49 8b 85 40 03 00 00 4c 8d 73 > > RIP [< inline >] sock_sndtimeo include/net/sock.h:2075 > > RIP [] netlink_unicast+0xe1/0x730 > > net/netlink/af_netlink.c:1232 > > RSP > > ---[ end trace 8383a15fba6fdc59 ]--- > > It is racy on audit_sock, especially on the netns exit path. I think that is the only place it is racy. The other places audit_sock is set is when the socket failure has just triggered a reset. Is there a notifier callback for failed or reaped sockets? > Could the following patch help a little bit? Also, I don't see how the > synchronize_net() here could sync with netlink rcv path, since unlike > packets from wire, netlink messages are not handled in BH context > nor I see any RCU taken on rcv path. Thanks Cong, this looks like it could help. I'll have a closer look. > diff --git a/kernel/audit.c b/kernel/audit.c > index f1ca116..20bc79e 100644 > --- a/kernel/audit.c > +++ b/kernel/audit.c > @@ -1167,10 +1167,13 @@ static void __net_exit audit_net_exit(struct net *net) > { > struct audit_net *aunet = net_generic(net, audit_net_id); > struct sock *sock = aunet->nlsk; > + > + mutex_lock(&audit_cmd_mutex); > if (sock == audit_sock) { > audit_pid = 0; > audit_sock = NULL; > } > + mutex_unlock(&audit_cmd_mutex); > > RCU_INIT_POINTER(aunet->nlsk, NULL); > synchronize_net(); - RGB -- Richard Guy Briggs Kernel Security Engineering, Base Operating Systems, Red Hat Remote, Ottawa, Canada Voice: +1.647.777.2635, Internal: (81) 32635
Re: netlink: GPF in sock_sndtimeo
On 2016-11-29 15:13, Cong Wang wrote: > On Tue, Nov 29, 2016 at 8:48 AM, Richard Guy Briggs wrote: > > On 2016-11-26 17:11, Cong Wang wrote: > >> It is racy on audit_sock, especially on the netns exit path. > > > > I think that is the only place it is racy. The other places audit_sock > > is set is when the socket failure has just triggered a reset. > > > > Is there a notifier callback for failed or reaped sockets? > > Is NETLINK_URELEASE event what you are looking for? Possibly, yes. Thanks, I'll have a look. - RGB -- Richard Guy Briggs Kernel Security Engineering, Base Operating Systems, Red Hat Remote, Ottawa, Canada Voice: +1.647.777.2635, Internal: (81) 32635
Re: [Patch net-next] audit: remove useless synchronize_net()
On 2016-11-29 09:14, Cong Wang wrote: > netlink kernel socket is protected by refcount, not RCU. > Its rcv path is neither protected by RCU. So the synchronize_net() > is just pointless. If I understand correctly, xfrm_user_net_exit() usage of RCU_INIT_POINTER() and synchronize_net() is similarly pointless? Also net/phonet/socket.c? I probably modelled things based on the former... > Cc: Richard Guy Briggs > Signed-off-by: Cong Wang > --- > kernel/audit.c | 3 +-- > 1 file changed, 1 insertion(+), 2 deletions(-) > > diff --git a/kernel/audit.c b/kernel/audit.c > index 92c463d..67b9fbd8 100644 > --- a/kernel/audit.c > +++ b/kernel/audit.c > @@ -1172,9 +1172,8 @@ static void __net_exit audit_net_exit(struct net *net) > audit_sock = NULL; > } > > - RCU_INIT_POINTER(aunet->nlsk, NULL); > - synchronize_net(); > netlink_kernel_release(sock); > + aunet->nlsk = NULL; > } > > static struct pernet_operations audit_net_ops __net_initdata = { > -- > 2.1.0 > - RGB -- Richard Guy Briggs Kernel Security Engineering, Base Operating Systems, Red Hat Remote, Ottawa, Canada Voice: +1.647.777.2635, Internal: (81) 32635
Re: netlink: GPF in sock_sndtimeo
On 2016-11-29 23:52, Richard Guy Briggs wrote: > On 2016-11-29 15:13, Cong Wang wrote: > > On Tue, Nov 29, 2016 at 8:48 AM, Richard Guy Briggs wrote: > > > On 2016-11-26 17:11, Cong Wang wrote: > > >> It is racy on audit_sock, especially on the netns exit path. > > > > > > I think that is the only place it is racy. The other places audit_sock > > > is set is when the socket failure has just triggered a reset. > > > > > > Is there a notifier callback for failed or reaped sockets? > > > > Is NETLINK_URELEASE event what you are looking for? > > Possibly, yes. Thanks, I'll have a look. I tried a quick compile attempt on the test case (I assume it is a socket fuzzer) and get the following compile error: cc -g -O0 -Wall -D_GNU_SOURCE -o socket_fuzz socket_fuzz.c socket_fuzz.c:16:1: warning: "_GNU_SOURCE" redefined : warning: this is the location of the previous definition socket_fuzz.c: In function ‘segv_handler’: socket_fuzz.c:89: warning: implicit declaration of function ‘__atomic_load_n’ socket_fuzz.c:89: error: ‘__ATOMIC_RELAXED’ undeclared (first use in this function) socket_fuzz.c:89: error: (Each undeclared identifier is reported only once socket_fuzz.c:89: error: for each function it appears in.) socket_fuzz.c: In function ‘loop’: socket_fuzz.c:280: warning: unused variable ‘errno0’ socket_fuzz.c: In function ‘test’: socket_fuzz.c:303: warning: implicit declaration of function ‘__atomic_fetch_add’ socket_fuzz.c:303: error: ‘__ATOMIC_SEQ_CST’ undeclared (first use in this function) socket_fuzz.c:303: warning: implicit declaration of function ‘__atomic_fetch_sub’ I also tried to extend Cong Wang's idea to attempt to proactively respond to a NETLINK_URELEASE on the audit_sock and reset it, but ran into a locking error stack dump using mutex_lock(&audit_cmd_mutex) in the notifier callback. Eliminating the lock since the sock is dead anways eliminates the error. Is it safe? I'll resubmit if this looks remotely sane. Meanwhile I'll try to get the test case to compile. This is being tracked as https://github.com/linux-audit/audit-kernel/issues/30 Subject: [PATCH] audit: proactively reset audit_sock on matching NETLINK_URELEASE diff --git a/kernel/audit.c b/kernel/audit.c index f1ca116..91d222d 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -423,6 +423,7 @@ static void kauditd_send_skb(struct sk_buff *skb) snprintf(s, sizeof(s), "audit_pid=%d reset", audit_pid); audit_log_lost(s); audit_pid = 0; + audit_nlk_portid = 0; audit_sock = NULL; } else { pr_warn("re-scheduling(#%d) write to audit_pid=%d\n", @@ -1143,6 +1144,28 @@ static int audit_bind(struct net *net, int group) return 0; } +static int audit_sock_netlink_notify(struct notifier_block *nb, +unsigned long event, +void *_notify) +{ + struct netlink_notify *notify = _notify; + struct audit_net *aunet = net_generic(notify->net, audit_net_id); + + if (event == NETLINK_URELEASE && notify->protocol == NETLINK_AUDIT) { + if (audit_nlk_portid == notify->portid && + audit_sock == aunet->nlsk) { + audit_pid = 0; + audit_nlk_portid = 0; + audit_sock = NULL; + } + } + return NOTIFY_DONE; +} + +static struct notifier_block audit_netlink_notifier = { + .notifier_call = audit_sock_netlink_notify, +}; + static int __net_init audit_net_init(struct net *net) { struct netlink_kernel_cfg cfg = { @@ -1167,10 +1190,14 @@ static void __net_exit audit_net_exit(struct net *net) { struct audit_net *aunet = net_generic(net, audit_net_id); struct sock *sock = aunet->nlsk; + + mutex_lock(&audit_cmd_mutex); if (sock == audit_sock) { audit_pid = 0; + audit_nlk_portid = 0; audit_sock = NULL; } + mutex_unlock(&audit_cmd_mutex); RCU_INIT_POINTER(aunet->nlsk, NULL); synchronize_net(); @@ -1202,6 +1229,7 @@ static int __init audit_init(void) audit_enabled = audit_default; audit_ever_enabled |= !!audit_default; + netlink_register_notifier(&audit_netlink_notifier); audit_log(NULL, GFP_KERNEL, AUDIT_KERNEL, "initialized"); for (i = 0; i < AUDIT_INODE_BUCKETS; i++) -- 1.7.1 > - RGB - RGB -- Richard Guy Briggs Kernel Security Engineering, Base Operating Systems, Red Hat Remote, Ottawa, Canada Voice: +1.647.777.2635, Internal: (81) 32635
Re: netlink: GPF in sock_sndtimeo
On 2016-12-08 22:57, Cong Wang wrote: > On Thu, Dec 8, 2016 at 10:02 PM, Richard Guy Briggs wrote: > > I also tried to extend Cong Wang's idea to attempt to proactively respond > > to a > > NETLINK_URELEASE on the audit_sock and reset it, but ran into a locking > > error > > stack dump using mutex_lock(&audit_cmd_mutex) in the notifier callback. > > Eliminating the lock since the sock is dead anways eliminates the error. > > > > Is it safe? I'll resubmit if this looks remotely sane. Meanwhile I'll try > > to > > get the test case to compile. > > It doesn't look safe, because 'audit_sock', 'audit_nlk_portid' and 'audit_pid' > are updated as a whole and race between audit_receive_msg() and > NETLINK_URELEASE. This is what I expected and why I originally added the mutex lock in the callback... The dumps I got were bare with no wrapper identifying the process context or specific error, so I'm at a bit of a loss how to solve this (without thinking more about it) other than instinctively removing the mutex. Another approach might be to look at consolidating the three into one identifier or derive the other two from one, or serialize their access. > > @@ -1167,10 +1190,14 @@ static void __net_exit audit_net_exit(struct net > > *net) > > { > > struct audit_net *aunet = net_generic(net, audit_net_id); > > struct sock *sock = aunet->nlsk; > > + > > + mutex_lock(&audit_cmd_mutex); > > if (sock == audit_sock) { > > audit_pid = 0; > > + audit_nlk_portid = 0; > > audit_sock = NULL; > > } > > + mutex_unlock(&audit_cmd_mutex); > > If you decide to use NETLINK_URELEASE notifier, the above piece is no > longer needed, the net_exit path simply releases a refcnt. Good point. It would have already killed it off. So this piece is arguably too late anyways. - RGB -- Richard Guy Briggs Kernel Security Engineering, Base Operating Systems, Red Hat Remote, Ottawa, Canada Voice: +1.647.777.2635, Internal: (81) 32635
Re: netlink: GPF in sock_sndtimeo
On 2016-12-09 11:49, Dmitry Vyukov wrote: > On Fri, Dec 9, 2016 at 7:02 AM, Richard Guy Briggs wrote: > > On 2016-11-29 23:52, Richard Guy Briggs wrote: > > I tried a quick compile attempt on the test case (I assume it is a > > socket fuzzer) and get the following compile error: > > cc -g -O0 -Wall -D_GNU_SOURCE -o socket_fuzz socket_fuzz.c > > socket_fuzz.c:16:1: warning: "_GNU_SOURCE" redefined > > : warning: this is the location of the previous definition > > socket_fuzz.c: In function ‘segv_handler’: > > socket_fuzz.c:89: warning: implicit declaration of function > > ‘__atomic_load_n’ > > socket_fuzz.c:89: error: ‘__ATOMIC_RELAXED’ undeclared (first use in this > > function) > > socket_fuzz.c:89: error: (Each undeclared identifier is reported only once > > socket_fuzz.c:89: error: for each function it appears in.) > > socket_fuzz.c: In function ‘loop’: > > socket_fuzz.c:280: warning: unused variable ‘errno0’ > > socket_fuzz.c: In function ‘test’: > > socket_fuzz.c:303: warning: implicit declaration of function > > ‘__atomic_fetch_add’ > > socket_fuzz.c:303: error: ‘__ATOMIC_SEQ_CST’ undeclared (first use in this > > function) > > socket_fuzz.c:303: warning: implicit declaration of function > > ‘__atomic_fetch_sub’ > > -std=gnu99 should help > ignore warnings I got a little further, left with "__ATOMIC_RELAXED undeclared", "__ATOMIC_SEQ_CST undeclared" under gcc 4.4.7-16. gcc 4.8.2-15 leaves me with "undefined reference to `clock_gettime'" What compiler version do you recommend? > >> - RGB > > > > - RGB - RGB -- Richard Guy Briggs Kernel Security Engineering, Base Operating Systems, Red Hat Remote, Ottawa, Canada Voice: +1.647.777.2635, Internal: (81) 32635
Re: netlink: GPF in sock_sndtimeo
On 2016-12-09 12:53, Dmitry Vyukov wrote: > On Fri, Dec 9, 2016 at 12:48 PM, Richard Guy Briggs wrote: > > On 2016-12-09 11:49, Dmitry Vyukov wrote: > >> On Fri, Dec 9, 2016 at 7:02 AM, Richard Guy Briggs wrote: > >> > On 2016-11-29 23:52, Richard Guy Briggs wrote: > >> > I tried a quick compile attempt on the test case (I assume it is a > >> > socket fuzzer) and get the following compile error: > >> > cc -g -O0 -Wall -D_GNU_SOURCE -o socket_fuzz socket_fuzz.c > >> > socket_fuzz.c:16:1: warning: "_GNU_SOURCE" redefined > >> > : warning: this is the location of the previous definition > >> > socket_fuzz.c: In function ‘segv_handler’: > >> > socket_fuzz.c:89: warning: implicit declaration of function > >> > ‘__atomic_load_n’ > >> > socket_fuzz.c:89: error: ‘__ATOMIC_RELAXED’ undeclared (first use in > >> > this function) > >> > socket_fuzz.c:89: error: (Each undeclared identifier is reported only > >> > once > >> > socket_fuzz.c:89: error: for each function it appears in.) > >> > socket_fuzz.c: In function ‘loop’: > >> > socket_fuzz.c:280: warning: unused variable ‘errno0’ > >> > socket_fuzz.c: In function ‘test’: > >> > socket_fuzz.c:303: warning: implicit declaration of function > >> > ‘__atomic_fetch_add’ > >> > socket_fuzz.c:303: error: ‘__ATOMIC_SEQ_CST’ undeclared (first use in > >> > this function) > >> > socket_fuzz.c:303: warning: implicit declaration of function > >> > ‘__atomic_fetch_sub’ > >> > >> -std=gnu99 should help > >> ignore warnings > > > > I got a little further, left with "__ATOMIC_RELAXED undeclared", > > "__ATOMIC_SEQ_CST > > undeclared" under gcc 4.4.7-16. > > > > gcc 4.8.2-15 leaves me with "undefined reference to `clock_gettime'" > > add -lrt Ok, that helped. Thanks! > > What compiler version do you recommend? > > 6.x sounds reasonable > 4.4 branch is 7.5 years old, surprised that it does not disintegrate > into dust yet :) These are under RHEL6... so there are updates to them, but yeah, they are old. > >> >> - RGB > >> > > >> > - RGB > > > > - RGB > > > > -- > > Richard Guy Briggs > > Kernel Security Engineering, Base Operating Systems, Red Hat > > Remote, Ottawa, Canada > > Voice: +1.647.777.2635, Internal: (81) 32635 - RGB -- Richard Guy Briggs Kernel Security Engineering, Base Operating Systems, Red Hat Remote, Ottawa, Canada Voice: +1.647.777.2635, Internal: (81) 32635
Re: netlink: GPF in sock_sndtimeo
On 2016-12-09 20:13, Cong Wang wrote: > On Fri, Dec 9, 2016 at 3:01 AM, Richard Guy Briggs wrote: > > On 2016-12-08 22:57, Cong Wang wrote: > >> On Thu, Dec 8, 2016 at 10:02 PM, Richard Guy Briggs > >> wrote: > >> > I also tried to extend Cong Wang's idea to attempt to proactively > >> > respond to a > >> > NETLINK_URELEASE on the audit_sock and reset it, but ran into a locking > >> > error > >> > stack dump using mutex_lock(&audit_cmd_mutex) in the notifier callback. > >> > Eliminating the lock since the sock is dead anways eliminates the error. > >> > > >> > Is it safe? I'll resubmit if this looks remotely sane. Meanwhile I'll > >> > try to > >> > get the test case to compile. > >> > >> It doesn't look safe, because 'audit_sock', 'audit_nlk_portid' and > >> 'audit_pid' > >> are updated as a whole and race between audit_receive_msg() and > >> NETLINK_URELEASE. > > > > This is what I expected and why I originally added the mutex lock in the > > callback... The dumps I got were bare with no wrapper identifying the > > process context or specific error, so I'm at a bit of a loss how to > > solve this (without thinking more about it) other than instinctively > > removing the mutex. > > Netlink notifier can safely be converted to blocking one, I will send > a patch. I had a quick look at how that might happen. The netlink notifier chain is atomic. Would the registered callback funciton need to spawn a one-time thread to avoid blocking? > But I seriously doubt you really need NETLINK_URELEASE here, > it adds nothing but overhead, b/c the netlink notifier is called on > every netlink socket in the system, but for net exit path, that is > relatively a slow path. I was a bit concerned about its overhead, but was hoping to update audit_sock more quickly in the case of a sock shutting down for any reason. > Also, kauditd_send_skb() needs audit_cmd_mutex too. Agreed. > I will send a formal patch. I had a look at your patch. It looks attractively simple. The audit next tree has patches queued that add an audit_reset function that will require more work. I still see some potential gaps. - If the process messes up (or the sock lookup messes up) it is reset in the kauditd thread under the audit_cmd_mutex. - If the process exits normally or is replaced due to an audit_replace error, it is reset from audit_receive_skb under the audit_cmd_mutex. - If the process dies before the kauditd thread notices, either reap it via notifier callback or it needs a check on net exit to reset. This last one appears necessary to decrement the sock refcount so the sock can be released in netlink_kernel_release(). If we want to be proactive and use the netlink notifier, we assume the overhead of adding to the netlink notifier chain and eliminate all the other reset calls under the kauditd thread. If we are ok being reactionary, then we'll at least need the net exit check on audit_sock. Have I understood this correctly? I'll follow with a patch based on audit#next There will be an upstream merge conflict between audit#next and net#next due to the removal of: RCU_INIT_POINTER(aunet->nlsk, NULL); synchronize_net(); from the end of audit_net_exit(). This patch should probably go through the audit maintainer due to the other anticipated merge conflicts. > Thanks. - RGB -- Richard Guy Briggs Kernel Security Engineering, Base Operating Systems, Red Hat Remote, Ottawa, Canada Voice: +1.647.777.2635, Internal: (81) 32635