(root)/
strace-6.5/
tests-mx32/
faccessat.c
       1  /*
       2   * Check decoding of faccessat 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  #ifdef __NR_faccessat
      14  
      15  # include <fcntl.h>
      16  # include <stdio.h>
      17  # include <unistd.h>
      18  
      19  # include "secontext.h"
      20  # include "xmalloc.h"
      21  
      22  # ifdef FD_PATH
      23  #  define YFLAG
      24  # else
      25  #  define FD_PATH ""
      26  # endif
      27  # ifndef SKIP_IF_PROC_IS_UNAVAILABLE
      28  #  define SKIP_IF_PROC_IS_UNAVAILABLE
      29  # endif
      30  
      31  # ifdef YFLAG
      32  #  define AT_FDCWD_FMT "<%s>"
      33  #  define AT_FDCWD_ARG(arg) arg,
      34  # else
      35  #  define AT_FDCWD_FMT
      36  #  define AT_FDCWD_ARG(arg)
      37  # endif
      38  
      39  static const char *errstr;
      40  
      41  static long
      42  k_faccessat(const unsigned int dirfd,
      43  	    const void *const pathname,
      44  	    const unsigned int mode)
      45  {
      46  	const kernel_ulong_t fill = (kernel_ulong_t) 0xdefaced00000000ULL;
      47  	const kernel_ulong_t bad = (kernel_ulong_t) 0xbadc0dedbadc0dedULL;
      48  
      49  	const kernel_ulong_t arg1 = fill | dirfd;
      50  	const kernel_ulong_t arg2 = (uintptr_t) pathname;
      51  	const kernel_ulong_t arg3 = fill | mode;
      52  	const long rc = syscall(__NR_faccessat,
      53  				arg1, arg2, arg3, bad, bad, bad);
      54  	errstr = sprintrc(rc);
      55  	return rc;
      56  }
      57  
      58  # ifndef PATH_TRACING
      59  static void
      60  tests_with_existing_file(void)
      61  {
      62  	/*
      63  	 * Make sure the current workdir of the tracee
      64  	 * is different from the current workdir of the tracer.
      65  	 */
      66  	create_and_enter_subdir("faccessat_subdir");
      67  
      68  	int cwd_fd = get_dir_fd(".");
      69  	char *cwd = get_fd_path(cwd_fd);
      70  
      71  	char *my_secontext = SECONTEXT_PID_MY();
      72  
      73  	k_faccessat(-1, NULL, F_OK);
      74  	printf("%s%s(-1, NULL, F_OK) = %s\n",
      75  	       my_secontext, "faccessat", errstr);
      76  
      77  	static const char sample[] = "faccessat_sample";
      78  	(void) unlink(sample);
      79  	int fd = open(sample, O_CREAT|O_RDONLY, 0400);
      80  	if (fd == -1)
      81  		perror_msg_and_fail("open");
      82  	close(fd);
      83  	char *sample_secontext = SECONTEXT_FILE(sample);
      84  
      85  	/*
      86  	 * Tests with AT_FDCWD.
      87  	 */
      88  
      89  	k_faccessat(-100, sample, F_OK);
      90  	printf("%s%s(AT_FDCWD" AT_FDCWD_FMT ", \"%s\"%s, F_OK) = %s\n",
      91  	       my_secontext, "faccessat",
      92  	       AT_FDCWD_ARG(cwd)
      93  	       sample, sample_secontext,
      94  	       errstr);
      95  
      96  	if (unlink(sample))
      97  		perror_msg_and_fail("unlink");
      98  
      99  	k_faccessat(-100, sample, F_OK);
     100  	printf("%s%s(AT_FDCWD" AT_FDCWD_FMT ", \"%s\", F_OK) = %s\n",
     101  	       my_secontext, "faccessat",
     102  	       AT_FDCWD_ARG(cwd)
     103  	       sample,
     104  	       errstr);
     105  
     106  	/*
     107  	 * Tests with dirfd.
     108  	 */
     109  
     110  	char *cwd_secontext = SECONTEXT_FILE(".");
     111  	char *sample_realpath = xasprintf("%s/%s", cwd, sample);
     112  
     113  	/* no file */
     114  	k_faccessat(cwd_fd, sample, F_OK);
     115  #  ifdef YFLAG
     116  	printf("%s%s(%d<%s>%s, \"%s\", F_OK) = %s\n",
     117  #  else
     118  	printf("%s%s(%d%s, \"%s\", F_OK) = %s\n",
     119  #  endif
     120  	       my_secontext, "faccessat",
     121  	       cwd_fd,
     122  #  ifdef YFLAG
     123  	       cwd,
     124  #  endif
     125  	       cwd_secontext,
     126  	       sample,
     127  	       errstr);
     128  
     129  	fd = open(sample, O_CREAT|O_RDONLY, 0400);
     130  	if (fd == -1)
     131  		perror_msg_and_fail("open");
     132  	close(fd);
     133  
     134  	k_faccessat(cwd_fd, sample, F_OK);
     135  #  ifdef YFLAG
     136  	printf("%s%s(%d<%s>%s, \"%s\"%s, F_OK) = %s\n",
     137  #  else
     138  	printf("%s%s(%d%s, \"%s\"%s, F_OK) = %s\n",
     139  #  endif
     140  	       my_secontext, "faccessat",
     141  	       cwd_fd,
     142  #  ifdef YFLAG
     143  	       cwd,
     144  #  endif
     145  	       cwd_secontext,
     146  	       sample, sample_secontext,
     147  	       errstr);
     148  
     149  	/* cwd_fd ignored when path is absolute */
     150  	if (chdir("../.."))
     151  		perror_msg_and_fail("chdir");
     152  
     153  	k_faccessat(cwd_fd, sample_realpath, F_OK);
     154  #  ifdef YFLAG
     155  	printf("%s%s(%d<%s>%s, \"%s\"%s, F_OK) = %s\n",
     156  #  else
     157  	printf("%s%s(%d%s, \"%s\"%s, F_OK) = %s\n",
     158  #  endif
     159  	       my_secontext, "faccessat",
     160  	       cwd_fd,
     161  #  ifdef YFLAG
     162  	       cwd,
     163  #  endif
     164  	       cwd_secontext,
     165  	       sample_realpath, sample_secontext,
     166  	       errstr);
     167  
     168  	if (fchdir(cwd_fd))
     169  		perror_msg_and_fail("fchdir");
     170  
     171  	if (unlink(sample))
     172  		perror_msg_and_fail("unlink");
     173  
     174  	leave_and_remove_subdir();
     175  }
     176  # endif
     177  
     178  int
     179  main(void)
     180  {
     181  	SKIP_IF_PROC_IS_UNAVAILABLE;
     182  
     183  # ifndef TEST_SECONTEXT
     184  
     185  	TAIL_ALLOC_OBJECT_CONST_PTR(const char, unterminated);
     186  	char *unterminated_str = xasprintf("%p", unterminated);
     187  	const void *const efault = unterminated + 1;
     188  	char *efault_str = xasprintf("%p", efault);
     189  
     190  	typedef struct {
     191  		char sym;
     192  		char null;
     193  	} sym_null;
     194  
     195  	TAIL_ALLOC_OBJECT_CONST_PTR(sym_null, dot);
     196  	dot->sym = '.';
     197  	dot->null = '\0';
     198  	const char *const null = &dot->null;
     199  
     200  	TAIL_ALLOC_OBJECT_CONST_PTR(sym_null, slash);
     201  	slash->sym = '/';
     202  	slash->null = '\0';
     203  
     204  	static const char path[] = "/dev/full";
     205  	const char *const fd_path = tail_memdup(path, sizeof(path));
     206          int fd = open(path, O_WRONLY);
     207          if (fd < 0)
     208                  perror_msg_and_fail("open: %s", path);
     209  	char *fd_str = xasprintf("%d%s", fd, FD_PATH);
     210  	const char *at_fdcwd_str =
     211  #  ifdef YFLAG
     212  		xasprintf("AT_FDCWD<%s>", get_fd_path(get_dir_fd(".")));
     213  #  else
     214  		"AT_FDCWD";
     215  #  endif
     216  	char *path_quoted = xasprintf("\"%s\"", path);
     217  
     218  	struct {
     219  		int val;
     220  		const char *str;
     221  	} dirfds[] = {
     222  		{ ARG_STR(-1) },
     223  		{ -100, at_fdcwd_str },
     224  		{ fd, fd_str },
     225  	}, modes[] = {
     226  		{ ARG_STR(F_OK) },
     227  		{ ARG_STR(R_OK) },
     228  		{ ARG_STR(W_OK) },
     229  		{ ARG_STR(X_OK) },
     230  		{ ARG_STR(R_OK|W_OK) },
     231  		{ ARG_STR(R_OK|X_OK) },
     232  		{ ARG_STR(W_OK|X_OK) },
     233  		{ ARG_STR(R_OK|W_OK|X_OK) },
     234  		{ 8, "0x8 /* ?_OK */" },
     235  		{ -1, "R_OK|W_OK|X_OK|0xfffffff8" },
     236  	};
     237  
     238  	struct {
     239  		const void *val;
     240  		const char *str;
     241  	} paths[] = {
     242  		{ 0, "NULL" },
     243  		{ efault, efault_str },
     244  		{ unterminated, unterminated_str },
     245  		{ null, "\"\"" },
     246  		{ &dot->sym, "\".\"" },
     247  		{ &slash->sym, "\"/\"" },
     248  		{ fd_path, path_quoted },
     249  	};
     250  
     251  	for (unsigned int dirfd_i = 0;
     252  	     dirfd_i < ARRAY_SIZE(dirfds);
     253  	     ++dirfd_i) {
     254  		for (unsigned int path_i = 0;
     255  		     path_i < ARRAY_SIZE(paths);
     256  		     ++path_i) {
     257  			for (unsigned int mode_i = 0;
     258  			     mode_i < ARRAY_SIZE(modes);
     259  			     ++mode_i) {
     260  				k_faccessat(dirfds[dirfd_i].val,
     261  					    paths[path_i].val,
     262  					    modes[mode_i].val);
     263  #  ifdef PATH_TRACING
     264  				if (dirfds[dirfd_i].val == fd ||
     265  				    paths[path_i].val == fd_path)
     266  #  endif
     267  				printf("faccessat(%s, %s, %s) = %s\n",
     268  				       dirfds[dirfd_i].str,
     269  				       paths[path_i].str,
     270  				       modes[mode_i].str,
     271  				       errstr);
     272  			}
     273  		}
     274  	}
     275  
     276  # endif /* !TEST_SECONTEXT */
     277  
     278  # ifndef PATH_TRACING
     279  	tests_with_existing_file();
     280  # endif
     281  
     282  	puts("+++ exited with 0 +++");
     283  	return 0;
     284  }
     285  
     286  #else
     287  
     288  SKIP_MAIN_UNDEFINED("__NR_faccessat")
     289  
     290  #endif