diff mbox series

[net] dccp/tcp: fix ireq->opt races

Message ID 1508269854.31614.114.camel@edumazet-glaptop3.roam.corp.google.com
State Superseded, archived
Delegated to: David Miller
Headers show
Series [net] dccp/tcp: fix ireq->opt races | expand

Commit Message

Eric Dumazet Oct. 17, 2017, 7:50 p.m. UTC
From: Eric Dumazet <edumazet@google.com>

syzkaller found another bug in DCCP/TCP stacks [1]

For the reasons explained in commit ce1050089c96 ("tcp/dccp: fix
ireq->pktopts race"), we need to make sure we do not access
ireq->opt unless we own the request sock.

[1]
BUG: KASAN: use-after-free in ip_queue_xmit+0x1687/0x18e0 net/ipv4/ip_output.c:474
Read of size 1 at addr ffff8801c951039c by task syz-executor5/3295

CPU: 1 PID: 3295 Comm: syz-executor5 Not tainted 4.14.0-rc4+ #80
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
Call Trace:
 __dump_stack lib/dump_stack.c:16 [inline]
 dump_stack+0x194/0x257 lib/dump_stack.c:52
 print_address_description+0x73/0x250 mm/kasan/report.c:252
 kasan_report_error mm/kasan/report.c:351 [inline]
 kasan_report+0x25b/0x340 mm/kasan/report.c:409
 __asan_report_load1_noabort+0x14/0x20 mm/kasan/report.c:427
 ip_queue_xmit+0x1687/0x18e0 net/ipv4/ip_output.c:474
 tcp_transmit_skb+0x1ab7/0x3840 net/ipv4/tcp_output.c:1135
 tcp_send_ack.part.37+0x3bb/0x650 net/ipv4/tcp_output.c:3587
 tcp_send_ack+0x49/0x60 net/ipv4/tcp_output.c:3557
 __tcp_ack_snd_check+0x2c6/0x4b0 net/ipv4/tcp_input.c:5072
 tcp_ack_snd_check net/ipv4/tcp_input.c:5085 [inline]
 tcp_rcv_state_process+0x2eff/0x4850 net/ipv4/tcp_input.c:6071
 tcp_child_process+0x342/0x990 net/ipv4/tcp_minisocks.c:816
 tcp_v4_rcv+0x1827/0x2f80 net/ipv4/tcp_ipv4.c:1682
 ip_local_deliver_finish+0x2e2/0xba0 net/ipv4/ip_input.c:216
 NF_HOOK include/linux/netfilter.h:249 [inline]
 ip_local_deliver+0x1ce/0x6e0 net/ipv4/ip_input.c:257
 dst_input include/net/dst.h:464 [inline]
 ip_rcv_finish+0x887/0x19a0 net/ipv4/ip_input.c:397
 NF_HOOK include/linux/netfilter.h:249 [inline]
 ip_rcv+0xc3f/0x1820 net/ipv4/ip_input.c:493
 __netif_receive_skb_core+0x1a3e/0x34b0 net/core/dev.c:4476
 __netif_receive_skb+0x2c/0x1b0 net/core/dev.c:4514
 netif_receive_skb_internal+0x10b/0x670 net/core/dev.c:4587
 netif_receive_skb+0xae/0x390 net/core/dev.c:4611
 tun_rx_batched.isra.50+0x5ed/0x860 drivers/net/tun.c:1372
 tun_get_user+0x249c/0x36d0 drivers/net/tun.c:1766
 tun_chr_write_iter+0xbf/0x160 drivers/net/tun.c:1792
 call_write_iter include/linux/fs.h:1770 [inline]
 new_sync_write fs/read_write.c:468 [inline]
 __vfs_write+0x68a/0x970 fs/read_write.c:481
 vfs_write+0x18f/0x510 fs/read_write.c:543
 SYSC_write fs/read_write.c:588 [inline]
 SyS_write+0xef/0x220 fs/read_write.c:580
 entry_SYSCALL_64_fastpath+0x1f/0xbe
RIP: 0033:0x40c341
RSP: 002b:00007f469523ec10 EFLAGS: 00000293 ORIG_RAX: 0000000000000001
RAX: ffffffffffffffda RBX: 0000000000718000 RCX: 000000000040c341
RDX: 0000000000000037 RSI: 0000000020004000 RDI: 0000000000000015
RBP: 0000000000000086 R08: 0000000000000000 R09: 0000000000000000
R10: 00000000000f4240 R11: 0000000000000293 R12: 00000000004b7fd1
R13: 00000000ffffffff R14: 0000000020000000 R15: 0000000000025000

Allocated by task 3295:
 save_stack_trace+0x16/0x20 arch/x86/kernel/stacktrace.c:59
 save_stack+0x43/0xd0 mm/kasan/kasan.c:447
 set_track mm/kasan/kasan.c:459 [inline]
 kasan_kmalloc+0xad/0xe0 mm/kasan/kasan.c:551
 __do_kmalloc mm/slab.c:3725 [inline]
 __kmalloc+0x162/0x760 mm/slab.c:3734
 kmalloc include/linux/slab.h:498 [inline]
 tcp_v4_save_options include/net/tcp.h:1962 [inline]
 tcp_v4_init_req+0x2d3/0x3e0 net/ipv4/tcp_ipv4.c:1271
 tcp_conn_request+0xf6d/0x3410 net/ipv4/tcp_input.c:6283
 tcp_v4_conn_request+0x157/0x210 net/ipv4/tcp_ipv4.c:1313
 tcp_rcv_state_process+0x8ea/0x4850 net/ipv4/tcp_input.c:5857
 tcp_v4_do_rcv+0x55c/0x7d0 net/ipv4/tcp_ipv4.c:1482
 tcp_v4_rcv+0x2d10/0x2f80 net/ipv4/tcp_ipv4.c:1711
 ip_local_deliver_finish+0x2e2/0xba0 net/ipv4/ip_input.c:216
 NF_HOOK include/linux/netfilter.h:249 [inline]
 ip_local_deliver+0x1ce/0x6e0 net/ipv4/ip_input.c:257
 dst_input include/net/dst.h:464 [inline]
 ip_rcv_finish+0x887/0x19a0 net/ipv4/ip_input.c:397
 NF_HOOK include/linux/netfilter.h:249 [inline]
 ip_rcv+0xc3f/0x1820 net/ipv4/ip_input.c:493
 __netif_receive_skb_core+0x1a3e/0x34b0 net/core/dev.c:4476
 __netif_receive_skb+0x2c/0x1b0 net/core/dev.c:4514
 netif_receive_skb_internal+0x10b/0x670 net/core/dev.c:4587
 netif_receive_skb+0xae/0x390 net/core/dev.c:4611
 tun_rx_batched.isra.50+0x5ed/0x860 drivers/net/tun.c:1372
 tun_get_user+0x249c/0x36d0 drivers/net/tun.c:1766
 tun_chr_write_iter+0xbf/0x160 drivers/net/tun.c:1792
 call_write_iter include/linux/fs.h:1770 [inline]
 new_sync_write fs/read_write.c:468 [inline]
 __vfs_write+0x68a/0x970 fs/read_write.c:481
 vfs_write+0x18f/0x510 fs/read_write.c:543
 SYSC_write fs/read_write.c:588 [inline]
 SyS_write+0xef/0x220 fs/read_write.c:580
 entry_SYSCALL_64_fastpath+0x1f/0xbe

Freed by task 3306:
 save_stack_trace+0x16/0x20 arch/x86/kernel/stacktrace.c:59
 save_stack+0x43/0xd0 mm/kasan/kasan.c:447
 set_track mm/kasan/kasan.c:459 [inline]
 kasan_slab_free+0x71/0xc0 mm/kasan/kasan.c:524
 __cache_free mm/slab.c:3503 [inline]
 kfree+0xca/0x250 mm/slab.c:3820
 inet_sock_destruct+0x59d/0x950 net/ipv4/af_inet.c:157
 __sk_destruct+0xfd/0x910 net/core/sock.c:1560
 sk_destruct+0x47/0x80 net/core/sock.c:1595
 __sk_free+0x57/0x230 net/core/sock.c:1603
 sk_free+0x2a/0x40 net/core/sock.c:1614
 sock_put include/net/sock.h:1652 [inline]
 inet_csk_complete_hashdance+0xd5/0xf0 net/ipv4/inet_connection_sock.c:959
 tcp_check_req+0xf4d/0x1620 net/ipv4/tcp_minisocks.c:765
 tcp_v4_rcv+0x17f6/0x2f80 net/ipv4/tcp_ipv4.c:1675
 ip_local_deliver_finish+0x2e2/0xba0 net/ipv4/ip_input.c:216
 NF_HOOK include/linux/netfilter.h:249 [inline]
 ip_local_deliver+0x1ce/0x6e0 net/ipv4/ip_input.c:257
 dst_input include/net/dst.h:464 [inline]
 ip_rcv_finish+0x887/0x19a0 net/ipv4/ip_input.c:397
 NF_HOOK include/linux/netfilter.h:249 [inline]
 ip_rcv+0xc3f/0x1820 net/ipv4/ip_input.c:493
 __netif_receive_skb_core+0x1a3e/0x34b0 net/core/dev.c:4476
 __netif_receive_skb+0x2c/0x1b0 net/core/dev.c:4514
 netif_receive_skb_internal+0x10b/0x670 net/core/dev.c:4587
 netif_receive_skb+0xae/0x390 net/core/dev.c:4611
 tun_rx_batched.isra.50+0x5ed/0x860 drivers/net/tun.c:1372
 tun_get_user+0x249c/0x36d0 drivers/net/tun.c:1766
 tun_chr_write_iter+0xbf/0x160 drivers/net/tun.c:1792
 call_write_iter include/linux/fs.h:1770 [inline]
 new_sync_write fs/read_write.c:468 [inline]
 __vfs_write+0x68a/0x970 fs/read_write.c:481
 vfs_write+0x18f/0x510 fs/read_write.c:543
 SYSC_write fs/read_write.c:588 [inline]
 SyS_write+0xef/0x220 fs/read_write.c:580
 entry_SYSCALL_64_fastpath+0x1f/0xbe

The buggy address belongs to the object at ffff8801c9510380
 which belongs to the cache kmalloc-64 of size 64
The buggy address is located 28 bytes inside of
 64-byte region [ffff8801c9510380, ffff8801c95103c0)
The buggy address belongs to the page:
page:ffffea0007254400 count:1 mapcount:0 mapping:ffff8801c9510000 index:0x0
flags: 0x200000000000100(slab)
raw: 0200000000000100 ffff8801c9510000 0000000000000000 0000000100000020
raw: ffffea0007264f60 ffffea00072e2ae0 ffff8801dac00340 0000000000000000
page dumped because: kasan: bad access detected

Memory state around the buggy address:
 ffff8801c9510280: fb fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc
 ffff8801c9510300: fb fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc
>ffff8801c9510380: fb fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc
                            ^
 ffff8801c9510400: 00 00 00 00 00 fc fc fc fc fc fc fc fc fc fc fc
 ffff8801c9510480: 00 00 00 00 00 00 fc fc fc fc fc fc fc fc fc fc

Comments

Eric Dumazet Oct. 17, 2017, 7:53 p.m. UTC | #1
On Tue, 2017-10-17 at 12:50 -0700, Eric Dumazet wrote:
> From: Eric Dumazet <edumazet@google.com>
> 
> syzkaller found another bug in DCCP/TCP stacks [1]
> 
> For the reasons explained in commit ce1050089c96 ("tcp/dccp: fix
> ireq->pktopts race"), we need to make sure we do not access
> ireq->opt unless we own the request sock.


Arg, I will send a v2 without the silly lines that confuse patchwork.
kernel test robot Oct. 20, 2017, 4:53 p.m. UTC | #2
Hi Eric,

[auto build test WARNING on net/master]

url:    https://github.com/0day-ci/linux/commits/Eric-Dumazet/dccp-tcp-fix-ireq-opt-races/20171021-001234
config: ia64-allmodconfig (attached as .config)
compiler: ia64-linux-gcc (GCC) 6.2.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=ia64 

All warnings (new ones prefixed by >>):

   In file included from arch/ia64/include/uapi/asm/intrinsics.h:21:0,
                    from arch/ia64/include/asm/intrinsics.h:10,
                    from arch/ia64/include/asm/atomic.h:17,
                    from include/linux/atomic.h:4,
                    from include/linux/rcupdate.h:38,
                    from net/ipv4/cipso_ipv4.c:40:
   net/ipv4/cipso_ipv4.c: In function 'cipso_v4_req_setattr':
   net/ipv4/cipso_ipv4.c:1954:22: error: 'struct inet_request_sock' has no member named 'opt'
     opt = xchg(&req_inet->opt, opt);
                         ^
   arch/ia64/include/uapi/asm/cmpxchg.h:56:16: note: in definition of macro 'xchg'
    ((__typeof__(*(ptr))) __xchg((unsigned long) (x), (ptr), sizeof(*(ptr))))
                   ^~~
   net/ipv4/cipso_ipv4.c:1954:22: error: 'struct inet_request_sock' has no member named 'opt'
     opt = xchg(&req_inet->opt, opt);
                         ^
   arch/ia64/include/uapi/asm/cmpxchg.h:33:10: note: in definition of macro '__xchg'
     switch (size) {       \
             ^~~~
>> net/ipv4/cipso_ipv4.c:1954:8: note: in expansion of macro 'xchg'
     opt = xchg(&req_inet->opt, opt);
           ^~~~
   In file included from arch/ia64/include/asm/gcc_intrin.h:9:0,
                    from arch/ia64/include/uapi/asm/intrinsics.h:19,
                    from arch/ia64/include/asm/intrinsics.h:10,
                    from arch/ia64/include/asm/atomic.h:17,
                    from include/linux/atomic.h:4,
                    from include/linux/rcupdate.h:38,
                    from net/ipv4/cipso_ipv4.c:40:
   net/ipv4/cipso_ipv4.c:1954:22: error: 'struct inet_request_sock' has no member named 'opt'
     opt = xchg(&req_inet->opt, opt);
                         ^
   arch/ia64/include/uapi/asm/gcc_intrin.h:279:40: note: in definition of macro 'ia64_xchg1'
            : "=r" (ia64_intri_res) : "r" (ptr), "r" (x) : "memory"); \
                                           ^~~
>> arch/ia64/include/uapi/asm/cmpxchg.h:56:23: note: in expansion of macro '__xchg'
    ((__typeof__(*(ptr))) __xchg((unsigned long) (x), (ptr), sizeof(*(ptr))))
                          ^~~~~~
>> net/ipv4/cipso_ipv4.c:1954:8: note: in expansion of macro 'xchg'
     opt = xchg(&req_inet->opt, opt);
           ^~~~
   net/ipv4/cipso_ipv4.c:1954:22: error: 'struct inet_request_sock' has no member named 'opt'
     opt = xchg(&req_inet->opt, opt);
                         ^
   arch/ia64/include/uapi/asm/gcc_intrin.h:287:16: note: in definition of macro 'ia64_xchg2'
            : "r" (ptr), "r" (x) : "memory");   \
                   ^~~
>> arch/ia64/include/uapi/asm/cmpxchg.h:56:23: note: in expansion of macro '__xchg'
    ((__typeof__(*(ptr))) __xchg((unsigned long) (x), (ptr), sizeof(*(ptr))))
                          ^~~~~~
>> net/ipv4/cipso_ipv4.c:1954:8: note: in expansion of macro 'xchg'
     opt = xchg(&req_inet->opt, opt);
           ^~~~
   net/ipv4/cipso_ipv4.c:1954:22: error: 'struct inet_request_sock' has no member named 'opt'
     opt = xchg(&req_inet->opt, opt);
                         ^
   arch/ia64/include/uapi/asm/gcc_intrin.h:295:16: note: in definition of macro 'ia64_xchg4'
            : "r" (ptr), "r" (x) : "memory");   \
                   ^~~
