(root)/
strace-6.5/
tests-mx32/
ioctl_fs_x.c
       1  /*
       2   * Check decoding of linux/fs.h 'X' ioctl commands.
       3   *
       4   * Copyright (c) 2020-2021 The strace developers.
       5   * All rights reserved.
       6   *
       7   * SPDX-License-Identifier: GPL-2.0-or-later
       8   */
       9  
      10  #include "tests.h"
      11  #include <linux/fs.h>
      12  
      13  #include <errno.h>
      14  #include <stdio.h>
      15  #include <stdlib.h>
      16  #include <sys/ioctl.h>
      17  
      18  static const char *errstr;
      19  
      20  static int
      21  do_ioctl(kernel_ulong_t cmd, kernel_ulong_t arg)
      22  {
      23  	int rc = ioctl(-1, cmd, arg);
      24  	errstr = sprintrc(rc);
      25  
      26  #ifdef INJECT_RETVAL
      27  	if (rc != INJECT_RETVAL)
      28  		error_msg_and_fail("Return value [%d] does not match"
      29  				   " expectations [%d]", rc, INJECT_RETVAL);
      30  
      31  	static char inj_errstr[4096];
      32  
      33  	snprintf(inj_errstr, sizeof(inj_errstr), "%s (INJECTED)", errstr);
      34  	errstr = inj_errstr;
      35  #endif
      36  
      37  	return rc;
      38  }
      39  
      40  static int
      41  do_ioctl_ptr(kernel_ulong_t cmd, const void *arg)
      42  {
      43  	return do_ioctl(cmd, (uintptr_t) arg);
      44  }
      45  
      46  #ifdef INJECT_RETVAL
      47  static void
      48  skip_ioctls(int argc, const char *argv[])
      49  {
      50  	if (argc < 2)
      51  		error_msg_and_fail("Usage: %s NUM_SKIP", argv[0]);
      52  
      53  	unsigned long num_skip = strtoul(argv[1], NULL, 0);
      54  
      55  	for (size_t i = 0; i < num_skip; ++i) {
      56  		int rc = ioctl(-1, FIFREEZE, 0);
      57  
      58  		printf("ioctl(-1, %s) = %s%s\n",
      59  		       XLAT_STR(FIFREEZE), sprintrc(rc),
      60  		       rc == INJECT_RETVAL ? " (INJECTED)" : "");
      61  
      62  		if (rc == INJECT_RETVAL)
      63  			return;
      64  	}
      65  
      66  	error_msg_and_fail("Issued %lu ioctl syscalls but failed"
      67  			   " to detect an injected return code %d",
      68  			   num_skip, INJECT_RETVAL);
      69  }
      70  #endif /* INJECT_RETVAL */
      71  
      72  int
      73  main(int argc, const char *argv[])
      74  {
      75  #ifdef INJECT_RETVAL
      76  	skip_ioctls(argc, argv);
      77  #endif
      78  
      79  	static const struct {
      80  		uint32_t cmd;
      81  		const char *str;
      82  		bool has_arg;
      83  	} simple_cmds[] = {
      84  		{ ARG_STR(FIFREEZE), false },
      85  		{ ARG_STR(FITHAW), false },
      86  		{ _IO('X', 0xff), "_IOC(_IOC_NONE, 0x58, 0xff, 0)", true },
      87  	};
      88  
      89  	for (size_t i = 0; i < ARRAY_SIZE(simple_cmds); ++i) {
      90  		do_ioctl(simple_cmds[i].cmd, 0);
      91  		if (simple_cmds[i].has_arg) {
      92  			printf("ioctl(-1, " XLAT_FMT ", 0) = %s\n",
      93  			       XLAT_SEL(simple_cmds[i].cmd, simple_cmds[i].str),
      94  			       errstr);
      95  		} else {
      96  			printf("ioctl(-1, " XLAT_FMT ") = %s\n",
      97  			       XLAT_SEL(simple_cmds[i].cmd, simple_cmds[i].str),
      98  			       errstr);
      99  		}
     100  
     101  		static const unsigned long arg =
     102  			(unsigned long) 0xbadc0deddeadc0deULL;
     103  
     104  		do_ioctl(simple_cmds[i].cmd, arg);
     105  		if (simple_cmds[i].has_arg) {
     106  			printf("ioctl(-1, " XLAT_FMT ", %#lx) = %s\n",
     107  			       XLAT_SEL(simple_cmds[i].cmd, simple_cmds[i].str),
     108  			       arg, errstr);
     109  		} else {
     110  			printf("ioctl(-1, " XLAT_FMT ") = %s\n",
     111  			       XLAT_SEL(simple_cmds[i].cmd, simple_cmds[i].str),
     112  			       errstr);
     113  		}
     114  	}
     115  
     116  	static const struct {
     117  		uint32_t cmd;
     118  		const char *str;
     119  	} null_arg_cmds[] = {
     120  		{ ARG_STR(FITRIM) },
     121  		{ ARG_STR(FS_IOC_FSSETXATTR) },
     122  		{ ARG_STR(FS_IOC_FSGETXATTR) },
     123  	};
     124  
     125  	for (size_t i = 0; i < ARRAY_SIZE(null_arg_cmds); ++i) {
     126  		do_ioctl(null_arg_cmds[i].cmd, 0);
     127  		printf("ioctl(-1, " XLAT_FMT ", NULL) = %s\n",
     128  		       XLAT_SEL(null_arg_cmds[i].cmd, null_arg_cmds[i].str),
     129  		       errstr);
     130  	}
     131  
     132  	TAIL_ALLOC_OBJECT_CONST_PTR(struct fstrim_range, p_range);
     133  
     134  	do_ioctl_ptr(FITRIM, (char *) p_range + 1);
     135  	printf("ioctl(-1, %s, %p) = %s\n",
     136  	       XLAT_STR(FITRIM), (char *) p_range + 1, errstr);
     137  
     138  	p_range->start = (typeof(p_range->start)) 0xdeadbeefcafef00dULL;
     139  	p_range->len = (typeof(p_range->len)) 0xfacefeedbabec0deULL;
     140  	p_range->minlen = (typeof(p_range->minlen)) 0xbadc0deddeadc0deULL;
     141  
     142  	do_ioctl_ptr(FITRIM, p_range);
     143  	printf("ioctl(-1, %s, {start=%#jx, len=%ju, minlen=%ju}) = %s\n",
     144  	       XLAT_STR(FITRIM), (uintmax_t) p_range->start,
     145  	       (uintmax_t) p_range->len, (uintmax_t) p_range->minlen,
     146  	       errstr);
     147  
     148  	/* FS_IOC_FSSETXATTR */
     149  	TAIL_ALLOC_OBJECT_CONST_PTR(struct fsxattr, p_fsxattr);
     150  
     151  	do_ioctl_ptr(FS_IOC_FSSETXATTR, (char *) p_fsxattr + 1);
     152  	printf("ioctl(-1, %s, %p) = %s\n",
     153  	       XLAT_STR(FS_IOC_FSSETXATTR), (char *) p_fsxattr + 1, errstr);
     154  
     155  #define VALID_FSX_XFLAGS 0x8001fffb
     156  #define INVALID_FSX_XFLAGS 0x7ffe0004
     157  
     158  	p_fsxattr->fsx_xflags = VALID_FSX_XFLAGS;
     159  	p_fsxattr->fsx_extsize = 0xdeadbeefU;
     160  	p_fsxattr->fsx_projid = 0xcafef00dU;
     161  	p_fsxattr->fsx_cowextsize = 0xbabec0deU;
     162  
     163  	do_ioctl_ptr(FS_IOC_FSSETXATTR, p_fsxattr);
     164  	printf("ioctl(-1, %s, {fsx_xflags=%s, fsx_extsize=%u, fsx_projid=%#x"
     165  	       ", fsx_cowextsize=%u}) = %s\n",
     166  	       XLAT_STR(FS_IOC_FSSETXATTR),
     167  	       XLAT_KNOWN(VALID_FSX_XFLAGS,
     168  			  "FS_XFLAG_REALTIME|FS_XFLAG_PREALLOC|"
     169  			  "FS_XFLAG_IMMUTABLE|FS_XFLAG_APPEND|"
     170  			  "FS_XFLAG_SYNC|FS_XFLAG_NOATIME|"
     171  			  "FS_XFLAG_NODUMP|FS_XFLAG_RTINHERIT|"
     172  			  "FS_XFLAG_PROJINHERIT|FS_XFLAG_NOSYMLINKS|"
     173  			  "FS_XFLAG_EXTSIZE|FS_XFLAG_EXTSZINHERIT|"
     174  			  "FS_XFLAG_NODEFRAG|FS_XFLAG_FILESTREAM|"
     175  			  "FS_XFLAG_DAX|FS_XFLAG_COWEXTSIZE|FS_XFLAG_HASATTR"),
     176  	       p_fsxattr->fsx_extsize,
     177  	       p_fsxattr->fsx_projid,
     178  	       p_fsxattr->fsx_cowextsize,
     179  	       errstr);
     180  
     181  	p_fsxattr->fsx_xflags = ~p_fsxattr->fsx_xflags;
     182  
     183  	do_ioctl_ptr(FS_IOC_FSSETXATTR, p_fsxattr);
     184  	printf("ioctl(-1, %s, {fsx_xflags=%s, fsx_extsize=%u, fsx_projid=%#x"
     185  	       ", fsx_cowextsize=%u}) = %s\n",
     186  	       XLAT_STR(FS_IOC_FSSETXATTR),
     187  	       XLAT_UNKNOWN(INVALID_FSX_XFLAGS, "FS_XFLAG_???"),
     188  	       p_fsxattr->fsx_extsize,
     189  	       p_fsxattr->fsx_projid,
     190  	       p_fsxattr->fsx_cowextsize,
     191  	       errstr);
     192  
     193  	/* FS_IOC_FSGETXATTR */
     194  	do_ioctl_ptr(FS_IOC_FSGETXATTR, (char *) p_fsxattr + 1);
     195  	printf("ioctl(-1, %s, %p) = %s\n",
     196  	       XLAT_STR(FS_IOC_FSGETXATTR), (char *) p_fsxattr + 1, errstr);
     197  
     198  	p_fsxattr->fsx_xflags = VALID_FSX_XFLAGS;
     199  	p_fsxattr->fsx_nextents = 0xfacefeedU;
     200  
     201  	if (do_ioctl_ptr(FS_IOC_FSGETXATTR, p_fsxattr) < 0) {
     202  		printf("ioctl(-1, %s, %p) = %s\n",
     203  		       XLAT_STR(FS_IOC_FSGETXATTR), p_fsxattr, errstr);
     204  	} else {
     205  		printf("ioctl(-1, %s, {fsx_xflags=%s, fsx_extsize=%u"
     206  		       ", fsx_nextents=%u, fsx_projid=%#x"
     207  		       ", fsx_cowextsize=%u}) = %s\n",
     208  		       XLAT_STR(FS_IOC_FSGETXATTR),
     209  		       XLAT_KNOWN(VALID_FSX_XFLAGS,
     210  				  "FS_XFLAG_REALTIME|FS_XFLAG_PREALLOC|"
     211  				  "FS_XFLAG_IMMUTABLE|FS_XFLAG_APPEND|"
     212  				  "FS_XFLAG_SYNC|FS_XFLAG_NOATIME|"
     213  				  "FS_XFLAG_NODUMP|FS_XFLAG_RTINHERIT|"
     214  				  "FS_XFLAG_PROJINHERIT|FS_XFLAG_NOSYMLINKS|"
     215  				  "FS_XFLAG_EXTSIZE|FS_XFLAG_EXTSZINHERIT|"
     216  				  "FS_XFLAG_NODEFRAG|FS_XFLAG_FILESTREAM|"
     217  				  "FS_XFLAG_DAX|FS_XFLAG_COWEXTSIZE|FS_XFLAG_HASATTR"),
     218  		       p_fsxattr->fsx_extsize,
     219  		       p_fsxattr->fsx_nextents,
     220  		       p_fsxattr->fsx_projid,
     221  		       p_fsxattr->fsx_cowextsize,
     222  		       errstr);
     223  	}
     224  
     225  	p_fsxattr->fsx_xflags = ~p_fsxattr->fsx_xflags;
     226  
     227  	if (do_ioctl_ptr(FS_IOC_FSGETXATTR, p_fsxattr) < 0) {
     228  		printf("ioctl(-1, %s, %p) = %s\n",
     229  		       XLAT_STR(FS_IOC_FSGETXATTR), p_fsxattr, errstr);
     230  	} else {
     231  		printf("ioctl(-1, %s, {fsx_xflags=%s, fsx_extsize=%u"
     232  		       ", fsx_nextents=%u, fsx_projid=%#x"
     233  		       ", fsx_cowextsize=%u}) = %s\n",
     234  		       XLAT_STR(FS_IOC_FSGETXATTR),
     235  		       XLAT_UNKNOWN(INVALID_FSX_XFLAGS, "FS_XFLAG_???"),
     236  		       p_fsxattr->fsx_extsize,
     237  		       p_fsxattr->fsx_nextents,
     238  		       p_fsxattr->fsx_projid,
     239  		       p_fsxattr->fsx_cowextsize,
     240  		       errstr);
     241  	}
     242  
     243  	puts("+++ exited with 0 +++");
     244  	return 0;
     245  }