netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] net: af_unix: protect ->sk_shutdown change with lock_sock()
@ 2016-05-18 10:14 Andrey Ryabinin
  2016-05-18 10:38 ` Hannes Frederic Sowa
  0 siblings, 1 reply; 12+ messages in thread
From: Andrey Ryabinin @ 2016-05-18 10:14 UTC (permalink / raw)
  To: David S. Miller
  Cc: Hannes Frederic Sowa, Rainer Weikusat, Eric Dumazet, netdev,
	linux-kernel, Andrey Ryabinin

->sk_shutdown bits share one bitfield with some other bits in sock struct,
such as ->sk_no_check_[r,t]x, ->sk_userlocks ...
sock_setsockopt() may write to these bits, while holding the socket lock.
In case of AF_UNIX sockets, we change ->sk_shutdown bits while holding only
unix_state_lock(). So concurrent setsockopt() and shutdown() may lead
to corrupting these bits.

Fix that by protecting writes to ->sk_shutdown with lock_sock()

Signed-off-by: Andrey Ryabinin <aryabinin@virtuozzo.com>
---
 net/unix/af_unix.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 80aa6a3..7586a4e 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -518,6 +518,7 @@ static void unix_release_sock(struct sock *sk, int embrion)
 	unix_remove_socket(sk);
 
 	/* Clear state */
+	lock_sock(sk);
 	unix_state_lock(sk);
 	sock_orphan(sk);
 	sk->sk_shutdown = SHUTDOWN_MASK;
@@ -527,6 +528,7 @@ static void unix_release_sock(struct sock *sk, int embrion)
 	state = sk->sk_state;
 	sk->sk_state = TCP_CLOSE;
 	unix_state_unlock(sk);
+	release_sock(sk);
 
 	wake_up_interruptible_all(&u->peer_wait);
 
@@ -534,12 +536,14 @@ static void unix_release_sock(struct sock *sk, int embrion)
 
 	if (skpair != NULL) {
 		if (sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET) {
+			lock_sock(skpair);
 			unix_state_lock(skpair);
 			/* No more writes */
 			skpair->sk_shutdown = SHUTDOWN_MASK;
 			if (!skb_queue_empty(&sk->sk_receive_queue) || embrion)
 				skpair->sk_err = ECONNRESET;
 			unix_state_unlock(skpair);
+			release_sock(skpair);
 			skpair->sk_state_change(skpair);
 			sk_wake_async(skpair, SOCK_WAKE_WAITD, POLL_HUP);
 		}
@@ -2547,12 +2551,14 @@ static int unix_shutdown(struct socket *sock, int mode)
 	 */
 	++mode;
 
+	lock_sock(sk);
 	unix_state_lock(sk);
 	sk->sk_shutdown |= mode;
 	other = unix_peer(sk);
 	if (other)
 		sock_hold(other);
 	unix_state_unlock(sk);
+	release_sock(sk);
 	sk->sk_state_change(sk);
 
 	if (other &&
@@ -2564,9 +2570,12 @@ static int unix_shutdown(struct socket *sock, int mode)
 			peer_mode |= SEND_SHUTDOWN;
 		if (mode&SEND_SHUTDOWN)
 			peer_mode |= RCV_SHUTDOWN;
+
+		lock_sock(other);
 		unix_state_lock(other);
 		other->sk_shutdown |= peer_mode;
 		unix_state_unlock(other);
+		release_sock(other);
 		other->sk_state_change(other);
 		if (peer_mode == SHUTDOWN_MASK)
 			sk_wake_async(other, SOCK_WAKE_WAITD, POLL_HUP);
-- 
2.7.3

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

* Re: [PATCH] net: af_unix: protect ->sk_shutdown change with lock_sock()
  2016-05-18 10:14 [PATCH] net: af_unix: protect ->sk_shutdown change with lock_sock() Andrey Ryabinin
@ 2016-05-18 10:38 ` Hannes Frederic Sowa
  2016-05-18 11:23   ` Andrey Ryabinin
  2016-05-18 12:03   ` [PATCH v2] net: sock: move ->sk_shutdown out of bitfields Andrey Ryabinin
  0 siblings, 2 replies; 12+ messages in thread
From: Hannes Frederic Sowa @ 2016-05-18 10:38 UTC (permalink / raw)
  To: Andrey Ryabinin, David S. Miller
  Cc: Rainer Weikusat, Eric Dumazet, netdev, linux-kernel

