Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1540235 > unrolled thread
| Started by | Richard Guy Briggs <rgb@redhat.com> |
|---|---|
| First post | 2016-12-12 11:10 +0100 |
| Last post | 2016-12-14 07:40 +0100 |
| Articles | 10 — 3 participants |
Back to article view | Back to linux.kernel
This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by
below is the oldest one visible, not the original post.
Re: netlink: GPF in sock_sndtimeo Richard Guy Briggs <rgb@redhat.com> - 2016-12-12 11:10 +0100
Re: netlink: GPF in sock_sndtimeo Cong Wang <xiyou.wangcong@gmail.com> - 2016-12-13 01:20 +0100
Re: netlink: GPF in sock_sndtimeo Richard Guy Briggs <rgb@redhat.com> - 2016-12-13 12:00 +0100
Re: netlink: GPF in sock_sndtimeo Cong Wang <xiyou.wangcong@gmail.com> - 2016-12-14 01:40 +0100
Re: netlink: GPF in sock_sndtimeo Richard Guy Briggs <rgb@redhat.com> - 2016-12-14 05:20 +0100
[RFC PATCH v3] audit: use proper refcount locking on audit_sock Richard Guy Briggs <rgb@redhat.com> - 2016-12-13 16:10 +0100
Re: [RFC PATCH v3] audit: use proper refcount locking on audit_sock Paul Moore <paul@paul-moore.com> - 2016-12-13 22:00 +0100
Re: [RFC PATCH v3] audit: use proper refcount locking on audit_sock Cong Wang <xiyou.wangcong@gmail.com> - 2016-12-14 01:20 +0100
Re: [RFC PATCH v3] audit: use proper refcount locking on audit_sock Richard Guy Briggs <rgb@redhat.com> - 2016-12-14 05:10 +0100
Re: [RFC PATCH v3] audit: use proper refcount locking on audit_sock Cong Wang <xiyou.wangcong@gmail.com> - 2016-12-14 07:40 +0100
| From | Richard Guy Briggs <rgb@redhat.com> |
|---|---|
| Date | 2016-12-12 11:10 +0100 |
| Subject | Re: netlink: GPF in sock_sndtimeo |
| Message-ID | <sNvIu-30q-41@gated-at.bofh.it> |
On 2016-12-09 20:13, Cong Wang wrote: > On Fri, Dec 9, 2016 at 3:01 AM, Richard Guy Briggs <rgb@redhat.com> wrote: > > On 2016-12-08 22:57, Cong Wang wrote: > >> On Thu, Dec 8, 2016 at 10:02 PM, Richard Guy Briggs <rgb@redhat.com> 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 <rgb@redhat.com> Kernel Security Engineering, Base Operating Systems, Red Hat Remote, Ottawa, Canada Voice: +1.647.777.2635, Internal: (81) 32635
[toc] | [next] | [standalone]
| From | Cong Wang <xiyou.wangcong@gmail.com> |
|---|---|
| Date | 2016-12-13 01:20 +0100 |
| Message-ID | <sNIZ3-2Az-9@gated-at.bofh.it> |
| In reply to | #1540235 |
On Mon, Dec 12, 2016 at 2:02 AM, Richard Guy Briggs <rgb@redhat.com> wrote: > On 2016-12-09 20:13, Cong Wang wrote: >> 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? It is already non-atomic now: https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=efa172f42836477bf1ac3c9a3053140df764699c > 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. > I don't see why we need to check it in net exit if we use refcnt, because we have two different users of audit_sock: kauditd and netns, if both take care of refcnt properly, we don't need to worry about who is the last, no matter what failures occur in what order.
[toc] | [prev] | [next] | [standalone]
| From | Richard Guy Briggs <rgb@redhat.com> |
|---|---|
| Date | 2016-12-13 12:00 +0100 |
| Message-ID | <sNSYq-aO-21@gated-at.bofh.it> |
| In reply to | #1540755 |
On 2016-12-12 16:10, Cong Wang wrote: > On Mon, Dec 12, 2016 at 2:02 AM, Richard Guy Briggs <rgb@redhat.com> wrote: > > On 2016-12-09 20:13, Cong Wang wrote: > >> 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? > > It is already non-atomic now: > https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=efa172f42836477bf1ac3c9a3053140df764699c Ok, that is recent... It is still less attractive as you point out due to the overhead, but still worth considering if we can't find another way. > > 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. > > I don't see why we need to check it in net exit if we use refcnt, > because we have two different users of audit_sock: kauditd and > netns, if both take care of refcnt properly, we don't need to worry > about who is the last, no matter what failures occur in what order. It is actually the audit_pid and audit_nlk_portid that I care about more. The audit daemon could vanish or close the socket while the kernel sock to which it was attached is still quite valid. Accessing the set of three atomically is the urge. I wonder if it makes more sense to test for the presence of auditd using audit_sock rather than audit_pid, but still keep audit_pid for our reporting and replacement strategy. Another idea would be to put the three in one struct. Can someone explain how they think the original test was able to trigger this GPF? Network namespace shutdown while something pretended to set up a new auditd? That's impressive for a fuzzer if that's the case... Is there an strace? I guess it is all in test(). - RGB -- Richard Guy Briggs <rgb@redhat.com> Kernel Security Engineering, Base Operating Systems, Red Hat Remote, Ottawa, Canada Voice: +1.647.777.2635, Internal: (81) 32635
[toc] | [prev] | [next] | [standalone]
| From | Cong Wang <xiyou.wangcong@gmail.com> |
|---|---|
| Date | 2016-12-14 01:40 +0100 |
| Message-ID | <sO5LX-81n-15@gated-at.bofh.it> |
| In reply to | #1540983 |
On Tue, Dec 13, 2016 at 2:52 AM, Richard Guy Briggs <rgb@redhat.com> wrote: > It is actually the audit_pid and audit_nlk_portid that I care about > more. The audit daemon could vanish or close the socket while the > kernel sock to which it was attached is still quite valid. Accessing > the set of three atomically is the urge. I wonder if it makes more > sense to test for the presence of auditd using audit_sock rather than > audit_pid, but still keep audit_pid for our reporting and replacement > strategy. Another idea would be to put the three in one struct. Note, the process has audit_pid should hold a refcnt to the netns too, so the netns can't be gone until that process is gone. > > Can someone explain how they think the original test was able to trigger > this GPF? Network namespace shutdown while something pretended to set > up a new auditd? That's impressive for a fuzzer if that's the case... > Is there an strace? I guess it is all in test(). > I am surprised you still don't get the race condition even when you are now working on v2... The race happens in this scenarios : 1) Create a new netns 2) In the new netns, communicate with kauditd to set audit_sock 3) Generate some audit messages, so kauditd will keep sending them via audit_sock 4) exit the netns 5) the previous audit_sock is now going away, but kaudit_sock could still access it in this small window.
[toc] | [prev] | [next] | [standalone]
| From | Richard Guy Briggs <rgb@redhat.com> |
|---|---|
| Date | 2016-12-14 05:20 +0100 |
| Message-ID | <sO9cR-1Lv-7@gated-at.bofh.it> |
| In reply to | #1541616 |
On 2016-12-13 16:17, Cong Wang wrote:
> On Tue, Dec 13, 2016 at 2:52 AM, Richard Guy Briggs <rgb@redhat.com> wrote:
> > It is actually the audit_pid and audit_nlk_portid that I care about
> > more. The audit daemon could vanish or close the socket while the
> > kernel sock to which it was attached is still quite valid. Accessing
> > the set of three atomically is the urge. I wonder if it makes more
> > sense to test for the presence of auditd using audit_sock rather than
> > audit_pid, but still keep audit_pid for our reporting and replacement
> > strategy. Another idea would be to put the three in one struct.
>
> Note, the process has audit_pid should hold a refcnt to the netns too,
> so the netns can't be gone until that process is gone.
I noted that. I did wonder if there might be a problem if all the
processes were moved to another netns with the struct sock stuck in the
now process-void netns.
This is alluded-to in 6f285b19d09f ("audit: Send replies in the proper
network namespace.").
> > Can someone explain how they think the original test was able to trigger
> > this GPF? Network namespace shutdown while something pretended to set
> > up a new auditd? That's impressive for a fuzzer if that's the case...
> > Is there an strace? I guess it is all in test().
>
> I am surprised you still don't get the race condition even when you
> are now working on v2...
>
> The race happens in this scenarios :
>
> 1) Create a new netns
>
> 2) In the new netns, communicate with kauditd to set audit_sock
>
> 3) Generate some audit messages, so kauditd will keep sending them
> via audit_sock
>
> 4) exit the netns
>
> 5) the previous audit_sock is now going away, but kaudit_sock could still
> access it in this small window.
Ah ok that fits...
- RGB
--
Richard Guy Briggs <rgb@redhat.com>
Kernel Security Engineering, Base Operating Systems, Red Hat
Remote, Ottawa, Canada
Voice: +1.647.777.2635, Internal: (81) 32635
[toc] | [prev] | [next] | [standalone]
| From | Richard Guy Briggs <rgb@redhat.com> |
|---|---|
| Date | 2016-12-13 16:10 +0100 |
| Subject | [RFC PATCH v3] audit: use proper refcount locking on audit_sock |
| Message-ID | <sNWSm-2IE-49@gated-at.bofh.it> |
| In reply to | #1540235 |
Resetting audit_sock appears to be racy.
audit_sock was being copied and dereferenced without using a refcount on
the source sock.
Bump the refcount on the underlying sock when we store a refrence in
audit_sock and release it when we reset audit_sock. audit_sock
modification needs the audit_cmd_mutex.
See: https://lkml.org/lkml/2016/11/26/232
Thanks to Eric Dumazet <edumazet@google.com> and Cong Wang
<xiyou.wangcong@gmail.com> on ideas how to fix it.
Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
---
There has been a lot of change in the audit code that is about to go
upstream to address audit queue issues. This patch is based on the
source tree: git://git.infradead.org/users/pcmoore/audit#next
---
kernel/audit.c | 28 +++++++++++++++++++++++-----
1 files changed, 23 insertions(+), 5 deletions(-)
diff --git a/kernel/audit.c b/kernel/audit.c
index f20eee0..3bb4126 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -446,14 +446,19 @@ static void kauditd_retry_skb(struct sk_buff *skb)
* Description:
* Break the auditd/kauditd connection and move all the records in the retry
* queue into the hold queue in case auditd reconnects.
+ * The audit_cmd_mutex must be held when calling this function.
*/
static void auditd_reset(void)
{
struct sk_buff *skb;
/* break the connection */
+ if (audit_sock) {
+ sock_put(audit_sock);
+ audit_sock = NULL;
+ }
audit_pid = 0;
- audit_sock = NULL;
+ audit_nlk_portid = 0;
/* flush all of the retry queue to the hold queue */
while ((skb = skb_dequeue(&audit_retry_queue)))
@@ -579,7 +584,9 @@ static int kauditd_thread(void *dummy)
auditd = 0;
if (AUDITD_BAD(rc, reschedule)) {
+ mutex_lock(&audit_cmd_mutex);
auditd_reset();
+ mutex_unlock(&audit_cmd_mutex);
reschedule = 0;
}
} else
@@ -594,7 +601,9 @@ static int kauditd_thread(void *dummy)
auditd = 0;
if (AUDITD_BAD(rc, reschedule)) {
kauditd_hold_skb(skb);
+ mutex_lock(&audit_cmd_mutex);
auditd_reset();
+ mutex_unlock(&audit_cmd_mutex);
reschedule = 0;
} else
/* temporary problem (we hope), queue
@@ -623,7 +632,9 @@ quick_loop:
if (rc) {
auditd = 0;
if (AUDITD_BAD(rc, reschedule)) {
+ mutex_lock(&audit_cmd_mutex);
auditd_reset();
+ mutex_unlock(&audit_cmd_mutex);
reschedule = 0;
}
@@ -1010,11 +1021,16 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
}
if (audit_enabled != AUDIT_OFF)
audit_log_config_change("audit_pid", new_pid, audit_pid, 1);
- audit_pid = new_pid;
- audit_nlk_portid = NETLINK_CB(skb).portid;
- audit_sock = skb->sk;
- if (!new_pid)
+ if (new_pid) {
+ if (audit_sock)
+ sock_put(audit_sock);
+ audit_pid = new_pid;
+ audit_nlk_portid = NETLINK_CB(skb).portid;
+ sock_hold(skb->sk);
+ audit_sock = skb->sk;
+ } else {
auditd_reset();
+ }
wake_up_interruptible(&kauditd_wait);
}
if (s.mask & AUDIT_STATUS_RATE_LIMIT) {
@@ -1283,8 +1299,10 @@ 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)
auditd_reset();
+ mutex_unlock(&audit_cmd_mutex);
RCU_INIT_POINTER(aunet->nlsk, NULL);
synchronize_net();
--
1.7.1
[toc] | [prev] | [next] | [standalone]
| From | Paul Moore <paul@paul-moore.com> |
|---|---|
| Date | 2016-12-13 22:00 +0100 |
| Subject | Re: [RFC PATCH v3] audit: use proper refcount locking on audit_sock |
| Message-ID | <sO2l4-5Po-31@gated-at.bofh.it> |
| In reply to | #1541158 |
On Tue, Dec 13, 2016 at 10:03 AM, Richard Guy Briggs <rgb@redhat.com> wrote: > Resetting audit_sock appears to be racy. > > audit_sock was being copied and dereferenced without using a refcount on > the source sock. > > Bump the refcount on the underlying sock when we store a refrence in > audit_sock and release it when we reset audit_sock. audit_sock > modification needs the audit_cmd_mutex. > > See: https://lkml.org/lkml/2016/11/26/232 > > Thanks to Eric Dumazet <edumazet@google.com> and Cong Wang > <xiyou.wangcong@gmail.com> on ideas how to fix it. > > Signed-off-by: Richard Guy Briggs <rgb@redhat.com> > --- > There has been a lot of change in the audit code that is about to go > upstream to address audit queue issues. This patch is based on the > source tree: git://git.infradead.org/users/pcmoore/audit#next > --- > kernel/audit.c | 28 +++++++++++++++++++++++----- > 1 files changed, 23 insertions(+), 5 deletions(-) This looks more reasonable. I still wonder about synchronization between threads changing the audit_* connection variables and the kauditd_thread, but I guess we can treat that as another issue; this patch fixes a bug and is worth merging now. I'm building a test kernel right now, assuming nothing blows up I'll push this patch with the rest of the audit patches tomorrow; if something bad happens, this is going to miss the first audit pull request. > diff --git a/kernel/audit.c b/kernel/audit.c > index f20eee0..3bb4126 100644 > --- a/kernel/audit.c > +++ b/kernel/audit.c > @@ -446,14 +446,19 @@ static void kauditd_retry_skb(struct sk_buff *skb) > * Description: > * Break the auditd/kauditd connection and move all the records in the retry > * queue into the hold queue in case auditd reconnects. > + * The audit_cmd_mutex must be held when calling this function. > */ Don't resend, but in the future please start comments like this on the previous line.
[toc] | [prev] | [next] | [standalone]
| From | Cong Wang <xiyou.wangcong@gmail.com> |
|---|---|
| Date | 2016-12-14 01:20 +0100 |
| Subject | Re: [RFC PATCH v3] audit: use proper refcount locking on audit_sock |
| Message-ID | <sO5sC-7Vh-45@gated-at.bofh.it> |
| In reply to | #1541158 |
On Tue, Dec 13, 2016 at 7:03 AM, Richard Guy Briggs <rgb@redhat.com> wrote:
> @@ -1283,8 +1299,10 @@ 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)
> auditd_reset();
> + mutex_unlock(&audit_cmd_mutex);
This still doesn't look correct to me, b/c here we release the audit_sock
refcnt twice:
1) inside audit_reset()
2) netlink_kernel_release()
[toc] | [prev] | [next] | [standalone]
| From | Richard Guy Briggs <rgb@redhat.com> |
|---|---|
| Date | 2016-12-14 05:10 +0100 |
| Subject | Re: [RFC PATCH v3] audit: use proper refcount locking on audit_sock |
| Message-ID | <sO93b-1Im-9@gated-at.bofh.it> |
| In reply to | #1541607 |
On 2016-12-13 16:19, Cong Wang wrote:
> On Tue, Dec 13, 2016 at 7:03 AM, Richard Guy Briggs <rgb@redhat.com> wrote:
> > @@ -1283,8 +1299,10 @@ 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)
> > auditd_reset();
> > + mutex_unlock(&audit_cmd_mutex);
>
> This still doesn't look correct to me, b/c here we release the audit_sock
> refcnt twice:
>
> 1) inside audit_reset()
The audit_reset() refcount decrement corresponds to a setting of
audit_sock only if audit_sock is still non-NULL.
> 2) netlink_kernel_release()
This refcount decrement corresponds to netlink_kernel_create().
- RGB
--
Richard Guy Briggs <rgb@redhat.com>
Kernel Security Engineering, Base Operating Systems, Red Hat
Remote, Ottawa, Canada
Voice: +1.647.777.2635, Internal: (81) 32635
[toc] | [prev] | [next] | [standalone]
| From | Cong Wang <xiyou.wangcong@gmail.com> |
|---|---|
| Date | 2016-12-14 07:40 +0100 |
| Subject | Re: [RFC PATCH v3] audit: use proper refcount locking on audit_sock |
| Message-ID | <sObol-35x-3@gated-at.bofh.it> |
| In reply to | #1541687 |
On Tue, Dec 13, 2016 at 8:00 PM, Richard Guy Briggs <rgb@redhat.com> wrote:
> On 2016-12-13 16:19, Cong Wang wrote:
>> On Tue, Dec 13, 2016 at 7:03 AM, Richard Guy Briggs <rgb@redhat.com> wrote:
>> > @@ -1283,8 +1299,10 @@ 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)
>> > auditd_reset();
>> > + mutex_unlock(&audit_cmd_mutex);
>>
>> This still doesn't look correct to me, b/c here we release the audit_sock
>> refcnt twice:
>>
>> 1) inside audit_reset()
>
> The audit_reset() refcount decrement corresponds to a setting of
> audit_sock only if audit_sock is still non-NULL.
>
Hmm, thinking about it again, looks like the sock == audit_sock
and audit_sock != NULL checks can guarantee we are safe. So,
Reviewed-by: Cong Wang <xiyou.wangcong@gmail.com>
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web