Home | History | Annotate | Download | only in strace
      1 /*
      2  * Copyright (c) 2012 The Chromium OS Authors.
      3  * Copyright (c) 2012-2018 The strace developers.
      4  * Written by Mike Frysinger <vapier (at) gentoo.org>.
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  * 1. Redistributions of source code must retain the above copyright
     10  *    notice, this list of conditions and the following disclaimer.
     11  * 2. Redistributions in binary form must reproduce the above copyright
     12  *    notice, this list of conditions and the following disclaimer in the
     13  *    documentation and/or other materials provided with the distribution.
     14  * 3. The name of the author may not be used to endorse or promote products
     15  *    derived from this software without specific prior written permission.
     16  *
     17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27  */
     28 
     29 #include "defs.h"
     30 #include <linux/ioctl.h>
     31 #include <linux/loop.h>
     32 
     33 typedef struct loop_info struct_loop_info;
     34 
     35 #include DEF_MPERS_TYPE(struct_loop_info)
     36 
     37 #include MPERS_DEFS
     38 
     39 #include "print_fields.h"
     40 #include "xlat/loop_cmds.h"
     41 #include "xlat/loop_flags_options.h"
     42 #include "xlat/loop_crypt_type_options.h"
     43 
     44 static void
     45 decode_loop_info(struct tcb *const tcp, const kernel_ulong_t addr)
     46 {
     47 	struct_loop_info info;
     48 
     49 	tprints(", ");
     50 	if (umove_or_printaddr(tcp, addr, &info))
     51 		return;
     52 
     53 	tprintf("{lo_number=%d", info.lo_number);
     54 
     55 	if (!abbrev(tcp)) {
     56 		PRINT_FIELD_DEV(", ", info, lo_device);
     57 		tprintf(", lo_inode=%" PRI_klu, (kernel_ulong_t) info.lo_inode);
     58 		PRINT_FIELD_DEV(", ", info, lo_rdevice);
     59 	}
     60 
     61 	tprintf(", lo_offset=%#x", info.lo_offset);
     62 
     63 	if (!abbrev(tcp) || info.lo_encrypt_type != LO_CRYPT_NONE) {
     64 		tprints(", lo_encrypt_type=");
     65 		printxval(loop_crypt_type_options, info.lo_encrypt_type,
     66 			"LO_CRYPT_???");
     67 		/*
     68 		 * It is converted to unsigned before use in kernel, see
     69 		 * loop_info64_from_old in drivers/block/loop.c
     70 		 */
     71 		tprintf(", lo_encrypt_key_size=%" PRIu32,
     72 			(uint32_t) info.lo_encrypt_key_size);
     73 	}
     74 
     75 	tprints(", lo_flags=");
     76 	printflags(loop_flags_options, info.lo_flags, "LO_FLAGS_???");
     77 
     78 	PRINT_FIELD_CSTRING(", ", info, lo_name);
     79 
     80 	if (!abbrev(tcp) || info.lo_encrypt_type != LO_CRYPT_NONE) {
     81 		const unsigned int lo_encrypt_key_size =
     82 			MIN((unsigned) info.lo_encrypt_key_size, LO_KEY_SIZE);
     83 		PRINT_FIELD_STRING(", ", info, lo_encrypt_key,
     84 					  lo_encrypt_key_size, 0);
     85 	}
     86 
     87 	if (!abbrev(tcp))
     88 		tprintf(", lo_init=[%#" PRI_klx ", %#" PRI_klx "]"
     89 			", reserved=[%#hhx, %#hhx, %#hhx, %#hhx]}",
     90 			(kernel_ulong_t) info.lo_init[0],
     91 			(kernel_ulong_t) info.lo_init[1],
     92 			info.reserved[0], info.reserved[1],
     93 			info.reserved[2], info.reserved[3]);
     94 	else
     95 		tprints(", ...}");
     96 }
     97 
     98 static void
     99 decode_loop_info64(struct tcb *const tcp, const kernel_ulong_t addr)
    100 {
    101 	struct loop_info64 info64;
    102 
    103 	tprints(", ");
    104 	if (umove_or_printaddr(tcp, addr, &info64))
    105 		return;
    106 
    107 	if (!abbrev(tcp)) {
    108 		PRINT_FIELD_DEV("{", info64, lo_device);
    109 		tprintf(", lo_inode=%" PRIu64, (uint64_t) info64.lo_inode);
    110 		PRINT_FIELD_DEV(", ", info64, lo_rdevice);
    111 		tprintf(", lo_offset=%#" PRIx64 ", lo_sizelimit=%" PRIu64
    112 			", lo_number=%" PRIu32,
    113 			(uint64_t) info64.lo_offset,
    114 			(uint64_t) info64.lo_sizelimit,
    115 			(uint32_t) info64.lo_number);
    116 	} else {
    117 		tprintf("{lo_offset=%#" PRIx64 ", lo_number=%" PRIu32,
    118 			(uint64_t) info64.lo_offset,
    119 			(uint32_t) info64.lo_number);
    120 	}
    121 
    122 	if (!abbrev(tcp) || info64.lo_encrypt_type != LO_CRYPT_NONE) {
    123 		tprints(", lo_encrypt_type=");
    124 		printxval(loop_crypt_type_options, info64.lo_encrypt_type,
    125 			"LO_CRYPT_???");
    126 		tprintf(", lo_encrypt_key_size=%" PRIu32,
    127 			info64.lo_encrypt_key_size);
    128 	}
    129 
    130 	tprints(", lo_flags=");
    131 	printflags(loop_flags_options, info64.lo_flags, "LO_FLAGS_???");
    132 
    133 	PRINT_FIELD_CSTRING(", ", info64, lo_file_name);
    134 
    135 	if (!abbrev(tcp) || info64.lo_encrypt_type != LO_CRYPT_NONE) {
    136 		PRINT_FIELD_CSTRING(", ", info64, lo_crypt_name);
    137 		const unsigned int lo_encrypt_key_size =
    138 			MIN((unsigned) info64.lo_encrypt_key_size, LO_KEY_SIZE);
    139 		PRINT_FIELD_STRING(", ", info64, lo_encrypt_key,
    140 					  lo_encrypt_key_size, 0);
    141 	}
    142 
    143 	if (!abbrev(tcp))
    144 		tprintf(", lo_init=[%#" PRIx64 ", %#" PRIx64 "]}",
    145 			(uint64_t) info64.lo_init[0],
    146 			(uint64_t) info64.lo_init[1]);
    147 	else
    148 		tprints(", ...}");
    149 }
    150 
    151 MPERS_PRINTER_DECL(int, loop_ioctl,
    152 		   struct tcb *tcp, const unsigned int code,
    153 		   const kernel_ulong_t arg)
    154 {
    155 	switch (code) {
    156 	case LOOP_GET_STATUS:
    157 		if (entering(tcp))
    158 			return 0;
    159 		ATTRIBUTE_FALLTHROUGH;
    160 	case LOOP_SET_STATUS:
    161 		decode_loop_info(tcp, arg);
    162 		break;
    163 
    164 	case LOOP_GET_STATUS64:
    165 		if (entering(tcp))
    166 			return 0;
    167 		ATTRIBUTE_FALLTHROUGH;
    168 	case LOOP_SET_STATUS64:
    169 		decode_loop_info64(tcp, arg);
    170 		break;
    171 
    172 	case LOOP_CLR_FD:
    173 	case LOOP_SET_CAPACITY:
    174 	/* newer loop-control stuff */
    175 	case LOOP_CTL_GET_FREE:
    176 		/* Takes no arguments */
    177 		break;
    178 
    179 	case LOOP_SET_FD:
    180 	case LOOP_CHANGE_FD:
    181 		tprints(", ");
    182 		printfd(tcp, arg);
    183 		break;
    184 
    185 	/* newer loop-control stuff */
    186 	case LOOP_CTL_ADD:
    187 	case LOOP_CTL_REMOVE:
    188 		tprintf(", %d", (int) arg);
    189 		break;
    190 
    191 	case LOOP_SET_DIRECT_IO:
    192 	case LOOP_SET_BLOCK_SIZE:
    193 		tprintf(", %" PRI_klu, arg);
    194 		break;
    195 
    196 	default:
    197 		return RVAL_DECODED;
    198 	}
    199 
    200 	return RVAL_IOCTL_DECODED;
    201 }
    202