linux-stable/net
Waiman Long 7fa67aa305 KEYS: Don't write out to userspace while holding key semaphore
commit d3ec10aa95 upstream.

A lockdep circular locking dependency report was seen when running a
keyutils test:

[12537.027242] ======================================================
[12537.059309] WARNING: possible circular locking dependency detected
[12537.088148] 4.18.0-147.7.1.el8_1.x86_64+debug #1 Tainted: G OE    --------- -  -
[12537.125253] ------------------------------------------------------
[12537.153189] keyctl/25598 is trying to acquire lock:
[12537.175087] 000000007c39f96c (&mm->mmap_sem){++++}, at: __might_fault+0xc4/0x1b0
[12537.208365]
[12537.208365] but task is already holding lock:
[12537.234507] 000000003de5b58d (&type->lock_class){++++}, at: keyctl_read_key+0x15a/0x220
[12537.270476]
[12537.270476] which lock already depends on the new lock.
[12537.270476]
[12537.307209]
[12537.307209] the existing dependency chain (in reverse order) is:
[12537.340754]
[12537.340754] -> #3 (&type->lock_class){++++}:
[12537.367434]        down_write+0x4d/0x110
[12537.385202]        __key_link_begin+0x87/0x280
[12537.405232]        request_key_and_link+0x483/0xf70
[12537.427221]        request_key+0x3c/0x80
[12537.444839]        dns_query+0x1db/0x5a5 [dns_resolver]
[12537.468445]        dns_resolve_server_name_to_ip+0x1e1/0x4d0 [cifs]
[12537.496731]        cifs_reconnect+0xe04/0x2500 [cifs]
[12537.519418]        cifs_readv_from_socket+0x461/0x690 [cifs]
[12537.546263]        cifs_read_from_socket+0xa0/0xe0 [cifs]
[12537.573551]        cifs_demultiplex_thread+0x311/0x2db0 [cifs]
[12537.601045]        kthread+0x30c/0x3d0
[12537.617906]        ret_from_fork+0x3a/0x50
[12537.636225]
[12537.636225] -> #2 (root_key_user.cons_lock){+.+.}:
[12537.664525]        __mutex_lock+0x105/0x11f0
[12537.683734]        request_key_and_link+0x35a/0xf70
[12537.705640]        request_key+0x3c/0x80
[12537.723304]        dns_query+0x1db/0x5a5 [dns_resolver]
[12537.746773]        dns_resolve_server_name_to_ip+0x1e1/0x4d0 [cifs]
[12537.775607]        cifs_reconnect+0xe04/0x2500 [cifs]
[12537.798322]        cifs_readv_from_socket+0x461/0x690 [cifs]
[12537.823369]        cifs_read_from_socket+0xa0/0xe0 [cifs]
[12537.847262]        cifs_demultiplex_thread+0x311/0x2db0 [cifs]
[12537.873477]        kthread+0x30c/0x3d0
[12537.890281]        ret_from_fork+0x3a/0x50
[12537.908649]
[12537.908649] -> #1 (&tcp_ses->srv_mutex){+.+.}:
[12537.935225]        __mutex_lock+0x105/0x11f0
[12537.954450]        cifs_call_async+0x102/0x7f0 [cifs]
[12537.977250]        smb2_async_readv+0x6c3/0xc90 [cifs]
[12538.000659]        cifs_readpages+0x120a/0x1e50 [cifs]
[12538.023920]        read_pages+0xf5/0x560
[12538.041583]        __do_page_cache_readahead+0x41d/0x4b0
[12538.067047]        ondemand_readahead+0x44c/0xc10
[12538.092069]        filemap_fault+0xec1/0x1830
[12538.111637]        __do_fault+0x82/0x260
[12538.129216]        do_fault+0x419/0xfb0
[12538.146390]        __handle_mm_fault+0x862/0xdf0
[12538.167408]        handle_mm_fault+0x154/0x550
[12538.187401]        __do_page_fault+0x42f/0xa60
[12538.207395]        do_page_fault+0x38/0x5e0
[12538.225777]        page_fault+0x1e/0x30
[12538.243010]
[12538.243010] -> #0 (&mm->mmap_sem){++++}:
[12538.267875]        lock_acquire+0x14c/0x420
[12538.286848]        __might_fault+0x119/0x1b0
[12538.306006]        keyring_read_iterator+0x7e/0x170
[12538.327936]        assoc_array_subtree_iterate+0x97/0x280
[12538.352154]        keyring_read+0xe9/0x110
[12538.370558]        keyctl_read_key+0x1b9/0x220
[12538.391470]        do_syscall_64+0xa5/0x4b0
[12538.410511]        entry_SYSCALL_64_after_hwframe+0x6a/0xdf
[12538.435535]
[12538.435535] other info that might help us debug this:
[12538.435535]
[12538.472829] Chain exists of:
[12538.472829]   &mm->mmap_sem --> root_key_user.cons_lock --> &type->lock_class
[12538.472829]
[12538.524820]  Possible unsafe locking scenario:
[12538.524820]
[12538.551431]        CPU0                    CPU1
[12538.572654]        ----                    ----
[12538.595865]   lock(&type->lock_class);
[12538.613737]                                lock(root_key_user.cons_lock);
[12538.644234]                                lock(&type->lock_class);
[12538.672410]   lock(&mm->mmap_sem);
[12538.687758]
[12538.687758]  *** DEADLOCK ***
[12538.687758]
[12538.714455] 1 lock held by keyctl/25598:
[12538.732097]  #0: 000000003de5b58d (&type->lock_class){++++}, at: keyctl_read_key+0x15a/0x220
[12538.770573]
[12538.770573] stack backtrace:
[12538.790136] CPU: 2 PID: 25598 Comm: keyctl Kdump: loaded Tainted: G
[12538.844855] Hardware name: HP ProLiant DL360 Gen9/ProLiant DL360 Gen9, BIOS P89 12/27/2015
[12538.881963] Call Trace:
[12538.892897]  dump_stack+0x9a/0xf0
[12538.907908]  print_circular_bug.isra.25.cold.50+0x1bc/0x279
[12538.932891]  ? save_trace+0xd6/0x250
[12538.948979]  check_prev_add.constprop.32+0xc36/0x14f0
[12538.971643]  ? keyring_compare_object+0x104/0x190
[12538.992738]  ? check_usage+0x550/0x550
[12539.009845]  ? sched_clock+0x5/0x10
[12539.025484]  ? sched_clock_cpu+0x18/0x1e0
[12539.043555]  __lock_acquire+0x1f12/0x38d0
[12539.061551]  ? trace_hardirqs_on+0x10/0x10
[12539.080554]  lock_acquire+0x14c/0x420
[12539.100330]  ? __might_fault+0xc4/0x1b0
[12539.119079]  __might_fault+0x119/0x1b0
[12539.135869]  ? __might_fault+0xc4/0x1b0
[12539.153234]  keyring_read_iterator+0x7e/0x170
[12539.172787]  ? keyring_read+0x110/0x110
[12539.190059]  assoc_array_subtree_iterate+0x97/0x280
[12539.211526]  keyring_read+0xe9/0x110
[12539.227561]  ? keyring_gc_check_iterator+0xc0/0xc0
[12539.249076]  keyctl_read_key+0x1b9/0x220
[12539.266660]  do_syscall_64+0xa5/0x4b0
[12539.283091]  entry_SYSCALL_64_after_hwframe+0x6a/0xdf

