Message ID | 20230309114919.63973-1-xiafukun@huawei.com |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel-owner@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:5915:0:0:0:0:0 with SMTP id v21csp246515wrd; Thu, 9 Mar 2023 04:00:53 -0800 (PST) X-Google-Smtp-Source: AK7set/3SPYJzPFpLV8yQEmZjwys5txuSVNNoPsCAr02fZ8dahUwooR4GEePVhlli2D5Tthacls4 X-Received: by 2002:a05:6a21:788b:b0:cb:77f0:9a27 with SMTP id bf11-20020a056a21788b00b000cb77f09a27mr24149292pzc.24.1678363253010; Thu, 09 Mar 2023 04:00:53 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1678363252; cv=none; d=google.com; s=arc-20160816; b=KzEd4Ng0pVQ0mAnSWUDFX28ncp3DhMr8le6LD3qHO3/BaCvBrspAjoFAW7xbhID7N4 zAnrLlph2GLVkghtH/878HIShh+LqTjEnOflqlJxuewB46BQ204wJy+dasX7j7WC1GSZ FQh8LRAQicGsgzRlFsKc6WcLqATkdslJn61sAc31s5IeeMuJkZZJ1fIQJXTjKACLTMur /aig5ADbVooo1geJppFBqmD/qcJrDHaBBOuJnd8UkDPCUTpewQoSr0/97bcjqBQqj4At XLFJsquZ7tmsoP71hO+a0HHqqvA8CqVybiW3A24Csl5FeZMHfl0xT8GFSkATDuxLUyTH Rocg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:mime-version:message-id:date:subject:cc:to:from; bh=SWIILWMcYXAQAUU1RuEgeFE9uLmdquO5sjsinxw4FwI=; b=RWCVs+n2/ZqeZHPQlgznLteWkazQGH4zpBGIMQywBpCIyyI3bz54X2+HzJRf1kZEG+ UDRkXzhui38UwDAHY0ZxEEXEglz7y3C/oX/X/fo2vTF8amlb8AnLfrDrPQcOIt1Ak9QD 91F+mDH95OWaQz5SdWifltatvywLih8Tb2X7k4rSNbH+dKnd6/qK3n6ZlqiT8SfJPFOl XNJUqBtprFU0MpG756to9vXauQTtG+stFIGsk3JGKur3P2HhLIZu9BS2tVrgkj++e6fH c3+04e4NGjjkerStJlYhDQiawRTvw09/SkpKYLw3QvFiHl1kSxncojbSXlhERP1eK/VG 0dyQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=huawei.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id b7-20020a656687000000b00502ed95c83bsi16880224pgw.362.2023.03.09.04.00.37; Thu, 09 Mar 2023 04:00:52 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=huawei.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231440AbjCILvv (ORCPT <rfc822;carlos.wei.hk@gmail.com> + 99 others); Thu, 9 Mar 2023 06:51:51 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50454 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231725AbjCILva (ORCPT <rfc822;linux-kernel@vger.kernel.org>); Thu, 9 Mar 2023 06:51:30 -0500 Received: from szxga01-in.huawei.com (szxga01-in.huawei.com [45.249.212.187]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 26A90E775A for <linux-kernel@vger.kernel.org>; Thu, 9 Mar 2023 03:51:22 -0800 (PST) Received: from kwepemi500009.china.huawei.com (unknown [172.30.72.53]) by szxga01-in.huawei.com (SkyGuard) with ESMTP id 4PXSDT3BPRzfZ5S; Thu, 9 Mar 2023 19:50:33 +0800 (CST) Received: from huawei.com (10.67.175.85) by kwepemi500009.china.huawei.com (7.221.188.199) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.21; Thu, 9 Mar 2023 19:51:20 +0800 From: Xia Fukun <xiafukun@huawei.com> To: <gregkh@linuxfoundation.org>, <prajnoha@redhat.com> CC: <linux-kernel@vger.kernel.org>, <xiafukun@huawei.com> Subject: [PATCH v3] kobject: Fix global-out-of-bounds in kobject_action_type() Date: Thu, 9 Mar 2023 19:49:19 +0800 Message-ID: <20230309114919.63973-1-xiafukun@huawei.com> X-Mailer: git-send-email 2.17.1 MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [10.67.175.85] X-ClientProxiedBy: dggems706-chm.china.huawei.com (10.3.19.183) To kwepemi500009.china.huawei.com (7.221.188.199) X-CFilter-Loop: Reflected X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_MED, SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: <linux-kernel.vger.kernel.org> X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1759891426262246822?= X-GMAIL-MSGID: =?utf-8?q?1759891426262246822?= |
Series |
[v3] kobject: Fix global-out-of-bounds in kobject_action_type()
|
|
Commit Message
Xia Fukun
March 9, 2023, 11:49 a.m. UTC
The following c language code can trigger KASAN's global variable
out-of-bounds access error in kobject_action_type():
int main() {
int fd;
char *filename = "/sys/block/ram12/uevent";
char str[86] = "offline";
int len = 86;
fd = open(filename, O_WRONLY);
if (fd == -1) {
printf("open");
exit(1);
}
if (write(fd, str, len) == -1) {
printf("write");
exit(1);
}
close(fd);
return 0;
}
Function kobject_action_type() receives the input parameters buf and count,
where count is the length of the string buf.
In the use case we provided, count is 86, the count_first is 85.
Buf points to a string with a length of 86, and its first seven
characters are "offline".
In line 87 of the code, kobject_actions[action] is the string "offline"
with the length of 7,an out-of-boundary access will appear:
kobject_actions[action][85].
Modify the judgment logic in line 87. If the length of the string
kobject_actions[action] is greater than count_first(e.g. buf is "off",
count is 3), continue the loop.
Otherwise, the match is considered successful.
This change means that our test case will be successfully parsed as an
offline event and no out-of-bounds access error will occur.
Fixes: f36776fafbaa ("kobject: support passing in variables for synthetic uevents")
Signed-off-by: Xia Fukun <xiafukun@huawei.com>
---
v2 -> v3:
- only declare that it is the latest version of the patch, no change
v1 -> v2:
- modify the matching logic
lib/kobject_uevent.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
Comments
On Thu, Mar 09, 2023 at 07:49:19PM +0800, Xia Fukun wrote: > The following c language code can trigger KASAN's global variable > out-of-bounds access error in kobject_action_type(): > > int main() { > int fd; > char *filename = "/sys/block/ram12/uevent"; > char str[86] = "offline"; > int len = 86; > > fd = open(filename, O_WRONLY); > if (fd == -1) { > printf("open"); > exit(1); > } > > if (write(fd, str, len) == -1) { > printf("write"); > exit(1); > } > > close(fd); > return 0; > } > > Function kobject_action_type() receives the input parameters buf and count, > where count is the length of the string buf. > > In the use case we provided, count is 86, the count_first is 85. > Buf points to a string with a length of 86, and its first seven > characters are "offline". > In line 87 of the code, kobject_actions[action] is the string "offline" > with the length of 7,an out-of-boundary access will appear: > > kobject_actions[action][85]. > > Modify the judgment logic in line 87. If the length of the string > kobject_actions[action] is greater than count_first(e.g. buf is "off", > count is 3), continue the loop. > Otherwise, the match is considered successful. > > This change means that our test case will be successfully parsed as an > offline event and no out-of-bounds access error will occur. Yes, but what other test cases did you run on this to verify it works? Given that your previous version broke previously working inputs I need a lot of validation and proof that this change will also not break anything. > > Fixes: f36776fafbaa ("kobject: support passing in variables for synthetic uevents") > Signed-off-by: Xia Fukun <xiafukun@huawei.com> > --- > v2 -> v3: > - only declare that it is the latest version of the patch, no change > > v1 -> v2: > - modify the matching logic > > lib/kobject_uevent.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c > index 7c44b7ae4c5c..474f996895c7 100644 > --- a/lib/kobject_uevent.c > +++ b/lib/kobject_uevent.c > @@ -84,7 +84,7 @@ static int kobject_action_type(const char *buf, size_t count, > for (action = 0; action < ARRAY_SIZE(kobject_actions); action++) { > if (strncmp(kobject_actions[action], buf, count_first) != 0) > continue; > - if (kobject_actions[action][count_first] != '\0') > + if (strlen(kobject_actions[action]) > count_first) I'm sorry, but as I said before, I'm still not convinced that this is correct. Why does this solve the problem? Shouldn't the length check come before we try to compare the string so that strncmp() doesn't have to give a false-positive if the string is too small? And really, this whole function is very hard to follow, is there any chance you can refactor it to be more obviously correct and readable? What about taking advantage of the well-tested string functions we already have for parsing sysfs inputs, like sysfs_match_string()? thanks, greg k-h
On 2023/3/9 20:40, Greg KH wrote:>> >> Modify the judgment logic in line 87. If the length of the string >> kobject_actions[action] is greater than count_first(e.g. buf is "off", >> count is 3), continue the loop. >> Otherwise, the match is considered successful. >> >> This change means that our test case will be successfully parsed as an >> offline event and no out-of-bounds access error will occur. > > Yes, but what other test cases did you run on this to verify it works? > Given that your previous version broke previously working inputs I need > a lot of validation and proof that this change will also not break > anything. > > > I'm sorry, but as I said before, I'm still not convinced that this is > correct. Why does this solve the problem? Shouldn't the length check > come before we try to compare the string so that strncmp() doesn't have > to give a false-positive if the string is too small? > The string "buf" needs to be compared in sequence with the string array defined below to confirm a match with one of them, and the length of these strings ranges from 3 to 7. Checking the length of "buf" in advance still cannot avoid the situation mentioned in this patch(e.g. buf is "off",count is 3) static const char *kobject_actions[] = { [KOBJ_ADD] = "add", [KOBJ_REMOVE] = "remove", [KOBJ_CHANGE] = "change", [KOBJ_MOVE] = "move", [KOBJ_ONLINE] = "online", [KOBJ_OFFLINE] = "offline", [KOBJ_BIND] = "bind", [KOBJ_UNBIND] = "unbind", }; > And really, this whole function is very hard to follow, is there any > chance you can refactor it to be more obviously correct and readable? > What about taking advantage of the well-tested string functions we > already have for parsing sysfs inputs, like sysfs_match_string()? > As for using sysfs_match_string() to refactor this code, do you think whether the following modification methods are suitable and clear? diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c index 7c44b7ae4c5c..5fce99c3cb8b 100644 --- a/lib/kobject_uevent.c +++ b/lib/kobject_uevent.c @@ -66,7 +66,7 @@ static int kobject_action_type(const char *buf, size_t count, enum kobject_action action; size_t count_first; const char *args_start; - int ret = -EINVAL; + int i, ret = -EINVAL; if (count && (buf[count-1] == '\n' || buf[count-1] == '\0')) count--; @@ -81,17 +81,16 @@ static int kobject_action_type(const char *buf, size_t count, } else } else count_first = count; - for (action = 0; action < ARRAY_SIZE(kobject_actions); action++) { - if (strncmp(kobject_actions[action], buf, count_first) != 0) - continue; - if (kobject_actions[action][count_first] != '\0') - continue; - if (args) - *args = args_start; - *type = action; - ret = 0; - break; - } + /* Use sysfs_match_string() to replace the fragile and convoluted loop */ + i = sysfs_match_string(kobject_actions, buf); + if (i < 0) + return ret; + action = kobject_action(i); + if (args) + *args = args_start; + *type = action; + ret = 0; + out: return ret; } > thanks, > > greg k-h Also, I apologize for my previous top-posting behavior. Considering that I am a novice in the kernel field, I hope you can forgive me a lot.
diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c index 7c44b7ae4c5c..474f996895c7 100644 --- a/lib/kobject_uevent.c +++ b/lib/kobject_uevent.c @@ -84,7 +84,7 @@ static int kobject_action_type(const char *buf, size_t count, for (action = 0; action < ARRAY_SIZE(kobject_actions); action++) { if (strncmp(kobject_actions[action], buf, count_first) != 0) continue; - if (kobject_actions[action][count_first] != '\0') + if (strlen(kobject_actions[action]) > count_first) continue; if (args) *args = args_start;