summaryrefslogtreecommitdiff
path: root/sysdeps/unix/sysv/linux/shmctl.c
diff options
context:
space:
mode:
authorAdhemerval Zanella <adhemerval.zanella@linaro.org>2020-09-29 14:51:36 -0300
committerAdhemerval Zanella <adhemerval.zanella@linaro.org>2020-10-14 11:49:55 -0300
commita49d7fd4f764e97ccaf922e433046590ae52fce9 (patch)
tree46f23931f1e7e5cd2a2b9c74cb3630f7fff3f167 /sysdeps/unix/sysv/linux/shmctl.c
parente11ed9d2b4558eeacff81557dc9557001af42a6b (diff)
downloadglibc-a49d7fd4f764e97ccaf922e433046590ae52fce9.tar
glibc-a49d7fd4f764e97ccaf922e433046590ae52fce9.tar.gz
glibc-a49d7fd4f764e97ccaf922e433046590ae52fce9.tar.bz2
glibc-a49d7fd4f764e97ccaf922e433046590ae52fce9.zip
sysvipc: Fix IPC_INFO and SHM_INFO handling [BZ #26636]
Both commands are Linux extensions where the third argument is either a 'struct shminfo' (IPC_INFO) or a 'struct shm_info' (SHM_INFO) instead of 'struct shmid_ds'. And their information does not contain any time related fields, so there is no need to extra conversion for __IPC_TIME64. The regression testcase checks for Linux specifix SysV ipc message control extension. For SHM_INFO it tries to match the values against the tunable /proc values and for MSG_STAT/MSG_STAT_ANY it check if the create\ shared memory is within the global list returned by the kernel. Checked on x86_64-linux-gnu and on i686-linux-gnu (Linux v5.4 and on Linux v4.15).
Diffstat (limited to 'sysdeps/unix/sysv/linux/shmctl.c')
-rw-r--r--sysdeps/unix/sysv/linux/shmctl.c24
1 files changed, 18 insertions, 6 deletions
diff --git a/sysdeps/unix/sysv/linux/shmctl.c b/sysdeps/unix/sysv/linux/shmctl.c
index 76d88441f1..1d19a798b1 100644
--- a/sysdeps/unix/sysv/linux/shmctl.c
+++ b/sysdeps/unix/sysv/linux/shmctl.c
@@ -90,8 +90,15 @@ __shmctl64 (int shmid, int cmd, struct __shmid64_ds *buf)
struct kernel_shmid64_ds kshmid, *arg = NULL;
if (buf != NULL)
{
- shmid64_to_kshmid64 (buf, &kshmid);
- arg = &kshmid;
+ /* This is a Linux extension where kernel expects either a
+ 'struct shminfo' (IPC_INFO) or 'struct shm_info' (SHM_INFO). */
+ if (cmd == IPC_INFO || cmd == SHM_INFO)
+ arg = (struct kernel_shmid64_ds *) buf;
+ else
+ {
+ shmid64_to_kshmid64 (buf, &kshmid);
+ arg = &kshmid;
+ }
}
# ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
if (cmd == IPC_SET)
@@ -107,7 +114,6 @@ __shmctl64 (int shmid, int cmd, struct __shmid64_ds *buf)
switch (cmd)
{
- case IPC_INFO:
case IPC_STAT:
case SHM_STAT:
case SHM_STAT_ANY:
@@ -168,8 +174,15 @@ __shmctl (int shmid, int cmd, struct shmid_ds *buf)
struct __shmid64_ds shmid64, *buf64 = NULL;
if (buf != NULL)
{
- shmid_to_shmid64 (&shmid64, buf);
- buf64 = &shmid64;
+ /* This is a Linux extension where kernel expects either a
+ 'struct shminfo' (IPC_INFO) or 'struct shm_info' (SHM_INFO). */
+ if (cmd == IPC_INFO || cmd == SHM_INFO)
+ buf64 = (struct __shmid64_ds *) buf;
+ else
+ {
+ shmid_to_shmid64 (&shmid64, buf);
+ buf64 = &shmid64;
+ }
}
int ret = __shmctl64 (shmid, cmd, buf64);
@@ -178,7 +191,6 @@ __shmctl (int shmid, int cmd, struct shmid_ds *buf)
switch (cmd)
{
- case IPC_INFO:
case IPC_STAT:
case SHM_STAT:
case SHM_STAT_ANY: