netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Sasha Levin <sashal@kernel.org>
To: linux-kernel@vger.kernel.org, stable@vger.kernel.org
Cc: Song Liu <songliubraving@fb.com>,
	Alexei Starovoitov <ast@kernel.org>,
	Peter Zijlstra <peterz@infradead.org>,
	Daniel Borkmann <daniel@iogearbox.net>,
	Sasha Levin <sashal@kernel.org>,
	netdev@vger.kernel.org, bpf@vger.kernel.org
Subject: [PATCH AUTOSEL 4.19 065/177] bpf/stackmap: Fix deadlock with rq_lock in bpf_get_stack()
Date: Tue, 10 Dec 2019 16:30:29 -0500	[thread overview]
Message-ID: <20191210213221.11921-65-sashal@kernel.org> (raw)
In-Reply-To: <20191210213221.11921-1-sashal@kernel.org>

From: Song Liu <songliubraving@fb.com>

[ Upstream commit eac9153f2b584c702cea02c1f1a57d85aa9aea42 ]

bpf stackmap with build-id lookup (BPF_F_STACK_BUILD_ID) can trigger A-A
deadlock on rq_lock():

rcu: INFO: rcu_sched detected stalls on CPUs/tasks:
[...]
Call Trace:
 try_to_wake_up+0x1ad/0x590
 wake_up_q+0x54/0x80
 rwsem_wake+0x8a/0xb0
 bpf_get_stack+0x13c/0x150
 bpf_prog_fbdaf42eded9fe46_on_event+0x5e3/0x1000
 bpf_overflow_handler+0x60/0x100
 __perf_event_overflow+0x4f/0xf0
 perf_swevent_overflow+0x99/0xc0
 ___perf_sw_event+0xe7/0x120
 __schedule+0x47d/0x620
 schedule+0x29/0x90
 futex_wait_queue_me+0xb9/0x110
 futex_wait+0x139/0x230
 do_futex+0x2ac/0xa50
 __x64_sys_futex+0x13c/0x180
 do_syscall_64+0x42/0x100
 entry_SYSCALL_64_after_hwframe+0x44/0xa9

This can be reproduced by:
1. Start a multi-thread program that does parallel mmap() and malloc();
2. taskset the program to 2 CPUs;
3. Attach bpf program to trace_sched_switch and gather stackmap with
   build-id, e.g. with trace.py from bcc tools:
   trace.py -U -p <pid> -s <some-bin,some-lib> t:sched:sched_switch

A sample reproducer is attached at the end.

This could also trigger deadlock with other locks that are nested with
rq_lock.

Fix this by checking whether irqs are disabled. Since rq_lock and all
other nested locks are irq safe, it is safe to do up_read() when irqs are
not disable. If the irqs are disabled, postpone up_read() in irq_work.

Fixes: 615755a77b24 ("bpf: extend stackmap to save binary_build_id+offset instead of address")
Signed-off-by: Song Liu <songliubraving@fb.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Link: https://lore.kernel.org/bpf/20191014171223.357174-1-songliubraving@fb.com

Reproducer:
============================ 8< ============================

char *filename;

void *worker(void *p)
{
        void *ptr;
        int fd;
        char *pptr;

        fd = open(filename, O_RDONLY);
        if (fd < 0)
                return NULL;
        while (1) {
                struct timespec ts = {0, 1000 + rand() % 2000};

                ptr = mmap(NULL, 4096 * 64, PROT_READ, MAP_PRIVATE, fd, 0);
                usleep(1);
                if (ptr == MAP_FAILED) {
                        printf("failed to mmap\n");
                        break;
                }
                munmap(ptr, 4096 * 64);
                usleep(1);
                pptr = malloc(1);
                usleep(1);
                pptr[0] = 1;
                usleep(1);
                free(pptr);
                usleep(1);
                nanosleep(&ts, NULL);
        }
        close(fd);
        return NULL;
}