>> arch/ia64/include/uapi/asm/cmpxchg.h:56:23: note: in expansion of macro '__xchg'
    ((__typeof__(*(ptr))) __xchg((unsigned long) (x), (ptr), sizeof(*(ptr))))
                          ^~~~~~
>> net/ipv4/cipso_ipv4.c:1954:8: note: in expansion of macro 'xchg'
     opt = xchg(&req_inet->opt, opt);
           ^~~~
   net/ipv4/cipso_ipv4.c:1954:22: error: 'struct inet_request_sock' has no member named 'opt'
     opt = xchg(&req_inet->opt, opt);
                         ^
   arch/ia64/include/uapi/asm/gcc_intrin.h:303:16: note: in definition of macro 'ia64_xchg8'
            : "r" (ptr), "r" (x) : "memory");   \
                   ^~~
>> arch/ia64/include/uapi/asm/cmpxchg.h:56:23: note: in expansion of macro '__xchg'
    ((__typeof__(*(ptr))) __xchg((unsigned long) (x), (ptr), sizeof(*(ptr))))
                          ^~~~~~
>> net/ipv4/cipso_ipv4.c:1954:8: note: in expansion of macro 'xchg'
     opt = xchg(&req_inet->opt, opt);
           ^~~~
   net/ipv4/cipso_ipv4.c: In function 'cipso_v4_req_delattr':
   net/ipv4/cipso_ipv4.c:2073:16: error: 'struct inet_request_sock' has no member named 'opt'
     opt = req_inet->opt;
                   ^~
   net/ipv4/cipso_ipv4.c:2077:27: error: 'struct inet_request_sock' has no member named 'opt'
     cipso_v4_delopt(&req_inet->opt);
                              ^~