On 18.05.2016 12:14, Andrey Ryabinin wrote:
> ->sk_shutdown bits share one bitfield with some other bits in sock struct,
> such as ->sk_no_check_[r,t]x, ->sk_userlocks ...
> sock_setsockopt() may write to these bits, while holding the socket lock.
> In case of AF_UNIX sockets, we change ->sk_shutdown bits while holding only
> unix_state_lock(). So concurrent setsockopt() and shutdown() may lead
> to corrupting these bits.
> 
> Fix that by protecting writes to ->sk_shutdown with lock_sock()

Is it possible to move sk_shutdown out of the bitfields? Maybe a whole
which suites is available somewhere?

af_unix doesn't depend on the socket locks anywhere and it would keep
locking much easier if we only depend on the state lock.

Bye,
Hannes

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

* Re: [PATCH] net: af_unix: protect ->sk_shutdown change with lock_sock()
  2016-05-18 10:38 ` Hannes Frederic Sowa
@ 2016-05-18 11:23   ` Andrey Ryabinin
  2016-05-18 12:03   ` [PATCH v2] net: sock: move ->sk_shutdown out of bitfields Andrey Ryabinin
  1 sibling, 0 replies; 12+ messages in thread
From: Andrey Ryabinin @ 2016-05-18 11:23 UTC (permalink / raw)
  To: Hannes Frederic Sowa, David S. Miller
  Cc: Rainer Weikusat, Eric Dumazet, netdev, linux-kernel



On 05/18/2016 01:38 PM, Hannes Frederic Sowa wrote:
> On 18.05.2016 12:14, Andrey Ryabinin wrote:
>> ->sk_shutdown bits share one bitfield with some other bits in sock struct,
>> such as ->sk_no_check_[r,t]x, ->sk_userlocks ...
>> sock_setsockopt() may write to these bits, while holding the socket lock.
>> In case of AF_UNIX sockets, we change ->sk_shutdown bits while holding only
>> unix_state_lock(). So concurrent setsockopt() and shutdown() may lead
>> to corrupting these bits.
>>
>> Fix that by protecting writes to ->sk_shutdown with lock_sock()
> 
> Is it possible to move sk_shutdown out of the bitfields? Maybe a whole
> which suites is available somewhere?
> 

Agreed. I see two possible 16-bit holes - one after 'sk_gso_max_segs'
and one more after 'sk_tsflags'.


> af_unix doesn't depend on the socket locks anywhere and it would keep
> locking much easier if we only depend on the state lock.
> 
> Bye,
> Hannes
> 
> 

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

* [PATCH v2] net: sock: move ->sk_shutdown out of bitfields.
  2016-05-18 10:38 ` Hannes Frederic Sowa
  2016-05-18 11:23   ` Andrey Ryabinin
@ 2016-05-18 12:03   ` Andrey Ryabinin
  2016-05-18 13:03     ` Eric Dumazet
  1 sibling, 1 reply; 12+ messages in thread
From: Andrey Ryabinin @ 2016-05-18 12:03 UTC (permalink / raw)
  To: David S. Miller
  Cc: Hannes Frederic Sowa, Rainer Weikusat, Eric Dumazet, netdev,
	linux-kernel, Andrey Ryabinin

->sk_shutdown bits share one bitfield with some other bits in sock struct,
such as ->sk_no_check_[r,t]x, ->sk_userlocks ...
sock_setsockopt() may write to these bits, while holding the socket lock.

In case of AF_UNIX sockets, we change ->sk_shutdown bits while holding only
unix_state_lock(). So concurrent setsockopt() and shutdown() may lead
to corrupting these bits.

Fix this by moving ->sk_shutdown bits out of bitfield into a separate byte.
This will not change the 'struct sock' size since ->sk_shutdown moved into
previously unused 16-bit hole.

Signed-off-by: Andrey Ryabinin <aryabinin@virtuozzo.com>
Suggested-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
---
 include/net/sock.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/net/sock.h b/include/net/sock.h
index c9c8b19..04dc131 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -383,8 +383,7 @@ struct sock {
 	int			sk_sndbuf;
 	struct sk_buff_head	sk_write_queue;
 	kmemcheck_bitfield_begin(flags);
-	unsigned int		sk_shutdown  : 2,
-				sk_no_check_tx : 1,
+	unsigned int		sk_no_check_tx : 1,
 				sk_no_check_rx : 1,
 				sk_userlocks : 4,
 				sk_protocol  : 8,
@@ -418,6 +417,7 @@ struct sock {
 	struct timer_list	sk_timer;
 	ktime_t			sk_stamp;
 	u16			sk_tsflags;
+	u8			sk_shutdown;
 	u32			sk_tskey;
 	struct socket		*sk_socket;
 	void			*sk_user_data;
-- 
2.7.3

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

* Re: [PATCH v2] net: sock: move ->sk_shutdown out of bitfields.
  2016-05-18 12:03   ` [PATCH v2] net: sock: move ->sk_shutdown out of bitfields Andrey Ryabinin
