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