| Rewrite of the following commit to support returning EINVAL for unknown |
| commands and therefore match upstream behaviour. |
| |
| commit 9ebaabeaac1a96b0d91f52902ce1dbf4f5a562dd |
| Author: Adhemerval Zanella <adhemerval.zanella@linaro.org> |
| Date: Tue Sep 29 14:55:02 2020 -0300 |
| |
| sysvipc: Return EINVAL for invalid shmctl commands |
| |
| It avoids regressions on possible future commands that might require |
| additional libc support. The downside is new commands added by newer |
| kernels will need further glibc support. |
| |
| Checked on x86_64-linux-gnu and i686-linux-gnu (Linux v4.15 and v5.4). |
| |
| diff --git a/sysdeps/unix/sysv/linux/shmctl.c b/sysdeps/unix/sysv/linux/shmctl.c |
| index 25c5152944a6fcf3..00768bc47614f9aa 100644 |
| |
| |
| @@ -33,6 +33,22 @@ |
| int |
| __new_shmctl (int shmid, int cmd, struct shmid_ds *buf) |
| { |
| + switch (cmd) |
| + { |
| + case IPC_RMID: |
| + case SHM_LOCK: |
| + case SHM_UNLOCK: |
| + case IPC_SET: |
| + case IPC_STAT: |
| + case SHM_STAT: |
| + case SHM_STAT_ANY: |
| + case IPC_INFO: |
| + case SHM_INFO: |
| + break; |
| + default: |
| + __set_errno (EINVAL); |
| + break; |
| + } |
| #ifdef __ASSUME_DIRECT_SYSVIPC_SYSCALLS |
| return INLINE_SYSCALL_CALL (shmctl, shmid, cmd | __IPC_64, buf); |
| #else |
| diff --git a/sysvipc/test-sysvipc.h b/sysvipc/test-sysvipc.h |
| index 21ef6c656581519e..d1c8349b45b5ce49 100644 |
| |
| |
| @@ -25,7 +25,7 @@ |
| #include <sys/shm.h> |
| #include <include/array_length.h> |
| |
| -/* Return the first invalid command SysV IPC command from common shared |
| +/* Return the first invalid SysV IPC command from common shared |
| between message queue, shared memory, and semaphore. */ |
| static inline int |
| first_common_invalid_cmd (void) |
| @@ -50,7 +50,7 @@ first_common_invalid_cmd (void) |
| return invalid; |
| } |
| |
| -/* Return the first invalid command SysV IPC command for semaphore. */ |
| +/* Return the first invalid SysV IPC command for semaphore. */ |
| static inline int |
| first_sem_invalid_cmd (void) |
| { |
| @@ -82,7 +82,7 @@ first_sem_invalid_cmd (void) |
| return invalid; |
| } |
| |
| -/* Return the first invalid command SysV IPC command for message queue. */ |
| +/* Return the first invalid SysV IPC command for message queue. */ |
| static inline int |
| first_msg_invalid_cmd (void) |
| { |
| @@ -107,4 +107,31 @@ first_msg_invalid_cmd (void) |
| return invalid; |
| } |
| |
| +/* Return the first invalid SysV IPC command for shared memory. */ |
| +static inline int |
| +first_shm_invalid_cmd (void) |
| +{ |
| + const int shm_cmds[] = { |
| + SHM_STAT, |
| + SHM_INFO, |
| +#ifdef SHM_STAT_ANY |
| + SHM_STAT_ANY, |
| +#endif |
| + SHM_LOCK, |
| + SHM_UNLOCK |
| + }; |
| + |
| + int invalid = first_common_invalid_cmd (); |
| + for (int i = 0; i < array_length (shm_cmds); i++) |
| + { |
| + if (invalid == shm_cmds[i]) |
| + { |
| + invalid++; |
| + i = 0; |
| + } |
| + } |
| + |
| + return invalid; |
| +} |
| + |
| #endif /* _TEST_SYSV_H */ |
| diff --git a/sysvipc/test-sysvshm.c b/sysvipc/test-sysvshm.c |
| index a7c2e0bd4065dbcd..0fdfddf8550413e4 100644 |
| |
| |
| @@ -25,6 +25,8 @@ |
| #include <sys/ipc.h> |
| #include <sys/shm.h> |
| |
| +#include <test-sysvipc.h> |
| + |
| #include <support/support.h> |
| #include <support/check.h> |
| #include <support/temp_file.h> |
| @@ -81,6 +83,9 @@ do_test (void) |
| FAIL_EXIT1 ("shmget failed (errno=%d)", errno); |
| } |
| |
| + TEST_COMPARE (shmctl (shmid, first_shm_invalid_cmd (), NULL), -1); |
| + TEST_COMPARE (errno, EINVAL); |
| + |
| /* Get shared memory kernel information and do some sanity checks. */ |
| struct shmid_ds shminfo; |
| if (shmctl (shmid, IPC_STAT, &shminfo) == -1) |