One way to prevent this deadlock scenario from happening is to not
allow writing to userspace while holding the key semaphore. Instead,
an internal buffer is allocated for getting the keys out from the
read method first before copying them out to userspace without holding
the lock.

That requires taking out the __user modifier from all the relevant
read methods as well as additional changes to not use any userspace
write helpers. That is,

  1) The put_user() call is replaced by a direct copy.
  2) The copy_to_user() call is replaced by memcpy().
  3) All the fault handling code is removed.

Compiling on a x86-64 system, the size of the rxrpc_read() function is
reduced from 3795 bytes to 2384 bytes with this patch.

Fixes: ^1da177e4c3f4 ("Linux-2.6.12-rc2")
Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Signed-off-by: Waiman Long <longman@redhat.com>
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2020-04-24 08:01:25 +02:00
..
6lowpan 6lowpan: Off by one handling ->nexthdr 2020-01-27 14:46:30 +01:00
9p 9p/virtio: Add cleanup path in p9_virtio_init 2019-07-31 07:28:39 +02:00
802
8021q vlan: fix memory leak in vlan_dev_set_egress_priority 2020-01-12 12:12:09 +01:00
appletalk appletalk: Set error code if register_snap_client failed 2019-12-17 20:38:59 +01:00
atm net: use skb_queue_empty_lockless() in poll() handlers 2019-11-10 11:25:34 +01:00
ax25 ax25: enforce CAP_NET_RAW for raw sockets 2019-10-05 12:47:43 +02:00
batman-adv batman-adv: Don't schedule OGM for disabled interface 2020-03-20 10:54:23 +01:00
bluetooth Bluetooth: RFCOMM: fix ODEBUG bug in rfcomm_dev_ioctl 2020-04-13 10:34:35 +02:00
bpf
bridge netfilter: ebtables: CONFIG_COMPAT: reject trailing data after last rule 2020-01-27 14:46:34 +01:00
caif net: use skb_queue_empty_lockless() in poll() handlers 2019-11-10 11:25:34 +01:00
can can: af_can: Fix error path of can_init() 2019-07-21 09:04:22 +02:00
ceph libceph: fix PG split vs OSD (re)connect race 2019-08-29 08:26:42 +02:00
core net: revert default NAPI poll timeout to 2 jiffies 2020-04-24 08:00:53 +02:00
dcb net: dcb: For wild-card lookups, use priority -1, not 0 2018-09-19 22:43:43 +02:00
dccp dccp: Fix memleak in __feat_register_sp 2020-01-17 19:45:43 +01:00
decnet net: add bool confirm_neigh parameter for dst_ops.update_pmtu 2020-01-04 14:00:14 +01:00
dns_resolver KEYS: Don't write out to userspace while holding key semaphore 2020-04-24 08:01:25 +02:00
dsa net: dsa: Fix duplicate frames flooded by learning 2020-04-02 16:34:24 +02:00
ethernet net: add annotations on hh->hh_len lockless accesses 2020-01-09 10:17:59 +01:00
hsr hsr: check protocol version in hsr_newlink() 2020-04-24 08:00:52 +02:00
ieee802154 nl802154: add missing attribute validation for dev_type 2020-03-20 10:54:10 +01:00
ife
ipv4 net: ipv4: devinet: Fix crash when add/del multicast IP with autojoin 2020-04-24 08:00:52 +02:00
ipv6 ipv6: don't auto-add link-local address to lag ports 2020-04-13 10:34:28 +02:00
ipx
iucv net/af_iucv: always register net_device notifier 2020-01-27 14:46:38 +01:00
kcm kcm: switch order of device registration to fix a crash 2019-04-17 08:37:45 +02:00
key xfrm: clean up xfrm protocol checks 2019-09-16 08:20:44 +02:00
l2tp l2tp: Allow duplicate session creation with UDP 2020-02-14 16:32:06 -05:00
l3mdev
lapb lapb: fixed leak of control-blocks. 2019-06-22 08:16:14 +02:00
llc llc: fix sk_buff refcounting in llc_conn_state_process() 2020-01-27 14:46:49 +01:00
mac80211 mac80211: fix authentication with iwlwifi/mvm 2020-04-02 16:34:36 +02:00
mac802154 net: mac802154: tx: expand tailroom if necessary 2018-09-09 19:55:52 +02:00
mpls mpls: fix warning with multi-label encap 2020-01-27 14:46:37 +01:00
ncsi
netfilter netfilter: nf_tables: report EOPNOTSUPP on unsupported flags/object type 2020-04-24 08:01:01 +02:00
netlabel netlabel: fix out-of-bounds memory accesses 2019-03-13 14:03:08 -07:00
netlink netlink: Use netlink header as base to calculate bad attribute offset 2020-03-20 10:54:07 +01:00
netrom netrom: hold sock when setting skb->destructor 2019-07-31 07:28:46 +02:00
nfc nfc: add missing attribute validation for vendor subcommand 2020-03-20 10:54:12 +01:00
nsh nsh: set mac len based on inner packet 2018-07-22 14:28:49 +02:00
openvswitch openvswitch: support asymmetric conntrack 2019-12-21 10:47:34 +01:00
packet net/packet: tpacket_rcv: avoid a producer race condition 2020-04-02 16:34:24 +02:00
phonet net: use skb_queue_empty_lockless() in poll() handlers 2019-11-10 11:25:34 +01:00
psample net: psample: fix skb_over_panic 2019-12-05 15:38:15 +01:00
qrtr net: qrtr: send msgs from local of same id as broadcast 2020-04-24 08:00:53 +02:00
rds net/rds: Fix 'ib_evt_handler_call' element in 'rds_ib_stat_names' 2020-01-27 14:46:47 +01:00
rfkill rfkill: Fix incorrect check to avoid NULL pointer dereference 2020-01-12 12:11:57 +01:00
rose net/rose: fix unbound loop in rose_loopback_timer() 2019-05-02 09:40:34 +02:00
rxrpc KEYS: Don't write out to userspace while holding key semaphore 2020-04-24 08:01:25 +02:00
sched net_sched: keep alloc_hash updated after hash allocation 2020-04-02 16:34:24 +02:00
sctp sctp: fix possibly using a bad saddr with a given dst 2020-04-13 10:34:18 +02:00
smc net/smc: check for valid ib_client_data 2020-03-20 10:54:20 +01:00
strparser strparser: Remove early eaten to fix full tcp receive buffer stall 2018-07-22 14:28:47 +02:00
sunrpc sunrpc: expiry_time should be seconds not timeval 2020-02-14 16:32:15 -05:00
switchdev
tipc tipc: reduce risk of wakeup queue starvation 2020-01-27 14:46:41 +01:00
tls net/tls: Fixed return value when tls_complete_pending_work() fails 2018-12-05 19:41:11 +01:00
unix af_unix: add compat_ioctl support 2020-01-17 19:45:49 +01:00
vmw_vsock hv_sock: Remove the accept port restriction 2020-02-14 16:32:21 -05:00
wimax
wireless cfg80211: check reg_rule for NULL in handle_channel_custom() 2020-03-20 10:54:24 +01:00
x25 net/x25: fix nonblocking connect 2020-01-29 15:02:39 +01:00
xfrm xfrm: policy: Fix doulbe free in xfrm_policy_timer 2020-04-02 16:34:32 +02:00
compat.c sock: Make sock->sk_stamp thread-safe 2019-01-09 17:14:46 +01:00
Kconfig
Makefile
socket.c compat_ioctl: handle SIOCOUTQNSD 2020-01-17 19:45:49 +01:00
sysctl_net.c