Received: by 2002:ad5:474a:0:0:0:0:0 with SMTP id i10csp3789934imu; Mon, 7 Jan 2019 09:28:08 -0800 (PST) X-Google-Smtp-Source: ALg8bN4YTg/zoa0/VQyR4ioyaZwTEKs9nVDmoOWWOiCLZZS5C8McoUIQ3EXf81WwUH7fPar3DwP5 X-Received: by 2002:a63:8f45:: with SMTP id r5mr11527080pgn.222.1546882088287; Mon, 07 Jan 2019 09:28:08 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1546882088; cv=none; d=google.com; s=arc-20160816; b=L8OpsIW3coaUX9BnkRAPa0Ao3Glgdk14vVTKJueiPqibdWOItEUxya+NTT1u5ttorP Z5n2RFECS4fHu3J7yqwEYdQF04wKdomLQlRHRXk0dNmqm76s5/gMP86ouQElQROyRGSc JxR+qctn2NqMsU49eiLKkv50y1/dC1NfHBJ0BwlvuoeNhlNUr1zubndAWNW0GGHPMAFe z8GVqBL1+nH6nL+kcaFc/uNo5H8KkglCcDPxrqCX3XsQNBNB6JERqk6Vk3Fb0iBEwOBg hj/MeyeSVy4mXibBjojzxg3imeB/li+sIH2sCHX6Tpf4DjS6FOY9KuPx1vjx5vZFmSH8 4lkQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=Co3LYX5YHOn7PqazCuKUR+R3L61lvjwYqbU6kNUr6Bg=; b=cTBdW/g+VeXglr0txWcY644C23xZ2feqOm3Op5t70NWmV34SEYfWyohgAFuHaoE7uW 0H1A1hhC2xJZAr49GINb4ApfJEsFh/OjuMoijrBxNnTMLAkN9+YH55IefMDQZslAcgko B9r3516qMq4rPyHyGsqiYgyt2l4qRu8p7PrEyAAJgSqU8lCYCAw8eMTdT9iU9589IMmT OFrgzCK7P01GNqVaIozQJmfXkL5AZ+BAIX3MB+4Te2X6RSt/jVWVJ4mt4D/XFOwpKW9Z uRPL3w0fVYLve94deiD6V9JLF8KMRiekQQIrn7Tf1Y04UfGHc807ClspmPwTt9SLeQgL 4Nwg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=WtTj9SSb; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id a1si3211061pgk.495.2019.01.07.09.27.53; Mon, 07 Jan 2019 09:28:08 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=WtTj9SSb; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727524AbfAGNc2 (ORCPT + 99 others); Mon, 7 Jan 2019 08:32:28 -0500 Received: from mail.kernel.org ([198.145.29.99]:37614 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726886AbfAGNc1 (ORCPT ); Mon, 7 Jan 2019 08:32:27 -0500 Received: from localhost.localdomain (NE2965lan1.rev.em-net.ne.jp [210.141.244.193]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id ACF3F206B6; Mon, 7 Jan 2019 13:32:25 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1546867946; bh=upSAVVBINLDaCCAR42l1E3Ud7pOlMm7G7Jd4VEqYi7o=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=WtTj9SSb82T0Hsn+bVOcCCSSVxL0f46t2KgUYtULgzGp5SlaCYUTQhst6c3eO1kLP Jf4jztelKbxXTt35ykaLUKtEoXFcMQ9qGHXumiKU9WGTV5erMS5hOE1ILHfZwhOFTt qs7JOb6+L3enYZYMw7L1w7XH2tzEMwffdNZzZ+qw= From: Masami Hiramatsu To: Ingo Molnar Cc: Masami Hiramatsu , peterz@infradead.org, Mathieu Desnoyers , linux-kernel , Andrea Righi , Steven Rostedt Subject: [PATCH 1/2] x86/kprobes: Verify stack frame on kretprobe Date: Mon, 7 Jan 2019 22:32:03 +0900 Message-Id: <154686792365.15479.4125763601617196113.stgit@devbox> X-Mailer: git-send-email 2.13.6 In-Reply-To: <154686789378.15479.2886543882215785247.stgit@devbox> References: <154686789378.15479.2886543882215785247.stgit@devbox> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Verify the stack frame pointer on kretprobe trampoline handler, If the stack frame pointer does not match, it skips the wrong entry and tries to find correct one. This can happen if user puts the kretprobe on the function which can be used in the path of ftrace user-function call. Such functions should not be probed, so this adds a warning message that reports which function should be blacklisted. Signed-off-by: Masami Hiramatsu --- arch/x86/kernel/kprobes/core.c | 26 ++++++++++++++++++++++++++ include/linux/kprobes.h | 1 + 2 files changed, 27 insertions(+) diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c index 4ba75afba527..69b6400d1ce2 100644 --- a/arch/x86/kernel/kprobes/core.c +++ b/arch/x86/kernel/kprobes/core.c @@ -569,6 +569,7 @@ void arch_prepare_kretprobe(struct kretprobe_instance *ri, struct pt_regs *regs) unsigned long *sara = stack_addr(regs); ri->ret_addr = (kprobe_opcode_t *) *sara; + ri->fp = sara; /* Replace the return addr with trampoline addr */ *sara = (unsigned long) &kretprobe_trampoline; @@ -759,15 +760,21 @@ static __used void *trampoline_handler(struct pt_regs *regs) unsigned long flags, orig_ret_address = 0; unsigned long trampoline_address = (unsigned long)&kretprobe_trampoline; kprobe_opcode_t *correct_ret_addr = NULL; + void *frame_pointer; + bool skipped = false; INIT_HLIST_HEAD(&empty_rp); kretprobe_hash_lock(current, &head, &flags); /* fixup registers */ #ifdef CONFIG_X86_64 regs->cs = __KERNEL_CS; + /* On x86-64, we use pt_regs->sp for return address holder. */ + frame_pointer = ®s->sp; #else regs->cs = __KERNEL_CS | get_kernel_rpl(); regs->gs = 0; + /* On x86-32, we use pt_regs->flags for return address holder. */ + frame_pointer = ®s->flags; #endif regs->ip = trampoline_address; regs->orig_ax = ~0UL; @@ -789,8 +796,25 @@ static __used void *trampoline_handler(struct pt_regs *regs) if (ri->task != current) /* another task is sharing our hash bucket */ continue; + /* + * Return probes must be pushed on this hash list correct + * order (same as return order) so that it can be poped + * correctly. However, if we find it is pushed it incorrect + * order, this means we find a function which should not be + * probed, because the wrong order entry is pushed on the + * path of processing other kretprobe itself. + */ + if (ri->fp != frame_pointer) { + if (!skipped) + pr_warn("kretprobe is stacked incorrectly. Trying to fixup.\n"); + skipped = true; + continue; + } orig_ret_address = (unsigned long)ri->ret_addr; + if (skipped) + pr_warn("%ps must be blacklisted because of incorrect kretprobe order\n", + ri->rp->kp.addr); if (orig_ret_address != trampoline_address) /* @@ -808,6 +832,8 @@ static __used void *trampoline_handler(struct pt_regs *regs) if (ri->task != current) /* another task is sharing our hash bucket */ continue; + if (ri->fp != frame_pointer) + continue; orig_ret_address = (unsigned long)ri->ret_addr; if (ri->rp && ri->rp->handler) { diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h index e07e91daaacc..72ff78c33033 100644 --- a/include/linux/kprobes.h +++ b/include/linux/kprobes.h @@ -173,6 +173,7 @@ struct kretprobe_instance { struct kretprobe *rp; kprobe_opcode_t *ret_addr; struct task_struct *task; + void *fp; char data[0]; };