2 * Copyright (C) 2009 Pierre-Marc Fournier
3 * Copyright (C) 2011-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; version 2.1 of
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.
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
20 #include <lttng/ust-dlfcn.h>
28 #include <lttng/ust.h>
32 static pid_t (*plibc_func
)(void) = NULL
;
37 if (plibc_func
== NULL
) {
38 plibc_func
= dlsym(RTLD_NEXT
, "fork");
39 if (plibc_func
== NULL
) {
40 fprintf(stderr
, "libustfork: unable to find \"fork\" symbol\n");
46 ust_before_fork(&sigset
);
47 /* Do the real fork */
48 retval
= plibc_func();
52 ust_after_fork_child(&sigset
);
54 ust_after_fork_parent(&sigset
);
60 int daemon(int nochdir
, int noclose
)
62 static int (*plibc_func
)(int nochdir
, int noclose
) = NULL
;
67 if (plibc_func
== NULL
) {
68 plibc_func
= dlsym(RTLD_NEXT
, "daemon");
69 if (plibc_func
== NULL
) {
70 fprintf(stderr
, "libustfork: unable to find \"daemon\" symbol\n");
76 ust_before_fork(&sigset
);
77 /* Do the real daemon call */
78 retval
= plibc_func(nochdir
, noclose
);
81 /* child, parent called _exit() directly */
82 ust_after_fork_child(&sigset
);
84 /* on error in the parent */
85 ust_after_fork_parent(&sigset
);
93 static int (*plibc_func
)(uid_t uid
) = NULL
;
97 if (plibc_func
== NULL
) {
98 plibc_func
= dlsym(RTLD_NEXT
, "setuid");
99 if (plibc_func
== NULL
) {
100 fprintf(stderr
, "libustfork: unable to find \"setuid\" symbol\n");
106 /* Do the real setuid */
107 retval
= plibc_func(uid
);
116 int setgid(gid_t gid
)
118 static int (*plibc_func
)(gid_t gid
) = NULL
;
122 if (plibc_func
== NULL
) {
123 plibc_func
= dlsym(RTLD_NEXT
, "setgid");
124 if (plibc_func
== NULL
) {
125 fprintf(stderr
, "libustfork: unable to find \"setgid\" symbol\n");
131 /* Do the real setgid */
132 retval
= plibc_func(gid
);
141 int seteuid(uid_t euid
)
143 static int (*plibc_func
)(uid_t euid
) = NULL
;
147 if (plibc_func
== NULL
) {
148 plibc_func
= dlsym(RTLD_NEXT
, "seteuid");
149 if (plibc_func
== NULL
) {
150 fprintf(stderr
, "libustfork: unable to find \"seteuid\" symbol\n");
156 /* Do the real seteuid */
157 retval
= plibc_func(euid
);
166 int setegid(gid_t egid
)
168 static int (*plibc_func
)(gid_t egid
) = NULL
;
172 if (plibc_func
== NULL
) {
173 plibc_func
= dlsym(RTLD_NEXT
, "setegid");
174 if (plibc_func
== NULL
) {
175 fprintf(stderr
, "libustfork: unable to find \"setegid\" symbol\n");
181 /* Do the real setegid */
182 retval
= plibc_func(egid
);
191 int setreuid(uid_t ruid
, uid_t euid
)
193 static int (*plibc_func
)(uid_t ruid
, uid_t euid
) = NULL
;
197 if (plibc_func
== NULL
) {
198 plibc_func
= dlsym(RTLD_NEXT
, "setreuid");
199 if (plibc_func
== NULL
) {
200 fprintf(stderr
, "libustfork: unable to find \"setreuid\" symbol\n");
206 /* Do the real setreuid */
207 retval
= plibc_func(ruid
, euid
);
210 ust_after_setreuid();
216 int setregid(gid_t rgid
, gid_t egid
)
218 static int (*plibc_func
)(gid_t rgid
, gid_t egid
) = NULL
;
222 if (plibc_func
== NULL
) {
223 plibc_func
= dlsym(RTLD_NEXT
, "setregid");
224 if (plibc_func
== NULL
) {
225 fprintf(stderr
, "libustfork: unable to find \"setregid\" symbol\n");
231 /* Do the real setregid */
232 retval
= plibc_func(rgid
, egid
);
235 ust_after_setregid();
245 struct ustfork_clone_info
{
251 static int clone_fn(void *arg
)
253 struct ustfork_clone_info
*info
= (struct ustfork_clone_info
*) arg
;
255 /* clone is now done and we are in child */
256 ust_after_fork_child(&info
->sigset
);
257 return info
->fn(info
->arg
);
260 int clone(int (*fn
)(void *), void *child_stack
, int flags
, void *arg
, ...)
262 static int (*plibc_func
)(int (*fn
)(void *), void *child_stack
,
263 int flags
, void *arg
, pid_t
*ptid
,
264 struct user_desc
*tls
, pid_t
*ctid
) = NULL
;
267 struct user_desc
*tls
;
269 /* end of var args */
275 ptid
= va_arg(ap
, pid_t
*);
276 tls
= va_arg(ap
, struct user_desc
*);
277 ctid
= va_arg(ap
, pid_t
*);
280 if (plibc_func
== NULL
) {
281 plibc_func
= dlsym(RTLD_NEXT
, "clone");
282 if (plibc_func
== NULL
) {
283 fprintf(stderr
, "libustfork: unable to find \"clone\" symbol.\n");
289 if (flags
& CLONE_VM
) {
291 * Creating a thread, no need to intervene, just pass on
294 retval
= plibc_func(fn
, child_stack
, flags
, arg
, ptid
,
298 /* Creating a real process, we need to intervene. */
299 struct ustfork_clone_info info
= { .fn
= fn
, .arg
= arg
};
301 ust_before_fork(&info
.sigset
);
302 retval
= plibc_func(clone_fn
, child_stack
, flags
, &info
,
305 /* The child doesn't get here. */
306 ust_after_fork_parent(&info
.sigset
);
312 int setns(int fd
, int nstype
)
314 static int (*plibc_func
)(int fd
, int nstype
) = NULL
;
318 if (plibc_func
== NULL
) {
319 plibc_func
= dlsym(RTLD_NEXT
, "setns");
320 if (plibc_func
== NULL
) {
321 fprintf(stderr
, "libustfork: unable to find \"setns\" symbol\n");
327 /* Do the real setns */
328 retval
= plibc_func(fd
, nstype
);
337 int unshare(int flags
)
339 static int (*plibc_func
)(int flags
) = NULL
;
343 if (plibc_func
== NULL
) {
344 plibc_func
= dlsym(RTLD_NEXT
, "unshare");
345 if (plibc_func
== NULL
) {
346 fprintf(stderr
, "libustfork: unable to find \"unshare\" symbol\n");
352 /* Do the real setns */
353 retval
= plibc_func(flags
);
362 int setresuid(uid_t ruid
, uid_t euid
, uid_t suid
)
364 static int (*plibc_func
)(uid_t ruid
, uid_t euid
, uid_t suid
) = NULL
;
368 if (plibc_func
== NULL
) {
369 plibc_func
= dlsym(RTLD_NEXT
, "setresuid");
370 if (plibc_func
== NULL
) {
371 fprintf(stderr
, "libustfork: unable to find \"setresuid\" symbol\n");
377 /* Do the real setresuid */
378 retval
= plibc_func(ruid
, euid
, suid
);
381 ust_after_setresuid();
387 int setresgid(gid_t rgid
, gid_t egid
, gid_t sgid
)
389 static int (*plibc_func
)(gid_t rgid
, gid_t egid
, gid_t sgid
) = NULL
;
393 if (plibc_func
== NULL
) {
394 plibc_func
= dlsym(RTLD_NEXT
, "setresgid");
395 if (plibc_func
== NULL
) {
396 fprintf(stderr
, "libustfork: unable to find \"setresgid\" symbol\n");
402 /* Do the real setresgid */
403 retval
= plibc_func(rgid
, egid
, sgid
);
406 ust_after_setresgid();
412 #elif defined (__FreeBSD__)
414 pid_t
rfork(int flags
)
416 static pid_t (*plibc_func
)(void) = NULL
;
421 if (plibc_func
== NULL
) {
422 plibc_func
= dlsym(RTLD_NEXT
, "rfork");
423 if (plibc_func
== NULL
) {
424 fprintf(stderr
, "libustfork: unable to find \"rfork\" symbol\n");
430 ust_before_fork(&sigset
);
431 /* Do the real rfork */
432 retval
= plibc_func();
436 ust_after_fork_child(&sigset
);
438 ust_after_fork_parent(&sigset
);
445 * On BSD, no need to override vfork, because it runs in the context of
446 * the parent, with parent waiting until execve or exit is executed in
451 #warning "Unknown OS. You might want to ensure that fork/clone/vfork/fork handling is complete."
This page took 0.0412 seconds and 5 git commands to generate.