->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. https://jira.sw.ru/browse/PSBM-47023 Link: http://lkml.kernel.org/g/1463588367-16310-1-git-send-email-aryabi...@virtuozzo.com Signed-off-by: Andrey Ryabinin <aryabi...@virtuozzo.com> Suggested-by: Hannes Frederic Sowa <han...@stressinduktion.org> Acked-by: Eric Dumazet <eduma...@google.com> --- 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 b940aa5..ccaacb6 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -370,8 +370,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, #ifdef __GENKSYMS__ sk_no_check : 2, #else @@ -382,6 +387,7 @@ struct sock { sk_protocol : 8, sk_type : 16; kmemcheck_bitfield_end(flags); + int sk_wmem_queued; gfp_t sk_allocation; u32 sk_pacing_rate; /* bytes per second */ @@ -390,6 +396,7 @@ struct sock { int sk_gso_type; unsigned int sk_gso_max_size; u16 sk_gso_max_segs; + u8 sk_shutdown; int sk_rcvlowat; unsigned long sk_lingertime; struct sk_buff_head sk_error_queue; -- 2.7.3 _______________________________________________ Devel mailing list Devel@openvz.org https://lists.openvz.org/mailman/listinfo/devel