public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] audit: listen in all network namespaces
@ 2013-07-16 20:15 Richard Guy Briggs
  0 siblings, 0 replies; 7+ messages in thread
From: Richard Guy Briggs @ 2013-07-16 20:15 UTC (permalink / raw)
  To: Eric Paris; +Cc: linux-kernel, Richard Guy Briggs

Convert audit from only listening in init_net to use register_pernet_subsys()
to dynamically manage the netlink socket list.

Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
---
 kernel/audit.c |   64 ++++++++++++++++++++++++++++++++++++++++++++++---------
 kernel/audit.h |    4 +++
 2 files changed, 57 insertions(+), 11 deletions(-)

diff --git a/kernel/audit.c b/kernel/audit.c
index 91e53d0..06e2676 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -64,6 +64,7 @@
 #include <linux/freezer.h>
 #include <linux/tty.h>
 #include <linux/pid_namespace.h>
+#include <net/netns/generic.h>
 
 #include "audit.h"
 
@@ -122,6 +123,7 @@ static atomic_t    audit_lost = ATOMIC_INIT(0);
 
 /* The netlink socket. */
 static struct sock *audit_sock;
+int audit_net_id;
 
 /* Hash for inode-based rules */
 struct list_head audit_inode_hash[AUDIT_INODE_BUCKETS];
@@ -391,6 +393,7 @@ static void kauditd_send_skb(struct sk_buff *skb)
 		printk(KERN_ERR "audit: *NO* daemon at audit_pid=%d\n", audit_pid);
 		audit_log_lost("auditd disappeared\n");
 		audit_pid = 0;
+		audit_sock = NULL;
 		/* we might get lucky and get this in the next auditd */
 		audit_hold_skb(skb);
 	} else
@@ -474,13 +477,15 @@ int audit_send_list(void *_dest)
 	struct audit_netlink_list *dest = _dest;
 	int pid = dest->pid;
 	struct sk_buff *skb;
+	struct net *net = get_net_ns_by_pid(pid);
+	struct audit_net *aunet = net_generic(net, audit_net_id);
 
 	/* wait for parent to finish and send an ACK */
 	mutex_lock(&audit_cmd_mutex);
 	mutex_unlock(&audit_cmd_mutex);
 
 	while ((skb = __skb_dequeue(&dest->q)) != NULL)
-		netlink_unicast(audit_sock, skb, pid, 0);
+		netlink_unicast(aunet->nlsk, skb, pid, 0);
 
 	kfree(dest);
 
@@ -515,13 +520,15 @@ out_kfree_skb:
 static int audit_send_reply_thread(void *arg)
 {
 	struct audit_reply *reply = (struct audit_reply *)arg;
+	struct net *net = get_net_ns_by_pid(reply->pid);
+	struct audit_net *aunet = net_generic(net, audit_net_id);
 
 	mutex_lock(&audit_cmd_mutex);
 	mutex_unlock(&audit_cmd_mutex);
 
 	/* Ignore failure. It'll only happen if the sender goes away,
 	   because our timeout is set to infinite. */
-	netlink_unicast(audit_sock, reply->skb, reply->pid, 0);
+	netlink_unicast(aunet->nlsk , reply->skb, reply->pid, 0);
 	kfree(reply);
 	return 0;
 }
@@ -690,6 +697,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 				audit_log_config_change("audit_pid", new_pid, audit_pid, 1);
 			audit_pid = new_pid;
 			audit_nlk_portid = NETLINK_CB(skb).portid;
+			audit_sock = NETLINK_CB(skb).sk;
 		}
 		if (status_get->mask & AUDIT_STATUS_RATE_LIMIT) {
 			err = audit_set_rate_limit(status_get->rate_limit);
@@ -886,24 +894,58 @@ static void audit_receive(struct sk_buff  *skb)
 	mutex_unlock(&audit_cmd_mutex);
 }
 
