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>
30 #include <lttng/ust.h>
34 static pid_t (*plibc_func
)(void) = NULL
;
39 if (plibc_func
== NULL
) {
40 plibc_func
= dlsym(RTLD_NEXT
, "fork");
41 if (plibc_func
== NULL
) {
42 fprintf(stderr
, "libustfork: unable to find \"fork\" symbol\n");
48 ust_before_fork(&sigset
);
49 /* Do the real fork */
50 retval
= plibc_func();
54 ust_after_fork_child(&sigset
);
56 ust_after_fork_parent(&sigset
);
62 int daemon(int nochdir
, int noclose
)
64 static int (*plibc_func
)(int nochdir
, int noclose
) = NULL
;
69 if (plibc_func
== NULL
) {
70 plibc_func
= dlsym(RTLD_NEXT
, "daemon");
71 if (plibc_func
== NULL
) {
72 fprintf(stderr
, "libustfork: unable to find \"daemon\" symbol\n");
78 ust_before_fork(&sigset
);
79 /* Do the real daemon call */
80 retval
= plibc_func(nochdir
, noclose
);
83 /* child, parent called _exit() directly */
84 ust_after_fork_child(&sigset
);
86 /* on error in the parent */
87 ust_after_fork_parent(&sigset
);
95 static int (*plibc_func
)(uid_t uid
) = NULL
;
99 if (plibc_func
== NULL
) {
100 plibc_func
= dlsym(RTLD_NEXT
, "setuid");
101 if (plibc_func
== NULL
) {
102 fprintf(stderr
, "libustfork: unable to find \"setuid\" symbol\n");
108 /* Do the real setuid */
109 retval
= plibc_func(uid
);
118 int setgid(gid_t gid
)
120 static int (*plibc_func
)(gid_t gid
) = NULL
;
124 if (plibc_func
== NULL
) {
125 plibc_func
= dlsym(RTLD_NEXT
, "setgid");
126 if (plibc_func
== NULL
) {
127 fprintf(stderr
, "libustfork: unable to find \"setgid\" symbol\n");
133 /* Do the real setgid */
134 retval
= plibc_func(gid
);
143 int seteuid(uid_t euid
)
145 static int (*plibc_func
)(uid_t euid
) = NULL
;
149 if (plibc_func
== NULL
) {
150 plibc_func
= dlsym(RTLD_NEXT
, "seteuid");
151 if (plibc_func
== NULL
) {
152 fprintf(stderr
, "libustfork: unable to find \"seteuid\" symbol\n");
158 /* Do the real seteuid */
159 retval
= plibc_func(euid
);
168 int setegid(gid_t egid
)
170 static int (*plibc_func
)(gid_t egid
) = NULL
;
174 if (plibc_func
== NULL
) {
175 plibc_func
= dlsym(RTLD_NEXT
, "setegid");
176 if (plibc_func
== NULL
) {
177 fprintf(stderr
, "libustfork: unable to find \"setegid\" symbol\n");
183 /* Do the real setegid */
184 retval
= plibc_func(egid
);
193 int setreuid(uid_t ruid
, uid_t euid
)
195 static int (*plibc_func
)(uid_t ruid
, uid_t euid
) = NULL
;
199 if (plibc_func
== NULL
) {
200 plibc_func
= dlsym(RTLD_NEXT
, "setreuid");
201 if (plibc_func
== NULL
) {
202 fprintf(stderr
, "libustfork: unable to find \"setreuid\" symbol\n");
208 /* Do the real setreuid */
209 retval
= plibc_func(ruid
, euid
);
212 ust_after_setreuid();
218 int setregid(gid_t rgid
, gid_t egid
)
220 static int (*plibc_func
)(gid_t rgid
, gid_t egid
) = NULL
;
224 if (plibc_func
== NULL
) {
225 plibc_func
= dlsym(RTLD_NEXT
, "setregid");
226 if (plibc_func
== NULL
) {
227 fprintf(stderr
, "libustfork: unable to find \"setregid\" symbol\n");
233 /* Do the real setregid */
234 retval
= plibc_func(rgid
, egid
);
237 ust_after_setregid();
247 struct ustfork_clone_info
{
253 static int clone_fn(void *arg
)
255 struct ustfork_clone_info
*info
= (struct ustfork_clone_info
*) arg
;
257 /* clone is now done and we are in child */
258 ust_after_fork_child(&info
->sigset
);
259 return info
->fn(info
->arg
);
262 int clone(int (*fn
)(void *), void *child_stack
, int flags
, void *arg
, ...)
264 static int (*plibc_func
)(int (*fn
)(void *), void *child_stack
,
265 int flags
, void *arg
, pid_t
*ptid
,
266 struct user_desc
*tls
, pid_t
*ctid
) = NULL
;
269 struct user_desc
*tls
;
271 /* end of var args */
277 ptid
= va_arg(ap
, pid_t
*);
278 tls
= va_arg(ap
, struct user_desc
*);
279 ctid
= va_arg(ap
, pid_t
*);
282 if (plibc_func
== NULL
) {
283 plibc_func
= dlsym(RTLD_NEXT
, "clone");
284 if (plibc_func
== NULL
) {
285 fprintf(stderr
, "libustfork: unable to find \"clone\" symbol.\n");
291 if (flags
& CLONE_VM
) {
293 * Creating a thread, no need to intervene, just pass on
296 retval
= plibc_func(fn
, child_stack
, flags
, arg
, ptid
,
300 /* Creating a real process, we need to intervene. */
301 struct ustfork_clone_info info
= { .fn
= fn
, .arg
= arg
};
303 ust_before_fork(&info
.sigset
);
304 retval
= plibc_func(clone_fn
, child_stack
, flags
, &info
,
307 /* The child doesn't get here. */
308 ust_after_fork_parent(&info
.sigset
);
314 int setns(int fd
, int nstype
)
316 static int (*plibc_func
)(int fd
, int nstype
) = NULL
;
320 if (plibc_func
== NULL
) {
321 plibc_func
= dlsym(RTLD_NEXT
, "setns");
322 if (plibc_func
== NULL
) {
323 fprintf(stderr
, "libustfork: unable to find \"setns\" symbol\n");
329 /* Do the real setns */
330 retval
= plibc_func(fd
, nstype
);
339 int unshare(int flags
)
341 static int (*plibc_func
)(int flags
) = NULL
;
345 if (plibc_func
== NULL
) {
346 plibc_func
= dlsym(RTLD_NEXT
, "unshare");
347 if (plibc_func
== NULL
) {
348 fprintf(stderr
, "libustfork: unable to find \"unshare\" symbol\n");
354 /* Do the real setns */
355 retval
= plibc_func(flags
);
364 int setresuid(uid_t ruid
, uid_t euid
, uid_t suid
)
366 static int (*plibc_func
)(uid_t ruid
, uid_t euid
, uid_t suid
) = NULL
;
370 if (plibc_func
== NULL
) {
371 plibc_func
= dlsym(RTLD_NEXT
, "setresuid");
372 if (plibc_func
== NULL
) {
373 fprintf(stderr
, "libustfork: unable to find \"setresuid\" symbol\n");
379 /* Do the real setresuid */
380 retval
= plibc_func(ruid
, euid
, suid
);
383 ust_after_setresuid();
389 int setresgid(gid_t rgid
, gid_t egid
, gid_t sgid
)
391 static int (*plibc_func
)(gid_t rgid
, gid_t egid
, gid_t sgid
) = NULL
;
395 if (plibc_func
== NULL
) {
396 plibc_func
= dlsym(RTLD_NEXT
, "setresgid");
397 if (plibc_func
== NULL
) {
398 fprintf(stderr
, "libustfork: unable to find \"setresgid\" symbol\n");
404 /* Do the real setresgid */
405 retval
= plibc_func(rgid
, egid
, sgid
);
408 ust_after_setresgid();
414 #elif defined (__FreeBSD__)
416 pid_t
rfork(int flags
)
418 static pid_t (*plibc_func
)(int flags
) = NULL
;
423 if (plibc_func
== NULL
) {
424 plibc_func
= dlsym(RTLD_NEXT
, "rfork");
425 if (plibc_func
== NULL
) {
426 fprintf(stderr
, "libustfork: unable to find \"rfork\" symbol\n");
432 ust_before_fork(&sigset
);
433 /* Do the real rfork */
434 retval
= plibc_func(flags
);
438 ust_after_fork_child(&sigset
);
440 ust_after_fork_parent(&sigset
);
447 * On BSD, no need to override vfork, because it runs in the context of
448 * the parent, with parent waiting until execve or exit is executed in
453 #warning "Unknown OS. You might want to ensure that fork/clone/vfork/fork handling is complete."
This page took 0.039253 seconds and 4 git commands to generate.