(root)/
strace-6.5/
tests-m32/
ipc_msg.c
       1  /*
       2   * Copyright (c) 2015 Elvira Khabirova <lineprinter0@gmail.com>
       3   * Copyright (c) 2015-2016 Dmitry V. Levin <ldv@strace.io>
       4   * Copyright (c) 2015-2021 The strace developers.
       5   * All rights reserved.
       6   *
       7   * SPDX-License-Identifier: GPL-2.0-or-later
       8   */
       9  
      10  #include "tests.h"
      11  #include <errno.h>
      12  #include <stdio.h>
      13  #include <stdlib.h>
      14  #include <sys/msg.h>
      15  
      16  #include "xlat.h"
      17  #include "xlat/resource_flags.h"
      18  
      19  #ifndef MSG_STAT_ANY
      20  # define MSG_STAT_ANY 13
      21  #endif
      22  
      23  #undef TEST_MSGCTL_BOGUS_ADDR
      24  #undef TEST_MSGCTL_BOGUS_CMD
      25  
      26  /*
      27   * Starting with commit glibc-2.32~83, on every 32-bit architecture
      28   * where 32-bit time_t support is enabled, glibc tries to retrieve
      29   * the data provided in the third argument of msgctl call.
      30   */
      31  #if GLIBC_PREREQ_GE(2, 32) && defined __TIMESIZE && __TIMESIZE != 64
      32  # define TEST_MSGCTL_BOGUS_ADDR 0
      33  #endif
      34  /*
      35   * Starting with commit glibc-2.31~358, on every architecture where
      36   * __ASSUME_SYSVIPC_BROKEN_MODE_T is defined, glibc tries to modify
      37   * the data provided in the third argument of msgctl call.
      38   */
      39  #if GLIBC_PREREQ_GE(2, 31) && \
      40   (defined __m68k__ || defined __s390__ || \
      41    (defined WORDS_BIGENDIAN && \
      42     (defined __arm__ || defined __microblaze__ || defined __sh__)))
      43  # define TEST_MSGCTL_BOGUS_ADDR 0
      44  #endif
      45  /*
      46   * Before glibc-2.22-122-gbe48165, ppc64 code tried to retrieve data
      47   * provided in third argument of msgctl call (in case of IPC_SET cmd)
      48   * which led to segmentation fault.
      49   */
      50  #if GLIBC_PREREQ_LT(2, 23) && (defined POWERPC64 || defined POWERPC64LE)
      51  # define TEST_MSGCTL_BOGUS_ADDR 0
      52  #endif
      53  
      54  /*
      55   * Starting with commit glibc-2.32.9000-149-gbe9b0b9a012780a403a2,
      56   * glibc skips msgctl syscall invocations and returns EINVAL
      57   * for invalid msgctl commands.
      58   *
      59   * Apparently, this change was later backported to vendor packages, e.g.:
      60   * Thu Mar 18 2021 Carlos O'Donell <carlos@redhat.com> - 2.28-153
      61   * - Support SEM_STAT_ANY via semctl. Return EINVAL for unknown commands
      62   *   to semctl, msgctl, and shmctl. (#1912670)
      63   */
      64  #if GLIBC_PREREQ_GE(2, 28)
      65  # define TEST_MSGCTL_BOGUS_CMD 0
      66  #endif
      67  
      68  #ifndef TEST_MSGCTL_BOGUS_ADDR
      69  # define TEST_MSGCTL_BOGUS_ADDR 1
      70  #endif
      71  #ifndef TEST_MSGCTL_BOGUS_CMD
      72  # define TEST_MSGCTL_BOGUS_CMD 1
      73  #endif
      74  
      75  #if XLAT_RAW
      76  # define str_ipc_excl_nowait "0xface1c00"
      77  # define str_ipc_private "0"
      78  # define str_ipc_rmid "0"
      79  # define str_ipc_set "0x1"
      80  # define str_ipc_stat "0x2"
      81  # define str_ipc_info "0x3"
      82  # define str_msg_stat "0xb"
      83  # define str_msg_info "0xc"
      84  # define str_msg_stat_any "0xd"
      85  # define str_ipc_64 "0x100"
      86  # define str_bogus_cmd "0xdeadbeef"
      87  #elif XLAT_VERBOSE
      88  # define str_ipc_excl_nowait \
      89  	"0xface1c00 /\\* IPC_EXCL\\|IPC_NOWAIT\\|0xface1000 \\*/"
      90  # define str_ipc_private "0 /\\* IPC_PRIVATE \\*/"
      91  # define str_ipc_rmid "0 /\\* IPC_RMID \\*/"
      92  # define str_ipc_set "0x1 /\\* IPC_SET \\*/"
      93  # define str_ipc_stat "0x2 /\\* IPC_STAT \\*/"
      94  # define str_ipc_info "0x3 /\\* IPC_INFO \\*/"
      95  # define str_msg_stat "0xb /\\* MSG_STAT \\*/"
      96  # define str_msg_info "0xc /\\* MSG_INFO \\*/"
      97  # define str_msg_stat_any "0xd /\\* MSG_STAT_ANY \\*/"
      98  # define str_ipc_64 "0x100 /\\* IPC_64 \\*/"
      99  # define str_bogus_cmd "0xdeadbeef /\\* MSG_\\?\\?\\? \\*/"
     100  #else
     101  # define str_ipc_excl_nowait "IPC_EXCL\\|IPC_NOWAIT\\|0xface1000"
     102  # define str_ipc_private "IPC_PRIVATE"
     103  # define str_ipc_rmid "IPC_RMID"
     104  # define str_ipc_set "IPC_SET"
     105  # define str_ipc_stat "IPC_STAT"
     106  # define str_ipc_info "IPC_INFO"
     107  # define str_msg_stat "MSG_STAT"
     108  # define str_msg_info "MSG_INFO"
     109  # define str_msg_stat_any "MSG_STAT_ANY"
     110  # define str_ipc_64 "IPC_64"
     111  # define str_bogus_cmd "0xdeadbeef /\\* MSG_\\?\\?\\? \\*/"
     112  #endif
     113  
     114  static int id = -1;
     115  
     116  static void
     117  cleanup(void)
     118  {
     119  	msgctl(id, IPC_RMID, NULL);
     120  	printf("msgctl\\(%d, (%s\\|)?%s, NULL\\) += 0\n",
     121  	       id, str_ipc_64, str_ipc_rmid);
     122  	id = -1;
     123  }
     124  
     125  static void
     126  print_msginfo(const char *const str_ipc_cmd,
     127  	      const struct msginfo *const info,
     128  	      const int rc)
     129  {
     130  	if (rc < 0) {
     131  		printf("msgctl\\(%d, (%s\\|)?%s, %p\\) = %s\n",
     132  		       id, str_ipc_64, str_ipc_cmd, info, sprintrc_grep(rc));
     133  		return;
     134  	}
     135  
     136  	printf("msgctl\\(%d, (%s\\|)?%s, \\{msgpool=%d, msgmap=%d, msgmax=%d"
     137  	       ", msgmnb=%d, msgmni=%d, msgssz=%d, msgtql=%d, msgseg=%u\\}\\)"
     138  	       " = %d\n",
     139  	       id,
     140  	       str_ipc_64,
     141  	       str_ipc_cmd,
     142  	       info->msgpool,
     143  	       info->msgmap,
     144  	       info->msgmax,
     145  	       info->msgmnb,
     146  	       info->msgmni,
     147  	       info->msgssz,
     148  	       info->msgtql,
     149  	       (unsigned) info->msgseg,
     150  	       rc);
     151  }
     152  
     153  static void
     154  print_msqid_ds(const char *const str_ipc_cmd,
     155  	       const struct msqid_ds *const ds,
     156  	       const int rc)
     157  {
     158  	if (rc < 0) {
     159  		printf("msgctl\\(%d, (%s\\|)?%s, %p\\) = %s\n",
     160  		       id, str_ipc_64, str_ipc_cmd, ds, sprintrc_grep(rc));
     161  		return;
     162  	}
     163  
     164  	printf("msgctl\\(%d, (%s\\|)?%s, \\{msg_perm=\\{uid=%u"
     165  	       ", gid=%u, mode=%#o, key=%u, cuid=%u, cgid=%u\\}"
     166  	       ", msg_stime=%u, msg_rtime=%u, msg_ctime=%u, msg_qnum=%u"
     167  	       ", msg_qbytes=%u, msg_lspid=%d, msg_lrpid=%d\\}\\) = %d\n",
     168  	       id,
     169  	       str_ipc_64,
     170  	       str_ipc_cmd,
     171  	       (unsigned) ds->msg_perm.uid,
     172  	       (unsigned) ds->msg_perm.gid,
     173  	       (unsigned) ds->msg_perm.mode,
     174  	       (unsigned) ds->msg_perm.__key,
     175  	       (unsigned) ds->msg_perm.cuid,
     176  	       (unsigned) ds->msg_perm.cgid,
     177  	       (unsigned) ds->msg_stime,
     178  	       (unsigned) ds->msg_rtime,
     179  	       (unsigned) ds->msg_ctime,
     180  	       (unsigned) ds->msg_qnum,
     181  	       (unsigned) ds->msg_qbytes,
     182  	       (int) ds->msg_lspid,
     183  	       (int) ds->msg_lrpid,
     184  	       rc);
     185  }
     186  
     187  int
     188  main(void)
     189  {
     190  	static const key_t private_key =
     191  		(key_t) (0xffffffff00000000ULL | IPC_PRIVATE);
     192  	static const key_t bogus_key = (key_t) 0xeca86420fdb9f531ULL;
     193  	static const int bogus_flags = 0xface1e55 & ~IPC_CREAT;
     194  #if TEST_MSGCTL_BOGUS_CMD || TEST_MSGCTL_BOGUS_ADDR
     195  	static const int bogus_msgid = 0xfdb97531;
     196  #endif
     197  #if TEST_MSGCTL_BOGUS_CMD
     198  	static const int bogus_cmd = 0xdeadbeef;
     199  #endif
     200  #if TEST_MSGCTL_BOGUS_ADDR
     201  	static void * const bogus_addr = (void *) -1L;
     202  #endif
     203  
     204  	int rc;
     205  	union {
     206  		struct msqid_ds ds;
     207  		struct msginfo info;
     208  	} buf;
     209  
     210  	rc = msgget(bogus_key, bogus_flags);
     211  	printf("msgget\\(%#llx, %s\\|%#04o\\) = %s\n",
     212  	       zero_extend_signed_to_ull(bogus_key),
     213  	       str_ipc_excl_nowait,
     214  	       bogus_flags & 0777, sprintrc_grep(rc));
     215  
     216  	id = msgget(private_key, 0600);
     217  	if (id < 0)
     218  		perror_msg_and_skip("msgget");
     219  	printf("msgget\\(%s, 0600\\) = %d\n", str_ipc_private, id);
     220  	atexit(cleanup);
     221  
     222  #if TEST_MSGCTL_BOGUS_CMD
     223  	rc = msgctl(bogus_msgid, bogus_cmd, NULL);
     224  	printf("msgctl\\(%d, (%s\\|)?%s, NULL\\) = %s\n",
     225  	       bogus_msgid, str_ipc_64, str_bogus_cmd, sprintrc_grep(rc));
     226  #endif
     227  
     228  #if TEST_MSGCTL_BOGUS_ADDR
     229  	rc = msgctl(bogus_msgid, IPC_SET, bogus_addr);
     230  	printf("msgctl\\(%d, (%s\\|)?%s, %p\\) = %s\n",
     231  	       bogus_msgid, str_ipc_64, str_ipc_set, bogus_addr,
     232  	       sprintrc_grep(rc));
     233  #endif
     234  
     235  	rc = msgctl(id, IPC_STAT, &buf.ds);
     236  	if (rc < 0)
     237  		perror_msg_and_skip("msgctl IPC_STAT");
     238  	print_msqid_ds(str_ipc_stat, &buf.ds, rc);
     239  
     240  	if (msgctl(id, IPC_SET, &buf.ds))
     241  		perror_msg_and_skip("msgctl IPC_SET");
     242  	printf("msgctl\\(%d, (%s\\|)?%s, \\{msg_perm=\\{uid=%u"
     243  	       ", gid=%u, mode=%#o\\}, msg_qbytes=%u\\}\\) = 0\n",
     244  	       id, str_ipc_64, str_ipc_set,
     245  	       (unsigned) buf.ds.msg_perm.uid,
     246  	       (unsigned) buf.ds.msg_perm.gid,
     247  	       (unsigned) buf.ds.msg_perm.mode,
     248  	       (unsigned) buf.ds.msg_qbytes);
     249  
     250  	rc = msgctl(id, IPC_INFO, &buf.ds);
     251  	print_msginfo(str_ipc_info, &buf.info, rc);
     252  
     253  	rc = msgctl(id, MSG_INFO, &buf.ds);
     254  	print_msginfo(str_msg_info, &buf.info, rc);
     255  
     256  	rc = msgctl(id, MSG_STAT, &buf.ds);
     257  	print_msqid_ds(str_msg_stat, &buf.ds, rc);
     258  
     259  	rc = msgctl(id, MSG_STAT_ANY, &buf.ds);
     260  	print_msqid_ds(str_msg_stat_any, &buf.ds, rc);
     261  
     262  	return 0;
     263  }