(root)/
strace-6.5/
tests/
execveat.c
       1  /*
       2   * This file is part of execveat strace test.
       3   *
       4   * Copyright (c) 2015-2016 Dmitry V. Levin <ldv@strace.io>
       5   * Copyright (c) 2015-2021 The strace developers.
       6   * All rights reserved.
       7   *
       8   * SPDX-License-Identifier: GPL-2.0-or-later
       9   */
      10  
      11  #include "tests.h"
      12  #include "scno.h"
      13  
      14  #ifdef __NR_execveat
      15  
      16  # include <fcntl.h>
      17  # include <stdio.h>
      18  # include <unistd.h>
      19  
      20  # include "secontext.h"
      21  
      22  static void
      23  tests_with_existing_file(void)
      24  {
      25  	/*
      26  	 * Make sure the current workdir of the tracee
      27  	 * is different from the current workdir of the tracer.
      28  	 */
      29  	create_and_enter_subdir("execveat_subdir");
      30  
      31  	char *my_secontext = SECONTEXT_PID_MY();
      32  
      33  	static const char sample[] = "execveat_sample";
      34  	(void) unlink(sample);
      35  	if (open(sample, O_RDONLY | O_CREAT, 0400) < 0)
      36  		perror_msg_and_fail("open");
      37  
      38  	char *sample_secontext = SECONTEXT_FILE(sample);
      39  	static const char *argv[] = { sample, NULL };
      40  
      41  	/*
      42  	 * Tests with AT_FDCWD.
      43  	 */
      44  
      45  	long rc = syscall(__NR_execveat, -100, sample, argv, NULL, 0);
      46  	printf("%s%s(AT_FDCWD, \"%s\"%s, [\"%s\"], NULL, 0) = %s\n",
      47  	       my_secontext, "execveat",
      48  	       sample, sample_secontext,
      49  	       argv[0],
      50  	       sprintrc(rc));
      51  
      52  	if (unlink(sample))
      53  		perror_msg_and_fail("unlink");
      54  
      55  	rc = syscall(__NR_execveat, -100, sample, argv, NULL, 0);
      56  	printf("%s%s(AT_FDCWD, \"%s\", [\"%s\"], NULL, 0) = %s\n",
      57  	       my_secontext, "execveat",
      58  	       sample,
      59  	       argv[0],
      60  	       sprintrc(rc));
      61  
      62  	/*
      63  	 * Tests with dirfd.
      64  	 */
      65  
      66  	int cwd_fd = get_dir_fd(".");
      67  	char *cwd = get_fd_path(cwd_fd);
      68  	char *cwd_secontext = SECONTEXT_FILE(".");
      69  	char *sample_realpath = xasprintf("%s/%s", cwd, sample);
      70  
      71  	/* no file */
      72  	rc = syscall(__NR_execveat, cwd_fd, sample, argv, NULL, 0);
      73  	printf("%s%s(%d%s, \"%s\", [\"%s\"], NULL, 0) = %s\n",
      74  	       my_secontext, "execveat",
      75  	       cwd_fd, cwd_secontext,
      76  	       sample,
      77  	       argv[0],
      78  	       sprintrc(rc));
      79  
      80  	if (open(sample, O_RDONLY | O_CREAT, 0400) < 0)
      81  		perror_msg_and_fail("open");
      82  
      83  	rc = syscall(__NR_execveat, cwd_fd, sample, argv, NULL, 0);
      84  	printf("%s%s(%d%s, \"%s\"%s, [\"%s\"], NULL, 0) = %s\n",
      85  	       my_secontext, "execveat",
      86  	       cwd_fd, cwd_secontext,
      87  	       sample, sample_secontext,
      88  	       argv[0],
      89  	       sprintrc(rc));
      90  
      91  	/* cwd_fd ignored when path is absolute */
      92  	if (chdir("../.."))
      93  		perror_msg_and_fail("chdir");
      94  
      95  	rc = syscall(__NR_execveat, cwd_fd, sample_realpath, argv, NULL, 0);
      96  	printf("%s%s(%d%s, \"%s\"%s, [\"%s\"], NULL, 0) = %s\n",
      97  	       my_secontext, "execveat",
      98  	       cwd_fd, cwd_secontext,
      99  	       sample_realpath, sample_secontext,
     100  	       argv[0],
     101  	       sprintrc(rc));
     102  
     103  	if (fchdir(cwd_fd))
     104  		perror_msg_and_fail("fchdir");
     105  
     106  	if (unlink(sample))
     107  		perror_msg_and_fail("unlink");
     108  
     109  	leave_and_remove_subdir();
     110  }
     111  
     112  # define FILENAME "test.execveat\nfilename"
     113  # define Q_FILENAME "test.execveat\\nfilename"
     114  
     115  static const char * const argv[] = {
     116  	FILENAME, "first", "second", (const char *) -1L,
     117  	(const char *) -2L, (const char *) -3L
     118  };
     119  static const char * const q_argv[] = {
     120  	Q_FILENAME, "first", "second"
     121  };
     122  
     123  static const char * const envp[] = {
     124  	"foobar=1", "foo\nbar=2", (const char *) -1L,
     125  	(const char *) -2L, (const char *) -3L
     126  };
     127  static const char * const q_envp[] = {
     128  	"foobar=1", "foo\\nbar=2"
     129  };
     130  
     131  int
     132  main(void)
     133  {
     134  	const char ** const tail_argv = tail_memdup(argv, sizeof(argv));
     135  	const char ** const tail_envp = tail_memdup(envp, sizeof(envp));
     136  	char *my_secontext = SECONTEXT_PID_MY();
     137  
     138  	syscall(__NR_execveat, -100, FILENAME, tail_argv, tail_envp, 0x1100);
     139  	printf("%s%s(AT_FDCWD, \"%s\""
     140  	       ", [\"%s\", \"%s\", \"%s\", %p, %p, %p, ... /* %p */]"
     141  # if VERBOSE
     142  	       ", [\"%s\", \"%s\", %p, %p, %p, ... /* %p */]"
     143  # else
     144  	       ", %p /* 5 vars, unterminated */"
     145  # endif
     146  	       ", AT_SYMLINK_NOFOLLOW|AT_EMPTY_PATH) = -1 %s (%m)\n",
     147  	       my_secontext, "execveat",
     148  	       Q_FILENAME, q_argv[0], q_argv[1], q_argv[2],
     149  	       argv[3], argv[4], argv[5], (char *) tail_argv + sizeof(argv),
     150  # if VERBOSE
     151  	       q_envp[0], q_envp[1], envp[2], envp[3], envp[4],
     152  	       (char *) tail_envp + sizeof(envp),
     153  # else
     154  	       tail_envp,
     155  # endif
     156  	       errno2name());
     157  
     158  	tail_argv[ARRAY_SIZE(q_argv)] = NULL;
     159  	tail_envp[ARRAY_SIZE(q_envp)] = NULL;
     160  	(void) q_envp;	/* workaround for clang bug #33068 */
     161  
     162  	syscall(__NR_execveat, -100, FILENAME, tail_argv, tail_envp, 0x1100);
     163  	printf("%s%s(AT_FDCWD, \"%s\", [\"%s\", \"%s\", \"%s\"]"
     164  # if VERBOSE
     165  	       ", [\"%s\", \"%s\"]"
     166  # else
     167  	       ", %p /* 2 vars */"
     168  # endif
     169  	       ", AT_SYMLINK_NOFOLLOW|AT_EMPTY_PATH) = -1 %s (%m)\n",
     170  	       my_secontext, "execveat",
     171  	       Q_FILENAME, q_argv[0], q_argv[1], q_argv[2],
     172  # if VERBOSE
     173  	       q_envp[0], q_envp[1],
     174  # else
     175  	       tail_envp,
     176  # endif
     177  	       errno2name());
     178  
     179  	syscall(__NR_execveat, -100, FILENAME, tail_argv + 2, tail_envp + 1, 0x1100);
     180  	printf("%s%s(AT_FDCWD, \"%s\", [\"%s\"]"
     181  # if VERBOSE
     182  	       ", [\"%s\"]"
     183  # else
     184  	       ", %p /* 1 var */"
     185  # endif
     186  	       ", AT_SYMLINK_NOFOLLOW|AT_EMPTY_PATH) = -1 %s (%m)\n",
     187  	       my_secontext, "execveat",
     188  	       Q_FILENAME, q_argv[2],
     189  # if VERBOSE
     190  	       q_envp[1],
     191  # else
     192  	       tail_envp + 1,
     193  # endif
     194  	       errno2name());
     195  
     196  	TAIL_ALLOC_OBJECT_CONST_PTR(char *, empty);
     197  	char **const efault = empty + 1;
     198  	*empty = NULL;
     199  
     200  	syscall(__NR_execveat, -100, FILENAME, empty, empty, 0x1100);
     201  	printf("%s%s(AT_FDCWD, \"%s\", []"
     202  # if VERBOSE
     203  	       ", []"
     204  # else
     205  	       ", %p /* 0 vars */"
     206  # endif
     207  	       ", AT_SYMLINK_NOFOLLOW|AT_EMPTY_PATH) = -1 %s (%m)\n",
     208  	       my_secontext, "execveat",
     209  	       Q_FILENAME,
     210  # if !VERBOSE
     211  	       empty,
     212  # endif
     213  	       errno2name());
     214  
     215  	char *const str_a = tail_alloc(DEFAULT_STRLEN + 2);
     216  	fill_memory_ex(str_a, DEFAULT_STRLEN + 1, '0', 10);
     217  	str_a[DEFAULT_STRLEN + 1] = '\0';
     218  
     219  	char *const str_b = tail_alloc(DEFAULT_STRLEN + 2);
     220  	fill_memory_ex(str_b, DEFAULT_STRLEN + 1, '_', 32);
     221  	str_b[DEFAULT_STRLEN + 1] = '\0';
     222  
     223  	char **const a = tail_alloc(sizeof(*a) * (DEFAULT_STRLEN + 2));
     224  	char **const b = tail_alloc(sizeof(*b) * (DEFAULT_STRLEN + 2));
     225  	unsigned int i;
     226  	for (i = 0; i <= DEFAULT_STRLEN; ++i) {
     227  		a[i] = &str_a[i];
     228  		b[i] = &str_b[i];
     229  	}
     230  	a[i] = b[i] = NULL;
     231  
     232  	syscall(__NR_execveat, -100, FILENAME, a, b, 0x1100);
     233  	printf("%s%s(AT_FDCWD, \"%s\", [\"%.*s\"...",
     234  	       my_secontext, "execveat",
     235  	       Q_FILENAME, DEFAULT_STRLEN, a[0]);
     236  	for (i = 1; i < DEFAULT_STRLEN; ++i)
     237  		printf(", \"%s\"", a[i]);
     238  # if VERBOSE
     239  	printf(", \"%s\"", a[i]);
     240  # else
     241  	printf(", ...");
     242  # endif
     243  # if VERBOSE
     244  	printf("], [\"%.*s\"...", DEFAULT_STRLEN, b[0]);
     245  	for (i = 1; i <= DEFAULT_STRLEN; ++i)
     246  		printf(", \"%s\"", b[i]);
     247  	printf("]");
     248  # else
     249  	printf("], %p /* %u vars */", b, DEFAULT_STRLEN + 1);
     250  # endif
     251  	printf(", AT_SYMLINK_NOFOLLOW|AT_EMPTY_PATH) = -1 %s (%m)\n",
     252  	       errno2name());
     253  
     254  	syscall(__NR_execveat, -100, FILENAME, a + 1, b + 1, 0x1100);
     255  	printf("%s%s(AT_FDCWD, \"%s\", [\"%s\"",
     256  	       my_secontext, "execveat",
     257  	       Q_FILENAME, a[1]);
     258  	for (i = 2; i <= DEFAULT_STRLEN; ++i)
     259  		printf(", \"%s\"", a[i]);
     260  # if VERBOSE
     261  	printf("], [\"%s\"", b[1]);
     262  	for (i = 2; i <= DEFAULT_STRLEN; ++i)
     263  		printf(", \"%s\"", b[i]);
     264  	printf("]");
     265  # else
     266  	printf("], %p /* %d vars */", b + 1, DEFAULT_STRLEN);
     267  # endif
     268  	printf(", AT_SYMLINK_NOFOLLOW|AT_EMPTY_PATH) = -1 %s (%m)\n",
     269  	       errno2name());
     270  
     271  	syscall(__NR_execveat, -100, FILENAME, NULL, efault, 0x1100);
     272  	printf("%s%s(AT_FDCWD, \"%s\", NULL, %p"
     273  	       ", AT_SYMLINK_NOFOLLOW|AT_EMPTY_PATH) = -1 %s (%m)\n",
     274  	       my_secontext, "execveat",
     275  	       Q_FILENAME, efault, errno2name());
     276  
     277  	syscall(__NR_execveat, -100, FILENAME, efault, NULL, 0x1100);
     278  	printf("%s%s(AT_FDCWD, \"%s\", %p, NULL"
     279  	       ", AT_SYMLINK_NOFOLLOW|AT_EMPTY_PATH) = -1 %s (%m)\n",
     280  	       my_secontext, "execveat",
     281  	       Q_FILENAME, efault, errno2name());
     282  
     283  	tests_with_existing_file();
     284  
     285  	puts("+++ exited with 0 +++");
     286  	return 0;
     287  }
     288  
     289  #else
     290  
     291  SKIP_MAIN_UNDEFINED("__NR_execveat")
     292  
     293  #endif