@ 2016-05-18 13:03     ` Eric Dumazet
  2016-05-18 13:14       ` Andrey Ryabinin
  2016-05-18 14:36       ` [PATCH v3] " Andrey Ryabinin
  0 siblings, 2 replies; 12+ messages in thread
From: Eric Dumazet @ 2016-05-18 13:03 UTC (permalink / raw)
  To: Andrey Ryabinin
  Cc: David S. Miller, Hannes Frederic Sowa, Rainer Weikusat,
	Eric Dumazet, netdev, linux-kernel

On Wed, 2016-05-18 at 15:03 +0300, Andrey Ryabinin wrote:
> ->sk_shutdown bits share one bitfield with some other bits in sock struct,
> such as ->sk_no_check_[r,t]x, ->sk_userlocks ...
> sock_setsockopt() may write to these bits, while holding the socket lock.
> 
> In case of AF_UNIX sockets, we change ->sk_shutdown bits while holding only
> unix_state_lock(). So concurrent setsockopt() and shutdown() may lead
> to corrupting these bits.
> 
> Fix this by moving ->sk_shutdown bits out of bitfield into a separate byte.
> This will not change the 'struct sock' size since ->sk_shutdown moved into
> previously unused 16-bit hole.
> 
> Signed-off-by: Andrey Ryabinin <aryabinin@virtuozzo.com>
> Suggested-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
> ---
>  include/net/sock.h | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/include/net/sock.h b/include/net/sock.h
> index c9c8b19..04dc131 100644
> --- a/include/net/sock.h
> +++ b/include/net/sock.h
> @@ -383,8 +383,7 @@ struct sock {
>  	int			sk_sndbuf;
>  	struct sk_buff_head	sk_write_queue;
>  	kmemcheck_bitfield_begin(flags);
> -	unsigned int		sk_shutdown  : 2,


Please replace by a padding, so that sk_protocol is sill a byte,
not 8 bits spaning 2 bytes in memory.

> -				sk_no_check_tx : 1,
> +	unsigned int		sk_no_check_tx : 1,
>  				sk_no_check_rx : 1,
>  				sk_userlocks : 4,
>  				sk_protocol  : 8,
> @@ -418,6 +417,7 @@ struct sock {
>  	struct timer_list	sk_timer;
>  	ktime_t			sk_stamp;
>  	u16			sk_tsflags;
> +	u8			sk_shutdown;
>  	u32			sk_tskey;
>  	struct socket		*sk_socket;
>  	void			*sk_user_data;

Thanks.

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

* Re: [PATCH v2] net: sock: move ->sk_shutdown out of bitfields.
  2016-05-18 13:03     ` Eric Dumazet
