diff mbox series

[2/4] Alpha: Fix the RLIM_INFINITY and RLIM64_INFINITY constants

Message ID 20171230184441.25392-3-aurelien@aurel32.net
State New
Headers show
Series Alpha: Fix getrlimit/setrlimit with RLIM_INFINITY | expand

Commit Message

Aurelien Jarno Dec. 30, 2017, 6:44 p.m. UTC
Fix the RLIM_INFINITY and RLIM64_INFINITY constants on alpha to match
the kernel one and all other architectures. Change the getrlimit,
getrlimit64, setrlimit, setrlimit64 into old compat symbols, and provide
the Linux generic functions as GLIBC_2_27 version.

Note that the alpha implementation does not include the generic
getrlimit64.c or setrlimit64.c as they:
- redefine SHLIB_COMPAT when __RLIM_T_MATCHES_RLIM64_T == 1
- redefine getrlimit or setrlimit, not allowing to rename them into
  __new_getrlimit or __new_setrlimit.

Changelog:
	* sysdeps/unix/sysv/linux/alpha/bits/resource.h (RLIM_INFINITY,
	RLIM64_INFINITY): Fix values to match the kernel ones.
	* sysdeps/unix/sysv/linux/alpha/getrlimit64.c: Rename __getrlimit64
	into __old_getrlimit64 and provide it as getrlimit@@GLIBC_2_0 and
	getrlimit64@@GLIBC_2_1.  Add a __getrlimit64 function and provide it
	as getrlimit@@GLIBC_2_27 and getrlimit64@@GLIBC_2_27.
	* sysdeps/unix/sysv/linux/alpha/setrlimit64.c: Ditto with setrlimit
	and setrlimit64.
	* sysdeps/unix/sysv/linux/alpha/libc.abilist (GLIBC_2.27): Add
	getrlimit, setrlimit, getrlimit64 and setrlimit64.
	* sysdeps/unix/sysv/linux/alpha/Versions (libc): Add getrlimit,
	setrlimit, getrlimit64 and setrlimit64.
---
 ChangeLog                                     | 15 +++++++
 sysdeps/unix/sysv/linux/alpha/Versions        |  3 ++
 sysdeps/unix/sysv/linux/alpha/bits/resource.h |  6 +--
 sysdeps/unix/sysv/linux/alpha/getrlimit64.c   | 56 +++++++++++++++++++--------
 sysdeps/unix/sysv/linux/alpha/libc.abilist    |  4 ++
 sysdeps/unix/sysv/linux/alpha/setrlimit64.c   | 52 ++++++++++++++++++-------
 6 files changed, 102 insertions(+), 34 deletions(-)

Comments

Adhemerval Zanella Netto Dec. 31, 2017, 7:33 p.m. UTC | #1
On 30/12/2017 16:44, Aurelien Jarno wrote:
> Fix the RLIM_INFINITY and RLIM64_INFINITY constants on alpha to match
> the kernel one and all other architectures. Change the getrlimit,
> getrlimit64, setrlimit, setrlimit64 into old compat symbols, and provide
> the Linux generic functions as GLIBC_2_27 version.
> 
> Note that the alpha implementation does not include the generic
> getrlimit64.c or setrlimit64.c as they:
> - redefine SHLIB_COMPAT when __RLIM_T_MATCHES_RLIM64_T == 1
> - redefine getrlimit or setrlimit, not allowing to rename them into
>   __new_getrlimit or __new_setrlimit.

I think we can work this around to avoid code duplication with the following
patch (based on this one plus the previous one you posted). Basically:

  * it adds a new define, USE_VERSIONED_RLIMIT, which supress the alias to the 
    exported symbols on generic implementation (since alpha will add the
    versioned one instead).

  * it simplifies the SHLIB_COMPAT macros on alpha since there is no need to 
    check for both GLIBC_2_0 and GLIBC_2_1 (it is already an arch-specific
    file which assumes an already defined ABI, in this case GLIBC_2_0).

  * it adds a weak_alias alias between __getrlimit64 and __GI_getrlimit64
    for alpha case to follow generic case with libc_hidden_weak definition.

What do you think?

---
diff --git a/sysdeps/unix/sysv/linux/alpha/getrlimit64.c b/sysdeps/unix/sysv/linux/alpha/getrlimit64.c
index 25cf4aa..d8ac917 100644
--- a/sysdeps/unix/sysv/linux/alpha/getrlimit64.c
+++ b/sysdeps/unix/sysv/linux/alpha/getrlimit64.c
@@ -15,40 +15,12 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
-#include <errno.h>
-#include <sys/types.h>
-#include <shlib-compat.h>
-
-/* Add this redirection so the strong_alias for __RLIM_T_MATCHES_RLIM64_T
-   linking getrlimit64 to {__}getrlimit does not throw a type error.  */
-#undef getrlimit
-#undef __getrlimit
-#define getrlimit getrlimit_redirect
-#define __getrlimit __getrlimit_redirect
-#include <sys/resource.h>
-#undef getrlimit
-#undef __getrlimit
-
-
-/* Put the soft and hard limits for RESOURCE in *RLIMITS.
-   Returns 0 if successful, -1 if not (and sets errno).  */
-int
-__getrlimit64 (enum __rlimit_resource resource, struct rlimit64 *rlimits)
-{
-  return INLINE_SYSCALL_CALL (prlimit64, 0, resource, NULL, rlimits);
-}
-libc_hidden_def (__getrlimit64)
-
-strong_alias (__getrlimit64, __GI_getrlimit)
-strong_alias (__getrlimit64, __GI_getrlimit64)
-strong_alias (__getrlimit64, __GI___getrlimit)
-strong_alias (__getrlimit64, __getrlimit)
-
+#define USE_VERSIONED_RLIMIT
+#include <sysdeps/unix/sysv/linux/getrlimit64.c>
 versioned_symbol (libc, __getrlimit, getrlimit, GLIBC_2_27);
 versioned_symbol (libc, __getrlimit64, getrlimit64, GLIBC_2_27);
 
