]> www.infradead.org Git - users/jedix/linux-maple.git/commit
rds: tcp: Sequence teardown of listen and acceptor sockets to avoid races
authorSowmini Varadhan <sowmini.varadhan@oracle.com>
Fri, 16 Jun 2017 19:13:49 +0000 (12:13 -0700)
committerChuck Anderson <chuck.anderson@oracle.com>
Sun, 18 Jun 2017 19:49:41 +0000 (12:49 -0700)
commit68d17254014e2174a0210ff079ff00bd9ead6e69
tree3d644ef71fe5348a2448834bc385be0a1b38d200
parent5a4f133cb84d6400e8c5cfdaabdcb431e300217a
rds: tcp: Sequence teardown of listen and acceptor sockets to avoid races

Commit a93d01f5777e ("RDS: TCP: avoid bad page reference in
rds_tcp_listen_data_ready") added the function
rds_tcp_listen_sock_def_readable()  to handle the case when a
partially set-up acceptor socket drops into rds_tcp_listen_data_ready().
However, if the listen socket (rtn->rds_tcp_listen_sock) is itself going
through a tear-down via rds_tcp_listen_stop(), the (*ready)() will be
null and we would hit a panic  of the form
  BUG: unable to handle kernel NULL pointer dereference at   (null)
  IP:           (null)
       :
  ? rds_tcp_listen_data_ready+0x59/0xb0 [rds_tcp]
  tcp_data_queue+0x39d/0x5b0
  tcp_rcv_established+0x2e5/0x660
  tcp_v4_do_rcv+0x122/0x220
  tcp_v4_rcv+0x8b7/0x980
        :
In the above case, it is not fatal to encounter a NULL value for
ready- we should just drop the packet and let the flush of the
acceptor thread finish gracefully.

In general, the tear-down sequence for listen() and accept() socket
that is ensured by this commit is:
     rtn->rds_tcp_listen_sock = NULL; /* prevent any new accepts */
     In rds_tcp_listen_stop():
         serialize with, and prevent, further callbacks using lock_sock()
         flush rds_wq
         flush acceptor workq
         sock_release(listen socket)

Orabug: 26289770

(Cherry-pick of upstream commit b21dd4506b71bdb9c5a20e759255cd2513ea7ebe)

Signed-off-by: Sowmini Varadhan <sowmini.varadhan@oracle.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/rds/tcp.c
net/rds/tcp.h
net/rds/tcp_listen.c