--
   In file included from arch/ia64/include/uapi/asm/intrinsics.h:21:0,
                    from arch/ia64/include/asm/intrinsics.h:10,
                    from arch/ia64/include/asm/atomic.h:17,
                    from include/linux/atomic.h:4,
                    from include/linux/rcupdate.h:38,
                    from net//ipv4/cipso_ipv4.c:40:
   net//ipv4/cipso_ipv4.c: In function 'cipso_v4_req_setattr':
   net//ipv4/cipso_ipv4.c:1954:22: error: 'struct inet_request_sock' has no member named 'opt'
     opt = xchg(&req_inet->opt, opt);
                         ^
   arch/ia64/include/uapi/asm/cmpxchg.h:56:16: note: in definition of macro 'xchg'
    ((__typeof__(*(ptr))) __xchg((unsigned long) (x), (ptr), sizeof(*(ptr))))
                   ^~~
   net//ipv4/cipso_ipv4.c:1954:22: error: 'struct inet_request_sock' has no member named 'opt'
     opt = xchg(&req_inet->opt, opt);
                         ^
   arch/ia64/include/uapi/asm/cmpxchg.h:33:10: note: in definition of macro '__xchg'
     switch (size) {       \
             ^~~~
   net//ipv4/cipso_ipv4.c:1954:8: note: in expansion of macro 'xchg'
     opt = xchg(&req_inet->opt, opt);
           ^~~~
   In file included from arch/ia64/include/asm/gcc_intrin.h:9:0,
                    from arch/ia64/include/uapi/asm/intrinsics.h:19,
                    from arch/ia64/include/asm/intrinsics.h:10,
                    from arch/ia64/include/asm/atomic.h:17,
                    from include/linux/atomic.h:4,
                    from include/linux/rcupdate.h:38,
                    from net//ipv4/cipso_ipv4.c:40:
   net//ipv4/cipso_ipv4.c:1954:22: error: 'struct inet_request_sock' has no member named 'opt'
     opt = xchg(&req_inet->opt, opt);
                         ^
   arch/ia64/include/uapi/asm/gcc_intrin.h:279:40: note: in definition of macro 'ia64_xchg1'
            : "=r" (ia64_intri_res) : "r" (ptr), "r" (x) : "memory"); \
                                           ^~~
>> arch/ia64/include/uapi/asm/cmpxchg.h:56:23: note: in expansion of macro '__xchg'
    ((__typeof__(*(ptr))) __xchg((unsigned long) (x), (ptr), sizeof(*(ptr))))
                          ^~~~~~
   net//ipv4/cipso_ipv4.c:1954:8: note: in expansion of macro 'xchg'
     opt = xchg(&req_inet->opt, opt);
           ^~~~
   net//ipv4/cipso_ipv4.c:1954:22: error: 'struct inet_request_sock' has no member named 'opt'
     opt = xchg(&req_inet->opt, opt);
                         ^
   arch/ia64/include/uapi/asm/gcc_intrin.h:287:16: note: in definition of macro 'ia64_xchg2'
            : "r" (ptr), "r" (x) : "memory");   \
                   ^~~
>> arch/ia64/include/uapi/asm/cmpxchg.h:56:23: note: in expansion of macro '__xchg'
    ((__typeof__(*(ptr))) __xchg((unsigned long) (x), (ptr), sizeof(*(ptr))))
                          ^~~~~~
   net//ipv4/cipso_ipv4.c:1954:8: note: in expansion of macro 'xchg'
     opt = xchg(&req_inet->opt, opt);
           ^~~~
   net//ipv4/cipso_ipv4.c:1954:22: error: 'struct inet_request_sock' has no member named 'opt'
     opt = xchg(&req_inet->opt, opt);
                         ^
   arch/ia64/include/uapi/asm/gcc_intrin.h:295:16: note: in definition of macro 'ia64_xchg4'
            : "r" (ptr), "r" (x) : "memory");   \
                   ^~~