-#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_27) \
-    || SHLIB_COMPAT (libc, GLIBC_2_1, GLIBC_2_27)
+#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_27)
 /* RLIM64_INFINITY was supposed to be a glibc convention rather than
    anything seen by the kernel, but it ended being passed to the kernel
    through the prlimit64 syscall.  Given that a lot of binaries with
@@ -78,11 +50,7 @@ __old_getrlimit64 (enum __rlimit_resource resource,
   return 0;
 }
 
-# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_27)
 strong_alias (__old_getrlimit64, __old_getrlimit)
 compat_symbol (libc, __old_getrlimit, getrlimit, GLIBC_2_0);
-# endif
-# if SHLIB_COMPAT (libc, GLIBC_2_1, GLIBC_2_27)
 compat_symbol (libc, __old_getrlimit64, getrlimit64, GLIBC_2_1);
-# endif
 #endif
diff --git a/sysdeps/unix/sysv/linux/alpha/setrlimit64.c b/sysdeps/unix/sysv/linux/alpha/setrlimit64.c
index b8074d2..1735f68 100644
--- a/sysdeps/unix/sysv/linux/alpha/setrlimit64.c
+++ b/sysdeps/unix/sysv/linux/alpha/setrlimit64.c
@@ -15,38 +15,12 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
-#include <errno.h>
-#include <sys/types.h>
-#include <shlib-compat.h>
-
-/* Add this redirection so the strong_alias for __RLIM_T_MATCHES_RLIM64_T
-   linking setrlimit64 to {__}setrlimit does not throw a type error.  */
-#undef setrlimit
-#undef __setrlimit
-#define setrlimit setrlimit_redirect
-#define __setrlimit __setrlimit_redirect
-#include <sys/resource.h>
-#undef setrlimit
-#undef __setrlimit
-
-/* Set the soft and hard limits for RESOURCE to *RLIMITS.
-   Only the super-user can increase hard limits.
-   Return 0 if successful, -1 if not (and sets errno).  */
-int
-__setrlimit64 (enum __rlimit_resource resource, const struct rlimit64 *rlimits)
-{
-  return INLINE_SYSCALL_CALL (prlimit64, 0, resource, rlimits, NULL);
-}
-strong_alias (__setrlimit64, __setrlimit)
-# ifdef SHARED
-__hidden_ver1 (__setrlimit64, __GI___setrlimit, __setrlimit64);
-# endif
-
+#define USE_VERSIONED_RLIMIT
+#include <sysdeps/unix/sysv/linux/setrlimit64.c>
 versioned_symbol (libc, __setrlimit, setrlimit, GLIBC_2_27);
 versioned_symbol (libc, __setrlimit64, setrlimit64, GLIBC_2_27);
 
-#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_27) \
-    || SHLIB_COMPAT (libc, GLIBC_2_1, GLIBC_2_27)
+#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_27)
 /* RLIM64_INFINITY was supposed to be a glibc convention rather than
    anything seen by the kernel, but it ended being passed to the kernel
    through the prlimit64 syscall.  Given that a lot of binaries with
@@ -73,11 +47,7 @@ __old_setrlimit64 (enum __rlimit_resource resource,
   return __setrlimit64 (resource, &krlimits);
 }
 
-# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_27)
 strong_alias (__old_setrlimit64, __old_setrlimit)
 compat_symbol (libc, __old_setrlimit, setrlimit, GLIBC_2_0);
-# endif
-# if SHLIB_COMPAT (libc, GLIBC_2_1, GLIBC_2_27)
 compat_symbol (libc, __old_setrlimit64, setrlimit64, GLIBC_2_1);
-# endif
 #endif
diff --git a/sysdeps/unix/sysv/linux/getrlimit64.c b/sysdeps/unix/sysv/linux/getrlimit64.c
index 37827e5..d14fc63 100644
--- a/sysdeps/unix/sysv/linux/getrlimit64.c
+++ b/sysdeps/unix/sysv/linux/getrlimit64.c
@@ -45,13 +45,16 @@ libc_hidden_def (__getrlimit64)
 strong_alias (__getrlimit64, __GI_getrlimit)
 strong_alias (__getrlimit64, __GI___getrlimit)
 strong_alias (__getrlimit64, __getrlimit)
+/* Alpha defines a versioned getrlimit{64}.  */
+# ifndef USE_VERSIONED_RLIMIT
 weak_alias (__getrlimit64, getrlimit)
-/* And there is no need for compat symbols.  */
-# undef SHLIB_COMPAT
-# define SHLIB_COMPAT(a, b, c) 0
-#endif
+weak_alias (__getrlimit64, getrlimit64)
+libc_hidden_weak (getrlimit64)
+# else
+weak_alias (__getrlimit64, __GI_getrlimit64)
+# endif
 
