Received: by 2002:ab2:3350:0:b0:1f4:6588:b3a7 with SMTP id o16csp1317610lqe; Mon, 8 Apr 2024 05:52:34 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCWKGIuXva7v7uzxm4KmktprCMV43Ro1npPEo48bd0LYy/OAKMGn0wnnUK4EDdZbgKJt0rSWq1JDigHJnNbapYc038CcKinCquGvYbTCRg== X-Google-Smtp-Source: AGHT+IEQCySwazfSG6P3HVXrD+Fm/1O++4JI07+Q2MXDRIPTg3Ak/vgDWcC7sjXmwoeDW0pttsed X-Received: by 2002:a17:90b:380e:b0:2a2:d10d:d30d with SMTP id mq14-20020a17090b380e00b002a2d10dd30dmr8799172pjb.26.1712580754443; Mon, 08 Apr 2024 05:52:34 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1712580754; cv=pass; d=google.com; s=arc-20160816; b=qIan8GLXc3VAKVlNgKwRJHVDPWzSiYUIBiHu4rmz92jcnZsiSa5E0LLC2ge9KBYQPH 1tKpJ0H9rufbJUI9OB1JtZy7GJE7WRtRGrGYpRt4ZR0Fg9CSbHrkWtS7x2M8hnqQ+UPZ RMiapcqXvUcWOZnyoz/TGvTn22jTpMxjonXLo+ILtHZF4VIaHCcak9C9DaLPc8/Sxn5F dmXvJhu3dI3Rc0WHwlKO+fjawr4MGvguC91Y0My3Djtt3Fqg+oDE2r59t1qxDyy5sKAw wLX2jUJNmT8rJYI0wYy2coj4vFz0I9UNiXMu99VWt+uRNypqvg4Yyw5jCkrMVyVJEtHW 53yA== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:references:in-reply-to:message-id :subject:cc:to:from:date:dkim-signature; bh=py6bA+hp1PrNafoy04BjyF7borTN3FEppCB29IkmTa8=; fh=5+bcjx7aBibEOdQMadHvNOYSE+oGV0H7DWESFgfO3u8=; b=OXWv2tfazzhCULlP6r/QG0riFf3vSnmL5azB5de0SI2aWkGEJtaWg0FYIQFRmRByL/ aYWF5+EefGCZQzvXFIBCUblIn2nB08MgL2RmxbRqEOHaydV6lPRDqleKxhqQtQE+80R6 q2gSqFTgeJhjraKFlZtMWltJt8Oswpu0ezSopnRr8eWd21ZKY3OZBS35Jkxfa9asPt5f g9QCoe6kv43Iwxb4J4Ek7ZH+96iEcMgigh4uHGz5M+jyojzakdHfwLIlvJuaaTtE/CHv it4j229+jlFHxEcEr2nDsBEliUiLmmuqCQeVccwnchXebEv7RZBditskAeiuBpPqYV5b EKxw==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=M0xMeCRG; arc=pass (i=1 dkim=pass dkdomain=kernel.org); spf=pass (google.com: domain of linux-kernel+bounces-135331-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:40f1:3f00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-135331-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from sy.mirrors.kernel.org (sy.mirrors.kernel.org. [2604:1380:40f1:3f00::1]) by mx.google.com with ESMTPS id cu24-20020a17090afa9800b002a25ece235asi8216959pjb.95.2024.04.08.05.52.33 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 08 Apr 2024 05:52:34 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel+bounces-135331-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:40f1:3f00::1 as permitted sender) client-ip=2604:1380:40f1:3f00::1; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=M0xMeCRG; arc=pass (i=1 dkim=pass dkdomain=kernel.org); spf=pass (google.com: domain of linux-kernel+bounces-135331-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:40f1:3f00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-135331-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sy.mirrors.kernel.org (Postfix) with ESMTPS id 23F64B24E70 for ; Mon, 8 Apr 2024 12:41:15 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 1BFB16D1BD; Mon, 8 Apr 2024 12:41:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="M0xMeCRG" Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 25A436A014; Mon, 8 Apr 2024 12:41:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712580067; cv=none; b=Qh9zepN0+7kCmHrFbSanlMipaseF4IFT2t8185gTFYFyu/3mc8QxqpXhQuL+xgMT+9EFsT/qXr8HgX2/gSb3OWDY6GcqJ0YS8PaI+6wwyHg650XdTxPEaxxSIo4jTwqid14kN0ucR29HimvM72P6QtyUkSyfeHZQVdTx9lt6TZI= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712580067; c=relaxed/simple; bh=uznQfg3AOHrzxljdeifxnUVqLDxe5aZvgkCnddzWjPI=; h=Date:From:To:Cc:Subject:Message-Id:In-Reply-To:References: Mime-Version:Content-Type; b=GCe+OtQ3pJBpb9fQ7+3yHdyA0+9PqKjPtH96JIb8/D70pgIzGfXH2kjioA4hLLd37nO+5P0S40r9mKGUBs2UTGReyWYsNmjZ/0phHbA+cw0HIq5Xw8NdMKLru2tNZMKcb/CRUVloe4PKBUCkPADIw2wS4L9NS2v1hFaBoWNr53c= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=M0xMeCRG; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id 57CCAC433C7; Mon, 8 Apr 2024 12:41:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1712580066; bh=uznQfg3AOHrzxljdeifxnUVqLDxe5aZvgkCnddzWjPI=; h=Date:From:To:Cc:Subject:In-Reply-To:References:From; b=M0xMeCRG7CKo7TXZmry2s3woUlQ93apSYPU5CjKDJUjsUbdCCD2qeAj1KI8TOaB4Z 7HbwMBjnM9i2MUiF3IAQnSzZ/dLqkFT14hnC5ejJN0Lg7TWOTR/uqSm523aVq+wJCG iux37RJFVsYacSU1l397/li8Ogz5SYj0H3dlLejRW1/K/eYtsh23ejlBw9nSyfavDo D8GkKZK05hySKPpmFJTjCORgED2UkN4uc073Z2APkXAoJvvfvu3+9+3F+0hXwQqDDU TlA4xV6RcKIBT0BBUmYDR7x8uPTEr2IgM1GasC1xfg+xZ2JpwT7zq+Xk7fCz0Gwg30 HY3itlSwYS9Ow== Date: Mon, 8 Apr 2024 21:41:02 +0900 From: Masami Hiramatsu (Google) To: Zheng Yejian Cc: , , , , Subject: Re: [PATCH v2] kprobes: Avoid possible warn in __arm_kprobe_ftrace() Message-Id: <20240408214102.be792c5cefd5ab757ef32a14@kernel.org> In-Reply-To: <20240408083403.3302274-1-zhengyejian1@huawei.com> References: <20240407035904.2556645-1-zhengyejian1@huawei.com> <20240408083403.3302274-1-zhengyejian1@huawei.com> X-Mailer: Sylpheed 3.7.0 (GTK+ 2.24.33; x86_64-pc-linux-gnu) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit Hi Zheng, On Mon, 8 Apr 2024 16:34:03 +0800 Zheng Yejian wrote: > There is once warn in __arm_kprobe_ftrace() on: > > ret = ftrace_set_filter_ip(ops, (unsigned long)p->addr, 0, 0); > if (WARN_ONCE(..., "Failed to arm kprobe-ftrace at %pS (error %d)\n", ...) > return ret; > > This warning is generated because 'p->addr' is detected to be not a valid > ftrace location in ftrace_set_filter_ip(). The ftrace address check is done > by check_ftrace_location() at the beginning of check_kprobe_address_safe(). > At that point, ftrace_location(addr) == addr should return true if the > module is loaded. Then the module is searched twice: > 1. in is_module_text_address(), we find that 'p->addr' is in a module; > 2. in __module_text_address(), we find the module; > > If the module has just been unloaded before the second search, then > '*probed_mod' is NULL and we would not go to get the module refcount, > then the return value of check_kprobe_address_safe() would be 0, but > actually we need to return -EINVAL. OK, so you found a race window in check_kprobe_address_safe(). It does something like below. check_kprobe_address_safe() { ... /* Timing [A] */ if (!(core_kernel_text(p->addr) || is_module_text_address(p->addr)) || ...(other reserved address check)) { return -EINVAL; } /* Timing [B] */ *probed_mod = __module_text_address(p->addr): if (*probe_mod) { if (!try_module_get(*probed_mod)) { return -ENOENT; } ... } } So, if p->addr is in a module which is alive at the timing [A], but unloaded at timing [B], 'p->addr' is passed the 'is_module_text_address(p->addr)' check, but *probed_mod becomes NULL. Thus the corresponding module is not referenced and kprobe_arm(p) will access a wrong address (use after free). This happens either kprobe on ftrace is enabled or not. To fix this problem, we should move the mutex_lock(kprobe_mutex) before check_kprobe_address_safe() because kprobe_module_callback() also lock it so it can stop module unloading. Can you ensure this will fix your problem? I think your patch is just optimizing but not fixing the fundamental problem, which is we don't have an atomic search symbol and get module API. In that case, we should stop a whole module unloading system until registering a new kprobe on a module. (After registering the kprobe, the callback can mark it gone and disarm_kprobe does not work anymore.) diff --git a/kernel/kprobes.c b/kernel/kprobes.c index 9d9095e81792..94eaefd1bc51 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -1633,11 +1633,11 @@ int register_kprobe(struct kprobe *p) p->nmissed = 0; INIT_LIST_HEAD(&p->list); + mutex_lock(&kprobe_mutex); + ret = check_kprobe_address_safe(p, &probed_mod); if (ret) - return ret; - - mutex_lock(&kprobe_mutex); + goto out; if (on_func_entry) p->flags |= KPROBE_FLAG_ON_FUNC_ENTRY; ---- Thank you, > > To fix it, originally we can simply check 'p->addr' is out of text again, > like below. But that would check twice respectively in kernel text and > module text, so finally I reduce them to be once. > > if (!(core_kernel_text((unsigned long) p->addr) || > is_module_text_address((unsigned long) p->addr)) || ...) { > ret = -EINVAL; > goto out; > } > ... > *probed_mod = __module_text_address((unsigned long) p->addr); > if (*probed_mod) { > ... > } else if (!core_kernel_text((unsigned long) p->addr)) { // check again! > ret = -EINVAL; > goto out; > } > > Signed-off-by: Zheng Yejian > --- > kernel/kprobes.c | 18 ++++++++++++------ > 1 file changed, 12 insertions(+), 6 deletions(-) > > v2: > - Update commit messages and comments as suggested by Masami. > Link: https://lore.kernel.org/all/20240408115038.b0c85767bf1f249eccc32fff@kernel.org/ > > v1: > - Link: https://lore.kernel.org/all/20240407035904.2556645-1-zhengyejian1@huawei.com/ > > diff --git a/kernel/kprobes.c b/kernel/kprobes.c > index 9d9095e81792..65adc815fc6e 100644 > --- a/kernel/kprobes.c > +++ b/kernel/kprobes.c > @@ -1567,10 +1567,17 @@ static int check_kprobe_address_safe(struct kprobe *p, > jump_label_lock(); > preempt_disable(); > > - /* Ensure it is not in reserved area nor out of text */ > - if (!(core_kernel_text((unsigned long) p->addr) || > - is_module_text_address((unsigned long) p->addr)) || > - in_gate_area_no_mm((unsigned long) p->addr) || > + /* Ensure the address is in a text area, and find a module if exists. */ > + *probed_mod = NULL; > + if (!core_kernel_text((unsigned long) p->addr)) { > + *probed_mod = __module_text_address((unsigned long) p->addr); > + if (!(*probed_mod)) { > + ret = -EINVAL; > + goto out; > + } > + } > + /* Ensure it is not in reserved area. */ > + if (in_gate_area_no_mm((unsigned long) p->addr) || > within_kprobe_blacklist((unsigned long) p->addr) || > jump_label_text_reserved(p->addr, p->addr) || > static_call_text_reserved(p->addr, p->addr) || > @@ -1580,8 +1587,7 @@ static int check_kprobe_address_safe(struct kprobe *p, > goto out; > } > > - /* Check if 'p' is probing a module. */ > - *probed_mod = __module_text_address((unsigned long) p->addr); > + /* Get module refcount and reject __init functions for loaded modules. */ > if (*probed_mod) { > /* > * We must hold a refcount of the probed module while updating > -- > 2.25.1 > -- Masami Hiramatsu (Google)