>> arch/ia64/include/uapi/asm/cmpxchg.h:56:23: note: in expansion of macro '__xchg'
    ((__typeof__(*(ptr))) __xchg((unsigned long) (x), (ptr), sizeof(*(ptr))))
                          ^~~~~~
   net//ipv4/cipso_ipv4.c:1954:8: note: in expansion of macro 'xchg'
     opt = xchg(&req_inet->opt, opt);
           ^~~~
   net//ipv4/cipso_ipv4.c:1954:22: error: 'struct inet_request_sock' has no member named 'opt'
     opt = xchg(&req_inet->opt, opt);
                         ^
   arch/ia64/include/uapi/asm/gcc_intrin.h:303:16: note: in definition of macro 'ia64_xchg8'
            : "r" (ptr), "r" (x) : "memory");   \
                   ^~~
>> arch/ia64/include/uapi/asm/cmpxchg.h:56:23: note: in expansion of macro '__xchg'
    ((__typeof__(*(ptr))) __xchg((unsigned long) (x), (ptr), sizeof(*(ptr))))
                          ^~~~~~
   net//ipv4/cipso_ipv4.c:1954:8: note: in expansion of macro 'xchg'
     opt = xchg(&req_inet->opt, opt);
           ^~~~
   net//ipv4/cipso_ipv4.c: In function 'cipso_v4_req_delattr':
   net//ipv4/cipso_ipv4.c:2073:16: error: 'struct inet_request_sock' has no member named 'opt'
     opt = req_inet->opt;
                   ^~
   net//ipv4/cipso_ipv4.c:2077:27: error: 'struct inet_request_sock' has no member named 'opt'
     cipso_v4_delopt(&req_inet->opt);
                              ^~

vim +/xchg +1954 net/ipv4/cipso_ipv4.c

446fda4f2 Paul Moore       2006-08-03  1898  
446fda4f2 Paul Moore       2006-08-03  1899  /**
389fb800a Paul Moore       2009-03-27  1900   * cipso_v4_req_setattr - Add a CIPSO option to a connection request socket
389fb800a Paul Moore       2009-03-27  1901   * @req: the connection request socket
389fb800a Paul Moore       2009-03-27  1902   * @doi_def: the CIPSO DOI to use
389fb800a Paul Moore       2009-03-27  1903   * @secattr: the specific security attributes of the socket
014ab19a6 Paul Moore       2008-10-10  1904   *
014ab19a6 Paul Moore       2008-10-10  1905   * Description:
389fb800a Paul Moore       2009-03-27  1906   * Set the CIPSO option on the given socket using the DOI definition and
389fb800a Paul Moore       2009-03-27  1907   * security attributes passed to the function.  Returns zero on success and
389fb800a Paul Moore       2009-03-27  1908   * negative values on failure.
014ab19a6 Paul Moore       2008-10-10  1909   *
014ab19a6 Paul Moore       2008-10-10  1910   */
389fb800a Paul Moore       2009-03-27  1911  int cipso_v4_req_setattr(struct request_sock *req,
389fb800a Paul Moore       2009-03-27  1912  			 const struct cipso_v4_doi *doi_def,
389fb800a Paul Moore       2009-03-27  1913  			 const struct netlbl_lsm_secattr *secattr)
014ab19a6 Paul Moore       2008-10-10  1914  {
389fb800a Paul Moore       2009-03-27  1915  	int ret_val = -EPERM;
389fb800a Paul Moore       2009-03-27  1916  	unsigned char *buf = NULL;
389fb800a Paul Moore       2009-03-27  1917  	u32 buf_len;
389fb800a Paul Moore       2009-03-27  1918  	u32 opt_len;
f6d8bd051 Eric Dumazet     2011-04-21  1919  	struct ip_options_rcu *opt = NULL;
389fb800a Paul Moore       2009-03-27  1920  	struct inet_request_sock *req_inet;
014ab19a6 Paul Moore       2008-10-10  1921  
389fb800a Paul Moore       2009-03-27  1922  	/* We allocate the maximum CIPSO option size here so we are probably
389fb800a Paul Moore       2009-03-27  1923  	 * being a little wasteful, but it makes our life _much_ easier later
389fb800a Paul Moore       2009-03-27  1924  	 * on and after all we are only talking about 40 bytes. */
389fb800a Paul Moore       2009-03-27  1925  	buf_len = CIPSO_V4_OPT_LEN_MAX;
389fb800a Paul Moore       2009-03-27  1926  	buf = kmalloc(buf_len, GFP_ATOMIC);
51456b291 Ian Morris       2015-04-03  1927  	if (!buf) {
389fb800a Paul Moore       2009-03-27  1928  		ret_val = -ENOMEM;
389fb800a Paul Moore       2009-03-27  1929  		goto req_setattr_failure;
389fb800a Paul Moore       2009-03-27  1930  	}
389fb800a Paul Moore       2009-03-27  1931  
389fb800a Paul Moore       2009-03-27  1932  	ret_val = cipso_v4_genopt(buf, buf_len, doi_def, secattr);
389fb800a Paul Moore       2009-03-27  1933  	if (ret_val < 0)
389fb800a Paul Moore       2009-03-27  1934  		goto req_setattr_failure;
389fb800a Paul Moore       2009-03-27  1935  	buf_len = ret_val;
389fb800a Paul Moore       2009-03-27  1936  
389fb800a Paul Moore       2009-03-27  1937  	/* We can't use ip_options_get() directly because it makes a call to
389fb800a Paul Moore       2009-03-27  1938  	 * ip_options_get_alloc() which allocates memory with GFP_KERNEL and
389fb800a Paul Moore       2009-03-27  1939  	 * we won't always have CAP_NET_RAW even though we _always_ want to
389fb800a Paul Moore       2009-03-27  1940  	 * set the IPOPT_CIPSO option. */
389fb800a Paul Moore       2009-03-27  1941  	opt_len = (buf_len + 3) & ~3;
389fb800a Paul Moore       2009-03-27  1942  	opt = kzalloc(sizeof(*opt) + opt_len, GFP_ATOMIC);
51456b291 Ian Morris       2015-04-03  1943  	if (!opt) {
389fb800a Paul Moore       2009-03-27  1944  		ret_val = -ENOMEM;
389fb800a Paul Moore       2009-03-27  1945  		goto req_setattr_failure;
389fb800a Paul Moore       2009-03-27  1946  	}
f6d8bd051 Eric Dumazet     2011-04-21  1947  	memcpy(opt->opt.__data, buf, buf_len);
f6d8bd051 Eric Dumazet     2011-04-21  1948  	opt->opt.optlen = opt_len;
f6d8bd051 Eric Dumazet     2011-04-21  1949  	opt->opt.cipso = sizeof(struct iphdr);
389fb800a Paul Moore       2009-03-27  1950  	kfree(buf);
389fb800a Paul Moore       2009-03-27  1951  	buf = NULL;
389fb800a Paul Moore       2009-03-27  1952  
389fb800a Paul Moore       2009-03-27  1953  	req_inet = inet_rsk(req);
389fb800a Paul Moore       2009-03-27 @1954  	opt = xchg(&req_inet->opt, opt);
f6d8bd051 Eric Dumazet     2011-04-21  1955  	if (opt)
4f9c8c1b0 Paul E. McKenney 2012-01-06  1956  		kfree_rcu(opt, rcu);
389fb800a Paul Moore       2009-03-27  1957  
389fb800a Paul Moore       2009-03-27  1958  	return 0;
389fb800a Paul Moore       2009-03-27  1959  
389fb800a Paul Moore       2009-03-27  1960  req_setattr_failure:
389fb800a Paul Moore       2009-03-27  1961  	kfree(buf);
389fb800a Paul Moore       2009-03-27  1962  	kfree(opt);
389fb800a Paul Moore       2009-03-27  1963  	return ret_val;
389fb800a Paul Moore       2009-03-27  1964  }
389fb800a Paul Moore       2009-03-27  1965  