-#if SHLIB_COMPAT (libc, GLIBC_2_1, GLIBC_2_2)
+#elif if SHLIB_COMPAT (libc, GLIBC_2_1, GLIBC_2_2)
 /* Back compatible 2GiB limited rlimit.  */
 extern int __new_getrlimit (enum __rlimit_resource, struct rlimit *)
   attribute_hidden;
@@ -82,7 +85,4 @@ __old_getrlimit64 (enum __rlimit_resource resource, struct rlimit64 *rlimits)
 }
 versioned_symbol (libc, __getrlimit64, getrlimit64, GLIBC_2_2);
 compat_symbol (libc, __old_getrlimit64, getrlimit64, GLIBC_2_1);
-#else
-weak_alias (__getrlimit64, getrlimit64)
-libc_hidden_weak (getrlimit64)
-#endif
+#endif /* __RLIM_T_MATCHES_RLIM64_T  */
diff --git a/sysdeps/unix/sysv/linux/setrlimit64.c b/sysdeps/unix/sysv/linux/setrlimit64.c
index ff835c8..0f5cc85 100644
--- a/sysdeps/unix/sysv/linux/setrlimit64.c
+++ b/sysdeps/unix/sysv/linux/setrlimit64.c
@@ -38,11 +38,16 @@ __setrlimit64 (enum __rlimit_resource resource, const struct rlimit64 *rlimits)
 {
   return INLINE_SYSCALL_CALL (prlimit64, 0, resource, rlimits, NULL);
 }
+/* Alpha defines a versioned setrlimit{64}.  */
+#ifndef USE_VERSIONED_RLIMIT
 weak_alias (__setrlimit64, setrlimit64)
+#endif
 
 #if __RLIM_T_MATCHES_RLIM64_T
 strong_alias (__setrlimit64, __setrlimit)
+# ifndef USE_VERSIONED_RLIMIT
 weak_alias (__setrlimit64, setrlimit)
+# endif
 # ifdef SHARED
 __hidden_ver1 (__setrlimit64, __GI___setrlimit, __setrlimit64);
 # endif
---