int main(int argc, char *argv[])
{
        void *ptr;
        int i;
        pthread_t threads[THREAD_COUNT];

        if (argc < 2)
                return 0;

        filename = argv[1];

        for (i = 0; i < THREAD_COUNT; i++) {
                if (pthread_create(threads + i, NULL, worker, NULL)) {
                        fprintf(stderr, "Error creating thread\n");
                        return 0;
                }
        }

        for (i = 0; i < THREAD_COUNT; i++)
                pthread_join(threads[i], NULL);
        return 0;
}
============================ 8< ============================

Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 kernel/bpf/stackmap.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/kernel/bpf/stackmap.c b/kernel/bpf/stackmap.c
index 7cb7a7f98a37d..55fff5e6d9831 100644
--- a/kernel/bpf/stackmap.c
+++ b/kernel/bpf/stackmap.c
@@ -292,7 +292,7 @@ static void stack_map_get_build_id_offset(struct bpf_stack_build_id *id_offs,
 	bool irq_work_busy = false;
 	struct stack_map_irq_work *work = NULL;
 
-	if (in_nmi()) {
+	if (irqs_disabled()) {
 		work = this_cpu_ptr(&up_read_work);
 		if (work->irq_work.flags & IRQ_WORK_BUSY)
 			/* cannot queue more up_read, fallback */
@@ -300,8 +300,9 @@ static void stack_map_get_build_id_offset(struct bpf_stack_build_id *id_offs,
 	}
 
 	/*
-	 * We cannot do up_read() in nmi context. To do build_id lookup
-	 * in nmi context, we need to run up_read() in irq_work. We use
+	 * We cannot do up_read() when the irq is disabled, because of
+	 * risk to deadlock with rq_lock. To do build_id lookup when the
+	 * irqs are disabled, we need to run up_read() in irq_work. We use
 	 * a percpu variable to do the irq_work. If the irq_work is
 	 * already used by another lookup, we fall back to report ips.
 	 *
-- 
2.20.1


  parent reply	other threads:[~2019-12-10 21:43 UTC|newest]

Thread overview: 35+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <20191210213221.11921-1-sashal@kernel.org>
2019-12-10 21:29 ` [PATCH AUTOSEL 4.19 011/177] rtlwifi: prevent memory leak in rtl_usb_probe Sasha Levin
2019-12-10 21:29 ` [PATCH AUTOSEL 4.19 012/177] libertas: fix a potential NULL pointer dereference Sasha Levin
2019-12-10 21:29 ` [PATCH AUTOSEL 4.19 013/177] ath10k: fix backtrace on coredump Sasha Levin
2019-12-10 21:29 ` [PATCH AUTOSEL 4.19 023/177] ath10k: fix offchannel tx failure when no ath10k_mac_tx_frm_has_freq Sasha Levin
2019-12-10 21:29 ` [PATCH AUTOSEL 4.19 026/177] selftests/bpf: Correct path to include msg + path Sasha Levin
2019-12-10 21:30 ` [PATCH AUTOSEL 4.19 038/177] mwifiex: pcie: Fix memory leak in mwifiex_pcie_init_evt_ring Sasha Levin
2019-12-10 21:30 ` [PATCH AUTOSEL 4.19 054/177] ath10k: Correct error handling of dma_map_single() Sasha Levin
2019-12-10 21:30 ` [PATCH AUTOSEL 4.19 062/177] Bluetooth: missed cpu_to_le16 conversion in hci_init4_req Sasha Levin
2019-12-10 21:30 ` [PATCH AUTOSEL 4.19 063/177] Bluetooth: Workaround directed advertising bug in Broadcom controllers Sasha Levin
2019-12-10 21:30 ` [PATCH AUTOSEL 4.19 064/177] Bluetooth: hci_core: fix init for HCI_USER_CHANNEL Sasha Levin
2019-12-10 21:30 ` Sasha Levin [this message]
2019-12-10 21:30 ` [PATCH AUTOSEL 4.19 071/177] rtl8xxxu: fix RTL8723BU connection failure issue after warm reboot Sasha Levin
2019-12-10 21:30 ` [PATCH AUTOSEL 4.19 077/177] i40e: initialize ITRN registers with correct values Sasha Levin
2019-12-10 21:30 ` [PATCH AUTOSEL 4.19 078/177] net: phy: dp83867: enable robust auto-mdix Sasha Levin
2019-12-10 21:30 ` [PATCH AUTOSEL 4.19 085/177] net: dsa: LAN9303: select REGMAP when LAN9303 enable Sasha Levin
2019-12-10 21:30 ` [PATCH AUTOSEL 4.19 090/177] net: hns3: add struct netdev_queue debug info for TX timeout Sasha Levin
2019-12-10 21:31 ` [PATCH AUTOSEL 4.19 096/177] libbpf: Fix error handling in bpf_map__reuse_fd() Sasha Levin
2019-12-10 21:31 ` [PATCH AUTOSEL 4.19 097/177] Bluetooth: Fix advertising duplicated flags Sasha Levin
2019-12-10 21:31 ` [PATCH AUTOSEL 4.19 099/177] ixgbe: protect TX timestamping from API misuse Sasha Levin
2019-12-10 21:31 ` [PATCH AUTOSEL 4.19 103/177] rfkill: allocate static minor Sasha Levin
2019-12-11  7:52   ` Greg Kroah-Hartman
2019-12-10 21:31 ` [PATCH AUTOSEL 4.19 104/177] bnx2x: Fix PF-VF communication over multi-cos queues Sasha Levin
2019-12-10 21:31 ` [PATCH AUTOSEL 4.19 107/177] rtlwifi: fix memory leak in rtl92c_set_fw_rsvdpagepkt() Sasha Levin
2019-12-10 21:31 ` [PATCH AUTOSEL 4.19 117/177] perf tools: Splice events onto evlist even on error Sasha Levin
2019-12-10 21:31 ` [PATCH AUTOSEL 4.19 121/177] perf parse: If pmu configuration fails free terms Sasha Levin
2019-12-10 21:31 ` [PATCH AUTOSEL 4.19 127/177] ath10k: fix get invalid tx rate for Mesh metric Sasha Levin
2019-12-10 21:31 ` [PATCH AUTOSEL 4.19 132/177] ice: delay less Sasha Levin
2019-12-10 21:31 ` [PATCH AUTOSEL 4.19 141/177] net: bcmgenet: Add RGMII_RXID support Sasha Levin
2019-12-10 21:31 ` [PATCH AUTOSEL 4.19 150/177] iwlwifi: mvm: fix unaligned read of rx_pkt_status Sasha Levin
2019-12-10 21:31 ` [PATCH AUTOSEL 4.19 153/177] tun: fix data-race in gro_normal_list() Sasha Levin
2019-12-10 21:32 ` [PATCH AUTOSEL 4.19 163/177] brcmfmac: remove monitor interface when detaching Sasha Levin
2019-12-10 21:32 ` [PATCH AUTOSEL 4.19 164/177] iwlwifi: check kasprintf() return value Sasha Levin
2019-12-10 21:32 ` [PATCH AUTOSEL 4.19 166/177] net: ethernet: ti: ale: clean ale tbl on init and intf restart Sasha Levin
2019-12-10 21:32 ` [PATCH AUTOSEL 4.19 170/177] mac80211: consider QoS Null frames for STA_NULLFUNC_ACKED Sasha Levin
2019-12-10 21:32 ` [PATCH AUTOSEL 4.19 177/177] net: phy: initialise phydev speed and duplex sanely Sasha Levin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20191210213221.11921-65-sashal@kernel.org \
    --to=sashal@kernel.org \
    --cc=ast@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=linux-kernel@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=peterz@infradead.org \
    --cc=songliubraving@fb.com \
    --cc=stable@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).