:::::: The code at line 1954 was first introduced by commit
:::::: 389fb800ac8be2832efedd19978a2b8ced37eb61 netlabel: Label incoming TCP connections correctly in SELinux

:::::: TO: Paul Moore <paul.moore@hp.com>
:::::: CC: James Morris <jmorris@namei.org>

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
kernel test robot Oct. 20, 2017, 4:53 p.m. UTC | #3
Hi Eric,

[auto build test ERROR on net/master]

url:    https://github.com/0day-ci/linux/commits/Eric-Dumazet/dccp-tcp-fix-ireq-opt-races/20171021-001234
config: blackfin-allyesconfig (attached as .config)
compiler: bfin-uclinux-gcc (GCC) 6.2.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=blackfin 

All errors (new ones prefixed by >>):

   In file included from arch/blackfin/include/asm/atomic.h:10:0,
                    from include/linux/atomic.h:4,
                    from include/linux/rcupdate.h:38,
                    from net/ipv4/cipso_ipv4.c:40:
   net/ipv4/cipso_ipv4.c: In function 'cipso_v4_req_setattr':
>> net/ipv4/cipso_ipv4.c:1954:22: error: 'struct inet_request_sock' has no member named 'opt'
     opt = xchg(&req_inet->opt, opt);
                         ^
   arch/blackfin/include/asm/cmpxchg.h:130:37: note: in definition of macro 'xchg'
    #define xchg(ptr, x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x), (ptr), sizeof(*(ptr))))
                                        ^~~
>> net/ipv4/cipso_ipv4.c:1954:22: error: 'struct inet_request_sock' has no member named 'opt'
     opt = xchg(&req_inet->opt, opt);
                         ^
   arch/blackfin/include/asm/cmpxchg.h:130:71: note: in definition of macro 'xchg'
    #define xchg(ptr, x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x), (ptr), sizeof(*(ptr))))
                                                                          ^~~
>> net/ipv4/cipso_ipv4.c:1954:22: error: 'struct inet_request_sock' has no member named 'opt'
     opt = xchg(&req_inet->opt, opt);
                         ^
   arch/blackfin/include/asm/cmpxchg.h:130:86: note: in definition of macro 'xchg'
    #define xchg(ptr, x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x), (ptr), sizeof(*(ptr))))
                                                                                         ^~~
   net/ipv4/cipso_ipv4.c: In function 'cipso_v4_req_delattr':
   net/ipv4/cipso_ipv4.c:2073:16: error: 'struct inet_request_sock' has no member named 'opt'
     opt = req_inet->opt;
                   ^~
   net/ipv4/cipso_ipv4.c:2077:27: error: 'struct inet_request_sock' has no member named 'opt'
     cipso_v4_delopt(&req_inet->opt);
                              ^~

vim +1954 net/ipv4/cipso_ipv4.c

446fda4f2 Paul Moore       2006-08-03  1898  
446fda4f2 Paul Moore       2006-08-03  1899  /**
389fb800a Paul Moore       2009-03-27  1900   * cipso_v4_req_setattr - Add a CIPSO option to a connection request socket
389fb800a Paul Moore       2009-03-27  1901   * @req: the connection request socket
389fb800a Paul Moore       2009-03-27  1902   * @doi_def: the CIPSO DOI to use
389fb800a Paul Moore       2009-03-27  1903   * @secattr: the specific security attributes of the socket
014ab19a6 Paul Moore       2008-10-10  1904   *
014ab19a6 Paul Moore       2008-10-10  1905   * Description:
389fb800a Paul Moore       2009-03-27  1906   * Set the CIPSO option on the given socket using the DOI definition and
389fb800a Paul Moore       2009-03-27  1907   * security attributes passed to the function.  Returns zero on success and
389fb800a Paul Moore       2009-03-27  1908   * negative values on failure.
014ab19a6 Paul Moore       2008-10-10  1909   *
014ab19a6 Paul Moore       2008-10-10  1910   */
389fb800a Paul Moore       2009-03-27  1911  int cipso_v4_req_setattr(struct request_sock *req,
389fb800a Paul Moore       2009-03-27  1912  			 const struct cipso_v4_doi *doi_def,
389fb800a Paul Moore       2009-03-27  1913  			 const struct netlbl_lsm_secattr *secattr)
014ab19a6 Paul Moore       2008-10-10  1914  {
389fb800a Paul Moore       2009-03-27  1915  	int ret_val = -EPERM;
389fb800a Paul Moore       2009-03-27  1916  	unsigned char *buf = NULL;
389fb800a Paul Moore       2009-03-27  1917  	u32 buf_len;
389fb800a Paul Moore       2009-03-27  1918  	u32 opt_len;
f6d8bd051 Eric Dumazet     2011-04-21  1919  	struct ip_options_rcu *opt = NULL;
389fb800a Paul Moore       2009-03-27  1920  	struct inet_request_sock *req_inet;
014ab19a6 Paul Moore       2008-10-10  1921  
389fb800a Paul Moore       2009-03-27  1922  	/* We allocate the maximum CIPSO option size here so we are probably
389fb800a Paul Moore       2009-03-27  1923  	 * being a little wasteful, but it makes our life _much_ easier later
389fb800a Paul Moore       2009-03-27  1924  	 * on and after all we are only talking about 40 bytes. */
389fb800a Paul Moore       2009-03-27  1925  	buf_len = CIPSO_V4_OPT_LEN_MAX;
389fb800a Paul Moore       2009-03-27  1926  	buf = kmalloc(buf_len, GFP_ATOMIC);
51456b291 Ian Morris       2015-04-03  1927  	if (!buf) {
389fb800a Paul Moore       2009-03-27  1928  		ret_val = -ENOMEM;
389fb800a Paul Moore       2009-03-27  1929  		goto req_setattr_failure;
389fb800a Paul Moore       2009-03-27  1930  	}
389fb800a Paul Moore       2009-03-27  1931  
389fb800a Paul Moore       2009-03-27  1932  	ret_val = cipso_v4_genopt(buf, buf_len, doi_def, secattr);
389fb800a Paul Moore       2009-03-27  1933  	if (ret_val < 0)
389fb800a Paul Moore       2009-03-27  1934  		goto req_setattr_failure;
389fb800a Paul Moore       2009-03-27  1935  	buf_len = ret_val;
389fb800a Paul Moore       2009-03-27  1936  
389fb800a Paul Moore       2009-03-27  1937  	/* We can't use ip_options_get() directly because it makes a call to
389fb800a Paul Moore       2009-03-27  1938  	 * ip_options_get_alloc() which allocates memory with GFP_KERNEL and
389fb800a Paul Moore       2009-03-27  1939  	 * we won't always have CAP_NET_RAW even though we _always_ want to
389fb800a Paul Moore       2009-03-27  1940  	 * set the IPOPT_CIPSO option. */
389fb800a Paul Moore       2009-03-27  1941  	opt_len = (buf_len + 3) & ~3;
389fb800a Paul Moore       2009-03-27  1942  	opt = kzalloc(sizeof(*opt) + opt_len, GFP_ATOMIC);
51456b291 Ian Morris       2015-04-03  1943  	if (!opt) {
389fb800a Paul Moore       2009-03-27  1944  		ret_val = -ENOMEM;
389fb800a Paul Moore       2009-03-27  1945  		goto req_setattr_failure;
389fb800a Paul Moore       2009-03-27  1946  	}
f6d8bd051 Eric Dumazet     2011-04-21  1947  	memcpy(opt->opt.__data, buf, buf_len);
f6d8bd051 Eric Dumazet     2011-04-21  1948  	opt->opt.optlen = opt_len;
f6d8bd051 Eric Dumazet     2011-04-21  1949  	opt->opt.cipso = sizeof(struct iphdr);
389fb800a Paul Moore       2009-03-27  1950  	kfree(buf);
389fb800a Paul Moore       2009-03-27  1951  	buf = NULL;
389fb800a Paul Moore       2009-03-27  1952  
389fb800a Paul Moore       2009-03-27  1953  	req_inet = inet_rsk(req);
389fb800a Paul Moore       2009-03-27 @1954  	opt = xchg(&req_inet->opt, opt);
f6d8bd051 Eric Dumazet     2011-04-21  1955  	if (opt)
4f9c8c1b0 Paul E. McKenney 2012-01-06  1956  		kfree_rcu(opt, rcu);
389fb800a Paul Moore       2009-03-27  1957  
389fb800a Paul Moore       2009-03-27  1958  	return 0;
389fb800a Paul Moore       2009-03-27  1959  
389fb800a Paul Moore       2009-03-27  1960  req_setattr_failure:
389fb800a Paul Moore       2009-03-27  1961  	kfree(buf);
389fb800a Paul Moore       2009-03-27  1962  	kfree(opt);
389fb800a Paul Moore       2009-03-27  1963  	return ret_val;
389fb800a Paul Moore       2009-03-27  1964  }
389fb800a Paul Moore       2009-03-27  1965  

