(root)/
strace-6.5/
tests-m32/
xchownx.c
       1  /*
       2   * Check decoding of chown/chown32/lchown/lchown32/fchown/fchown32 syscalls.
       3   *
       4   * Copyright (c) 2016 Dmitry V. Levin <ldv@strace.io>
       5   * Copyright (c) 2016-2021 The strace developers.
       6   * All rights reserved.
       7   *
       8   * SPDX-License-Identifier: GPL-2.0-or-later
       9   */
      10  
      11  #include <fcntl.h>
      12  #include <stdio.h>
      13  #include <unistd.h>
      14  
      15  #ifdef UGID_TYPE_IS_SHORT
      16  # define UGID_TYPE	short
      17  # define GETEUID	syscall(__NR_geteuid)
      18  # define GETEGID	syscall(__NR_getegid)
      19  # define CHECK_OVERFLOWUID(arg)	check_overflowuid(arg)
      20  # define CHECK_OVERFLOWGID(arg)	check_overflowgid(arg)
      21  #else
      22  # define UGID_TYPE	int
      23  # define GETEUID	geteuid()
      24  # define GETEGID	getegid()
      25  # define CHECK_OVERFLOWUID(arg)
      26  # define CHECK_OVERFLOWGID(arg)
      27  #endif
      28  
      29  #define UNLINK_SAMPLE					\
      30  	do {						\
      31  		if (unlink(sample))			\
      32  			perror_msg_and_fail("unlink");	\
      33  	} while (0)
      34  
      35  #define CLOSE_SAMPLE					\
      36  	do {						\
      37  		if (close(fd))				\
      38  			perror_msg_and_fail("close");	\
      39  	} while (0)
      40  
      41  #ifdef ACCESS_BY_DESCRIPTOR
      42  # define SYSCALL_ARG1 fd
      43  # define FMT_ARG1 "%d"
      44  # define EOK_CMD CLOSE_SAMPLE
      45  # define CLEANUP_CMD UNLINK_SAMPLE
      46  #else
      47  # define SYSCALL_ARG1 sample
      48  # define FMT_ARG1 "\"%s\""
      49  # define EOK_CMD UNLINK_SAMPLE
      50  # define CLEANUP_CMD CLOSE_SAMPLE
      51  #endif
      52  
      53  static int
      54  ugid2int(const unsigned UGID_TYPE id)
      55  {
      56  	if ((unsigned UGID_TYPE) -1U == id)
      57  		return -1;
      58  	else
      59  		return id;
      60  }
      61  
      62  static void
      63  print_int(const unsigned int num)
      64  {
      65  	if (num == -1U)
      66  		printf(", -1");
      67  	else
      68  		printf(", %u", num);
      69  }
      70  
      71  static int
      72  num_matches_id(const unsigned int num, const unsigned int id)
      73  {
      74  	return num == id || num == -1U;
      75  }
      76  
      77  #define PAIR(val)	{ val, gid }, { uid, val }
      78  
      79  int
      80  main(void)
      81  {
      82  	static const char sample[] = SYSCALL_NAME "_sample";
      83  
      84  	unsigned int uid = GETEUID;
      85  	CHECK_OVERFLOWUID(uid);
      86  	unsigned int gid = GETEGID;
      87  	CHECK_OVERFLOWUID(gid);
      88  
      89  	const struct {
      90  		const long uid, gid;
      91  	} tests[] = {
      92  		{ uid, gid },
      93  		{ (unsigned long) 0xffffffff00000000ULL | uid, gid },
      94  		{ uid, (unsigned long) 0xffffffff00000000ULL | gid },
      95  		PAIR(-1U),
      96  		PAIR(-1L),
      97  		{ 0xffff0000U | uid, gid },
      98  		{ uid, 0xffff0000U | gid },
      99  		PAIR(0xffff),
     100  		PAIR(0xc0deffffU),
     101  		PAIR(0xfacefeedU),
     102  		PAIR((long) 0xfacefeeddeadbeefULL)
     103  	};
     104  
     105  	int fd = open(sample, O_RDONLY | O_CREAT, 0400);
     106  	if (fd < 0)
     107  		perror_msg_and_fail("open");
     108  
     109  	CLEANUP_CMD;
     110  
     111  	long expected = 0;
     112  
     113  	for (unsigned int i = 0; i < ARRAY_SIZE(tests); ++i) {
     114  		const unsigned int unum = ugid2int(tests[i].uid);
     115  		const unsigned int gnum = ugid2int(tests[i].gid);
     116  
     117  		if (num_matches_id(unum, uid) &&
     118  		    num_matches_id(gnum, gid)) {
     119  			if (expected)
     120  				continue;
     121  		} else {
     122  			if (!expected) {
     123  				expected = -1;
     124  				EOK_CMD;
     125  			}
     126  		}
     127  
     128  		const long rc = syscall(SYSCALL_NR, SYSCALL_ARG1,
     129  					tests[i].uid, tests[i].gid);
     130  		const char *errstr = sprintrc(rc);
     131  		printf("%s(" FMT_ARG1, SYSCALL_NAME, SYSCALL_ARG1);
     132  		print_int(unum);
     133  		print_int(gnum);
     134  		printf(") = %s\n", errstr);
     135  	}
     136  
     137  	puts("+++ exited with 0 +++");
     138  	return 0;
     139  }