diff mbox series

[1/2] Deprecate sysctl syscall interface

Message ID 1524523018-7216-1-git-send-email-adhemerval.zanella@linaro.org
State New
Headers show
Series [1/2] Deprecate sysctl syscall interface | expand

Commit Message

Adhemerval Zanella April 23, 2018, 10:36 p.m. UTC
The sysctl syscall has been long deprecated [1] (since Linux 2.6.24)
with its usage issues a kernel warning stating it.  Also on GLIBC new
portsi, which uses generic syscall interface, builds a stub version that
returns ENOSYS (so new ports should not rely on it anyway and some
kernel config do disable it by not setting CONFIG_SYSCTL_SYSCALL).

Every interface is directly accessed through /proc/sys and the only
real case scanarion I am aware is to have a fail-proof way to gather
entropy in cases where /dev/urandom or /proc is not available.  However,
as noted previously, this is quite fragile (new ports do not provide it)
and GLIBC now provides getentropy to this specific case (although it is
only supported on Linux 3.17).  If sysctl is stricly required, it still
can be issues through syscall().

This patch deprecate sysctl interface by issuing ENOSYS as default
and adds compat symbol for architectures which still defines
__NR_sysctl.

Checked on x86_64-linux-gnu and i686-linux-gnu.  Also checked with a
check-abi on all affected ABIs.

	* sysdeps/unix/sysv/linux/arm/ioperm.c (sysctl_call): New function.
	(init_iosys): Call syscall_call instead of sysctl.
	* sysdeps/unix/sysv/linux/generic/sysctl.c: Remove file.
	* sysdeps/unix/sysv/linux/sysctl.c: New file.
	* sysdeps/unix/sysv/linux/alpha/Versions [GLIBC_2.28] (sysctl): New
	symbol.
	* sysdeps/unix/sysv/linux/arm/Versions: Likewise.
	* sysdeps/unix/sysv/linux/i386/Versions: Likewise.
	* sysdeps/unix/sysv/linux/hppa/Versions:iLikewise.
	* sysdeps/unix/sysv/linux/ia64/Versions: Likewise.
	* sysdeps/unix/sysv/linux/powerpc/Versions: Likewise.
	* sysdeps/unix/sysv/linux/m68k/Versions: Likewise.
	* sysdeps/unix/sysv/linux/microblaze/Versions: Likewise.
	* sysdeps/unix/sysv/linux/mips/Versions: Likewise.
	* sysdeps/unix/sysv/linux/s390/Versions: Likewise.
	* sysdeps/unix/sysv/linux/sh/Versions: Likewise.
	* sysdeps/unix/sysv/linux/sparc/Versions: Likewise.
	* sysdeps/unix/sysv/linux/x86_64/Versions: Likewise.
	* sysdeps/unix/sysv/linux/alpha/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/hppa/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/ia64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/microblaze/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist:
	Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist:
	Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/sh/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/arm/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/i386/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/x86_64/64/libc.abilist: Likewise.

[1] https://lwn.net/Articles/247243/
---
 ChangeLog                                          | 44 ++++++++++++++++++++++
 sysdeps/unix/sysv/linux/alpha/Versions             |  3 ++
 sysdeps/unix/sysv/linux/alpha/libc.abilist         |  2 +
 sysdeps/unix/sysv/linux/arm/Versions               |  3 ++
 sysdeps/unix/sysv/linux/arm/ioperm.c               | 21 ++++++++++-
 sysdeps/unix/sysv/linux/arm/libc.abilist           |  2 +
 sysdeps/unix/sysv/linux/generic/sysctl.c           | 32 ----------------
 sysdeps/unix/sysv/linux/hppa/Versions              |  3 ++
 sysdeps/unix/sysv/linux/hppa/libc.abilist          |  2 +
 sysdeps/unix/sysv/linux/i386/Versions              |  3 ++
 sysdeps/unix/sysv/linux/i386/libc.abilist          |  2 +
 sysdeps/unix/sysv/linux/ia64/Versions              |  3 ++
 sysdeps/unix/sysv/linux/ia64/libc.abilist          |  2 +
 sysdeps/unix/sysv/linux/m68k/Versions              |  3 ++
 sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist |  2 +
 sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist   |  2 +
 sysdeps/unix/sysv/linux/microblaze/Versions        |  3 ++
 sysdeps/unix/sysv/linux/microblaze/libc.abilist    |  2 +
 sysdeps/unix/sysv/linux/mips/Versions              |  3 ++
 .../unix/sysv/linux/mips/mips32/fpu/libc.abilist   |  2 +
 .../unix/sysv/linux/mips/mips32/nofpu/libc.abilist |  2 +
 .../unix/sysv/linux/mips/mips64/n32/libc.abilist   |  2 +
 .../unix/sysv/linux/mips/mips64/n64/libc.abilist   |  2 +
 sysdeps/unix/sysv/linux/powerpc/Versions           |  3 ++
 .../sysv/linux/powerpc/powerpc32/fpu/libc.abilist  |  2 +
 .../linux/powerpc/powerpc32/nofpu/libc.abilist     |  2 +
 .../sysv/linux/powerpc/powerpc64/libc-le.abilist   |  2 +
 .../unix/sysv/linux/powerpc/powerpc64/libc.abilist |  2 +
 sysdeps/unix/sysv/linux/s390/Versions              |  3 ++
 sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist  |  2 +
 sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist  |  2 +
 sysdeps/unix/sysv/linux/sh/Versions                |  3 ++
 sysdeps/unix/sysv/linux/sh/libc.abilist            |  2 +
 sysdeps/unix/sysv/linux/sparc/Versions             |  3 ++
 sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist |  2 +
 sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist |  2 +
 sysdeps/unix/sysv/linux/sysctl.c                   | 44 ++++++++++++++++------
 sysdeps/unix/sysv/linux/x86_64/64/libc.abilist     |  2 +
 sysdeps/unix/sysv/linux/x86_64/Versions            |  3 ++
 sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist    |  1 +
 40 files changed, 180 insertions(+), 45 deletions(-)
 delete mode 100644 sysdeps/unix/sysv/linux/generic/sysctl.c

-- 
2.7.4

Comments

Joseph Myers April 23, 2018, 11:15 p.m. UTC | #1
I don't think it makes sense at all to add a new symbol version for 
something being deprecated.  If you deprecate a symbol, you make the 
*existing* version into a compat symbol, and stop it being declared and 
stop it being defined for new ports and static linking.

-- 
Joseph S. Myers
joseph@codesourcery.com
Joseph Myers April 23, 2018, 11:19 p.m. UTC | #2
Also, sysctl is documented, so a proper obsoletion would need to remove 
the documentation, in addition to removing the declaration, adding a NEWS 
entry, making existing symbol versions into compat symbols and ensuring 
the function is not built at all for new ports or static linking.

-- 
Joseph S. Myers
joseph@codesourcery.com
Adhemerval Zanella April 25, 2018, 12:50 p.m. UTC | #3
On 23/04/2018 20:19, Joseph Myers wrote:
> Also, sysctl is documented, so a proper obsoletion would need to remove 

> the documentation, in addition to removing the declaration, adding a NEWS 

> entry, making existing symbol versions into compat symbols and ensuring 

> the function is not built at all for new ports or static linking.

> 


My initial idea was to follow generic logic (new ports returns EINVAL),
but indeed adding new symbols does not make sense for deprecation.  Below
it is an updated patch which addresses the issues you brought.

---

The sysctl syscall has been long deprecated [1] (since Linux 2.6.24)
with its usage issues a kernel warning stating it.  Also on GLIBC new
ports, which uses generic syscall interface, builds a stub version that
returns ENOSYS (so new ports should not rely on it anyway and some
kernel config do disable it by not setting CONFIG_SYSCTL_SYSCALL).

Every interface is directly accessed through /proc/sys and the only
real case scanarion I am aware is to have a fail-proof way to gather
entropy in cases where /dev/urandom or /proc is not available.  However,
as noted previously, this is quite fragile (new ports do not provide it)
and GLIBC now provides getentropy to this specific case (although it is
only supported on Linux 3.17).  If sysctl is stricly required, it still
can be issues through syscall().