@ 2016-05-18 13:14       ` Andrey Ryabinin
  2016-05-18 13:49         ` Eric Dumazet
  2016-05-18 14:36       ` [PATCH v3] " Andrey Ryabinin
  1 sibling, 1 reply; 12+ messages in thread
From: Andrey Ryabinin @ 2016-05-18 13:14 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: David S. Miller, Hannes Frederic Sowa, Rainer Weikusat,
	Eric Dumazet, netdev, linux-kernel



On 05/18/2016 04:03 PM, Eric Dumazet wrote:
> On Wed, 2016-05-18 at 15:03 +0300, Andrey Ryabinin wrote:
>> ->sk_shutdown bits share one bitfield with some other bits in sock struct,
>> such as ->sk_no_check_[r,t]x, ->sk_userlocks ...
>> sock_setsockopt() may write to these bits, while holding the socket lock.
>>
>> In case of AF_UNIX sockets, we change ->sk_shutdown bits while holding only
>> unix_state_lock(). So concurrent setsockopt() and shutdown() may lead
>> to corrupting these bits.
>>
>> Fix this by moving ->sk_shutdown bits out of bitfield into a separate byte.
>> This will not change the 'struct sock' size since ->sk_shutdown moved into
>> previously unused 16-bit hole.
>>
>> Signed-off-by: Andrey Ryabinin <aryabinin@virtuozzo.com>
>> Suggested-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
>> ---
>>  include/net/sock.h | 4 ++--
>>  1 file changed, 2 insertions(+), 2 deletions(-)
>>
>> diff --git a/include/net/sock.h b/include/net/sock.h
>> index c9c8b19..04dc131 100644
>> --- a/include/net/sock.h
>> +++ b/include/net/sock.h
>> @@ -383,8 +383,7 @@ struct sock {
>>  	int			sk_sndbuf;
>>  	struct sk_buff_head	sk_write_queue;
>>  	kmemcheck_bitfield_begin(flags);
>> -	unsigned int		sk_shutdown  : 2,
> 
> 
> Please replace by a padding, so that sk_protocol is sill a byte,
> not 8 bits spaning 2 bytes in memory.

I think, it would be better to have something like this:

	u16 sk_type;
	u8 sk_protocol;
	kmemcheck_bitfield_begin(flags);
	u8			sk_no_check_tx : 1,
				sk_no_check_rx : 1,
				sk_userlocks : 4,
	kmemcheck_bitfield_end(flags);

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

* Re: [PATCH v2] net: sock: move ->sk_shutdown out of bitfields.
  2016-05-18 13:14       ` Andrey Ryabinin
