From patchwork Tue Nov 24 13:16:52 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xiaoming Ni X-Patchwork-Id: 41182 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 52B85393D027; Tue, 24 Nov 2020 13:17:12 +0000 (GMT) X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from szxga07-in.huawei.com (szxga07-in.huawei.com [45.249.212.35]) by sourceware.org (Postfix) with ESMTPS id 69497384A022; Tue, 24 Nov 2020 13:17:08 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 69497384A022 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=huawei.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=nixiaoming@huawei.com Received: from DGGEMS412-HUB.china.huawei.com (unknown [172.30.72.60]) by szxga07-in.huawei.com (SkyGuard) with ESMTP id 4CgPgJ04lhz6ysd; Tue, 24 Nov 2020 21:16:44 +0800 (CST) Received: from use12-sp2.huawei.com (10.67.189.174) by DGGEMS412-HUB.china.huawei.com (10.3.19.212) with Microsoft SMTP Server id 14.3.487.0; Tue, 24 Nov 2020 21:16:56 +0800 From: Xiaoming Ni To: , , , , , , Subject: [PATCH v3] io:nftw/ftw:fix stack overflow when large nopenfd [BZ #26353] Date: Tue, 24 Nov 2020 21:16:52 +0800 Message-ID: <20201124131652.111854-1-nixiaoming@huawei.com> X-Mailer: git-send-email 2.27.0 MIME-Version: 1.0 X-Originating-IP: [10.67.189.174] X-CFilter-Loop: Reflected X-Spam-Status: No, score=-12.5 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, KAM_MANYTO, RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: wangle6@huawei.com, nixiaoming@huawei.com Errors-To: libc-alpha-bounces@sourceware.org Sender: "Libc-alpha" In ftw_startup(), call alloca to apply for a large amount of stack space. When descriptors is very large, stack overflow is triggered. BZ #26353 Replace the memory application of data.dirstreams from alloca() to malloc() by referring to the memory application of data.dirbuf in the current function. Combine the memory allocation of data.dirbuf and data.dirstreams according to the advice of Adhemerval Zanella. v3: Combine the memory allocation of data.dirbuf and data.dirstreams according to the advice of Adhemerval Zanella. remove the upper limit check of descriptors v2: https://public-inbox.org/libc-alpha/20200815070851.46403-1-nixiaoming@huawei.com/ not set errno after malloc fails. add check ftw return value on testcase add more testcase v1: https://public-inbox.org/libc-alpha/20200808084640.49174-1-nixiaoming@huawei.com/ --- io/Makefile | 3 ++- io/ftw.c | 18 ++++++++++-------- io/tst-bz26353.c | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 9 deletions(-) create mode 100644 io/tst-bz26353.c diff --git a/io/Makefile b/io/Makefile index 6dd2c33fcf..7845d07f45 100644 --- a/io/Makefile +++ b/io/Makefile @@ -68,7 +68,8 @@ tests := test-utime test-stat test-stat2 test-lfs tst-getcwd \ tst-posix_fallocate tst-posix_fallocate64 \ tst-fts tst-fts-lfs tst-open-tmpfile \ tst-copy_file_range tst-getcwd-abspath tst-lockf \ - tst-ftw-lnk tst-file_change_detection tst-lchmod + tst-ftw-lnk tst-file_change_detection tst-lchmod \ + tst-bz26353 # Likewise for statx, but we do not need static linking here. tests-internal += tst-statx diff --git a/io/ftw.c b/io/ftw.c index 7104816e85..c38e94dffc 100644 --- a/io/ftw.c +++ b/io/ftw.c @@ -72,6 +72,7 @@ char *alloca (); #else # include #endif +#include #if ! _LIBC && !HAVE_DECL_STPCPY && !defined stpcpy char *stpcpy (); @@ -643,18 +644,19 @@ ftw_startup (const char *dir, int is_nftw, void *func, int descriptors, __set_errno (ENOENT); return -1; } - data.maxdir = descriptors < 1 ? 1 : descriptors; data.actdir = 0; - data.dirstreams = (struct dir_data **) alloca (data.maxdir - * sizeof (struct dir_data *)); - memset (data.dirstreams, '\0', data.maxdir * sizeof (struct dir_data *)); - /* PATH_MAX is always defined when we get here. */ data.dirbufsize = MAX (2 * strlen (dir), PATH_MAX); - data.dirbuf = (char *) malloc (data.dirbufsize); - if (data.dirbuf == NULL) + data.dirstreams = malloc (data.maxdir * sizeof (struct dir_data *) + + data.dirbufsize); + if (data.dirstreams == NULL) return -1; + + memset (data.dirstreams, '\0', data.maxdir * sizeof (struct dir_data *)); + + data.dirbuf = (char *) data.dirstreams + + data.maxdir * sizeof (struct dir_data *); cp = __stpcpy (data.dirbuf, dir); /* Strip trailing slashes. */ while (cp > data.dirbuf + 1 && cp[-1] == '/') @@ -803,7 +805,7 @@ ftw_startup (const char *dir, int is_nftw, void *func, int descriptors, out_fail: save_err = errno; __tdestroy (data.known_objects, free); - free (data.dirbuf); + free (data.dirstreams); __set_errno (save_err); return result; diff --git a/io/tst-bz26353.c b/io/tst-bz26353.c new file mode 100644 index 0000000000..7567d9c038 --- /dev/null +++ b/io/tst-bz26353.c @@ -0,0 +1,34 @@ +#include +#include +#include +#include +#include +#include +#include + +int my_func(const char *file, const struct stat *sb ,int flag) +{ + printf ("%s\n", file); + return 0; +} + +/*Check whether stack overflow occurs*/ +int do_test(int large_nopenfd) +{ + int ret = ftw("./tst-bz26353", my_func, large_nopenfd); + printf ("test big num %d, ret=%d errno=%d, without stack overflow\n", + large_nopenfd, ret, errno); + return 0; +} + +int main(int argc, char *argv[]) +{ + int ret = 0; + mkdir ("./tst-bz26353", 0755); + /* The default stack size is 8 MB. + * Before the bug is fixed, stack overflow will be triggered. */ + ret += do_test(8192 * 1024); + ret += do_test(INT_MAX); + rmdir ("./tst-bz26353"); + return ret; +}