:::::: The code at line 1954 was first introduced by commit
:::::: 389fb800ac8be2832efedd19978a2b8ced37eb61 netlabel: Label incoming TCP connections correctly in SELinux

:::::: TO: Paul Moore <paul.moore@hp.com>
:::::: CC: James Morris <jmorris@namei.org>

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
Eric Dumazet Oct. 20, 2017, 5:38 p.m. UTC | #4
On Sat, 2017-10-21 at 00:53 +0800, kbuild test robot wrote:
> Hi Eric,
> 
> [auto build test WARNING on net/master]
> 
> url:    https://github.com/0day-ci/linux/commits/Eric-Dumazet/dccp-tcp-fix-ireq-opt-races/20171021-001234
> config: ia64-allmodconfig (attached as .config)
> compiler: ia64-linux-gcc (GCC) 6.2.0
> reproduce:
>         wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
>         chmod +x ~/bin/make.cross
>         # save the attached .config to linux build tree
>         make.cross ARCH=ia64 

Thanks, v4 of the patch should fix this.

https://patchwork.ozlabs.org/patch/828713/
kernel test robot Oct. 20, 2017, 6:34 p.m. UTC | #5
Hi Eric,

[auto build test WARNING on net/master]

url:    https://github.com/0day-ci/linux/commits/Eric-Dumazet/dccp-tcp-fix-ireq-opt-races/20171021-001234
reproduce:
        # apt-get install sparse
        make ARCH=x86_64 allmodconfig
        make C=1 CF=-D__CHECK_ENDIAN__


sparse warnings: (new ones prefixed by >>)


vim +1954 net/ipv4/cipso_ipv4.c

446fda4f2 Paul Moore       2006-08-03  1898  
446fda4f2 Paul Moore       2006-08-03  1899  /**
389fb800a Paul Moore       2009-03-27  1900   * cipso_v4_req_setattr - Add a CIPSO option to a connection request socket
389fb800a Paul Moore       2009-03-27  1901   * @req: the connection request socket
389fb800a Paul Moore       2009-03-27  1902   * @doi_def: the CIPSO DOI to use
389fb800a Paul Moore       2009-03-27  1903   * @secattr: the specific security attributes of the socket
014ab19a6 Paul Moore       2008-10-10  1904   *
014ab19a6 Paul Moore       2008-10-10  1905   * Description:
389fb800a Paul Moore       2009-03-27  1906   * Set the CIPSO option on the given socket using the DOI definition and
389fb800a Paul Moore       2009-03-27  1907   * security attributes passed to the function.  Returns zero on success and
389fb800a Paul Moore       2009-03-27  1908   * negative values on failure.
014ab19a6 Paul Moore       2008-10-10  1909   *
014ab19a6 Paul Moore       2008-10-10  1910   */
389fb800a Paul Moore       2009-03-27  1911  int cipso_v4_req_setattr(struct request_sock *req,
389fb800a Paul Moore       2009-03-27  1912  			 const struct cipso_v4_doi *doi_def,
389fb800a Paul Moore       2009-03-27  1913  			 const struct netlbl_lsm_secattr *secattr)
014ab19a6 Paul Moore       2008-10-10  1914  {
389fb800a Paul Moore       2009-03-27  1915  	int ret_val = -EPERM;
389fb800a Paul Moore       2009-03-27  1916  	unsigned char *buf = NULL;
389fb800a Paul Moore       2009-03-27  1917  	u32 buf_len;
389fb800a Paul Moore       2009-03-27  1918  	u32 opt_len;
f6d8bd051 Eric Dumazet     2011-04-21  1919  	struct ip_options_rcu *opt = NULL;
389fb800a Paul Moore       2009-03-27  1920  	struct inet_request_sock *req_inet;
014ab19a6 Paul Moore       2008-10-10  1921  
389fb800a Paul Moore       2009-03-27  1922  	/* We allocate the maximum CIPSO option size here so we are probably
389fb800a Paul Moore       2009-03-27  1923  	 * being a little wasteful, but it makes our life _much_ easier later
389fb800a Paul Moore       2009-03-27  1924  	 * on and after all we are only talking about 40 bytes. */
389fb800a Paul Moore       2009-03-27  1925  	buf_len = CIPSO_V4_OPT_LEN_MAX;
389fb800a Paul Moore       2009-03-27  1926  	buf = kmalloc(buf_len, GFP_ATOMIC);
51456b291 Ian Morris       2015-04-03  1927  	if (!buf) {
389fb800a Paul Moore       2009-03-27  1928  		ret_val = -ENOMEM;
389fb800a Paul Moore       2009-03-27  1929  		goto req_setattr_failure;
389fb800a Paul Moore       2009-03-27  1930  	}
389fb800a Paul Moore       2009-03-27  1931  
389fb800a Paul Moore       2009-03-27  1932  	ret_val = cipso_v4_genopt(buf, buf_len, doi_def, secattr);
389fb800a Paul Moore       2009-03-27  1933  	if (ret_val < 0)
389fb800a Paul Moore       2009-03-27  1934  		goto req_setattr_failure;
389fb800a Paul Moore       2009-03-27  1935  	buf_len = ret_val;
389fb800a Paul Moore       2009-03-27  1936  
389fb800a Paul Moore       2009-03-27  1937  	/* We can't use ip_options_get() directly because it makes a call to
389fb800a Paul Moore       2009-03-27  1938  	 * ip_options_get_alloc() which allocates memory with GFP_KERNEL and
389fb800a Paul Moore       2009-03-27  1939  	 * we won't always have CAP_NET_RAW even though we _always_ want to
389fb800a Paul Moore       2009-03-27  1940  	 * set the IPOPT_CIPSO option. */
389fb800a Paul Moore       2009-03-27  1941  	opt_len = (buf_len + 3) & ~3;
389fb800a Paul Moore       2009-03-27  1942  	opt = kzalloc(sizeof(*opt) + opt_len, GFP_ATOMIC);
51456b291 Ian Morris       2015-04-03  1943  	if (!opt) {
389fb800a Paul Moore       2009-03-27  1944  		ret_val = -ENOMEM;
389fb800a Paul Moore       2009-03-27  1945  		goto req_setattr_failure;
389fb800a Paul Moore       2009-03-27  1946  	}
f6d8bd051 Eric Dumazet     2011-04-21  1947  	memcpy(opt->opt.__data, buf, buf_len);
f6d8bd051 Eric Dumazet     2011-04-21  1948  	opt->opt.optlen = opt_len;
f6d8bd051 Eric Dumazet     2011-04-21  1949  	opt->opt.cipso = sizeof(struct iphdr);
389fb800a Paul Moore       2009-03-27  1950  	kfree(buf);
389fb800a Paul Moore       2009-03-27  1951  	buf = NULL;
389fb800a Paul Moore       2009-03-27  1952  
389fb800a Paul Moore       2009-03-27  1953  	req_inet = inet_rsk(req);
389fb800a Paul Moore       2009-03-27 @1954  	opt = xchg(&req_inet->opt, opt);
f6d8bd051 Eric Dumazet     2011-04-21  1955  	if (opt)
4f9c8c1b0 Paul E. McKenney 2012-01-06  1956  		kfree_rcu(opt, rcu);
389fb800a Paul Moore       2009-03-27  1957  
389fb800a Paul Moore       2009-03-27  1958  	return 0;
389fb800a Paul Moore       2009-03-27  1959  
389fb800a Paul Moore       2009-03-27  1960  req_setattr_failure:
389fb800a Paul Moore       2009-03-27  1961  	kfree(buf);
389fb800a Paul Moore       2009-03-27  1962  	kfree(opt);
389fb800a Paul Moore       2009-03-27  1963  	return ret_val;
389fb800a Paul Moore       2009-03-27  1964  }
389fb800a Paul Moore       2009-03-27  1965  

