Thread (51 messages) 51 messages, 3 authors, 2020-10-29

Re: [PATCH ghak90 V9 10/13] audit: add support for containerid to network namespaces

From: Paul Moore <paul@paul-moore.com>
Date: 2020-07-05 15:11:44
Also in: linux-fsdevel, lkml, netdev, netfilter-devel

On Sat, Jun 27, 2020 at 9:23 AM Richard Guy Briggs [off-list ref] wrote:
quoted hunk ↗ jump to hunk
This also adds support to qualify NETFILTER_PKT records.

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

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

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

Please see the github audit kernel issue for contid net support:
  https://github.com/linux-audit/audit-kernel/issues/92
Please see the github audit testsuiite issue for the test case:
  https://github.com/linux-audit/audit-testsuite/issues/64
Please see the github audit wiki for the feature overview:
  https://github.com/linux-audit/audit-kernel/wiki/RFE-Audit-Container-ID
Signed-off-by: Richard Guy Briggs <redacted>
Acked-by: Neil Horman <nhorman@tuxdriver.com>
Reviewed-by: Ondrej Mosnacek <omosnace@redhat.com>
---
 include/linux/audit.h    |  20 ++++++
 kernel/audit.c           | 156 ++++++++++++++++++++++++++++++++++++++++++++++-
 kernel/nsproxy.c         |   4 ++
 net/netfilter/nft_log.c  |  11 +++-
 net/netfilter/xt_AUDIT.c |  11 +++-
 5 files changed, 195 insertions(+), 7 deletions(-)
diff --git a/include/linux/audit.h b/include/linux/audit.h
index c4a755ae0d61..304fbb7c3c5b 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -128,6 +128,13 @@ struct audit_task_info {

 extern struct audit_task_info init_struct_audit;

+struct audit_contobj_netns {
+       struct list_head        list;
+       struct audit_contobj    *obj;
+       int                     count;
This seems like it might be a good candidate for refcount_t, yes?
+       struct rcu_head         rcu;
+};
...
quoted hunk ↗ jump to hunk
diff --git a/kernel/audit.c b/kernel/audit.c
index 997c34178ee8..a862721dfd9b 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -437,6 +452,136 @@ static struct sock *audit_get_sk(const struct net *net)
        return aunet->sk;
 }

+void audit_netns_contid_add(struct net *net, struct audit_contobj *cont)
+{
+       struct audit_net *aunet;
+       struct list_head *contobj_list;
+       struct audit_contobj_netns *contns;
+
+       if (!net)
+               return;
+       if (!cont)
+               return;
+       aunet = net_generic(net, audit_net_id);
+       if (!aunet)
+               return;
+       contobj_list = &aunet->contobj_list;
+       rcu_read_lock();
+       spin_lock(&aunet->contobj_list_lock);
+       list_for_each_entry_rcu(contns, contobj_list, list)
+               if (contns->obj == cont) {
+                       contns->count++;
+                       goto out;
+               }
+       contns = kmalloc(sizeof(*contns), GFP_ATOMIC);
+       if (contns) {
+               INIT_LIST_HEAD(&contns->list);
+               contns->obj = cont;
+               contns->count = 1;
+               list_add_rcu(&contns->list, contobj_list);
+       }
+out:
+       spin_unlock(&aunet->contobj_list_lock);
+       rcu_read_unlock();
+}
+
+void audit_netns_contid_del(struct net *net, struct audit_contobj *cont)
+{
+       struct audit_net *aunet;
+       struct list_head *contobj_list;
+       struct audit_contobj_netns *contns = NULL;
+
+       if (!net)
+               return;
+       if (!cont)
+               return;
+       aunet = net_generic(net, audit_net_id);
+       if (!aunet)
+               return;
+       contobj_list = &aunet->contobj_list;
+       rcu_read_lock();
+       spin_lock(&aunet->contobj_list_lock);
+       list_for_each_entry_rcu(contns, contobj_list, list)
+               if (contns->obj == cont) {
+                       contns->count--;
+                       if (contns->count < 1) {
One could simplify this with "(--countns->count) < 1", although if it
is changed to a refcount_t (which seems like a smart thing), the
normal decrement/test would be the best choice.

+                               list_del_rcu(&contns->list);
+                               kfree_rcu(contns, rcu);
+                       }
+                       break;
+               }
+       spin_unlock(&aunet->contobj_list_lock);
+       rcu_read_unlock();
+}
--
paul moore
www.paul-moore.com
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help