|
|
6ca6e8 |
commit d57cdc1b5a52b5468b9259c0b9a215e22a1fa1f6
|
|
|
6ca6e8 |
Author: Florian Weimer <fweimer@redhat.com>
|
|
|
6ca6e8 |
Date: Tue Nov 8 14:15:02 2022 +0100
|
|
|
6ca6e8 |
|
|
|
6ca6e8 |
Linux: Support __IPC_64 in sysvctl *ctl command arguments (bug 29771)
|
|
|
6ca6e8 |
|
|
|
6ca6e8 |
Old applications pass __IPC_64 as part of the command argument because
|
|
|
6ca6e8 |
old glibc did not check for unknown commands, and passed through the
|
|
|
6ca6e8 |
arguments directly to the kernel, without adding __IPC_64.
|
|
|
6ca6e8 |
Applications need to continue doing that for old glibc compatibility,
|
|
|
6ca6e8 |
so this commit enables this approach in current glibc.
|
|
|
6ca6e8 |
|
|
|
6ca6e8 |
For msgctl and shmctl, if no translation is required, make
|
|
|
6ca6e8 |
direct system calls, as we did before the time64 changes. If
|
|
|
6ca6e8 |
translation is required, mask __IPC_64 from the command argument.
|
|
|
6ca6e8 |
|
|
|
6ca6e8 |
For semctl, the union-in-vararg argument handling means that
|
|
|
6ca6e8 |
translation is needed on all architectures.
|
|
|
6ca6e8 |
|
|
|
6ca6e8 |
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
|
|
6ca6e8 |
(cherry picked from commit 22a46dee24351fd5f4f188ad80554cad79c82524)
|
|
|
6ca6e8 |
|
|
|
6ca6e8 |
diff --git a/sysdeps/unix/sysv/linux/ipc_priv.h b/sysdeps/unix/sysv/linux/ipc_priv.h
|
|
|
6ca6e8 |
index f9852367a466cea9..d4efb9f3483daa9f 100644
|
|
|
6ca6e8 |
--- a/sysdeps/unix/sysv/linux/ipc_priv.h
|
|
|
6ca6e8 |
+++ b/sysdeps/unix/sysv/linux/ipc_priv.h
|
|
|
6ca6e8 |
@@ -63,4 +63,10 @@ struct __old_ipc_perm
|
|
|
6ca6e8 |
# define __IPC_TIME64 0
|
|
|
6ca6e8 |
#endif
|
|
|
6ca6e8 |
|
|
|
6ca6e8 |
+#if __IPC_TIME64 || defined __ASSUME_SYSVIPC_BROKEN_MODE_T
|
|
|
6ca6e8 |
+# define IPC_CTL_NEED_TRANSLATION 1
|
|
|
6ca6e8 |
+#else
|
|
|
6ca6e8 |
+# define IPC_CTL_NEED_TRANSLATION 0
|
|
|
6ca6e8 |
+#endif
|
|
|
6ca6e8 |
+
|
|
|
6ca6e8 |
#include <ipc_ops.h>
|
|
|
6ca6e8 |
diff --git a/sysdeps/unix/sysv/linux/msgctl.c b/sysdeps/unix/sysv/linux/msgctl.c
|
|
|
6ca6e8 |
index 9f38c06d53936390..ba7b94c22d17bc7f 100644
|
|
|
6ca6e8 |
--- a/sysdeps/unix/sysv/linux/msgctl.c
|
|
|
6ca6e8 |
+++ b/sysdeps/unix/sysv/linux/msgctl.c
|
|
|
6ca6e8 |
@@ -86,11 +86,19 @@ msgctl_syscall (int msqid, int cmd, msgctl_arg_t *buf)
|
|
|
6ca6e8 |
int
|
|
|
6ca6e8 |
__msgctl64 (int msqid, int cmd, struct __msqid64_ds *buf)
|
|
|
6ca6e8 |
{
|
|
|
6ca6e8 |
-#if __IPC_TIME64
|
|
|
6ca6e8 |
+#if IPC_CTL_NEED_TRANSLATION
|
|
|
6ca6e8 |
+# if __IPC_TIME64
|
|
|
6ca6e8 |
struct kernel_msqid64_ds ksemid, *arg = NULL;
|
|
|
6ca6e8 |
-#else
|
|
|
6ca6e8 |
+# else
|
|
|
6ca6e8 |
msgctl_arg_t *arg;
|
|
|
6ca6e8 |
-#endif
|
|
|
6ca6e8 |
+# endif
|
|
|
6ca6e8 |
+
|
|
|
6ca6e8 |
+ /* Some applications pass the __IPC_64 flag in cmd, to invoke
|
|
|
6ca6e8 |
+ previously unsupported commands back when there was no EINVAL
|
|
|
6ca6e8 |
+ error checking in glibc. Mask the flag for the switch statements
|
|
|
6ca6e8 |
+ below. msgctl_syscall adds back the __IPC_64 flag for the actual
|
|
|
6ca6e8 |
+ system call. */
|
|
|
6ca6e8 |
+ cmd &= ~__IPC_64;
|
|
|
6ca6e8 |
|
|
|
6ca6e8 |
switch (cmd)
|
|
|
6ca6e8 |
{
|
|
|
6ca6e8 |
@@ -102,19 +110,19 @@ __msgctl64 (int msqid, int cmd, struct __msqid64_ds *buf)
|
|
|
6ca6e8 |
case IPC_STAT:
|
|
|
6ca6e8 |
case MSG_STAT:
|
|
|
6ca6e8 |
case MSG_STAT_ANY:
|
|
|
6ca6e8 |
-#if __IPC_TIME64
|
|
|
6ca6e8 |
+# if __IPC_TIME64
|
|
|
6ca6e8 |
if (buf != NULL)
|
|
|
6ca6e8 |
{
|
|
|
6ca6e8 |
msqid64_to_kmsqid64 (buf, &ksemid);
|
|
|
6ca6e8 |
arg = &ksemid;
|
|
|
6ca6e8 |
}
|
|
|
6ca6e8 |
-# ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
|
|
|
6ca6e8 |
+# ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
|
|
|
6ca6e8 |
if (cmd == IPC_SET)
|
|
|
6ca6e8 |
arg->msg_perm.mode *= 0x10000U;
|
|
|
6ca6e8 |
-# endif
|
|
|
6ca6e8 |
-#else
|
|
|
6ca6e8 |
+# endif
|
|
|
6ca6e8 |
+# else
|
|
|
6ca6e8 |
arg = buf;
|
|
|
6ca6e8 |
-#endif
|
|
|
6ca6e8 |
+# endif
|
|
|
6ca6e8 |
break;
|
|
|
6ca6e8 |
|
|
|
6ca6e8 |
case IPC_INFO:
|
|
|
6ca6e8 |
@@ -138,21 +146,25 @@ __msgctl64 (int msqid, int cmd, struct __msqid64_ds *buf)
|
|
|
6ca6e8 |
case IPC_STAT:
|
|
|
6ca6e8 |
case MSG_STAT:
|
|
|
6ca6e8 |
case MSG_STAT_ANY:
|
|
|
6ca6e8 |
-#ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
|
|
|
6ca6e8 |
+# ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
|
|
|
6ca6e8 |
arg->msg_perm.mode >>= 16;
|
|
|
6ca6e8 |
-#else
|
|
|
6ca6e8 |
+# else
|
|
|
6ca6e8 |
/* Old Linux kernel versions might not clear the mode padding. */
|
|
|
6ca6e8 |
if (sizeof ((struct msqid_ds){0}.msg_perm.mode)
|
|
|
6ca6e8 |
!= sizeof (__kernel_mode_t))
|
|
|
6ca6e8 |
arg->msg_perm.mode &= 0xFFFF;
|
|
|
6ca6e8 |
-#endif
|
|
|
6ca6e8 |
+# endif
|
|
|
6ca6e8 |
|
|
|
6ca6e8 |
-#if __IPC_TIME64
|
|
|
6ca6e8 |
+# if __IPC_TIME64
|
|
|
6ca6e8 |
kmsqid64_to_msqid64 (arg, buf);
|
|
|
6ca6e8 |
-#endif
|
|
|
6ca6e8 |
+# endif
|
|
|
6ca6e8 |
}
|
|
|
6ca6e8 |
|
|
|
6ca6e8 |
return ret;
|
|
|
6ca6e8 |
+
|
|
|
6ca6e8 |
+#else /* !IPC_CTL_NEED_TRANSLATION */
|
|
|
6ca6e8 |
+ return msgctl_syscall (msqid, cmd, buf);
|
|
|
6ca6e8 |
+#endif
|
|
|
6ca6e8 |
}
|
|
|
6ca6e8 |
#if __TIMESIZE != 64
|
|
|
6ca6e8 |
libc_hidden_def (__msgctl64)
|
|
|
6ca6e8 |
diff --git a/sysdeps/unix/sysv/linux/semctl.c b/sysdeps/unix/sysv/linux/semctl.c
|
|
|
6ca6e8 |
index bb2690d30f80bb22..97fa411547fdd81e 100644
|
|
|
6ca6e8 |
--- a/sysdeps/unix/sysv/linux/semctl.c
|
|
|
6ca6e8 |
+++ b/sysdeps/unix/sysv/linux/semctl.c
|
|
|
6ca6e8 |
@@ -141,6 +141,13 @@ __semctl64 (int semid, int semnum, int cmd, ...)
|
|
|
6ca6e8 |
union semun64 arg64 = { 0 };
|
|
|
6ca6e8 |
va_list ap;
|
|
|
6ca6e8 |
|
|
|
6ca6e8 |
+ /* Some applications pass the __IPC_64 flag in cmd, to invoke
|
|
|
6ca6e8 |
+ previously unsupported commands back when there was no EINVAL
|
|
|
6ca6e8 |
+ error checking in glibc. Mask the flag for the switch statements
|
|
|
6ca6e8 |
+ below. semctl_syscall adds back the __IPC_64 flag for the actual
|
|
|
6ca6e8 |
+ system call. */
|
|
|
6ca6e8 |
+ cmd &= ~__IPC_64;
|
|
|
6ca6e8 |
+
|
|
|
6ca6e8 |
/* Get the argument only if required. */
|
|
|
6ca6e8 |
switch (cmd)
|
|
|
6ca6e8 |
{
|
|
|
6ca6e8 |
diff --git a/sysdeps/unix/sysv/linux/shmctl.c b/sysdeps/unix/sysv/linux/shmctl.c
|
|
|
6ca6e8 |
index f52018bfae4b3364..c44cbd6e4ac890a5 100644
|
|
|
6ca6e8 |
--- a/sysdeps/unix/sysv/linux/shmctl.c
|
|
|
6ca6e8 |
+++ b/sysdeps/unix/sysv/linux/shmctl.c
|
|
|
6ca6e8 |
@@ -86,11 +86,19 @@ shmctl_syscall (int shmid, int cmd, shmctl_arg_t *buf)
|
|
|
6ca6e8 |
int
|
|
|
6ca6e8 |
__shmctl64 (int shmid, int cmd, struct __shmid64_ds *buf)
|
|
|
6ca6e8 |
{
|
|
|
6ca6e8 |
-#if __IPC_TIME64
|
|
|
6ca6e8 |
+#if IPC_CTL_NEED_TRANSLATION
|
|
|
6ca6e8 |
+# if __IPC_TIME64
|
|
|
6ca6e8 |
struct kernel_shmid64_ds kshmid, *arg = NULL;
|
|
|
6ca6e8 |
-#else
|
|
|
6ca6e8 |
+# else
|
|
|
6ca6e8 |
shmctl_arg_t *arg;
|
|
|
6ca6e8 |
-#endif
|
|
|
6ca6e8 |
+# endif
|
|
|
6ca6e8 |
+
|
|
|
6ca6e8 |
+ /* Some applications pass the __IPC_64 flag in cmd, to invoke
|
|
|
6ca6e8 |
+ previously unsupported commands back when there was no EINVAL
|
|
|
6ca6e8 |
+ error checking in glibc. Mask the flag for the switch statements
|
|
|
6ca6e8 |
+ below. shmctl_syscall adds back the __IPC_64 flag for the actual
|
|
|
6ca6e8 |
+ system call. */
|
|
|
6ca6e8 |
+ cmd &= ~__IPC_64;
|
|
|
6ca6e8 |
|
|
|
6ca6e8 |
switch (cmd)
|
|
|
6ca6e8 |
{
|
|
|
6ca6e8 |
@@ -104,19 +112,19 @@ __shmctl64 (int shmid, int cmd, struct __shmid64_ds *buf)
|
|
|
6ca6e8 |
case IPC_STAT:
|
|
|
6ca6e8 |
case SHM_STAT:
|
|
|
6ca6e8 |
case SHM_STAT_ANY:
|
|
|
6ca6e8 |
-#if __IPC_TIME64
|
|
|
6ca6e8 |
+# if __IPC_TIME64
|
|
|
6ca6e8 |
if (buf != NULL)
|
|
|
6ca6e8 |
{
|
|
|
6ca6e8 |
shmid64_to_kshmid64 (buf, &kshmid);
|
|
|
6ca6e8 |
arg = &kshmid;
|
|
|
6ca6e8 |
}
|
|
|
6ca6e8 |
-# ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
|
|
|
6ca6e8 |
+# ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
|
|
|
6ca6e8 |
if (cmd == IPC_SET)
|
|
|
6ca6e8 |
arg->shm_perm.mode *= 0x10000U;
|
|
|
6ca6e8 |
-# endif
|
|
|
6ca6e8 |
-#else
|
|
|
6ca6e8 |
+# endif
|
|
|
6ca6e8 |
+# else
|
|
|
6ca6e8 |
arg = buf;
|
|
|
6ca6e8 |
-#endif
|
|
|
6ca6e8 |
+# endif
|
|
|
6ca6e8 |
break;
|
|
|
6ca6e8 |
|
|
|
6ca6e8 |
case IPC_INFO:
|
|
|
6ca6e8 |
@@ -141,21 +149,25 @@ __shmctl64 (int shmid, int cmd, struct __shmid64_ds *buf)
|
|
|
6ca6e8 |
case IPC_STAT:
|
|
|
6ca6e8 |
case SHM_STAT:
|
|
|
6ca6e8 |
case SHM_STAT_ANY:
|
|
|
6ca6e8 |
-#ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
|
|
|
6ca6e8 |
+# ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
|
|
|
6ca6e8 |
arg->shm_perm.mode >>= 16;
|
|
|
6ca6e8 |
-#else
|
|
|
6ca6e8 |
+# else
|
|
|
6ca6e8 |
/* Old Linux kernel versions might not clear the mode padding. */
|
|
|
6ca6e8 |
if (sizeof ((struct shmid_ds){0}.shm_perm.mode)
|
|
|
6ca6e8 |
!= sizeof (__kernel_mode_t))
|
|
|
6ca6e8 |
arg->shm_perm.mode &= 0xFFFF;
|
|
|
6ca6e8 |
-#endif
|
|
|
6ca6e8 |
+# endif
|
|
|
6ca6e8 |
|
|
|
6ca6e8 |
-#if __IPC_TIME64
|
|
|
6ca6e8 |
+# if __IPC_TIME64
|
|
|
6ca6e8 |
kshmid64_to_shmid64 (arg, buf);
|
|
|
6ca6e8 |
-#endif
|
|
|
6ca6e8 |
+# endif
|
|
|
6ca6e8 |
}
|
|
|
6ca6e8 |
|
|
|
6ca6e8 |
return ret;
|
|
|
6ca6e8 |
+
|
|
|
6ca6e8 |
+#else /* !IPC_CTL_NEED_TRANSLATION */
|
|
|
6ca6e8 |
+ return shmctl_syscall (shmid, cmd, buf);
|
|
|
6ca6e8 |
+#endif
|
|
|
6ca6e8 |
}
|
|
|
6ca6e8 |
#if __TIMESIZE != 64
|
|
|
6ca6e8 |
libc_hidden_def (__shmctl64)
|