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