> 
> Changelog:
> 	* sysdeps/unix/sysv/linux/alpha/bits/resource.h (RLIM_INFINITY,
> 	RLIM64_INFINITY): Fix values to match the kernel ones.
> 	* sysdeps/unix/sysv/linux/alpha/getrlimit64.c: Rename __getrlimit64
> 	into __old_getrlimit64 and provide it as getrlimit@@GLIBC_2_0 and
> 	getrlimit64@@GLIBC_2_1.  Add a __getrlimit64 function and provide it
> 	as getrlimit@@GLIBC_2_27 and getrlimit64@@GLIBC_2_27.
> 	* sysdeps/unix/sysv/linux/alpha/setrlimit64.c: Ditto with setrlimit
> 	and setrlimit64.
> 	* sysdeps/unix/sysv/linux/alpha/libc.abilist (GLIBC_2.27): Add
> 	getrlimit, setrlimit, getrlimit64 and setrlimit64.
> 	* sysdeps/unix/sysv/linux/alpha/Versions (libc): Add getrlimit,
> 	setrlimit, getrlimit64 and setrlimit64.
> ---
>  ChangeLog                                     | 15 +++++++
>  sysdeps/unix/sysv/linux/alpha/Versions        |  3 ++
>  sysdeps/unix/sysv/linux/alpha/bits/resource.h |  6 +--
>  sysdeps/unix/sysv/linux/alpha/getrlimit64.c   | 56 +++++++++++++++++++--------
>  sysdeps/unix/sysv/linux/alpha/libc.abilist    |  4 ++
>  sysdeps/unix/sysv/linux/alpha/setrlimit64.c   | 52 ++++++++++++++++++-------
>  6 files changed, 102 insertions(+), 34 deletions(-)
> 
> diff --git a/ChangeLog b/ChangeLog
> index 433b10145d..1e8740530d 100644
> --- a/ChangeLog
> +++ b/ChangeLog
> @@ -1,3 +1,18 @@
> +2017-12-30  Aurelien Jarno <aurelien@aurel32.net>
> +
> +	* sysdeps/unix/sysv/linux/alpha/bits/resource.h (RLIM_INFINITY,
> +	RLIM64_INFINITY): Fix values to match the kernel ones.
> +	* sysdeps/unix/sysv/linux/alpha/getrlimit64.c: Rename __getrlimit64
> +	into __old_getrlimit64 and provide it as getrlimit@@GLIBC_2_0 and
> +	getrlimit64@@GLIBC_2_1.  Add a __getrlimit64 function and provide it
> +	as getrlimit@@GLIBC_2_27 and getrlimit64@@GLIBC_2_27.
> +	* sysdeps/unix/sysv/linux/alpha/setrlimit64.c: Ditto with setrlimit
> +	and setrlimit64.
> +	* sysdeps/unix/sysv/linux/alpha/libc.abilist (GLIBC_2.27): Add
> +	getrlimit, setrlimit, getrlimit64 and setrlimit64.
> +	* sysdeps/unix/sysv/linux/alpha/Versions (libc): Add getrlimit,
> +	setrlimit, getrlimit64 and setrlimit64.
> +
>  2017-12-30  Aurelien Jarno <aurelien@aurel32.net>
>  
>  	[BZ #22648]
> diff --git a/sysdeps/unix/sysv/linux/alpha/Versions b/sysdeps/unix/sysv/linux/alpha/Versions
> index 29b82f999b..3b7971c2a3 100644
> --- a/sysdeps/unix/sysv/linux/alpha/Versions
> +++ b/sysdeps/unix/sysv/linux/alpha/Versions
> @@ -85,6 +85,9 @@ libc {
>      #errlist-compat	140
>      _sys_errlist; sys_errlist; _sys_nerr; sys_nerr;
>    }
> +  GLIBC_2.27 {
> +    getrlimit; setrlimit; getrlimit64; setrlimit64;
> +  }
>    GLIBC_PRIVATE {
>      __libc_alpha_cache_shape;
>    }

Ok.

> diff --git a/sysdeps/unix/sysv/linux/alpha/bits/resource.h b/sysdeps/unix/sysv/linux/alpha/bits/resource.h
> index bd5142caa4..749703b716 100644
> --- a/sysdeps/unix/sysv/linux/alpha/bits/resource.h
> +++ b/sysdeps/unix/sysv/linux/alpha/bits/resource.h
> @@ -112,13 +112,13 @@ enum __rlimit_resource
>  
>  /* Value to indicate that there is no limit.  */
>  #ifndef __USE_FILE_OFFSET64
> -# define RLIM_INFINITY ((long int)(~0UL >> 1))
> +# define RLIM_INFINITY ((__rlim_t) -1)
>  #else
> -# define RLIM_INFINITY 0x7fffffffffffffffLL
> +# define RLIM_INFINITY 0xffffffffffffffffuLL
>  #endif
>  
>  #ifdef __USE_LARGEFILE64
> -# define RLIM64_INFINITY 0x7fffffffffffffffLL
> +# define RLIM64_INFINITY 0xffffffffffffffffuLL
>  #endif
>  
>  /* We can represent all limits.  */

Ok.  

> diff --git a/sysdeps/unix/sysv/linux/alpha/getrlimit64.c b/sysdeps/unix/sysv/linux/alpha/getrlimit64.c
> index ad398a136f..25cf4aa555 100644
> --- a/sysdeps/unix/sysv/linux/alpha/getrlimit64.c
> +++ b/sysdeps/unix/sysv/linux/alpha/getrlimit64.c
> @@ -17,9 +17,10 @@
>  
>  #include <errno.h>
>  #include <sys/types.h>
> +#include <shlib-compat.h>
>  
> -/* Add this redirection so the strong_alias linking getrlimit64 to
> -   {__}getrlimit does not throw a type error.  */
> +/* Add this redirection so the strong_alias for __RLIM_T_MATCHES_RLIM64_T
> +   linking getrlimit64 to {__}getrlimit does not throw a type error.  */
>  #undef getrlimit
>  #undef __getrlimit
>  #define getrlimit getrlimit_redirect
> @@ -28,37 +29,60 @@
>  #undef getrlimit
>  #undef __getrlimit
>  
> +
> +/* Put the soft and hard limits for RESOURCE in *RLIMITS.
> +   Returns 0 if successful, -1 if not (and sets errno).  */
> +int
> +__getrlimit64 (enum __rlimit_resource resource, struct rlimit64 *rlimits)
> +{
> +  return INLINE_SYSCALL_CALL (prlimit64, 0, resource, NULL, rlimits);
> +}
> +libc_hidden_def (__getrlimit64)
> +
> +strong_alias (__getrlimit64, __GI_getrlimit)
> +strong_alias (__getrlimit64, __GI_getrlimit64)
> +strong_alias (__getrlimit64, __GI___getrlimit)
> +strong_alias (__getrlimit64, __getrlimit)
> +
> +versioned_symbol (libc, __getrlimit, getrlimit, GLIBC_2_27);
> +versioned_symbol (libc, __getrlimit64, getrlimit64, GLIBC_2_27);
> +
> +#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_27) \
> +    || SHLIB_COMPAT (libc, GLIBC_2_1, GLIBC_2_27)
>  /* RLIM64_INFINITY was supposed to be a glibc convention rather than
>     anything seen by the kernel, but it ended being passed to the kernel
>     through the prlimit64 syscall.  Given that a lot of binaries with
>     the wrong constant value are in the wild, provide a wrapper function
>     fixing the value after the syscall.  */
> -#define KERNEL_RLIM64_INFINITY		0xffffffffffffffffULL
> +# define OLD_RLIM64_INFINITY           0x7fffffffffffffffULL
>  
>  int
> -__getrlimit64 (enum __rlimit_resource resource, struct rlimit64 *rlimits)
> +attribute_compat_text_section
> +__old_getrlimit64 (enum __rlimit_resource resource,
> +		   struct rlimit64 *rlimits)
>  {
>    struct rlimit64 krlimits;
>  
> -  if (INLINE_SYSCALL_CALL (prlimit64, 0, resource, NULL, &krlimits) < 0)
> +  if (__getrlimit64 (resource, &krlimits) < 0)
>      return -1;
>  
> -  if (krlimits.rlim_cur == KERNEL_RLIM64_INFINITY)
> -    rlimits->rlim_cur = RLIM64_INFINITY;
> +  if (krlimits.rlim_cur == RLIM64_INFINITY)
> +    rlimits->rlim_cur = OLD_RLIM64_INFINITY;
>    else
>      rlimits->rlim_cur = krlimits.rlim_cur;
> -  if (krlimits.rlim_max == KERNEL_RLIM64_INFINITY)
> -    rlimits->rlim_max = RLIM64_INFINITY;
> +  if (krlimits.rlim_max == RLIM64_INFINITY)
> +    rlimits->rlim_max = OLD_RLIM64_INFINITY;
>    else
>      rlimits->rlim_max = krlimits.rlim_max;
>  
>    return 0;
>  }
> -libc_hidden_def (__getrlimit64)
> -strong_alias (__getrlimit64, __GI_getrlimit)
> -strong_alias (__getrlimit64, __GI___getrlimit)
> -strong_alias (__getrlimit64, __getrlimit)
> -weak_alias (__getrlimit64, getrlimit)
>  
> -weak_alias (__getrlimit64, getrlimit64)
> -libc_hidden_weak (getrlimit64)
> +# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_27)
> +strong_alias (__old_getrlimit64, __old_getrlimit)
> +compat_symbol (libc, __old_getrlimit, getrlimit, GLIBC_2_0);
> +# endif
> +# if SHLIB_COMPAT (libc, GLIBC_2_1, GLIBC_2_27)
> +compat_symbol (libc, __old_getrlimit64, getrlimit64, GLIBC_2_1);
> +# endif
> +#endif
> diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist
> index fd2d81fb68..8674a874b4 100644
> --- a/sysdeps/unix/sysv/linux/alpha/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist
> @@ -2016,6 +2016,8 @@ GLIBC_2.26 pwritev64v2 F
>  GLIBC_2.26 reallocarray F
>  GLIBC_2.27 GLIBC_2.27 A
>  GLIBC_2.27 copy_file_range F
> +GLIBC_2.27 getrlimit F
> +GLIBC_2.27 getrlimit64 F
>  GLIBC_2.27 glob F
>  GLIBC_2.27 glob64 F
>  GLIBC_2.27 memfd_create F
> @@ -2025,6 +2027,8 @@ GLIBC_2.27 pkey_free F
>  GLIBC_2.27 pkey_get F
>  GLIBC_2.27 pkey_mprotect F
>  GLIBC_2.27 pkey_set F
> +GLIBC_2.27 setrlimit F
> +GLIBC_2.27 setrlimit64 F
>  GLIBC_2.27 strfromf128 F
>  GLIBC_2.27 strfromf32 F
>  GLIBC_2.27 strfromf32x F

Ok.

> diff --git a/sysdeps/unix/sysv/linux/alpha/setrlimit64.c b/sysdeps/unix/sysv/linux/alpha/setrlimit64.c
> index a5f7907afd..b8074d2df6 100644
> --- a/sysdeps/unix/sysv/linux/alpha/setrlimit64.c
> +++ b/sysdeps/unix/sysv/linux/alpha/setrlimit64.c
> @@ -17,9 +17,10 @@
>  
>  #include <errno.h>
>  #include <sys/types.h>
> +#include <shlib-compat.h>
>  
> -/* Add this redirection so the strong_alias linking setrlimit64 to
> -   {__}setrlimit does not throw a type error.  */
> +/* Add this redirection so the strong_alias for __RLIM_T_MATCHES_RLIM64_T
> +   linking setrlimit64 to {__}setrlimit does not throw a type error.  */
>  #undef setrlimit
>  #undef __setrlimit
>  #define setrlimit setrlimit_redirect
> @@ -28,34 +29,55 @@
>  #undef setrlimit
>  #undef __setrlimit
>  
> +/* Set the soft and hard limits for RESOURCE to *RLIMITS.
> +   Only the super-user can increase hard limits.
> +   Return 0 if successful, -1 if not (and sets errno).  */
> +int
> +__setrlimit64 (enum __rlimit_resource resource, const struct rlimit64 *rlimits)
> +{
> +  return INLINE_SYSCALL_CALL (prlimit64, 0, resource, rlimits, NULL);
> +}
> +strong_alias (__setrlimit64, __setrlimit)
> +# ifdef SHARED
> +__hidden_ver1 (__setrlimit64, __GI___setrlimit, __setrlimit64);
> +# endif
> +
> +versioned_symbol (libc, __setrlimit, setrlimit, GLIBC_2_27);
> +versioned_symbol (libc, __setrlimit64, setrlimit64, GLIBC_2_27);
> +
> +#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_27) \
> +    || SHLIB_COMPAT (libc, GLIBC_2_1, GLIBC_2_27)
>  /* RLIM64_INFINITY was supposed to be a glibc convention rather than
>     anything seen by the kernel, but it ended being passed to the kernel
>     through the prlimit64 syscall.  Given that a lot of binaries with
>     the wrong constant value are in the wild, provide a wrapper function
>     fixing the value before the syscall.  */
> -#define KERNEL_RLIM64_INFINITY		0xffffffffffffffffULL
> +# define OLD_RLIM64_INFINITY           0x7fffffffffffffffULL
>  
>  int
> -__setrlimit64 (enum __rlimit_resource resource, const struct rlimit64 *rlimits)
> +attribute_compat_text_section
> +__old_setrlimit64 (enum __rlimit_resource resource,
> +		   const struct rlimit64 *rlimits)
>  {
>    struct rlimit64 krlimits;
>  
> -  if (rlimits->rlim_cur == RLIM64_INFINITY)
> -    krlimits.rlim_cur = KERNEL_RLIM64_INFINITY;
> +  if (rlimits->rlim_cur == OLD_RLIM64_INFINITY)
> +    krlimits.rlim_cur = RLIM64_INFINITY;
>    else
>      krlimits.rlim_cur = rlimits->rlim_cur;
> -  if (rlimits->rlim_max == RLIM64_INFINITY)
> -    krlimits.rlim_max = KERNEL_RLIM64_INFINITY;
> +  if (rlimits->rlim_max == OLD_RLIM64_INFINITY)
> +    krlimits.rlim_max = RLIM64_INFINITY;
>    else
>      krlimits.rlim_max = rlimits->rlim_max;
>  
> -  return INLINE_SYSCALL_CALL (prlimit64, 0, resource, &krlimits, NULL);
> +  return __setrlimit64 (resource, &krlimits);
>  }
>  
> -weak_alias (__setrlimit64, setrlimit64)
> -
> -strong_alias (__setrlimit64, __setrlimit)
> -weak_alias (__setrlimit64, setrlimit)
> -#ifdef SHARED
> -__hidden_ver1 (__setrlimit64, __GI___setrlimit, __setrlimit64);
> +# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_27)
> +strong_alias (__old_setrlimit64, __old_setrlimit)
> +compat_symbol (libc, __old_setrlimit, setrlimit, GLIBC_2_0);
> +# endif
> +# if SHLIB_COMPAT (libc, GLIBC_2_1, GLIBC_2_27)
> +compat_symbol (libc, __old_setrlimit64, setrlimit64, GLIBC_2_1);
> +# endif
>  #endif
>
Aurelien Jarno Jan. 3, 2018, 4:35 p.m. UTC | #2
On 2017-12-31 17:33, Adhemerval Zanella wrote:
> 
> 
> On 30/12/2017 16:44, Aurelien Jarno wrote:
> > Fix the RLIM_INFINITY and RLIM64_INFINITY constants on alpha to match
> > the kernel one and all other architectures. Change the getrlimit,
> > getrlimit64, setrlimit, setrlimit64 into old compat symbols, and provide
> > the Linux generic functions as GLIBC_2_27 version.
> > 
> > Note that the alpha implementation does not include the generic
> > getrlimit64.c or setrlimit64.c as they:
> > - redefine SHLIB_COMPAT when __RLIM_T_MATCHES_RLIM64_T == 1
> > - redefine getrlimit or setrlimit, not allowing to rename them into
> >   __new_getrlimit or __new_setrlimit.
> 
> I think we can work this around to avoid code duplication with the following
> patch (based on this one plus the previous one you posted). Basically:
> 
>   * it adds a new define, USE_VERSIONED_RLIMIT, which supress the alias to the 
>     exported symbols on generic implementation (since alpha will add the
>     versioned one instead).
> 
>   * it simplifies the SHLIB_COMPAT macros on alpha since there is no need to 
>     check for both GLIBC_2_0 and GLIBC_2_1 (it is already an arch-specific
>     file which assumes an already defined ABI, in this case GLIBC_2_0).
> 
>   * it adds a weak_alias alias between __getrlimit64 and __GI_getrlimit64
>     for alpha case to follow generic case with libc_hidden_weak definition.
> 
> What do you think?

Thanks, this looks all good to me, and works as expected. I am currently
writing a test to catch this kind of issues. I'll send the new patches
when it's done. I have already committed the patches 3 & 4.

Aurelien
diff mbox series

Patch

diff --git a/ChangeLog b/ChangeLog
index 433b10145d..1e8740530d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@ 
+2017-12-30  Aurelien Jarno <aurelien@aurel32.net>
+
+	* sysdeps/unix/sysv/linux/alpha/bits/resource.h (RLIM_INFINITY,
+	RLIM64_INFINITY): Fix values to match the kernel ones.
+	* sysdeps/unix/sysv/linux/alpha/getrlimit64.c: Rename __getrlimit64
+	into __old_getrlimit64 and provide it as getrlimit@@GLIBC_2_0 and
+	getrlimit64@@GLIBC_2_1.  Add a __getrlimit64 function and provide it
+	as getrlimit@@GLIBC_2_27 and getrlimit64@@GLIBC_2_27.
+	* sysdeps/unix/sysv/linux/alpha/setrlimit64.c: Ditto with setrlimit
+	and setrlimit64.
+	* sysdeps/unix/sysv/linux/alpha/libc.abilist (GLIBC_2.27): Add
+	getrlimit, setrlimit, getrlimit64 and setrlimit64.
+	* sysdeps/unix/sysv/linux/alpha/Versions (libc): Add getrlimit,
+	setrlimit, getrlimit64 and setrlimit64.
+
 2017-12-30  Aurelien Jarno <aurelien@aurel32.net>
 
 	[BZ #22648]
diff --git a/sysdeps/unix/sysv/linux/alpha/Versions b/sysdeps/unix/sysv/linux/alpha/Versions
index 29b82f999b..3b7971c2a3 100644
--- a/sysdeps/unix/sysv/linux/alpha/Versions
+++ b/sysdeps/unix/sysv/linux/alpha/Versions
@@ -85,6 +85,9 @@  libc {
     #errlist-compat	140
     _sys_errlist; sys_errlist; _sys_nerr; sys_nerr;
   }
+  GLIBC_2.27 {
+    getrlimit; setrlimit; getrlimit64; setrlimit64;
+  }
   GLIBC_PRIVATE {
     __libc_alpha_cache_shape;
   }
diff --git a/sysdeps/unix/sysv/linux/alpha/bits/resource.h b/sysdeps/unix/sysv/linux/alpha/bits/resource.h
index bd5142caa4..749703b716 100644
--- a/sysdeps/unix/sysv/linux/alpha/bits/resource.h
+++ b/sysdeps/unix/sysv/linux/alpha/bits/resource.h
@@ -112,13 +112,13 @@  enum __rlimit_resource
 
 /* Value to indicate that there is no limit.  */
 #ifndef __USE_FILE_OFFSET64
-# define RLIM_INFINITY ((long int)(~0UL >> 1))
+# define RLIM_INFINITY ((__rlim_t) -1)
 #else
-# define RLIM_INFINITY 0x7fffffffffffffffLL
+# define RLIM_INFINITY 0xffffffffffffffffuLL
 #endif
 
 #ifdef __USE_LARGEFILE64
-# define RLIM64_INFINITY 0x7fffffffffffffffLL
+# define RLIM64_INFINITY 0xffffffffffffffffuLL
 #endif
 
 /* We can represent all limits.  */
diff --git a/sysdeps/unix/sysv/linux/alpha/getrlimit64.c b/sysdeps/unix/sysv/linux/alpha/getrlimit64.c
index ad398a136f..25cf4aa555 100644
--- a/sysdeps/unix/sysv/linux/alpha/getrlimit64.c
+++ b/sysdeps/unix/sysv/linux/alpha/getrlimit64.c
@@ -17,9 +17,10 @@ 
 
 #include <errno.h>
 #include <sys/types.h>
+#include <shlib-compat.h>
 
-/* Add this redirection so the strong_alias linking getrlimit64 to
-   {__}getrlimit does not throw a type error.  */
+/* Add this redirection so the strong_alias for __RLIM_T_MATCHES_RLIM64_T
+   linking getrlimit64 to {__}getrlimit does not throw a type error.  */
 #undef getrlimit
 #undef __getrlimit
 #define getrlimit getrlimit_redirect
@@ -28,37 +29,60 @@ 
 #undef getrlimit
 #undef __getrlimit
 
+
+/* Put the soft and hard limits for RESOURCE in *RLIMITS.
+   Returns 0 if successful, -1 if not (and sets errno).  */
+int
+__getrlimit64 (enum __rlimit_resource resource, struct rlimit64 *rlimits)
+{
+  return INLINE_SYSCALL_CALL (prlimit64, 0, resource, NULL, rlimits);
+}
+libc_hidden_def (__getrlimit64)
+
+strong_alias (__getrlimit64, __GI_getrlimit)
+strong_alias (__getrlimit64, __GI_getrlimit64)
+strong_alias (__getrlimit64, __GI___getrlimit)
+strong_alias (__getrlimit64, __getrlimit)
+
+versioned_symbol (libc, __getrlimit, getrlimit, GLIBC_2_27);
+versioned_symbol (libc, __getrlimit64, getrlimit64, GLIBC_2_27);
+
+#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_27) \
+    || SHLIB_COMPAT (libc, GLIBC_2_1, GLIBC_2_27)
 /* RLIM64_INFINITY was supposed to be a glibc convention rather than
    anything seen by the kernel, but it ended being passed to the kernel
    through the prlimit64 syscall.  Given that a lot of binaries with
    the wrong constant value are in the wild, provide a wrapper function
    fixing the value after the syscall.  */
-#define KERNEL_RLIM64_INFINITY		0xffffffffffffffffULL
+# define OLD_RLIM64_INFINITY           0x7fffffffffffffffULL
 
 int
-__getrlimit64 (enum __rlimit_resource resource, struct rlimit64 *rlimits)
+attribute_compat_text_section
+__old_getrlimit64 (enum __rlimit_resource resource,
+		   struct rlimit64 *rlimits)
 {
   struct rlimit64 krlimits;
 
-  if (INLINE_SYSCALL_CALL (prlimit64, 0, resource, NULL, &krlimits) < 0)
+  if (__getrlimit64 (resource, &krlimits) < 0)
     return -1;
 
-  if (krlimits.rlim_cur == KERNEL_RLIM64_INFINITY)
-    rlimits->rlim_cur = RLIM64_INFINITY;
+  if (krlimits.rlim_cur == RLIM64_INFINITY)
+    rlimits->rlim_cur = OLD_RLIM64_INFINITY;
   else
     rlimits->rlim_cur = krlimits.rlim_cur;
-  if (krlimits.rlim_max == KERNEL_RLIM64_INFINITY)
-    rlimits->rlim_max = RLIM64_INFINITY;
+  if (krlimits.rlim_max == RLIM64_INFINITY)
+    rlimits->rlim_max = OLD_RLIM64_INFINITY;
   else
     rlimits->rlim_max = krlimits.rlim_max;
 
   return 0;
 }
-libc_hidden_def (__getrlimit64)
-strong_alias (__getrlimit64, __GI_getrlimit)
-strong_alias (__getrlimit64, __GI___getrlimit)
-strong_alias (__getrlimit64, __getrlimit)
-weak_alias (__getrlimit64, getrlimit)
 
-weak_alias (__getrlimit64, getrlimit64)
-libc_hidden_weak (getrlimit64)
+# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_27)
+strong_alias (__old_getrlimit64, __old_getrlimit)
+compat_symbol (libc, __old_getrlimit, getrlimit, GLIBC_2_0);
+# endif
+# if SHLIB_COMPAT (libc, GLIBC_2_1, GLIBC_2_27)
+compat_symbol (libc, __old_getrlimit64, getrlimit64, GLIBC_2_1);
+# endif
+#endif
diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist
index fd2d81fb68..8674a874b4 100644
--- a/sysdeps/unix/sysv/linux/alpha/libc.abilist
+++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist
@@ -2016,6 +2016,8 @@  GLIBC_2.26 pwritev64v2 F
 GLIBC_2.26 reallocarray F
 GLIBC_2.27 GLIBC_2.27 A
 GLIBC_2.27 copy_file_range F
+GLIBC_2.27 getrlimit F
+GLIBC_2.27 getrlimit64 F
 GLIBC_2.27 glob F
 GLIBC_2.27 glob64 F
 GLIBC_2.27 memfd_create F
@@ -2025,6 +2027,8 @@  GLIBC_2.27 pkey_free F
 GLIBC_2.27 pkey_get F
 GLIBC_2.27 pkey_mprotect F
 GLIBC_2.27 pkey_set F
+GLIBC_2.27 setrlimit F
+GLIBC_2.27 setrlimit64 F
 GLIBC_2.27 strfromf128 F
 GLIBC_2.27 strfromf32 F
 GLIBC_2.27 strfromf32x F
diff --git a/sysdeps/unix/sysv/linux/alpha/setrlimit64.c b/sysdeps/unix/sysv/linux/alpha/setrlimit64.c
index a5f7907afd..b8074d2df6 100644
--- a/sysdeps/unix/sysv/linux/alpha/setrlimit64.c
+++ b/sysdeps/unix/sysv/linux/alpha/setrlimit64.c
@@ -17,9 +17,10 @@ 
 
 #include <errno.h>
 #include <sys/types.h>
+#include <shlib-compat.h>
 
-/* Add this redirection so the strong_alias linking setrlimit64 to
-   {__}setrlimit does not throw a type error.  */
+/* Add this redirection so the strong_alias for __RLIM_T_MATCHES_RLIM64_T
+   linking setrlimit64 to {__}setrlimit does not throw a type error.  */
 #undef setrlimit
 #undef __setrlimit
 #define setrlimit setrlimit_redirect
@@ -28,34 +29,55 @@ 
 #undef setrlimit
 #undef __setrlimit
 
+/* Set the soft and hard limits for RESOURCE to *RLIMITS.
+   Only the super-user can increase hard limits.
+   Return 0 if successful, -1 if not (and sets errno).  */
+int
+__setrlimit64 (enum __rlimit_resource resource, const struct rlimit64 *rlimits)
+{
+  return INLINE_SYSCALL_CALL (prlimit64, 0, resource, rlimits, NULL);
+}
+strong_alias (__setrlimit64, __setrlimit)
+# ifdef SHARED
+__hidden_ver1 (__setrlimit64, __GI___setrlimit, __setrlimit64);
+# endif
+
+versioned_symbol (libc, __setrlimit, setrlimit, GLIBC_2_27);
+versioned_symbol (libc, __setrlimit64, setrlimit64, GLIBC_2_27);
+
+#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_27) \
+    || SHLIB_COMPAT (libc, GLIBC_2_1, GLIBC_2_27)
 /* RLIM64_INFINITY was supposed to be a glibc convention rather than
    anything seen by the kernel, but it ended being passed to the kernel
    through the prlimit64 syscall.  Given that a lot of binaries with
    the wrong constant value are in the wild, provide a wrapper function
    fixing the value before the syscall.  */
-#define KERNEL_RLIM64_INFINITY		0xffffffffffffffffULL
+# define OLD_RLIM64_INFINITY           0x7fffffffffffffffULL
 
 int
-__setrlimit64 (enum __rlimit_resource resource, const struct rlimit64 *rlimits)
+attribute_compat_text_section
+__old_setrlimit64 (enum __rlimit_resource resource,
+		   const struct rlimit64 *rlimits)
 {
   struct rlimit64 krlimits;
 
-  if (rlimits->rlim_cur == RLIM64_INFINITY)
-    krlimits.rlim_cur = KERNEL_RLIM64_INFINITY;
+  if (rlimits->rlim_cur == OLD_RLIM64_INFINITY)
+    krlimits.rlim_cur = RLIM64_INFINITY;
   else
     krlimits.rlim_cur = rlimits->rlim_cur;
-  if (rlimits->rlim_max == RLIM64_INFINITY)
-    krlimits.rlim_max = KERNEL_RLIM64_INFINITY;
+  if (rlimits->rlim_max == OLD_RLIM64_INFINITY)
+    krlimits.rlim_max = RLIM64_INFINITY;
   else
     krlimits.rlim_max = rlimits->rlim_max;
 
-  return INLINE_SYSCALL_CALL (prlimit64, 0, resource, &krlimits, NULL);
+  return __setrlimit64 (resource, &krlimits);
 }
 
-weak_alias (__setrlimit64, setrlimit64)
-
-strong_alias (__setrlimit64, __setrlimit)
-weak_alias (__setrlimit64, setrlimit)
-#ifdef SHARED
-__hidden_ver1 (__setrlimit64, __GI___setrlimit, __setrlimit64);
+# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_27)
+strong_alias (__old_setrlimit64, __old_setrlimit)
+compat_symbol (libc, __old_setrlimit, setrlimit, GLIBC_2_0);
+# endif
+# if SHLIB_COMPAT (libc, GLIBC_2_1, GLIBC_2_27)
+compat_symbol (libc, __old_setrlimit64, setrlimit64, GLIBC_2_1);
+# endif
 #endif