ustfork: Fix possible race conditions
[lttng-ust.git] / src / lib / lttng-ust-fork / ustfork.c
CommitLineData
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
cf54f06a
OD
21#include <urcu/uatomic.h>
22
2d99476b
PMF
23pid_t fork(void)
24{
25 static pid_t (*plibc_func)(void) = NULL;
cf54f06a 26 pid_t (*func)(void);
7f0aeeba 27 sigset_t sigset;
2d99476b 28 pid_t retval;
111902ab 29 int saved_errno;
2d99476b 30
cf54f06a
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 }
cf54f06a 39 uatomic_set(&plibc_func, func);
2d99476b
PMF
40 }
41
d0c8f180 42 lttng_ust_before_fork(&sigset);
df793c55 43 /* Do the real fork */
cf54f06a 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
56int daemon(int nochdir, int noclose)
57{
58 static int (*plibc_func)(int nochdir, int noclose) = NULL;
cf54f06a 59 int (*func)(int nochdir, int noclose);
2f6150e9
MD
60 sigset_t sigset;
61 int retval;
111902ab 62 int saved_errno;
2f6150e9 63
cf54f06a
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 }
cf54f06a 72 uatomic_set(&plibc_func, func);
2f6150e9
MD
73 }
74
d0c8f180 75 lttng_ust_before_fork(&sigset);
2f6150e9 76 /* Do the real daemon call */
cf54f06a 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
90int setuid(uid_t uid)
91{
92 static int (*plibc_func)(uid_t uid) = NULL;
cf54f06a 93 int (*func)(uid_t uid);
fca2f191
MJ
94 int retval;
95 int saved_errno;
96
cf54f06a
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 }
cf54f06a 105 uatomic_set(&plibc_func, func);
fca2f191
MJ
106 }
107
108 /* Do the real setuid */
cf54f06a 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
118int setgid(gid_t gid)
119{
120 static int (*plibc_func)(gid_t gid) = NULL;
cf54f06a 121 int (*func)(gid_t gid);
fca2f191
MJ
122 int retval;
123 int saved_errno;
124
cf54f06a
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 }
cf54f06a 133 uatomic_set(&plibc_func, func);
fca2f191
MJ
134 }
135
136 /* Do the real setgid */
cf54f06a 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
146int seteuid(uid_t euid)
147{
148 static int (*plibc_func)(uid_t euid) = NULL;
cf54f06a 149 int (*func)(uid_t euid);
fca2f191
MJ
150 int retval;
151 int saved_errno;
152
cf54f06a
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 }
cf54f06a 161 uatomic_set(&plibc_func, func);
fca2f191
MJ
162 }
163
164 /* Do the real seteuid */
cf54f06a 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
174int setegid(gid_t egid)
175{
176 static int (*plibc_func)(gid_t egid) = NULL;
cf54f06a 177 int (*func)(gid_t egid);
fca2f191
MJ
178 int retval;
179 int saved_errno;
180
cf54f06a
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 }
cf54f06a 189 uatomic_set(&plibc_func, func);
fca2f191
MJ
190 }
191
192 /* Do the real setegid */
cf54f06a 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
202int setreuid(uid_t ruid, uid_t euid)
203{
204 static int (*plibc_func)(uid_t ruid, uid_t euid) = NULL;
cf54f06a 205 int (*func)(uid_t ruid, uid_t euid);
fca2f191
MJ
206 int retval;
207 int saved_errno;
208
cf54f06a
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 }
cf54f06a 217 uatomic_set(&plibc_func, func);
fca2f191
MJ
218 }
219
220 /* Do the real setreuid */
cf54f06a 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
230int setregid(gid_t rgid, gid_t egid)
231{
232 static int (*plibc_func)(gid_t rgid, gid_t egid) = NULL;
cf54f06a 233 int (*func)(gid_t rgid, gid_t egid);
fca2f191
MJ
234 int retval;
235 int saved_errno;
236
cf54f06a
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 }
cf54f06a 245 uatomic_set(&plibc_func, func);
fca2f191
MJ
246 }
247
248 /* Do the real setregid */
cf54f06a 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
260struct user_desc;
261
e822f505 262struct ustfork_clone_info {
616ed36a
PMF
263 int (*fn)(void *);
264 void *arg;
7f0aeeba 265 sigset_t sigset;
616ed36a
PMF
266};
267
268static 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
277int 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;
cf54f06a
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
cf54f06a
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 }
cf54f06a 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 */
cf54f06a
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);
cf54f06a
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
334int setns(int fd, int nstype)
335{
336 static int (*plibc_func)(int fd, int nstype) = NULL;
cf54f06a 337 int (*func)(int fd, int nstype);
735bef47
MJ
338 int retval;
339 int saved_errno;
340
cf54f06a
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 }
cf54f06a 349 uatomic_set(&plibc_func, func);
735bef47
MJ
350 }
351
352 /* Do the real setns */
cf54f06a 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
362int unshare(int flags)
363{
364 static int (*plibc_func)(int flags) = NULL;
cf54f06a 365 int (*func)(int flags);
735bef47
MJ
366 int retval;
367 int saved_errno;
368
cf54f06a
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 }
cf54f06a 377 uatomic_set(&plibc_func, func);
735bef47
MJ
378 }
379
380 /* Do the real setns */
cf54f06a 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
390int 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;
cf54f06a 393 int (*func)(uid_t ruid, uid_t euid, uid_t suid);
fca2f191
MJ
394 int retval;
395 int saved_errno;
396
cf54f06a
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 }
cf54f06a 405 uatomic_set(&plibc_func, func);
fca2f191
MJ
406 }
407
408 /* Do the real setresuid */
cf54f06a 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
418int 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;
cf54f06a 421 int (*func)(gid_t rgid, gid_t egid, gid_t sgid);
fca2f191
MJ
422 int retval;
423 int saved_errno;
424
cf54f06a
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 }
cf54f06a 433 uatomic_set(&plibc_func, func);
fca2f191
MJ
434 }
435
436 /* Do the real setresgid */
cf54f06a 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
448pid_t rfork(int flags)
449{
e2a195a6 450 static pid_t (*plibc_func)(int flags) = NULL;
cf54f06a 451 pid_t (*func)(int flags);
939c89cb
MD
452 sigset_t sigset;
453 pid_t retval;
111902ab 454 int saved_errno;
939c89cb 455
cf54f06a
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 }
cf54f06a 464 uatomic_set(&plibc_func, func);
939c89cb
MD
465 }
466
d0c8f180 467 lttng_ust_before_fork(&sigset);
939c89cb 468 /* Do the real rfork */
cf54f06a 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
This page took 0.061825 seconds and 4 git commands to generate.