1*49cdfc7eSAndroid Build Coastguard Worker // SPDX-License-Identifier: GPL-2.0-or-later
2*49cdfc7eSAndroid Build Coastguard Worker /*
3*49cdfc7eSAndroid Build Coastguard Worker * Copyright (c) 2021 SUSE LLC <[email protected]>
4*49cdfc7eSAndroid Build Coastguard Worker */
5*49cdfc7eSAndroid Build Coastguard Worker
6*49cdfc7eSAndroid Build Coastguard Worker #define _GNU_SOURCE
7*49cdfc7eSAndroid Build Coastguard Worker #include <stdio.h>
8*49cdfc7eSAndroid Build Coastguard Worker #include "lapi/fcntl.h"
9*49cdfc7eSAndroid Build Coastguard Worker #include "tst_safe_file_at.h"
10*49cdfc7eSAndroid Build Coastguard Worker
11*49cdfc7eSAndroid Build Coastguard Worker #define TST_NO_DEFAULT_MAIN
12*49cdfc7eSAndroid Build Coastguard Worker #include "tst_test.h"
13*49cdfc7eSAndroid Build Coastguard Worker
14*49cdfc7eSAndroid Build Coastguard Worker static char fd_path[PATH_MAX];
15*49cdfc7eSAndroid Build Coastguard Worker
tst_decode_fd(const int fd)16*49cdfc7eSAndroid Build Coastguard Worker const char *tst_decode_fd(const int fd)
17*49cdfc7eSAndroid Build Coastguard Worker {
18*49cdfc7eSAndroid Build Coastguard Worker ssize_t ret;
19*49cdfc7eSAndroid Build Coastguard Worker char proc_path[32];
20*49cdfc7eSAndroid Build Coastguard Worker
21*49cdfc7eSAndroid Build Coastguard Worker if (fd < 0)
22*49cdfc7eSAndroid Build Coastguard Worker return "!";
23*49cdfc7eSAndroid Build Coastguard Worker
24*49cdfc7eSAndroid Build Coastguard Worker sprintf(proc_path, "/proc/self/fd/%d", fd);
25*49cdfc7eSAndroid Build Coastguard Worker ret = readlink(proc_path, fd_path, sizeof(fd_path));
26*49cdfc7eSAndroid Build Coastguard Worker
27*49cdfc7eSAndroid Build Coastguard Worker if (ret < 0)
28*49cdfc7eSAndroid Build Coastguard Worker return "?";
29*49cdfc7eSAndroid Build Coastguard Worker
30*49cdfc7eSAndroid Build Coastguard Worker fd_path[ret] = '\0';
31*49cdfc7eSAndroid Build Coastguard Worker
32*49cdfc7eSAndroid Build Coastguard Worker return fd_path;
33*49cdfc7eSAndroid Build Coastguard Worker }
34*49cdfc7eSAndroid Build Coastguard Worker
safe_openat(const char * const file,const int lineno,const int dirfd,const char * const path,const int oflags,...)35*49cdfc7eSAndroid Build Coastguard Worker int safe_openat(const char *const file, const int lineno,
36*49cdfc7eSAndroid Build Coastguard Worker const int dirfd, const char *const path, const int oflags, ...)
37*49cdfc7eSAndroid Build Coastguard Worker {
38*49cdfc7eSAndroid Build Coastguard Worker int fd;
39*49cdfc7eSAndroid Build Coastguard Worker mode_t mode = 0;
40*49cdfc7eSAndroid Build Coastguard Worker
41*49cdfc7eSAndroid Build Coastguard Worker if (TST_OPEN_NEEDS_MODE(oflags)) {
42*49cdfc7eSAndroid Build Coastguard Worker va_list ap;
43*49cdfc7eSAndroid Build Coastguard Worker
44*49cdfc7eSAndroid Build Coastguard Worker va_start(ap, oflags);
45*49cdfc7eSAndroid Build Coastguard Worker mode = va_arg(ap, int);
46*49cdfc7eSAndroid Build Coastguard Worker va_end(ap);
47*49cdfc7eSAndroid Build Coastguard Worker }
48*49cdfc7eSAndroid Build Coastguard Worker
49*49cdfc7eSAndroid Build Coastguard Worker fd = openat(dirfd, path, oflags, mode);
50*49cdfc7eSAndroid Build Coastguard Worker if (fd > -1)
51*49cdfc7eSAndroid Build Coastguard Worker return fd;
52*49cdfc7eSAndroid Build Coastguard Worker
53*49cdfc7eSAndroid Build Coastguard Worker tst_brk_(file, lineno, TBROK | TERRNO,
54*49cdfc7eSAndroid Build Coastguard Worker "openat(%d<%s>, '%s', %o, %o)",
55*49cdfc7eSAndroid Build Coastguard Worker dirfd, tst_decode_fd(dirfd), path, oflags, mode);
56*49cdfc7eSAndroid Build Coastguard Worker
57*49cdfc7eSAndroid Build Coastguard Worker return fd;
58*49cdfc7eSAndroid Build Coastguard Worker }
59*49cdfc7eSAndroid Build Coastguard Worker
safe_file_readat(const char * const file,const int lineno,const int dirfd,const char * const path,char * const buf,const size_t nbyte)60*49cdfc7eSAndroid Build Coastguard Worker ssize_t safe_file_readat(const char *const file, const int lineno,
61*49cdfc7eSAndroid Build Coastguard Worker const int dirfd, const char *const path,
62*49cdfc7eSAndroid Build Coastguard Worker char *const buf, const size_t nbyte)
63*49cdfc7eSAndroid Build Coastguard Worker {
64*49cdfc7eSAndroid Build Coastguard Worker int fd = safe_openat(file, lineno, dirfd, path, O_RDONLY);
65*49cdfc7eSAndroid Build Coastguard Worker ssize_t rval;
66*49cdfc7eSAndroid Build Coastguard Worker
67*49cdfc7eSAndroid Build Coastguard Worker if (fd < 0)
68*49cdfc7eSAndroid Build Coastguard Worker return -1;
69*49cdfc7eSAndroid Build Coastguard Worker
70*49cdfc7eSAndroid Build Coastguard Worker rval = safe_read(file, lineno, NULL, 0, fd, buf, nbyte - 1);
71*49cdfc7eSAndroid Build Coastguard Worker if (rval < 0)
72*49cdfc7eSAndroid Build Coastguard Worker return -1;
73*49cdfc7eSAndroid Build Coastguard Worker
74*49cdfc7eSAndroid Build Coastguard Worker close(fd);
75*49cdfc7eSAndroid Build Coastguard Worker buf[rval] = '\0';
76*49cdfc7eSAndroid Build Coastguard Worker
77*49cdfc7eSAndroid Build Coastguard Worker if (rval >= (ssize_t)nbyte - 1) {
78*49cdfc7eSAndroid Build Coastguard Worker tst_brk_(file, lineno, TBROK,
79*49cdfc7eSAndroid Build Coastguard Worker "Buffer length %zu too small to read %d<%s>/%s",
80*49cdfc7eSAndroid Build Coastguard Worker nbyte, dirfd, tst_decode_fd(dirfd), path);
81*49cdfc7eSAndroid Build Coastguard Worker }
82*49cdfc7eSAndroid Build Coastguard Worker
83*49cdfc7eSAndroid Build Coastguard Worker return rval;
84*49cdfc7eSAndroid Build Coastguard Worker }
85*49cdfc7eSAndroid Build Coastguard Worker
tst_file_vprintfat(const int dirfd,const char * const path,const char * const fmt,va_list va)86*49cdfc7eSAndroid Build Coastguard Worker int tst_file_vprintfat(const int dirfd, const char *const path,
87*49cdfc7eSAndroid Build Coastguard Worker const char *const fmt, va_list va)
88*49cdfc7eSAndroid Build Coastguard Worker {
89*49cdfc7eSAndroid Build Coastguard Worker const int fd = openat(dirfd, path, O_WRONLY);
90*49cdfc7eSAndroid Build Coastguard Worker int ret, errno_cpy;
91*49cdfc7eSAndroid Build Coastguard Worker
92*49cdfc7eSAndroid Build Coastguard Worker if (fd < 0)
93*49cdfc7eSAndroid Build Coastguard Worker return -1;
94*49cdfc7eSAndroid Build Coastguard Worker
95*49cdfc7eSAndroid Build Coastguard Worker ret = vdprintf(fd, fmt, va);
96*49cdfc7eSAndroid Build Coastguard Worker errno_cpy = errno;
97*49cdfc7eSAndroid Build Coastguard Worker close(fd);
98*49cdfc7eSAndroid Build Coastguard Worker
99*49cdfc7eSAndroid Build Coastguard Worker if (ret < 0) {
100*49cdfc7eSAndroid Build Coastguard Worker errno = errno_cpy;
101*49cdfc7eSAndroid Build Coastguard Worker return -2;
102*49cdfc7eSAndroid Build Coastguard Worker }
103*49cdfc7eSAndroid Build Coastguard Worker
104*49cdfc7eSAndroid Build Coastguard Worker return ret;
105*49cdfc7eSAndroid Build Coastguard Worker }
106*49cdfc7eSAndroid Build Coastguard Worker
tst_file_printfat(const int dirfd,const char * const path,const char * const fmt,...)107*49cdfc7eSAndroid Build Coastguard Worker int tst_file_printfat(const int dirfd, const char *const path,
108*49cdfc7eSAndroid Build Coastguard Worker const char *const fmt, ...)
109*49cdfc7eSAndroid Build Coastguard Worker {
110*49cdfc7eSAndroid Build Coastguard Worker va_list va;
111*49cdfc7eSAndroid Build Coastguard Worker int rval;
112*49cdfc7eSAndroid Build Coastguard Worker
113*49cdfc7eSAndroid Build Coastguard Worker va_start(va, fmt);
114*49cdfc7eSAndroid Build Coastguard Worker rval = tst_file_vprintfat(dirfd, path, fmt, va);
115*49cdfc7eSAndroid Build Coastguard Worker va_end(va);
116*49cdfc7eSAndroid Build Coastguard Worker
117*49cdfc7eSAndroid Build Coastguard Worker return rval;
118*49cdfc7eSAndroid Build Coastguard Worker }
119*49cdfc7eSAndroid Build Coastguard Worker
safe_file_vprintfat(const char * const file,const int lineno,const int dirfd,const char * const path,const char * const fmt,va_list va)120*49cdfc7eSAndroid Build Coastguard Worker int safe_file_vprintfat(const char *const file, const int lineno,
121*49cdfc7eSAndroid Build Coastguard Worker const int dirfd, const char *const path,
122*49cdfc7eSAndroid Build Coastguard Worker const char *const fmt, va_list va)
123*49cdfc7eSAndroid Build Coastguard Worker {
124*49cdfc7eSAndroid Build Coastguard Worker char buf[16];
125*49cdfc7eSAndroid Build Coastguard Worker va_list vac;
126*49cdfc7eSAndroid Build Coastguard Worker int rval, errno_cpy;
127*49cdfc7eSAndroid Build Coastguard Worker
128*49cdfc7eSAndroid Build Coastguard Worker va_copy(vac, va);
129*49cdfc7eSAndroid Build Coastguard Worker
130*49cdfc7eSAndroid Build Coastguard Worker rval = tst_file_vprintfat(dirfd, path, fmt, va);
131*49cdfc7eSAndroid Build Coastguard Worker
132*49cdfc7eSAndroid Build Coastguard Worker if (rval == -2) {
133*49cdfc7eSAndroid Build Coastguard Worker errno_cpy = errno;
134*49cdfc7eSAndroid Build Coastguard Worker rval = vsnprintf(buf, sizeof(buf), fmt, vac);
135*49cdfc7eSAndroid Build Coastguard Worker va_end(vac);
136*49cdfc7eSAndroid Build Coastguard Worker
137*49cdfc7eSAndroid Build Coastguard Worker if (rval >= (ssize_t)sizeof(buf))
138*49cdfc7eSAndroid Build Coastguard Worker strcpy(buf + sizeof(buf) - 5, "...");
139*49cdfc7eSAndroid Build Coastguard Worker else if (rval < 0)
140*49cdfc7eSAndroid Build Coastguard Worker buf[0] = '\0';
141*49cdfc7eSAndroid Build Coastguard Worker
142*49cdfc7eSAndroid Build Coastguard Worker errno = errno_cpy;
143*49cdfc7eSAndroid Build Coastguard Worker tst_brk_(file, lineno, TBROK | TERRNO,
144*49cdfc7eSAndroid Build Coastguard Worker "vdprintf(%d<%s>, '%s', '%s'<%s>)",
145*49cdfc7eSAndroid Build Coastguard Worker dirfd, tst_decode_fd(dirfd), path, fmt, buf);
146*49cdfc7eSAndroid Build Coastguard Worker return -1;
147*49cdfc7eSAndroid Build Coastguard Worker }
148*49cdfc7eSAndroid Build Coastguard Worker
149*49cdfc7eSAndroid Build Coastguard Worker va_end(vac);
150*49cdfc7eSAndroid Build Coastguard Worker
151*49cdfc7eSAndroid Build Coastguard Worker if (rval == -1) {
152*49cdfc7eSAndroid Build Coastguard Worker tst_brk_(file, lineno, TBROK | TERRNO,
153*49cdfc7eSAndroid Build Coastguard Worker "openat(%d<%s>, '%s', O_WRONLY)",
154*49cdfc7eSAndroid Build Coastguard Worker dirfd, tst_decode_fd(dirfd), path);
155*49cdfc7eSAndroid Build Coastguard Worker }
156*49cdfc7eSAndroid Build Coastguard Worker
157*49cdfc7eSAndroid Build Coastguard Worker return rval;
158*49cdfc7eSAndroid Build Coastguard Worker }
159*49cdfc7eSAndroid Build Coastguard Worker
safe_file_printfat(const char * const file,const int lineno,const int dirfd,const char * const path,const char * const fmt,...)160*49cdfc7eSAndroid Build Coastguard Worker int safe_file_printfat(const char *const file, const int lineno,
161*49cdfc7eSAndroid Build Coastguard Worker const int dirfd, const char *const path,
162*49cdfc7eSAndroid Build Coastguard Worker const char *const fmt, ...)
163*49cdfc7eSAndroid Build Coastguard Worker {
164*49cdfc7eSAndroid Build Coastguard Worker va_list va;
165*49cdfc7eSAndroid Build Coastguard Worker int rval;
166*49cdfc7eSAndroid Build Coastguard Worker
167*49cdfc7eSAndroid Build Coastguard Worker va_start(va, fmt);
168*49cdfc7eSAndroid Build Coastguard Worker rval = safe_file_vprintfat(file, lineno, dirfd, path, fmt, va);
169*49cdfc7eSAndroid Build Coastguard Worker va_end(va);
170*49cdfc7eSAndroid Build Coastguard Worker
171*49cdfc7eSAndroid Build Coastguard Worker return rval;
172*49cdfc7eSAndroid Build Coastguard Worker }
173*49cdfc7eSAndroid Build Coastguard Worker
safe_unlinkat(const char * const file,const int lineno,const int dirfd,const char * const path,const int flags)174*49cdfc7eSAndroid Build Coastguard Worker int safe_unlinkat(const char *const file, const int lineno,
175*49cdfc7eSAndroid Build Coastguard Worker const int dirfd, const char *const path, const int flags)
176*49cdfc7eSAndroid Build Coastguard Worker {
177*49cdfc7eSAndroid Build Coastguard Worker const int rval = unlinkat(dirfd, path, flags);
178*49cdfc7eSAndroid Build Coastguard Worker const char *flags_sym;
179*49cdfc7eSAndroid Build Coastguard Worker
180*49cdfc7eSAndroid Build Coastguard Worker if (!rval)
181*49cdfc7eSAndroid Build Coastguard Worker return rval;
182*49cdfc7eSAndroid Build Coastguard Worker
183*49cdfc7eSAndroid Build Coastguard Worker switch(flags) {
184*49cdfc7eSAndroid Build Coastguard Worker case AT_REMOVEDIR:
185*49cdfc7eSAndroid Build Coastguard Worker flags_sym = "AT_REMOVEDIR";
186*49cdfc7eSAndroid Build Coastguard Worker break;
187*49cdfc7eSAndroid Build Coastguard Worker case 0:
188*49cdfc7eSAndroid Build Coastguard Worker flags_sym = "0";
189*49cdfc7eSAndroid Build Coastguard Worker break;
190*49cdfc7eSAndroid Build Coastguard Worker default:
191*49cdfc7eSAndroid Build Coastguard Worker flags_sym = "?";
192*49cdfc7eSAndroid Build Coastguard Worker break;
193*49cdfc7eSAndroid Build Coastguard Worker }
194*49cdfc7eSAndroid Build Coastguard Worker
195*49cdfc7eSAndroid Build Coastguard Worker tst_brk_(file, lineno, TBROK | TERRNO,
196*49cdfc7eSAndroid Build Coastguard Worker "unlinkat(%d<%s>, '%s', %s)",
197*49cdfc7eSAndroid Build Coastguard Worker dirfd, tst_decode_fd(dirfd), path, flags_sym);
198*49cdfc7eSAndroid Build Coastguard Worker
199*49cdfc7eSAndroid Build Coastguard Worker return rval;
200*49cdfc7eSAndroid Build Coastguard Worker }
201*49cdfc7eSAndroid Build Coastguard Worker
safe_fchownat(const char * const file,const int lineno,const int dirfd,const char * const path,uid_t owner,gid_t group,int flags)202*49cdfc7eSAndroid Build Coastguard Worker int safe_fchownat(const char *const file, const int lineno,
203*49cdfc7eSAndroid Build Coastguard Worker const int dirfd, const char *const path, uid_t owner, gid_t group, int flags)
204*49cdfc7eSAndroid Build Coastguard Worker {
205*49cdfc7eSAndroid Build Coastguard Worker int rval;
206*49cdfc7eSAndroid Build Coastguard Worker
207*49cdfc7eSAndroid Build Coastguard Worker rval = fchownat(dirfd, path, owner, group, flags);
208*49cdfc7eSAndroid Build Coastguard Worker
209*49cdfc7eSAndroid Build Coastguard Worker if (rval == -1) {
210*49cdfc7eSAndroid Build Coastguard Worker tst_brk_(file, lineno, TBROK | TERRNO,
211*49cdfc7eSAndroid Build Coastguard Worker "fchownat(%d<%s>, '%s', %d, %d, %d) failed", dirfd,
212*49cdfc7eSAndroid Build Coastguard Worker tst_decode_fd(dirfd), path, owner, group, flags);
213*49cdfc7eSAndroid Build Coastguard Worker } else if (rval) {
214*49cdfc7eSAndroid Build Coastguard Worker tst_brk_(file, lineno, TBROK | TERRNO,
215*49cdfc7eSAndroid Build Coastguard Worker "Invalid fchownat(%d<%s>, '%s', %d, %d, %d) return value %d",
216*49cdfc7eSAndroid Build Coastguard Worker dirfd, tst_decode_fd(dirfd), path, owner, group, flags, rval);
217*49cdfc7eSAndroid Build Coastguard Worker }
218*49cdfc7eSAndroid Build Coastguard Worker
219*49cdfc7eSAndroid Build Coastguard Worker return rval;
220*49cdfc7eSAndroid Build Coastguard Worker }
221*49cdfc7eSAndroid Build Coastguard Worker
safe_fstatat(const char * const file,const int lineno,const int dirfd,const char * const path,struct stat * statbuf,int flags)222*49cdfc7eSAndroid Build Coastguard Worker int safe_fstatat(const char *const file, const int lineno,
223*49cdfc7eSAndroid Build Coastguard Worker const int dirfd, const char *const path, struct stat *statbuf, int flags)
224*49cdfc7eSAndroid Build Coastguard Worker {
225*49cdfc7eSAndroid Build Coastguard Worker int rval;
226*49cdfc7eSAndroid Build Coastguard Worker
227*49cdfc7eSAndroid Build Coastguard Worker rval = fstatat(dirfd, path, statbuf, flags);
228*49cdfc7eSAndroid Build Coastguard Worker
229*49cdfc7eSAndroid Build Coastguard Worker if (rval == -1) {
230*49cdfc7eSAndroid Build Coastguard Worker tst_brk_(file, lineno, TBROK | TERRNO,
231*49cdfc7eSAndroid Build Coastguard Worker "fstatat(%d<%s>, '%s', %p, %d) failed", dirfd,
232*49cdfc7eSAndroid Build Coastguard Worker tst_decode_fd(dirfd), path, statbuf, flags);
233*49cdfc7eSAndroid Build Coastguard Worker } else if (rval) {
234*49cdfc7eSAndroid Build Coastguard Worker tst_brk_(file, lineno, TBROK | TERRNO,
235*49cdfc7eSAndroid Build Coastguard Worker "Invalid fstatat(%d<%s>, '%s', %p, %d) return value %d",
236*49cdfc7eSAndroid Build Coastguard Worker dirfd, tst_decode_fd(dirfd), path, statbuf, flags, rval);
237*49cdfc7eSAndroid Build Coastguard Worker }
238*49cdfc7eSAndroid Build Coastguard Worker
239*49cdfc7eSAndroid Build Coastguard Worker return rval;
240*49cdfc7eSAndroid Build Coastguard Worker }
241