unofficial mirror of libc-alpha@sourceware.org
 help / color / mirror / Atom feed
From: Xiaoming Ni <nixiaoming@huawei.com>
To: <eggert@cs.ucla.edu>, <libc-alpha@sourceware.org>,
	<carlos@redhat.com>, <glibc-bugs@sourceware.org>,
	<drepper.fsp@gmail.com>, <unassigned@sourceware.org>,
	<adhemerval.zanella@linaro.org>
Cc: wangle6@huawei.com, nixiaoming@huawei.com
Subject: [PATCH v3] io:nftw/ftw:fix stack overflow when large nopenfd [BZ #26353]
Date: Tue, 24 Nov 2020 21:16:52 +0800	[thread overview]
Message-ID: <20201124131652.111854-1-nixiaoming@huawei.com> (raw)

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 <sys/stat.h>
 #endif
+#include <scratch_buffer.h>
 
 #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 <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <ftw.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <limits.h>
+
+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;
+}
-- 
2.27.0


             reply	other threads:[~2020-11-24 13:17 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-11-24 13:16 Xiaoming Ni [this message]
2020-11-24 14:14 ` [PATCH v3] io:nftw/ftw:fix stack overflow when large nopenfd [BZ #26353] Adhemerval Zanella via Libc-alpha

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/libc/involved.html

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20201124131652.111854-1-nixiaoming@huawei.com \
    --to=nixiaoming@huawei.com \
    --cc=adhemerval.zanella@linaro.org \
    --cc=carlos@redhat.com \
    --cc=drepper.fsp@gmail.com \
    --cc=eggert@cs.ucla.edu \
    --cc=glibc-bugs@sourceware.org \
    --cc=libc-alpha@sourceware.org \
    --cc=unassigned@sourceware.org \
    --cc=wangle6@huawei.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).