@ 2016-05-18 13:49         ` Eric Dumazet
  0 siblings, 0 replies; 12+ messages in thread
From: Eric Dumazet @ 2016-05-18 13:49 UTC (permalink / raw)
  To: Andrey Ryabinin
  Cc: David S. Miller, Hannes Frederic Sowa, Rainer Weikusat,
	Eric Dumazet, netdev, linux-kernel

On Wed, 2016-05-18 at 16:14 +0300, Andrey Ryabinin wrote:
> 
> On 05/18/2016 04:03 PM, Eric Dumazet wrote:
> > On Wed, 2016-05-18 at 15:03 +0300, Andrey Ryabinin wrote:
> >> ->sk_shutdown bits share one bitfield with some other bits in sock struct,
> >> such as ->sk_no_check_[r,t]x, ->sk_userlocks ...
> >> sock_setsockopt() may write to these bits, while holding the socket lock.
> >>
> >> In case of AF_UNIX sockets, we change ->sk_shutdown bits while holding only
> >> unix_state_lock(). So concurrent setsockopt() and shutdown() may lead
> >> to corrupting these bits.
> >>
> >> Fix this by moving ->sk_shutdown bits out of bitfield into a separate byte.
> >> This will not change the 'struct sock' size since ->sk_shutdown moved into
> >> previously unused 16-bit hole.
> >>
> >> Signed-off-by: Andrey Ryabinin <aryabinin@virtuozzo.com>
> >> Suggested-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
> >> ---
> >>  include/net/sock.h | 4 ++--
> >>  1 file changed, 2 insertions(+), 2 deletions(-)
> >>
> >> diff --git a/include/net/sock.h b/include/net/sock.h
> >> index c9c8b19..04dc131 100644
> >> --- a/include/net/sock.h
> >> +++ b/include/net/sock.h
> >> @@ -383,8 +383,7 @@ struct sock {
> >>  	int			sk_sndbuf;
> >>  	struct sk_buff_head	sk_write_queue;
> >>  	kmemcheck_bitfield_begin(flags);
> >> -	unsigned int		sk_shutdown  : 2,
> > 
> > 
> > Please replace by a padding, so that sk_protocol is sill a byte,
> > not 8 bits spaning 2 bytes in memory.
> 
> I think, it would be better to have something like this:
> 
> 	u16 sk_type;
> 	u8 sk_protocol;
> 	kmemcheck_bitfield_begin(flags);
> 	u8			sk_no_check_tx : 1,
> 				sk_no_check_rx : 1,
> 				sk_userlocks : 4,
> 	kmemcheck_bitfield_end(flags);
> 
> 

No. This would add extra 32 bits for KMEMCHECK users.

Check kmemcheck_bitfield_begin definition.

These fields are together to fill 32 bits.

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

* [PATCH v3] net: sock: move ->sk_shutdown out of bitfields.
  2016-05-18 13:03     ` Eric Dumazet
  2016-05-18 13:14       ` Andrey Ryabinin
@ 2016-05-18 14:36       ` Andrey Ryabinin
  2016-05-18 15:31         ` Eric Dumazet
  1 sibling, 1 reply; 12+ messages in thread
From: Andrey Ryabinin @ 2016-05-18 14:36 UTC (permalink / raw)
  To: David S. Miller
  Cc: Hannes Frederic Sowa, Rainer Weikusat, Eric Dumazet, netdev,
	linux-kernel, Andrey Ryabinin

->sk_shutdown bits share one bitfield with some other bits in sock struct,
such as ->sk_no_check_[r,t]x, ->sk_userlocks ...
sock_setsockopt() may write to these bits, while holding the socket lock.

In case of AF_UNIX sockets, we change ->sk_shutdown bits while holding only
unix_state_lock(). So concurrent setsockopt() and shutdown() may lead
to corrupting these bits.

Fix this by moving ->sk_shutdown bits out of bitfield into a separate byte.
This will not change the 'struct sock' size since ->sk_shutdown moved into
previously unused 16-bit hole.

Signed-off-by: Andrey Ryabinin <aryabinin@virtuozzo.com>
Suggested-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
---

Changes since v1:
 - move sk_shutdown into a separate byte instead of locking
	AF_UNIX sockets.

Changes since v2:
 - reorder bitfields, so that sk_type/sk_protocol still fit in
    separate 2-bytes/byte.
	
 include/net/sock.h | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/include/net/sock.h b/include/net/sock.h
index c9c8b19..1c019d4 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -383,12 +383,11 @@ struct sock {
 	int			sk_sndbuf;
 	struct sk_buff_head	sk_write_queue;
 	kmemcheck_bitfield_begin(flags);
-	unsigned int		sk_shutdown  : 2,
+	unsigned int		sk_type : 16,
+				sk_protocol : 8,
 				sk_no_check_tx : 1,
 				sk_no_check_rx : 1,
-				sk_userlocks : 4,
-				sk_protocol  : 8,
-				sk_type      : 16;
+				sk_userlocks : 4;
 #define SK_PROTOCOL_MAX U8_MAX
 	kmemcheck_bitfield_end(flags);
 	int			sk_wmem_queued;
@@ -418,6 +417,7 @@ struct sock {
 	struct timer_list	sk_timer;
 	ktime_t			sk_stamp;
 	u16			sk_tsflags;
+	u8			sk_shutdown;
 	u32			sk_tskey;
 	struct socket		*sk_socket;
 	void			*sk_user_data;
-- 
2.7.3

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

* Re: [PATCH v3] net: sock: move ->sk_shutdown out of bitfields.
  2016-05-18 14:36       ` [PATCH v3] " Andrey Ryabinin
@ 2016-05-18 15:31         ` Eric Dumazet
  2016-05-18 16:19           ` [PATCH v4] " Andrey Ryabinin
  0 siblings, 1 reply; 12+ messages in thread
From: Eric Dumazet @ 2016-05-18 15:31 UTC (permalink / raw)
  To: Andrey Ryabinin
  Cc: David S. Miller, Hannes Frederic Sowa, Rainer Weikusat,
	Eric Dumazet, netdev, linux-kernel

On Wed, 2016-05-18 at 17:36 +0300, Andrey Ryabinin wrote:
> ->sk_shutdown bits share one bitfield with some other bits in sock struct,
> such as ->sk_no_check_[r,t]x, ->sk_userlocks ...
> sock_setsockopt() may write to these bits, while holding the socket lock.
> 
> In case of AF_UNIX sockets, we change ->sk_shutdown bits while holding only
> unix_state_lock(). So concurrent setsockopt() and shutdown() may lead
> to corrupting these bits.
> 
> Fix this by moving ->sk_shutdown bits out of bitfield into a separate byte.
> This will not change the 'struct sock' size since ->sk_shutdown moved into
> previously unused 16-bit hole.
> 
> Signed-off-by: Andrey Ryabinin <aryabinin@virtuozzo.com>
> Suggested-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
> ---
> 
> Changes since v1:
>  - move sk_shutdown into a separate byte instead of locking
> 	AF_UNIX sockets.
> 
> Changes since v2:
>  - reorder bitfields, so that sk_type/sk_protocol still fit in
>     separate 2-bytes/byte.
> 	

