Message ID | 20230517101957.14655-1-xiafukun@huawei.com |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel-owner@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp1026323vqo; Wed, 17 May 2023 03:31:33 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ54yeTV+j+yKHCRL93LfZkC4Zk/aGvy6owPO71iLD1iHmk3HP6yHlM6EDqSoqEu5eePDaUh X-Received: by 2002:a05:6a20:3d95:b0:106:57b9:6da1 with SMTP id s21-20020a056a203d9500b0010657b96da1mr10273059pzi.20.1684319492905; Wed, 17 May 2023 03:31:32 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1684319492; cv=none; d=google.com; s=arc-20160816; b=y/TM3pwaD2aLxMMUmc55Q3mJZorDF85F8mscNRZDQVh4/dSkA5KMnxBd1qR7+afg/r d0b+7YLr8xoIYD66FghWHJnT9sT3r27tvVEfdrJKoZdARzfNRcap/jETS+Lel1VaBf1y tUFN0pyXrKy3WxjZXPJ7+HkzQyIAiQkAqCVqPPmvqjEVzrAglrWYcnWT7Q1ucXQFomm2 WMeSLoE6eIjZPuzc4Q0a30eix1iyZZLvKHvbHZdW0nDpLWSJ/agk66H9Ed++g+/NFtjY q4FthLga3yncmFU7zFI4C0OhiEjzXTRrd082qD6tZcS3+AVtgw7WOoc0lnS/FkwXIulE NgZw== 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=UHC7KvWjh+qUwbutF432yOvfQM15u8RvIjZALKuoHyw=; b=mIz+qa/eGhdHISN87cQAH66lOr8GO4GmVgxLNnn0904Y2It+C2etYL0fmzrJXQpv7t rQnDP0IAJWopOtFk0nQKhUkGc55i7mI3juqF+oLYIN/RmALnMqt09zzTzdu3TkmgSmTg pWS+CjUXawugD/q4IjhO4xeMMSsdjGz/2O6KBOuiHPlzr68mh6+0GD/qrPbaW0Eth4Kd sAD/g2p+IcIIfWIMLFGs+t2jGonotmPrlwcFon+b+qMZDg4lZyN8UT7R8PXiR+AwRX0b i8mixCI+QHKDRov6wn00ISReBG4WQ6F24DFVCMIio4sm6bcU/Ck/Kd4vKdVftkisrJIw rg+Q== 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 t17-20020a639551000000b00528c6c71e0dsi20828626pgn.351.2023.05.17.03.31.18; Wed, 17 May 2023 03:31:32 -0700 (PDT) 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 S230268AbjEQKVZ (ORCPT <rfc822;pacteraone@gmail.com> + 99 others); Wed, 17 May 2023 06:21:25 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45582 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230205AbjEQKVX (ORCPT <rfc822;linux-kernel@vger.kernel.org>); Wed, 17 May 2023 06:21:23 -0400 Received: from szxga01-in.huawei.com (szxga01-in.huawei.com [45.249.212.187]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 81F2735A8 for <linux-kernel@vger.kernel.org>; Wed, 17 May 2023 03:21:20 -0700 (PDT) Received: from kwepemi500009.china.huawei.com (unknown [172.30.72.57]) by szxga01-in.huawei.com (SkyGuard) with ESMTP id 4QLptd06ZhzqSKP; Wed, 17 May 2023 18:16:56 +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.23; Wed, 17 May 2023 18:21:17 +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 v6] kobject: Fix global-out-of-bounds in kobject_action_type() Date: Wed, 17 May 2023 18:19:57 +0800 Message-ID: <20230517101957.14655-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,T_SCC_BODY_TEXT_LINE 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?1766136996538067960?= X-GMAIL-MSGID: =?utf-8?q?1766136996538067960?= |
Series |
[v6] kobject: Fix global-out-of-bounds in kobject_action_type()
|
|
Commit Message
Xia Fukun
May 17, 2023, 10:19 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].
Use sysfs_match_string() to replace the fragile and convoluted loop.
This function is well-tested for parsing sysfs inputs. Moreover, this
modification will not cause any functional changes.
Fixes: f36776fafbaa ("kobject: support passing in variables for synthetic uevents")
Signed-off-by: Xia Fukun <xiafukun@huawei.com>
---
v5 -> v6:
- Ensure that the following extensions remain effective:
https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-uevent
v4 -> v5:
- Fixed build errors and warnings, and retested the patch.
v3 -> v4:
- Refactor the function to be more obviously correct and readable.
---
include/linux/kobject.h | 3 +++
lib/kobject_uevent.c | 30 +++++++++++++++++-------------
2 files changed, 20 insertions(+), 13 deletions(-)
Comments
On Wed, May 17, 2023 at 06:19:57PM +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]. > > Use sysfs_match_string() to replace the fragile and convoluted loop. > This function is well-tested for parsing sysfs inputs. Moreover, this > modification will not cause any functional changes. > > Fixes: f36776fafbaa ("kobject: support passing in variables for synthetic uevents") > Signed-off-by: Xia Fukun <xiafukun@huawei.com> > --- > v5 -> v6: > - Ensure that the following extensions remain effective: > https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-uevent > > v4 -> v5: > - Fixed build errors and warnings, and retested the patch. > > v3 -> v4: > - Refactor the function to be more obviously correct and readable. > --- > include/linux/kobject.h | 3 +++ > lib/kobject_uevent.c | 30 +++++++++++++++++------------- > 2 files changed, 20 insertions(+), 13 deletions(-) > > diff --git a/include/linux/kobject.h b/include/linux/kobject.h > index c392c811d9ad..9d3ecce3c4f6 100644 > --- a/include/linux/kobject.h > +++ b/include/linux/kobject.h > @@ -32,6 +32,9 @@ > #define UEVENT_NUM_ENVP 64 /* number of env pointers */ > #define UEVENT_BUFFER_SIZE 2048 /* buffer for the variables */ > > +/* the maximum length of the string contained in kobject_actions[] */ > +#define UEVENT_KACT_STRSIZE 16 Why does this value need to be in a global .h file when it is only used in one .c file? And how are you going to keep it in sync with kobject_actions if it changes in the future? And that variable isn't even in this file, how would anyone know to modify this if the structure changes in a .c file? > + > #ifdef CONFIG_UEVENT_HELPER > /* path to the userspace helper executed on an event */ > extern char uevent_helper[]; > diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c > index 7c44b7ae4c5c..4030a928e9c6 100644 > --- a/lib/kobject_uevent.c > +++ b/lib/kobject_uevent.c > @@ -66,7 +66,8 @@ 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; > + char kobj_act_buf[UEVENT_KACT_STRSIZE] = ""; Why does this need to be initialized? And are you sure the size is correct? If so, how? And how was any of this tested? Based on your prior submissions, we are going to require some sort of proof. What would you do if you were in my position? thanks, greg k-h
On 2023/5/17 20:17, Greg KH wrote: > On Wed, May 17, 2023 at 06:19:57PM +0800, Xia Fukun wrote: >> --- a/include/linux/kobject.h >> +++ b/include/linux/kobject.h >> @@ -32,6 +32,9 @@ >> #define UEVENT_NUM_ENVP 64 /* number of env pointers */ >> #define UEVENT_BUFFER_SIZE 2048 /* buffer for the variables */ >> >> +/* the maximum length of the string contained in kobject_actions[] */ >> +#define UEVENT_KACT_STRSIZE 16 > > Why does this value need to be in a global .h file when it is only used > in one .c file? > > And how are you going to keep it in sync with kobject_actions if it > changes in the future? And that variable isn't even in this file, how > would anyone know to modify this if the structure changes in a .c file? Your criticism is correct. UEVENT_KACT_STRSIZE should not be defined in the global .h file here. I will move it to that .c file. >> --- a/lib/kobject_uevent.c >> +++ b/lib/kobject_uevent.c >> @@ -66,7 +66,8 @@ 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; >> + char kobj_act_buf[UEVENT_KACT_STRSIZE] = ""; > > Why does this need to be initialized? My initialization method has some flaws, which should be done as follows: char kobj_act_buf[UEVENT_KACT_STRSIZE] = {0}; Initialize the string kobj_act_buf to "/0" and parse it using sysfs_match_string after subsequent copy operations. > And are you sure the size is correct? If so, how? UEVENT_KACT_STRSIZE is defined as the maximum length of the string contained in kobject_actions[]. At present, the maximum length of strings in this array is 7. Based on the actual meaning of these strings, these actions will not exceed 16 if there are any subsequent changes. > And how was any of this tested? Based on your prior submissions, we are > going to require some sort of proof. What would you do if you were in > my position? My testing method is to apply the patch, compile the kernel image, and start the QEMU virtual machine. Then compile and execute the code mentioned in the patch that triggers out-of-bounds issues. In addition, the following operations will be performed to verify the functions mentioned by Peter Rajnoha <prajnoha@redhat.com>: # echo "add fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed A=1 B=abc" > /sys/block/ram0/uevent # udevadm monitor --kernel --env monitor will print the received events for: KERNEL - the kernel uevent KERNEL[189.376386] add /devices/virtual/block/ram0 (block) ACTION=add DEVPATH=/devices/virtual/block/ram0 SUBSYSTEM=block SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed SYNTH_ARG_A=1 SYNTH_ARG_B=abc DEVNAME=/dev/ram0 DEVTYPE=disk DISKSEQ=14 SEQNUM=3781 MAJOR=1 MINOR=0 > thanks, > > greg k-h Thank you for your suggestion. My submission was indeed negligent, and your guidance has benefited me greatly.
Gentle ping ... On 2023/5/18 10:37, Xia Fukun wrote: > On 2023/5/17 20:17, Greg KH wrote: > >> And how was any of this tested? Based on your prior submissions, we are >> going to require some sort of proof. What would you do if you were in >> my position? > > My testing method is to apply the patch, compile the kernel image, > and start the QEMU virtual machine. Then compile and execute the code > mentioned in the patch that triggers out-of-bounds issues. > > In addition, the following operations will be performed to verify the > functions mentioned by Peter Rajnoha <prajnoha@redhat.com>: > > # echo "add fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed A=1 B=abc" > > /sys/block/ram0/uevent > > # udevadm monitor --kernel --env > monitor will print the received events for: > KERNEL - the kernel uevent > > KERNEL[189.376386] add /devices/virtual/block/ram0 (block) > ACTION=add > DEVPATH=/devices/virtual/block/ram0 > SUBSYSTEM=block > SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed > SYNTH_ARG_A=1 > SYNTH_ARG_B=abc > DEVNAME=/dev/ram0 > DEVTYPE=disk > DISKSEQ=14 > SEQNUM=3781 > MAJOR=1 > MINOR=0 > > Thank you for your suggestion. My submission was indeed negligent, > and your guidance has benefited me greatly. I have submitted v7 of the patch according to your suggestion and tested it to ensure its functionality is correct. Please take the time to review it. Thank you very much.
On Tue, May 23, 2023 at 04:52:23PM +0800, Xia Fukun wrote:
> Gentle ping ...
Please relax, there are lots of other changes to review before yours,
and frankly, due to all of the problems that this patch has had over
time, it's on the bottom of my list.
To help out, why don't you review stuff as well?
thanks,
greg k-h
diff --git a/include/linux/kobject.h b/include/linux/kobject.h index c392c811d9ad..9d3ecce3c4f6 100644 --- a/include/linux/kobject.h +++ b/include/linux/kobject.h @@ -32,6 +32,9 @@ #define UEVENT_NUM_ENVP 64 /* number of env pointers */ #define UEVENT_BUFFER_SIZE 2048 /* buffer for the variables */ +/* the maximum length of the string contained in kobject_actions[] */ +#define UEVENT_KACT_STRSIZE 16 + #ifdef CONFIG_UEVENT_HELPER /* path to the userspace helper executed on an event */ extern char uevent_helper[]; diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c index 7c44b7ae4c5c..4030a928e9c6 100644 --- a/lib/kobject_uevent.c +++ b/lib/kobject_uevent.c @@ -66,7 +66,8 @@ 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; + char kobj_act_buf[UEVENT_KACT_STRSIZE] = ""; if (count && (buf[count-1] == '\n' || buf[count-1] == '\0')) count--; @@ -77,21 +78,24 @@ static int kobject_action_type(const char *buf, size_t count, args_start = strnchr(buf, count, ' '); if (args_start) { count_first = args_start - buf; + if (count_first > UEVENT_KACT_STRSIZE) + goto out; + args_start = args_start + 1; + strncpy(kobj_act_buf, buf, count_first); + i = sysfs_match_string(kobject_actions, kobj_act_buf); } else - count_first = count; + i = sysfs_match_string(kobject_actions, buf); - 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; - } + if (i < 0) + goto out; + + action = i; + if (args) + *args = args_start; + + *type = action; + ret = 0; out: return ret; }