1 /*
2 * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
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) 1999-2022 The strace developers.
7 * All rights reserved.
8 *
9 * SPDX-License-Identifier: LGPL-2.1-or-later
10 */
11
12 #include "defs.h"
13 #include <linux/fcntl.h>
14
15 /* Working around UAPI breakage in v5.19-rc1~89^2~9^2~18 */
16 #ifndef F_GETLK64
17 # ifdef __mips__
18 # define F_GETLK64 33
19 # define F_SETLK64 34
20 # define F_SETLKW64 35
21 # else
22 # define F_GETLK64 12
23 # define F_SETLK64 13
24 # define F_SETLKW64 14
25 # endif
26 #endif /* !F_GETLK64 */
27
28 #include "xlat/f_owner_types.h"
29 #include "xlat/f_seals.h"
30 #include "xlat/fcntlcmds.h"
31 #include "xlat/fdflags.h"
32 #include "xlat/lockfcmds.h"
33 #include "xlat/notifyflags.h"
34
35 static void
36 print_struct_flock64(struct tcb *const tcp, const struct flock64 *fl, const int getlk)
37 {
38 tprint_struct_begin();
39 PRINT_FIELD_XVAL(*fl, l_type, lockfcmds, "F_???");
40 tprint_struct_next();
41 PRINT_FIELD_XVAL(*fl, l_whence, whence_codes, "SEEK_???");
42 tprint_struct_next();
43 PRINT_FIELD_D(*fl, l_start);
44 tprint_struct_next();
45 PRINT_FIELD_D(*fl, l_len);
46 if (getlk) {
47 tprint_struct_next();
48 PRINT_FIELD_TGID(*fl, l_pid, tcp);
49 }
50 tprint_struct_end();
51 }
52
53 static void
54 printflock64(struct tcb *const tcp, const kernel_ulong_t addr, const int getlk)
55 {
56 struct flock64 fl;
57
58 if (fetch_struct_flock64(tcp, addr, &fl))
59 print_struct_flock64(tcp, &fl, getlk);
60 }
61
62 static void
63 printflock(struct tcb *const tcp, const kernel_ulong_t addr, const int getlk)
64 {
65 struct flock64 fl;
66
67 if (fetch_struct_flock(tcp, addr, &fl))
68 print_struct_flock64(tcp, &fl, getlk);
69 }
70
71 static void
72 print_f_owner_ex(struct tcb *const tcp, const kernel_ulong_t addr)
73 {
74 struct { int type, pid; } owner;
75
76 if (umove_or_printaddr(tcp, addr, &owner))
77 return;
78
79 tprint_struct_begin();
80 PRINT_FIELD_XVAL(owner, type, f_owner_types, "F_OWNER_???");
81
82 enum pid_type pid_type = PT_NONE;
83 switch (owner.type)
84 {
85 case F_OWNER_TID:
86 pid_type = PT_TID;
87 break;
88 case F_OWNER_PID:
89 pid_type = PT_TGID;
90 break;
91 case F_OWNER_PGRP:
92 pid_type = PT_PGID;
93 break;
94 }
95 tprint_struct_next();
96 tprints_field_name("pid");
97 printpid(tcp, owner.pid, pid_type);
98 tprint_struct_end();
99 }
100
101 static int
102 print_fcntl(struct tcb *tcp)
103 {
104 const unsigned int cmd = tcp->u_arg[1];
105
106 switch (cmd) {
107 case F_SETFD:
108 tprint_arg_next();
109 printflags(fdflags, tcp->u_arg[2], "FD_???");
110 break;
111 case F_SETOWN:
112 tprint_arg_next();
113 printpid_tgid_pgid(tcp, tcp->u_arg[2]);
114 break;
115 case F_SETPIPE_SZ:
116 tprint_arg_next();
117 PRINT_VAL_D(tcp->u_arg[2]);
118 break;
119 case F_DUPFD:
120 case F_DUPFD_CLOEXEC:
121 tprint_arg_next();
122 PRINT_VAL_D(tcp->u_arg[2]);
123 return RVAL_DECODED | RVAL_FD;
124 case F_SETFL:
125 tprint_arg_next();
126 tprint_open_modes(tcp->u_arg[2]);
127 break;
128 case F_SETLK:
129 case F_SETLKW:
130 tprint_arg_next();
131 printflock(tcp, tcp->u_arg[2], 0);
132 break;
133 case F_OFD_SETLK:
134 case F_OFD_SETLKW:
135 tprint_arg_next();
136 printflock64(tcp, tcp->u_arg[2], 0);
137 break;
138 case F_SETOWN_EX:
139 tprint_arg_next();
140 print_f_owner_ex(tcp, tcp->u_arg[2]);
141 break;
142 case F_NOTIFY:
143 tprint_arg_next();
144 printflags64(notifyflags, tcp->u_arg[2], "DN_???");
145 break;
146 case F_SETLEASE:
147 tprint_arg_next();
148 printxval64(lockfcmds, tcp->u_arg[2], "F_???");
149 break;
150 case F_ADD_SEALS:
151 tprint_arg_next();
152 printflags64(f_seals, tcp->u_arg[2], "F_SEAL_???");
153 break;
154 case F_SETSIG:
155 tprint_arg_next();
156 printsignal(tcp->u_arg[2]);
157 break;
158 case F_GETOWN:
159 return RVAL_DECODED |
160 ((int) tcp->u_rval < 0 ? RVAL_PGID : RVAL_TGID);
161 case F_GETPIPE_SZ:
162 break;
163 case F_GETFD:
164 if (entering(tcp) || syserror(tcp) || tcp->u_rval == 0)
165 return 0;
166 tcp->auxstr = sprintflags("flags ", fdflags,
167 (kernel_ulong_t) tcp->u_rval);
168 return RVAL_HEX | RVAL_STR;
169 case F_GETFL:
170 if (entering(tcp) || syserror(tcp))
171 return 0;
172 tcp->auxstr = sprint_open_modes(tcp->u_rval);
173 return RVAL_HEX | RVAL_STR;
174 case F_GETLK:
175 if (entering(tcp))
176 return 0;
177 tprint_arg_next();
178 printflock(tcp, tcp->u_arg[2], 1);
179 break;
180 case F_OFD_GETLK:
181 if (entering(tcp))
182 return 0;
183 tprint_arg_next();
184 printflock64(tcp, tcp->u_arg[2], 1);
185 break;
186 case F_GETOWN_EX:
187 if (entering(tcp))
188 return 0;
189 tprint_arg_next();
190 print_f_owner_ex(tcp, tcp->u_arg[2]);
191 break;
192 case F_GETLEASE:
193 if (entering(tcp) || syserror(tcp))
194 return 0;
195 tcp->auxstr = xlookup(lockfcmds, (kernel_ulong_t) tcp->u_rval);
196 return RVAL_HEX | RVAL_STR;
197 case F_GET_SEALS:
198 if (entering(tcp) || syserror(tcp) || tcp->u_rval == 0)
199 return 0;
200 tcp->auxstr = sprintflags("seals ", f_seals,
201 (kernel_ulong_t) tcp->u_rval);
202 return RVAL_HEX | RVAL_STR;
203 case F_GETSIG:
204 if (entering(tcp) || syserror(tcp) || tcp->u_rval == 0)
205 return 0;
206 tcp->auxstr = signame(tcp->u_rval);
207 return RVAL_STR;
208 default:
209 tprint_arg_next();
210 PRINT_VAL_X(tcp->u_arg[2]);
211 break;
212 }
213 return RVAL_DECODED;
214 }
215
216 SYS_FUNC(fcntl)
217 {
218 if (entering(tcp)) {
219 /* fd */
220 printfd(tcp, tcp->u_arg[0]);
221 tprint_arg_next();
222
223 /* cmd */
224 printxval(fcntlcmds, tcp->u_arg[1], "F_???");
225 }
226 return print_fcntl(tcp);
227 }
228
229 SYS_FUNC(fcntl64)
230 {
231 const unsigned int cmd = tcp->u_arg[1];
232 if (entering(tcp)) {
233 /* fd */
234 printfd(tcp, tcp->u_arg[0]);
235 tprint_arg_next();
236
237 /* cmd */
238 printxval(fcntlcmds, cmd, "F_???");
239 }
240 switch (cmd) {
241 case F_SETLK64:
242 case F_SETLKW64:
243 tprint_arg_next();
244 printflock64(tcp, tcp->u_arg[2], 0);
245 return RVAL_DECODED;
246 case F_GETLK64:
247 if (exiting(tcp)) {
248 tprint_arg_next();
249 printflock64(tcp, tcp->u_arg[2], 1);
250 }
251 return 0;
252 }
253 return print_fcntl(tcp);
254 }