]> granicus.if.org Git - strace/blob - tests/xchownx.c
Remove XLAT_END
[strace] / tests / xchownx.c
1 /*
2  * Check decoding of chown/chown32/lchown/lchown32/fchown/fchown32 syscalls.
3  *
4  * Copyright (c) 2016 Dmitry V. Levin <ldv@altlinux.org>
5  * Copyright (c) 2016-2018 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         unsigned int i;
112         long expected = 0;
113
114         for (i = 0; i < ARRAY_SIZE(tests); ++i) {
115                 const unsigned int unum = ugid2int(tests[i].uid);
116                 const unsigned int gnum = ugid2int(tests[i].gid);
117
118                 if (num_matches_id(unum, uid) &&
119                     num_matches_id(gnum, gid)) {
120                         if (expected)
121                                 continue;
122                 } else {
123                         if (!expected) {
124                                 expected = -1;
125                                 EOK_CMD;
126                         }
127                 }
128
129                 const long rc = syscall(SYSCALL_NR, SYSCALL_ARG1,
130                                         tests[i].uid, tests[i].gid);
131                 const char *errstr = sprintrc(rc);
132                 printf("%s(" FMT_ARG1, SYSCALL_NAME, SYSCALL_ARG1);
133                 print_int(unum);
134                 print_int(gnum);
135                 printf(") = %s\n", errstr);
136         }
137
138         puts("+++ exited with 0 +++");
139         return 0;
140 }