• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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-2017 The strace developers.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. The name of the author may not be used to endorse or promote products
18  *    derived from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include "defs.h"
33 #include "flock.h"
34 
35 #include "xlat/f_owner_types.h"
36 #include "xlat/f_seals.h"
37 #include "xlat/fcntlcmds.h"
38 #include "xlat/fcntl64cmds.h"
39 #include "xlat/fdflags.h"
40 #include "xlat/lockfcmds.h"
41 #include "xlat/notifyflags.h"
42 
43 static void
print_struct_flock64(const struct_kernel_flock64 * fl,const int getlk)44 print_struct_flock64(const struct_kernel_flock64 *fl, const int getlk)
45 {
46 	tprints("{l_type=");
47 	printxval(lockfcmds, (unsigned short) fl->l_type, "F_???");
48 	tprints(", l_whence=");
49 	printxval(whence_codes, (unsigned short) fl->l_whence, "SEEK_???");
50 	tprintf(", l_start=%" PRId64 ", l_len=%" PRId64,
51 		(int64_t) fl->l_start, (int64_t) fl->l_len);
52 	if (getlk)
53 		tprintf(", l_pid=%lu", (unsigned long) fl->l_pid);
54 	tprints("}");
55 }
56 
57 static void
printflock64(struct tcb * const tcp,const kernel_ulong_t addr,const int getlk)58 printflock64(struct tcb *const tcp, const kernel_ulong_t addr, const int getlk)
59 {
60 	struct_kernel_flock64 fl;
61 
62 	if (fetch_struct_flock64(tcp, addr, &fl))
63 		print_struct_flock64(&fl, getlk);
64 }
65 
66 static void
printflock(struct tcb * const tcp,const kernel_ulong_t addr,const int getlk)67 printflock(struct tcb *const tcp, const kernel_ulong_t addr, const int getlk)
68 {
69 	struct_kernel_flock64 fl;
70 
71 	if (fetch_struct_flock(tcp, addr, &fl))
72 		print_struct_flock64(&fl, getlk);
73 }
74 
75 static void
print_f_owner_ex(struct tcb * const tcp,const kernel_ulong_t addr)76 print_f_owner_ex(struct tcb *const tcp, const kernel_ulong_t addr)
77 {
78 	struct { int type, pid; } owner;
79 
80 	if (umove_or_printaddr(tcp, addr, &owner))
81 		return;
82 
83 	tprints("{type=");
84 	printxval(f_owner_types, owner.type, "F_OWNER_???");
85 	tprintf(", pid=%d}", owner.pid);
86 }
87 
88 static int
print_fcntl(struct tcb * tcp)89 print_fcntl(struct tcb *tcp)
90 {
91 	const unsigned int cmd = tcp->u_arg[1];
92 
93 	switch (cmd) {
94 	case F_SETFD:
95 		tprints(", ");
96 		printflags(fdflags, tcp->u_arg[2], "FD_???");
97 		break;
98 	case F_SETOWN:
99 	case F_SETPIPE_SZ:
100 		tprintf(", %" PRI_kld, tcp->u_arg[2]);
101 		break;
102 	case F_DUPFD:
103 	case F_DUPFD_CLOEXEC:
104 		tprintf(", %" PRI_kld, tcp->u_arg[2]);
105 		return RVAL_DECODED | RVAL_FD;
106 	case F_SETFL:
107 		tprints(", ");
108 		tprint_open_modes(tcp->u_arg[2]);
109 		break;
110 	case F_SETLK:
111 	case F_SETLKW:
112 		tprints(", ");
113 		printflock(tcp, tcp->u_arg[2], 0);
114 		break;
115 	case F_OFD_SETLK:
116 	case F_OFD_SETLKW:
117 		tprints(", ");
118 		printflock64(tcp, tcp->u_arg[2], 0);
119 		break;
120 	case F_SETOWN_EX:
121 		tprints(", ");
122 		print_f_owner_ex(tcp, tcp->u_arg[2]);
123 		break;
124 	case F_NOTIFY:
125 		tprints(", ");
126 		printflags64(notifyflags, tcp->u_arg[2], "DN_???");
127 		break;
128 	case F_SETLEASE:
129 		tprints(", ");
130 		printxval64(lockfcmds, tcp->u_arg[2], "F_???");
131 		break;
132 	case F_ADD_SEALS:
133 		tprints(", ");
134 		printflags64(f_seals, tcp->u_arg[2], "F_SEAL_???");
135 		break;
136 	case F_SETSIG:
137 		tprints(", ");
138 		tprints(signame(tcp->u_arg[2]));
139 		break;
140 	case F_GETOWN:
141 	case F_GETPIPE_SZ:
142 		break;
143 	case F_GETFD:
144 		if (entering(tcp) || syserror(tcp) || tcp->u_rval == 0)
145 			return 0;
146 		tcp->auxstr = sprintflags("flags ", fdflags,
147 					  (kernel_ulong_t) tcp->u_rval);
148 		return RVAL_HEX | RVAL_STR;
149 	case F_GETFL:
150 		if (entering(tcp) || syserror(tcp))
151 			return 0;
152 		tcp->auxstr = sprint_open_modes(tcp->u_rval);
153 		return RVAL_HEX | RVAL_STR;
154 	case F_GETLK:
155 		if (entering(tcp))
156 			return 0;
157 		tprints(", ");
158 		printflock(tcp, tcp->u_arg[2], 1);
159 		break;
160 	case F_OFD_GETLK:
161 		if (entering(tcp))
162 			return 0;
163 		tprints(", ");
164 		printflock64(tcp, tcp->u_arg[2], 1);
165 		break;
166 	case F_GETOWN_EX:
167 		if (entering(tcp))
168 			return 0;
169 		tprints(", ");
170 		print_f_owner_ex(tcp, tcp->u_arg[2]);
171 		break;
172 	case F_GETLEASE:
173 		if (entering(tcp) || syserror(tcp))
174 			return 0;
175 		tcp->auxstr = xlookup(lockfcmds, (kernel_ulong_t) tcp->u_rval);
176 		return RVAL_HEX | RVAL_STR;
177 	case F_GET_SEALS:
178 		if (entering(tcp) || syserror(tcp) || tcp->u_rval == 0)
179 			return 0;
180 		tcp->auxstr = sprintflags("seals ", f_seals,
181 					  (kernel_ulong_t) tcp->u_rval);
182 		return RVAL_HEX | RVAL_STR;
183 	case F_GETSIG:
184 		if (entering(tcp) || syserror(tcp) || tcp->u_rval == 0)
185 			return 0;
186 		tcp->auxstr = signame(tcp->u_rval);
187 		return RVAL_STR;
188 	default:
189 		tprintf(", %#" PRI_klx, tcp->u_arg[2]);
190 		break;
191 	}
192 	return RVAL_DECODED;
193 }
194 
SYS_FUNC(fcntl)195 SYS_FUNC(fcntl)
196 {
197 	if (entering(tcp)) {
198 		printfd(tcp, tcp->u_arg[0]);
199 		tprints(", ");
200 		const unsigned int cmd = tcp->u_arg[1];
201 		const char *str = xlookup(fcntlcmds, cmd);
202 		if (str) {
203 			tprints(str);
204 		} else {
205 			/*
206 			 * fcntl syscall does not recognize these
207 			 * constants, but we would like to show them
208 			 * for better debugging experience.
209 			 */
210 			printxval(fcntl64cmds, cmd, "F_???");
211 		}
212 	}
213 	return print_fcntl(tcp);
214 }
215 
SYS_FUNC(fcntl64)216 SYS_FUNC(fcntl64)
217 {
218 	const unsigned int cmd = tcp->u_arg[1];
219 	if (entering(tcp)) {
220 		printfd(tcp, tcp->u_arg[0]);
221 		tprints(", ");
222 		const char *str = xlookup(fcntl64cmds, cmd);
223 		if (str) {
224 			tprints(str);
225 		} else {
226 			printxval(fcntlcmds, cmd, "F_???");
227 		}
228 	}
229 	switch (cmd) {
230 		case F_SETLK64:
231 		case F_SETLKW64:
232 			tprints(", ");
233 			printflock64(tcp, tcp->u_arg[2], 0);
234 			return RVAL_DECODED;
235 		case F_GETLK64:
236 			if (exiting(tcp)) {
237 				tprints(", ");
238 				printflock64(tcp, tcp->u_arg[2], 1);
239 			}
240 			return 0;
241 	}
242 	return print_fcntl(tcp);
243 }
244