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
21 #include <lttng/ust-dlfcn.h>
29 #include <lttng/ust.h>
33 static pid_t (*plibc_func
)(void) = NULL
;
38 if (plibc_func
== NULL
) {
39 plibc_func
= dlsym(RTLD_NEXT
, "fork");
40 if (plibc_func
== NULL
) {
41 fprintf(stderr
, "libustfork: unable to find \"fork\" symbol\n");
47 ust_before_fork(&sigset
);
48 /* Do the real fork */
49 retval
= plibc_func();
53 ust_after_fork_child(&sigset
);
55 ust_after_fork_parent(&sigset
);
61 int daemon(int nochdir
, int noclose
)
63 static int (*plibc_func
)(int nochdir
, int noclose
) = NULL
;
68 if (plibc_func
== NULL
) {
69 plibc_func
= dlsym(RTLD_NEXT
, "daemon");
70 if (plibc_func
== NULL
) {
71 fprintf(stderr
, "libustfork: unable to find \"daemon\" symbol\n");
77 ust_before_fork(&sigset
);
78 /* Do the real daemon call */
79 retval
= plibc_func(nochdir
, noclose
);
82 /* child, parent called _exit() directly */
83 ust_after_fork_child(&sigset
);
85 /* on error in the parent */
86 ust_after_fork_parent(&sigset
);
94 static int (*plibc_func
)(uid_t uid
) = NULL
;
98 if (plibc_func
== NULL
) {
99 plibc_func
= dlsym(RTLD_NEXT
, "setuid");
100 if (plibc_func
== NULL
) {
101 fprintf(stderr
, "libustfork: unable to find \"setuid\" symbol\n");
107 /* Do the real setuid */
108 retval
= plibc_func(uid
);
117 int setgid(gid_t gid
)
119 static int (*plibc_func
)(gid_t gid
) = NULL
;
123 if (plibc_func
== NULL
) {
124 plibc_func
= dlsym(RTLD_NEXT
, "setgid");
125 if (plibc_func
== NULL
) {
126 fprintf(stderr
, "libustfork: unable to find \"setgid\" symbol\n");
132 /* Do the real setgid */
133 retval
= plibc_func(gid
);
142 int seteuid(uid_t euid
)
144 static int (*plibc_func
)(uid_t euid
) = NULL
;
148 if (plibc_func
== NULL
) {
149 plibc_func
= dlsym(RTLD_NEXT
, "seteuid");
150 if (plibc_func
== NULL
) {
151 fprintf(stderr
, "libustfork: unable to find \"seteuid\" symbol\n");
157 /* Do the real seteuid */
158 retval
= plibc_func(euid
);
167 int setegid(gid_t egid
)
169 static int (*plibc_func
)(gid_t egid
) = NULL
;
173 if (plibc_func
== NULL
) {
174 plibc_func
= dlsym(RTLD_NEXT
, "setegid");
175 if (plibc_func
== NULL
) {
176 fprintf(stderr
, "libustfork: unable to find \"setegid\" symbol\n");
182 /* Do the real setegid */
183 retval
= plibc_func(egid
);
192 int setreuid(uid_t ruid
, uid_t euid
)
194 static int (*plibc_func
)(uid_t ruid
, uid_t euid
) = NULL
;
198 if (plibc_func
== NULL
) {
199 plibc_func
= dlsym(RTLD_NEXT
, "setreuid");
200 if (plibc_func
== NULL
) {
201 fprintf(stderr
, "libustfork: unable to find \"setreuid\" symbol\n");
207 /* Do the real setreuid */
208 retval
= plibc_func(ruid
, euid
);
211 ust_after_setreuid();
217 int setregid(gid_t rgid
, gid_t egid
)
219 static int (*plibc_func
)(gid_t rgid
, gid_t egid
) = NULL
;
223 if (plibc_func
== NULL
) {
224 plibc_func
= dlsym(RTLD_NEXT
, "setregid");
225 if (plibc_func
== NULL
) {
226 fprintf(stderr
, "libustfork: unable to find \"setregid\" symbol\n");
232 /* Do the real setregid */
233 retval
= plibc_func(rgid
, egid
);
236 ust_after_setregid();
246 struct ustfork_clone_info
{
252 static int clone_fn(void *arg
)
254 struct ustfork_clone_info
*info
= (struct ustfork_clone_info
*) arg
;
256 /* clone is now done and we are in child */
257 ust_after_fork_child(&info
->sigset
);
258 return info
->fn(info
->arg
);
261 int clone(int (*fn
)(void *), void *child_stack
, int flags
, void *arg
, ...)
263 static int (*plibc_func
)(int (*fn
)(void *), void *child_stack
,
264 int flags
, void *arg
, pid_t
*ptid
,
265 struct user_desc
*tls
, pid_t
*ctid
) = NULL
;
268 struct user_desc
*tls
;
270 /* end of var args */
276 ptid
= va_arg(ap
, pid_t
*);
277 tls
= va_arg(ap
, struct user_desc
*);
278 ctid
= va_arg(ap
, pid_t
*);
281 if (plibc_func
== NULL
) {
282 plibc_func
= dlsym(RTLD_NEXT
, "clone");
283 if (plibc_func
== NULL
) {
284 fprintf(stderr
, "libustfork: unable to find \"clone\" symbol.\n");
290 if (flags
& CLONE_VM
) {
292 * Creating a thread, no need to intervene, just pass on
295 retval
= plibc_func(fn
, child_stack
, flags
, arg
, ptid
,
299 /* Creating a real process, we need to intervene. */
300 struct ustfork_clone_info info
= { .fn
= fn
, .arg
= arg
};
302 ust_before_fork(&info
.sigset
);
303 retval
= plibc_func(clone_fn
, child_stack
, flags
, &info
,
306 /* The child doesn't get here. */
307 ust_after_fork_parent(&info
.sigset
);
313 int setns(int fd
, int nstype
)
315 static int (*plibc_func
)(int fd
, int nstype
) = NULL
;
319 if (plibc_func
== NULL
) {
320 plibc_func
= dlsym(RTLD_NEXT
, "setns");
321 if (plibc_func
== NULL
) {
322 fprintf(stderr
, "libustfork: unable to find \"setns\" symbol\n");
328 /* Do the real setns */
329 retval
= plibc_func(fd
, nstype
);
338 int unshare(int flags
)
340 static int (*plibc_func
)(int flags
) = NULL
;
344 if (plibc_func
== NULL
) {
345 plibc_func
= dlsym(RTLD_NEXT
, "unshare");
346 if (plibc_func
== NULL
) {
347 fprintf(stderr
, "libustfork: unable to find \"unshare\" symbol\n");
353 /* Do the real setns */
354 retval
= plibc_func(flags
);
363 int setresuid(uid_t ruid
, uid_t euid
, uid_t suid
)
365 static int (*plibc_func
)(uid_t ruid
, uid_t euid
, uid_t suid
) = NULL
;
369 if (plibc_func
== NULL
) {
370 plibc_func
= dlsym(RTLD_NEXT
, "setresuid");
371 if (plibc_func
== NULL
) {
372 fprintf(stderr
, "libustfork: unable to find \"setresuid\" symbol\n");
378 /* Do the real setresuid */
379 retval
= plibc_func(ruid
, euid
, suid
);
382 ust_after_setresuid();
388 int setresgid(gid_t rgid
, gid_t egid
, gid_t sgid
)
390 static int (*plibc_func
)(gid_t rgid
, gid_t egid
, gid_t sgid
) = NULL
;
394 if (plibc_func
== NULL
) {
395 plibc_func
= dlsym(RTLD_NEXT
, "setresgid");
396 if (plibc_func
== NULL
) {
397 fprintf(stderr
, "libustfork: unable to find \"setresgid\" symbol\n");
403 /* Do the real setresgid */
404 retval
= plibc_func(rgid
, egid
, sgid
);
407 ust_after_setresgid();
413 #elif defined (__FreeBSD__)
415 pid_t
rfork(int flags
)
417 static pid_t (*plibc_func
)(void) = NULL
;
422 if (plibc_func
== NULL
) {
423 plibc_func
= dlsym(RTLD_NEXT
, "rfork");
424 if (plibc_func
== NULL
) {
425 fprintf(stderr
, "libustfork: unable to find \"rfork\" symbol\n");
431 ust_before_fork(&sigset
);
432 /* Do the real rfork */
433 retval
= plibc_func();
437 ust_after_fork_child(&sigset
);
439 ust_after_fork_parent(&sigset
);
446 * On BSD, no need to override vfork, because it runs in the context of
447 * the parent, with parent waiting until execve or exit is executed in
452 #warning "Unknown OS. You might want to ensure that fork/clone/vfork/fork handling is complete."
This page took 0.039872 seconds and 4 git commands to generate.