This patch deprecate sysctl interface by issuing ENOSYS as default
and adds compat symbol for architectures which still defines
__NR_sysctl.

Checked on x86_64-linux-gnu and i686-linux-gnu.  Also checked with a
check-abi on all affected ABIs.

	* NEWS: Add sysctl.h deprecation entry.
	* include/sys/sysctl.h: Remove file.
	* sysdeps/unix/sysv/linux/bits/sysctl.h: Likewise.
	* sysdeps/unix/sysv/linux/generic/sysctl.c: Likewise.
	* sysdeps/unix/sysv/linux/sys/sysctl.h: Likewise.
	* sysdeps/unix/sysv/linux/x86/bits/sysctl.h: Likewise.
	* manual/sysinfo.texi: Update sysctl documentation.
	* sysdeps/unix/sysv/linux/Makefile (sysdep_headers): Remove
	bits/sysctl.
	* sysdeps/unix/sysv/linux/arm/ioperm.c (sysctl_call): New function.
	(init_iosys): Call syscall_call instead of sysctl.
	* sysdeps/unix/sysv/linux/sysctl.c (__sysctl): Rename to __old_sysctl
	and export only in compatibility mode.

[1] https://lwn.net/Articles/247243/
---
 ChangeLog                                 |  16 ++++
 NEWS                                      |   5 ++
 include/sys/sysctl.h                      |  13 ---
 manual/sysinfo.texi                       | 139 +-----------------------------
 sysdeps/unix/sysv/linux/Makefile          |   4 +-
 sysdeps/unix/sysv/linux/arm/ioperm.c      |  21 ++++-
 sysdeps/unix/sysv/linux/bits/sysctl.h     |   1 -
 sysdeps/unix/sysv/linux/generic/sysctl.c  |  32 -------
 sysdeps/unix/sysv/linux/sys/sysctl.h      |  73 ----------------
 sysdeps/unix/sysv/linux/sysctl.c          |  39 ++++++---
 sysdeps/unix/sysv/linux/x86/bits/sysctl.h |  20 -----
 11 files changed, 72 insertions(+), 291 deletions(-)
 delete mode 100644 include/sys/sysctl.h
 delete mode 100644 sysdeps/unix/sysv/linux/bits/sysctl.h
 delete mode 100644 sysdeps/unix/sysv/linux/generic/sysctl.c
 delete mode 100644 sysdeps/unix/sysv/linux/sys/sysctl.h
 delete mode 100644 sysdeps/unix/sysv/linux/x86/bits/sysctl.h

diff --git a/NEWS b/NEWS
index 92c9b14..ffe3bb4 100644
--- a/NEWS
+++ b/NEWS
@@ -57,6 +57,11 @@ Deprecated and removed features, and other changes affecting compatibility:
    these macros should first include <sys/types.h>, and then include
    <sys/sysmacros.h> if __GNU_LIBRARY__ is defined.
 
+ * The Linux header file <sys/sysctl.h> is no longer installed.  The
+   sysctl syscall has been long deprecated since Linux 2.6.24 in favor
+   of /proc/sys.  A compatibility symbol is still provided, however it is
+   not being defined for static linking or for new ports.
+
 Changes to build and runtime requirements:
 
   [Add changes to build and runtime requirements here]
diff --git a/include/sys/sysctl.h b/include/sys/sysctl.h
deleted file mode 100644
index 2a15e91..0000000
--- a/include/sys/sysctl.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef _SYS_SYSCTL_H
-#include_next <sys/sysctl.h>
-
-# ifndef _ISOMAC
-
-/* Read or write system parameters (Linux, FreeBSD specific).  */
-extern int __sysctl (int *__name, int __nlen, void *__oldval,
-		     size_t *__oldlenp, void *__newval, size_t __newlen);
-libc_hidden_proto (__sysctl)
-
-
-# endif /* !_ISOMAC */
-#endif  /* _SYS_SYSCTL_H */
diff --git a/manual/sysinfo.texi b/manual/sysinfo.texi
index 4beee01..1ebc0b9 100644
--- a/manual/sysinfo.texi
+++ b/manual/sysinfo.texi
@@ -1113,140 +1113,5 @@ when @code{umount2} is also available.
 @node System Parameters
 @section System Parameters
 
-This section describes the @code{sysctl} function, which gets and sets
-a variety of system parameters.
-
-The symbols used in this section are declared in the file @file{sys/sysctl.h}.
-
-@deftypefun int sysctl (int *@var{names}, int @var{nlen}, void *@var{oldval}, size_t *@var{oldlenp}, void *@var{newval}, size_t @var{newlen})
-@standards{BSD, sys/sysctl.h}
-@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
-@c Direct syscall, Linux only.
-
-@code{sysctl} gets or sets a specified system parameter.  There are so
-many of these parameters that it is not practical to list them all here,
-but here are some examples:
-
-@itemize @bullet
-@item network domain name
-@item paging parameters
-@item network Address Resolution Protocol timeout time
-@item maximum number of files that may be open
-@item root filesystem device
-@item when kernel was built
-@end itemize
-
-The set of available parameters depends on the kernel configuration and
-can change while the system is running, particularly when you load and
-unload loadable kernel modules.
-
-The system parameters with which @code{sysctl} is concerned are arranged
-in a hierarchical structure like a hierarchical filesystem.  To identify
-a particular parameter, you specify a path through the structure in a
-way analogous to specifying the pathname of a file.  Each component of
-the path is specified by an integer and each of these integers has a
-macro defined for it by @file{sys/sysctl.h}.  @var{names} is the path, in
-the form of an array of integers.  Each component of the path is one
-element of the array, in order.  @var{nlen} is the number of components
-in the path.
-
-For example, the first component of the path for all the paging
-parameters is the value @code{CTL_VM}.  For the free page thresholds, the
-second component of the path is @code{VM_FREEPG}.  So to get the free
-page threshold values, make @var{names} an array containing the two
-elements @code{CTL_VM} and @code{VM_FREEPG} and make @var{nlen} = 2.
-
-
-The format of the value of a parameter depends on the parameter.
-Sometimes it is an integer; sometimes it is an ASCII string; sometimes
-it is an elaborate structure.  In the case of the free page thresholds
-used in the example above, the parameter value is a structure containing
-several integers.
-
-In any case, you identify a place to return the parameter's value with
-@var{oldval} and specify the amount of storage available at that
-location as *@var{oldlenp}.  *@var{oldlenp} does double duty because it
-is also the output location that contains the actual length of the
-returned value.
-
-If you don't want the parameter value returned, specify a null pointer
-for @var{oldval}.
-
-To set the parameter, specify the address and length of the new value
-as @var{newval} and @var{newlen}.  If you don't want to set the parameter,
-specify a null pointer as @var{newval}.
-
-If you get and set a parameter in the same @code{sysctl} call, the value
-returned is the value of the parameter before it was set.
-
-Each system parameter has a set of permissions similar to the
-permissions for a file (including the permissions on directories in its
-path) that determine whether you may get or set it.  For the purposes of
-these permissions, every parameter is considered to be owned by the
-superuser and Group 0 so processes with that effective uid or gid may
-have more access to system parameters.  Unlike with files, the superuser
-does not invariably have full permission to all system parameters, because
-some of them are designed not to be changed ever.
-
-
-@code{sysctl} returns a zero return value if it succeeds.  Otherwise, it
-returns @code{-1} and sets @code{errno} appropriately.  Besides the
-failures that apply to all system calls, the following are the
-@code{errno} codes for all possible failures:
-
-@table @code
-@item EPERM
-The process is not permitted to access one of the components of the
-path of the system parameter or is not permitted to access the system parameter
-itself in the way (read or write) that it requested.
-@c There is some indication in the Linux 2.2 code that the code is trying to
-@c return EACCES here, but the EACCES value never actually makes it to the
-@c user.
-@item ENOTDIR
-There is no system parameter corresponding to @var{name}.
-@item EFAULT
-@var{oldval} is not null, which means the process wanted to read the parameter,
-but *@var{oldlenp} is zero, so there is no place to return it.
-@item EINVAL
-@itemize @bullet
-@item
-The process attempted to set a system parameter to a value that is not valid
-for that parameter.
-@item
-The space provided for the return of the system parameter is not the right
-size for that parameter.
-@end itemize
-@item ENOMEM
-This value may be returned instead of the more correct @code{EINVAL} in some
-cases where the space provided for the return of the system parameter is too
-small.
-
-@end table
-
-@end deftypefun
-
-If you have a Linux kernel with the @code{proc} filesystem, you can get
-and set most of the same parameters by reading and writing to files in
-the @code{sys} directory of the @code{proc} filesystem.  In the @code{sys}
-directory, the directory structure represents the hierarchical structure
-of the parameters.  E.g. you can display the free page thresholds with
-@smallexample
-cat /proc/sys/vm/freepages
-@end smallexample
-@c In Linux, the sysctl() and /proc instances of the parameter are created
-@c together.  The proc filesystem accesses the same data structure as
-@c sysctl(), which has special fields in it for /proc.  But it is still
-@c possible to create a sysctl-only parameter.
-
-Some more traditional and more widely available, though less general,
-@glibcadj{} functions for getting and setting some of the same system
-parameters are:
-
-@itemize @bullet
-@item
-@code{getdomainname}, @code{setdomainname}
-@item
-@code{gethostname}, @code{sethostname} (@xref{Host Identification}.)
-@item
-@code{uname} (@xref{Platform Type}.)
-@end itemize
+The @code{sysctl} function is deprecated in favor of @code{proc} filesystem
+and @theglibc{} provides only symbol for backward compatibility.
diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
index 8f19e0e..6737900 100644
--- a/sysdeps/unix/sysv/linux/Makefile
+++ b/sysdeps/unix/sysv/linux/Makefile
@@ -28,7 +28,7 @@ CFLAGS-open_by_handle_at.c = -fexceptions -fasynchronous-unwind-tables
 CFLAGS-sync_file_range.c = -fexceptions -fasynchronous-unwind-tables
 CFLAGS-tst-writev.c += "-DARTIFICIAL_LIMIT=(0x80000000-sysconf(_SC_PAGESIZE))"
 
