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