From 4f75b7a09a57e0d33ee0741c18114ce8ac5d6c3f Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Wed, 1 Aug 2012 10:33:11 -0700 Subject: [PATCH] Distinguish ELOOP diagnosis threshold from SYMLOOP_MAX. --- ChangeLog | 13 +++++++ elf/chroot_canon.c | 7 ++-- hurd/lookup-retry.c | 5 +-- stdlib/canonicalize.c | 6 ++-- sysdeps/generic/eloop-threshold.h | 72 +++++++++++++++++++++++++++++++++++++ sysdeps/mach/hurd/bits/local_lim.h | 13 +------ sysdeps/mach/hurd/eloop-threshold.h | 37 +++++++++++++++++++ sysdeps/mach/hurd/sys/param.h | 3 +- sysdeps/mach/hurd/sysconf.c | 26 ++++++++++++++ 9 files changed, 159 insertions(+), 23 deletions(-) create mode 100644 sysdeps/generic/eloop-threshold.h create mode 100644 sysdeps/mach/hurd/eloop-threshold.h create mode 100644 sysdeps/mach/hurd/sysconf.c diff --git a/ChangeLog b/ChangeLog index b31e23f..47f1338 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2012-08-03 Roland McGrath + + * sysdeps/mach/hurd/sys/param.h (MAXSYMLINKS): Macro removed. + * sysdeps/mach/hurd/bits/local_lim.h (SYMLOOP_MAX): Macro removed. + * sysdeps/mach/hurd/eloop-threshold.h: New file. + * hurd/lookup-retry.c (__hurd_file_name_lookup_retry): Use + __eloop_threshold instead of SYMLOOP_MAX. + + * sysdeps/generic/eloop-threshold.h: New file. + * stdlib/canonicalize.c (__realpath): Use __eloop_threshold instead + of MAXSYMLINKS. + * elf/chroot_canon.c (chroot_canon): Likewise. + 2012-08-03 Joseph Myers [BZ #13717] diff --git a/elf/chroot_canon.c b/elf/chroot_canon.c index a7a7d9b..397125f 100644 --- a/elf/chroot_canon.c +++ b/elf/chroot_canon.c @@ -1,6 +1,5 @@ /* Return the canonical absolute name of a given file inside chroot. - Copyright (C) 1996,1997,1998,1999,2000,2001,2004,2005,2010,2011 - Free Software Foundation, Inc. + Copyright (C) 1996-2012 Free Software Foundation, Inc. This file is part of the GNU C Library. This program is free software; you can redistribute it and/or modify @@ -20,12 +19,12 @@ #include #include #include -#include #include #include #include #include +#include #include #ifndef PATH_MAX @@ -127,7 +126,7 @@ chroot_canon (const char *chroot, const char *name) char *buf = alloca (PATH_MAX); size_t len; - if (++num_links > MAXSYMLINKS) + if (++num_links > __eloop_threshold ()) { __set_errno (ELOOP); goto error; diff --git a/hurd/lookup-retry.c b/hurd/lookup-retry.c index 4fa2a21..c95ca0f 100644 --- a/hurd/lookup-retry.c +++ b/hurd/lookup-retry.c @@ -24,6 +24,7 @@ #include #include #include <_itoa.h> +#include /* Translate the error from dir_lookup into the error the user sees. */ static inline error_t @@ -103,7 +104,7 @@ __hurd_file_name_lookup_retry (error_t (*use_init_port) /* Fall through. */ case FS_RETRY_NORMAL: - if (nloops++ >= SYMLOOP_MAX) + if (nloops++ >= __eloop_threshold ()) { __mach_port_deallocate (__mach_task_self (), *result); return ELOOP; @@ -180,7 +181,7 @@ __hurd_file_name_lookup_retry (error_t (*use_init_port) dirport = INIT_PORT_CRDIR; if (*result != MACH_PORT_NULL) __mach_port_deallocate (__mach_task_self (), *result); - if (nloops++ >= SYMLOOP_MAX) + if (nloops++ >= __eloop_threshold ()) return ELOOP; file_name = &retryname[1]; break; diff --git a/stdlib/canonicalize.c b/stdlib/canonicalize.c index 876b482..aeff804 100644 --- a/stdlib/canonicalize.c +++ b/stdlib/canonicalize.c @@ -1,5 +1,5 @@ /* Return the canonical absolute name of a given file. - Copyright (C) 1996-2002,2004,2005,2006,2008 Free Software Foundation, Inc. + Copyright (C) 1996-2012 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 @@ -21,11 +21,11 @@ #include #include #include -#include #include #include #include +#include #include /* Return the canonical absolute name of file NAME. A canonical name @@ -166,7 +166,7 @@ __realpath (const char *name, char *resolved) char *buf = __alloca (path_max); size_t len; - if (++num_links > MAXSYMLINKS) + if (++num_links > __eloop_threshold ()) { __set_errno (ELOOP); goto error; diff --git a/sysdeps/generic/eloop-threshold.h b/sysdeps/generic/eloop-threshold.h new file mode 100644 index 0000000..2342d29 --- /dev/null +++ b/sysdeps/generic/eloop-threshold.h @@ -0,0 +1,72 @@ +/* Threshold at which to diagnose ELOOP. Generic version. + Copyright (C) 2012 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 +#include + +/* 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 __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/sysdeps/mach/hurd/bits/local_lim.h b/sysdeps/mach/hurd/bits/local_lim.h index 48411d0..c957dad 100644 --- a/sysdeps/mach/hurd/bits/local_lim.h +++ b/sysdeps/mach/hurd/bits/local_lim.h @@ -1,5 +1,5 @@ /* Minimum guaranteed maximum values for system limits. Hurd version. - Copyright (C) 1993,94,96,98,2002 Free Software Foundation, Inc. + Copyright (C) 1993-2012 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 @@ -32,14 +32,3 @@ suitable, and `sysconf' will return a number at least as large. */ #define NGROUPS_MAX 256 - -/* The maximum number of symbolic links that are allowed in a single file - name resolution. When a further link is encountered, the call returns - ELOOP. This name is a GNU extension; POSIX.1 has no such limit, and BSD - calls it MAXSYMLINKS in . (We define the name under - _BSD_SOURCE even without _GNU_SOURCE because our uses it - to define MAXSYMLINKS.) */ - -#if defined __USE_GNU || defined __USE_BSD /* 1003.1a defines this */ -#define SYMLOOP_MAX 8 -#endif diff --git a/sysdeps/mach/hurd/eloop-threshold.h b/sysdeps/mach/hurd/eloop-threshold.h new file mode 100644 index 0000000..b8fae16 --- /dev/null +++ b/sysdeps/mach/hurd/eloop-threshold.h @@ -0,0 +1,37 @@ +/* Threshold at which to diagnose ELOOP. Hurd version. + Copyright (C) 2012 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 + +/* Return the maximum number of symlink traversals to permit + before diagnosing ELOOP. + + In the Hurd version, here we are actually setting the only policy + there is on the system. We use a literal number here rather than + defining SYMLOOP_MAX so that programs don't compile in a number + but instead use sysconf and the number can be changed here to + affect sysconf's result. */ + +static inline unsigned int __attribute__ ((const)) +__eloop_threshold (void) +{ + return 32; +} + +#endif /* eloop-threshold.h */ diff --git a/sysdeps/mach/hurd/sys/param.h b/sysdeps/mach/hurd/sys/param.h index 42f4f46..e58d517 100644 --- a/sysdeps/mach/hurd/sys/param.h +++ b/sysdeps/mach/hurd/sys/param.h @@ -1,4 +1,4 @@ -/* Copyright (C) 1993,1994,1995,1997,1999,2011 Free Software Foundation, Inc. +/* Copyright (C) 1993-2012 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 @@ -83,7 +83,6 @@ #define NBBY CHAR_BIT #define NGROUPS NGROUPS_MAX -#define MAXSYMLINKS SYMLOOP_MAX #define CANBSIZ MAX_CANON /* XXX ? */ /* ARG_MAX is unlimited, but we define NCARGS for BSD programs that want to diff --git a/sysdeps/mach/hurd/sysconf.c b/sysdeps/mach/hurd/sysconf.c new file mode 100644 index 0000000..6d1666d --- /dev/null +++ b/sysdeps/mach/hurd/sysconf.c @@ -0,0 +1,26 @@ +/* Return values of system parameters. Hurd version. + Copyright (C) 2012 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 + . */ + +#include +#include + +#include + +#define SYMLOOP_MAX (__eloop_threshold ()) + +#include -- 2.7.4