summaryrefslogtreecommitdiff
path: root/ipc_msgctl.c
blob: 4c95e5cd36f607494fe721c0c18a875071575675 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/*
 * Copyright (c) 1993 Ulrich Pegelow <pegelow@moorea.uni-muenster.de>
 * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
 * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
 * Copyright (c) 2003-2006 Roland McGrath <roland@redhat.com>
 * Copyright (c) 2006-2015 Dmitry V. Levin <ldv@strace.io>
 * Copyright (c) 2015-2020 The strace developers.
 * All rights reserved.
 *
 * SPDX-License-Identifier: LGPL-2.1-or-later
 */

#include "defs.h"

#include DEF_MPERS_TYPE(msqid_ds_t)

#include "ipc_defs.h"

#include MSG_H_PROVIDER
typedef struct NAME_OF_STRUCT_MSQID_DS msqid_ds_t;

#include MPERS_DEFS

#include "xlat/msgctl_flags.h"

#define key NAME_OF_STRUCT_IPC_PERM_KEY

static void
print_ipc_perm(const typeof_field(msqid_ds_t, msg_perm) *const p,
	       const unsigned int cmd)
{
	tprint_struct_begin();
	PRINT_FIELD_ID(*p, uid);
	tprint_struct_next();
	PRINT_FIELD_ID(*p, gid);
	tprint_struct_next();
	PRINT_FIELD_OBJ_U(*p, mode, print_numeric_ll_umode_t);
	if (cmd != IPC_SET) {
		tprint_struct_next();
		PRINT_FIELD_U(*p, key);
		tprint_struct_next();
		PRINT_FIELD_ID(*p, cuid);
		tprint_struct_next();
		PRINT_FIELD_ID(*p, cgid);
	}
	tprint_struct_end();
}

static void
print_msqid_ds(struct tcb *const tcp, const kernel_ulong_t addr,
	       const unsigned int cmd)
{
	msqid_ds_t msqid_ds;

	if (umove_or_printaddr(tcp, addr, &msqid_ds))
		return;

	tprint_struct_begin();
	PRINT_FIELD_OBJ_PTR(msqid_ds, msg_perm, print_ipc_perm, cmd);
	if (cmd != IPC_SET) {
		tprint_struct_next();
		PRINT_FIELD_U(msqid_ds, msg_stime);
		tprint_struct_next();
		PRINT_FIELD_U(msqid_ds, msg_rtime);
		tprint_struct_next();
		PRINT_FIELD_U(msqid_ds, msg_ctime);
		tprint_struct_next();
		PRINT_FIELD_U(msqid_ds, msg_qnum);
	}
	tprint_struct_next();
	PRINT_FIELD_U(msqid_ds, msg_qbytes);
	if (cmd != IPC_SET) {
		tprint_struct_next();
		PRINT_FIELD_D(msqid_ds, msg_lspid);
		tprint_struct_next();
		PRINT_FIELD_D(msqid_ds, msg_lrpid);
	}
	tprint_struct_end();
}

static void
print_msginfo(struct tcb *const tcp, const kernel_ulong_t addr,
	      const unsigned int cmd)
{
	struct msginfo info;

	if (umove_or_printaddr(tcp, addr, &info))
		return;

	tprint_struct_begin();
	PRINT_FIELD_D(info, msgpool);
	tprint_struct_next();
	PRINT_FIELD_D(info, msgmap);
	tprint_struct_next();
	PRINT_FIELD_D(info, msgmax);
	tprint_struct_next();
	PRINT_FIELD_D(info, msgmnb);
	tprint_struct_next();
	PRINT_FIELD_D(info, msgmni);
	tprint_struct_next();
	PRINT_FIELD_D(info, msgssz);
	tprint_struct_next();
	PRINT_FIELD_D(info, msgtql);
	tprint_struct_next();
	PRINT_FIELD_U(info, msgseg);
	tprint_struct_end();
}

SYS_FUNC(msgctl)
{
	const kernel_ulong_t addr = tcp->u_arg[indirect_ipccall(tcp) ? 3 : 2];
	unsigned int cmd = tcp->u_arg[1];

	/* TODO: We don't properly decode old compat ipc calls. */
	if (cmd & IPC_64)
		cmd &= ~IPC_64;

	if (entering(tcp)) {
		tprintf("%d, ", (int) tcp->u_arg[0]);
		PRINTCTL(msgctl_flags, tcp->u_arg[1], "MSG_???");
		tprints(", ");
		switch (cmd) {
		case IPC_SET:
			print_msqid_ds(tcp, addr, cmd);
			return RVAL_DECODED;

		case IPC_STAT:
		case MSG_STAT:
		case MSG_STAT_ANY:
		case IPC_INFO:
		case MSG_INFO:
			/* decode on exiting */
			break;

		default:
			printaddr(addr);
			return RVAL_DECODED;
		}
	} else {
		switch (cmd) {
		case IPC_STAT:
		case MSG_STAT:
		case MSG_STAT_ANY:
			print_msqid_ds(tcp, addr, cmd);
			break;

		case IPC_INFO:
		case MSG_INFO:
			print_msginfo(tcp, addr, cmd);
			break;
		}
	}
	return 0;
}