(root)/
strace-6.5/
tests-mx32/
faccessat2.c
       1  /*
       2   * Check decoding of faccessat2 syscall.
       3   *
       4   * Copyright (c) 2016-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 "scno.h"
      12  
      13  #include "xmalloc.h"
      14  #include <fcntl.h>
      15  #include <stdio.h>
      16  #include <unistd.h>
      17  
      18  #define XLAT_MACROS_ONLY
      19  # include "xlat/faccessat_flags.h"
      20  #undef XLAT_MACROS_ONLY
      21  
      22  #ifndef FD_PATH
      23  # define FD_PATH ""
      24  #else
      25  # define YFLAG
      26  #endif
      27  #ifndef SKIP_IF_PROC_IS_UNAVAILABLE
      28  # define SKIP_IF_PROC_IS_UNAVAILABLE
      29  #endif
      30  
      31  static const char *errstr;
      32  
      33  static long
      34  k_faccessat2(const unsigned int dirfd,
      35  	     const void *const pathname,
      36  	     const unsigned int mode,
      37  	     const unsigned int flags)
      38  {
      39  	const kernel_ulong_t fill = (kernel_ulong_t) 0xdefaced00000000ULL;
      40  	const kernel_ulong_t bad = (kernel_ulong_t) 0xbadc0dedbadc0dedULL;
      41  
      42  	const kernel_ulong_t arg1 = fill | dirfd;
      43  	const kernel_ulong_t arg2 = (uintptr_t) pathname;
      44  	const kernel_ulong_t arg3 = fill | mode;
      45  	const kernel_ulong_t arg4 = fill | flags;
      46  	const long rc = syscall(__NR_faccessat2,
      47  				arg1, arg2, arg3, arg4, bad, bad);
      48  	errstr = sprintrc(rc);
      49  	return rc;
      50  }
      51  
      52  int
      53  main(void)
      54  {
      55  	SKIP_IF_PROC_IS_UNAVAILABLE;
      56  
      57  	TAIL_ALLOC_OBJECT_CONST_PTR(const char, unterminated);
      58  	char *unterminated_str = xasprintf("%p", unterminated);
      59  	const void *const efault = unterminated + 1;
      60  	char *efault_str = xasprintf("%p", efault);
      61  
      62  	typedef struct {
      63  		char sym;
      64  		char null;
      65  	} sym_null;
      66  
      67  	TAIL_ALLOC_OBJECT_CONST_PTR(sym_null, dot);
      68  	dot->sym = '.';
      69  	dot->null = '\0';
      70  	const char *const null = &dot->null;
      71  
      72  	TAIL_ALLOC_OBJECT_CONST_PTR(sym_null, slash);
      73  	slash->sym = '/';
      74  	slash->null = '\0';
      75  
      76  	static const char path[] = "/dev/full";
      77  	const char *const fd_path = tail_memdup(path, sizeof(path));
      78          int fd = open(path, O_WRONLY);
      79          if (fd < 0)
      80                  perror_msg_and_fail("open: %s", path);
      81  	char *fd_str = xasprintf("%d%s", fd, FD_PATH);
      82  	const char *at_fdcwd_str =
      83  #ifdef YFLAG
      84  		xasprintf("AT_FDCWD<%s>", get_fd_path(get_dir_fd(".")));
      85  #else
      86  		"AT_FDCWD";
      87  #endif
      88  
      89  	char *path_quoted = xasprintf("\"%s\"", path);
      90  
      91  	struct {
      92  		int val;
      93  		const char *str;
      94  	} dirfds[] = {
      95  		{ ARG_STR(-1) },
      96  		{ -100, at_fdcwd_str },
      97  		{ fd, fd_str },
      98  	}, modes[] = {
      99  		{ ARG_STR(F_OK) },
     100  		{ ARG_STR(R_OK) },
     101  		{ ARG_STR(W_OK) },
     102  		{ ARG_STR(X_OK) },
     103  		{ ARG_STR(R_OK|W_OK) },
     104  		{ ARG_STR(R_OK|X_OK) },
     105  		{ ARG_STR(W_OK|X_OK) },
     106  		{ ARG_STR(R_OK|W_OK|X_OK) },
     107  		{ 8, "0x8 /* ?_OK */" },
     108  		{ -1, "R_OK|W_OK|X_OK|0xfffffff8" },
     109  	}, flags[] = {
     110  		{ ARG_STR(0) },
     111  		{ ARG_STR(AT_SYMLINK_NOFOLLOW) },
     112  		{ ARG_STR(AT_EACCESS) },
     113  		{ ARG_STR(AT_EMPTY_PATH) },
     114  		{ ARG_STR(AT_SYMLINK_NOFOLLOW|AT_EACCESS) },
     115  		{ ARG_STR(AT_SYMLINK_NOFOLLOW|AT_EMPTY_PATH) },
     116  		{ ARG_STR(AT_EACCESS|AT_EMPTY_PATH) },
     117  		{ ARG_STR(AT_SYMLINK_NOFOLLOW|AT_EACCESS|AT_EMPTY_PATH) },
     118  		{ 1, "0x1 /* AT_??? */" },
     119  		{ -1, "AT_SYMLINK_NOFOLLOW|AT_EACCESS|AT_EMPTY_PATH|0xffffecff" },
     120  	};
     121  
     122  	struct {
     123  		const void *val;
     124  		const char *str;
     125  	} paths[] = {
     126  		{ 0, "NULL" },
     127  		{ efault, efault_str },
     128  		{ unterminated, unterminated_str },
     129  		{ null, "\"\"" },
     130  		{ &dot->sym, "\".\"" },
     131  		{ &slash->sym, "\"/\"" },
     132  		{ fd_path, path_quoted },
     133  	};
     134  
     135  	for (unsigned int dirfd_i = 0;
     136  	     dirfd_i < ARRAY_SIZE(dirfds);
     137  	     ++dirfd_i) {
     138  		for (unsigned int path_i = 0;
     139  		     path_i < ARRAY_SIZE(paths);
     140  		     ++path_i) {
     141  			for (unsigned int mode_i = 0;
     142  			     mode_i < ARRAY_SIZE(modes);
     143  			     ++mode_i) {
     144  				for (unsigned int flag_i = 0;
     145  				     flag_i < ARRAY_SIZE(flags);
     146  				     ++flag_i) {
     147  					k_faccessat2(dirfds[dirfd_i].val,
     148  						    paths[path_i].val,
     149  						    modes[mode_i].val,
     150  						    flags[flag_i].val);
     151  #ifdef PATH_TRACING
     152  					if (dirfds[dirfd_i].val == fd ||
     153  					    paths[path_i].val == fd_path)
     154  #endif
     155  					printf("faccessat2(%s, %s, %s, %s) = %s\n",
     156  					       dirfds[dirfd_i].str,
     157  					       paths[path_i].str,
     158  					       modes[mode_i].str,
     159  					       flags[flag_i].str,
     160  					       errstr);
     161  				}
     162  			}
     163  		}
     164  	}
     165  
     166  	puts("+++ exited with 0 +++");
     167  	return 0;
     168  }