-/* Initialize audit support at boot time. */
-static int __init audit_init(void)
+static int __net_init audit_net_init(struct net *net)
 {
-	int i;
 	struct netlink_kernel_cfg cfg = {
 		.input	= audit_receive,
 	};
 
+	struct audit_net *aunet = net_generic(net, audit_net_id);
+
+	pr_info("audit: initializing netlink socket in namespace\n");
+
+	aunet->nlsk = netlink_kernel_create(net, NETLINK_AUDIT, &cfg);
+	if (aunet->nlsk == NULL)
+		return -ENOMEM;
+	if (!aunet->nlsk)
+		audit_panic("cannot initialize netlink socket in namespace");
+	else
+		aunet->nlsk->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT;
+	return 0;
+}
+
+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;
+	if (sock == audit_sock) {
+		audit_pid = 0;
+		audit_sock = NULL;
+	}
+
+	rcu_assign_pointer(aunet->nlsk, NULL);
+	synchronize_net();
+	netlink_kernel_release(sock);
+}
+
+static struct pernet_operations __net_initdata audit_net_ops = {
+	.init = audit_net_init,
+	.exit = audit_net_exit,
+	.id = &audit_net_id,
+	.size = sizeof(struct audit_net),
+};
+
+/* Initialize audit support at boot time. */
+static int __init audit_init(void)
+{
+	int i;
+
 	if (audit_initialized == AUDIT_DISABLED)
 		return 0;
 
-	printk(KERN_INFO "audit: initializing netlink socket (%s)\n",
+	pr_info("audit: initializing netlink subsys (%s)\n",
 	       audit_default ? "enabled" : "disabled");
-	audit_sock = netlink_kernel_create(&init_net, NETLINK_AUDIT, &cfg);
-	if (!audit_sock)
-		audit_panic("cannot initialize netlink socket");
-	else
-		audit_sock->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT;
+	register_pernet_subsys(&audit_net_ops);
 
 	skb_queue_head_init(&audit_skb_queue);
 	skb_queue_head_init(&audit_skb_hold_queue);
diff --git a/kernel/audit.h b/kernel/audit.h
index 123c9b7..b7cc537 100644
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -249,6 +249,10 @@ struct audit_netlink_list {
 
 int audit_send_list(void *);
 
+struct audit_net {
+	struct sock *nlsk;
+};
+
 extern int selinux_audit_rule_update(void);
 
 extern struct mutex audit_filter_mutex;
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH] audit: listen in all network namespaces
       [not found] <1374006760-7687-1-git-send-email-rgb@redhat.com>
@ 2013-12-19  3:59 ` Gao feng
  2013-12-19 18:40   ` Eric Paris
  0 siblings, 1 reply; 7+ messages in thread
From: Gao feng @ 2013-12-19  3:59 UTC (permalink / raw)
  To: Richard Guy Briggs
  Cc: linux-audit, Eric Paris, Steve Grubb, Serge E. Hallyn,
	Eric W. Biederman, linux-kernel@vger.kernel.org, Linux Containers

On 07/17/2013 04:32 AM, Richard Guy Briggs wrote:
> Convert audit from only listening in init_net to use register_pernet_subsys()
> to dynamically manage the netlink socket list.
> 
> Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> ---

I think it's the time for us to discuss if we should revert this
commit, since this one prevent me from continuing to achieve
audit namespace.


The major problem is in kaudit_send_skb, we have no idea which
audit sock the skb should send to.

in this patch, there only is one auditd proecess, so the
audit_sock is the only one. but when we have audit namespace.
there will be multi audit socks. we have to store audit_sock
into auditns(auditns will be passed to kauditd_send_skb),
this will cause auditns have to get a reference of netns.
and for some reason(netfilter audit target), netns will
get reference of auditns too. this is terrible...

So why not we revert this one, and use a very simple one to
replace it? the below patch will save us from the refer to
each other case, achieve the same effect.

what's your opinion?


Add a compare function which always return true for
audit netlink socket, this will cause audit netlink
sockets netns unaware, and no matter which netns the
user space audit netlink sockets belong to, they all
can find out and communicate with audit_sock.

This gets rid of the necessary to create per-netns
audit kernel side socket(audit_sock), it's pain to
depend on and get reference of netns for auditns.

Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com>
---
 kernel/audit.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/kernel/audit.c b/kernel/audit.c
index 7b0e23a..468950b 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -886,12 +886,18 @@ static void audit_receive(struct sk_buff  *skb)
 	mutex_unlock(&audit_cmd_mutex);
 }

+static bool audit_compare(struct net *net, struct sock *sk)
+{
+	return true;
+}
+
 /* Initialize audit support at boot time. */
 static int __init audit_init(void)
 {
 	int i;
 	struct netlink_kernel_cfg cfg = {
 		.input	= audit_receive,
+		.compare = audit_compare,
 	};

 	if (audit_initialized == AUDIT_DISABLED)

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH] audit: listen in all network namespaces
  2013-12-19  3:59 ` [PATCH] audit: listen in all network namespaces Gao feng
@ 2013-12-19 18:40   ` Eric Paris
  2013-12-20  1:35     ` Gao feng
  2013-12-20  2:46     ` Gao feng
  0 siblings, 2 replies; 7+ messages in thread
From: Eric Paris @ 2013-12-19 18:40 UTC (permalink / raw)
  To: Gao feng
  Cc: Richard Guy Briggs, linux-audit, Steve Grubb, Serge E. Hallyn,
	Eric W. Biederman, linux-kernel@vger.kernel.org, Linux Containers

On Thu, 2013-12-19 at 11:59 +0800, Gao feng wrote:
> On 07/17/2013 04:32 AM, Richard Guy Briggs wrote:
> > Convert audit from only listening in init_net to use register_pernet_subsys()
> > to dynamically manage the netlink socket list.
> > 
> > Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> > ---
> 
> I think it's the time for us to discuss if we should revert this
> commit, since this one prevent me from continuing to achieve
> audit namespace.
> 
> 
> The major problem is in kaudit_send_skb, we have no idea which
> audit sock the skb should send to.

right, we have problems here no matter what...

If we stick with the current approach you will need to know socket +
portid.  With your approach one only needs to know portid.  Since these
are can both be part of the audit_ns structure I don't see a huge
difference...

> we have to store audit_sock
> into auditns(auditns will be passed to kauditd_send_skb),
> this will cause auditns have to get a reference of netns.
> and for some reason(netfilter audit target), netns will
> get reference of auditns too. this is terrible...

I'm not sure I agree/understand this entirely...

> So why not we revert this one, and use a very simple one to
> replace it? the below patch will save us from the refer to
> each other case, achieve the same effect.
> 
> what's your opinion?

Help me go all the way back to the beginning.  What's our end goal here
again?

When thinking about this I realized we have another problem that I don't
think we've considered.  Which makes me lean away from the single
socket/kauditd  :(

I we have one socket and one kauditd ANY auditd can completely freeze
the audit system.  Which seems problematic, especially if there isn't
equal levels of trust between the different namespaces...  If one auditd
gets hung (intentionally or not) the kernel will never send another
audit message....

Makes me think we really need a kauditd thread per namespace, possibly
an skb queue per namespace.  At which point an audit socket per
namespace makes a lot of sense too....


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] audit: listen in all network namespaces
  2013-12-19 18:40   ` Eric Paris
@ 2013-12-20  1:35     ` Gao feng
  2013-12-20  2:46     ` Gao feng
  1 sibling, 0 replies; 7+ messages in thread
From: Gao feng @ 2013-12-20  1:35 UTC (permalink / raw)
  To: Eric Paris
  Cc: Richard Guy Briggs, linux-audit, Steve Grubb, Serge E. Hallyn,
	Eric W. Biederman, linux-kernel@vger.kernel.org, Linux Containers

On 12/20/2013 02:40 AM, Eric Paris wrote:
> On Thu, 2013-12-19 at 11:59 +0800, Gao feng wrote:
>> On 07/17/2013 04:32 AM, Richard Guy Briggs wrote:
>>> Convert audit from only listening in init_net to use register_pernet_subsys()
>>> to dynamically manage the netlink socket list.
>>>
>>> Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
>>> ---
>>
>> I think it's the time for us to discuss if we should revert this
>> commit, since this one prevent me from continuing to achieve
>> audit namespace.
>>
>>
>> The major problem is in kaudit_send_skb, we have no idea which
>> audit sock the skb should send to.
> 
> right, we have problems here no matter what...
> 
> If we stick with the current approach you will need to know socket +
> portid.  With your approach one only needs to know portid.  Since these
> are can both be part of the audit_ns structure I don't see a huge
> difference...
> 
>> we have to store audit_sock
>> into auditns(auditns will be passed to kauditd_send_skb),
>> this will cause auditns have to get a reference of netns.
>> and for some reason(netfilter audit target), netns will
>> get reference of auditns too. this is terrible...
> 
> I'm not sure I agree/understand this entirely...
> 

My brain must be destroyed, I need to think about if auditns
should get reference of netns. it's not clear to me now. :(
but I intend to think you are right.

>> So why not we revert this one, and use a very simple one to
>> replace it? the below patch will save us from the refer to
>> each other case, achieve the same effect.
>>
>> what's your opinion?
> 
> Help me go all the way back to the beginning.  What's our end goal here
> again?
> 
> When thinking about this I realized we have another problem that I don't
> think we've considered.  Which makes me lean away from the single
> socket/kauditd  :(
> 
> I we have one socket and one kauditd ANY auditd can completely freeze
> the audit system.  Which seems problematic, especially if there isn't
> equal levels of trust between the different namespaces...  If one auditd
> gets hung (intentionally or not) the kernel will never send another
> audit message....
> 
> Makes me think we really need a kauditd thread per namespace, possibly
> an skb queue per namespace.  At which point an audit socket per
> namespace makes a lot of sense too....
> 

You are right, and My prototype supports per kauditd/auditd/sbk queue per
audit namespace. one auditd freeze in one auditns will not affect audit
subsystem in another auditns.

Thanks!

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] audit: listen in all network namespaces
  2013-12-19 18:40   ` Eric Paris
  2013-12-20  1:35     ` Gao feng
@ 2013-12-20  2:46     ` Gao feng
  2013-12-20  3:11       ` Eric Paris
  1 sibling, 1 reply; 7+ messages in thread
From: Gao feng @ 2013-12-20  2:46 UTC (permalink / raw)
  To: Eric Paris
  Cc: Richard Guy Briggs, linux-audit, Steve Grubb, Serge E. Hallyn,
	Eric W. Biederman, linux-kernel@vger.kernel.org, Linux Containers

On 12/20/2013 02:40 AM, Eric Paris wrote:
> On Thu, 2013-12-19 at 11:59 +0800, Gao feng wrote:
>> On 07/17/2013 04:32 AM, Richard Guy Briggs wrote:
>>> Convert audit from only listening in init_net to use register_pernet_subsys()
>>> to dynamically manage the netlink socket list.
>>>
>>> Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
>>> ---
>>
>> I think it's the time for us to discuss if we should revert this
>> commit, since this one prevent me from continuing to achieve
>> audit namespace.
>>
>>
>> The major problem is in kaudit_send_skb, we have no idea which
>> audit sock the skb should send to.
> 
> right, we have problems here no matter what...
> 
> If we stick with the current approach you will need to know socket +
> portid.  With your approach one only needs to know portid.  Since these
> are can both be part of the audit_ns structure I don't see a huge
> difference...
> 
>> we have to store audit_sock
>> into auditns(auditns will be passed to kauditd_send_skb),
>> this will cause auditns have to get a reference of netns.
>> and for some reason(netfilter audit target), netns will
>> get reference of auditns too. this is terrible...
> 
> I'm not sure I agree/understand this entirely...
> 

Yes, the audit_sock is created and destroyed by net namespace,
so if auditns wants to use audit_sock, it must prevent netns
from being destroyed. so auditns has to get reference of netns.

and in some case, netns will get reference of auditns too. this
is complex than making audit_sock global and getting rid of this
reference.


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] audit: listen in all network namespaces
  2013-12-20  2:46     ` Gao feng
@ 2013-12-20  3:11       ` Eric Paris
  2013-12-20  3:45         ` Gao feng
  0 siblings, 1 reply; 7+ messages in thread
From: Eric Paris @ 2013-12-20  3:11 UTC (permalink / raw)
  To: Gao feng
  Cc: Richard Guy Briggs, linux-audit, Steve Grubb, Serge E. Hallyn,
	Eric W. Biederman, linux-kernel@vger.kernel.org, Linux Containers

On Fri, 2013-12-20 at 10:46 +0800, Gao feng wrote:
> On 12/20/2013 02:40 AM, Eric Paris wrote:
> > On Thu, 2013-12-19 at 11:59 +0800, Gao feng wrote:
> >> On 07/17/2013 04:32 AM, Richard Guy Briggs wrote:

> >> we have to store audit_sock
> >> into auditns(auditns will be passed to kauditd_send_skb),
> >> this will cause auditns have to get a reference of netns.
> >> and for some reason(netfilter audit target), netns will
> >> get reference of auditns too. this is terrible...
> > 
> > I'm not sure I agree/understand this entirely...
> > 
> 
> Yes, the audit_sock is created and destroyed by net namespace,
> so if auditns wants to use audit_sock, it must prevent netns
> from being destroyed. so auditns has to get reference of netns.

Namespace == mind blown.  Ok, so:

 auditd in audit_ns2 and net_ns2. <--- ONLY process in net_ns2
 some process in audit_ns2 and net_ns3

Lets assume that auditd is killed improperly/dies.  Because the last
process in net_ns2 is gone net_ns2 is invalid/freed.

Today in the kernel the way we detect auditd is gone is by using the
socket and getting ECONNREFUSSED.  So here you think that audit_ns2
should hold a reference on net_ns2, to make sure that socket is always
valid.

I instead propose that we could run all audit_ns and reset the audit_pid
in that namespace and the audit_sock in the namespace to 0/null inside
audit_net_exit.  Since obviously if the net_ns disappeared, the auditd
which was running in any audit namespace in that net_ns isn't running
any more.  We didn't need to hold a reference on the net_ns.  We just
have to clear the skb_queue, reset the audit_pid to 0, and reset the
socket to NULL...

Maybe the one magic socket is the right answer.  I'm not arguing against
your solution.  I'm really trying to understand why we are going that
way...

> and in some case, netns will get reference of auditns too. this
> is complex than making audit_sock global and getting rid of this
> reference.

This I haven't even started to try to wrap my head around...


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] audit: listen in all network namespaces
  2013-12-20  3:11       ` Eric Paris
@ 2013-12-20  3:45         ` Gao feng
  0 siblings, 0 replies; 7+ messages in thread
