* [PATCH v2 0/2] tempname ALSR etc. fixes from Gnulib @ 2022-08-25 21:46 Paul Eggert 2022-08-25 21:46 ` Paul Eggert ` (2 more replies) 0 siblings, 3 replies; 7+ messages in thread From: Paul Eggert @ 2022-08-25 21:46 UTC (permalink / raw) To: libc-alpha; +Cc: Paul Eggert This updates v1 as follows: * It omits v1's first two patches as they have been installed into glibc already. * It appends a patch to split __path_search into a separate file, as suggested by Bruno Haible on the Gnulib mailing list <https://lists.gnu.org/r/bug-gnulib/2022-08/msg00077.html> and now implemented in Gnulib <https://git.savannah.gnu.org/cgit/gnulib.git/commit/?id=044bf893acee0a55b22b4be0ede0e3ce010c480a>. v2's first patch is identical to v1's third patch. v2's second patch is new. Paul Eggert (2): Merge tempname ASLR etc. patch from Gnulib Split __path_search into a separate file stdio-common/Makefile | 2 + stdio-common/path-search.c | 31 +++++++ stdio-common/tempname.c | 14 --- sysdeps/posix/path-search.c | 92 ++++++++++++++++++++ sysdeps/posix/tempname.c | 164 ++++++++++++------------------------ 5 files changed, 178 insertions(+), 125 deletions(-) create mode 100644 stdio-common/path-search.c create mode 100644 sysdeps/posix/path-search.c -- 2.37.2 ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v2 0/2] tempname ALSR etc. fixes from Gnulib 2022-08-25 21:46 [PATCH v2 0/2] tempname ALSR etc. fixes from Gnulib Paul Eggert @ 2022-08-25 21:46 ` Paul Eggert 2022-08-25 21:46 ` [PATCH v2 1/2] Merge tempname ASLR etc. patch " Paul Eggert 2022-08-25 21:46 ` [PATCH v2 2/2] Split __path_search into a separate file Paul Eggert 2 siblings, 0 replies; 7+ messages in thread From: Paul Eggert @ 2022-08-25 21:46 UTC (permalink / raw) To: libc-alpha This updates v1 as follows: * It omits v1's first two patches as they have been installed into glibc already. * It appends a patch to split __path_search into a separate file, as suggested by Bruno Haible on the Gnulib mailing list <https://lists.gnu.org/r/bug-gnulib/2022-08/msg00077.html> and now implemented in Gnulib <https://git.savannah.gnu.org/cgit/gnulib.git/commit/?id=044bf893acee0a55b22b4be0ede0e3ce010c480a>. v2's first patch is identical to v1's third patch. v2's second patch is new. Paul Eggert (2): Merge tempname ASLR etc. patch from Gnulib Split __path_search into a separate file stdio-common/Makefile | 2 + stdio-common/path-search.c | 31 +++++++ stdio-common/tempname.c | 14 --- sysdeps/posix/path-search.c | 92 ++++++++++++++++++++ sysdeps/posix/tempname.c | 164 ++++++++++++------------------------ 5 files changed, 178 insertions(+), 125 deletions(-) create mode 100644 stdio-common/path-search.c create mode 100644 sysdeps/posix/path-search.c -- 2.37.2 ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v2 1/2] Merge tempname ASLR etc. patch from Gnulib 2022-08-25 21:46 [PATCH v2 0/2] tempname ALSR etc. fixes from Gnulib Paul Eggert 2022-08-25 21:46 ` Paul Eggert @ 2022-08-25 21:46 ` Paul Eggert 2022-08-25 21:46 ` Paul Eggert 2022-08-25 21:46 ` [PATCH v2 2/2] Split __path_search into a separate file Paul Eggert 2 siblings, 1 reply; 7+ messages in thread From: Paul Eggert @ 2022-08-25 21:46 UTC (permalink / raw) To: libc-alpha; +Cc: Paul Eggert Merge patch from Gnulib that fixes problems with ASLR info leak and entropy loss. This syncs tempname.c with Gnulib commit 564b523fe97a8d63493aa68acb627b8c40744fb9 (2022-08-22) and fixes <https://bugs.gnu.org/57129> which was reported against Emacs and uncovered some unlikely Glibc bugs. * sysdeps/posix/tempname.c: Don't include stdalign.h. (mix_random_values): New function. (random_bits): Use it. Args are now new value address and old value, and this function now returns a success indicator. Omit old USE_GETRANDOM argument: always try getrandom now, as there is no good reason not to now that GRND_NONBLOCK is used. Caller changed. Use CLOCK_REALTIME for for ersatz entropy, as CLOCK_MONOTONIC doesn't work on some platforms. Also, mix in ersatz entropy from tv_sec and from clock (). (try_tempname_len): Do not mix in ASLR-based entropy, as the result is published to the world and ASLR should be private. Do not try to use a static var as that has issues if multithreaded. Instead, simply generate new random bits. Worry about bias only with high-quality random bits. --- sysdeps/posix/tempname.c | 94 +++++++++++++++++++++++++--------------- 1 file changed, 59 insertions(+), 35 deletions(-) diff --git a/sysdeps/posix/tempname.c b/sysdeps/posix/tempname.c index 60f8541085..0e2f29f5de 100644 --- a/sysdeps/posix/tempname.c +++ b/sysdeps/posix/tempname.c @@ -48,7 +48,6 @@ #include <string.h> #include <fcntl.h> -#include <stdalign.h> #include <stdint.h> #include <sys/random.h> #include <sys/stat.h> @@ -77,20 +76,55 @@ typedef uint_fast64_t random_value; #define BASE_62_DIGITS 10 /* 62**10 < UINT_FAST64_MAX */ #define BASE_62_POWER (62LL * 62 * 62 * 62 * 62 * 62 * 62 * 62 * 62 * 62) +/* Return the result of mixing the entropy from R and S. + Assume that R and S are not particularly random, + and that the result should look randomish to an untrained eye. */ + static random_value -random_bits (random_value var, bool use_getrandom) +mix_random_values (random_value r, random_value s) +{ + /* As this code is used only when high-quality randomness is neither + available nor necessary, there is no need for fancier polynomials + such as those in the Linux kernel's 'random' driver. */ + return (2862933555777941757 * r + 3037000493) ^ s; +} + +/* Set *R to a random value. + Return true if *R is set to high-quality value taken from getrandom. + Otherwise return false, falling back to a low-quality *R that might + depend on S. + + This function returns false only when getrandom fails. + On GNU systems this should happen only early in the boot process, + when the fallback should be good enough for programs using tempname + because any attacker likely has root privileges already. */ + +static bool +random_bits (random_value *r, random_value s) { - random_value r; /* Without GRND_NONBLOCK it can be blocked for minutes on some systems. */ - if (use_getrandom && __getrandom (&r, sizeof r, GRND_NONBLOCK) == sizeof r) - return r; -#if _LIBC || (defined CLOCK_MONOTONIC && HAVE_CLOCK_GETTIME) - /* Add entropy if getrandom did not work. */ + if (__getrandom (r, sizeof *r, GRND_NONBLOCK) == sizeof *r) + return true; + + /* If getrandom did not work, use ersatz entropy based on low-order + clock bits. On GNU systems getrandom should fail only + early in booting, when ersatz should be good enough. + Do not use ASLR-based entropy, as that would leak ASLR info into + the resulting file name which is typically public. + + Of course we are in a state of sin here. */ + + random_value v = s; + +#if _LIBC || (defined CLOCK_REALTIME && HAVE_CLOCK_GETTIME) struct __timespec64 tv; - __clock_gettime64 (CLOCK_MONOTONIC, &tv); - var ^= tv.tv_nsec; + __clock_gettime64 (CLOCK_REALTIME, &tv); + v = mix_random_values (v, tv.tv_sec); + v = mix_random_values (v, tv.tv_nsec); #endif - return 2862933555777941757 * var + 3037000493; + + *r = mix_random_values (v, clock ()); + return false; } #if _LIBC @@ -213,7 +247,7 @@ static const char letters[] = and return a read-write fd. The file is mode 0600. __GT_DIR: create a directory, which will be mode 0700. - We use a clever algorithm to get hard-to-predict names. */ + */ #ifdef _LIBC static #endif @@ -261,25 +295,17 @@ try_tempname_len (char *tmpl, int suffixlen, void *args, unsigned int attempts = ATTEMPTS_MIN; #endif - /* A random variable. The initial value is used only the for fallback path - on 'random_bits' on 'getrandom' failure. Its initial value tries to use - some entropy from the ASLR and ignore possible bits from the stack - alignment. */ - random_value v = ((uintptr_t) &v) / alignof (max_align_t); + /* A random variable. */ + random_value v = 0; - /* How many random base-62 digits can currently be extracted from V. */ + /* A value derived from the random variable, and how many random + base-62 digits can currently be extracted from VDIGBUF. */ + random_value vdigbuf; int vdigits = 0; - /* Whether to consume entropy when acquiring random bits. On the - first try it's worth the entropy cost with __GT_NOCREATE, which - is inherently insecure and can use the entropy to make it a bit - less secure. On the (rare) second and later attempts it might - help against DoS attacks. */ - bool use_getrandom = tryfunc == try_nocreate; - - /* Least unfair value for V. If V is less than this, V can generate - BASE_62_DIGITS digits fairly. Otherwise it might be biased. */ - random_value const unfair_min + /* Least biased value for V. If V is less than this, V can generate + BASE_62_DIGITS unbiased digits. Otherwise the digits are biased. */ + random_value const biased_min = RANDOM_VALUE_MAX - RANDOM_VALUE_MAX % BASE_62_POWER; len = strlen (tmpl); @@ -299,18 +325,16 @@ try_tempname_len (char *tmpl, int suffixlen, void *args, { if (vdigits == 0) { - do - { - v = random_bits (v, use_getrandom); - use_getrandom = true; - } - while (unfair_min <= v); + /* Worry about bias only if the bits are high quality. */ + while (random_bits (&v, v) && biased_min <= v) + continue; + vdigbuf = v; vdigits = BASE_62_DIGITS; } - XXXXXX[i] = letters[v % 62]; - v /= 62; + XXXXXX[i] = letters[vdigbuf % 62]; + vdigbuf /= 62; vdigits--; } -- 2.37.2 ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v2 1/2] Merge tempname ASLR etc. patch from Gnulib 2022-08-25 21:46 ` [PATCH v2 1/2] Merge tempname ASLR etc. patch " Paul Eggert @ 2022-08-25 21:46 ` Paul Eggert 0 siblings, 0 replies; 7+ messages in thread From: Paul Eggert @ 2022-08-25 21:46 UTC (permalink / raw) To: libc-alpha Merge patch from Gnulib that fixes problems with ASLR info leak and entropy loss. This syncs tempname.c with Gnulib commit 564b523fe97a8d63493aa68acb627b8c40744fb9 (2022-08-22) and fixes <https://bugs.gnu.org/57129> which was reported against Emacs and uncovered some unlikely Glibc bugs. * sysdeps/posix/tempname.c: Don't include stdalign.h. (mix_random_values): New function. (random_bits): Use it. Args are now new value address and old value, and this function now returns a success indicator. Omit old USE_GETRANDOM argument: always try getrandom now, as there is no good reason not to now that GRND_NONBLOCK is used. Caller changed. Use CLOCK_REALTIME for for ersatz entropy, as CLOCK_MONOTONIC doesn't work on some platforms. Also, mix in ersatz entropy from tv_sec and from clock (). (try_tempname_len): Do not mix in ASLR-based entropy, as the result is published to the world and ASLR should be private. Do not try to use a static var as that has issues if multithreaded. Instead, simply generate new random bits. Worry about bias only with high-quality random bits. --- sysdeps/posix/tempname.c | 94 +++++++++++++++++++++++++--------------- 1 file changed, 59 insertions(+), 35 deletions(-) diff --git a/sysdeps/posix/tempname.c b/sysdeps/posix/tempname.c index 60f8541085..0e2f29f5de 100644 --- a/sysdeps/posix/tempname.c +++ b/sysdeps/posix/tempname.c @@ -48,7 +48,6 @@ #include <string.h> #include <fcntl.h> -#include <stdalign.h> #include <stdint.h> #include <sys/random.h> #include <sys/stat.h> @@ -77,20 +76,55 @@ typedef uint_fast64_t random_value; #define BASE_62_DIGITS 10 /* 62**10 < UINT_FAST64_MAX */ #define BASE_62_POWER (62LL * 62 * 62 * 62 * 62 * 62 * 62 * 62 * 62 * 62) +/* Return the result of mixing the entropy from R and S. + Assume that R and S are not particularly random, + and that the result should look randomish to an untrained eye. */ + static random_value -random_bits (random_value var, bool use_getrandom) +mix_random_values (random_value r, random_value s) +{ + /* As this code is used only when high-quality randomness is neither + available nor necessary, there is no need for fancier polynomials + such as those in the Linux kernel's 'random' driver. */ + return (2862933555777941757 * r + 3037000493) ^ s; +} + +/* Set *R to a random value. + Return true if *R is set to high-quality value taken from getrandom. + Otherwise return false, falling back to a low-quality *R that might + depend on S. + + This function returns false only when getrandom fails. + On GNU systems this should happen only early in the boot process, + when the fallback should be good enough for programs using tempname + because any attacker likely has root privileges already. */ + +static bool +random_bits (random_value *r, random_value s) { - random_value r; /* Without GRND_NONBLOCK it can be blocked for minutes on some systems. */ - if (use_getrandom && __getrandom (&r, sizeof r, GRND_NONBLOCK) == sizeof r) - return r; -#if _LIBC || (defined CLOCK_MONOTONIC && HAVE_CLOCK_GETTIME) - /* Add entropy if getrandom did not work. */ + if (__getrandom (r, sizeof *r, GRND_NONBLOCK) == sizeof *r) + return true; + + /* If getrandom did not work, use ersatz entropy based on low-order + clock bits. On GNU systems getrandom should fail only + early in booting, when ersatz should be good enough. + Do not use ASLR-based entropy, as that would leak ASLR info into + the resulting file name which is typically public. + + Of course we are in a state of sin here. */ + + random_value v = s; + +#if _LIBC || (defined CLOCK_REALTIME && HAVE_CLOCK_GETTIME) struct __timespec64 tv; - __clock_gettime64 (CLOCK_MONOTONIC, &tv); - var ^= tv.tv_nsec; + __clock_gettime64 (CLOCK_REALTIME, &tv); + v = mix_random_values (v, tv.tv_sec); + v = mix_random_values (v, tv.tv_nsec); #endif - return 2862933555777941757 * var + 3037000493; + + *r = mix_random_values (v, clock ()); + return false; } #if _LIBC @@ -213,7 +247,7 @@ static const char letters[] = and return a read-write fd. The file is mode 0600. __GT_DIR: create a directory, which will be mode 0700. - We use a clever algorithm to get hard-to-predict names. */ + */ #ifdef _LIBC static #endif @@ -261,25 +295,17 @@ try_tempname_len (char *tmpl, int suffixlen, void *args, unsigned int attempts = ATTEMPTS_MIN; #endif - /* A random variable. The initial value is used only the for fallback path - on 'random_bits' on 'getrandom' failure. Its initial value tries to use - some entropy from the ASLR and ignore possible bits from the stack - alignment. */ - random_value v = ((uintptr_t) &v) / alignof (max_align_t); + /* A random variable. */ + random_value v = 0; - /* How many random base-62 digits can currently be extracted from V. */ + /* A value derived from the random variable, and how many random + base-62 digits can currently be extracted from VDIGBUF. */ + random_value vdigbuf; int vdigits = 0; - /* Whether to consume entropy when acquiring random bits. On the - first try it's worth the entropy cost with __GT_NOCREATE, which - is inherently insecure and can use the entropy to make it a bit - less secure. On the (rare) second and later attempts it might - help against DoS attacks. */ - bool use_getrandom = tryfunc == try_nocreate; - - /* Least unfair value for V. If V is less than this, V can generate - BASE_62_DIGITS digits fairly. Otherwise it might be biased. */ - random_value const unfair_min + /* Least biased value for V. If V is less than this, V can generate + BASE_62_DIGITS unbiased digits. Otherwise the digits are biased. */ + random_value const biased_min = RANDOM_VALUE_MAX - RANDOM_VALUE_MAX % BASE_62_POWER; len = strlen (tmpl); @@ -299,18 +325,16 @@ try_tempname_len (char *tmpl, int suffixlen, void *args, { if (vdigits == 0) { - do - { - v = random_bits (v, use_getrandom); - use_getrandom = true; - } - while (unfair_min <= v); + /* Worry about bias only if the bits are high quality. */ + while (random_bits (&v, v) && biased_min <= v) + continue; + vdigbuf = v; vdigits = BASE_62_DIGITS; } - XXXXXX[i] = letters[v % 62]; - v /= 62; + XXXXXX[i] = letters[vdigbuf % 62]; + vdigbuf /= 62; vdigits--; } -- 2.37.2 ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v2 2/2] Split __path_search into a separate file 2022-08-25 21:46 [PATCH v2 0/2] tempname ALSR etc. fixes from Gnulib Paul Eggert 2022-08-25 21:46 ` Paul Eggert 2022-08-25 21:46 ` [PATCH v2 1/2] Merge tempname ASLR etc. patch " Paul Eggert @ 2022-08-25 21:46 ` Paul Eggert 2022-08-25 21:46 ` Paul Eggert 2022-08-26 9:47 ` Florian Weimer 2 siblings, 2 replies; 7+ messages in thread From: Paul Eggert @ 2022-08-25 21:46 UTC (permalink / raw) To: libc-alpha; +Cc: Paul Eggert This simplifies sharing tempname with Gnulib. Suggested by Bruno Haible in: https://lists.gnu.org/r/bug-gnulib/2022-08/msg00077.html * stdio-common/Makefile (routines): Add path-search. (CFLAGS-path-search.c): New macro, which has -fexceptions because tempname.c has it. * stdio-common/path-search.c, sysdeps/posix/path-search.c: New files. * stdio-common/tempname.c (__need_size_t): Do not define. No need to include stddef.h, since stdio.h declares size_t. (__path_search): Move to path-search.c. * sysdeps/posix/tempname.c: Don't include sys/types.h, assert.h, stddef.h; not needed. (P_tmpdir): Remove. (__secure_getenv) [_LIBC]: Remove. (__stat64) [!_LIBC]: Remove. (direxists, __path_search) [_LIBC]: Move to path-search.c. --- stdio-common/Makefile | 2 + stdio-common/path-search.c | 31 +++++++++++++ stdio-common/tempname.c | 14 ------ sysdeps/posix/path-search.c | 92 +++++++++++++++++++++++++++++++++++++ sysdeps/posix/tempname.c | 82 --------------------------------- 5 files changed, 125 insertions(+), 96 deletions(-) create mode 100644 stdio-common/path-search.c create mode 100644 sysdeps/posix/path-search.c diff --git a/stdio-common/Makefile b/stdio-common/Makefile index b1e9144de0..1543b5414b 100644 --- a/stdio-common/Makefile +++ b/stdio-common/Makefile @@ -49,6 +49,7 @@ routines := \ itoa-digits \ itoa-udigits \ itowa-digits \ + path-search \ perror \ printf \ printf-prs \ @@ -351,6 +352,7 @@ $(objpfx)tst-errno-manual.out: tst-errno-manual.py \ CFLAGS-vfprintf.c += -Wno-uninitialized CFLAGS-vfwprintf.c += -Wno-uninitialized +CFLAGS-path-search.c += -fexceptions CFLAGS-tmpfile.c += -fexceptions CFLAGS-tmpfile64.c += -fexceptions CFLAGS-tempname.c += -fexceptions diff --git a/stdio-common/path-search.c b/stdio-common/path-search.c new file mode 100644 index 0000000000..6ad7002d7c --- /dev/null +++ b/stdio-common/path-search.c @@ -0,0 +1,31 @@ +/* Copyright (C) 1991-2022 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <stdio.h> +#include <errno.h> + +/* Perform the "SVID path search malarkey" on DIR and PFX. Write a + template suitable for use in __gen_tempname into TMPL, bounded + by TMPL_LEN. */ +int +__path_search (char *tmpl, size_t tmpl_len, const char *dir, const char *pfx, + int try_tmpdir) +{ + __set_errno (ENOSYS); + return -1; +} +stub_warning (__path_search) diff --git a/stdio-common/tempname.c b/stdio-common/tempname.c index 621876a9d9..6538fb1777 100644 --- a/stdio-common/tempname.c +++ b/stdio-common/tempname.c @@ -15,23 +15,9 @@ License along with the GNU C Library; if not, see <https://www.gnu.org/licenses/>. */ -#define __need_size_t -#include <stddef.h> #include <stdio.h> #include <errno.h> -/* Perform the "SVID path search malarkey" on DIR and PFX. Write a - template suitable for use in __gen_tempname into TMPL, bounded - by TMPL_LEN. */ -int -__path_search (char *tmpl, size_t tmpl_len, const char *dir, const char *pfx, - int try_tmpdir) -{ - __set_errno (ENOSYS); - return -1; -} -stub_warning (__path_search) - /* Generate a (hopefully) unique temporary filename in DIR (if applicable), using template TMPL. KIND determines what to do with that name. It may be one of: diff --git a/sysdeps/posix/path-search.c b/sysdeps/posix/path-search.c new file mode 100644 index 0000000000..ae2f404f58 --- /dev/null +++ b/sysdeps/posix/path-search.c @@ -0,0 +1,92 @@ +/* Copyright (C) 1991-2022 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include <sys/stat.h> + +/* Return nonzero if DIR is an existent directory. */ +static int +direxists (const char *dir) +{ + struct __stat64_t64 buf; + return __stat64_time64 (dir, &buf) == 0 && S_ISDIR (buf.st_mode); +} + +/* Path search algorithm, for tmpnam, tmpfile, etc. If DIR is + non-null and exists, uses it; otherwise uses the first of $TMPDIR, + P_tmpdir, /tmp that exists. Copies into TMPL a template suitable + for use with mk[s]temp. Will fail (-1) if DIR is non-null and + doesn't exist, none of the searched dirs exists, or there's not + enough space in TMPL. */ +int +__path_search (char *tmpl, size_t tmpl_len, const char *dir, const char *pfx, + int try_tmpdir) +{ + const char *d; + size_t dlen, plen; + + if (!pfx || !pfx[0]) + { + pfx = "file"; + plen = 4; + } + else + { + plen = strlen (pfx); + if (plen > 5) + plen = 5; + } + + if (try_tmpdir) + { + d = __libc_secure_getenv ("TMPDIR"); + if (d != NULL && direxists (d)) + dir = d; + else if (dir != NULL && direxists (dir)) + /* nothing */ ; + else + dir = NULL; + } + if (dir == NULL) + { + if (direxists (P_tmpdir)) + dir = P_tmpdir; + else if (strcmp (P_tmpdir, "/tmp") != 0 && direxists ("/tmp")) + dir = "/tmp"; + else + { + __set_errno (ENOENT); + return -1; + } + } + + dlen = strlen (dir); + while (dlen > 1 && dir[dlen - 1] == '/') + dlen--; /* remove trailing slashes */ + + /* check we have room for "${dir}/${pfx}XXXXXX\0" */ + if (tmpl_len < dlen + 1 + plen + 6 + 1) + { + __set_errno (EINVAL); + return -1; + } + + sprintf (tmpl, "%.*s/%.*sXXXXXX", (int) dlen, dir, (int) plen, pfx); + return 0; +} diff --git a/sysdeps/posix/tempname.c b/sysdeps/posix/tempname.c index 0e2f29f5de..11b4796b34 100644 --- a/sysdeps/posix/tempname.c +++ b/sysdeps/posix/tempname.c @@ -20,16 +20,10 @@ # include "tempname.h" #endif -#include <sys/types.h> -#include <assert.h> #include <stdbool.h> - #include <errno.h> #include <stdio.h> -#ifndef P_tmpdir -# define P_tmpdir "/tmp" -#endif #ifndef TMP_MAX # define TMP_MAX 238328 #endif @@ -43,7 +37,6 @@ # error report this to bug-gnulib@gnu.org #endif -#include <stddef.h> #include <stdlib.h> #include <string.h> @@ -55,14 +48,12 @@ #if _LIBC # define struct_stat64 struct __stat64_t64 -# define __secure_getenv __libc_secure_getenv #else # define struct_stat64 struct stat # define __gen_tempname gen_tempname # define __mkdir mkdir # define __open open # define __lstat64_time64(file, buf) lstat (file, buf) -# define __stat64(file, buf) stat (file, buf) # define __getrandom getrandom # define __clock_gettime64 clock_gettime # define __timespec64 timespec @@ -127,79 +118,6 @@ random_bits (random_value *r, random_value s) return false; } -#if _LIBC -/* Return nonzero if DIR is an existent directory. */ -static int -direxists (const char *dir) -{ - struct_stat64 buf; - return __stat64_time64 (dir, &buf) == 0 && S_ISDIR (buf.st_mode); -} - -/* Path search algorithm, for tmpnam, tmpfile, etc. If DIR is - non-null and exists, uses it; otherwise uses the first of $TMPDIR, - P_tmpdir, /tmp that exists. Copies into TMPL a template suitable - for use with mk[s]temp. Will fail (-1) if DIR is non-null and - doesn't exist, none of the searched dirs exists, or there's not - enough space in TMPL. */ -int -__path_search (char *tmpl, size_t tmpl_len, const char *dir, const char *pfx, - int try_tmpdir) -{ - const char *d; - size_t dlen, plen; - - if (!pfx || !pfx[0]) - { - pfx = "file"; - plen = 4; - } - else - { - plen = strlen (pfx); - if (plen > 5) - plen = 5; - } - - if (try_tmpdir) - { - d = __secure_getenv ("TMPDIR"); - if (d != NULL && direxists (d)) - dir = d; - else if (dir != NULL && direxists (dir)) - /* nothing */ ; - else - dir = NULL; - } - if (dir == NULL) - { - if (direxists (P_tmpdir)) - dir = P_tmpdir; - else if (strcmp (P_tmpdir, "/tmp") != 0 && direxists ("/tmp")) - dir = "/tmp"; - else - { - __set_errno (ENOENT); - return -1; - } - } - - dlen = strlen (dir); - while (dlen > 1 && dir[dlen - 1] == '/') - dlen--; /* remove trailing slashes */ - - /* check we have room for "${dir}/${pfx}XXXXXX\0" */ - if (tmpl_len < dlen + 1 + plen + 6 + 1) - { - __set_errno (EINVAL); - return -1; - } - - sprintf (tmpl, "%.*s/%.*sXXXXXX", (int) dlen, dir, (int) plen, pfx); - return 0; -} -#endif /* _LIBC */ - #if _LIBC static int try_tempname_len (char *, int, void *, int (*) (char *, void *), size_t); -- 2.37.2 ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v2 2/2] Split __path_search into a separate file 2022-08-25 21:46 ` [PATCH v2 2/2] Split __path_search into a separate file Paul Eggert @ 2022-08-25 21:46 ` Paul Eggert 2022-08-26 9:47 ` Florian Weimer 1 sibling, 0 replies; 7+ messages in thread From: Paul Eggert @ 2022-08-25 21:46 UTC (permalink / raw) To: libc-alpha This simplifies sharing tempname with Gnulib. Suggested by Bruno Haible in: https://lists.gnu.org/r/bug-gnulib/2022-08/msg00077.html * stdio-common/Makefile (routines): Add path-search. (CFLAGS-path-search.c): New macro, which has -fexceptions because tempname.c has it. * stdio-common/path-search.c, sysdeps/posix/path-search.c: New files. * stdio-common/tempname.c (__need_size_t): Do not define. No need to include stddef.h, since stdio.h declares size_t. (__path_search): Move to path-search.c. * sysdeps/posix/tempname.c: Don't include sys/types.h, assert.h, stddef.h; not needed. (P_tmpdir): Remove. (__secure_getenv) [_LIBC]: Remove. (__stat64) [!_LIBC]: Remove. (direxists, __path_search) [_LIBC]: Move to path-search.c. --- stdio-common/Makefile | 2 + stdio-common/path-search.c | 31 +++++++++++++ stdio-common/tempname.c | 14 ------ sysdeps/posix/path-search.c | 92 +++++++++++++++++++++++++++++++++++++ sysdeps/posix/tempname.c | 82 --------------------------------- 5 files changed, 125 insertions(+), 96 deletions(-) create mode 100644 stdio-common/path-search.c create mode 100644 sysdeps/posix/path-search.c diff --git a/stdio-common/Makefile b/stdio-common/Makefile index b1e9144de0..1543b5414b 100644 --- a/stdio-common/Makefile +++ b/stdio-common/Makefile @@ -49,6 +49,7 @@ routines := \ itoa-digits \ itoa-udigits \ itowa-digits \ + path-search \ perror \ printf \ printf-prs \ @@ -351,6 +352,7 @@ $(objpfx)tst-errno-manual.out: tst-errno-manual.py \ CFLAGS-vfprintf.c += -Wno-uninitialized CFLAGS-vfwprintf.c += -Wno-uninitialized +CFLAGS-path-search.c += -fexceptions CFLAGS-tmpfile.c += -fexceptions CFLAGS-tmpfile64.c += -fexceptions CFLAGS-tempname.c += -fexceptions diff --git a/stdio-common/path-search.c b/stdio-common/path-search.c new file mode 100644 index 0000000000..6ad7002d7c --- /dev/null +++ b/stdio-common/path-search.c @@ -0,0 +1,31 @@ +/* Copyright (C) 1991-2022 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <stdio.h> +#include <errno.h> + +/* Perform the "SVID path search malarkey" on DIR and PFX. Write a + template suitable for use in __gen_tempname into TMPL, bounded + by TMPL_LEN. */ +int +__path_search (char *tmpl, size_t tmpl_len, const char *dir, const char *pfx, + int try_tmpdir) +{ + __set_errno (ENOSYS); + return -1; +} +stub_warning (__path_search) diff --git a/stdio-common/tempname.c b/stdio-common/tempname.c index 621876a9d9..6538fb1777 100644 --- a/stdio-common/tempname.c +++ b/stdio-common/tempname.c @@ -15,23 +15,9 @@ License along with the GNU C Library; if not, see <https://www.gnu.org/licenses/>. */ -#define __need_size_t -#include <stddef.h> #include <stdio.h> #include <errno.h> -/* Perform the "SVID path search malarkey" on DIR and PFX. Write a - template suitable for use in __gen_tempname into TMPL, bounded - by TMPL_LEN. */ -int -__path_search (char *tmpl, size_t tmpl_len, const char *dir, const char *pfx, - int try_tmpdir) -{ - __set_errno (ENOSYS); - return -1; -} -stub_warning (__path_search) - /* Generate a (hopefully) unique temporary filename in DIR (if applicable), using template TMPL. KIND determines what to do with that name. It may be one of: diff --git a/sysdeps/posix/path-search.c b/sysdeps/posix/path-search.c new file mode 100644 index 0000000000..ae2f404f58 --- /dev/null +++ b/sysdeps/posix/path-search.c @@ -0,0 +1,92 @@ +/* Copyright (C) 1991-2022 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include <sys/stat.h> + +/* Return nonzero if DIR is an existent directory. */ +static int +direxists (const char *dir) +{ + struct __stat64_t64 buf; + return __stat64_time64 (dir, &buf) == 0 && S_ISDIR (buf.st_mode); +} + +/* Path search algorithm, for tmpnam, tmpfile, etc. If DIR is + non-null and exists, uses it; otherwise uses the first of $TMPDIR, + P_tmpdir, /tmp that exists. Copies into TMPL a template suitable + for use with mk[s]temp. Will fail (-1) if DIR is non-null and + doesn't exist, none of the searched dirs exists, or there's not + enough space in TMPL. */ +int +__path_search (char *tmpl, size_t tmpl_len, const char *dir, const char *pfx, + int try_tmpdir) +{ + const char *d; + size_t dlen, plen; + + if (!pfx || !pfx[0]) + { + pfx = "file"; + plen = 4; + } + else + { + plen = strlen (pfx); + if (plen > 5) + plen = 5; + } + + if (try_tmpdir) + { + d = __libc_secure_getenv ("TMPDIR"); + if (d != NULL && direxists (d)) + dir = d; + else if (dir != NULL && direxists (dir)) + /* nothing */ ; + else + dir = NULL; + } + if (dir == NULL) + { + if (direxists (P_tmpdir)) + dir = P_tmpdir; + else if (strcmp (P_tmpdir, "/tmp") != 0 && direxists ("/tmp")) + dir = "/tmp"; + else + { + __set_errno (ENOENT); + return -1; + } + } + + dlen = strlen (dir); + while (dlen > 1 && dir[dlen - 1] == '/') + dlen--; /* remove trailing slashes */ + + /* check we have room for "${dir}/${pfx}XXXXXX\0" */ + if (tmpl_len < dlen + 1 + plen + 6 + 1) + { + __set_errno (EINVAL); + return -1; + } + + sprintf (tmpl, "%.*s/%.*sXXXXXX", (int) dlen, dir, (int) plen, pfx); + return 0; +} diff --git a/sysdeps/posix/tempname.c b/sysdeps/posix/tempname.c index 0e2f29f5de..11b4796b34 100644 --- a/sysdeps/posix/tempname.c +++ b/sysdeps/posix/tempname.c @@ -20,16 +20,10 @@ # include "tempname.h" #endif -#include <sys/types.h> -#include <assert.h> #include <stdbool.h> - #include <errno.h> #include <stdio.h> -#ifndef P_tmpdir -# define P_tmpdir "/tmp" -#endif #ifndef TMP_MAX # define TMP_MAX 238328 #endif @@ -43,7 +37,6 @@ # error report this to bug-gnulib@gnu.org #endif -#include <stddef.h> #include <stdlib.h> #include <string.h> @@ -55,14 +48,12 @@ #if _LIBC # define struct_stat64 struct __stat64_t64 -# define __secure_getenv __libc_secure_getenv #else # define struct_stat64 struct stat # define __gen_tempname gen_tempname # define __mkdir mkdir # define __open open # define __lstat64_time64(file, buf) lstat (file, buf) -# define __stat64(file, buf) stat (file, buf) # define __getrandom getrandom # define __clock_gettime64 clock_gettime # define __timespec64 timespec @@ -127,79 +118,6 @@ random_bits (random_value *r, random_value s) return false; } -#if _LIBC -/* Return nonzero if DIR is an existent directory. */ -static int -direxists (const char *dir) -{ - struct_stat64 buf; - return __stat64_time64 (dir, &buf) == 0 && S_ISDIR (buf.st_mode); -} - -/* Path search algorithm, for tmpnam, tmpfile, etc. If DIR is - non-null and exists, uses it; otherwise uses the first of $TMPDIR, - P_tmpdir, /tmp that exists. Copies into TMPL a template suitable - for use with mk[s]temp. Will fail (-1) if DIR is non-null and - doesn't exist, none of the searched dirs exists, or there's not - enough space in TMPL. */ -int -__path_search (char *tmpl, size_t tmpl_len, const char *dir, const char *pfx, - int try_tmpdir) -{ - const char *d; - size_t dlen, plen; - - if (!pfx || !pfx[0]) - { - pfx = "file"; - plen = 4; - } - else - { - plen = strlen (pfx); - if (plen > 5) - plen = 5; - } - - if (try_tmpdir) - { - d = __secure_getenv ("TMPDIR"); - if (d != NULL && direxists (d)) - dir = d; - else if (dir != NULL && direxists (dir)) - /* nothing */ ; - else - dir = NULL; - } - if (dir == NULL) - { - if (direxists (P_tmpdir)) - dir = P_tmpdir; - else if (strcmp (P_tmpdir, "/tmp") != 0 && direxists ("/tmp")) - dir = "/tmp"; - else - { - __set_errno (ENOENT); - return -1; - } - } - - dlen = strlen (dir); - while (dlen > 1 && dir[dlen - 1] == '/') - dlen--; /* remove trailing slashes */ - - /* check we have room for "${dir}/${pfx}XXXXXX\0" */ - if (tmpl_len < dlen + 1 + plen + 6 + 1) - { - __set_errno (EINVAL); - return -1; - } - - sprintf (tmpl, "%.*s/%.*sXXXXXX", (int) dlen, dir, (int) plen, pfx); - return 0; -} -#endif /* _LIBC */ - #if _LIBC static int try_tempname_len (char *, int, void *, int (*) (char *, void *), size_t); -- 2.37.2 ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v2 2/2] Split __path_search into a separate file 2022-08-25 21:46 ` [PATCH v2 2/2] Split __path_search into a separate file Paul Eggert 2022-08-25 21:46 ` Paul Eggert @ 2022-08-26 9:47 ` Florian Weimer 1 sibling, 0 replies; 7+ messages in thread From: Florian Weimer @ 2022-08-26 9:47 UTC (permalink / raw) To: Paul Eggert; +Cc: libc-alpha * Paul Eggert: > This simplifies sharing tempname with Gnulib. > Suggested by Bruno Haible in: > https://lists.gnu.org/r/bug-gnulib/2022-08/msg00077.html > * stdio-common/Makefile (routines): Add path-search. > (CFLAGS-path-search.c): New macro, which has -fexceptions > because tempname.c has it. > * stdio-common/path-search.c, sysdeps/posix/path-search.c: > New files. > * stdio-common/tempname.c (__need_size_t): Do not define. > No need to include stddef.h, since stdio.h declares size_t. > (__path_search): Move to path-search.c. > * sysdeps/posix/tempname.c: > Don't include sys/types.h, assert.h, stddef.h; not needed. > (P_tmpdir): Remove. > (__secure_getenv) [_LIBC]: Remove. > (__stat64) [!_LIBC]: Remove. > (direxists, __path_search) [_LIBC]: Move to path-search.c. sysdeps/posix/path-search.c is not intended to be shared with gnulib, right? Change looks okay to me. Thanks, Florian ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2022-08-26 9:47 UTC | newest] Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2022-08-25 21:46 [PATCH v2 0/2] tempname ALSR etc. fixes from Gnulib Paul Eggert 2022-08-25 21:46 ` Paul Eggert 2022-08-25 21:46 ` [PATCH v2 1/2] Merge tempname ASLR etc. patch " Paul Eggert 2022-08-25 21:46 ` Paul Eggert 2022-08-25 21:46 ` [PATCH v2 2/2] Split __path_search into a separate file Paul Eggert 2022-08-25 21:46 ` Paul Eggert 2022-08-26 9:47 ` Florian Weimer
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).