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