Commit | Line | Data |
---|---|---|
e822f505 | 1 | /* |
c0c0989a MJ |
2 | * SPDX-License-Identifier: LGPL-2.1-only |
3 | * | |
e822f505 | 4 | * Copyright (C) 2009 Pierre-Marc Fournier |
3678c8aa | 5 | * Copyright (C) 2011-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
2d99476b PMF |
6 | */ |
7 | ||
9d315d6d MJ |
8 | /* Has to be included first to override dlfcn.h */ |
9 | #include <common/compat/dlfcn.h> | |
10 | ||
2d99476b PMF |
11 | #include <unistd.h> |
12 | #include <stdio.h> | |
df793c55 | 13 | #include <signal.h> |
616ed36a PMF |
14 | #include <sched.h> |
15 | #include <stdarg.h> | |
e2a195a6 | 16 | #include <stdlib.h> |
eb2b066f | 17 | #include <errno.h> |
2d99476b | 18 | |
d0c8f180 | 19 | #include <lttng/ust-fork.h> |
e822f505 | 20 | |
9db5701d OD |
21 | #include <urcu/uatomic.h> |
22 | ||
2d99476b PMF |
23 | pid_t fork(void) |
24 | { | |
25 | static pid_t (*plibc_func)(void) = NULL; | |
9db5701d | 26 | pid_t (*func)(void); |
7f0aeeba | 27 | sigset_t sigset; |
2d99476b | 28 | pid_t retval; |
111902ab | 29 | int saved_errno; |
2d99476b | 30 | |
9db5701d OD |
31 | func = uatomic_read(plibc_func); |
32 | if (func == NULL) { | |
33 | func = dlsym(RTLD_NEXT, "fork"); | |
34 | if (func == NULL) { | |
e822f505 | 35 | fprintf(stderr, "libustfork: unable to find \"fork\" symbol\n"); |
3678c8aa | 36 | errno = ENOSYS; |
2c10b7fd | 37 | return -1; |
2d99476b | 38 | } |
9db5701d | 39 | uatomic_set(&plibc_func, func); |
2d99476b PMF |
40 | } |
41 | ||
d0c8f180 | 42 | lttng_ust_before_fork(&sigset); |
df793c55 | 43 | /* Do the real fork */ |
9db5701d | 44 | retval = func(); |
111902ab | 45 | saved_errno = errno; |
e822f505 | 46 | if (retval == 0) { |
df793c55 | 47 | /* child */ |
d0c8f180 | 48 | lttng_ust_after_fork_child(&sigset); |
e822f505 | 49 | } else { |
d0c8f180 | 50 | lttng_ust_after_fork_parent(&sigset); |
df793c55 | 51 | } |
111902ab | 52 | errno = saved_errno; |
2d99476b PMF |
53 | return retval; |
54 | } | |
97b042a3 | 55 | |
2f6150e9 MD |
56 | int daemon(int nochdir, int noclose) |
57 | { | |
58 | static int (*plibc_func)(int nochdir, int noclose) = NULL; | |
9db5701d | 59 | int (*func)(int nochdir, int noclose); |
2f6150e9 MD |
60 | sigset_t sigset; |
61 | int retval; | |
111902ab | 62 | int saved_errno; |
2f6150e9 | 63 | |
9db5701d OD |
64 | func = uatomic_read(plibc_func); |
65 | if (func == NULL) { | |
66 | func = dlsym(RTLD_NEXT, "daemon"); | |
67 | if (func == NULL) { | |
2f6150e9 MD |
68 | fprintf(stderr, "libustfork: unable to find \"daemon\" symbol\n"); |
69 | errno = ENOSYS; | |
70 | return -1; | |
71 | } | |
9db5701d | 72 | uatomic_set(&plibc_func, func); |
2f6150e9 MD |
73 | } |
74 | ||
d0c8f180 | 75 | lttng_ust_before_fork(&sigset); |
2f6150e9 | 76 | /* Do the real daemon call */ |
9db5701d | 77 | retval = func(nochdir, noclose); |
111902ab | 78 | saved_errno = errno; |
2f6150e9 MD |
79 | if (retval == 0) { |
80 | /* child, parent called _exit() directly */ | |
d0c8f180 | 81 | lttng_ust_after_fork_child(&sigset); |
2f6150e9 MD |
82 | } else { |
83 | /* on error in the parent */ | |
d0c8f180 | 84 | lttng_ust_after_fork_parent(&sigset); |
2f6150e9 | 85 | } |
111902ab | 86 | errno = saved_errno; |
2f6150e9 MD |
87 | return retval; |
88 | } | |
89 | ||
fca2f191 MJ |
90 | int setuid(uid_t uid) |
91 | { | |
92 | static int (*plibc_func)(uid_t uid) = NULL; | |
9db5701d | 93 | int (*func)(uid_t uid); |
fca2f191 MJ |
94 | int retval; |
95 | int saved_errno; | |
96 | ||
9db5701d OD |
97 | func = uatomic_read(plibc_func); |
98 | if (func == NULL) { | |
99 | func = dlsym(RTLD_NEXT, "setuid"); | |
100 | if (func == NULL) { | |
fca2f191 MJ |
101 | fprintf(stderr, "libustfork: unable to find \"setuid\" symbol\n"); |
102 | errno = ENOSYS; | |
103 | return -1; | |
104 | } | |
9db5701d | 105 | uatomic_set(&plibc_func, func); |
fca2f191 MJ |
106 | } |
107 | ||
108 | /* Do the real setuid */ | |
9db5701d | 109 | retval = func(uid); |
fca2f191 MJ |
110 | saved_errno = errno; |
111 | ||
d0c8f180 | 112 | lttng_ust_after_setuid(); |
fca2f191 MJ |
113 | |
114 | errno = saved_errno; | |
115 | return retval; | |
116 | } | |
117 | ||
118 | int setgid(gid_t gid) | |
119 | { | |
120 | static int (*plibc_func)(gid_t gid) = NULL; | |
9db5701d | 121 | int (*func)(gid_t gid); |
fca2f191 MJ |
122 | int retval; |
123 | int saved_errno; | |
124 | ||
9db5701d OD |
125 | func = uatomic_read(plibc_func); |
126 | if (func == NULL) { | |
127 | func = dlsym(RTLD_NEXT, "setgid"); | |
128 | if (func == NULL) { | |
fca2f191 MJ |
129 | fprintf(stderr, "libustfork: unable to find \"setgid\" symbol\n"); |
130 | errno = ENOSYS; | |
131 | return -1; | |
132 | } | |
9db5701d | 133 | uatomic_set(&plibc_func, func); |
fca2f191 MJ |
134 | } |
135 | ||
136 | /* Do the real setgid */ | |
9db5701d | 137 | retval = func(gid); |
fca2f191 MJ |
138 | saved_errno = errno; |
139 | ||
d0c8f180 | 140 | lttng_ust_after_setgid(); |
fca2f191 MJ |
141 | |
142 | errno = saved_errno; | |
143 | return retval; | |
144 | } | |
145 | ||
146 | int seteuid(uid_t euid) | |
147 | { | |
148 | static int (*plibc_func)(uid_t euid) = NULL; | |
9db5701d | 149 | int (*func)(uid_t euid); |
fca2f191 MJ |
150 | int retval; |
151 | int saved_errno; | |
152 | ||
9db5701d OD |
153 | func = uatomic_read(plibc_func); |
154 | if (func == NULL) { | |
155 | func = dlsym(RTLD_NEXT, "seteuid"); | |
156 | if (func == NULL) { | |
fca2f191 MJ |
157 | fprintf(stderr, "libustfork: unable to find \"seteuid\" symbol\n"); |
158 | errno = ENOSYS; | |
159 | return -1; | |
160 | } | |
9db5701d | 161 | uatomic_set(&plibc_func, func); |
fca2f191 MJ |
162 | } |
163 | ||
164 | /* Do the real seteuid */ | |
9db5701d | 165 | retval = func(euid); |
fca2f191 MJ |
166 | saved_errno = errno; |
167 | ||
d0c8f180 | 168 | lttng_ust_after_seteuid(); |
fca2f191 MJ |
169 | |
170 | errno = saved_errno; | |
171 | return retval; | |
172 | } | |
173 | ||
174 | int setegid(gid_t egid) | |
175 | { | |
176 | static int (*plibc_func)(gid_t egid) = NULL; | |
9db5701d | 177 | int (*func)(gid_t egid); |
fca2f191 MJ |
178 | int retval; |
179 | int saved_errno; | |
180 | ||
9db5701d OD |
181 | func = uatomic_read(plibc_func); |
182 | if (func == NULL) { | |
183 | func = dlsym(RTLD_NEXT, "setegid"); | |
184 | if (func == NULL) { | |
fca2f191 MJ |
185 | fprintf(stderr, "libustfork: unable to find \"setegid\" symbol\n"); |
186 | errno = ENOSYS; | |
187 | return -1; | |
188 | } | |
9db5701d | 189 | uatomic_set(&plibc_func, func); |
fca2f191 MJ |
190 | } |
191 | ||
192 | /* Do the real setegid */ | |
9db5701d | 193 | retval = func(egid); |
fca2f191 MJ |
194 | saved_errno = errno; |
195 | ||
d0c8f180 | 196 | lttng_ust_after_setegid(); |
fca2f191 MJ |
197 | |
198 | errno = saved_errno; | |
199 | return retval; | |
200 | } | |
201 | ||
202 | int setreuid(uid_t ruid, uid_t euid) | |
203 | { | |
204 | static int (*plibc_func)(uid_t ruid, uid_t euid) = NULL; | |
9db5701d | 205 | int (*func)(uid_t ruid, uid_t euid); |
fca2f191 MJ |
206 | int retval; |
207 | int saved_errno; | |
208 | ||
9db5701d OD |
209 | func = uatomic_read(plibc_func); |
210 | if (func == NULL) { | |
211 | func = dlsym(RTLD_NEXT, "setreuid"); | |
212 | if (func == NULL) { | |
fca2f191 MJ |
213 | fprintf(stderr, "libustfork: unable to find \"setreuid\" symbol\n"); |
214 | errno = ENOSYS; | |
215 | return -1; | |
216 | } | |
9db5701d | 217 | uatomic_set(&plibc_func, func); |
fca2f191 MJ |
218 | } |
219 | ||
220 | /* Do the real setreuid */ | |
9db5701d | 221 | retval = func(ruid, euid); |
fca2f191 MJ |
222 | saved_errno = errno; |
223 | ||
d0c8f180 | 224 | lttng_ust_after_setreuid(); |
fca2f191 MJ |
225 | |
226 | errno = saved_errno; | |
227 | return retval; | |
228 | } | |
229 | ||
230 | int setregid(gid_t rgid, gid_t egid) | |
231 | { | |
232 | static int (*plibc_func)(gid_t rgid, gid_t egid) = NULL; | |
9db5701d | 233 | int (*func)(gid_t rgid, gid_t egid); |
fca2f191 MJ |
234 | int retval; |
235 | int saved_errno; | |
236 | ||
9db5701d OD |
237 | func = uatomic_read(plibc_func); |
238 | if (func == NULL) { | |
239 | func = dlsym(RTLD_NEXT, "setregid"); | |
240 | if (func == NULL) { | |
fca2f191 MJ |
241 | fprintf(stderr, "libustfork: unable to find \"setregid\" symbol\n"); |
242 | errno = ENOSYS; | |
243 | return -1; | |
244 | } | |
9db5701d | 245 | uatomic_set(&plibc_func, func); |
fca2f191 MJ |
246 | } |
247 | ||
248 | /* Do the real setregid */ | |
9db5701d | 249 | retval = func(rgid, egid); |
fca2f191 MJ |
250 | saved_errno = errno; |
251 | ||
d0c8f180 | 252 | lttng_ust_after_setregid(); |
fca2f191 MJ |
253 | |
254 | errno = saved_errno; | |
255 | return retval; | |
256 | } | |
257 | ||
939c89cb MD |
258 | #ifdef __linux__ |
259 | ||
260 | struct user_desc; | |
261 | ||
e822f505 | 262 | struct ustfork_clone_info { |
616ed36a PMF |
263 | int (*fn)(void *); |
264 | void *arg; | |
7f0aeeba | 265 | sigset_t sigset; |
616ed36a PMF |
266 | }; |
267 | ||
268 | static int clone_fn(void *arg) | |
269 | { | |
e822f505 | 270 | struct ustfork_clone_info *info = (struct ustfork_clone_info *) arg; |
616ed36a PMF |
271 | |
272 | /* clone is now done and we are in child */ | |
d0c8f180 | 273 | lttng_ust_after_fork_child(&info->sigset); |
616ed36a PMF |
274 | return info->fn(info->arg); |
275 | } | |
276 | ||
277 | int clone(int (*fn)(void *), void *child_stack, int flags, void *arg, ...) | |
278 | { | |
e822f505 MD |
279 | static int (*plibc_func)(int (*fn)(void *), void *child_stack, |
280 | int flags, void *arg, pid_t *ptid, | |
281 | struct user_desc *tls, pid_t *ctid) = NULL; | |
9db5701d OD |
282 | int (*func)(int (*fn)(void *), void *child_stack, |
283 | int flags, void *arg, pid_t *ptid, | |
284 | struct user_desc *tls, pid_t *ctid); | |
e822f505 | 285 | /* var args */ |
616ed36a PMF |
286 | pid_t *ptid; |
287 | struct user_desc *tls; | |
288 | pid_t *ctid; | |
e822f505 | 289 | /* end of var args */ |
616ed36a | 290 | va_list ap; |
e822f505 | 291 | int retval; |
111902ab | 292 | int saved_errno; |
616ed36a PMF |
293 | |
294 | va_start(ap, arg); | |
295 | ptid = va_arg(ap, pid_t *); | |
296 | tls = va_arg(ap, struct user_desc *); | |
297 | ctid = va_arg(ap, pid_t *); | |
298 | va_end(ap); | |
299 | ||
9db5701d OD |
300 | func = uatomic_read(plibc_func); |
301 | if (func == NULL) { | |
302 | func = dlsym(RTLD_NEXT, "clone"); | |
303 | if (func == NULL) { | |
e822f505 | 304 | fprintf(stderr, "libustfork: unable to find \"clone\" symbol.\n"); |
3678c8aa | 305 | errno = ENOSYS; |
616ed36a PMF |
306 | return -1; |
307 | } | |
9db5701d | 308 | uatomic_set(&plibc_func, func); |
616ed36a PMF |
309 | } |
310 | ||
e822f505 MD |
311 | if (flags & CLONE_VM) { |
312 | /* | |
313 | * Creating a thread, no need to intervene, just pass on | |
314 | * the arguments. | |
315 | */ | |
9db5701d OD |
316 | retval = func(fn, child_stack, flags, arg, ptid, |
317 | tls, ctid); | |
111902ab | 318 | saved_errno = errno; |
e822f505 MD |
319 | } else { |
320 | /* Creating a real process, we need to intervene. */ | |
3fd2b913 | 321 | struct ustfork_clone_info info = { .fn = fn, .arg = arg }; |
616ed36a | 322 | |
d0c8f180 | 323 | lttng_ust_before_fork(&info.sigset); |
9db5701d OD |
324 | retval = func(clone_fn, child_stack, flags, &info, |
325 | ptid, tls, ctid); | |
111902ab | 326 | saved_errno = errno; |
e822f505 | 327 | /* The child doesn't get here. */ |
d0c8f180 | 328 | lttng_ust_after_fork_parent(&info.sigset); |
616ed36a | 329 | } |
111902ab | 330 | errno = saved_errno; |
616ed36a PMF |
331 | return retval; |
332 | } | |
939c89cb | 333 | |
735bef47 MJ |
334 | int setns(int fd, int nstype) |
335 | { | |
336 | static int (*plibc_func)(int fd, int nstype) = NULL; | |
9db5701d | 337 | int (*func)(int fd, int nstype); |
735bef47 MJ |
338 | int retval; |
339 | int saved_errno; | |
340 | ||
9db5701d OD |
341 | func = uatomic_read(plibc_func); |
342 | if (func == NULL) { | |
343 | func = dlsym(RTLD_NEXT, "setns"); | |
344 | if (func == NULL) { | |
735bef47 MJ |
345 | fprintf(stderr, "libustfork: unable to find \"setns\" symbol\n"); |
346 | errno = ENOSYS; | |
347 | return -1; | |
348 | } | |
9db5701d | 349 | uatomic_set(&plibc_func, func); |
735bef47 MJ |
350 | } |
351 | ||
352 | /* Do the real setns */ | |
9db5701d | 353 | retval = func(fd, nstype); |
735bef47 MJ |
354 | saved_errno = errno; |
355 | ||
d0c8f180 | 356 | lttng_ust_after_setns(); |
735bef47 MJ |
357 | |
358 | errno = saved_errno; | |
359 | return retval; | |
360 | } | |
361 | ||
362 | int unshare(int flags) | |
363 | { | |
364 | static int (*plibc_func)(int flags) = NULL; | |
9db5701d | 365 | int (*func)(int flags); |
735bef47 MJ |
366 | int retval; |
367 | int saved_errno; | |
368 | ||
9db5701d OD |
369 | func = uatomic_read(plibc_func); |
370 | if (func == NULL) { | |
371 | func = dlsym(RTLD_NEXT, "unshare"); | |
372 | if (func == NULL) { | |
735bef47 MJ |
373 | fprintf(stderr, "libustfork: unable to find \"unshare\" symbol\n"); |
374 | errno = ENOSYS; | |
375 | return -1; | |
376 | } | |
9db5701d | 377 | uatomic_set(&plibc_func, func); |
735bef47 MJ |
378 | } |
379 | ||
380 | /* Do the real setns */ | |
9db5701d | 381 | retval = func(flags); |
735bef47 MJ |
382 | saved_errno = errno; |
383 | ||
d0c8f180 | 384 | lttng_ust_after_unshare(); |
735bef47 MJ |
385 | |
386 | errno = saved_errno; | |
387 | return retval; | |
388 | } | |
389 | ||
fca2f191 MJ |
390 | int setresuid(uid_t ruid, uid_t euid, uid_t suid) |
391 | { | |
392 | static int (*plibc_func)(uid_t ruid, uid_t euid, uid_t suid) = NULL; | |
9db5701d | 393 | int (*func)(uid_t ruid, uid_t euid, uid_t suid); |
fca2f191 MJ |
394 | int retval; |
395 | int saved_errno; | |
396 | ||
9db5701d OD |
397 | func = uatomic_read(plibc_func); |
398 | if (func == NULL) { | |
399 | func = dlsym(RTLD_NEXT, "setresuid"); | |
400 | if (func == NULL) { | |
fca2f191 MJ |
401 | fprintf(stderr, "libustfork: unable to find \"setresuid\" symbol\n"); |
402 | errno = ENOSYS; | |
403 | return -1; | |
404 | } | |
9db5701d | 405 | uatomic_set(&plibc_func, func); |
fca2f191 MJ |
406 | } |
407 | ||
408 | /* Do the real setresuid */ | |
9db5701d | 409 | retval = func(ruid, euid, suid); |
fca2f191 MJ |
410 | saved_errno = errno; |
411 | ||
d0c8f180 | 412 | lttng_ust_after_setresuid(); |
fca2f191 MJ |
413 | |
414 | errno = saved_errno; | |
415 | return retval; | |
416 | } | |
417 | ||
418 | int setresgid(gid_t rgid, gid_t egid, gid_t sgid) | |
419 | { | |
420 | static int (*plibc_func)(gid_t rgid, gid_t egid, gid_t sgid) = NULL; | |
9db5701d | 421 | int (*func)(gid_t rgid, gid_t egid, gid_t sgid); |
fca2f191 MJ |
422 | int retval; |
423 | int saved_errno; | |
424 | ||
9db5701d OD |
425 | func = uatomic_read(plibc_func); |
426 | if (func == NULL) { | |
427 | func = dlsym(RTLD_NEXT, "setresgid"); | |
428 | if (func == NULL) { | |
fca2f191 MJ |
429 | fprintf(stderr, "libustfork: unable to find \"setresgid\" symbol\n"); |
430 | errno = ENOSYS; | |
431 | return -1; | |
432 | } | |
9db5701d | 433 | uatomic_set(&plibc_func, func); |
fca2f191 MJ |
434 | } |
435 | ||
436 | /* Do the real setresgid */ | |
9db5701d | 437 | retval = func(rgid, egid, sgid); |
fca2f191 MJ |
438 | saved_errno = errno; |
439 | ||
d0c8f180 | 440 | lttng_ust_after_setresgid(); |
fca2f191 MJ |
441 | |
442 | errno = saved_errno; | |
443 | return retval; | |
444 | } | |
445 | ||
939c89cb MD |
446 | #elif defined (__FreeBSD__) |
447 | ||
448 | pid_t rfork(int flags) | |
449 | { | |
e2a195a6 | 450 | static pid_t (*plibc_func)(int flags) = NULL; |
9db5701d | 451 | pid_t (*func)(int flags); |
939c89cb MD |
452 | sigset_t sigset; |
453 | pid_t retval; | |
111902ab | 454 | int saved_errno; |
939c89cb | 455 | |
9db5701d OD |
456 | func = uatomic_read(plibc_func); |
457 | if (func == NULL) { | |
458 | func = dlsym(RTLD_NEXT, "rfork"); | |
459 | if (func == NULL) { | |
939c89cb | 460 | fprintf(stderr, "libustfork: unable to find \"rfork\" symbol\n"); |
3678c8aa | 461 | errno = ENOSYS; |
939c89cb MD |
462 | return -1; |
463 | } | |
9db5701d | 464 | uatomic_set(&plibc_func, func); |
939c89cb MD |
465 | } |
466 | ||
d0c8f180 | 467 | lttng_ust_before_fork(&sigset); |
939c89cb | 468 | /* Do the real rfork */ |
9db5701d | 469 | retval = func(flags); |
111902ab | 470 | saved_errno = errno; |
939c89cb MD |
471 | if (retval == 0) { |
472 | /* child */ | |
d0c8f180 | 473 | lttng_ust_after_fork_child(&sigset); |
939c89cb | 474 | } else { |
d0c8f180 | 475 | lttng_ust_after_fork_parent(&sigset); |
939c89cb | 476 | } |
111902ab | 477 | errno = saved_errno; |
939c89cb MD |
478 | return retval; |
479 | } | |
480 | ||
481 | /* | |
482 | * On BSD, no need to override vfork, because it runs in the context of | |
483 | * the parent, with parent waiting until execve or exit is executed in | |
484 | * the child. | |
485 | */ | |
486 | ||
487 | #else | |
488 | #warning "Unknown OS. You might want to ensure that fork/clone/vfork/fork handling is complete." | |
489 | #endif |