(root)/
strace-6.5/
src/
ipc_semctl.c
       1  /*
       2   * Copyright (c) 1993 Ulrich Pegelow <pegelow@moorea.uni-muenster.de>
       3   * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
       4   * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
       5   * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
       6   * Copyright (c) 2003-2006 Roland McGrath <roland@redhat.com>
       7   * Copyright (c) 2006-2015 Dmitry V. Levin <ldv@strace.io>
       8   * Copyright (c) 2015-2021 The strace developers.
       9   * All rights reserved.
      10   *
      11   * SPDX-License-Identifier: LGPL-2.1-or-later
      12   */
      13  
      14  #include "defs.h"
      15  
      16  #include DEF_MPERS_TYPE(semid_ds_t)
      17  #include DEF_MPERS_TYPE(semun_ptr_t)
      18  
      19  #include "ipc_defs.h"
      20  
      21  #include SEM_H_PROVIDER
      22  
      23  typedef struct NAME_OF_STRUCT_SEMID_DS semid_ds_t;
      24  typedef kernel_ulong_t semun_ptr_t;
      25  
      26  #include MPERS_DEFS
      27  
      28  #include "xlat/semctl_flags.h"
      29  
      30  #define key NAME_OF_STRUCT_IPC_PERM_KEY
      31  
      32  static void
      33  print_ipc_perm(const typeof_field(semid_ds_t, sem_perm) *const p,
      34  	       const unsigned int cmd)
      35  {
      36  	tprint_struct_begin();
      37  	PRINT_FIELD_ID(*p, uid);
      38  	tprint_struct_next();
      39  	PRINT_FIELD_ID(*p, gid);
      40  	tprint_struct_next();
      41  	PRINT_FIELD_OBJ_U(*p, mode, print_numeric_ll_umode_t);
      42  	if (cmd != IPC_SET) {
      43  		tprint_struct_next();
      44  		PRINT_FIELD_U(*p, key);
      45  		tprint_struct_next();
      46  		PRINT_FIELD_ID(*p, cuid);
      47  		tprint_struct_next();
      48  		PRINT_FIELD_ID(*p, cgid);
      49  	}
      50  	tprint_struct_end();
      51  }
      52  
      53  static void
      54  print_semid_ds(struct tcb *const tcp, const kernel_ulong_t addr,
      55  	       const unsigned int cmd, const bool indirect_addr)
      56  {
      57  	semid_ds_t ds;
      58  
      59  	if (!tfetch_mem(tcp, addr, sizeof(ds), &ds)) {
      60  		if (indirect_addr)
      61  			tprint_indirect_begin();
      62  		printaddr(addr);
      63  		if (indirect_addr)
      64  			tprint_indirect_end();
      65  		return;
      66  	}
      67  
      68  	tprint_struct_begin();
      69  	PRINT_FIELD_OBJ_PTR(ds, sem_perm, print_ipc_perm, cmd);
      70  	if (cmd != IPC_SET) {
      71  		tprint_struct_next();
      72  		PRINT_FIELD_U(ds, sem_otime);
      73  		tprint_struct_next();
      74  		PRINT_FIELD_U(ds, sem_ctime);
      75  		tprint_struct_next();
      76  		PRINT_FIELD_U(ds, sem_nsems);
      77  	}
      78  	tprint_struct_end();
      79  }
      80  
      81  static void
      82  print_seminfo(struct tcb *const tcp, const kernel_ulong_t addr,
      83  	      const unsigned int cmd, const bool indirect_addr)
      84  {
      85  	struct seminfo info;
      86  
      87  	if (umove_or_printaddr(tcp, addr, &info))
      88  		return;
      89  	if (!tfetch_mem(tcp, addr, sizeof(info), &info)) {
      90  		if (indirect_addr)
      91  			tprint_indirect_begin();
      92  		printaddr(addr);
      93  		if (indirect_addr)
      94  			tprint_indirect_end();
      95  		return;
      96  	}
      97  
      98  	tprint_struct_begin();
      99  	PRINT_FIELD_D(info, semmap);
     100  	tprint_struct_next();
     101  	PRINT_FIELD_D(info, semmni);
     102  	tprint_struct_next();
     103  	PRINT_FIELD_D(info, semmns);
     104  	tprint_struct_next();
     105  	PRINT_FIELD_D(info, semmnu);
     106  	tprint_struct_next();
     107  	PRINT_FIELD_D(info, semmsl);
     108  	tprint_struct_next();
     109  	PRINT_FIELD_D(info, semopm);
     110  	tprint_struct_next();
     111  	PRINT_FIELD_D(info, semume);
     112  	tprint_struct_next();
     113  	PRINT_FIELD_D(info, semusz);
     114  	tprint_struct_next();
     115  	PRINT_FIELD_D(info, semvmx);
     116  	tprint_struct_next();
     117  	PRINT_FIELD_D(info, semaem);
     118  	tprint_struct_end();
     119  }
     120  
     121  SYS_FUNC(semctl)
     122  {
     123  	kernel_ulong_t addr;
     124  	unsigned int cmd = tcp->u_arg[2];
     125  	const bool indirect_addr = indirect_ipccall(tcp)
     126  #ifdef SPARC64
     127  		    && current_personality != 0
     128  #endif
     129  		    ;
     130  
     131  	/* TODO: We don't properly decode old compat ipc calls. */
     132  	if (cmd & IPC_64)
     133  		cmd &= ~IPC_64;
     134  
     135  	if (entering(tcp)) {
     136  		/* semid */
     137  		PRINT_VAL_D((int) tcp->u_arg[0]);
     138  		tprint_arg_next();
     139  
     140  		/* semnum */
     141  		PRINT_VAL_D((int) tcp->u_arg[1]);
     142  		tprint_arg_next();
     143  
     144  		/* cmd */
     145  		PRINTCTL(semctl_flags, tcp->u_arg[2], "SEM_???");
     146  		tprint_arg_next();
     147  
     148  		if (indirect_addr) {
     149  			semun_ptr_t ptr;
     150  			if (umove_or_printaddr(tcp, tcp->u_arg[3], &ptr))
     151  				return RVAL_DECODED;
     152  			addr = ptr;
     153  		} else {
     154  			addr = tcp->u_arg[3];
     155  		}
     156  		switch (cmd) {
     157  		case IPC_SET:
     158  			print_semid_ds(tcp, addr, cmd, indirect_addr);
     159  			return RVAL_DECODED;
     160  
     161  		case IPC_STAT:
     162  		case SEM_STAT:
     163  		case SEM_STAT_ANY:
     164  		case IPC_INFO:
     165  		case SEM_INFO:
     166  			/* decode on exiting */
     167  			set_tcb_priv_ulong(tcp, addr);
     168  			break;
     169  
     170  		default:
     171  			if (indirect_addr)
     172  				tprint_indirect_begin();
     173  			printaddr(addr);
     174  			if (indirect_addr)
     175  				tprint_indirect_end();
     176  			return RVAL_DECODED;
     177  		}
     178  	} else {
     179  		addr = get_tcb_priv_ulong(tcp);
     180  		switch (cmd) {
     181  		case IPC_STAT:
     182  		case SEM_STAT:
     183  		case SEM_STAT_ANY:
     184  			print_semid_ds(tcp, addr, cmd, indirect_addr);
     185  			break;
     186  
     187  		case IPC_INFO:
     188  		case SEM_INFO:
     189  			print_seminfo(tcp, addr, cmd, indirect_addr);
     190  			break;
     191  		}
     192  	}
     193  	return 0;
     194  }