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