I suggested to use an explicit padding, to clearly show that two bits
are available there. You also could add a comment to remind the rules.

Something like :

diff --git a/include/net/sock.h b/include/net/sock.h
index c9c8b19df27c558354687119db60c0716909ea3f..4e239a7ef4f67b1988fe119d81566d1465a2b596 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -382,8 +382,10 @@ struct sock {
 	atomic_t		sk_omem_alloc;
 	int			sk_sndbuf;
 	struct sk_buff_head	sk_write_queue;
+
+	/* because of non atomicity rules, all changes are protected by socket lock */
 	kmemcheck_bitfield_begin(flags);
-	unsigned int		sk_shutdown  : 2,
+	unsigned int		sk_padding   : 2,
 				sk_no_check_tx : 1,
 				sk_no_check_rx : 1,
 				sk_userlocks : 4,
@@ -391,6 +393,7 @@ struct sock {
 				sk_type      : 16;
 #define SK_PROTOCOL_MAX U8_MAX
 	kmemcheck_bitfield_end(flags);
+
 	int			sk_wmem_queued;
 	gfp_t			sk_allocation;
 	u32			sk_pacing_rate; /* bytes per second */
@@ -418,6 +421,7 @@ struct sock {
 	struct timer_list	sk_timer;
 	ktime_t			sk_stamp;
 	u16			sk_tsflags;
+	u8			sk_shutdown;
 	u32			sk_tskey;
 	struct socket		*sk_socket;
 	void			*sk_user_data;

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

* [PATCH v4] net: sock: move ->sk_shutdown out of bitfields.
  2016-05-18 15:31         ` Eric Dumazet
@ 2016-05-18 16:19           ` Andrey Ryabinin
  2016-05-18 17:17             ` Eric Dumazet
  2016-05-20 22:05             ` David Miller
  0 siblings, 2 replies; 12+ messages in thread
From: Andrey Ryabinin @ 2016-05-18 16:19 UTC (permalink / raw)
  To: David S. Miller
  Cc: Hannes Frederic Sowa, Rainer Weikusat, Eric Dumazet, netdev,
	linux-kernel, Andrey Ryabinin

->sk_shutdown bits share one bitfield with some other bits in sock struct,
such as ->sk_no_check_[r,t]x, ->sk_userlocks ...
sock_setsockopt() may write to these bits, while holding the socket lock.

In case of AF_UNIX sockets, we change ->sk_shutdown bits while holding only
unix_state_lock(). So concurrent setsockopt() and shutdown() may lead
to corrupting these bits.

Fix this by moving ->sk_shutdown bits out of bitfield into a separate byte.
This will not change the 'struct sock' size since ->sk_shutdown moved into
previously unused 16-bit hole.

Signed-off-by: Andrey Ryabinin <aryabinin@virtuozzo.com>
Suggested-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
---

Changes since v1:
 - move sk_shutdown into a separate byte instead of locking
	AF_UNIX sockets.

Changes since v2:
 - reorder bitfields, so that sk_type/sk_protocol still fit in
    separate 2-bytes/byte.

Changes since v3:
  - padding and comment per Eric.

 include/net/sock.h | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/include/net/sock.h b/include/net/sock.h
index c9c8b19..649d2a8 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -382,8 +382,13 @@ struct sock {
 	atomic_t		sk_omem_alloc;
 	int			sk_sndbuf;
 	struct sk_buff_head	sk_write_queue;
+
+	/*
+	 * Because of non atomicity rules, all
+	 * changes are protected by socket lock.
+	 */
 	kmemcheck_bitfield_begin(flags);
-	unsigned int		sk_shutdown  : 2,
+	unsigned int		sk_padding : 2,
 				sk_no_check_tx : 1,
 				sk_no_check_rx : 1,
 				sk_userlocks : 4,
@@ -391,6 +396,7 @@ struct sock {
 				sk_type      : 16;
 #define SK_PROTOCOL_MAX U8_MAX
 	kmemcheck_bitfield_end(flags);
+
 	int			sk_wmem_queued;
 	gfp_t			sk_allocation;
 	u32			sk_pacing_rate; /* bytes per second */
@@ -418,6 +424,7 @@ struct sock {
 	struct timer_list	sk_timer;
 	ktime_t			sk_stamp;
 	u16			sk_tsflags;
+	u8			sk_shutdown;
 	u32			sk_tskey;
 	struct socket		*sk_socket;
 	void			*sk_user_data;
-- 
2.7.3

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

* Re: [PATCH v4] net: sock: move ->sk_shutdown out of bitfields.
  2016-05-18 16:19           ` [PATCH v4] " Andrey Ryabinin
@ 2016-05-18 17:17             ` Eric Dumazet
  2016-05-20 22:05             ` David Miller
  1 sibling, 0 replies; 12+ messages in thread
From: Eric Dumazet @ 2016-05-18 17:17 UTC (permalink / raw)
  To: Andrey Ryabinin
  Cc: David S. Miller, Hannes Frederic Sowa, Rainer Weikusat,
	Eric Dumazet, netdev, linux-kernel

On Wed, 2016-05-18 at 19:19 +0300, Andrey Ryabinin wrote:
> ->sk_shutdown bits share one bitfield with some other bits in sock struct,
> such as ->sk_no_check_[r,t]x, ->sk_userlocks ...
> sock_setsockopt() may write to these bits, while holding the socket lock.
> 
> In case of AF_UNIX sockets, we change ->sk_shutdown bits while holding only
> unix_state_lock(). So concurrent setsockopt() and shutdown() may lead
> to corrupting these bits.
> 
> Fix this by moving ->sk_shutdown bits out of bitfield into a separate byte.
> This will not change the 'struct sock' size since ->sk_shutdown moved into
> previously unused 16-bit hole.
> 
> Signed-off-by: Andrey Ryabinin <aryabinin@virtuozzo.com>
> Suggested-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
> ---

Acked-by: Eric Dumazet <edumazet@google.com>

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

* Re: [PATCH v4] net: sock: move ->sk_shutdown out of bitfields.
  2016-05-18 16:19           ` [PATCH v4] " Andrey Ryabinin
  2016-05-18 17:17             ` Eric Dumazet
@ 2016-05-20 22:05             ` David Miller
  1 sibling, 0 replies; 12+ messages in thread
From: David Miller @ 2016-05-20 22:05 UTC (permalink / raw)
  To: aryabinin; +Cc: hannes, rweikusat, edumazet, netdev, linux-kernel

From: Andrey Ryabinin <aryabinin@virtuozzo.com>
Date: Wed, 18 May 2016 19:19:27 +0300

> ->sk_shutdown bits share one bitfield with some other bits in sock struct,
> such as ->sk_no_check_[r,t]x, ->sk_userlocks ...
> sock_setsockopt() may write to these bits, while holding the socket lock.
> 
> In case of AF_UNIX sockets, we change ->sk_shutdown bits while holding only
> unix_state_lock(). So concurrent setsockopt() and shutdown() may lead
> to corrupting these bits.
> 
> Fix this by moving ->sk_shutdown bits out of bitfield into a separate byte.
> This will not change the 'struct sock' size since ->sk_shutdown moved into
> previously unused 16-bit hole.
> 
> Signed-off-by: Andrey Ryabinin <aryabinin@virtuozzo.com>
> Suggested-by: Hannes Frederic Sowa <hannes@stressinduktion.org>

Looks good, applied and queued up for -stable.

Thanks.

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

end of thread, other threads:[~2016-05-20 22:05 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-05-18 10:14 [PATCH] net: af_unix: protect ->sk_shutdown change with lock_sock() Andrey Ryabinin
2016-05-18 10:38 ` Hannes Frederic Sowa
2016-05-18 11:23   ` Andrey Ryabinin
2016-05-18 12:03   ` [PATCH v2] net: sock: move ->sk_shutdown out of bitfields Andrey Ryabinin
2016-05-18 13:03     ` Eric Dumazet
2016-05-18 13:14       ` Andrey Ryabinin
2016-05-18 13:49         ` Eric Dumazet
2016-05-18 14:36       ` [PATCH v3] " Andrey Ryabinin
2016-05-18 15:31         ` Eric Dumazet
2016-05-18 16:19           ` [PATCH v4] " Andrey Ryabinin
2016-05-18 17:17             ` Eric Dumazet
2016-05-20 22:05             ` David Miller

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).