Home | History | Annotate | Download | only in strace
      1 /*
      2  * Copyright (c) 1991, 1992 Paul Kranenburg <pk (at) cs.few.eur.nl>
      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  * 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
     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
     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
     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
     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
     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 
    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 
    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