7a8b60
This is a rewrite of the commit for the pre-64-bit time_t version of
7a8b60
the msgctl handling. Similar to semctl we want the RHEL8 handling of
7a8b60
the unknown commands to be the same as upstream.
7a8b60
7a8b60
commit be9b0b9a012780a403a266c90878efffb9a5f3ca
7a8b60
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
7a8b60
Date:   Tue Sep 29 14:45:09 2020 -0300
7a8b60
7a8b60
    sysvipc: Return EINVAL for invalid msgctl commands
7a8b60
    
7a8b60
    It avoids regressions on possible future commands that might require
7a8b60
    additional libc support.  The downside is new commands added by newer
7a8b60
    kernels will need further glibc support.
7a8b60
    
7a8b60
    Checked on x86_64-linux-gnu and i686-linux-gnu (Linux v4.15 and v5.4).
7a8b60
7a8b60
diff --git a/sysdeps/unix/sysv/linux/msgctl.c b/sysdeps/unix/sysv/linux/msgctl.c
7a8b60
index 7280cba31a8815a2..6a2c79d188b875b9 100644
7a8b60
--- a/sysdeps/unix/sysv/linux/msgctl.c
7a8b60
+++ b/sysdeps/unix/sysv/linux/msgctl.c
7a8b60
@@ -29,6 +29,20 @@
7a8b60
 int
7a8b60
 __new_msgctl (int msqid, int cmd, struct msqid_ds *buf)
7a8b60
 {
7a8b60
+  switch (cmd)
7a8b60
+    {
7a8b60
+    case IPC_RMID:
7a8b60
+    case IPC_SET:
7a8b60
+    case IPC_STAT:
7a8b60
+    case MSG_STAT:
7a8b60
+    case MSG_STAT_ANY:
7a8b60
+    case IPC_INFO:
7a8b60
+    case MSG_INFO:
7a8b60
+      break;
7a8b60
+    default:
7a8b60
+      __set_errno (EINVAL);
7a8b60
+      return -1;
7a8b60
+    }
7a8b60
 #ifdef __ASSUME_DIRECT_SYSVIPC_SYSCALLS
7a8b60
   return INLINE_SYSCALL_CALL (msgctl, msqid, cmd | __IPC_64, buf);
7a8b60
 #else
7a8b60
diff --git a/sysvipc/test-sysvipc.h b/sysvipc/test-sysvipc.h
7a8b60
index ed0057b7871e505c..133fb71c6113a2b5 100644
7a8b60
--- a/sysvipc/test-sysvipc.h
7a8b60
+++ b/sysvipc/test-sysvipc.h
7a8b60
@@ -134,4 +134,29 @@ first_shm_invalid_cmd (void)
7a8b60
   return invalid;
7a8b60
 }
7a8b60
 
7a8b60
+/* Return the first invalid command SysV IPC command for message queue.  */
7a8b60
+static inline int
7a8b60
+first_msg_invalid_cmd (void)
7a8b60
+{
7a8b60
+  const int msg_cmds[] = {
7a8b60
+    MSG_STAT,
7a8b60
+    MSG_INFO,
7a8b60
+#ifdef MSG_STAT_ANY
7a8b60
+    MSG_STAT_ANY,
7a8b60
+#endif
7a8b60
+  };
7a8b60
+
7a8b60
+  int invalid = first_common_invalid_cmd ();
7a8b60
+  for (int i = 0; i < array_length (msg_cmds); i++)
7a8b60
+    {
7a8b60
+      if (invalid == msg_cmds[i])
7a8b60
+	{
7a8b60
+	  invalid++;
7a8b60
+	  i = 0;
7a8b60
+	}
7a8b60
+    }
7a8b60
+
7a8b60
+  return invalid;
7a8b60
+}
7a8b60
+
7a8b60
 #endif /* _TEST_SYSV_H  */
7a8b60
diff --git a/sysvipc/test-sysvmsg.c b/sysvipc/test-sysvmsg.c
7a8b60
index 1e0471807cd26da1..74a907ad39ee114e 100644
7a8b60
--- a/sysvipc/test-sysvmsg.c
7a8b60
+++ b/sysvipc/test-sysvmsg.c
7a8b60
@@ -24,6 +24,8 @@
7a8b60
 #include <sys/ipc.h>
7a8b60
 #include <sys/msg.h>
7a8b60
 
7a8b60
+#include <test-sysvipc.h>
7a8b60
+
7a8b60
 #include <support/support.h>
7a8b60
 #include <support/check.h>
7a8b60
 #include <support/temp_file.h>
7a8b60
@@ -86,6 +88,9 @@ do_test (void)
7a8b60
       FAIL_EXIT1 ("msgget failed (errno=%d)", errno);
7a8b60
     }
7a8b60
 
7a8b60
+  TEST_COMPARE (msgctl (msqid, first_msg_invalid_cmd (), NULL), -1);
7a8b60
+  TEST_COMPARE (errno, EINVAL);
7a8b60
+
7a8b60
   /* Get message queue kernel information and do some sanity checks.  */
7a8b60
   struct msqid_ds msginfo;
7a8b60
   if (msgctl (msqid, IPC_STAT, &msginfo) == -1)