Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1232368 > unrolled thread
| Started by | David Miller <davem@davemloft.net> |
|---|---|
| First post | 2015-09-24 21:20 +0200 |
| Last post | 2015-09-26 21:50 +0200 |
| Articles | 17 — 4 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: [PATCH v2] netlink: Replace rhash_portid with bound David Miller <davem@davemloft.net> - 2015-09-24 21:20 +0200
Re: [PATCH v2] netlink: Replace rhash_portid with bound Tejun Heo <tj@kernel.org> - 2015-09-24 22:10 +0200
netlink: Add barrier to netlink_connect for theoretical case Herbert Xu <herbert@gondor.apana.org.au> - 2015-09-25 03:50 +0200
Re: netlink: Add barrier to netlink_connect for theoretical case Linus Torvalds <torvalds@linux-foundation.org> - 2015-09-25 05:30 +0200
Re: netlink: Add barrier to netlink_connect for theoretical case Herbert Xu <herbert@gondor.apana.org.au> - 2015-09-25 05:50 +0200
Re: netlink: Add barrier to netlink_connect for theoretical case Tejun Heo <tj@kernel.org> - 2015-09-25 17:10 +0200
Re: netlink: Add barrier to netlink_connect for theoretical case Tejun Heo <tj@kernel.org> - 2015-09-25 17:10 +0200
netlink: Add netlink_bound helper and use it in netlink_getname Herbert Xu <herbert@gondor.apana.org.au> - 2015-09-26 15:20 +0200
Re: netlink: Add netlink_bound helper and use it in netlink_getname Tejun Heo <tj@kernel.org> - 2015-09-26 20:10 +0200
Re: netlink: Add netlink_bound helper and use it in netlink_getname Herbert Xu <herbert@gondor.apana.org.au> - 2015-09-26 21:50 +0200
Re: netlink: Add netlink_bound helper and use it in netlink_getname Herbert Xu <herbert@gondor.apana.org.au> - 2015-09-26 22:00 +0200
Re: netlink: Add netlink_bound helper and use it in netlink_getname Tejun Heo <tj@kernel.org> - 2015-09-26 22:10 +0200
Re: netlink: Add netlink_bound helper and use it in netlink_getname Herbert Xu <herbert@gondor.apana.org.au> - 2015-09-26 22:20 +0200
Re: netlink: Add netlink_bound helper and use it in netlink_getname Tejun Heo <tj@kernel.org> - 2015-09-26 22:20 +0200
Re: netlink: Add netlink_bound helper and use it in netlink_getname Tejun Heo <tj@kernel.org> - 2015-09-26 22:00 +0200
Re: netlink: Add netlink_bound helper and use it in netlink_getname Herbert Xu <herbert@gondor.apana.org.au> - 2015-09-26 21:50 +0200
Re: netlink: Add netlink_bound helper and use it in netlink_getname Tejun Heo <tj@kernel.org> - 2015-09-26 21:50 +0200
| From | David Miller <davem@davemloft.net> |
|---|---|
| Date | 2015-09-24 21:20 +0200 |
| Subject | Re: [PATCH v2] netlink: Replace rhash_portid with bound |
| Message-ID | <qckdJ-3Kz-35@gated-at.bofh.it> |
From: Herbert Xu <herbert@gondor.apana.org.au>
Date: Tue, 22 Sep 2015 11:38:56 +0800
> The commit 1f770c0a09da855a2b51af6d19de97fb955eca85 ("netlink:
> Fix autobind race condition that leads to zero port ID") created
> some new races that can occur due to inconcsistencies between the
> two port IDs.
>
> Tejun is right that a barrier is unavoidable. Therefore I am
> reverting to the original patch that used a boolean to indicate
> that a user netlink socket has been bound.
>
> Barriers have been added where necessary to ensure that a valid
> portid and the hashed socket is visible.
>
> I have also changed netlink_insert to only return EBUSY if the
> socket is bound to a portid different to the requested one. This
> combined with only reading nlk->bound once in netlink_bind fixes
> a race where two threads that bind the socket at the same time
> with different port IDs may both succeed.
>
> Fixes: 1f770c0a09da ("netlink: Fix autobind race condition that leads to zero port ID")
> Reported-by: Tejun Heo <tj@kernel.org>
> Reported-by: Linus Torvalds <torvalds@linux-foundation.org>
> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
I've decided to apply this and queue it up for -stable.
Thanks everyone.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [next] | [standalone]
| From | Tejun Heo <tj@kernel.org> |
|---|---|
| Date | 2015-09-24 22:10 +0200 |
| Message-ID | <qcl06-4Uy-23@gated-at.bofh.it> |
| In reply to | #1232368 |
Hello, David.
On Thu, Sep 24, 2015 at 12:11:42PM -0700, David Miller wrote:
> From: Herbert Xu <herbert@gondor.apana.org.au>
> Date: Tue, 22 Sep 2015 11:38:56 +0800
>
> > The commit 1f770c0a09da855a2b51af6d19de97fb955eca85 ("netlink:
> > Fix autobind race condition that leads to zero port ID") created
> > some new races that can occur due to inconcsistencies between the
> > two port IDs.
...
> I've decided to apply this and queue it up for -stable.
This is mostly correct; however, if there are or can be in-kernel
users which create the client side of netlink socket, it isn't. Let's
say such in-kernel user does kernel_connect() and then query the
assigned port number by kernel_getsockname(). That can just return
zero. Maybe such scenario is not possible for some combination of
reasons but why leak this level of synchronization detail to the users
in the first place? This should be terminated from the site where
such synchronization scheme is implemented. This expands the scope of
correctness verification to all possible users of these functions.
Thanks.
--
tejun
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Herbert Xu <herbert@gondor.apana.org.au> |
|---|---|
| Date | 2015-09-25 03:50 +0200 |
| Subject | netlink: Add barrier to netlink_connect for theoretical case |
| Message-ID | <qcqj7-3Qz-1@gated-at.bofh.it> |
| In reply to | #1232413 |
On Thu, Sep 24, 2015 at 04:05:10PM -0400, Tejun Heo wrote:
>
> > I've decided to apply this and queue it up for -stable.
Thanks Dave!
> This is mostly correct; however, if there are or can be in-kernel
> users which create the client side of netlink socket, it isn't. Let's
> say such in-kernel user does kernel_connect() and then query the
> assigned port number by kernel_getsockname(). That can just return
> zero. Maybe such scenario is not possible for some combination of
> reasons but why leak this level of synchronization detail to the users
> in the first place? This should be terminated from the site where
> such synchronization scheme is implemented. This expands the scope of
> correctness verification to all possible users of these functions.
Well had you said this in the first place I would've fixed it a
long time ago. There aren't any in-kernel users right now and
even if there were they'd have to do a connect/bind/sendmsg on
the same socket in two threads at the same time. But let's close
this theoretical hole:
---8<---
If a netlink_connect call is followed by a netlink_getname call
the portid returned may not be up-to-date. This patch adds a
barrier for that case.
As all nlk->bound dereferences now have barriers this patch also
adds a netlink_bound helper to encapsulate the barrier, as was
suggested by Tejun.
Fixes: da314c9923fe ("netlink: Replace rhash_portid with bound")
Reported-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 2c15fae..02121e1 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -125,6 +125,15 @@ static inline u32 netlink_group_mask(u32 group)
return group ? 1 << (group - 1) : 0;
}
+static inline bool netlink_bound(struct netlink_sock *nlk)
+{
+ /* Ensure nlk is hashed and visible. */
+ if (nlk->bound)
+ smp_rmb();
+
+ return nlk->bound;
+}
+
int netlink_add_tap(struct netlink_tap *nt)
{
if (unlikely(nt->dev->type != ARPHRD_NETLINK))
@@ -1524,14 +1533,10 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr,
return err;
}
- bound = nlk->bound;
- if (bound) {
- /* Ensure nlk->portid is up-to-date. */
- smp_rmb();
-
+ bound = netlink_bound(nlk);
+ if (bound)
if (nladdr->nl_pid != nlk->portid)
return -EINVAL;
- }
if (nlk->netlink_bind && groups) {
int group;
@@ -1547,9 +1552,6 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr,
}
}
- /* No need for barriers here as we return to user-space without
- * using any of the bound attributes.
- */
if (!bound) {
err = nladdr->nl_pid ?
netlink_insert(sk, nladdr->nl_pid) :
@@ -1598,10 +1600,7 @@ static int netlink_connect(struct socket *sock, struct sockaddr *addr,
!netlink_allowed(sock, NL_CFG_F_NONROOT_SEND))
return -EPERM;
- /* No need for barriers here as we return to user-space without
- * using any of the bound attributes.
- */
- if (!nlk->bound)
+ if (!netlink_bound(nlk))
err = netlink_autobind(sock);
if (err == 0) {
@@ -2442,13 +2441,10 @@ static int netlink_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
dst_group = nlk->dst_group;
}
- if (!nlk->bound) {
+ if (!netlink_bound(nlk)) {
err = netlink_autobind(sock);
if (err)
goto out;
- } else {
- /* Ensure nlk is hashed and visible. */
- smp_rmb();
}
/* It's a really convoluted way for userland to ask for mmaped
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Linus Torvalds <torvalds@linux-foundation.org> |
|---|---|
| Date | 2015-09-25 05:30 +0200 |
| Subject | Re: netlink: Add barrier to netlink_connect for theoretical case |
| Message-ID | <qcrRU-6eR-15@gated-at.bofh.it> |
| In reply to | #1232525 |
On Thu, Sep 24, 2015 at 6:43 PM, Herbert Xu <herbert@gondor.apana.org.au> wrote:
> On Thu, Sep 24, 2015 at 04:05:10PM -0400, Tejun Heo wrote:
>
> +static inline bool netlink_bound(struct netlink_sock *nlk)
> +{
> + /* Ensure nlk is hashed and visible. */
> + if (nlk->bound)
> + smp_rmb();
> +
> + return nlk->bound;
> +}
The above looks very suspicious.
If "nlk->bound" isn't stable, then you might read 0 the first time,
not do the smp_rmb(), and then read 1 on the second access to
nlk->bound.
In other words, you just ended up returning 1 without actually doing
the mb, so there will be no serialization between the "bound" variable
and reading the portid afterwards.
That makes no sense.
And if nlk->bound *is* stable, then the smp_rmb() doesn't make any
sense that I can see.
So for the code to actually make sense, it should either do:
int bound = nlk->bound;
smp_rmb();
return bound;
which is fine on x86, but might be expensive on other architectures
due to the unconditional rmb.
So you *could* write it with a conditional rmb, but then you need to
use a READ_ONCE(), to make sure that gcc really does the read exactly
once, because at that point the "rmb" no longer keeps gcc from playing
tricks. So
int bound = READ_ONCE(nlk->bound);
if (bound)
smp_rmb();
return bound;
could also be correct. Sadly, while "smp_rmb()" is a no-op on x86, it
*is* a barrier, so the above conditional smp_rmb() actually sucks on
x86, because I suspect that gcc will create a jump around an empty
asm. So the unconditional rmb is actually simpler better on at least
x86.
But the function as you wrote it does not make sense. When you do a
barrier, you really have to think about where the accesses are.
Linus
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Herbert Xu <herbert@gondor.apana.org.au> |
|---|---|
| Date | 2015-09-25 05:50 +0200 |
| Subject | Re: netlink: Add barrier to netlink_connect for theoretical case |
| Message-ID | <qcsbf-6Bg-1@gated-at.bofh.it> |
| In reply to | #1232551 |
On Thu, Sep 24, 2015 at 08:24:56PM -0700, Linus Torvalds wrote:
>
> The above looks very suspicious.
You're right Linus. I've added the READ_ONCE there. The reason I
kept the conditional is because the helper is always called in a
context where the result is used as part of an if statement. The
assembly actually looks sane, e.g., for netlink_bind:
3a06: 41 0f b6 94 24 e8 02 movzbl 0x2e8(%r12),%edx
3a0d: 00 00
3a0f: 84 d2 test %dl,%dl
3a11: 0f 85 97 00 00 00 jne 3aae <netlink_bind+0x12e>
3a17: 49 83 bc 24 98 03 00 cmpq $0x0,0x398(%r12)
3a1e: 00 00
...
3aae: 41 8b 84 24 a0 02 00 mov 0x2a0(%r12),%eax
3ab5: 00
3ab6: 41 39 46 04 cmp %eax,0x4(%r14)
3aba: 0f 84 57 ff ff ff je 3a17 <netlink_bind+0x97>
3ac0: b8 ea ff ff ff mov $0xffffffea,%eax
3ac5: eb d1 jmp 3a98 <netlink_bind+0x118>
So there is no unnecessary jumping around. I checked the other
two call sites and they look the same. I'm on a fairly old compiler
though (4.7.2) so it is possible that newer gcc's may do silly things.
Thanks,
---8<---
If a netlink_connect call is followed by a netlink_getname call
the portid returned may not be up-to-date. This patch adds a
barrier for that case.
As all nlk->bound dereferences now have barriers this patch also
adds a netlink_bound helper to encapsulate the barrier, as was
suggested by Tejun. Also as suggested by Linus, the lockless
read of nlk->bound is now protected with READ_ONCE to ensure that
the compiler doesn't do double reads that may screw up our use
of the barrier.
Fixes: da314c9923fe ("netlink: Replace rhash_portid with bound")
Reported-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 2c15fae..dd0a294 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -125,6 +125,17 @@ static inline u32 netlink_group_mask(u32 group)
return group ? 1 << (group - 1) : 0;
}
+static inline bool netlink_bound(struct netlink_sock *nlk)
+{
+ bool bound = READ_ONCE(nlk->bound);
+
+ /* Ensure nlk is hashed and visible. */
+ if (bound)
+ smp_rmb();
+
+ return bound;
+}
+
int netlink_add_tap(struct netlink_tap *nt)
{
if (unlikely(nt->dev->type != ARPHRD_NETLINK))
@@ -1524,14 +1535,10 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr,
return err;
}
- bound = nlk->bound;
- if (bound) {
- /* Ensure nlk->portid is up-to-date. */
- smp_rmb();
-
+ bound = netlink_bound(nlk);
+ if (bound)
if (nladdr->nl_pid != nlk->portid)
return -EINVAL;
- }
if (nlk->netlink_bind && groups) {
int group;
@@ -1547,9 +1554,6 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr,
}
}
- /* No need for barriers here as we return to user-space without
- * using any of the bound attributes.
- */
if (!bound) {
err = nladdr->nl_pid ?
netlink_insert(sk, nladdr->nl_pid) :
@@ -1598,10 +1602,7 @@ static int netlink_connect(struct socket *sock, struct sockaddr *addr,
!netlink_allowed(sock, NL_CFG_F_NONROOT_SEND))
return -EPERM;
- /* No need for barriers here as we return to user-space without
- * using any of the bound attributes.
- */
- if (!nlk->bound)
+ if (!netlink_bound(nlk))
err = netlink_autobind(sock);
if (err == 0) {
@@ -2442,13 +2443,10 @@ static int netlink_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
dst_group = nlk->dst_group;
}
- if (!nlk->bound) {
+ if (!netlink_bound(nlk)) {
err = netlink_autobind(sock);
if (err)
goto out;
- } else {
- /* Ensure nlk is hashed and visible. */
- smp_rmb();
}
/* It's a really convoluted way for userland to ask for mmaped
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Tejun Heo <tj@kernel.org> |
|---|---|
| Date | 2015-09-25 17:10 +0200 |
| Subject | Re: netlink: Add barrier to netlink_connect for theoretical case |
| Message-ID | <qcCNk-4XD-11@gated-at.bofh.it> |
| In reply to | #1232555 |
Hello, Herbert.
On Fri, Sep 25, 2015 at 11:39:57AM +0800, Herbert Xu wrote:
> +static inline bool netlink_bound(struct netlink_sock *nlk)
> +{
> + bool bound = READ_ONCE(nlk->bound);
> +
> + /* Ensure nlk is hashed and visible. */
> + if (bound)
> + smp_rmb();
> +
> + return bound;
> +}
While I can't see anything wrong with the above, I'm not a fan of it
for whatever worth that may be. I don't think it adds anything in
terms of readability or clarity of the code. It does avoid smp_rmb()
when @bound is false but that's unlikely to be helfpul - where the
barrier is being avoided is a cold path. This is largely a generic
characteristic because if where the barrier is being avoided is a hot
path, why wouldn't the code just grab a lock in that path instead of
using a gated barrier? So, there's a reason why we don't see code
like the above commonly. It doesn't buy us anything meaningful while
making the code more complicated and sometimes more fragile.
Thanks.
--
tejun
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Tejun Heo <tj@kernel.org> |
|---|---|
| Date | 2015-09-25 17:10 +0200 |
| Subject | Re: netlink: Add barrier to netlink_connect for theoretical case |
| Message-ID | <qcCNk-4XD-23@gated-at.bofh.it> |
| In reply to | #1232525 |
Hello, Herbert. On Fri, Sep 25, 2015 at 09:43:27AM +0800, Herbert Xu wrote: > Well had you said this in the first place I would've fixed it a > long time ago. There aren't any in-kernel users right now and > even if there were they'd have to do a connect/bind/sendmsg on > the same socket in two threads at the same time. But let's close > this theoretical hole: I'm not even sure we guarantee memory barrier on kernel/user crossings. In practice, we probably have enough barriers (e.g. some syscall traps imply barrier) but I can't think of a reason why we'd guarantee the existence of barrier there. As an extreme example, imagine UML on an architecture with relaxed memory model. Thanks. -- tejun -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Herbert Xu <herbert@gondor.apana.org.au> |
|---|---|
| Date | 2015-09-26 15:20 +0200 |
| Subject | netlink: Add netlink_bound helper and use it in netlink_getname |
| Message-ID | <qcXyp-10Y-1@gated-at.bofh.it> |
| In reply to | #1232872 |
On Fri, Sep 25, 2015 at 11:01:13AM -0400, Tejun Heo wrote:
>
> I'm not even sure we guarantee memory barrier on kernel/user
> crossings. In practice, we probably have enough barriers (e.g. some
> syscall traps imply barrier) but I can't think of a reason why we'd
> guarantee the existence of barrier there. As an extreme example,
> imagine UML on an architecture with relaxed memory model.
You misunderstood what I wrote. I was not basing this on whether
user-space transitions contained a barrier, but on the fact that
the next syscall must recheck nlk->bound before using nlk->portid.
In fact thanks to your email I now realise that my fix to the
getsockname problem is wrong. Instead of adding a barrier to
netlink_connect I should be adding a nlk->bound check to getname.
---8<---
netlink_getname must check nlk->bound before using nlk->portid
as otherwise nlk->portid may contain garbage.
This patch also adds a netlink_bound helper that encapsulate the
barrier, as was suggested by Tejun. Also as suggested by Linus,
the lockless read of nlk->bound in netlink_bound is protected with
READ_ONCE to ensure that the compiler doesn't do double reads that
may screw up our use of the barrier.
Fixes: da314c9923fe ("netlink: Replace rhash_portid with bound")
Reported-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 2c15fae..c860464 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -125,6 +125,17 @@ static inline u32 netlink_group_mask(u32 group)
return group ? 1 << (group - 1) : 0;
}
+static inline bool netlink_bound(struct netlink_sock *nlk)
+{
+ bool bound = READ_ONCE(nlk->bound);
+
+ /* Ensure nlk is hashed and visible. */
+ if (bound)
+ smp_rmb();
+
+ return bound;
+}
+
int netlink_add_tap(struct netlink_tap *nt)
{
if (unlikely(nt->dev->type != ARPHRD_NETLINK))
@@ -1524,14 +1535,10 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr,
return err;
}
- bound = nlk->bound;
- if (bound) {
- /* Ensure nlk->portid is up-to-date. */
- smp_rmb();
-
+ bound = netlink_bound(nlk);
+ if (bound)
if (nladdr->nl_pid != nlk->portid)
return -EINVAL;
- }
if (nlk->netlink_bind && groups) {
int group;
@@ -1547,9 +1554,6 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr,
}
}
- /* No need for barriers here as we return to user-space without
- * using any of the bound attributes.
- */
if (!bound) {
err = nladdr->nl_pid ?
netlink_insert(sk, nladdr->nl_pid) :
@@ -1628,7 +1632,7 @@ static int netlink_getname(struct socket *sock, struct sockaddr *addr,
nladdr->nl_pid = nlk->dst_portid;
nladdr->nl_groups = netlink_group_mask(nlk->dst_group);
} else {
- nladdr->nl_pid = nlk->portid;
+ nladdr->nl_pid = netlink_bound(nlk) ? nlk->portid : 0;
nladdr->nl_groups = nlk->groups ? nlk->groups[0] : 0;
}
return 0;
@@ -2442,13 +2446,10 @@ static int netlink_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
dst_group = nlk->dst_group;
}
- if (!nlk->bound) {
+ if (!netlink_bound(nlk)) {
err = netlink_autobind(sock);
if (err)
goto out;
- } else {
- /* Ensure nlk is hashed and visible. */
- smp_rmb();
}
/* It's a really convoluted way for userland to ask for mmaped
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Tejun Heo <tj@kernel.org> |
|---|---|
| Date | 2015-09-26 20:10 +0200 |
| Subject | Re: netlink: Add netlink_bound helper and use it in netlink_getname |
| Message-ID | <qd254-7y5-21@gated-at.bofh.it> |
| In reply to | #1233199 |
Hello, Herbert.
On Sat, Sep 26, 2015 at 09:16:21PM +0800, Herbert Xu wrote:
> You misunderstood what I wrote. I was not basing this on whether
> user-space transitions contained a barrier, but on the fact that
> the next syscall must recheck nlk->bound before using nlk->portid.
But that isn't what you wrote in the comment.
/* No need for barriers here as we return to user-space without
* using any of the bound attributes.
*/
> In fact thanks to your email I now realise that my fix to the
> getsockname problem is wrong. Instead of adding a barrier to
> netlink_connect I should be adding a nlk->bound check to getname.
I don't know, man. This thread almost feels surreal at this point.
> @@ -1628,7 +1632,7 @@ static int netlink_getname(struct socket *sock, struct sockaddr *addr,
> nladdr->nl_pid = nlk->dst_portid;
> nladdr->nl_groups = netlink_group_mask(nlk->dst_group);
> } else {
> - nladdr->nl_pid = nlk->portid;
> + nladdr->nl_pid = netlink_bound(nlk) ? nlk->portid : 0;
> nladdr->nl_groups = nlk->groups ? nlk->groups[0] : 0;
> }
> return 0;
So, this is really weird because netlink_getname() doens't participate
in the autobind race and thus it's perfectly fine for it to not worry
about whether ->bound is set or the memory barrier - whoever its
caller may be, the caller is of course responsible for ensuring that
the port is bound and visible if it expects to read back the number -
ie. if the caller doesn't know (in memory ordering sense) that
bind/connect/sendmsg succeeded, it of course can't expect to reliably
read back the port number. getname never needed the barrier. The
above is shifting synchronization from the source to its users. This
is a bad thing to do.
Thanks.
--
tejun
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Herbert Xu <herbert@gondor.apana.org.au> |
|---|---|
| Date | 2015-09-26 21:50 +0200 |
| Subject | Re: netlink: Add netlink_bound helper and use it in netlink_getname |
| Message-ID | <qd3DQ-1aw-3@gated-at.bofh.it> |
| In reply to | #1233255 |
On Sat, Sep 26, 2015 at 03:45:54PM -0400, Tejun Heo wrote: > Hello, Herbert. > > On Sun, Sep 27, 2015 at 03:41:10AM +0800, Herbert Xu wrote: > > Thread 1 Thread 2 > > sendmsg getsockname > > netlink_autobind netlink_getname > > > > Thread 2 should not have to do anything special to guarantee that > > getsockname does not return garbage. It must either be the bound > > portid if the autobind completed in thread 1 and is visible or it > > should return zero. > > > > As it stands thread 2 may see a portid belonging to somebody else > > if it catches the autobind in thread 1 trying different portids > > while roving. > > If the fact that thread 1 finished autobind isn't visible to thread 2, > it's valid for getsockname to return zero. No ordering between the > two operations is defined. If the fact that thread 1 finished > autobind is visible to thread 2, ordering is defined and because > ordering is transitive, by that very ordering, the port number is > visible to thread 2 too as long as thread 1 does proper barriering. If the autobind is not complete then netlink_getname must return zero rather than some garbage portid that belongs to somebody else's socket. That's what we did before any of this lockless code was introduced. If you don't check nlk->bound then you may return garbage. Cheers, -- Email: Herbert Xu <herbert@gondor.apana.org.au> Home Page: http://gondor.apana.org.au/~herbert/ PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Herbert Xu <herbert@gondor.apana.org.au> |
|---|---|
| Date | 2015-09-26 22:00 +0200 |
| Subject | Re: netlink: Add netlink_bound helper and use it in netlink_getname |
| Message-ID | <qd3Nv-1lI-3@gated-at.bofh.it> |
| In reply to | #1233275 |
On Sat, Sep 26, 2015 at 03:52:45PM -0400, Tejun Heo wrote: > > Ah, yeah, you're right. We need to check that there because it may > contain a garbage value. I still think it'd better to use > netlink_bound() test in connect() too tho. Well I disagree. When I say that it returns to user-space I really mean that the next time we use portid via the same call path that triggered the connect we must be checking nlk->bound anyway. Good luck finding more bugs in this code :) Cheers, -- Email: Herbert Xu <herbert@gondor.apana.org.au> Home Page: http://gondor.apana.org.au/~herbert/ PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Tejun Heo <tj@kernel.org> |
|---|---|
| Date | 2015-09-26 22:10 +0200 |
| Subject | Re: netlink: Add netlink_bound helper and use it in netlink_getname |
| Message-ID | <qd3Xb-1Ms-5@gated-at.bofh.it> |
| In reply to | #1233279 |
Hello, On Sun, Sep 27, 2015 at 03:55:48AM +0800, Herbert Xu wrote: > Well I disagree. When I say that it returns to user-space I really > mean that the next time we use portid via the same call path that > triggered the connect we must be checking nlk->bound anyway. > > Good luck finding more bugs in this code :) Frankly, I don't understand what you've been trying to achieve. You're actively disregarding best practices (like terminating synchronization where it starts) and reach the target state by doing a browian motion in the solution space. Sure, if you do enough of that, eventually you can arrive somewhere where it's not broken but it leads to a lot more overhead for everyone involved - the author, reviewers and later readers of the code and if you spread barrier usages like this across the kernel, we'll end up with code base which is a lot harder to verify and maintain. I hope you stop doing things this way but suppose that you're ignoring any conceptual arguments in this thread. Thanks. -- tejun -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Herbert Xu <herbert@gondor.apana.org.au> |
|---|---|
| Date | 2015-09-26 22:20 +0200 |
| Subject | Re: netlink: Add netlink_bound helper and use it in netlink_getname |
| Message-ID | <qd46R-1XH-7@gated-at.bofh.it> |
| In reply to | #1233289 |
On Sat, Sep 26, 2015 at 04:05:18PM -0400, Tejun Heo wrote: > > Frankly, I don't understand what you've been trying to achieve. > You're actively disregarding best practices (like terminating > synchronization where it starts) and reach the target state by doing a > browian motion in the solution space. Sure, if you do enough of that, > eventually you can arrive somewhere where it's not broken but it leads > to a lot more overhead for everyone involved - the author, reviewers > and later readers of the code and if you spread barrier usages like > this across the kernel, we'll end up with code base which is a lot > harder to verify and maintain. I hope you stop doing things this way > but suppose that you're ignoring any conceptual arguments in this > thread. Your point so far has been that if you add barriers or use primitives everywhere then races magically disappear. Well guess what the bug that you have discovered supposedly due to a missing barrier in netlink_connect has nothing to do with the barrier. Instead it is caused by a logical error elsewhere that would have gone unnoticed otherwise. So I retain my position that blindly adding barriers do not make bugs go away. Instead you need to have real understanding of what the code is doing and every spot where a barrier may be needed must be audited manually. Cheers, -- Email: Herbert Xu <herbert@gondor.apana.org.au> Home Page: http://gondor.apana.org.au/~herbert/ PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Tejun Heo <tj@kernel.org> |
|---|---|
| Date | 2015-09-26 22:20 +0200 |
| Subject | Re: netlink: Add netlink_bound helper and use it in netlink_getname |
| Message-ID | <qd46S-1XH-9@gated-at.bofh.it> |
| In reply to | #1233292 |
Hello, On Sun, Sep 27, 2015 at 04:10:41AM +0800, Herbert Xu wrote: > Well guess what the bug that you have discovered supposedly due to > a missing barrier in netlink_connect has nothing to do with the > barrier. Instead it is caused by a logical error elsewhere that > would have gone unnoticed otherwise. It's a combination of two problems. The garbage port number is a logical error but there still is an ordering problem there between ->bound and ->portid. We need to test ->bind there again because of the garbage port problem. > So I retain my position that blindly adding barriers do not make > bugs go away. Instead you need to have real understanding of what That's a dishonest summary of what I've been saying. > the code is doing and every spot where a barrier may be needed must > be audited manually. What I've been saying is that we do need to be careful and audit each barrier usages but at the same time there are established patterns that we can use to make the process significantly easier and more reliable. Thanks. -- tejun -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Tejun Heo <tj@kernel.org> |
|---|---|
| Date | 2015-09-26 22:00 +0200 |
| Subject | Re: netlink: Add netlink_bound helper and use it in netlink_getname |
| Message-ID | <qd3Nv-1lI-5@gated-at.bofh.it> |
| In reply to | #1233275 |
Hello, On Sun, Sep 27, 2015 at 03:49:16AM +0800, Herbert Xu wrote: > If the autobind is not complete then netlink_getname must return > zero rather than some garbage portid that belongs to somebody > else's socket. That's what we did before any of this lockless > code was introduced. > > If you don't check nlk->bound then you may return garbage. Ah, yeah, you're right. We need to check that there because it may contain a garbage value. I still think it'd better to use netlink_bound() test in connect() too tho. Thanks. -- tejun -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Herbert Xu <herbert@gondor.apana.org.au> |
|---|---|
| Date | 2015-09-26 21:50 +0200 |
| Subject | Re: netlink: Add netlink_bound helper and use it in netlink_getname |
| Message-ID | <qd3DQ-1aw-5@gated-at.bofh.it> |
| In reply to | #1233255 |
On Sat, Sep 26, 2015 at 02:09:03PM -0400, Tejun Heo wrote:
>
> > @@ -1628,7 +1632,7 @@ static int netlink_getname(struct socket *sock, struct sockaddr *addr,
> > nladdr->nl_pid = nlk->dst_portid;
> > nladdr->nl_groups = netlink_group_mask(nlk->dst_group);
> > } else {
> > - nladdr->nl_pid = nlk->portid;
> > + nladdr->nl_pid = netlink_bound(nlk) ? nlk->portid : 0;
> > nladdr->nl_groups = nlk->groups ? nlk->groups[0] : 0;
> > }
> > return 0;
>
> So, this is really weird because netlink_getname() doens't participate
> in the autobind race and thus it's perfectly fine for it to not worry
> about whether ->bound is set or the memory barrier - whoever its
> caller may be, the caller is of course responsible for ensuring that
> the port is bound and visible if it expects to read back the number -
> ie. if the caller doesn't know (in memory ordering sense) that
> bind/connect/sendmsg succeeded, it of course can't expect to reliably
> read back the port number. getname never needed the barrier. The
> above is shifting synchronization from the source to its users. This
> is a bad thing to do.
Thread 1 Thread 2
sendmsg getsockname
netlink_autobind netlink_getname
Thread 2 should not have to do anything special to guarantee that
getsockname does not return garbage. It must either be the bound
portid if the autobind completed in thread 1 and is visible or it
should return zero.
As it stands thread 2 may see a portid belonging to somebody else
if it catches the autobind in thread 1 trying different portids
while roving.
Cheers,
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Tejun Heo <tj@kernel.org> |
|---|---|
| Date | 2015-09-26 21:50 +0200 |
| Subject | Re: netlink: Add netlink_bound helper and use it in netlink_getname |
| Message-ID | <qd3DQ-1aw-7@gated-at.bofh.it> |
| In reply to | #1233277 |
Hello, Herbert. On Sun, Sep 27, 2015 at 03:41:10AM +0800, Herbert Xu wrote: > Thread 1 Thread 2 > sendmsg getsockname > netlink_autobind netlink_getname > > Thread 2 should not have to do anything special to guarantee that > getsockname does not return garbage. It must either be the bound > portid if the autobind completed in thread 1 and is visible or it > should return zero. > > As it stands thread 2 may see a portid belonging to somebody else > if it catches the autobind in thread 1 trying different portids > while roving. If the fact that thread 1 finished autobind isn't visible to thread 2, it's valid for getsockname to return zero. No ordering between the two operations is defined. If the fact that thread 1 finished autobind is visible to thread 2, ordering is defined and because ordering is transitive, by that very ordering, the port number is visible to thread 2 too as long as thread 1 does proper barriering. Thanks. -- tejun -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web