(root)/
strace-6.5/
src/
loop.c
       1  /*
       2   * Copyright (c) 2012 The Chromium OS Authors.
       3   * Copyright (c) 2012-2021 The strace developers.
       4   * Written by Mike Frysinger <vapier@gentoo.org>.
       5   *
       6   * SPDX-License-Identifier: LGPL-2.1-or-later
       7   */
       8  
       9  #include "defs.h"
      10  
      11  #include DEF_MPERS_TYPE(struct_loop_info)
      12  
      13  #include <linux/loop.h>
      14  
      15  typedef struct loop_info struct_loop_info;
      16  
      17  #include MPERS_DEFS
      18  
      19  #include "xlat/loop_flags_options.h"
      20  #include "xlat/loop_crypt_type_options.h"
      21  
      22  static void
      23  decode_loop_info(struct tcb *const tcp, const kernel_ulong_t addr)
      24  {
      25  	struct_loop_info info;
      26  
      27  	if (umove_or_printaddr(tcp, addr, &info))
      28  		return;
      29  
      30  	tprint_struct_begin();
      31  	PRINT_FIELD_D(info, lo_number);
      32  
      33  	if (!abbrev(tcp)) {
      34  		tprint_struct_next();
      35  		PRINT_FIELD_DEV(info, lo_device);
      36  		tprint_struct_next();
      37  		PRINT_FIELD_U(info, lo_inode);
      38  		tprint_struct_next();
      39  		PRINT_FIELD_DEV(info, lo_rdevice);
      40  	}
      41  
      42  	tprint_struct_next();
      43  	PRINT_FIELD_X(info, lo_offset);
      44  
      45  	if (!abbrev(tcp) || info.lo_encrypt_type != LO_CRYPT_NONE) {
      46  		tprint_struct_next();
      47  		PRINT_FIELD_XVAL(info, lo_encrypt_type,
      48  				 loop_crypt_type_options, "LO_CRYPT_???");
      49  		/*
      50  		 * It is converted to unsigned before use in the kernel,
      51  		 * see loop_info64_from_old in drivers/block/loop.c
      52  		 */
      53  		tprint_struct_next();
      54  		PRINT_FIELD_U(info, lo_encrypt_key_size);
      55  	}
      56  
      57  	tprint_struct_next();
      58  	PRINT_FIELD_FLAGS(info, lo_flags, loop_flags_options, "LO_FLAGS_???");
      59  
      60  	tprint_struct_next();
      61  	PRINT_FIELD_CSTRING(info, lo_name);
      62  
      63  	if (!abbrev(tcp) || info.lo_encrypt_type != LO_CRYPT_NONE) {
      64  		const unsigned int lo_encrypt_key_size =
      65  			MIN((unsigned) info.lo_encrypt_key_size, LO_KEY_SIZE);
      66  		tprint_struct_next();
      67  		PRINT_FIELD_STRING(info, lo_encrypt_key,
      68  				   lo_encrypt_key_size, 0);
      69  	}
      70  
      71  	if (!abbrev(tcp)) {
      72  		tprint_struct_next();
      73  		PRINT_FIELD_X_ARRAY(info, lo_init);
      74  		tprint_struct_next();
      75  		PRINT_FIELD_X_ARRAY(info, reserved);
      76  	} else {
      77  		tprint_struct_next();
      78  		tprint_more_data_follows();
      79  	}
      80  
      81  	tprint_struct_end();
      82  }
      83  
      84  static void
      85  print_loop_info64(struct tcb *const tcp, const struct loop_info64 *const info64)
      86  {
      87  	if (!abbrev(tcp)) {
      88  		tprint_struct_begin();
      89  		PRINT_FIELD_DEV(*info64, lo_device);
      90  		tprint_struct_next();
      91  		PRINT_FIELD_U(*info64, lo_inode);
      92  		tprint_struct_next();
      93  		PRINT_FIELD_DEV(*info64, lo_rdevice);
      94  		tprint_struct_next();
      95  		PRINT_FIELD_X(*info64, lo_offset);
      96  		tprint_struct_next();
      97  		PRINT_FIELD_U(*info64, lo_sizelimit);
      98  		tprint_struct_next();
      99  		PRINT_FIELD_U(*info64, lo_number);
     100  	} else {
     101  		tprint_struct_begin();
     102  		PRINT_FIELD_X(*info64, lo_offset);
     103  		tprint_struct_next();
     104  		PRINT_FIELD_U(*info64, lo_number);
     105  	}
     106  
     107  	if (!abbrev(tcp) || info64->lo_encrypt_type != LO_CRYPT_NONE) {
     108  		tprint_struct_next();
     109  		PRINT_FIELD_XVAL(*info64, lo_encrypt_type,
     110  				 loop_crypt_type_options, "LO_CRYPT_???");
     111  		tprint_struct_next();
     112  		PRINT_FIELD_U(*info64, lo_encrypt_key_size);
     113  	}
     114  
     115  	tprint_struct_next();
     116  	PRINT_FIELD_FLAGS(*info64, lo_flags, loop_flags_options, "LO_FLAGS_???");
     117  
     118  	tprint_struct_next();
     119  	PRINT_FIELD_CSTRING(*info64, lo_file_name);
     120  
     121  	if (!abbrev(tcp) || info64->lo_encrypt_type != LO_CRYPT_NONE) {
     122  		tprint_struct_next();
     123  		PRINT_FIELD_CSTRING(*info64, lo_crypt_name);
     124  		const unsigned int lo_encrypt_key_size =
     125  			MIN((unsigned) info64->lo_encrypt_key_size, LO_KEY_SIZE);
     126  		tprint_struct_next();
     127  		PRINT_FIELD_STRING(*info64, lo_encrypt_key,
     128  				   lo_encrypt_key_size, 0);
     129  	}
     130  
     131  	if (!abbrev(tcp)) {
     132  		tprint_struct_next();
     133  		PRINT_FIELD_X_ARRAY(*info64, lo_init);
     134  	} else {
     135  		tprint_struct_next();
     136  		tprint_more_data_follows();
     137  	}
     138  
     139  	tprint_struct_end();
     140  }
     141  
     142  static void
     143  decode_loop_info64(struct tcb *const tcp, const kernel_ulong_t addr)
     144  {
     145  	struct loop_info64 info64;
     146  
     147  	if (!umove_or_printaddr(tcp, addr, &info64))
     148  		print_loop_info64(tcp, &info64);
     149  }
     150  
     151  static void
     152  decode_loop_config(struct tcb *const tcp, const kernel_ulong_t addr)
     153  {
     154  	struct loop_config config;
     155  
     156  	if (umove_or_printaddr(tcp, addr, &config))
     157  		return;
     158  
     159  	tprint_struct_begin();
     160  	PRINT_FIELD_FD(config, fd, tcp);
     161  
     162  	tprint_struct_next();
     163  	PRINT_FIELD_U(config, block_size);
     164  
     165  	tprint_struct_next();
     166  	PRINT_FIELD_OBJ_TCB_PTR(config, info, tcp, print_loop_info64);
     167  
     168  	if (!IS_ARRAY_ZERO(config.__reserved)) {
     169  		tprint_struct_next();
     170  		PRINT_FIELD_X_ARRAY(config, __reserved);
     171  	}
     172  
     173  	tprint_struct_end();
     174  }
     175  
     176  MPERS_PRINTER_DECL(int, loop_ioctl,
     177  		   struct tcb *tcp, const unsigned int code,
     178  		   const kernel_ulong_t arg)
     179  {
     180  	switch (code) {
     181  	case LOOP_GET_STATUS:
     182  		if (entering(tcp))
     183  			return 0;
     184  		ATTRIBUTE_FALLTHROUGH;
     185  	case LOOP_SET_STATUS:
     186  		tprint_arg_next();
     187  		decode_loop_info(tcp, arg);
     188  		break;
     189  
     190  	case LOOP_GET_STATUS64:
     191  		if (entering(tcp))
     192  			return 0;
     193  		ATTRIBUTE_FALLTHROUGH;
     194  	case LOOP_SET_STATUS64:
     195  		tprint_arg_next();
     196  		decode_loop_info64(tcp, arg);
     197  		break;
     198  
     199  	case LOOP_CONFIGURE:
     200  		tprint_arg_next();
     201  		decode_loop_config(tcp, arg);
     202  		break;
     203  
     204  	case LOOP_CLR_FD:
     205  	case LOOP_SET_CAPACITY:
     206  	/* newer loop-control stuff */
     207  	case LOOP_CTL_GET_FREE:
     208  		/* Takes no arguments */
     209  		break;
     210  
     211  	case LOOP_SET_FD:
     212  	case LOOP_CHANGE_FD:
     213  		tprint_arg_next();
     214  		printfd(tcp, arg);
     215  		break;
     216  
     217  	/* newer loop-control stuff */
     218  	case LOOP_CTL_ADD:
     219  	case LOOP_CTL_REMOVE:
     220  		tprint_arg_next();
     221  		PRINT_VAL_D((int) arg);
     222  		break;
     223  
     224  	case LOOP_SET_DIRECT_IO:
     225  	case LOOP_SET_BLOCK_SIZE:
     226  		tprint_arg_next();
     227  		PRINT_VAL_U(arg);
     228  		break;
     229  
     230  	default:
     231  		return RVAL_DECODED;
     232  	}
     233  
     234  	return RVAL_IOCTL_DECODED;
     235  }