:::::: The code at line 1954 was first introduced by commit
:::::: 389fb800ac8be2832efedd19978a2b8ced37eb61 netlabel: Label incoming TCP connections correctly in SELinux

:::::: TO: Paul Moore <paul.moore@hp.com>
:::::: CC: James Morris <jmorris@namei.org>

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
diff mbox series

Patch

==================================================================

Fixes: e994b2f0fb92 ("tcp: do not lock listener to process SYN packets")
Fixes: 079096f103fa ("tcp/dccp: install syn_recv requests into ehash table")
Signed-off-by: Eric Dumazet <edumazet@google.com>
---
 include/net/inet_sock.h         |    2 +-
 net/dccp/ipv4.c                 |   13 ++++++++-----
 net/ipv4/inet_connection_sock.c |    8 +++-----
 net/ipv4/syncookies.c           |    2 +-
 net/ipv4/tcp_input.c            |    2 +-
 net/ipv4/tcp_ipv4.c             |   22 +++++++++++++---------
 6 files changed, 27 insertions(+), 22 deletions(-)

diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h
index aa95053dfc78d35d04aef276e2a5dce7343f72a0..425752f768d2f1a0efb13964204e07f27609e9db 100644
--- a/include/net/inet_sock.h
+++ b/include/net/inet_sock.h
@@ -96,7 +96,7 @@  struct inet_request_sock {
 	kmemcheck_bitfield_end(flags);
 	u32                     ir_mark;
 	union {
-		struct ip_options_rcu	*opt;
+		struct ip_options_rcu __rcu	*ireq_opt;
 #if IS_ENABLED(CONFIG_IPV6)
 		struct {
 			struct ipv6_txoptions	*ipv6_opt;
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
index 001c08696334bba0ceb896c116e595b814af0667..0490916864f93d5466e87f5b97dc524b3ee57a2e 100644
--- a/net/dccp/ipv4.c
+++ b/net/dccp/ipv4.c
@@ -414,8 +414,7 @@  struct sock *dccp_v4_request_recv_sock(const struct sock *sk,
 	sk_daddr_set(newsk, ireq->ir_rmt_addr);
 	sk_rcv_saddr_set(newsk, ireq->ir_loc_addr);
 	newinet->inet_saddr	= ireq->ir_loc_addr;
-	newinet->inet_opt	= ireq->opt;
-	ireq->opt	   = NULL;
+	RCU_INIT_POINTER(newinet->inet_opt, rcu_dereference(ireq->ireq_opt));
 	newinet->mc_index  = inet_iif(skb);
 	newinet->mc_ttl	   = ip_hdr(skb)->ttl;
 	newinet->inet_id   = jiffies;
@@ -430,7 +429,10 @@  struct sock *dccp_v4_request_recv_sock(const struct sock *sk,
 	if (__inet_inherit_port(sk, newsk) < 0)
 		goto put_and_exit;
 	*own_req = inet_ehash_nolisten(newsk, req_to_sk(req_unhash));
-
+	if (*own_req)
+		ireq->ireq_opt = NULL;
+	else
+		newinet->inet_opt = NULL;
 	return newsk;
 
 exit_overflow:
@@ -441,6 +443,7 @@  struct sock *dccp_v4_request_recv_sock(const struct sock *sk,
 	__NET_INC_STATS(sock_net(sk), LINUX_MIB_LISTENDROPS);
 	return NULL;
 put_and_exit:
+	newinet->inet_opt = NULL;
 	inet_csk_prepare_forced_close(newsk);
 	dccp_done(newsk);
 	goto exit;
@@ -492,7 +495,7 @@  static int dccp_v4_send_response(const struct sock *sk, struct request_sock *req
 							      ireq->ir_rmt_addr);
 		err = ip_build_and_send_pkt(skb, sk, ireq->ir_loc_addr,
 					    ireq->ir_rmt_addr,
-					    ireq->opt);
+					    rcu_dereference(ireq->ireq_opt));
 		err = net_xmit_eval(err);
 	}
 
@@ -548,7 +551,7 @@  static void dccp_v4_ctl_send_reset(const struct sock *sk, struct sk_buff *rxskb)
 static void dccp_v4_reqsk_destructor(struct request_sock *req)
 {
 	dccp_feat_list_purge(&dccp_rsk(req)->dreq_featneg);
-	kfree(inet_rsk(req)->opt);
+	kfree(rcu_dereference_protected(inet_rsk(req)->ireq_opt, 1));
 }
 
 void dccp_syn_ack_timeout(const struct request_sock *req)
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index 67aec7a106860b26c929fea1624d652c87972f04..5ec9136a7c36933cb36e5cd50058eb6cf189a7c3 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -540,9 +540,10 @@  struct dst_entry *inet_csk_route_req(const struct sock *sk,
 {
 	const struct inet_request_sock *ireq = inet_rsk(req);
 	struct net *net = read_pnet(&ireq->ireq_net);
-	struct ip_options_rcu *opt = ireq->opt;
+	struct ip_options_rcu *opt;
 	struct rtable *rt;
 
+	opt = rcu_dereference(ireq->ireq_opt);
 	flowi4_init_output(fl4, ireq->ir_iif, ireq->ir_mark,
 			   RT_CONN_FLAGS(sk), RT_SCOPE_UNIVERSE,
 			   sk->sk_protocol, inet_sk_flowi_flags(sk),
@@ -576,10 +577,9 @@  struct dst_entry *inet_csk_route_child_sock(const struct sock *sk,
 	struct flowi4 *fl4;
 	struct rtable *rt;
 
+	opt = rcu_dereference(ireq->ireq_opt);
 	fl4 = &newinet->cork.fl.u.ip4;
 
-	rcu_read_lock();
-	opt = rcu_dereference(newinet->inet_opt);
 	flowi4_init_output(fl4, ireq->ir_iif, ireq->ir_mark,
 			   RT_CONN_FLAGS(sk), RT_SCOPE_UNIVERSE,
 			   sk->sk_protocol, inet_sk_flowi_flags(sk),
@@ -592,13 +592,11 @@  struct dst_entry *inet_csk_route_child_sock(const struct sock *sk,
 		goto no_route;
 	if (opt && opt->opt.is_strictroute && rt->rt_uses_gateway)
 		goto route_err;
-	rcu_read_unlock();
 	return &rt->dst;
 
 route_err:
 	ip_rt_put(rt);
 no_route:
-	rcu_read_unlock();
 	__IP_INC_STATS(net, IPSTATS_MIB_OUTNOROUTES);
 	return NULL;
 }
diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c
index b1bb1b3a108232d56aa82383422d68b5ff9da3ed..77cf32a80952fcf3ceff4ada946cc2d0df2411d9 100644
--- a/net/ipv4/syncookies.c
+++ b/net/ipv4/syncookies.c
@@ -355,7 +355,7 @@  struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb)
 	/* We throwed the options of the initial SYN away, so we hope
 	 * the ACK carries the same options again (see RFC1122 4.2.3.8)
 	 */
-	ireq->opt = tcp_v4_save_options(sock_net(sk), skb);
+	RCU_INIT_POINTER(ireq->ireq_opt, tcp_v4_save_options(sock_net(sk), skb));
 
 	if (security_inet_conn_request(sk, skb, req)) {
 		reqsk_free(req);
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index c5d7656beeee29b3c92e1c8824dbf00d3fa32d28..7eec3383702bbab497a12095b55d255532ad5f60 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -6196,7 +6196,7 @@  struct request_sock *inet_reqsk_alloc(const struct request_sock_ops *ops,
 		struct inet_request_sock *ireq = inet_rsk(req);
 
 		kmemcheck_annotate_bitfield(ireq, flags);
-		ireq->opt = NULL;
+		ireq->ireq_opt = NULL;
 #if IS_ENABLED(CONFIG_IPV6)
 		ireq->pktopts = NULL;
 #endif
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 85164d4d3e537537c87d74c00172592c860d4dfb..4c43365c374c8bf868fc0b862333244ca26d5016 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -877,7 +877,7 @@  static int tcp_v4_send_synack(const struct sock *sk, struct dst_entry *dst,
 
 		err = ip_build_and_send_pkt(skb, sk, ireq->ir_loc_addr,
 					    ireq->ir_rmt_addr,
-					    ireq->opt);
+					    rcu_dereference(ireq->ireq_opt));
 		err = net_xmit_eval(err);
 	}
 
@@ -889,7 +889,7 @@  static int tcp_v4_send_synack(const struct sock *sk, struct dst_entry *dst,
  */
 static void tcp_v4_reqsk_destructor(struct request_sock *req)
 {
-	kfree(inet_rsk(req)->opt);
+	kfree(rcu_dereference_protected(inet_rsk(req)->ireq_opt, 1));
 }
 
 #ifdef CONFIG_TCP_MD5SIG
@@ -1265,10 +1265,11 @@  static void tcp_v4_init_req(struct request_sock *req,
 			    struct sk_buff *skb)
 {
 	struct inet_request_sock *ireq = inet_rsk(req);
+	struct net *net = sock_net(sk_listener);
 
 	sk_rcv_saddr_set(req_to_sk(req), ip_hdr(skb)->daddr);
 	sk_daddr_set(req_to_sk(req), ip_hdr(skb)->saddr);
-	ireq->opt = tcp_v4_save_options(sock_net(sk_listener), skb);
+	RCU_INIT_POINTER(ireq->ireq_opt, tcp_v4_save_options(net, skb));
 }
 
 static struct dst_entry *tcp_v4_route_req(const struct sock *sk,
@@ -1355,10 +1356,9 @@  struct sock *tcp_v4_syn_recv_sock(const struct sock *sk, struct sk_buff *skb,
 	sk_daddr_set(newsk, ireq->ir_rmt_addr);
 	sk_rcv_saddr_set(newsk, ireq->ir_loc_addr);
 	newsk->sk_bound_dev_if = ireq->ir_iif;
-	newinet->inet_saddr	      = ireq->ir_loc_addr;
-	inet_opt	      = ireq->opt;
-	rcu_assign_pointer(newinet->inet_opt, inet_opt);
-	ireq->opt	      = NULL;
+	newinet->inet_saddr   = ireq->ir_loc_addr;
+	inet_opt	      = rcu_dereference(ireq->ireq_opt);
+	RCU_INIT_POINTER(newinet->inet_opt, inet_opt);
 	newinet->mc_index     = inet_iif(skb);
 	newinet->mc_ttl	      = ip_hdr(skb)->ttl;
 	newinet->rcv_tos      = ip_hdr(skb)->tos;
@@ -1403,9 +1403,12 @@  struct sock *tcp_v4_syn_recv_sock(const struct sock *sk, struct sk_buff *skb,
 	if (__inet_inherit_port(sk, newsk) < 0)
 		goto put_and_exit;
 	*own_req = inet_ehash_nolisten(newsk, req_to_sk(req_unhash));
-	if (*own_req)
+	if (likely(*own_req)) {
 		tcp_move_syn(newtp, req);
-
+		ireq->ireq_opt = NULL;
+	} else {
+		newinet->inet_opt = NULL;
+	}
 	return newsk;
 
 exit_overflow:
@@ -1416,6 +1419,7 @@  struct sock *tcp_v4_syn_recv_sock(const struct sock *sk, struct sk_buff *skb,
 	tcp_listendrop(sk);
 	return NULL;
 put_and_exit:
+	newinet->inet_opt = NULL;
 	inet_csk_prepare_forced_close(newsk);
 	tcp_done(newsk);
 	goto exit;