2 * SPDX-License-Identifier: LGPL-2.1-only
4 * Copyright (C) 2009 Pierre-Marc Fournier
5 * Copyright (C) 2011-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
8 /* Has to be included first to override dlfcn.h */
9 #include <common/compat/dlfcn.h>
19 #include <lttng/ust-fork.h>
23 static pid_t (*plibc_func
)(void) = NULL
;
28 if (plibc_func
== NULL
) {
29 plibc_func
= dlsym(RTLD_NEXT
, "fork");
30 if (plibc_func
== NULL
) {
31 fprintf(stderr
, "libustfork: unable to find \"fork\" symbol\n");
37 lttng_ust_before_fork(&sigset
);
38 /* Do the real fork */
39 retval
= plibc_func();
43 lttng_ust_after_fork_child(&sigset
);
45 lttng_ust_after_fork_parent(&sigset
);
51 int daemon(int nochdir
, int noclose
)
53 static int (*plibc_func
)(int nochdir
, int noclose
) = NULL
;
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");
67 lttng_ust_before_fork(&sigset
);
68 /* Do the real daemon call */
69 retval
= plibc_func(nochdir
, noclose
);
72 /* child, parent called _exit() directly */
73 lttng_ust_after_fork_child(&sigset
);
75 /* on error in the parent */
76 lttng_ust_after_fork_parent(&sigset
);
84 static int (*plibc_func
)(uid_t uid
) = NULL
;
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");
97 /* Do the real setuid */
98 retval
= plibc_func(uid
);
101 lttng_ust_after_setuid();
107 int setgid(gid_t gid
)
109 static int (*plibc_func
)(gid_t gid
) = NULL
;
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");
122 /* Do the real setgid */
123 retval
= plibc_func(gid
);
126 lttng_ust_after_setgid();
132 int seteuid(uid_t euid
)
134 static int (*plibc_func
)(uid_t euid
) = NULL
;
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");
147 /* Do the real seteuid */
148 retval
= plibc_func(euid
);
151 lttng_ust_after_seteuid();
157 int setegid(gid_t egid
)
159 static int (*plibc_func
)(gid_t egid
) = NULL
;
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");
172 /* Do the real setegid */
173 retval
= plibc_func(egid
);
176 lttng_ust_after_setegid();
182 int setreuid(uid_t ruid
, uid_t euid
)
184 static int (*plibc_func
)(uid_t ruid
, uid_t euid
) = NULL
;
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");
197 /* Do the real setreuid */
198 retval
= plibc_func(ruid
, euid
);
201 lttng_ust_after_setreuid();
207 int setregid(gid_t rgid
, gid_t egid
)
209 static int (*plibc_func
)(gid_t rgid
, gid_t egid
) = NULL
;
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");
222 /* Do the real setregid */
223 retval
= plibc_func(rgid
, egid
);
226 lttng_ust_after_setregid();
236 struct ustfork_clone_info
{
242 static int clone_fn(void *arg
)
244 struct ustfork_clone_info
*info
= (struct ustfork_clone_info
*) arg
;
246 /* clone is now done and we are in child */
247 lttng_ust_after_fork_child(&info
->sigset
);
248 return info
->fn(info
->arg
);
251 int clone(int (*fn
)(void *), void *child_stack
, int flags
, void *arg
, ...)
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
;
258 struct user_desc
*tls
;
260 /* end of var args */
266 ptid
= va_arg(ap
, pid_t
*);
267 tls
= va_arg(ap
, struct user_desc
*);
268 ctid
= va_arg(ap
, pid_t
*);
271 if (plibc_func
== NULL
) {
272 plibc_func
= dlsym(RTLD_NEXT
, "clone");
273 if (plibc_func
== NULL
) {
274 fprintf(stderr
, "libustfork: unable to find \"clone\" symbol.\n");
280 if (flags
& CLONE_VM
) {
282 * Creating a thread, no need to intervene, just pass on
285 retval
= plibc_func(fn
, child_stack
, flags
, arg
, ptid
,
289 /* Creating a real process, we need to intervene. */
290 struct ustfork_clone_info info
= { .fn
= fn
, .arg
= arg
};
292 lttng_ust_before_fork(&info
.sigset
);
293 retval
= plibc_func(clone_fn
, child_stack
, flags
, &info
,
296 /* The child doesn't get here. */
297 lttng_ust_after_fork_parent(&info
.sigset
);
303 int setns(int fd
, int nstype
)
305 static int (*plibc_func
)(int fd
, int nstype
) = NULL
;
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");
318 /* Do the real setns */
319 retval
= plibc_func(fd
, nstype
);
322 lttng_ust_after_setns();
328 int unshare(int flags
)
330 static int (*plibc_func
)(int flags
) = NULL
;
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");
343 /* Do the real setns */
344 retval
= plibc_func(flags
);
347 lttng_ust_after_unshare();
353 int setresuid(uid_t ruid
, uid_t euid
, uid_t suid
)
355 static int (*plibc_func
)(uid_t ruid
, uid_t euid
, uid_t suid
) = NULL
;
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");
368 /* Do the real setresuid */
369 retval
= plibc_func(ruid
, euid
, suid
);
372 lttng_ust_after_setresuid();
378 int setresgid(gid_t rgid
, gid_t egid
, gid_t sgid
)
380 static int (*plibc_func
)(gid_t rgid
, gid_t egid
, gid_t sgid
) = NULL
;
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");
393 /* Do the real setresgid */
394 retval
= plibc_func(rgid
, egid
, sgid
);
397 lttng_ust_after_setresgid();
403 #elif defined (__FreeBSD__)
405 pid_t
rfork(int flags
)
407 static pid_t (*plibc_func
)(int flags
) = NULL
;
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");
421 lttng_ust_before_fork(&sigset
);
422 /* Do the real rfork */
423 retval
= plibc_func(flags
);
427 lttng_ust_after_fork_child(&sigset
);
429 lttng_ust_after_fork_parent(&sigset
);
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
442 #warning "Unknown OS. You might want to ensure that fork/clone/vfork/fork handling is complete."
This page took 0.048804 seconds and 4 git commands to generate.