1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (c) 2017 Cyril Hrubis <chrubis@suse.cz>
4 */
5
6 #define _GNU_SOURCE
7 #include <unistd.h>
8 #include <errno.h>
9 #include <sched.h>
10 #include <sys/ptrace.h>
11 #include "config.h"
12 #ifdef HAVE_SYS_FANOTIFY_H
13 # include <sys/fanotify.h>
14 #endif
15 #define TST_NO_DEFAULT_MAIN
16 #include "tst_test.h"
17 #include "lapi/setns.h"
18 #include "tst_safe_macros.h"
19 #include "lapi/personality.h"
20
safe_setpgid(const char * file,const int lineno,pid_t pid,pid_t pgid)21 int safe_setpgid(const char *file, const int lineno, pid_t pid, pid_t pgid)
22 {
23 int rval;
24
25 rval = setpgid(pid, pgid);
26 if (rval) {
27 tst_brk(TBROK | TERRNO,
28 "%s:%d: setpgid(%i, %i) failed",
29 file, lineno, pid, pgid);
30 }
31
32 return rval;
33 }
34
safe_getpgid(const char * file,const int lineno,pid_t pid)35 pid_t safe_getpgid(const char *file, const int lineno, pid_t pid)
36 {
37 pid_t pgid;
38
39 pgid = getpgid(pid);
40 if (pgid == -1) {
41 tst_brk(TBROK | TERRNO,
42 "%s:%d: getpgid(%i) failed", file, lineno, pid);
43 }
44
45 return pgid;
46 }
47
safe_fanotify_init(const char * file,const int lineno,unsigned int flags,unsigned int event_f_flags)48 int safe_fanotify_init(const char *file, const int lineno,
49 unsigned int flags, unsigned int event_f_flags)
50 {
51 int rval;
52
53 #ifdef HAVE_SYS_FANOTIFY_H
54 rval = fanotify_init(flags, event_f_flags);
55
56 if (rval == -1) {
57 if (errno == ENOSYS) {
58 tst_brk(TCONF,
59 "fanotify is not configured in this kernel.");
60 }
61 tst_brk(TBROK | TERRNO,
62 "%s:%d: fanotify_init() failed", file, lineno);
63 }
64 #else
65 tst_brk(TCONF, "Header <sys/fanotify.h> is not present");
66 #endif /* HAVE_SYS_FANOTIFY_H */
67
68 return rval;
69 }
70
safe_personality(const char * filename,unsigned int lineno,unsigned long persona)71 int safe_personality(const char *filename, unsigned int lineno,
72 unsigned long persona)
73 {
74 int prev_persona = personality(persona);
75
76 if (prev_persona < 0) {
77 tst_brk_(filename, lineno, TBROK | TERRNO,
78 "persona(%ld) failed", persona);
79 }
80
81 return prev_persona;
82 }
83
safe_setregid(const char * file,const int lineno,gid_t rgid,gid_t egid)84 int safe_setregid(const char *file, const int lineno,
85 gid_t rgid, gid_t egid)
86 {
87 int rval;
88
89 rval = setregid(rgid, egid);
90 if (rval == -1) {
91 tst_brk_(file, lineno, TBROK | TERRNO,
92 "setregid(%li, %li) failed",
93 (long)rgid, (long)egid);
94 }
95
96 return rval;
97 }
98
99
safe_setreuid(const char * file,const int lineno,uid_t ruid,uid_t euid)100 int safe_setreuid(const char *file, const int lineno,
101 uid_t ruid, uid_t euid)
102 {
103 int rval;
104
105 rval = setreuid(ruid, euid);
106 if (rval == -1) {
107 tst_brk_(file, lineno, TBROK | TERRNO,
108 "setreuid(%li, %li) failed",
109 (long)ruid, (long)euid);
110 }
111
112 return rval;
113 }
114
115
safe_sigaction(const char * file,const int lineno,int signum,const struct sigaction * act,struct sigaction * oldact)116 int safe_sigaction(const char *file, const int lineno,
117 int signum, const struct sigaction *act,
118 struct sigaction *oldact)
119 {
120 int rval;
121
122 rval = sigaction(signum, act, oldact);
123
124 if (rval == -1) {
125 tst_brk_(file, lineno, TBROK | TERRNO,
126 "sigaction(%s (%d), %p, %p) failed",
127 tst_strsig(signum), signum, act, oldact);
128 }
129
130 return rval;
131 }
132
safe_getgrnam(const char * file,const int lineno,const char * name)133 struct group *safe_getgrnam(const char *file, const int lineno,
134 const char *name)
135 {
136 struct group *rval;
137
138 errno = 0;
139 rval = getgrnam(name);
140 if (rval == NULL) {
141 tst_brk_(file, lineno, TBROK | TERRNO,
142 "getgrnam(%s) failed", name);
143 }
144
145 return rval;
146 }
147
safe_getgrnam_fallback(const char * file,const int lineno,const char * name,const char * fallback)148 struct group *safe_getgrnam_fallback(const char *file, const int lineno,
149 const char *name, const char *fallback)
150 {
151 struct group *rval;
152
153 errno = 0;
154 rval = getgrnam(name);
155 if (rval == NULL) {
156 tst_res_(file, lineno, TINFO,
157 "getgrnam(%s) failed - try fallback %s",
158 name, fallback);
159 rval = safe_getgrnam(file, lineno, fallback);
160 }
161
162 return rval;
163 }
164
safe_getgrgid(const char * file,const int lineno,gid_t gid)165 struct group *safe_getgrgid(const char *file, const int lineno, gid_t gid)
166 {
167 struct group *rval;
168
169 errno = 0;
170 rval = getgrgid(gid);
171 if (rval == NULL) {
172 tst_brk_(file, lineno, TBROK | TERRNO,
173 "getgrgid(%li) failed", (long)gid);
174 }
175
176 return rval;
177 }
178
safe_chroot(const char * file,const int lineno,const char * path)179 int safe_chroot(const char *file, const int lineno, const char *path)
180 {
181 int rval;
182
183 rval = chroot(path);
184 if (rval == -1) {
185 tst_brk_(file, lineno, TBROK | TERRNO,
186 "chroot(%s) failed", path);
187 }
188
189 return rval;
190 }
191
safe_unshare(const char * file,const int lineno,int flags)192 void safe_unshare(const char *file, const int lineno, int flags)
193 {
194 int res;
195
196 res = unshare(flags);
197 if (res == -1) {
198 if (errno == EINVAL) {
199 tst_brk_(file, lineno, TCONF | TERRNO,
200 "unshare(%d) unsupported", flags);
201 } else {
202 tst_brk_(file, lineno, TBROK | TERRNO,
203 "unshare(%d) failed", flags);
204 }
205 }
206 }
207
safe_setns(const char * file,const int lineno,int fd,int nstype)208 void safe_setns(const char *file, const int lineno, int fd, int nstype)
209 {
210 int ret;
211
212 ret = setns(fd, nstype);
213 if (ret == -1) {
214 tst_brk_(file, lineno, TBROK | TERRNO, "setns(%i, %i) failed",
215 fd, nstype);
216 }
217 }
218
tst_safe_ptrace(const char * file,const int lineno,int req,pid_t pid,void * addr,void * data)219 long tst_safe_ptrace(const char *file, const int lineno, int req, pid_t pid,
220 void *addr, void *data)
221 {
222 long ret;
223
224 errno = 0;
225 ret = ptrace(req, pid, addr, data);
226
227 if (ret == -1) {
228 tst_brk_(file, lineno, TBROK | TERRNO, "ptrace() failed");
229 } else if (ret) {
230 tst_brk_(file, lineno, TBROK | TERRNO,
231 "Invalid ptrace() return value %ld", ret);
232 }
233
234 return ret;
235 }
236
safe_pipe2(const char * file,const int lineno,int fildes[2],int flags)237 int safe_pipe2(const char *file, const int lineno, int fildes[2], int flags)
238 {
239 int ret;
240
241 ret = pipe2(fildes, flags);
242 if (ret == -1) {
243 tst_brk_(file, lineno, TBROK | TERRNO,
244 "pipe2({%d,%d}) failed with flag(%d)",
245 fildes[0], fildes[1], flags);
246 }
247
248 return ret;
249 }
250