From patchwork Fri Jun 5 13:21:27 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Thompson X-Patchwork-Id: 187507 Delivered-To: patches@linaro.org Received: by 2002:a92:cf06:0:0:0:0:0 with SMTP id c6csp2377955ilo; Fri, 5 Jun 2020 06:22:23 -0700 (PDT) X-Received: by 2002:a1c:451:: with SMTP id 78mr2842779wme.83.1591363343775; Fri, 05 Jun 2020 06:22:23 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1591363343; cv=none; d=google.com; s=arc-20160816; b=CVzDiruf3RsszGhaw0pzXsT0Kp2zTJdTtfSHIDiEwEGR0CfPQveixo58CfU9jaZX0E B3RJPnysivyrqjzKt7g5oJJP2xdKnQl9+kQq2oIbM274V1TDpuvdYJWd8zxCgRAt0R3u dpmnHludjQde7ALPeCE3BiS3NYuTDPgB61fthks28SN+iIIJw0Vyju94og7jeXrssZf1 bs8IkvbxT3BKt+ii+HBiiIQmnoE6QExAe4FMy4XErSysmmIRmmHMe8QQy3tO4Imh825S /cU30rDJkKBpMk4v5wE4bn7/Jmiib7pJkPqf/3WlRHq7f4ABDJk43wkDGZWTMpu4aXst JejQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature; bh=xAlKxt3CeRGgnokjPKgwbHDWms7QUL6gxBaF1E7hzHQ=; b=CFUKLYKEcpHqPIcWcLGdKhQ4sfdTE7C2w2Yg2RC8zAI/Dc2BkZb6B4uAK8HD3br7Gp q3BLOonfXhx6oF5EJdo7U5WnWJT9DB2zeoToxpwYp26w3wGfBtrRvUVJ4oiwtOmjb6gQ Arw4WzMBdZ2PC8mbsy1fo3a8FmGxopk6wYEyYeQQcnNAm4HMUiRybhCyEQnSeEvLnW3I 7HNTvyWEJ5iDyVmb8c0xh14KXZ1rFMCbjPmSUZX+t1IpQpW+J+wJq/g5KzXjAdkhwtPw hQEibK7bxdqeDikQEXvmr2Lg0MdTkBLk/RrQ8kf6RLNeA0LbJ3IM4cpsrSp864H/HFxk ZCLQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=yYiav+kM; spf=pass (google.com: domain of daniel.thompson@linaro.org designates 209.85.220.65 as permitted sender) smtp.mailfrom=daniel.thompson@linaro.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from mail-sor-f65.google.com (mail-sor-f65.google.com. [209.85.220.65]) by mx.google.com with SMTPS id w7sor5352382wmk.19.2020.06.05.06.22.23 for (Google Transport Security); Fri, 05 Jun 2020 06:22:23 -0700 (PDT) Received-SPF: pass (google.com: domain of daniel.thompson@linaro.org designates 209.85.220.65 as permitted sender) client-ip=209.85.220.65; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=yYiav+kM; spf=pass (google.com: domain of daniel.thompson@linaro.org designates 209.85.220.65 as permitted sender) smtp.mailfrom=daniel.thompson@linaro.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=xAlKxt3CeRGgnokjPKgwbHDWms7QUL6gxBaF1E7hzHQ=; b=yYiav+kMyZ2Ix7WiVK7dI5HnTMjAng05HBGjcV43tWiZ6XDmWimy/6ZQNI7sxlIeF0 ny/pb2rEHxegQzT78UTHLx57Bavu+D8NPjlonHJRBg6EZ9iiNlX+eQ7e1zjdEgQSejc6 f20Onq0IJRAlGwXVdIKKG73OrUMooHFJPdDDKhBMmrFbRI7PzSYUnX5X7YwtML9MBhpb N6Ue6HDCNLoLE/Pwz9P/J0wj27Hid2yPPeQdp0icf93cf5xbDIpv2D/dhNngYGAyL/sg bDY9CaZ+0Fse6H5ZAjs5SGLwks3JyrNKZq5zD9AEb66Zor5YraVenWPJFPis3j/fjPgY 0C8Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=xAlKxt3CeRGgnokjPKgwbHDWms7QUL6gxBaF1E7hzHQ=; b=M+cb5p1CoSlayMV244z9lEbU9CsXWRhSpVFU1d8Rf+mAHYfRr321Fu4Tiky7oPdOt9 hyQENkbkEEWcTAty5G7E/FcB/aVpIOLvwPrhkbpRIkLqBLdfyCef0N/F0o+2O67T+Acq WmM34YgRqfi5aOcwI5+JOljPm9fa6MWQG8fLJcNbvieju/VTrQaD5q4AXWjDYV1VDioV Nt7JImrxb5/stZthR8LSQhrP3u9eCc2+PWsStlxAr6QaReU/KveLK8r074Vdd4nWWHxR t5ffV8lBwEzCPAAc4EMmCqsES1jTyiTt3hsxX/1Ri4bjrYt5AzsyDx10hvAWFTRfOIHn 9mVA== X-Gm-Message-State: AOAM5337BpqoWP+s61/H0jTde8CvthMbHXs8ioBHzBuLHB3xD9TIe8KI IGZ92458PeIUTtTeGAl0bunmoNSt X-Google-Smtp-Source: ABdhPJyt8YO6c3MFb5eo6VCQfHwV4YCdIkN/j71Gnogub1Z5Ahg9B5DQxJEiYFr2NP7rx7grZEK9JQ== X-Received: by 2002:a7b:c0cc:: with SMTP id s12mr2780173wmh.111.1591363343349; Fri, 05 Jun 2020 06:22:23 -0700 (PDT) Return-Path: Received: from wychelm.lan (cpc141214-aztw34-2-0-cust773.18-1.cable.virginm.net. [86.9.19.6]) by smtp.gmail.com with ESMTPSA id 1sm11419211wmz.13.2020.06.05.06.22.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 05 Jun 2020 06:22:22 -0700 (PDT) From: Daniel Thompson To: Jason Wessel , Douglas Anderson Cc: Daniel Thompson , Peter Zijlstra , sumit.garg@linaro.org, pmladek@suse.com, sergey.senozhatsky@gmail.com, will@kernel.org, kgdb-bugreport@lists.sourceforge.net, linux-kernel@vger.kernel.org, patches@linaro.org Subject: [RFC PATCH 1/4] kgdb: Honour the kprobe blacklist when setting breakpoints Date: Fri, 5 Jun 2020 14:21:27 +0100 Message-Id: <20200605132130.1411255-2-daniel.thompson@linaro.org> X-Mailer: git-send-email 2.25.4 In-Reply-To: <20200605132130.1411255-1-daniel.thompson@linaro.org> References: <20200605132130.1411255-1-daniel.thompson@linaro.org> MIME-Version: 1.0 Currently kgdb has absolutely no safety rails in place to discourage or prevent a user from placing a breakpoint in dangerous places such as the debugger's own trap entry/exit and other places where it is not safe to take synchronous traps. Modify the default implementation of kgdb_validate_break_address() so that we honour the kprobe blacklist (if there is one). The resulting blacklist will include code that kgdb could, in fact, debug but I think we can assume that anyone with sufficient knowledge to meaningfully debug that code would trivially be able to find and remove the safety rail if they need to. Suggested-by: Peter Zijlstra Signed-off-by: Daniel Thompson --- kernel/debug/debug_core.c | 11 +++++++++++ kernel/debug/kdb/kdb_bp.c | 9 +++++++++ 2 files changed, 20 insertions(+) -- 2.25.4 diff --git a/kernel/debug/debug_core.c b/kernel/debug/debug_core.c index ef94e906f05a..81f56d616e04 100644 --- a/kernel/debug/debug_core.c +++ b/kernel/debug/debug_core.c @@ -56,6 +56,7 @@ #include #include #include +#include #include #include @@ -188,6 +189,16 @@ int __weak kgdb_validate_break_address(unsigned long addr) { struct kgdb_bkpt tmp; int err; + + /* + * Disallow breakpoints that are marked as unsuitable for kprobing. + * This check is a little over-zealous because it does include + * code that kgdb is entirely capable of debugging but in exchange + * we can avoid recursive trapping (and all the problems that brings). + */ + if (within_kprobe_blacklist(addr)) + return -EINVAL; + /* Validate setting the breakpoint and then removing it. If the * remove fails, the kernel needs to emit a bad message because we * are deep trouble not being able to put things back the way we diff --git a/kernel/debug/kdb/kdb_bp.c b/kernel/debug/kdb/kdb_bp.c index d7ebb2c79cb8..ec4940146612 100644 --- a/kernel/debug/kdb/kdb_bp.c +++ b/kernel/debug/kdb/kdb_bp.c @@ -306,6 +306,15 @@ static int kdb_bp(int argc, const char **argv) if (!template.bp_addr) return KDB_BADINT; + /* + * This check is redundant (since the breakpoint machinery should + * be doing the same check during kdb_bp_install) but gives the + * user immediate feedback. + */ + diag = kgdb_validate_break_address(template.bp_addr); + if (diag) + return diag; + /* * Find an empty bp structure to allocate */ From patchwork Fri Jun 5 13:21:28 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Thompson X-Patchwork-Id: 187508 Delivered-To: patches@linaro.org Received: by 2002:a92:cf06:0:0:0:0:0 with SMTP id c6csp2377973ilo; Fri, 5 Jun 2020 06:22:25 -0700 (PDT) X-Received: by 2002:a5d:6305:: with SMTP id i5mr9390485wru.268.1591363345055; Fri, 05 Jun 2020 06:22:25 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1591363345; cv=none; d=google.com; s=arc-20160816; b=m5yKxhlj3lIJwfbPvG7ornbpbgO5nEs/3B9h9BJpkzn4sLs6IF9HnV0dNpfVkvvfaI zq5BCnwLBhOlChODPPKd05PzkINKwWh07FE9+KaddEvrT7SqJgBiP2UCx/G9VKBJESQN 6EXpD+YRiO1A/JnmqXuGFZ/ZVElDnSqf4PKtHPlHv3QlMmSlt6GTtl5I0M90zO/fulNN FbW0B+pKmP9Xr4puOfQ2DkE0H0rj7p+is1CsxFSuoCoRIjpmjYyJuebUGjoKc416LKXy N0+UOvYOfM8gezXaFS7Etiv+TL1adiz4wKmwknHsKkYPQHxZSHYVrU4nGSfQRcwZ1Wkm SZVA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature; bh=0Wd49qJJfphbkQd0zc5Sg32oNGChg1bIC5PBSadN6hM=; b=nweZmeLSD1m7CI11JOQqoZPp7+fwnSHQOjhQkbmRdZpSnvxL9AcElIAfJRVMZ/q+XL v/3u0Sv2DxW5puciOjF7aXdBzKq9nE8/UV2OBSOaMdk6aaExLZw2jZI0WQTSW0h5JraH SFnXXROlZKv5qHb0Ak0fW498yg903iVSNQzPPbqDMynCvoij0OQ19UJJchBa6hPMiXPP WI4iOscOYno0d552e5s4M+L0LCoHJRAu8QT34mQ6JolkVSH17FOD7zc7H5kJpHk3rCIl 35ZRdxdYuoEFE85A8FhalHLI4Fun6ED1vncwxjssAPJgySx+6NCWYA/kX/ELXZIRGS93 NmXQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=Ki1mWzQU; spf=pass (google.com: domain of daniel.thompson@linaro.org designates 209.85.220.65 as permitted sender) smtp.mailfrom=daniel.thompson@linaro.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from mail-sor-f65.google.com (mail-sor-f65.google.com. [209.85.220.65]) by mx.google.com with SMTPS id q13sor5354367wra.46.2020.06.05.06.22.24 for (Google Transport Security); Fri, 05 Jun 2020 06:22:25 -0700 (PDT) Received-SPF: pass (google.com: domain of daniel.thompson@linaro.org designates 209.85.220.65 as permitted sender) client-ip=209.85.220.65; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=Ki1mWzQU; spf=pass (google.com: domain of daniel.thompson@linaro.org designates 209.85.220.65 as permitted sender) smtp.mailfrom=daniel.thompson@linaro.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=0Wd49qJJfphbkQd0zc5Sg32oNGChg1bIC5PBSadN6hM=; b=Ki1mWzQUC6JcLvWE/8DkDtIIdjhYtPuZOCRYcToxv8LWR6pRb4lGurJyBIOkPuorTR Bsi8zComYX+iO1sRCteKaKGKyFUrV6SX6hjPxqnASoH0k1DXUJXEKyc3HGx2ueMIE2qb uywx8D1qZVnXSdiKKLdwXvNKLMNFIU9Bu8JHD5HLksHo/nlTZTGo8jsu+Ah8CXeONqWi hvJhuA1ziakt2ACYLpIUSNY1wMXCd97jniit9A4a3KTg0apr2Lf0h7yCyZefMoacoO2C 9q2d2vkvbL2DdSsZcTpTomTgUQeXMVAHG5xrferfVgiIys/NkQQv1KlcJViHEKl8u1a0 kXFg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=0Wd49qJJfphbkQd0zc5Sg32oNGChg1bIC5PBSadN6hM=; b=CeSvYEhra7UdAcMe4J3O+I0f+jWxT593RCzIBAHZ9igWYIiEwSF8dvQ8vwkavlXWG6 exRorTeOE9g5VzfqYuD1uyR0lboUGuHigpSMhkpiUi0ytQEHv7tFXPYJbgxdh4L8a+SQ yALC3hm7Gy50ukeMbmn/7DPAZBGQvdKsxQcDp15ApcqhfD2Ep5kVmo/nS1wRZjd6dnc1 ypyVlYZJquvlfs3ALjuu88BgfoJocqjGwEX4qzckcV9HTNBgk09gOFqPfsumEgD6LJn0 f9kyUmzG8xRBfBQ/jaCE62N3fHBo51HjDybwDiezwCC+3UdGQHx8SBxUqZR/RhJX/7lh RRlg== X-Gm-Message-State: AOAM533elaFzaJ77KzcVclHp1Dm9HeIEpDe8V200UYZgfR52TX5G/Bea qCae3KQkvlHdEitnmSVXnlgHh0R4 X-Google-Smtp-Source: ABdhPJzpXOyKm+//aW91zcmMraLFE6hXoKeh/4G6ONWrnUgxSkq+Twz2EbRA9faf1wyV0IhllSZGdQ== X-Received: by 2002:a5d:4701:: with SMTP id y1mr9434014wrq.310.1591363344584; Fri, 05 Jun 2020 06:22:24 -0700 (PDT) Return-Path: Received: from wychelm.lan (cpc141214-aztw34-2-0-cust773.18-1.cable.virginm.net. [86.9.19.6]) by smtp.gmail.com with ESMTPSA id 1sm11419211wmz.13.2020.06.05.06.22.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 05 Jun 2020 06:22:24 -0700 (PDT) From: Daniel Thompson To: Jason Wessel , Douglas Anderson Cc: Daniel Thompson , Peter Zijlstra , sumit.garg@linaro.org, pmladek@suse.com, sergey.senozhatsky@gmail.com, will@kernel.org, kgdb-bugreport@lists.sourceforge.net, linux-kernel@vger.kernel.org, patches@linaro.org Subject: [RFC PATCH 2/4] kgdb: Use the kprobe blacklist to limit single stepping Date: Fri, 5 Jun 2020 14:21:28 +0100 Message-Id: <20200605132130.1411255-3-daniel.thompson@linaro.org> X-Mailer: git-send-email 2.25.4 In-Reply-To: <20200605132130.1411255-1-daniel.thompson@linaro.org> References: <20200605132130.1411255-1-daniel.thompson@linaro.org> MIME-Version: 1.0 If we are running in a part of the kernel that dislikes breakpoint debugging then it is very unlikely to be safe to single step. Add some safety rails to prevent stepping through anything on the kprobe blacklist. As part of this kdb_ss() will no longer set the DOING_SS flags when it requests a step. This is safe because this flag is already redundant, returning KDB_CMD_SS is all that is needed to request a step (and this saves us from having to unset the flag if the safety check fails). Signed-off-by: Daniel Thompson --- include/linux/kgdb.h | 1 + kernel/debug/debug_core.c | 13 +++++++++++++ kernel/debug/gdbstub.c | 10 +++++++++- kernel/debug/kdb/kdb_bp.c | 8 ++------ kernel/debug/kdb/kdb_main.c | 10 ++++++++-- 5 files changed, 33 insertions(+), 9 deletions(-) -- 2.25.4 diff --git a/include/linux/kgdb.h b/include/linux/kgdb.h index c62d76478adc..93b612d81714 100644 --- a/include/linux/kgdb.h +++ b/include/linux/kgdb.h @@ -213,6 +213,7 @@ extern void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc); /* Optional functions. */ extern int kgdb_validate_break_address(unsigned long addr); +extern int kgdb_validate_single_step_address(unsigned long addr); extern int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt); extern int kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt); diff --git a/kernel/debug/debug_core.c b/kernel/debug/debug_core.c index 81f56d616e04..4a2df4509fe1 100644 --- a/kernel/debug/debug_core.c +++ b/kernel/debug/debug_core.c @@ -215,6 +215,18 @@ int __weak kgdb_validate_break_address(unsigned long addr) return err; } +int __weak kgdb_validate_single_step_address(unsigned long addr) +{ + /* + * Disallow stepping when we are executing code that is marked + * as unsuitable for kprobing. + */ + if (within_kprobe_blacklist(addr)) + return -EINVAL; + + return 0; +} + unsigned long __weak kgdb_arch_pc(int exception, struct pt_regs *regs) { return instruction_pointer(regs); @@ -1192,6 +1204,7 @@ noinline void kgdb_breakpoint(void) atomic_dec(&kgdb_setting_breakpoint); } EXPORT_SYMBOL_GPL(kgdb_breakpoint); +NOKPROBE_SYMBOL(kgdb_breakpoint); static int __init opt_kgdb_wait(char *str) { diff --git a/kernel/debug/gdbstub.c b/kernel/debug/gdbstub.c index 4b280fc7dd67..beb73a61a16d 100644 --- a/kernel/debug/gdbstub.c +++ b/kernel/debug/gdbstub.c @@ -1041,8 +1041,16 @@ int gdb_serial_stub(struct kgdb_state *ks) if (tmp == 0) break; /* Fall through - on tmp < 0 */ - case 'c': /* Continue packet */ case 's': /* Single step packet */ + error = kgdb_validate_single_step_address( + kgdb_arch_pc(ks->ex_vector, + ks->linux_regs)); + if (error != 0) { + error_packet(remcom_out_buffer, error); + break; + } + fallthrough; + case 'c': /* Continue packet */ if (kgdb_contthread && kgdb_contthread != current) { /* Can't switch threads in kgdb */ error_packet(remcom_out_buffer, -EINVAL); diff --git a/kernel/debug/kdb/kdb_bp.c b/kernel/debug/kdb/kdb_bp.c index ec4940146612..4853c413f579 100644 --- a/kernel/debug/kdb/kdb_bp.c +++ b/kernel/debug/kdb/kdb_bp.c @@ -507,18 +507,14 @@ static int kdb_bc(int argc, const char **argv) * None. * Remarks: * - * Set the arch specific option to trigger a debug trap after the next - * instruction. + * KDB_CMD_SS is a command that our caller acts on to effect the step. */ static int kdb_ss(int argc, const char **argv) { if (argc != 0) return KDB_ARGCOUNT; - /* - * Set trace flag and go. - */ - KDB_STATE_SET(DOING_SS); + return KDB_CMD_SS; } diff --git a/kernel/debug/kdb/kdb_main.c b/kernel/debug/kdb/kdb_main.c index ec190569f690..4b277c066f48 100644 --- a/kernel/debug/kdb/kdb_main.c +++ b/kernel/debug/kdb/kdb_main.c @@ -1189,7 +1189,7 @@ static int kdb_local(kdb_reason_t reason, int error, struct pt_regs *regs, kdb_dbtrap_t db_result) { char *cmdbuf; - int diag; + int diag, res; struct task_struct *kdb_current = kdb_curr_task(raw_smp_processor_id()); @@ -1346,10 +1346,16 @@ static int kdb_local(kdb_reason_t reason, int error, struct pt_regs *regs, } if (diag == KDB_CMD_GO || diag == KDB_CMD_CPU - || diag == KDB_CMD_SS || diag == KDB_CMD_KGDB) break; + if (diag == KDB_CMD_SS) { + res = kgdb_validate_single_step_address(instruction_pointer(regs)); + if (res == 0) + break; + diag = res; + } + if (diag) kdb_cmderror(diag); } From patchwork Fri Jun 5 13:21:29 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Thompson X-Patchwork-Id: 187509 Delivered-To: patches@linaro.org Received: by 2002:a92:cf06:0:0:0:0:0 with SMTP id c6csp2377984ilo; Fri, 5 Jun 2020 06:22:26 -0700 (PDT) X-Received: by 2002:a1c:7717:: with SMTP id t23mr2680092wmi.175.1591363346270; Fri, 05 Jun 2020 06:22:26 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1591363346; cv=none; d=google.com; s=arc-20160816; b=pSIvmBPDm5vW5xT/Pdu81jlf1qXjCW8eg8E3s549xQNOIYs9Cj9fU2ecqanO0kqT9a OZPeqjqZLLeGgRfrQ9ukv+KgOgisP0Xl+O/Nd2yKluPYLYuiWgATpz0tNKQZm6id4BSv ipQJ9sXiatYsK977Bj0lqlIRh+Z9OCdLHGt5AzCUdMz+SD4MXHEgAVW+9QSqcDkLFEfB 2Cj3/6boIKCHu8kWy5paEDVl/fcSqB2h0mNYzijVIJivxZXlpYHGFE0rijmA29IO2R5h JwKFEaVQTUHb5WNjcZY7G7Ko8JRK33gE7O3nuGzA9ZY+6Ghmp/phFMSMq8ji7e487F2Z Pwig== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature; bh=B90P5vlRjcmc/HwmlTNh5ez1pbs9ga7qbMLqz94WeAc=; b=E3vXJVSWgXezZEfT0JUQ05zH6PmL8nagXNK4/qwVuYqggQU/PvWcXa2HS8IqxC0ffW 5UF9x86C9ih99gez3VVTOeA3z+GmXfQjwxiX7TNSkJb4zC3OMIS7FFehFVOfwcMc9Q+U kR/+7M3c8Jh0MCboYAjoScAlwHgJhKv1vzc7tGYe0ztFkjEkTavtPUcJUytwlusWKZJx QXfX47Ke7l2O2PWJVB95UDB8DxWz1PpXkX2NDGuCNnc/IUClj1tGjId/o3nUCeWCKx7u VKjKSvVOkFYWLwolp0LMx1PpZzkOtq92ChRXSEAQaaCXbX58lzRpp73gAplRQiE8uMhn MIKA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=YTkZfuza; spf=pass (google.com: domain of daniel.thompson@linaro.org designates 209.85.220.65 as permitted sender) smtp.mailfrom=daniel.thompson@linaro.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from mail-sor-f65.google.com (mail-sor-f65.google.com. [209.85.220.65]) by mx.google.com with SMTPS id h25sor5436893wml.4.2020.06.05.06.22.26 for (Google Transport Security); Fri, 05 Jun 2020 06:22:26 -0700 (PDT) Received-SPF: pass (google.com: domain of daniel.thompson@linaro.org designates 209.85.220.65 as permitted sender) client-ip=209.85.220.65; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=YTkZfuza; spf=pass (google.com: domain of daniel.thompson@linaro.org designates 209.85.220.65 as permitted sender) smtp.mailfrom=daniel.thompson@linaro.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=B90P5vlRjcmc/HwmlTNh5ez1pbs9ga7qbMLqz94WeAc=; b=YTkZfuzam21k+uBt0acIuHPSgWol4t9gl77sHHb0fCSWzBFXoGCJliwFNTqsttd+AF qtG/4YyJse4VKAOpBl7G1blPNzVVKsKoDWzWj4UXjvgAdw8JX29fx0ejWQy08+oKs5Dv WprF3Nft8aVQ16a1n1ccsooduEpWognLe1f1P8GiXz3fGs+n1sDxlY2j7pTVqemseUk0 kG/3KCz5+UlMh7EARDuudE7NV3tPDG1JBMqeRXYWUEOL5BhuPEHCfG3rWnS6tzJHeorJ 7I8gAiNYwQcv0fx+jJ28f7Z/rJlJDa7HfKq4aPIFZYnKik7nbdG4smPYqqGN7o3UF27Q jS6g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=B90P5vlRjcmc/HwmlTNh5ez1pbs9ga7qbMLqz94WeAc=; b=SKjLHtOiKvi0Rb9FqUrA1s9I06PP8jm5nHtm26qRaGeEPtAiGgjKmbCqHsxcTslTxh 65PhdrzNtsKr5Ko/BLJRv26aF00/sNIyjTv26k+P/VHAcujnINCIvoCcZWuA5YhLILHf 84YoVNJz8eGwCW6zPzOLY1eHs/J6Kb4muk0Hn8Nl60LMSW7lqNcuhIzHA2mgvNi7pegZ CwPETPxpZtewkYdg92rwqGaeQvEiCmkj/ehNeWp+nHAtfQMjPOYbp7TmUre1dCsP893r PfiRxMF0iuAyjfcGnuvyqinWygymfpL7+KTJXJUOTmOgckBFxjLUiKU+vk7tfRHywurD eAmw== X-Gm-Message-State: AOAM53353dFNsX58fP7ZhoSb0l2RKLuXc5oIcQ8PCk15eZhLhN9YJBoY CYcGtF0EPIiraqc9SnHdpiv28dr/ X-Google-Smtp-Source: ABdhPJyIAgP4Nu6MeJ5AZk9gWIJ9ycHXjBABtQl48AzXyVO5HV3VWQMGZqu06mldUl+jLuwYIcLGMg== X-Received: by 2002:a1c:2bc2:: with SMTP id r185mr2853782wmr.49.1591363345886; Fri, 05 Jun 2020 06:22:25 -0700 (PDT) Return-Path: Received: from wychelm.lan (cpc141214-aztw34-2-0-cust773.18-1.cable.virginm.net. [86.9.19.6]) by smtp.gmail.com with ESMTPSA id 1sm11419211wmz.13.2020.06.05.06.22.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 05 Jun 2020 06:22:25 -0700 (PDT) From: Daniel Thompson To: Jason Wessel , Douglas Anderson Cc: Daniel Thompson , Peter Zijlstra , sumit.garg@linaro.org, pmladek@suse.com, sergey.senozhatsky@gmail.com, will@kernel.org, kgdb-bugreport@lists.sourceforge.net, linux-kernel@vger.kernel.org, patches@linaro.org Subject: [RFC PATCH 3/4] kgdb: Add NOKPROBE labels on the trap handler functions Date: Fri, 5 Jun 2020 14:21:29 +0100 Message-Id: <20200605132130.1411255-4-daniel.thompson@linaro.org> X-Mailer: git-send-email 2.25.4 In-Reply-To: <20200605132130.1411255-1-daniel.thompson@linaro.org> References: <20200605132130.1411255-1-daniel.thompson@linaro.org> MIME-Version: 1.0 Currently kgdb honours the kprobe blacklist but doesn't place its own trap handling code on the list. Add macros to discourage attempting to use kgdb to debug itself. These changes do not make it impossible to provoke recursive trapping since they do not cover all the calls that can be made on kgdb's entry logic. However going much further whilst we are sharing the kprobe blacklist risks reducing the capabilities of kprobe and this is a bad trade off (especially so given kgdb's users are currently conditioned to avoid recursive traps). Signed-off-by: Daniel Thompson --- kernel/debug/debug_core.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) -- 2.25.4 diff --git a/kernel/debug/debug_core.c b/kernel/debug/debug_core.c index 4a2df4509fe1..21d1d91da4bb 100644 --- a/kernel/debug/debug_core.c +++ b/kernel/debug/debug_core.c @@ -184,6 +184,7 @@ int __weak kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt) return probe_kernel_write((char *)bpt->bpt_addr, (char *)bpt->saved_instr, BREAK_INSTR_SIZE); } +NOKPROBE_SYMBOL(kgdb_arch_remove_breakpoint); int __weak kgdb_validate_break_address(unsigned long addr) { @@ -321,6 +322,7 @@ static void kgdb_flush_swbreak_addr(unsigned long addr) /* Force flush instruction cache if it was outside the mm */ flush_icache_range(addr, addr + BREAK_INSTR_SIZE); } +NOKPROBE_SYMBOL(kgdb_flush_swbreak_addr); /* * SW breakpoint management: @@ -411,6 +413,7 @@ int dbg_deactivate_sw_breakpoints(void) } return ret; } +NOKPROBE_SYMBOL(dbg_deactivate_sw_breakpoints); int dbg_remove_sw_break(unsigned long addr) { @@ -567,6 +570,7 @@ static int kgdb_reenter_check(struct kgdb_state *ks) return 1; } +NOKPROBE_SYMBOL(kgdb_reenter_check); static void dbg_touch_watchdogs(void) { @@ -801,6 +805,7 @@ static int kgdb_cpu_enter(struct kgdb_state *ks, struct pt_regs *regs, return kgdb_info[cpu].ret_state; } +NOKPROBE_SYMBOL(kgdb_cpu_enter); /* * kgdb_handle_exception() - main entry point from a kernel exception @@ -845,6 +850,7 @@ kgdb_handle_exception(int evector, int signo, int ecode, struct pt_regs *regs) arch_kgdb_ops.enable_nmi(1); return ret; } +NOKPROBE_SYMBOL(kgdb_handle_exception); /* * GDB places a breakpoint at this function to know dynamically loaded objects. @@ -879,6 +885,7 @@ int kgdb_nmicallback(int cpu, void *regs) #endif return 1; } +NOKPROBE_SYMBOL(kgdb_nmicallback); int kgdb_nmicallin(int cpu, int trapnr, void *regs, int err_code, atomic_t *send_ready) @@ -904,6 +911,7 @@ int kgdb_nmicallin(int cpu, int trapnr, void *regs, int err_code, #endif return 1; } +NOKPROBE_SYMBOL(kgdb_nmicallin); static void kgdb_console_write(struct console *co, const char *s, unsigned count) @@ -1204,7 +1212,6 @@ noinline void kgdb_breakpoint(void) atomic_dec(&kgdb_setting_breakpoint); } EXPORT_SYMBOL_GPL(kgdb_breakpoint); -NOKPROBE_SYMBOL(kgdb_breakpoint); static int __init opt_kgdb_wait(char *str) { From patchwork Fri Jun 5 13:21:30 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Thompson X-Patchwork-Id: 187510 Delivered-To: patches@linaro.org Received: by 2002:a92:cf06:0:0:0:0:0 with SMTP id c6csp2378024ilo; Fri, 5 Jun 2020 06:22:28 -0700 (PDT) X-Received: by 2002:a1c:a74d:: with SMTP id q74mr2669343wme.177.1591363348429; Fri, 05 Jun 2020 06:22:28 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1591363348; cv=none; d=google.com; s=arc-20160816; b=r7J2X+FOEngbS1Dz2LWcIvJW/KGZz7x7/tQnoN70ZHulV8cFVhWPvtShC/W00nJO8c yB2ttmOBt7H/5uSt9XrPtp1N+q59yE0W142gaWUwIpIeBVNM00vH37KZdPxRzH8eerL3 sjRkHWlrA5m0An0nOzgB0GNgLgl0xWCCNVw53s2uRyxSQwMHpqs7s1V6N+FDtgcPRY06 nns4PxCduMeWwtv2TsLrQ51urA5J8GxS9AVZUyf+y6aVdqs1jKlaNigF5vz5M9vtnfY2 08hx2NDnkm+77GZSFtTvdpphKBMpVNnJglo4ZzRnNxuDbZKi6p/ZQDIv3N2xJc/qMJ0H VYvA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature; bh=cq5fX+bpLSy6uSSoDVV3qE07g/yYDJmAmlVeivVCrbg=; b=aoGFbV6MRdqwu5JBn5Nyp34WbJ7IV/BAgDG7a3DvcWWS0kQERD2OvERdMq76BTKaUU +qBt3g1Ux1HC0o8BiUXc/fddGP9ktC42t5AgLtZE9Jx9QIW5NG1eS4Fs8zzJxS0v6TLR sMKrTSE8ShZFdxesT9QArMDr5T5ISSbPBHcE1LojuT0jw8NY06QrVJV64qN5L5yx+OlK M8joerKh7tNcYwGvW+ZbEZjuMc/x8x0V6gFxA84HOZnj2s4wWiARda2aa6LhIigCmfKW 22KaAEyDJ7FTefLBMec+7WMacuv7W4bn1SYaLj77Bap4pvLwhSXhWEzTiqaKM0GqNQYc jrjA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=tHSInCv5; spf=pass (google.com: domain of daniel.thompson@linaro.org designates 209.85.220.65 as permitted sender) smtp.mailfrom=daniel.thompson@linaro.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from mail-sor-f65.google.com (mail-sor-f65.google.com. [209.85.220.65]) by mx.google.com with SMTPS id g3sor5219573wru.20.2020.06.05.06.22.28 for (Google Transport Security); Fri, 05 Jun 2020 06:22:28 -0700 (PDT) Received-SPF: pass (google.com: domain of daniel.thompson@linaro.org designates 209.85.220.65 as permitted sender) client-ip=209.85.220.65; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=tHSInCv5; spf=pass (google.com: domain of daniel.thompson@linaro.org designates 209.85.220.65 as permitted sender) smtp.mailfrom=daniel.thompson@linaro.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=cq5fX+bpLSy6uSSoDVV3qE07g/yYDJmAmlVeivVCrbg=; b=tHSInCv5tmCFl7C+FnF0hUzspzSSZSZrWDsVSUq206gZxw7YgZ2NBZIf6oCRVum1SG JW8bRAorhwLFDzhc7ZfmRsk4NBrxhrgb0/cMFdQ8Ik2dU933gTZknQ24Vwn4kJCX5LoI Anznf+o/JC/qoT7xZpdMv8Ky0agesGgWYBDLuRVVS5vofYoTUiTee8PZelDWuzTSYrRD pLOSTu9VAPK1eSVX5Di98VQEM1p7LLQmM2/wYMhDDFn6oCs41NrRR9WXAM9+eOa+iWNa VdUVKestQGLO24NWBCUTLbYS6UGLr7hXbu00iOCixNhhtqUNmvtBUC+gt2F+CHUSyh84 dJQw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=cq5fX+bpLSy6uSSoDVV3qE07g/yYDJmAmlVeivVCrbg=; b=i83DelZhzsuPxcX7f2kSCB1JU83+FbKuhnmHmz2jPOxJqnS0naEZ7+c0YxVy+Q+3zO qapgDVWjnUfGB9kZe4hENRobG1t8AE4QUw5V3PTOPy3VeEcJP6bCHpGanTwAykRdcz7a S/tytaxLSOmm+B5A6mBYH1h5hmg5a+GPpNZVpkmmuheIi81/ZCweW7YrzALErMWlZQwv 16KNRNwaKc91t1Ye793xR6ROSiknR6rE2ABEpoVvokpcwf23NAcIQMu8aXJarBgtFOWS eaC7Z/EbcD3zxxbBtGwN4hP/ozlQyRtnxvnXG7KC1g5dCCS/kEX8X09IJN9e+oW8fhaz vh4g== X-Gm-Message-State: AOAM530Ey4Pl/7l+QIVSaB3zojzhuyRkUqBx9y29ntOTUF77369t9sgq 0CJ1jZE7x6wjo9uoANGsOd1iLA9s X-Google-Smtp-Source: ABdhPJzpzmNBSznJzF4dI3nAVtneyx7UG1IfG6ZseiC1LlZ025y+KhMI3JPHyGeY5C25gn2owk9Bww== X-Received: by 2002:a5d:6a4b:: with SMTP id t11mr9453793wrw.404.1591363347628; Fri, 05 Jun 2020 06:22:27 -0700 (PDT) Return-Path: Received: from wychelm.lan (cpc141214-aztw34-2-0-cust773.18-1.cable.virginm.net. [86.9.19.6]) by smtp.gmail.com with ESMTPSA id 1sm11419211wmz.13.2020.06.05.06.22.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 05 Jun 2020 06:22:27 -0700 (PDT) From: Daniel Thompson To: Jason Wessel , Douglas Anderson Cc: Daniel Thompson , Peter Zijlstra , sumit.garg@linaro.org, pmladek@suse.com, sergey.senozhatsky@gmail.com, will@kernel.org, kgdb-bugreport@lists.sourceforge.net, linux-kernel@vger.kernel.org, patches@linaro.org Subject: [RFC PATCH 4/4] kprobes: Allow the kprobes blacklist to be compiled independently Date: Fri, 5 Jun 2020 14:21:30 +0100 Message-Id: <20200605132130.1411255-5-daniel.thompson@linaro.org> X-Mailer: git-send-email 2.25.4 In-Reply-To: <20200605132130.1411255-1-daniel.thompson@linaro.org> References: <20200605132130.1411255-1-daniel.thompson@linaro.org> MIME-Version: 1.0 IMPORTANT: As menitoned in the covering letter, this series in an RFC and this patch, in particular, is acknowledged as needing more work. In particular I haven't trimmed uneccessary #includes after splitting out the code and may also have missed some places where an an architecture overrides one of the weak symbols used for blacklist checking. If I don't get objections to the general approach taken to splitting out this code then I will do the final clean up and detailed review. The kprobes blacklist is useful for other tools that set breakpoints such as kgdb or kdb. Currently the blacklist is only available on platforms where CONFIG_KPROBES is set (when kprobes is not set then the blacklist essentially covers the entire kernel). Separate out the blacklist handling logic from the rest of kprobes to allow it to be compiled independently. Signed-off-by: Daniel Thompson --- arch/Kconfig | 6 +- arch/arm/probes/kprobes/Makefile | 1 + arch/arm/probes/kprobes/blacklist.c | 37 ++++ arch/arm/probes/kprobes/core.c | 10 - arch/powerpc/kernel/Makefile | 1 + arch/powerpc/kernel/kprobes-blacklist.c | 34 ++++ arch/powerpc/kernel/kprobes.c | 8 - include/asm-generic/kprobes.h | 2 +- include/asm-generic/vmlinux.lds.h | 2 +- include/linux/kprobes.h | 29 ++- kernel/Makefile | 1 + kernel/kprobes.c | 204 +------------------ kernel/kprobes_blacklist.c | 260 ++++++++++++++++++++++++ lib/Kconfig.kgdb | 1 + 14 files changed, 367 insertions(+), 229 deletions(-) create mode 100644 arch/arm/probes/kprobes/blacklist.c create mode 100644 arch/powerpc/kernel/kprobes-blacklist.c create mode 100644 kernel/kprobes_blacklist.c -- 2.25.4 diff --git a/arch/Kconfig b/arch/Kconfig index 786a85d4ad40..dd1d709bd195 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -63,7 +63,7 @@ config KPROBES bool "Kprobes" depends on MODULES depends on HAVE_KPROBES - select KALLSYMS + select KPROBES_BLACKLIST help Kprobes allows you to trap at almost any kernel address and execute a callback function. register_kprobe() establishes @@ -71,6 +71,10 @@ config KPROBES for kernel debugging, non-intrusive instrumentation and testing. If in doubt, say "N". +config KPROBES_BLACKLIST + bool + select KALLSYMS + config JUMP_LABEL bool "Optimize very unlikely/likely branches" depends on HAVE_ARCH_JUMP_LABEL diff --git a/arch/arm/probes/kprobes/Makefile b/arch/arm/probes/kprobes/Makefile index 14db56f49f0a..8b7ede9fb335 100644 --- a/arch/arm/probes/kprobes/Makefile +++ b/arch/arm/probes/kprobes/Makefile @@ -1,5 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_KPROBES) += core.o actions-common.o checkers-common.o +obj-$(CONFIG_KPROBES_BLACKLIST) += blacklist.o obj-$(CONFIG_ARM_KPROBES_TEST) += test-kprobes.o test-kprobes-objs := test-core.o diff --git a/arch/arm/probes/kprobes/blacklist.c b/arch/arm/probes/kprobes/blacklist.c new file mode 100644 index 000000000000..c3b37f0b59d0 --- /dev/null +++ b/arch/arm/probes/kprobes/blacklist.c @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * arch/arm/kernel/kprobe/blacklist.c + * + * Kprobes on ARM + * + * Abhishek Sagar + * Copyright (C) 2006, 2007 Motorola Inc. + * + * Nicolas Pitre + * Copyright (C) 2007 Marvell Ltd. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +bool arch_within_kprobe_blacklist(unsigned long addr) +{ + void *a = (void *)addr; + + return __in_irqentry_text(addr) || + in_entry_text(addr) || + in_idmap_text(addr) || + memory_contains(__kprobes_text_start, __kprobes_text_end, a, 1); +} diff --git a/arch/arm/probes/kprobes/core.c b/arch/arm/probes/kprobes/core.c index 90b5bc723c83..dce82761f83a 100644 --- a/arch/arm/probes/kprobes/core.c +++ b/arch/arm/probes/kprobes/core.c @@ -545,13 +545,3 @@ int __init arch_init_kprobes() #endif return 0; } - -bool arch_within_kprobe_blacklist(unsigned long addr) -{ - void *a = (void *)addr; - - return __in_irqentry_text(addr) || - in_entry_text(addr) || - in_idmap_text(addr) || - memory_contains(__kprobes_text_start, __kprobes_text_end, a, 1); -} diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index 1c4385852d3d..fd912afbb6f1 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile @@ -110,6 +110,7 @@ obj-$(CONFIG_KGDB) += kgdb.o obj-$(CONFIG_BOOTX_TEXT) += btext.o obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_KPROBES) += kprobes.o +obj-$(CONFIG_KPROBES_BLACKLIST) += kprobes-blacklist.o obj-$(CONFIG_OPTPROBES) += optprobes.o optprobes_head.o obj-$(CONFIG_KPROBES_ON_FTRACE) += kprobes-ftrace.o obj-$(CONFIG_UPROBES) += uprobes.o diff --git a/arch/powerpc/kernel/kprobes-blacklist.c b/arch/powerpc/kernel/kprobes-blacklist.c new file mode 100644 index 000000000000..4410a80e313a --- /dev/null +++ b/arch/powerpc/kernel/kprobes-blacklist.c @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Kernel Probes (KProbes) + * + * Copyright (C) IBM Corporation, 2002, 2004 + * + * 2002-Oct Created by Vamsi Krishna S Kernel + * Probes initial implementation ( includes contributions from + * Rusty Russell). + * 2004-July Suparna Bhattacharya added jumper probes + * interface to access function arguments. + * 2004-Nov Ananth N Mavinakayanahalli kprobes port + * for PPC64 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +bool arch_within_kprobe_blacklist(unsigned long addr) +{ + return (addr >= (unsigned long)__kprobes_text_start && + addr < (unsigned long)__kprobes_text_end) || + (addr >= (unsigned long)_stext && + addr < (unsigned long)__head_end); +} diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c index 81efb605113e..9e87a7fe3207 100644 --- a/arch/powerpc/kernel/kprobes.c +++ b/arch/powerpc/kernel/kprobes.c @@ -30,14 +30,6 @@ DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); struct kretprobe_blackpoint kretprobe_blacklist[] = {{NULL, NULL}}; -bool arch_within_kprobe_blacklist(unsigned long addr) -{ - return (addr >= (unsigned long)__kprobes_text_start && - addr < (unsigned long)__kprobes_text_end) || - (addr >= (unsigned long)_stext && - addr < (unsigned long)__head_end); -} - kprobe_opcode_t *kprobe_lookup_name(const char *name, unsigned int offset) { kprobe_opcode_t *addr = NULL; diff --git a/include/asm-generic/kprobes.h b/include/asm-generic/kprobes.h index 4a982089c95c..40800c6ff52f 100644 --- a/include/asm-generic/kprobes.h +++ b/include/asm-generic/kprobes.h @@ -3,7 +3,7 @@ #define _ASM_GENERIC_KPROBES_H #if defined(__KERNEL__) && !defined(__ASSEMBLY__) -#ifdef CONFIG_KPROBES +#ifdef CONFIG_KPROBES_BLACKLIST /* * Blacklist ganerating macro. Specify functions which is not probed * by using this macro. diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index 71e387a5fe90..bd8bcadba148 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -176,7 +176,7 @@ #define BRANCH_PROFILE() #endif -#ifdef CONFIG_KPROBES +#ifdef CONFIG_KPROBES_BLACKLIST #define KPROBE_BLACKLIST() . = ALIGN(8); \ __start_kprobe_blacklist = .; \ KEEP(*(_kprobe_blacklist)) \ diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h index 04bdaf01112c..ef6521e75761 100644 --- a/include/linux/kprobes.h +++ b/include/linux/kprobes.h @@ -234,10 +234,6 @@ extern int arch_populate_kprobe_blacklist(void); extern bool arch_kprobe_on_func_entry(unsigned long offset); extern bool kprobe_on_func_entry(kprobe_opcode_t *addr, const char *sym, unsigned long offset); -extern bool within_kprobe_blacklist(unsigned long addr); -extern int kprobe_add_ksym_blacklist(unsigned long entry); -extern int kprobe_add_area_blacklist(unsigned long start, unsigned long end); - struct kprobe_insn_cache { struct mutex mutex; void *(*alloc)(void); /* allocate insn page */ @@ -350,12 +346,10 @@ static inline struct kprobe_ctlblk *get_kprobe_ctlblk(void) return this_cpu_ptr(&kprobe_ctlblk); } -kprobe_opcode_t *kprobe_lookup_name(const char *name, unsigned int offset); int register_kprobe(struct kprobe *p); void unregister_kprobe(struct kprobe *p); int register_kprobes(struct kprobe **kps, int num); void unregister_kprobes(struct kprobe **kps, int num); -unsigned long arch_deref_entry_point(void *); int register_kretprobe(struct kretprobe *rp); void unregister_kretprobe(struct kretprobe *rp); @@ -373,6 +367,9 @@ void dump_kprobe(struct kprobe *kp); void *alloc_insn_page(void); void free_insn_page(void *page); +int init_kprobes(void); +void debugfs_kprobe_init(struct dentry *dir); + #else /* !CONFIG_KPROBES: */ static inline int kprobes_built_in(void) @@ -431,11 +428,29 @@ static inline int enable_kprobe(struct kprobe *kp) return -ENOSYS; } +static inline int init_kprobes(void) +{ + return 0; +} + +static inline void debugfs_kprobe_init(struct dentry *dir) +{ +} +#endif /* CONFIG_KPROBES */ + +#ifdef CONFIG_KPROBES_BLACKLIST +extern bool within_kprobe_blacklist(unsigned long addr); +extern int kprobe_add_ksym_blacklist(unsigned long entry); +extern int kprobe_add_area_blacklist(unsigned long start, unsigned long end); +kprobe_opcode_t *kprobe_lookup_name(const char *name, unsigned int offset); +unsigned long arch_deref_entry_point(void *); +#else /* CONFIG_KPROBES_BLACKLIST */ static inline bool within_kprobe_blacklist(unsigned long addr) { return true; } -#endif /* CONFIG_KPROBES */ +#endif /* CONFIG_KPROBES_BLACKLIST */ + static inline int disable_kretprobe(struct kretprobe *rp) { return disable_kprobe(&rp->kp); diff --git a/kernel/Makefile b/kernel/Makefile index 4cb4130ced32..7ce7948575df 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -82,6 +82,7 @@ obj-$(CONFIG_AUDITSYSCALL) += auditsc.o audit_watch.o audit_fsnotify.o audit_tre obj-$(CONFIG_GCOV_KERNEL) += gcov/ obj-$(CONFIG_KCOV) += kcov.o obj-$(CONFIG_KPROBES) += kprobes.o +obj-$(CONFIG_KPROBES_BLACKLIST) += kprobes_blacklist.o obj-$(CONFIG_FAIL_FUNCTION) += fail_function.o obj-$(CONFIG_KGDB) += debug/ obj-$(CONFIG_DETECT_HUNG_TASK) += hung_task.o diff --git a/kernel/kprobes.c b/kernel/kprobes.c index 2625c241ac00..b592316a5d50 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -59,20 +59,11 @@ static struct { raw_spinlock_t lock ____cacheline_aligned_in_smp; } kretprobe_table_locks[KPROBE_TABLE_SIZE]; -kprobe_opcode_t * __weak kprobe_lookup_name(const char *name, - unsigned int __unused) -{ - return ((kprobe_opcode_t *)(kallsyms_lookup_name(name))); -} - static raw_spinlock_t *kretprobe_table_lock_ptr(unsigned long hash) { return &(kretprobe_table_locks[hash].lock); } -/* Blacklist -- list of struct kprobe_blacklist_entry */ -static LIST_HEAD(kprobe_blacklist); - #ifdef __ARCH_WANT_KPROBES_INSN_SLOT /* * kprobe->ainsn.insn points to the copy of the instruction to be @@ -1419,50 +1410,6 @@ static int register_aggr_kprobe(struct kprobe *orig_p, struct kprobe *p) return ret; } -bool __weak arch_within_kprobe_blacklist(unsigned long addr) -{ - /* The __kprobes marked functions and entry code must not be probed */ - return addr >= (unsigned long)__kprobes_text_start && - addr < (unsigned long)__kprobes_text_end; -} - -static bool __within_kprobe_blacklist(unsigned long addr) -{ - struct kprobe_blacklist_entry *ent; - - if (arch_within_kprobe_blacklist(addr)) - return true; - /* - * If there exists a kprobe_blacklist, verify and - * fail any probe registration in the prohibited area - */ - list_for_each_entry(ent, &kprobe_blacklist, list) { - if (addr >= ent->start_addr && addr < ent->end_addr) - return true; - } - return false; -} - -bool within_kprobe_blacklist(unsigned long addr) -{ - char symname[KSYM_NAME_LEN], *p; - - if (__within_kprobe_blacklist(addr)) - return true; - - /* Check if the address is on a suffixed-symbol */ - if (!lookup_symbol_name(addr, symname)) { - p = strchr(symname, '.'); - if (!p) - return false; - *p = '\0'; - addr = (unsigned long)kprobe_lookup_name(symname, 0); - if (addr) - return __within_kprobe_blacklist(addr); - } - return false; -} - /* * If we have a symbol_name argument, look it up and add the offset field * to it. This way, we can specify a relative address to a symbol. @@ -1845,11 +1792,6 @@ static struct notifier_block kprobe_exceptions_nb = { .priority = 0x7fffffff /* we need to be notified first */ }; -unsigned long __weak arch_deref_entry_point(void *entry) -{ - return (unsigned long)entry; -} - #ifdef CONFIG_KRETPROBES /* * This kprobe pre_handler is registered with every kretprobe. When probe @@ -2143,78 +2085,6 @@ void dump_kprobe(struct kprobe *kp) } NOKPROBE_SYMBOL(dump_kprobe); -int kprobe_add_ksym_blacklist(unsigned long entry) -{ - struct kprobe_blacklist_entry *ent; - unsigned long offset = 0, size = 0; - - if (!kernel_text_address(entry) || - !kallsyms_lookup_size_offset(entry, &size, &offset)) - return -EINVAL; - - ent = kmalloc(sizeof(*ent), GFP_KERNEL); - if (!ent) - return -ENOMEM; - ent->start_addr = entry; - ent->end_addr = entry + size; - INIT_LIST_HEAD(&ent->list); - list_add_tail(&ent->list, &kprobe_blacklist); - - return (int)size; -} - -/* Add all symbols in given area into kprobe blacklist */ -int kprobe_add_area_blacklist(unsigned long start, unsigned long end) -{ - unsigned long entry; - int ret = 0; - - for (entry = start; entry < end; entry += ret) { - ret = kprobe_add_ksym_blacklist(entry); - if (ret < 0) - return ret; - if (ret == 0) /* In case of alias symbol */ - ret = 1; - } - return 0; -} - -int __init __weak arch_populate_kprobe_blacklist(void) -{ - return 0; -} - -/* - * Lookup and populate the kprobe_blacklist. - * - * Unlike the kretprobe blacklist, we'll need to determine - * the range of addresses that belong to the said functions, - * since a kprobe need not necessarily be at the beginning - * of a function. - */ -static int __init populate_kprobe_blacklist(unsigned long *start, - unsigned long *end) -{ - unsigned long entry; - unsigned long *iter; - int ret; - - for (iter = start; iter < end; iter++) { - entry = arch_deref_entry_point((void *)*iter); - ret = kprobe_add_ksym_blacklist(entry); - if (ret == -EINVAL) - continue; - if (ret < 0) - return ret; - } - - /* Symbols in __kprobes_text are blacklisted */ - ret = kprobe_add_area_blacklist((unsigned long)__kprobes_text_start, - (unsigned long)__kprobes_text_end); - - return ret ? : arch_populate_kprobe_blacklist(); -} - /* Module notifier call back, checking kprobes on the module */ static int kprobes_module_callback(struct notifier_block *nb, unsigned long val, void *data) @@ -2264,11 +2134,9 @@ static struct notifier_block kprobe_module_nb = { .priority = 0 }; -/* Markers of _kprobe_blacklist section */ -extern unsigned long __start_kprobe_blacklist[]; -extern unsigned long __stop_kprobe_blacklist[]; -static int __init init_kprobes(void) + +int __init init_kprobes(void) { int i, err = 0; @@ -2280,13 +2148,6 @@ static int __init init_kprobes(void) raw_spin_lock_init(&(kretprobe_table_locks[i].lock)); } - err = populate_kprobe_blacklist(__start_kprobe_blacklist, - __stop_kprobe_blacklist); - if (err) { - pr_err("kprobes: failed to populate blacklist: %d\n", err); - pr_err("Please take care of using kprobes.\n"); - } - if (kretprobe_blacklist_size) { /* lookup the function address from its name */ for (i = 0; kretprobe_blacklist[i].name != NULL; i++) { @@ -2322,7 +2183,6 @@ static int __init init_kprobes(void) init_test_probes(); return err; } -subsys_initcall(init_kprobes); #ifdef CONFIG_DEBUG_FS static void report_probe(struct seq_file *pi, struct kprobe *p, @@ -2417,54 +2277,6 @@ static const struct file_operations debugfs_kprobes_operations = { .release = seq_release, }; -/* kprobes/blacklist -- shows which functions can not be probed */ -static void *kprobe_blacklist_seq_start(struct seq_file *m, loff_t *pos) -{ - return seq_list_start(&kprobe_blacklist, *pos); -} - -static void *kprobe_blacklist_seq_next(struct seq_file *m, void *v, loff_t *pos) -{ - return seq_list_next(v, &kprobe_blacklist, pos); -} - -static int kprobe_blacklist_seq_show(struct seq_file *m, void *v) -{ - struct kprobe_blacklist_entry *ent = - list_entry(v, struct kprobe_blacklist_entry, list); - - /* - * If /proc/kallsyms is not showing kernel address, we won't - * show them here either. - */ - if (!kallsyms_show_value()) - seq_printf(m, "0x%px-0x%px\t%ps\n", NULL, NULL, - (void *)ent->start_addr); - else - seq_printf(m, "0x%px-0x%px\t%ps\n", (void *)ent->start_addr, - (void *)ent->end_addr, (void *)ent->start_addr); - return 0; -} - -static const struct seq_operations kprobe_blacklist_seq_ops = { - .start = kprobe_blacklist_seq_start, - .next = kprobe_blacklist_seq_next, - .stop = kprobe_seq_stop, /* Reuse void function */ - .show = kprobe_blacklist_seq_show, -}; - -static int kprobe_blacklist_open(struct inode *inode, struct file *filp) -{ - return seq_open(filp, &kprobe_blacklist_seq_ops); -} - -static const struct file_operations debugfs_kprobe_blacklist_ops = { - .open = kprobe_blacklist_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, -}; - static int arm_all_kprobes(void) { struct hlist_head *head; @@ -2615,23 +2427,13 @@ static const struct file_operations fops_kp = { .llseek = default_llseek, }; -static int __init debugfs_kprobe_init(void) +void __init debugfs_kprobe_init(struct dentry *dir) { - struct dentry *dir; unsigned int value = 1; - dir = debugfs_create_dir("kprobes", NULL); - debugfs_create_file("list", 0400, dir, NULL, &debugfs_kprobes_operations); debugfs_create_file("enabled", 0600, dir, &value, &fops_kp); - - debugfs_create_file("blacklist", 0400, dir, NULL, - &debugfs_kprobe_blacklist_ops); - - return 0; } - -late_initcall(debugfs_kprobe_init); #endif /* CONFIG_DEBUG_FS */ diff --git a/kernel/kprobes_blacklist.c b/kernel/kprobes_blacklist.c new file mode 100644 index 000000000000..ee101dfc8899 --- /dev/null +++ b/kernel/kprobes_blacklist.c @@ -0,0 +1,260 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Kernel Probes (KProbes) + * kernel/kprobes_blacklist.c + * + * Copyright (C) IBM Corporation, 2002, 2004 + * + * 2002-Oct Created by Vamsi Krishna S Kernel + * Probes initial implementation (includes suggestions from + * Rusty Russell). + * 2004-Aug Updated by Prasanna S Panchamukhi with + * hlists and exceptions notifier as suggested by Andi Kleen. + * 2004-July Suparna Bhattacharya added jumper probes + * interface to access function arguments. + * 2004-Sep Prasanna S Panchamukhi Changed Kprobes + * exceptions notifier to be first on the priority list. + * 2005-May Hien Nguyen , Jim Keniston + * and Prasanna S Panchamukhi + * added function-return probes. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/* Blacklist -- list of struct kprobe_blacklist_entry */ +static LIST_HEAD(kprobe_blacklist); + +kprobe_opcode_t * __weak kprobe_lookup_name(const char *name, + unsigned int __unused) +{ + return ((kprobe_opcode_t *)(kallsyms_lookup_name(name))); +} + +bool __weak arch_within_kprobe_blacklist(unsigned long addr) +{ + /* The __kprobes marked functions and entry code must not be probed */ + return addr >= (unsigned long)__kprobes_text_start && + addr < (unsigned long)__kprobes_text_end; +} + +unsigned long __weak arch_deref_entry_point(void *entry) +{ + return (unsigned long)entry; +} + +static bool __within_kprobe_blacklist(unsigned long addr) +{ + struct kprobe_blacklist_entry *ent; + + if (arch_within_kprobe_blacklist(addr)) + return true; + /* + * If there exists a kprobe_blacklist, verify and + * fail any probe registration in the prohibited area + */ + list_for_each_entry(ent, &kprobe_blacklist, list) { + if (addr >= ent->start_addr && addr < ent->end_addr) + return true; + } + return false; +} + +bool within_kprobe_blacklist(unsigned long addr) +{ + char symname[KSYM_NAME_LEN], *p; + + if (__within_kprobe_blacklist(addr)) + return true; + + /* Check if the address is on a suffixed-symbol */ + if (!lookup_symbol_name(addr, symname)) { + p = strchr(symname, '.'); + if (!p) + return false; + *p = '\0'; + addr = (unsigned long)kprobe_lookup_name(symname, 0); + if (addr) + return __within_kprobe_blacklist(addr); + } + return false; +} + +int kprobe_add_ksym_blacklist(unsigned long entry) +{ + struct kprobe_blacklist_entry *ent; + unsigned long offset = 0, size = 0; + + if (!kernel_text_address(entry) || + !kallsyms_lookup_size_offset(entry, &size, &offset)) + return -EINVAL; + + ent = kmalloc(sizeof(*ent), GFP_KERNEL); + if (!ent) + return -ENOMEM; + ent->start_addr = entry; + ent->end_addr = entry + size; + INIT_LIST_HEAD(&ent->list); + list_add_tail(&ent->list, &kprobe_blacklist); + + return (int)size; +} + +/* Add all symbols in given area into kprobe blacklist */ +int kprobe_add_area_blacklist(unsigned long start, unsigned long end) +{ + unsigned long entry; + int ret = 0; + + for (entry = start; entry < end; entry += ret) { + ret = kprobe_add_ksym_blacklist(entry); + if (ret < 0) + return ret; + if (ret == 0) /* In case of alias symbol */ + ret = 1; + } + return 0; +} + +int __init __weak arch_populate_kprobe_blacklist(void) +{ + return 0; +} + +/* + * Lookup and populate the kprobe_blacklist. + * + * Unlike the kretprobe blacklist, we'll need to determine + * the range of addresses that belong to the said functions, + * since a kprobe need not necessarily be at the beginning + * of a function. + */ +static int __init populate_kprobe_blacklist(unsigned long *start, + unsigned long *end) +{ + unsigned long entry; + unsigned long *iter; + int ret; + + for (iter = start; iter < end; iter++) { + entry = arch_deref_entry_point((void *)*iter); + ret = kprobe_add_ksym_blacklist(entry); + if (ret == -EINVAL) + continue; + if (ret < 0) + return ret; + } + + /* Symbols in __kprobes_text are blacklisted */ + ret = kprobe_add_area_blacklist((unsigned long)__kprobes_text_start, + (unsigned long)__kprobes_text_end); + + return ret ? : arch_populate_kprobe_blacklist(); +} + +/* Markers of _kprobe_blacklist section */ +extern unsigned long __start_kprobe_blacklist[]; +extern unsigned long __stop_kprobe_blacklist[]; + +static int __init init_kprobes_blacklist(void) +{ + int err; + + err = populate_kprobe_blacklist(__start_kprobe_blacklist, + __stop_kprobe_blacklist); + if (err) { + pr_err("kprobes: failed to populate blacklist: %d\n", err); + pr_err("Please take care of using kprobes.\n"); + } + + return init_kprobes(); +} +subsys_initcall(init_kprobes_blacklist); + +#ifdef CONFIG_DEBUG_FS +/* kprobes/blacklist -- shows which functions can not be probed */ +static void *kprobe_blacklist_seq_start(struct seq_file *m, loff_t *pos) +{ + return seq_list_start(&kprobe_blacklist, *pos); +} + +static void *kprobe_blacklist_seq_next(struct seq_file *m, void *v, loff_t *pos) +{ + return seq_list_next(v, &kprobe_blacklist, pos); +} + +static void kprobe_blacklist_seq_stop(struct seq_file *f, void *v) +{ + /* Nothing to do */ +} + +static int kprobe_blacklist_seq_show(struct seq_file *m, void *v) +{ + struct kprobe_blacklist_entry *ent = + list_entry(v, struct kprobe_blacklist_entry, list); + + /* + * If /proc/kallsyms is not showing kernel address, we won't + * show them here either. + */ + if (!kallsyms_show_value()) + seq_printf(m, "0x%px-0x%px\t%ps\n", NULL, NULL, + (void *)ent->start_addr); + else + seq_printf(m, "0x%px-0x%px\t%ps\n", (void *)ent->start_addr, + (void *)ent->end_addr, (void *)ent->start_addr); + return 0; +} + +static const struct seq_operations kprobe_blacklist_seq_ops = { + .start = kprobe_blacklist_seq_start, + .next = kprobe_blacklist_seq_next, + .stop = kprobe_blacklist_seq_stop, + .show = kprobe_blacklist_seq_show, +}; + +static int kprobe_blacklist_open(struct inode *inode, struct file *filp) +{ + return seq_open(filp, &kprobe_blacklist_seq_ops); +} + +static const struct file_operations debugfs_kprobe_blacklist_ops = { + .open = kprobe_blacklist_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + +static int __init debugfs_kprobe_blacklist_init(void) +{ + struct dentry *dir; + + dir = debugfs_create_dir("kprobes", NULL); + debugfs_kprobe_init(dir); + + debugfs_create_file("blacklist", 0400, dir, NULL, + &debugfs_kprobe_blacklist_ops); + + return 0; +} +late_initcall(debugfs_kprobe_blacklist_init); +#endif /* CONFIG_DEBUG_FS */ diff --git a/lib/Kconfig.kgdb b/lib/Kconfig.kgdb index ffa7a76de086..da372d335882 100644 --- a/lib/Kconfig.kgdb +++ b/lib/Kconfig.kgdb @@ -7,6 +7,7 @@ menuconfig KGDB bool "KGDB: kernel debugger" depends on HAVE_ARCH_KGDB depends on DEBUG_KERNEL + select KPROBES_BLACKLIST help If you say Y here, it will be possible to remotely debug the kernel using gdb. It is recommended but not required, that