From patchwork Fri Aug 7 10:16:01 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xiaoming Ni X-Patchwork-Id: 40231 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 011C43861916; Fri, 7 Aug 2020 10:16:17 +0000 (GMT) X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from huawei.com (szxga04-in.huawei.com [45.249.212.190]) by sourceware.org (Postfix) with ESMTPS id AE6A23858D35; Fri, 7 Aug 2020 10:16:13 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org AE6A23858D35 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 DGGEMS401-HUB.china.huawei.com (unknown [172.30.72.59]) by Forcepoint Email with ESMTP id B7BC7E77DE12EA9992F3; Fri, 7 Aug 2020 18:16:11 +0800 (CST) Received: from use12-sp2.huawei.com (10.67.189.174) by DGGEMS401-HUB.china.huawei.com (10.3.19.201) with Microsoft SMTP Server id 14.3.487.0; Fri, 7 Aug 2020 18:16:05 +0800 From: Xiaoming Ni To: , , , , , , Subject: [PATCH v2] stdlib: realpath use malloc replace __alloca to reduce stack overflow risks [BZ #26341] Date: Fri, 7 Aug 2020 18:16:01 +0800 Message-ID: <20200807101601.61670-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=-10.3 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, KAM_MANYTO, RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL, SPF_HELO_PASS, 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: yukeji@huawei.com, wangle6@huawei.com, nixiaoming@huawei.com Errors-To: libc-alpha-bounces@sourceware.org Sender: "Libc-alpha" Realpath() cyclically invokes __alloca() when processing soft link files, which may consume 164 KB stack space. Therefore, replace __alloca with malloc to reduce stack overflow risks v2: Avoid repeated malloc and free operations. and add testcase v1: https://patches-gcc.linaro.org/patch/39851/ Signed-off-by: Xiaoming Ni --- stdlib/Makefile | 3 +- stdlib/canonicalize.c | 25 +++++++++++++-- stdlib/tst-bz26341.c | 73 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 98 insertions(+), 3 deletions(-) create mode 100644 stdlib/tst-bz26341.c diff --git a/stdlib/Makefile b/stdlib/Makefile index 4615f6dfe7..bfdd9036b1 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -87,7 +87,7 @@ tests := tst-strtol tst-strtod testmb testrand testsort testdiv \ tst-makecontext-align test-bz22786 tst-strtod-nan-sign \ tst-swapcontext1 tst-setcontext4 tst-setcontext5 \ tst-setcontext6 tst-setcontext7 tst-setcontext8 \ - tst-setcontext9 tst-bz20544 + tst-setcontext9 tst-bz20544 tst-bz26341 tests-internal := tst-strtod1i tst-strtod3 tst-strtod4 tst-strtod5i \ tst-tls-atexit tst-tls-atexit-nodelete @@ -98,6 +98,7 @@ ifeq ($(build-hardcoded-path-in-tests),yes) tests += tst-empty-env endif +LDLIBS-tst-bz26341 = -lpthread LDLIBS-test-atexit-race = $(shared-thread-library) LDLIBS-test-at_quick_exit-race = $(shared-thread-library) LDLIBS-test-cxa_atexit-race = $(shared-thread-library) diff --git a/stdlib/canonicalize.c b/stdlib/canonicalize.c index cbd885a3c5..c02a8a5800 100644 --- a/stdlib/canonicalize.c +++ b/stdlib/canonicalize.c @@ -46,6 +46,7 @@ __realpath (const char *name, char *resolved) const char *start, *end, *rpath_limit; long int path_max; int num_links = 0; + char *buf = NULL; if (name == NULL) { @@ -163,9 +164,18 @@ __realpath (const char *name, char *resolved) if (S_ISLNK (st.st_mode)) { - char *buf = __alloca (path_max); size_t len; + if (buf == NULL) + { + buf = malloc (path_max); + if (buf == NULL) + { + __set_errno (ENOMEM); + goto error; + } + } + if (++num_links > __eloop_threshold ()) { __set_errno (ELOOP); @@ -178,7 +188,14 @@ __realpath (const char *name, char *resolved) buf[n] = '\0'; if (!extra_buf) - extra_buf = __alloca (path_max); + { + extra_buf = malloc (path_max); + if (extra_buf == NULL) + { + __set_errno (ENOMEM); + goto error; + } + } len = strlen (end); if (path_max - n <= len) @@ -210,12 +227,16 @@ __realpath (const char *name, char *resolved) *dest = '\0'; assert (resolved == NULL || resolved == rpath); + free(extra_buf); + free(buf); return rpath; error: assert (resolved == NULL || resolved == rpath); if (resolved == NULL) free (rpath); + free (extra_buf); + free (buf); return NULL; } libc_hidden_def (__realpath) diff --git a/stdlib/tst-bz26341.c b/stdlib/tst-bz26341.c new file mode 100644 index 0000000000..0fe095b7d1 --- /dev/null +++ b/stdlib/tst-bz26341.c @@ -0,0 +1,73 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int creat_link(void) +{ + int i; + int fd; + char fname[2][16] = {0}; + char *p1 = fname[0]; + char *p2 = fname[1]; + strcpy(p1, "f0"); + fd = open(p1, O_RDONLY|O_CREAT, 0444); + close(fd); + + for (i = 0; i < 41; i++) { + sprintf(p2, "f%d", i); + symlink(p1, p2); + p1 = p2; + p2 = fname[i % 2]; + } + return 0; +} + +void clean_link(void) +{ + char fname[16] = {0}; + int i; + for (i = 0; i < 41; i++) { + sprintf(fname, "f%d", i); + unlink(fname); + } +} + +void *do_realpath(void *ignore) +{ + char *p = realpath("f40", NULL); + printf("%p\n", p); + if (p != NULL) + printf("%s\n", p); + return NULL; +} + +/* Set different stack sizes and check whether stack overflow occurs. */ +int do_test(int size) +{ + pthread_t tid; + pthread_attr_t thread_attr; + pthread_attr_init(&thread_attr); + pthread_attr_setstacksize(&thread_attr, size); + + pthread_create(&tid, &thread_attr, do_realpath, NULL); + pthread_join(tid, NULL); + return 0; +} + +int main(int argc, char *argv[]) +{ + creat_link(); + do_test(8192*1024); + do_test(160*1024); + do_test(40*1024); + clean_link(); + printf("\n"); + return 0; +} +