From: Gao feng @ 2013-12-20  3:45 UTC (permalink / raw)
  To: Eric Paris
  Cc: Richard Guy Briggs, linux-audit, Steve Grubb, Serge E. Hallyn,
	Eric W. Biederman, linux-kernel@vger.kernel.org, Linux Containers

On 12/20/2013 11:11 AM, Eric Paris wrote:
> On Fri, 2013-12-20 at 10:46 +0800, Gao feng wrote:
>> On 12/20/2013 02:40 AM, Eric Paris wrote:
>>> On Thu, 2013-12-19 at 11:59 +0800, Gao feng wrote:
>>>> On 07/17/2013 04:32 AM, Richard Guy Briggs wrote:
> 
>>>> we have to store audit_sock
>>>> into auditns(auditns will be passed to kauditd_send_skb),
>>>> this will cause auditns have to get a reference of netns.
>>>> and for some reason(netfilter audit target), netns will
>>>> get reference of auditns too. this is terrible...
>>>
>>> I'm not sure I agree/understand this entirely...
>>>
>>
>> Yes, the audit_sock is created and destroyed by net namespace,
>> so if auditns wants to use audit_sock, it must prevent netns
>> from being destroyed. so auditns has to get reference of netns.
> 
> Namespace == mind blown.  Ok, so:
> 
>  auditd in audit_ns2 and net_ns2. <--- ONLY process in net_ns2
>  some process in audit_ns2 and net_ns3
> 
> Lets assume that auditd is killed improperly/dies.  Because the last
> process in net_ns2 is gone net_ns2 is invalid/freed.
> 
> Today in the kernel the way we detect auditd is gone is by using the
> socket and getting ECONNREFUSSED.  So here you think that audit_ns2
> should hold a reference on net_ns2, to make sure that socket is always
> valid.
> 
> I instead propose that we could run all audit_ns and reset the audit_pid
> in that namespace and the audit_sock in the namespace to 0/null inside
> audit_net_exit.  Since obviously if the net_ns disappeared, the auditd
> which was running in any audit namespace in that net_ns isn't running
> any more.  We didn't need to hold a reference on the net_ns.  We just
> have to clear the skb_queue, reset the audit_pid to 0, and reset the
> socket to NULL...

