>From 1f866f6707cb9cc0f5e76c1d88d39f629fac51c8 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Thu, 24 Dec 2020 11:38:48 -0800 Subject: [PATCH 06/10] eloop-threshold: new module * config/srclist.txt: Add a comment about it. * lib/eloop-threshold.h, modules/eloop-threshold: New files. --- ChangeLog | 4 ++ config/srclist.txt | 1 + lib/eloop-threshold.h | 83 +++++++++++++++++++++++++++++++++++++++++ modules/eloop-threshold | 22 +++++++++++ 4 files changed, 110 insertions(+) create mode 100644 lib/eloop-threshold.h create mode 100644 modules/eloop-threshold diff --git a/ChangeLog b/ChangeLog index 94427d748..b119360f3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2020-12-24 Paul Eggert + eloop-threshold: new module + * config/srclist.txt: Add a comment about it. + * lib/eloop-threshold.h, modules/eloop-threshold: New files. + canonicalize: prefer faccessat to stat A proper faccessat doesn't have the EOVERFLOW problem, and can be more efficient as it needn't gather data from the filesystem to diff --git a/config/srclist.txt b/config/srclist.txt index 02e843829..f33b1353f 100644 --- a/config/srclist.txt +++ b/config/srclist.txt @@ -60,6 +60,7 @@ $LIBCSRC posix/regex.c lib #$LIBCSRC posix/regex_internal.c lib #$LIBCSRC posix/regex_internal.h lib $LIBCSRC posix/regexec.c lib +#$LIBCSRC sysdeps/generic/eloop-threshold.h lib $LIBCSRC time/timegm.c lib #$LIBCSRC time/mktime.c lib $LIBCSRC time/mktime-internal.h lib diff --git a/lib/eloop-threshold.h b/lib/eloop-threshold.h new file mode 100644 index 000000000..b61e4869d --- /dev/null +++ b/lib/eloop-threshold.h @@ -0,0 +1,83 @@ +/* Threshold at which to diagnose ELOOP. Generic version. + Copyright (C) 2012-2020 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 + . */ + +#ifndef _ELOOP_THRESHOLD_H +#define _ELOOP_THRESHOLD_H 1 + +#include +#ifdef _LIBC +# include +# define _GL_ATTRIBUTE_CONST __attribute__ ((const)) +#else +# include +# include "minmax.h" +# define __sysconf sysconf +# if (!defined SYMLOOP_MAX \ + && ! (defined _SC_SYMLOOP_MAX && defined _POSIX_SYMLOOP_MAX)) +# define SYMLOOP_MAX 8 +# endif +#endif + +/* POSIX specifies SYMLOOP_MAX as the "Maximum number of symbolic + links that can be reliably traversed in the resolution of a + pathname in the absence of a loop." This makes it a minimum that + we should certainly accept. But it leaves open the possibility + that more might sometimes work--just not "reliably". + + For example, Linux implements a complex policy whereby there is a + small limit on the number of direct symlink traversals (a symlink + to a symlink to a symlink), but larger limit on the total number of + symlink traversals overall. Hence the SYMLOOP_MAX number should be + the small one, but the limit library functions enforce on users + should be the larger one. + + So, we use the larger of the reported SYMLOOP_MAX (if any) and our + own constant MIN_ELOOP_THRESHOLD, below. This constant should be + large enough that it never rules out a file name and directory tree + that the underlying system (i.e. calls to 'open' et al) would + resolve successfully. It should be small enough that actual loops + are detected without a huge number of iterations. */ + +#ifndef MIN_ELOOP_THRESHOLD +# define MIN_ELOOP_THRESHOLD 40 +#endif + +/* Return the maximum number of symlink traversals to permit + before diagnosing ELOOP. */ +static inline unsigned int _GL_ATTRIBUTE_CONST +__eloop_threshold (void) +{ +#ifdef SYMLOOP_MAX + const int symloop_max = SYMLOOP_MAX; +#else + /* The function is marked 'const' even though we use memory and + call a function, because sysconf is required to return the + same value in every call and so it must always be safe to + call __eloop_threshold exactly once and reuse the value. */ + static long int sysconf_symloop_max; + if (sysconf_symloop_max == 0) + sysconf_symloop_max = __sysconf (_SC_SYMLOOP_MAX); + const unsigned int symloop_max = (sysconf_symloop_max <= 0 + ? _POSIX_SYMLOOP_MAX + : sysconf_symloop_max); +#endif + + return MAX (symloop_max, MIN_ELOOP_THRESHOLD); +} + +#endif /* eloop-threshold.h */ diff --git a/modules/eloop-threshold b/modules/eloop-threshold new file mode 100644 index 000000000..60433e530 --- /dev/null +++ b/modules/eloop-threshold @@ -0,0 +1,22 @@ +Description: +Threshold for symbolic link loops and ELOOP + +Files: +lib/eloop-threshold.h + +Depends-on: +minmax +unistd + +configure.ac: + +Makefile.am: + +Include: + + +License: +LGPLv2+ + +Maintainer: +all, glibc -- 2.27.0