76b6d9
This change is equivalent to this upstream change:
76b6d9
76b6d9
commit 22a46dee24351fd5f4f188ad80554cad79c82524
76b6d9
Author: Florian Weimer <fweimer@redhat.com>
76b6d9
Date:   Tue Nov 8 14:15:02 2022 +0100
76b6d9
76b6d9
    Linux: Support __IPC_64 in sysvctl *ctl command arguments (bug 29771)
76b6d9
76b6d9
    Old applications pass __IPC_64 as part of the command argument because
76b6d9
    old glibc did not check for unknown commands, and passed through the
76b6d9
    arguments directly to the kernel, without adding __IPC_64.
76b6d9
    Applications need to continue doing that for old glibc compatibility,
76b6d9
    so this commit enables this approach in current glibc.
76b6d9
76b6d9
    For msgctl and shmctl, if no translation is required, make
76b6d9
    direct system calls, as we did before the time64 changes.  If
76b6d9
    translation is required, mask __IPC_64 from the command argument.
76b6d9
76b6d9
    For semctl, the union-in-vararg argument handling means that
76b6d9
    translation is needed on all architectures.
76b6d9
76b6d9
    Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
76b6d9
76b6d9
The downstream versions of shmctl and msgctl did not produce
76b6d9
errors because they lacked a -1 error return path.  There is no
76b6d9
translation requirement downstream on any architecture, so we
76b6d9
can remove the switch from shmctl and msgctl.
76b6d9
76b6d9
For semctl, we have to do the varargs translation, so this patch adds
76b6d9
the same masking as the upstream commit.
76b6d9
76b6d9
diff --git a/sysdeps/unix/sysv/linux/msgctl.c b/sysdeps/unix/sysv/linux/msgctl.c
76b6d9
index 3362f4562f58f28b..7280cba31a8815a2 100644
76b6d9
--- a/sysdeps/unix/sysv/linux/msgctl.c
76b6d9
+++ b/sysdeps/unix/sysv/linux/msgctl.c
76b6d9
@@ -29,20 +29,6 @@
76b6d9
 int
76b6d9
 __new_msgctl (int msqid, int cmd, struct msqid_ds *buf)
76b6d9
 {
76b6d9
-  switch (cmd)
76b6d9
-    {
76b6d9
-    case IPC_RMID:
76b6d9
-    case IPC_SET:
76b6d9
-    case IPC_STAT:
76b6d9
-    case MSG_STAT:
76b6d9
-    case MSG_STAT_ANY:
76b6d9
-    case IPC_INFO:
76b6d9
-    case MSG_INFO:
76b6d9
-      break;
76b6d9
-    default:
76b6d9
-      __set_errno (EINVAL);
76b6d9
-      return -1;
76b6d9
-    }
76b6d9
 #ifdef __ASSUME_DIRECT_SYSVIPC_SYSCALLS
76b6d9
   return INLINE_SYSCALL_CALL (msgctl, msqid, cmd | __IPC_64, buf);
76b6d9
 #else
76b6d9
diff --git a/sysdeps/unix/sysv/linux/semctl.c b/sysdeps/unix/sysv/linux/semctl.c
76b6d9
index 03c56c69a5412c82..16d3f04fadd039ab 100644
76b6d9
--- a/sysdeps/unix/sysv/linux/semctl.c
76b6d9
+++ b/sysdeps/unix/sysv/linux/semctl.c
76b6d9
@@ -42,6 +42,13 @@ __new_semctl (int semid, int semnum, int cmd, ...)
76b6d9
   union semun arg = { 0 };
76b6d9
   va_list ap;
76b6d9
 
76b6d9
+  /* Some applications pass the __IPC_64 flag in cmd, to invoke
76b6d9
+     previously unsupported commands back when there was no EINVAL
76b6d9
+     error checking in glibc.  Mask the flag for the switch statements
76b6d9
+     below.  msgctl_syscall adds back the __IPC_64 flag for the actual
76b6d9
+     system call.  */
76b6d9
+  cmd &= ~__IPC_64;
76b6d9
+
76b6d9
   /* Get the argument only if required.  */
76b6d9
   switch (cmd)
76b6d9
     {
76b6d9
diff --git a/sysdeps/unix/sysv/linux/shmctl.c b/sysdeps/unix/sysv/linux/shmctl.c
76b6d9
index 00768bc47614f9aa..25c5152944a6fcf3 100644
76b6d9
--- a/sysdeps/unix/sysv/linux/shmctl.c
76b6d9
+++ b/sysdeps/unix/sysv/linux/shmctl.c
76b6d9
@@ -33,22 +33,6 @@
76b6d9
 int
76b6d9
 __new_shmctl (int shmid, int cmd, struct shmid_ds *buf)
76b6d9
 {
76b6d9
-  switch (cmd)
76b6d9
-    {
76b6d9
-    case IPC_RMID:
76b6d9
-    case SHM_LOCK:
76b6d9
-    case SHM_UNLOCK:
76b6d9
-    case IPC_SET:
76b6d9
-    case IPC_STAT:
76b6d9
-    case SHM_STAT:
76b6d9
-    case SHM_STAT_ANY:
76b6d9
-    case IPC_INFO:
76b6d9
-    case SHM_INFO:
76b6d9
-      break;
76b6d9
-    default:
76b6d9
-      __set_errno (EINVAL);
76b6d9
-      break;
76b6d9
-    }
76b6d9
 #ifdef __ASSUME_DIRECT_SYSVIPC_SYSCALLS
76b6d9
   return INLINE_SYSCALL_CALL (shmctl, shmid, cmd | __IPC_64, buf);
76b6d9
 #else