-sysdep_headers += sys/mount.h sys/acct.h sys/sysctl.h \
+sysdep_headers += sys/mount.h sys/acct.h \
 		  sys/klog.h \
 		  sys/user.h sys/prctl.h \
 		  sys/kd.h sys/soundcard.h sys/vt.h \
@@ -38,7 +38,7 @@ sysdep_headers += sys/mount.h sys/acct.h sys/sysctl.h \
 		  bits/a.out.h sys/inotify.h sys/signalfd.h sys/eventfd.h \
 		  sys/timerfd.h sys/fanotify.h bits/eventfd.h bits/inotify.h \
 		  bits/signalfd.h bits/timerfd.h bits/epoll.h \
-		  bits/socket_type.h bits/syscall.h bits/sysctl.h \
+		  bits/socket_type.h bits/syscall.h \
 		  bits/mman-linux.h bits/mman-shared.h bits/ptrace-shared.h \
 		  bits/siginfo-arch.h bits/siginfo-consts-arch.h
 
diff --git a/sysdeps/unix/sysv/linux/arm/ioperm.c b/sysdeps/unix/sysv/linux/arm/ioperm.c
index 4c0bb63..0762475 100644
--- a/sysdeps/unix/sysv/linux/arm/ioperm.c
+++ b/sysdeps/unix/sysv/linux/arm/ioperm.c
@@ -61,14 +61,31 @@ static struct {
  */
 
 static int
+sysctl_call (int *name, int nlen, void *oldval, size_t *oldlenp,
+	     void *newval, size_t newlen)
+{
+  struct kernel_sysctl_args
+  {
+    int *name;
+    int nlen;
+    void *oldval;
+    size_t *oldlenp;
+    void *newval;
+    size_t newlen;
+    unsigned long __unused[4];
+  } args = { name, nlen, oldval, oldlenp, newval, newlen };
+  return INLINE_SYSCALL_CALL (_sysctl, &args);
+}
+
+static int
 init_iosys (void)
 {
   static int iobase_name[] = { CTL_BUS, CTL_BUS_ISA, BUS_ISA_PORT_BASE };
   static int ioshift_name[] = { CTL_BUS, CTL_BUS_ISA, BUS_ISA_PORT_SHIFT };
   size_t len = sizeof(io.base);
 
-  if (! __sysctl (iobase_name, 3, &io.io_base, &len, NULL, 0)
-      && ! __sysctl (ioshift_name, 3, &io.shift, &len, NULL, 0))
+  if (! sysctl_call (iobase_name, 3, &io.io_base, &len, NULL, 0)
+      && ! sysctl_call (ioshift_name, 3, &io.shift, &len, NULL, 0))
     {
       io.initdone = 1;
       return 0;
diff --git a/sysdeps/unix/sysv/linux/bits/sysctl.h b/sysdeps/unix/sysv/linux/bits/sysctl.h
deleted file mode 100644
index 81447b2..0000000
--- a/sysdeps/unix/sysv/linux/bits/sysctl.h
+++ /dev/null
@@ -1 +0,0 @@
-/* Empty file.  */
diff --git a/sysdeps/unix/sysv/linux/generic/sysctl.c b/sysdeps/unix/sysv/linux/generic/sysctl.c
deleted file mode 100644
index 61e7fa8..0000000
--- a/sysdeps/unix/sysv/linux/generic/sysctl.c
+++ /dev/null
@@ -1,32 +0,0 @@
-/* Copyright (C) 2011-2018 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
-
-   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
-   <http://www.gnu.org/licenses/>.  */
-
-#include <errno.h>
-
-#include <sysdep.h>
-#include <sys/syscall.h>
-
-/* This deprecated syscall is no longer used (replaced with /proc/sys).  */
-int
-sysctl (int *name, int nlen, void *oldval, size_t *oldlenp,
-        void *newval, size_t newlen)
-{
-  __set_errno (ENOSYS);
-  return -1;
-}
-stub_warning (sysctl)
diff --git a/sysdeps/unix/sysv/linux/sys/sysctl.h b/sysdeps/unix/sysv/linux/sys/sysctl.h
deleted file mode 100644
index d125a83..0000000
--- a/sysdeps/unix/sysv/linux/sys/sysctl.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/* Copyright (C) 1996-2018 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
-   <http://www.gnu.org/licenses/>.  */
-
-#ifndef	_SYS_SYSCTL_H
-#define	_SYS_SYSCTL_H	1
-
-#include <features.h>
-#define __need_size_t
-#include <stddef.h>
-/* Prevent more kernel headers than necessary to be included.  */
-#ifndef _LINUX_KERNEL_H
-# define _LINUX_KERNEL_H	1
-# define __undef_LINUX_KERNEL_H
-#endif
-#ifndef _LINUX_TYPES_H
-# define _LINUX_TYPES_H		1
-# define __undef_LINUX_TYPES_H
-#endif
-#ifndef _LINUX_LIST_H
-# define _LINUX_LIST_H		1
-# define __undef_LINUX_LIST_H
-#endif
-#ifndef __LINUX_COMPILER_H
-# define __LINUX_COMPILER_H	1
-# define __user
-# define __undef__LINUX_COMPILER_H
-#endif
-
-#include <linux/sysctl.h>
-
-#ifdef __undef_LINUX_KERNEL_H
-# undef _LINUX_KERNEL_H
-# undef __undef_LINUX_KERNEL_H
-#endif
-#ifdef __undef_LINUX_TYPES_H
-# undef _LINUX_TYPES_H
-# undef __undef_LINUX_TYPES_H
-#endif
-#ifdef __undef_LINUX_LIST_H
-# undef _LINUX_LIST_H
-# undef __undef_LINUX_LIST_H
-#endif
-#ifdef __undef__LINUX_COMPILER_H
-# undef __LINUX_COMPILER_H
-# undef __user
-# undef __undef__LINUX_COMPILER_H
-#endif
-
-#include <bits/sysctl.h>
-
-__BEGIN_DECLS
-
-/* Read or write system parameters.  */
-extern int sysctl (int *__name, int __nlen, void *__oldval,
-		   size_t *__oldlenp, void *__newval, size_t __newlen) __THROW;
-
-__END_DECLS
-
-#endif	/* _SYS_SYSCTL_H */
diff --git a/sysdeps/unix/sysv/linux/sysctl.c b/sysdeps/unix/sysv/linux/sysctl.c
index bb5e31a..38a0081 100644
--- a/sysdeps/unix/sysv/linux/sysctl.c
+++ b/sysdeps/unix/sysv/linux/sysctl.c
@@ -16,18 +16,29 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
-#include <errno.h>
-#include <string.h>	/* For the real memset prototype.  */
-#include <sys/sysctl.h>
+#include <shlib-compat.h>
 
-#include <sysdep.h>
-#include <sys/syscall.h>
+/* This deprecated syscall is no longer used (replaced with /proc/sys).  */
+#if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_28)
+
+# include <unistd.h>
+# include <errno.h>
 
 int
-__sysctl (int *name, int nlen, void *oldval, size_t *oldlenp,
-	  void *newval, size_t newlen)
+__old_sysctl (int *name, int nlen, void *oldval, size_t *oldlenp,
+	      void *newval, size_t newlen)
 {
-  struct __sysctl_args args =
+# ifdef __NR__sysctl
+  struct kernel_sysctl_args
+  {
+    int *name;
+    int nlen;
+    void *oldval;
+    size_t *oldlenp;
+    void *newval;
+    size_t newlen;
+    unsigned long __unused[4];
+  } args =
   {
     .name = name,
     .nlen = nlen,
@@ -37,7 +48,13 @@ __sysctl (int *name, int nlen, void *oldval, size_t *oldlenp,
     .newlen = newlen
   };
 
-  return INLINE_SYSCALL (_sysctl, 1, &args);
+  return INLINE_SYSCALL_CALL (_sysctl, &args);
+# else
+  return INLINE_SYSCALL_ERROR_RETURN_VALUE (ENOSYS);
+# endif
 }
-libc_hidden_def (__sysctl)
-weak_alias (__sysctl, sysctl)
+compat_symbol (libc, __old_sysctl, sysctl, GLIBC_2_0);
+# ifdef __NR__sysctl
+strong_alias (__old_sysctl, __sysctl)
+# endif
+#endif
diff --git a/sysdeps/unix/sysv/linux/x86/bits/sysctl.h b/sysdeps/unix/sysv/linux/x86/bits/sysctl.h
deleted file mode 100644
index 8d76ed8..0000000
--- a/sysdeps/unix/sysv/linux/x86/bits/sysctl.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/* Copyright (C) 2012-2018 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
-   <http://www.gnu.org/licenses/>.  */
-
-#if defined __x86_64__ && defined __ILP32__
-# error "sysctl system call is unsupported in x32 kernel"
-#endif
-- 
2.7.4
Joseph Myers April 25, 2018, 2:46 p.m. UTC | #4
On Wed, 25 Apr 2018, Adhemerval Zanella wrote:

> This patch deprecate sysctl interface by issuing ENOSYS as default


That description doesn't make sense, since deprecating is nothing to do 
with ENOSYS errors; the ENOSYS handling in this patch is actually a matter 
of unification with the generic sysctl implementation.  I think you need 
to update the patch description so it accurately describes this version of 
the patch.

-- 
Joseph S. Myers
joseph@codesourcery.com
Adhemerval Zanella April 25, 2018, 5:55 p.m. UTC | #5
On 25/04/2018 11:46, Joseph Myers wrote:
> On Wed, 25 Apr 2018, Adhemerval Zanella wrote:

> 

>> This patch deprecate sysctl interface by issuing ENOSYS as default

> 

> That description doesn't make sense, since deprecating is nothing to do 

> with ENOSYS errors; the ENOSYS handling in this patch is actually a matter 

> of unification with the generic sysctl implementation.  I think you need 

> to update the patch description so it accurately describes this version of 

> the patch.

> 


What about:

---

This patch deprecates sysctl interface by removing the Linux sysctl.h header,
adding a compatibility symbol (with previous semantic including returning
ENOSYS), and avoiding new ports to build and provide the symbol.

---
Adhemerval Zanella April 30, 2018, 11:09 a.m. UTC | #6
On 25/04/2018 14:55, Adhemerval Zanella wrote:
> 

> 

> On 25/04/2018 11:46, Joseph Myers wrote:

>> On Wed, 25 Apr 2018, Adhemerval Zanella wrote:

>>

>>> This patch deprecate sysctl interface by issuing ENOSYS as default

>>

>> That description doesn't make sense, since deprecating is nothing to do 

>> with ENOSYS errors; the ENOSYS handling in this patch is actually a matter 

>> of unification with the generic sysctl implementation.  I think you need 

>> to update the patch description so it accurately describes this version of 

>> the patch.

>>

> 

> What about:

> 

> ---

> 

> This patch deprecates sysctl interface by removing the Linux sysctl.h header,

> adding a compatibility symbol (with previous semantic including returning

> ENOSYS), and avoiding new ports to build and provide the symbol.

> 

> ---

> 


Following Florian's suggestion, I will change to:

* The obsolete function sysctl is no longer available to newly linkerd binaries;
  the header <sys/sysctl.h> has been removed.  This function has been deprecated
  since Linux 2.6.24 in favor of /proc/sys.
Florian Weimer April 30, 2018, 11:19 a.m. UTC | #7
On 04/30/2018 01:09 PM, Adhemerval Zanella wrote:
> * The obsolete function sysctl is no longer available to newly linkerd binaries;

>    the header <sys/sysctl.h> has been removed.  This function has been deprecated

>    since Linux 2.6.24 in favor of /proc/sys.


Typo: “linkerd”.

Thanks,
Florian
Adhemerval Zanella April 30, 2018, 11:25 a.m. UTC | #8
On 30/04/2018 08:19, Florian Weimer wrote:
> On 04/30/2018 01:09 PM, Adhemerval Zanella wrote:

>> * The obsolete function sysctl is no longer available to newly linkerd binaries;

>>    the header <sys/sysctl.h> has been removed.  This function has been deprecated

>>    since Linux 2.6.24 in favor of /proc/sys.

> 

> Typo: “linkerd”.

> 


Yeah, I noted while actually changing my local repo.
Zack Weinberg April 30, 2018, 12:09 p.m. UTC | #9
On Mon, Apr 30, 2018 at 7:09 AM, Adhemerval Zanella
<adhemerval.zanella@linaro.org> wrote:
>

> * The obsolete function sysctl is no longer available to newly linkerd binaries;

>   the header <sys/sysctl.h> has been removed.  This function has been deprecated

>   since Linux 2.6.24 in favor of /proc/sys.


I've been thinking about this since you posted the original patch, and
I don't think this is the right treatment of this specific function.
sysctl still exists and is the preferred interface on the BSDs and I
think also Solaris.  Linux may not support it at the kernel level but
we should leave open the possibility of a future user-space shim, or
of the kernel people changing their minds (frankly, I have never found
the argument for /proc/sys instead of sysctl at all convincing).  That
means:

 - Do still install a generic <sys/sysctl.h> that prototypes sysctl()
and includes bits/sysctl.h but does nothing else.
 - Do still install a generic <bits/sysctl.h> that declares nothing.
 - Drop sysdeps/u/s/l/sysctl.c as in this patch, but move
sysdeps/u/s/l/generic/sysctl.c to misc/, and *don't* make it a compat
symbol.

zw
Adhemerval Zanella April 30, 2018, 12:35 p.m. UTC | #10
On 30/04/2018 09:09, Zack Weinberg wrote:
> On Mon, Apr 30, 2018 at 7:09 AM, Adhemerval Zanella

> <adhemerval.zanella@linaro.org> wrote:

>>

>> * The obsolete function sysctl is no longer available to newly linkerd binaries;

>>   the header <sys/sysctl.h> has been removed.  This function has been deprecated

>>   since Linux 2.6.24 in favor of /proc/sys.

> 

> I've been thinking about this since you posted the original patch, and

> I don't think this is the right treatment of this specific function.

> sysctl still exists and is the preferred interface on the BSDs and I

> think also Solaris.  Linux may not support it at the kernel level but

> we should leave open the possibility of a future user-space shim, or

> of the kernel people changing their minds (frankly, I have never found

> the argument for /proc/sys instead of sysctl at all convincing).  That

> means:


I find it highly unlikely:

  * the deprecation occurred 10 years ago.

  * the kernel kernel/sysctl_binary.c was changed to be a compatibility wrapper 
    around /proc/sys (26a7034b40), the changes were only to *remove* deprecated
    fields and no new fields were added since then, meaning sysctl just
    provides a subset of /proc/sys (with unknown exceptions of 
    NET_IPV6_ACCEPT_RA_FROM_LOCAL (d93331965) and KERN_PANIC_ON_WARN (9e3961a097).

  * new ports do not provide the syscall (aarch64, nios2, riscv64, x86_64-x32)
    so portable programs should not rely on it.

  * although linux and bsd do share some object names, most are Linux specific
    and some vary between kernel versions and not all are properly documented.

  * sysctl for procps already uses /proc/sys.

> 

>  - Do still install a generic <sys/sysctl.h> that prototypes sysctl()

> and includes bits/sysctl.h but does nothing else.

>  - Do still install a generic <bits/sysctl.h> that declares nothing.

>  - Drop sysdeps/u/s/l/sysctl.c as in this patch, but move

> sysdeps/u/s/l/generic/sysctl.c to misc/, and *don't* make it a compat

> symbol.


I see no gain in continuing provide this symbol for the aforementioned reasons.
As mentioned in comment, the only real world usage I could is fail-proof way to
gather some entropy in cases where /dev/urandom or /proc is not available.
However even then Linux have moved to a more proper syscall (getentropy).
Zack Weinberg April 30, 2018, 8:33 p.m. UTC | #11
(I didn't intend for any of this thread to be in private.  Sorry about
that.  I'm not trimming any quotes to provide libc-alpha with as much
context as possible.)

On Mon, Apr 30, 2018 at 4:25 PM, Adhemerval Zanella
<adhemerval.zanella@linaro.org> wrote:
> On 30/04/2018 17:10, Zack Weinberg wrote:

>> On Mon, Apr 30, 2018 at 3:23 PM, Adhemerval Zanella

>> <adhemerval.zanella@linaro.org> wrote:Why?

>>> The idea you are proposing was the original patch I sent, however I tend

>>> to agree more with Joseph where symbol deprecation should not add newer

>>> symbols (which would require for ports that do not return -1/ENOSYS).

>>

>> Why would it require that?  I don't see any reason not to use the

>> "always return -1/ENOSYS" symbol for everything.  Where the system

>> call exists, it already unconditionally fails, doesn't it?  So there's

>> no observable behavior change.

>

> Current Linux still provides the syscall on some architecture. This is an

> output of an script I have that check if the __NR_<syscall> can be build

> against a toolchain (this one configured against a 3.2 kernel one or the

> minimum one for the architectures, 3.7 for aarch64 for instance):

>

> SYSCALL: _sysctl

>                aarch64: FAIL

>                  alpha: OK

>                    arm: OK

>                   hppa: OK

>                   i686: OK

>                   ia64: OK

>                   m68k: OK

>             microblaze: OK

>                   mips: OK

>                 mips64: OK

>             mips64-n32: OK

>                  nios2: FAIL

>                powerpc: OK

>              powerpc64: OK

>             powerpcspe: OK

>                riscv64: FAIL

>                   s390: OK

>                  s390x: OK

>                    sh4: OK

>                sparc64: OK

>                sparcv9: OK

>                 tilegx: FAIL

>                 x86_64: OK

>             x86_64-x32: FAIL

>

> For the architectures that still provides it, the kernel deprecation is still

> only printing a kernel warning the symbols is deprecated and it might be removed

> in the future.  So we still need to provide a compat symbol with old semantic

> and if the idea is to now return -1/ENOSYS add a new symbol on 2.28.


IMHO this means we should not deprecate sysctl in our code until the
kernel does remove it entirely.

>> (If there are architectures where the system call _doesn't_ already

>> unconditionally fail, then I think we should leave sysctl alone for as

>> long as that remains true.)

>

> This patch is exactly to not provide access though glibc for this syscall.

> User still can access it though syscall().


I do not think we should remove access through glibc to any syscall
that does something useful on at least one architecture that glibc
supports.

(I also think we should _add_ access through glibc to all of the
syscalls that we currently don't.)

>>> Also, AC_CHECK_FUNC will still correctly fail for sysctl check since

>>> linkage will fail with undefined symbol (just double checked on a chroot

>>> environment), which the advantage imho this will be explicit for builds

>>> that do not use autoconf.

>>

>> This is an argument for scrapping the stubs mechanism altogether, but

>> as long as we have it, it should be used consistently.

>

>>> Also, your suggestion:

>>>

>>>>  - Drop sysdeps/u/s/l/sysctl.c as in this patch, but move

>>>> sysdeps/u/s/l/generic/sysctl.c to misc/, and *don't* make it a compat

>>>> symbol.

>>>

>>> Will incur in a new symbol for non Linux targets, which I think it is not

>>> the desirable action.

>>

>> A major part of my point here is that I think it _would be_

>> appropriate to make sysctl() part of the generic glibc API surface,

>> despite Linux refusing to support it.  There are more non-Linux

>> operating systems that support it (e.g. all of the BSDs) than don't

>> (e.g. Hurd).

>>

>> Again, if we scrapped the stubs mechanism (so system primitives that

>> aren't available on some targets wouldn't be defined at all) then my

>> opinion would change.

>

> We can follow up this on libc-alpha, but since it has been deprecated over

> 10 years on Linux and there is no upcoming port for non Linux target besides

> Hurd I really think there is little to no gain to continue support a really

> problematic ABI (at least from Linux side).
Adhemerval Zanella May 3, 2018, 2:15 p.m. UTC | #12
On 30/04/2018 17:33, Zack Weinberg wrote:
> (I didn't intend for any of this thread to be in private.  Sorry about

> that.  I'm not trimming any quotes to provide libc-alpha with as much

> context as possible.)

> 

> On Mon, Apr 30, 2018 at 4:25 PM, Adhemerval Zanella

> <adhemerval.zanella@linaro.org> wrote:

>> On 30/04/2018 17:10, Zack Weinberg wrote:

>>> On Mon, Apr 30, 2018 at 3:23 PM, Adhemerval Zanella

>>> <adhemerval.zanella@linaro.org> wrote:Why?

>>>> The idea you are proposing was the original patch I sent, however I tend

>>>> to agree more with Joseph where symbol deprecation should not add newer

>>>> symbols (which would require for ports that do not return -1/ENOSYS).

>>>

>>> Why would it require that?  I don't see any reason not to use the

>>> "always return -1/ENOSYS" symbol for everything.  Where the system

>>> call exists, it already unconditionally fails, doesn't it?  So there's

>>> no observable behavior change.

>>

>> Current Linux still provides the syscall on some architecture. This is an

>> output of an script I have that check if the __NR_<syscall> can be build

>> against a toolchain (this one configured against a 3.2 kernel one or the

>> minimum one for the architectures, 3.7 for aarch64 for instance):

>>

>> SYSCALL: _sysctl

>>                aarch64: FAIL

>>                  alpha: OK

>>                    arm: OK

>>                   hppa: OK

>>                   i686: OK

>>                   ia64: OK

>>                   m68k: OK

>>             microblaze: OK

>>                   mips: OK

>>                 mips64: OK

>>             mips64-n32: OK

>>                  nios2: FAIL

>>                powerpc: OK

>>              powerpc64: OK

>>             powerpcspe: OK

>>                riscv64: FAIL

>>                   s390: OK

>>                  s390x: OK

>>                    sh4: OK

>>                sparc64: OK

>>                sparcv9: OK

>>                 tilegx: FAIL

>>                 x86_64: OK

>>             x86_64-x32: FAIL

>>

>> For the architectures that still provides it, the kernel deprecation is still

>> only printing a kernel warning the symbols is deprecated and it might be removed

>> in the future.  So we still need to provide a compat symbol with old semantic

>> and if the idea is to now return -1/ENOSYS add a new symbol on 2.28.

> 

> IMHO this means we should not deprecate sysctl in our code until the

> kernel does remove it entirely.


My view for deprecate sysctl on glibc is summarized as:

  * the deprecation in kernel occurred 10 years ago.

  * the kernel kernel/sysctl_binary.c was changed to be a compatibility wrapper 
    around /proc/sys (26a7034b40), the changes were only to *remove* deprecated
    fields and no new fields were added since then, meaning sysctl just
    provides a subset of /proc/sys (with unknown exceptions of 
    NET_IPV6_ACCEPT_RA_FROM_LOCAL (d93331965) and KERN_PANIC_ON_WARN (9e3961a097).

  * new ports do not provide the syscall (aarch64, nios2, riscv64, x86_64-x32)
    so portable programs should not rely on it.

  * although linux and bsd do share some object names, most are Linux specific
    and some vary between kernel versions and not all are properly documented.

  * sysctl for procps already uses /proc/sys.

  * this syscall is still available for architecture that support it thought
    syscall(...) (sysctl(2) manual shows the expected abi).

So I would like to hear if we should either continue to provide sysctl glibc
implementation (which differ slight than kernel signature) or if we should
deprecate.  If deprecation is the prefered way we can either by removing the
symbol for new ports while adding a compat symbol or by adding a link warning
stating it deprecated and should be removed in future releases.
diff mbox series

Patch

diff --git a/sysdeps/unix/sysv/linux/alpha/Versions b/sysdeps/unix/sysv/linux/alpha/Versions
index 3b7971c..da8b0c1 100644
--- a/sysdeps/unix/sysv/linux/alpha/Versions
+++ b/sysdeps/unix/sysv/linux/alpha/Versions
@@ -88,6 +88,9 @@  libc {
   GLIBC_2.27 {
     getrlimit; setrlimit; getrlimit64; setrlimit64;
   }
+  GLIBC_2.28 {
+    sysctl;
+  }
   GLIBC_PRIVATE {
     __libc_alpha_cache_shape;
   }
diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist
index 8674a87..09fc772 100644
--- a/sysdeps/unix/sysv/linux/alpha/libc.abilist
+++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist
@@ -2054,6 +2054,8 @@  GLIBC_2.27 wcstof64 F
 GLIBC_2.27 wcstof64_l F
 GLIBC_2.27 wcstof64x F
 GLIBC_2.27 wcstof64x_l F
+GLIBC_2.28 GLIBC_2.28 A
+GLIBC_2.28 sysctl F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/arm/Versions b/sysdeps/unix/sysv/linux/arm/Versions
index 7e5ba53..de5c1e9 100644
--- a/sysdeps/unix/sysv/linux/arm/Versions
+++ b/sysdeps/unix/sysv/linux/arm/Versions
@@ -10,6 +10,9 @@  libc {
   GLIBC_2.24 {
     recvmsg; sendmsg;
   }
+  GLIBC_2.28 {
+    sysctl;
+  }
   GLIBC_PRIVATE {
     # A copy of sigaction lives in libpthread, and needs these.
     __default_sa_restorer; __default_rt_sa_restorer;
diff --git a/sysdeps/unix/sysv/linux/arm/ioperm.c b/sysdeps/unix/sysv/linux/arm/ioperm.c
index 4c0bb63..0762475 100644
--- a/sysdeps/unix/sysv/linux/arm/ioperm.c
+++ b/sysdeps/unix/sysv/linux/arm/ioperm.c
@@ -61,14 +61,31 @@  static struct {
  */
 
 static int
+sysctl_call (int *name, int nlen, void *oldval, size_t *oldlenp,
+	     void *newval, size_t newlen)
+{
+  struct kernel_sysctl_args
+  {
+    int *name;
+    int nlen;
+    void *oldval;
+    size_t *oldlenp;
+    void *newval;
+    size_t newlen;
+    unsigned long __unused[4];
+  } args = { name, nlen, oldval, oldlenp, newval, newlen };
+  return INLINE_SYSCALL_CALL (_sysctl, &args);
+}
+
+static int
 init_iosys (void)
 {
   static int iobase_name[] = { CTL_BUS, CTL_BUS_ISA, BUS_ISA_PORT_BASE };
   static int ioshift_name[] = { CTL_BUS, CTL_BUS_ISA, BUS_ISA_PORT_SHIFT };
   size_t len = sizeof(io.base);
 
-  if (! __sysctl (iobase_name, 3, &io.io_base, &len, NULL, 0)
-      && ! __sysctl (ioshift_name, 3, &io.shift, &len, NULL, 0))
+  if (! sysctl_call (iobase_name, 3, &io.io_base, &len, NULL, 0)
+      && ! sysctl_call (ioshift_name, 3, &io.shift, &len, NULL, 0))
     {
       io.initdone = 1;
       return 0;
diff --git a/sysdeps/unix/sysv/linux/arm/libc.abilist b/sysdeps/unix/sysv/linux/arm/libc.abilist
index 044ec10..35741a8 100644
--- a/sysdeps/unix/sysv/linux/arm/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arm/libc.abilist
@@ -130,6 +130,8 @@  GLIBC_2.27 wcstof32x F
 GLIBC_2.27 wcstof32x_l F
 GLIBC_2.27 wcstof64 F
 GLIBC_2.27 wcstof64_l F
+GLIBC_2.28 GLIBC_2.28 A
+GLIBC_2.28 sysctl F
 GLIBC_2.4 GLIBC_2.4 A
 GLIBC_2.4 _Exit F
 GLIBC_2.4 _IO_2_1_stderr_ D 0xa0
diff --git a/sysdeps/unix/sysv/linux/generic/sysctl.c b/sysdeps/unix/sysv/linux/generic/sysctl.c
deleted file mode 100644
index 61e7fa8..0000000
--- a/sysdeps/unix/sysv/linux/generic/sysctl.c
+++ /dev/null
@@ -1,32 +0,0 @@ 
-/* Copyright (C) 2011-2018 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
-
-   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
-   <http://www.gnu.org/licenses/>.  */
-
-#include <errno.h>
-
-#include <sysdep.h>
-#include <sys/syscall.h>
-
-/* This deprecated syscall is no longer used (replaced with /proc/sys).  */
-int
-sysctl (int *name, int nlen, void *oldval, size_t *oldlenp,
-        void *newval, size_t newlen)
-{
-  __set_errno (ENOSYS);
-  return -1;
-}
-stub_warning (sysctl)
diff --git a/sysdeps/unix/sysv/linux/hppa/Versions b/sysdeps/unix/sysv/linux/hppa/Versions
index b5098b2..4cbc3cd 100644
--- a/sysdeps/unix/sysv/linux/hppa/Versions
+++ b/sysdeps/unix/sysv/linux/hppa/Versions
@@ -35,4 +35,7 @@  libc {
   GLIBC_2.19 {
     fanotify_mark;
   }
+  GLIBC_2.28 {
+    sysctl;
+  }
 }
diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist
index 2360130..1da5f49 100644
--- a/sysdeps/unix/sysv/linux/hppa/libc.abilist
+++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist
@@ -1894,6 +1894,8 @@  GLIBC_2.27 wcstof32x F
 GLIBC_2.27 wcstof32x_l F
 GLIBC_2.27 wcstof64 F
 GLIBC_2.27 wcstof64_l F
+GLIBC_2.28 GLIBC_2.28 A
+GLIBC_2.28 sysctl F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/i386/Versions b/sysdeps/unix/sysv/linux/i386/Versions
index b59ace4..b8679e1 100644
--- a/sysdeps/unix/sysv/linux/i386/Versions
+++ b/sysdeps/unix/sysv/linux/i386/Versions
@@ -45,6 +45,9 @@  libc {
     # f*
     fallocate64;
   }
+  GLIBC_2.28 {
+    sysctl;
+  }
   GLIBC_PRIVATE {
     __modify_ldt; __uname;
   }
diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist
index 39c993f..2a1c99c 100644
--- a/sysdeps/unix/sysv/linux/i386/libc.abilist
+++ b/sysdeps/unix/sysv/linux/i386/libc.abilist
@@ -2064,6 +2064,8 @@  GLIBC_2.27 wcstof64 F
 GLIBC_2.27 wcstof64_l F
 GLIBC_2.27 wcstof64x F
 GLIBC_2.27 wcstof64x_l F
+GLIBC_2.28 GLIBC_2.28 A
+GLIBC_2.28 sysctl F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/ia64/Versions b/sysdeps/unix/sysv/linux/ia64/Versions
index 116f4e8..3da728c 100644
--- a/sysdeps/unix/sysv/linux/ia64/Versions
+++ b/sysdeps/unix/sysv/linux/ia64/Versions
@@ -25,6 +25,9 @@  libc {
   GLIBC_2.24 {
     recvmsg; sendmsg;
   }
+  GLIBC_2.28 {
+    sysctl;
+  }
 }
 libpthread {
   GLIBC_2.3.3 {
diff --git a/sysdeps/unix/sysv/linux/ia64/libc.abilist b/sysdeps/unix/sysv/linux/ia64/libc.abilist
index 68496aa..8b51692 100644
--- a/sysdeps/unix/sysv/linux/ia64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/ia64/libc.abilist
@@ -1928,6 +1928,8 @@  GLIBC_2.27 wcstof64 F
 GLIBC_2.27 wcstof64_l F
 GLIBC_2.27 wcstof64x F
 GLIBC_2.27 wcstof64x_l F
+GLIBC_2.28 GLIBC_2.28 A
+GLIBC_2.28 sysctl F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/m68k/Versions b/sysdeps/unix/sysv/linux/m68k/Versions
index 7ecc96e..93be63d 100644
--- a/sysdeps/unix/sysv/linux/m68k/Versions
+++ b/sysdeps/unix/sysv/linux/m68k/Versions
@@ -40,6 +40,9 @@  libc {
   GLIBC_2.12 {
     __m68k_read_tp;
   }
+  GLIBC_2.28 {
+    sysctl;
+  }
   GLIBC_PRIVATE {
     __vdso_atomic_cmpxchg_32; __vdso_atomic_barrier;
   }
diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
index b676025..d26f322 100644
--- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
@@ -131,6 +131,8 @@  GLIBC_2.27 wcstof32x F
 GLIBC_2.27 wcstof32x_l F
 GLIBC_2.27 wcstof64 F
 GLIBC_2.27 wcstof64_l F
+GLIBC_2.28 GLIBC_2.28 A
+GLIBC_2.28 sysctl F
 GLIBC_2.4 GLIBC_2.4 A
 GLIBC_2.4 _Exit F
 GLIBC_2.4 _IO_2_1_stderr_ D 0x98
diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
index cdd1df5..04dcf51 100644
--- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
@@ -2008,6 +2008,8 @@  GLIBC_2.27 wcstof32x F
 GLIBC_2.27 wcstof32x_l F
 GLIBC_2.27 wcstof64 F
 GLIBC_2.27 wcstof64_l F
+GLIBC_2.28 GLIBC_2.28 A
+GLIBC_2.28 sysctl F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/microblaze/Versions b/sysdeps/unix/sysv/linux/microblaze/Versions
index aa48a3c..d1ee89c 100644
--- a/sysdeps/unix/sysv/linux/microblaze/Versions
+++ b/sysdeps/unix/sysv/linux/microblaze/Versions
@@ -2,4 +2,7 @@  libc {
   GLIBC_2.18 {
     fallocate64;
   }
+  GLIBC_2.28 {
+    sysctl;
+  }
 }
diff --git a/sysdeps/unix/sysv/linux/microblaze/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
index e4265fd..dd4656c 100644
--- a/sysdeps/unix/sysv/linux/microblaze/libc.abilist
+++ b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
@@ -2129,3 +2129,5 @@  GLIBC_2.27 wcstof32x F
 GLIBC_2.27 wcstof32x_l F
 GLIBC_2.27 wcstof64 F
 GLIBC_2.27 wcstof64_l F
+GLIBC_2.28 GLIBC_2.28 A
+GLIBC_2.28 sysctl F
diff --git a/sysdeps/unix/sysv/linux/mips/Versions b/sysdeps/unix/sysv/linux/mips/Versions
index 453f276..ac26de3 100644
--- a/sysdeps/unix/sysv/linux/mips/Versions
+++ b/sysdeps/unix/sysv/linux/mips/Versions
@@ -37,6 +37,9 @@  libc {
   GLIBC_2.11 {
     fallocate64;
   }
+  GLIBC_2.28 {
+    sysctl;
+  }
   GLIBC_PRIVATE {
     # nptl/pthread_cond_timedwait.c uses INTERNAL_VSYSCALL(clock_gettime).
     __vdso_clock_gettime;
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
index 3a7e0b4..8283a0a 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
@@ -1983,6 +1983,8 @@  GLIBC_2.27 wcstof32x F
 GLIBC_2.27 wcstof32x_l F
 GLIBC_2.27 wcstof64 F
 GLIBC_2.27 wcstof64_l F
+GLIBC_2.28 GLIBC_2.28 A
+GLIBC_2.28 sysctl F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
index 5e80592..081fc77 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
@@ -1981,6 +1981,8 @@  GLIBC_2.27 wcstof32x F
 GLIBC_2.27 wcstof32x_l F
 GLIBC_2.27 wcstof64 F
 GLIBC_2.27 wcstof64_l F
+GLIBC_2.28 GLIBC_2.28 A
+GLIBC_2.28 sysctl F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
index 1973fac..f6b7502 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
@@ -1989,6 +1989,8 @@  GLIBC_2.27 wcstof64 F
 GLIBC_2.27 wcstof64_l F
 GLIBC_2.27 wcstof64x F
 GLIBC_2.27 wcstof64x_l F
+GLIBC_2.28 GLIBC_2.28 A
+GLIBC_2.28 sysctl F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
index 5e18ab8..abfd0e0 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
@@ -1984,6 +1984,8 @@  GLIBC_2.27 wcstof64 F
 GLIBC_2.27 wcstof64_l F
 GLIBC_2.27 wcstof64x F
 GLIBC_2.27 wcstof64x_l F
+GLIBC_2.28 GLIBC_2.28 A
+GLIBC_2.28 sysctl F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/powerpc/Versions b/sysdeps/unix/sysv/linux/powerpc/Versions
index 8ebeea1..228f8f1 100644
--- a/sysdeps/unix/sysv/linux/powerpc/Versions
+++ b/sysdeps/unix/sysv/linux/powerpc/Versions
@@ -5,6 +5,9 @@  ld {
   }
 }
 libc {
+  GLIBC_2.28 {
+    sysctl;
+  }
   GLIBC_PRIVATE {
     __vdso_get_tbfreq;
     __vdso_clock_gettime;
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
index 676aa50..836fdab 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
@@ -2012,6 +2012,8 @@  GLIBC_2.27 wcstof32x F
 GLIBC_2.27 wcstof32x_l F
 GLIBC_2.27 wcstof64 F
 GLIBC_2.27 wcstof64_l F
+GLIBC_2.28 GLIBC_2.28 A
+GLIBC_2.28 sysctl F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
index 2016c7c..e68ef0e 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
@@ -2017,6 +2017,8 @@  GLIBC_2.27 wcstof32x F
 GLIBC_2.27 wcstof32x_l F
 GLIBC_2.27 wcstof64 F
 GLIBC_2.27 wcstof64_l F
+GLIBC_2.28 GLIBC_2.28 A
+GLIBC_2.28 sysctl F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
index 3d19e38..e15404f 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
@@ -2229,3 +2229,5 @@  GLIBC_2.27 wcstof64 F
 GLIBC_2.27 wcstof64_l F
 GLIBC_2.27 wcstof64x F
 GLIBC_2.27 wcstof64x_l F
+GLIBC_2.28 GLIBC_2.28 A
+GLIBC_2.28 sysctl F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
index c57ab21..5983ac1 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
@@ -131,6 +131,8 @@  GLIBC_2.27 wcstof32x F
 GLIBC_2.27 wcstof32x_l F
 GLIBC_2.27 wcstof64 F
 GLIBC_2.27 wcstof64_l F
+GLIBC_2.28 GLIBC_2.28 A
+GLIBC_2.28 sysctl F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 _Exit F
 GLIBC_2.3 _IO_2_1_stderr_ D 0xe0
diff --git a/sysdeps/unix/sysv/linux/s390/Versions b/sysdeps/unix/sysv/linux/s390/Versions
index 55518a7..640579d 100644
--- a/sysdeps/unix/sysv/linux/s390/Versions
+++ b/sysdeps/unix/sysv/linux/s390/Versions
@@ -3,6 +3,9 @@  libc {
     __longjmp_chk;
     getcontext;
   }
+  GLIBC_2.28 {
+    sysctl;
+  }
   GLIBC_PRIVATE {
     __vdso_clock_gettime;
     __vdso_clock_getres;
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
index 2590372..fad7b94 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
@@ -2022,6 +2022,8 @@  GLIBC_2.27 wcstof64 F
 GLIBC_2.27 wcstof64_l F
 GLIBC_2.27 wcstof64x F
 GLIBC_2.27 wcstof64x_l F
+GLIBC_2.28 GLIBC_2.28 A
+GLIBC_2.28 sysctl F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
index 5d6800c..8e88894 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
@@ -1923,6 +1923,8 @@  GLIBC_2.27 wcstof64 F
 GLIBC_2.27 wcstof64_l F
 GLIBC_2.27 wcstof64x F
 GLIBC_2.27 wcstof64x_l F
+GLIBC_2.28 GLIBC_2.28 A
+GLIBC_2.28 sysctl F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/sh/Versions b/sysdeps/unix/sysv/linux/sh/Versions
index e0938c4..c0bc2da 100644
--- a/sysdeps/unix/sysv/linux/sh/Versions
+++ b/sysdeps/unix/sysv/linux/sh/Versions
@@ -30,4 +30,7 @@  libc {
   GLIBC_2.16 {
     fanotify_mark;
   }
+  GLIBC_2.28 {
+    sysctl;
+  }
 }
diff --git a/sysdeps/unix/sysv/linux/sh/libc.abilist b/sysdeps/unix/sysv/linux/sh/libc.abilist
index c04872c..4b8f56f 100644
--- a/sysdeps/unix/sysv/linux/sh/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sh/libc.abilist
@@ -1898,6 +1898,8 @@  GLIBC_2.27 wcstof32x F
 GLIBC_2.27 wcstof32x_l F
 GLIBC_2.27 wcstof64 F
 GLIBC_2.27 wcstof64_l F
+GLIBC_2.28 GLIBC_2.28 A
+GLIBC_2.28 sysctl F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/sparc/Versions b/sysdeps/unix/sysv/linux/sparc/Versions
index 4dc1cd7..49c18b1 100644
--- a/sysdeps/unix/sysv/linux/sparc/Versions
+++ b/sysdeps/unix/sysv/linux/sparc/Versions
@@ -29,6 +29,9 @@  libc {
 
     __getshmlba;
   }
+  GLIBC_2.28 {
+    sysctl;
+  }
 }
 
 libpthread {
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
index 85cbe30..5bb6028 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
@@ -2015,6 +2015,8 @@  GLIBC_2.27 wcstof64 F
 GLIBC_2.27 wcstof64_l F
 GLIBC_2.27 wcstof64x F
 GLIBC_2.27 wcstof64x_l F
+GLIBC_2.28 GLIBC_2.28 A
+GLIBC_2.28 sysctl F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
index f7a1ab8..1ea1a9e 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
@@ -1952,6 +1952,8 @@  GLIBC_2.27 wcstof64 F
 GLIBC_2.27 wcstof64_l F
 GLIBC_2.27 wcstof64x F
 GLIBC_2.27 wcstof64x_l F
+GLIBC_2.28 GLIBC_2.28 A
+GLIBC_2.28 sysctl F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/sysctl.c b/sysdeps/unix/sysv/linux/sysctl.c
index bb5e31a..c73290b 100644
--- a/sysdeps/unix/sysv/linux/sysctl.c
+++ b/sysdeps/unix/sysv/linux/sysctl.c
@@ -16,18 +16,37 @@ 
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
+#include <unistd.h>
 #include <errno.h>
-#include <string.h>	/* For the real memset prototype.  */
-#include <sys/sysctl.h>
-
-#include <sysdep.h>
-#include <sys/syscall.h>
+#include <shlib-compat.h>
 
+/* This deprecated syscall is no longer used (replaced with /proc/sys).  */
 int
-__sysctl (int *name, int nlen, void *oldval, size_t *oldlenp,
-	  void *newval, size_t newlen)
+__deprecated_sysctl (int *name, int nlen, void *oldval, size_t *oldlenp,
+		     void *newval, size_t newlen)
 {
-  struct __sysctl_args args =
+  __set_errno (ENOSYS);
+  return -1;
+}
+#ifndef __NR__sysctl
+weak_alias (__deprecated_sysctl, sysctl)
+#else
+versioned_symbol (libc, __deprecated_sysctl, sysctl, GLIBC_2_28);
+# if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_28)
+int
+__old_sysctl (int *name, int nlen, void *oldval, size_t *oldlenp,
+	      void *newval, size_t newlen)
+{
+  struct kernel_sysctl_args
+  {
+    int *name;
+    int nlen;
+    void *oldval;
+    size_t *oldlenp;
+    void *newval;
+    size_t newlen;
+    unsigned long __unused[4];
+  } args =
   {
     .name = name,
     .nlen = nlen,
@@ -37,7 +56,10 @@  __sysctl (int *name, int nlen, void *oldval, size_t *oldlenp,
     .newlen = newlen
   };
 
-  return INLINE_SYSCALL (_sysctl, 1, &args);
+  return INLINE_SYSCALL_CALL (_sysctl, &args);
 }
-libc_hidden_def (__sysctl)
-weak_alias (__sysctl, sysctl)
+compat_symbol (libc, __old_sysctl, sysctl, GLIBC_2_0);
+strong_alias (__old_sysctl, __sysctl)
+# endif
+#endif
+stub_warning (sysctl)
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
index 2a3cc40..576d3bd 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
@@ -1905,6 +1905,8 @@  GLIBC_2.27 wcstof64 F
 GLIBC_2.27 wcstof64_l F
 GLIBC_2.27 wcstof64x F
 GLIBC_2.27 wcstof64x_l F
+GLIBC_2.28 GLIBC_2.28 A
+GLIBC_2.28 sysctl F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/x86_64/Versions b/sysdeps/unix/sysv/linux/x86_64/Versions
index 2a7ed28..f76a5ff 100644
--- a/sysdeps/unix/sysv/linux/x86_64/Versions
+++ b/sysdeps/unix/sysv/linux/x86_64/Versions
@@ -6,6 +6,9 @@  libc {
 
     modify_ldt;
   }
+  GLIBC_2.28 {
+    sysctl;
+  }
 }
 
 librt {
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
index 8bc16b9..31d612f 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
@@ -2148,3 +2148,4 @@  GLIBC_2.27 wcstof64 F
 GLIBC_2.27 wcstof64_l F
 GLIBC_2.27 wcstof64x F
 GLIBC_2.27 wcstof64x_l F
+GLIBC_2.28 GLIBC_2.28 A