Home | History | Annotate | Download | only in strace
      1 /*
      2  * Copyright (c) 1993 Ulrich Pegelow <pegelow (at) moorea.uni-muenster.de>
      3  * Copyright (c) 1993 Branko Lankester <branko (at) hacktic.nl>
      4  * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs (at) world.std.com>
      5  * Copyright (c) 1996-1999 Wichert Akkerman <wichert (at) cistron.nl>
      6  * All rights reserved.
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions
     10  * are met:
     11  * 1. Redistributions of source code must retain the above copyright
     12  *    notice, this list of conditions and the following disclaimer.
     13  * 2. Redistributions in binary form must reproduce the above copyright
     14  *    notice, this list of conditions and the following disclaimer in the
     15  *    documentation and/or other materials provided with the distribution.
     16  * 3. The name of the author may not be used to endorse or promote products
     17  *    derived from this software without specific prior written permission.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     21  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     22  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     24  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 #include "defs.h"
     32 #ifdef HAVE_MQUEUE_H
     33 # include <mqueue.h>
     34 #endif
     35 #include <fcntl.h>
     36 #include <sys/ipc.h>
     37 #include <sys/sem.h>
     38 #include <sys/msg.h>
     39 #include <sys/shm.h>
     40 
     41 #ifndef MSG_STAT
     42 #define MSG_STAT 11
     43 #endif
     44 #ifndef MSG_INFO
     45 #define MSG_INFO 12
     46 #endif
     47 #ifndef SHM_STAT
     48 #define SHM_STAT 13
     49 #endif
     50 #ifndef SHM_INFO
     51 #define SHM_INFO 14
     52 #endif
     53 #ifndef SEM_STAT
     54 #define SEM_STAT 18
     55 #endif
     56 #ifndef SEM_INFO
     57 #define SEM_INFO 19
     58 #endif
     59 
     60 #if !defined IPC_64
     61 # define IPC_64 0x100
     62 #endif
     63 
     64 extern void printsigevent(struct tcb *tcp, long arg);
     65 
     66 #include "xlat/msgctl_flags.h"
     67 #include "xlat/semctl_flags.h"
     68 #include "xlat/shmctl_flags.h"
     69 #include "xlat/resource_flags.h"
     70 #include "xlat/shm_resource_flags.h"
     71 #include "xlat/shm_flags.h"
     72 #include "xlat/ipc_msg_flags.h"
     73 #include "xlat/semop_flags.h"
     74 
     75 int sys_msgget(struct tcb *tcp)
     76 {
     77 	if (entering(tcp)) {
     78 		if (tcp->u_arg[0])
     79 			tprintf("%#lx, ", tcp->u_arg[0]);
     80 		else
     81 			tprints("IPC_PRIVATE, ");
     82 		if (printflags(resource_flags, tcp->u_arg[1] & ~0777, NULL) != 0)
     83 			tprints("|");
     84 		tprintf("%#lo", tcp->u_arg[1] & 0777);
     85 	}
     86 	return 0;
     87 }
     88 
     89 #ifdef IPC_64
     90 # define PRINTCTL(flagset, arg, dflt) \
     91 	if ((arg) & IPC_64) tprints("IPC_64|"); \
     92 	printxval((flagset), (arg) &~ IPC_64, dflt)
     93 #else
     94 # define PRINTCTL printxval
     95 #endif
     96 
     97 static int
     98 indirect_ipccall(struct tcb *tcp)
     99 {
    100 #ifdef X86_64
    101 	return current_personality == 1;
    102 #endif
    103 #if defined IA64
    104 	return tcp->scno < 1024; /* ia32 emulation syscalls are low */
    105 #endif
    106 #if defined(ALPHA) || defined(MIPS) || defined(HPPA) || defined(__ARM_EABI__) || defined(AARCH64)
    107 	return 0;
    108 #endif
    109 	return 1;
    110 }
    111 
    112 int sys_msgctl(struct tcb *tcp)
    113 {
    114 	if (entering(tcp)) {
    115 		tprintf("%lu, ", tcp->u_arg[0]);
    116 		PRINTCTL(msgctl_flags, tcp->u_arg[1], "MSG_???");
    117 		tprintf(", %#lx", tcp->u_arg[indirect_ipccall(tcp) ? 3 : 2]);
    118 	}
    119 	return 0;
    120 }
    121 
    122 static void
    123 tprint_msgsnd(struct tcb *tcp, long addr, unsigned long count,
    124 	      unsigned long flags)
    125 {
    126 	long mtype;
    127 
    128 	if (umove(tcp, addr, &mtype) < 0) {
    129 		tprintf("%#lx", addr);
    130 	} else {
    131 		tprintf("{%lu, ", mtype);
    132 		printstr(tcp, addr + sizeof(mtype), count);
    133 		tprints("}");
    134 	}
    135 	tprintf(", %lu, ", count);
    136 	printflags(ipc_msg_flags, flags, "MSG_???");
    137 }
    138 
    139 int sys_msgsnd(struct tcb *tcp)
    140 {
    141 	if (entering(tcp)) {
    142 		tprintf("%d, ", (int) tcp->u_arg[0]);
    143 		if (indirect_ipccall(tcp)) {
    144 			tprint_msgsnd(tcp, tcp->u_arg[3], tcp->u_arg[1],
    145 				      tcp->u_arg[2]);
    146 		} else {
    147 			tprint_msgsnd(tcp, tcp->u_arg[1], tcp->u_arg[2],
    148 				      tcp->u_arg[3]);
    149 		}
    150 	}
    151 	return 0;
    152 }
    153 
    154 static void
    155 tprint_msgrcv(struct tcb *tcp, long addr, unsigned long count, long msgtyp)
    156 {
    157 	long mtype;
    158 
    159 	if (syserror(tcp) || umove(tcp, addr, &mtype) < 0) {
    160 		tprintf("%#lx", addr);
    161 	} else {
    162 		tprintf("{%lu, ", mtype);
    163 		printstr(tcp, addr + sizeof(mtype), count);
    164 		tprints("}");
    165 	}
    166 	tprintf(", %lu, %ld, ", count, msgtyp);
    167 }
    168 
    169 int sys_msgrcv(struct tcb *tcp)
    170 {
    171 	if (entering(tcp)) {
    172 		tprintf("%d, ", (int) tcp->u_arg[0]);
    173 	} else {
    174 		if (indirect_ipccall(tcp)) {
    175 			struct ipc_wrapper {
    176 				struct msgbuf *msgp;
    177 				long msgtyp;
    178 			} tmp;
    179 
    180 			if (umove(tcp, tcp->u_arg[3], &tmp) < 0) {
    181 				tprintf("%#lx, %lu, ",
    182 					tcp->u_arg[3], tcp->u_arg[1]);
    183 			} else {
    184 				tprint_msgrcv(tcp, (long) tmp.msgp,
    185 					tcp->u_arg[1], tmp.msgtyp);
    186 			}
    187 			printflags(ipc_msg_flags, tcp->u_arg[2], "MSG_???");
    188 		} else {
    189 			tprint_msgrcv(tcp, tcp->u_arg[1],
    190 				tcp->u_arg[2], tcp->u_arg[3]);
    191 			printflags(ipc_msg_flags, tcp->u_arg[4], "MSG_???");
    192 		}
    193 	}
    194 	return 0;
    195 }
    196 
    197 static void
    198 tprint_sembuf(struct tcb *tcp, long addr, unsigned long count)
    199 {
    200 	unsigned long i, max_count;
    201 
    202 	if (abbrev(tcp))
    203 		max_count = (max_strlen < count) ? max_strlen : count;
    204 	else
    205 		max_count = count;
    206 
    207 	if (!max_count) {
    208 		tprintf("%#lx, %lu", addr, count);
    209 		return;
    210 	}
    211 
    212 	for (i = 0; i < max_count; ++i) {
    213 		struct sembuf sb;
    214 		if (i)
    215 			tprints(", ");
    216 		if (umove(tcp, addr + i * sizeof(struct sembuf), &sb) < 0) {
    217 			if (i) {
    218 				tprints("{???}");
    219 				break;
    220 			} else {
    221 				tprintf("%#lx, %lu", addr, count);
    222 				return;
    223 			}
    224 		} else {
    225 			if (!i)
    226 				tprints("{");
    227 			tprintf("{%u, %d, ", sb.sem_num, sb.sem_op);
    228 			printflags(semop_flags, sb.sem_flg, "SEM_???");
    229 			tprints("}");
    230 		}
    231 	}
    232 
    233 	if (i < max_count || max_count < count)
    234 		tprints(", ...");
    235 
    236 	tprintf("}, %lu", count);
    237 }
    238 
    239 int sys_semop(struct tcb *tcp)
    240 {
    241 	if (entering(tcp)) {
    242 		tprintf("%lu, ", tcp->u_arg[0]);
    243 		if (indirect_ipccall(tcp)) {
    244 			tprint_sembuf(tcp, tcp->u_arg[3], tcp->u_arg[1]);
    245 		} else {
    246 			tprint_sembuf(tcp, tcp->u_arg[1], tcp->u_arg[2]);
    247 		}
    248 	}
    249 	return 0;
    250 }
    251 
    252 int sys_semtimedop(struct tcb *tcp)
    253 {
    254 	if (entering(tcp)) {
    255 		tprintf("%lu, ", tcp->u_arg[0]);
    256 		if (indirect_ipccall(tcp)) {
    257 			tprint_sembuf(tcp, tcp->u_arg[3], tcp->u_arg[1]);
    258 			tprints(", ");
    259 #if defined(S390) || defined(S390X)
    260 			printtv(tcp, tcp->u_arg[2]);
    261 #else
    262 			printtv(tcp, tcp->u_arg[4]);
    263 #endif
    264 		} else {
    265 			tprint_sembuf(tcp, tcp->u_arg[1], tcp->u_arg[2]);
    266 			tprints(", ");
    267 			printtv(tcp, tcp->u_arg[3]);
    268 		}
    269 	}
    270 	return 0;
    271 }
    272 
    273 int sys_semget(struct tcb *tcp)
    274 {
    275 	if (entering(tcp)) {
    276 		if (tcp->u_arg[0])
    277 			tprintf("%#lx", tcp->u_arg[0]);
    278 		else
    279 			tprints("IPC_PRIVATE");
    280 		tprintf(", %lu, ", tcp->u_arg[1]);
    281 		if (printflags(resource_flags, tcp->u_arg[2] & ~0777, NULL) != 0)
    282 			tprints("|");
    283 		tprintf("%#lo", tcp->u_arg[2] & 0777);
    284 	}
    285 	return 0;
    286 }
    287 
    288 int sys_semctl(struct tcb *tcp)
    289 {
    290 	if (entering(tcp)) {
    291 		tprintf("%lu, %lu, ", tcp->u_arg[0], tcp->u_arg[1]);
    292 		PRINTCTL(semctl_flags, tcp->u_arg[2], "SEM_???");
    293 		tprintf(", %#lx", tcp->u_arg[3]);
    294 	}
    295 	return 0;
    296 }
    297 
    298 int sys_shmget(struct tcb *tcp)
    299 {
    300 	if (entering(tcp)) {
    301 		if (tcp->u_arg[0])
    302 			tprintf("%#lx", tcp->u_arg[0]);
    303 		else
    304 			tprints("IPC_PRIVATE");
    305 		tprintf(", %lu, ", tcp->u_arg[1]);
    306 		if (printflags(shm_resource_flags, tcp->u_arg[2] & ~0777, NULL) != 0)
    307 			tprints("|");
    308 		tprintf("%#lo", tcp->u_arg[2] & 0777);
    309 	}
    310 	return 0;
    311 }
    312 
    313 int sys_shmctl(struct tcb *tcp)
    314 {
    315 	if (entering(tcp)) {
    316 		tprintf("%lu, ", tcp->u_arg[0]);
    317 		PRINTCTL(shmctl_flags, tcp->u_arg[1], "SHM_???");
    318 		if (indirect_ipccall(tcp)) {
    319 			tprintf(", %#lx", tcp->u_arg[3]);
    320 		} else {
    321 			tprintf(", %#lx", tcp->u_arg[2]);
    322 		}
    323 	}
    324 	return 0;
    325 }
    326 
    327 int sys_shmat(struct tcb *tcp)
    328 {
    329 	if (exiting(tcp)) {
    330 		tprintf("%lu", tcp->u_arg[0]);
    331 		if (indirect_ipccall(tcp)) {
    332 			tprintf(", %#lx, ", tcp->u_arg[3]);
    333 			printflags(shm_flags, tcp->u_arg[1], "SHM_???");
    334 		} else {
    335 			tprintf(", %#lx, ", tcp->u_arg[1]);
    336 			printflags(shm_flags, tcp->u_arg[2], "SHM_???");
    337 		}
    338 		if (syserror(tcp))
    339 			return 0;
    340 		if (indirect_ipccall(tcp)) {
    341 			unsigned long raddr;
    342 			if (umove(tcp, tcp->u_arg[2], &raddr) < 0)
    343 				return RVAL_NONE;
    344 			tcp->u_rval = raddr;
    345 		}
    346 		return RVAL_HEX;
    347 	}
    348 	return 0;
    349 }
    350 
    351 int sys_shmdt(struct tcb *tcp)
    352 {
    353 	if (entering(tcp)) {
    354 		if (indirect_ipccall(tcp)) {
    355 			tprintf("%#lx", tcp->u_arg[3]);
    356 		} else {
    357 			tprintf("%#lx", tcp->u_arg[0]);
    358 		}
    359 	}
    360 	return 0;
    361 }
    362 
    363 int
    364 sys_mq_open(struct tcb *tcp)
    365 {
    366 	if (entering(tcp)) {
    367 		printpath(tcp, tcp->u_arg[0]);
    368 		tprints(", ");
    369 		/* flags */
    370 		tprint_open_modes(tcp->u_arg[1]);
    371 		if (tcp->u_arg[1] & O_CREAT) {
    372 # ifndef HAVE_MQUEUE_H
    373 			tprintf(", %lx", tcp->u_arg[2]);
    374 # else
    375 			struct mq_attr attr;
    376 			/* mode */
    377 			tprintf(", %#lo, ", tcp->u_arg[2]);
    378 			if (umove(tcp, tcp->u_arg[3], &attr) < 0)
    379 				tprints("{???}");
    380 			else
    381 				tprintf("{mq_maxmsg=%ld, mq_msgsize=%ld}",
    382 					(long) attr.mq_maxmsg,
    383 					(long) attr.mq_msgsize);
    384 # endif
    385 		}
    386 	}
    387 	return 0;
    388 }
    389 
    390 int
    391 sys_mq_timedsend(struct tcb *tcp)
    392 {
    393 	if (entering(tcp)) {
    394 		tprintf("%ld, ", tcp->u_arg[0]);
    395 		printstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
    396 		tprintf(", %lu, %ld, ", tcp->u_arg[2], tcp->u_arg[3]);
    397 		printtv(tcp, tcp->u_arg[4]);
    398 	}
    399 	return 0;
    400 }
    401 
    402 int
    403 sys_mq_timedreceive(struct tcb *tcp)
    404 {
    405 	if (entering(tcp))
    406 		tprintf("%ld, ", tcp->u_arg[0]);
    407 	else {
    408 		printstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
    409 		tprintf(", %lu, %ld, ", tcp->u_arg[2], tcp->u_arg[3]);
    410 		printtv(tcp, tcp->u_arg[4]);
    411 	}
    412 	return 0;
    413 }
    414 
    415 int
    416 sys_mq_notify(struct tcb *tcp)
    417 {
    418 	if (entering(tcp)) {
    419 		tprintf("%ld, ", tcp->u_arg[0]);
    420 		printsigevent(tcp, tcp->u_arg[1]);
    421 	}
    422 	return 0;
    423 }
    424 
    425 static void
    426 printmqattr(struct tcb *tcp, long addr)
    427 {
    428 	if (addr == 0)
    429 		tprints("NULL");
    430 	else {
    431 # ifndef HAVE_MQUEUE_H
    432 		tprintf("%#lx", addr);
    433 # else
    434 		struct mq_attr attr;
    435 		if (umove(tcp, addr, &attr) < 0) {
    436 			tprints("{...}");
    437 			return;
    438 		}
    439 		tprints("{mq_flags=");
    440 		tprint_open_modes(attr.mq_flags);
    441 		tprintf(", mq_maxmsg=%ld, mq_msgsize=%ld, mq_curmsg=%ld}",
    442 			(long) attr.mq_maxmsg, (long) attr.mq_msgsize,
    443 			(long) attr.mq_curmsgs);
    444 # endif
    445 	}
    446 }
    447 
    448 int
    449 sys_mq_getsetattr(struct tcb *tcp)
    450 {
    451 	if (entering(tcp)) {
    452 		tprintf("%ld, ", tcp->u_arg[0]);
    453 		printmqattr(tcp, tcp->u_arg[1]);
    454 		tprints(", ");
    455 	} else
    456 		printmqattr(tcp, tcp->u_arg[2]);
    457 	return 0;
    458 }
    459 
    460 int
    461 sys_ipc(struct tcb *tcp)
    462 {
    463 	return printargs(tcp);
    464 }
    465