Track the parent container of a container to be able to filter and
report nesting.
Now that we have a way to track and check the parent container of a
container, modify the contid field format to be able to report that
nesting using a carrat ("^") modifier to indicate nesting. The
original field format was "contid=" for task-associated records
and "contid=[,[...]]" for network-namespace-associated
records. The new field format is
"contid=[,^[...]][,[...]]".
Signed-off-by: Richard Guy Briggs
---
include/linux/audit.h | 1 +
kernel/audit.c| 60 ++-
kernel/audit.h| 2 ++
kernel/auditfilter.c | 17 ++-
kernel/auditsc.c | 2 +-
5 files changed, 70 insertions(+), 12 deletions(-)
diff --git a/include/linux/audit.h b/include/linux/audit.h
index 304fbb7c3c5b..025b52ae8422 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -115,6 +115,7 @@ struct audit_contobj {
refcount_t refcount;
refcount_t sigflag;
struct rcu_head rcu;
+ struct audit_contobj*parent;
};
struct audit_task_info {
diff --git a/kernel/audit.c b/kernel/audit.c
index efa65ec01239..aaf74702e993 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -221,6 +221,7 @@ struct audit_reply {
void audit_netns_contid_add(struct net *net, struct audit_contobj *cont);
void audit_netns_contid_del(struct net *net, struct audit_contobj *cont);
+void audit_log_contid(struct audit_buffer *ab, struct audit_contobj *cont);
void __init audit_task_init(void)
{
@@ -277,6 +278,7 @@ static void _audit_contobj_put_sig(struct audit_contobj
*cont)
refcount_set(&cont->sigflag, 0);
if (!refcount_read(&cont->refcount)) {
put_task_struct(cont->owner);
+ _audit_contobj_put(cont->parent);
list_del_rcu(&cont->list);
kfree_rcu(cont, rcu);
}
@@ -574,7 +576,7 @@ void audit_log_netns_contid_list(struct net *net, struct
audit_context *context)
audit_log_format(ab, "contid=");
} else
audit_log_format(ab, ",");
- audit_log_format(ab, "%llu", cont->obj->id);
+ audit_log_contid(ab, cont->obj);
}
audit_log_end(ab);
out:
@@ -1747,7 +1749,9 @@ static int audit_receive_msg(struct sk_buff *skb, struct
nlmsghdr *nlh)
kfree(sig_data);
break;
case AUDIT_SIGNAL_INFO2: {
+ char *contidstr = NULL;
unsigned int contidstrlen = 0;
+ struct audit_contobj *cont = audit_sig_cid;
len = 0;
if (audit_sig_sid) {
@@ -1757,13 +1761,27 @@ static int audit_receive_msg(struct sk_buff *skb,
struct nlmsghdr *nlh)
return err;
}
if (audit_sig_cid) {
- contidstr = kmalloc(21, GFP_KERNEL);
+ contidstr = kmalloc(AUDIT_MESSAGE_TEXT_MAX, GFP_KERNEL);
if (!contidstr) {
if (audit_sig_sid)
security_release_secctx(ctx, len);
return -ENOMEM;
}
- contidstrlen = scnprintf(contidstr, 20, "%llu",
audit_sig_cid->id);
+ rcu_read_lock();
+ while (cont) {
+ if (cont->parent)
+ contidstrlen += scnprintf(contidstr,
+
AUDIT_MESSAGE_TEXT_MAX -
+ contidstrlen,
+ "%llu,^",
cont->id);
+ else
+ contidstrlen += scnprintf(contidstr,
+
AUDIT_MESSAGE_TEXT_MAX -
+ contidstrlen,
+ "%llu",
cont->id);
+ cont = cont->parent;
+ }
+ rcu_read_unlock();
}
sig_data2 = kmalloc(sizeof(*sig_data2) + contidstrlen + len,
GFP_KERNEL);
if (!sig_data2) {
@@ -2444,6 +2462,23 @@ void audit_log_session_info(struct audit_buffer *ab)
audit_log_format(ab, "auid=%u ses=%u", auid, sessionid);
}
+void audit_log_contid(struct audit_buffer *ab, struct audit_contobj *cont)
+{
+ if (!cont) {
+ audit_log_format(ab, "-1");
+ return;
+ }
+ rcu_read_lock();
+ while (cont) {
+ if (cont->parent)
+ audit_log_format(ab, "%llu,^", cont->id);
+