multi auditns can share the same netns. it happens if you unshare
auditns. if you want to reset audit_sock to null inside audit_net_exit,
you have to maintain a list in netns, this list contains the auditnss
whose audit_sock is created in this netns. so you can foreach this
list and reset the audit socks of audit nss.

Above is unsharing auditns, consider unsharing netns. auditd is running
in auditns1 and netns1, and then who-know-why the auditd call unshare(CLONE_NEWNET)
to change it's netns from netns1 to new netns2. so the netns1 is released
and auditns->audit_sock being reset to NULL. the auditd cannot receive
the audit log. auditd will in chaos, "I'm still alive, why kernel think
I'm die?"

So maybe you will say, we can reset the audit_sock of netns2 to auditns.
ok, this is a way. but how can we decide if we should reset the auditns->audit_sock?
when we create the new netns, the old netns is still alive, so the auditns->audit_sock
is still valid in that time.

I don't know if there are some other problems we should consider.
it is too complex..

> 
> Maybe the one magic socket is the right answer.  I'm not arguing against
> your solution.  I'm really trying to understand why we are going that
> way...
> 

That's why we should discuss :)


^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2013-12-20  3:45 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <1374006760-7687-1-git-send-email-rgb@redhat.com>
2013-12-19  3:59 ` [PATCH] audit: listen in all network namespaces Gao feng
2013-12-19 18:40   ` Eric Paris
2013-12-20  1:35     ` Gao feng
2013-12-20  2:46     ` Gao feng
2013-12-20  3:11       ` Eric Paris
2013-12-20  3:45         ` Gao feng
2013-07-16 20:15 Richard Guy Briggs

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox