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(shmid_ds_t)
17 #include DEF_MPERS_TYPE(struct_shm_info_t)
18 #include DEF_MPERS_TYPE(struct_shm_ipc_info_t)
19
20 #include "ipc_defs.h"
21
22 #include SHM_H_PROVIDER
23 typedef struct NAME_OF_STRUCT_SHMID_DS shmid_ds_t;
24 typedef struct shm_info struct_shm_info_t;
25 typedef struct NAME_OF_STRUCT_SHMINFO struct_shm_ipc_info_t;
26
27 #include MPERS_DEFS
28
29 #include "xlat/shmctl_flags.h"
30
31 #define key NAME_OF_STRUCT_IPC_PERM_KEY
32
33 static void
34 print_ipc_perm(const typeof_field(shmid_ds_t, shm_perm) *const p,
35 const unsigned int cmd)
36 {
37 tprint_struct_begin();
38 PRINT_FIELD_ID(*p, uid);
39 tprint_struct_next();
40 PRINT_FIELD_ID(*p, gid);
41 tprint_struct_next();
42 PRINT_FIELD_OBJ_U(*p, mode, print_numeric_ll_umode_t);
43 if (cmd != IPC_SET) {
44 tprint_struct_next();
45 PRINT_FIELD_U(*p, key);
46 tprint_struct_next();
47 PRINT_FIELD_ID(*p, cuid);
48 tprint_struct_next();
49 PRINT_FIELD_ID(*p, cgid);
50 }
51 tprint_struct_end();
52 }
53
54 static void
55 print_shmid_ds(struct tcb *const tcp, const kernel_ulong_t addr,
56 const unsigned int cmd)
57 {
58 shmid_ds_t shmid_ds;
59
60 if (umove_or_printaddr(tcp, addr, &shmid_ds))
61 return;
62
63 tprint_struct_begin();
64 PRINT_FIELD_OBJ_PTR(shmid_ds, shm_perm, print_ipc_perm, cmd);
65 if (cmd != IPC_SET) {
66 tprint_struct_next();
67 PRINT_FIELD_U(shmid_ds, shm_segsz);
68 tprint_struct_next();
69 PRINT_FIELD_TGID(shmid_ds, shm_cpid, tcp);
70 tprint_struct_next();
71 PRINT_FIELD_TGID(shmid_ds, shm_lpid, tcp);
72 tprint_struct_next();
73 PRINT_FIELD_U(shmid_ds, shm_nattch);
74 tprint_struct_next();
75 PRINT_FIELD_U(shmid_ds, shm_atime);
76 tprint_struct_next();
77 PRINT_FIELD_U(shmid_ds, shm_dtime);
78 tprint_struct_next();
79 PRINT_FIELD_U(shmid_ds, shm_ctime);
80 }
81 tprint_struct_end();
82 }
83
84 static void
85 print_ipc_info(struct tcb *const tcp, const kernel_ulong_t addr,
86 const unsigned int cmd)
87 {
88 struct_shm_ipc_info_t info;
89
90 if (umove_or_printaddr(tcp, addr, &info))
91 return;
92
93 tprint_struct_begin();
94 PRINT_FIELD_U(info, shmmax);
95 tprint_struct_next();
96 PRINT_FIELD_U(info, shmmin);
97 tprint_struct_next();
98 PRINT_FIELD_U(info, shmmni);
99 tprint_struct_next();
100 PRINT_FIELD_U(info, shmseg);
101 tprint_struct_next();
102 PRINT_FIELD_U(info, shmall);
103 tprint_struct_end();
104 }
105
106 static void
107 print_shm_info(struct tcb *const tcp, const kernel_ulong_t addr,
108 const unsigned int cmd)
109 {
110 struct_shm_info_t info;
111
112 if (umove_or_printaddr(tcp, addr, &info))
113 return;
114
115 tprint_struct_begin();
116 PRINT_FIELD_D(info, used_ids);
117 tprint_struct_next();
118 PRINT_FIELD_U(info, shm_tot);
119 tprint_struct_next();
120 PRINT_FIELD_U(info, shm_rss);
121 tprint_struct_next();
122 PRINT_FIELD_U(info, shm_swp);
123 tprint_struct_next();
124 PRINT_FIELD_U(info, swap_attempts);
125 tprint_struct_next();
126 PRINT_FIELD_U(info, swap_successes);
127 tprint_struct_end();
128 }
129
130 SYS_FUNC(shmctl)
131 {
132 const kernel_ulong_t addr = tcp->u_arg[indirect_ipccall(tcp) ? 3 : 2];
133 unsigned int cmd = tcp->u_arg[1];
134
135 /* TODO: We don't properly decode old compat ipc calls. */
136 if (cmd & IPC_64)
137 cmd &= ~IPC_64;
138
139 if (entering(tcp)) {
140 /* shmid */
141 PRINT_VAL_D((int) tcp->u_arg[0]);
142 tprint_arg_next();
143
144 /* cmd */
145 PRINTCTL(shmctl_flags, tcp->u_arg[1], "SHM_???");
146 tprint_arg_next();
147
148 switch (cmd) {
149 case IPC_SET:
150 /* buf */
151 print_shmid_ds(tcp, addr, cmd);
152 return RVAL_DECODED;
153
154 case IPC_STAT:
155 case SHM_STAT:
156 case SHM_STAT_ANY:
157 case IPC_INFO:
158 case SHM_INFO:
159 /* decode on exiting */
160 break;
161
162 default:
163 /* buf */
164 printaddr(addr);
165 return RVAL_DECODED;
166 }
167 } else {
168 switch (cmd) {
169 case IPC_STAT:
170 case SHM_STAT:
171 case SHM_STAT_ANY:
172 /* buf */
173 print_shmid_ds(tcp, addr, cmd);
174 break;
175
176 case IPC_INFO:
177 /* buf */
178 print_ipc_info(tcp, addr, cmd);
179 break;
180
181 case SHM_INFO:
182 /* buf */
183 print_shm_info(tcp, addr, cmd);
184 break;
185 }
186 }
187 return 0;
188 }