Fix: FreeBSD: Pass flags arguments to rfork wrapper
[lttng-ust.git] / liblttng-ust-fork / ustfork.c
CommitLineData
e822f505
MD
1/*
2 * Copyright (C) 2009 Pierre-Marc Fournier
3678c8aa 3 * Copyright (C) 2011-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
2d99476b
PMF
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
e822f505
MD
7 * License as published by the Free Software Foundation; version 2.1 of
8 * the License.
2d99476b
PMF
9 *
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.
14 *
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
18 */
19
20#define _GNU_SOURCE
f02baefb 21#include <lttng/ust-dlfcn.h>
2d99476b
PMF
22#include <unistd.h>
23#include <stdio.h>
df793c55 24#include <signal.h>
616ed36a
PMF
25#include <sched.h>
26#include <stdarg.h>
b115a3fc 27#include <stdlib.h>
eb2b066f 28#include <errno.h>
2d99476b 29
4318ae1b 30#include <lttng/ust.h>
e822f505 31
2d99476b
PMF
32pid_t fork(void)
33{
34 static pid_t (*plibc_func)(void) = NULL;
7f0aeeba 35 sigset_t sigset;
2d99476b 36 pid_t retval;
111902ab 37 int saved_errno;
2d99476b 38
e822f505 39 if (plibc_func == NULL) {
2d99476b 40 plibc_func = dlsym(RTLD_NEXT, "fork");
e822f505
MD
41 if (plibc_func == NULL) {
42 fprintf(stderr, "libustfork: unable to find \"fork\" symbol\n");
3678c8aa 43 errno = ENOSYS;
2c10b7fd 44 return -1;
2d99476b
PMF
45 }
46 }
47
7f0aeeba 48 ust_before_fork(&sigset);
df793c55 49 /* Do the real fork */
2d99476b 50 retval = plibc_func();
111902ab 51 saved_errno = errno;
e822f505 52 if (retval == 0) {
df793c55 53 /* child */
7f0aeeba 54 ust_after_fork_child(&sigset);
e822f505 55 } else {
7f0aeeba 56 ust_after_fork_parent(&sigset);
df793c55 57 }
111902ab 58 errno = saved_errno;
2d99476b
PMF
59 return retval;
60}
97b042a3 61
2f6150e9
MD
62int daemon(int nochdir, int noclose)
63{
64 static int (*plibc_func)(int nochdir, int noclose) = NULL;
65 sigset_t sigset;
66 int retval;
111902ab 67 int saved_errno;
2f6150e9
MD
68
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");
73 errno = ENOSYS;
74 return -1;
75 }
76 }
77
78 ust_before_fork(&sigset);
79 /* Do the real daemon call */
80 retval = plibc_func(nochdir, noclose);
111902ab 81 saved_errno = errno;
2f6150e9
MD
82 if (retval == 0) {
83 /* child, parent called _exit() directly */
84 ust_after_fork_child(&sigset);
85 } else {
86 /* on error in the parent */
87 ust_after_fork_parent(&sigset);
88 }
111902ab 89 errno = saved_errno;
2f6150e9
MD
90 return retval;
91}
92
fca2f191
MJ
93int setuid(uid_t uid)
94{
95 static int (*plibc_func)(uid_t uid) = NULL;
96 int retval;
97 int saved_errno;
98
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");
103 errno = ENOSYS;
104 return -1;
105 }
106 }
107
108 /* Do the real setuid */
109 retval = plibc_func(uid);
110 saved_errno = errno;
111
112 ust_after_setuid();
113
114 errno = saved_errno;
115 return retval;
116}
117
118int setgid(gid_t gid)
119{
120 static int (*plibc_func)(gid_t gid) = NULL;
121 int retval;
122 int saved_errno;
123
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");
128 errno = ENOSYS;
129 return -1;
130 }
131 }
132
133 /* Do the real setgid */
134 retval = plibc_func(gid);
135 saved_errno = errno;
136
137 ust_after_setgid();
138
139 errno = saved_errno;
140 return retval;
141}
142
143int seteuid(uid_t euid)
144{
145 static int (*plibc_func)(uid_t euid) = NULL;
146 int retval;
147 int saved_errno;
148
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");
153 errno = ENOSYS;
154 return -1;
155 }
156 }
157
158 /* Do the real seteuid */
159 retval = plibc_func(euid);
160 saved_errno = errno;
161
162 ust_after_seteuid();
163
164 errno = saved_errno;
165 return retval;
166}
167
168int setegid(gid_t egid)
169{
170 static int (*plibc_func)(gid_t egid) = NULL;
171 int retval;
172 int saved_errno;
173
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");
178 errno = ENOSYS;
179 return -1;
180 }
181 }
182
183 /* Do the real setegid */
184 retval = plibc_func(egid);
185 saved_errno = errno;
186
187 ust_after_setegid();
188
189 errno = saved_errno;
190 return retval;
191}
192
193int setreuid(uid_t ruid, uid_t euid)
194{
195 static int (*plibc_func)(uid_t ruid, uid_t euid) = NULL;
196 int retval;
197 int saved_errno;
198
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");
203 errno = ENOSYS;
204 return -1;
205 }
206 }
207
208 /* Do the real setreuid */
209 retval = plibc_func(ruid, euid);
210 saved_errno = errno;
211
212 ust_after_setreuid();
213
214 errno = saved_errno;
215 return retval;
216}
217
218int setregid(gid_t rgid, gid_t egid)
219{
220 static int (*plibc_func)(gid_t rgid, gid_t egid) = NULL;
221 int retval;
222 int saved_errno;
223
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");
228 errno = ENOSYS;
229 return -1;
230 }
231 }
232
233 /* Do the real setregid */
234 retval = plibc_func(rgid, egid);
235 saved_errno = errno;
236
237 ust_after_setregid();
238
239 errno = saved_errno;
240 return retval;
241}
242
939c89cb
MD
243#ifdef __linux__
244
245struct user_desc;
246
e822f505 247struct ustfork_clone_info {
616ed36a
PMF
248 int (*fn)(void *);
249 void *arg;
7f0aeeba 250 sigset_t sigset;
616ed36a
PMF
251};
252
253static int clone_fn(void *arg)
254{
e822f505 255 struct ustfork_clone_info *info = (struct ustfork_clone_info *) arg;
616ed36a
PMF
256
257 /* clone is now done and we are in child */
7f0aeeba 258 ust_after_fork_child(&info->sigset);
616ed36a
PMF
259 return info->fn(info->arg);
260}
261
262int clone(int (*fn)(void *), void *child_stack, int flags, void *arg, ...)
263{
e822f505
MD
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;
267 /* var args */
616ed36a
PMF
268 pid_t *ptid;
269 struct user_desc *tls;
270 pid_t *ctid;
e822f505 271 /* end of var args */
616ed36a 272 va_list ap;
e822f505 273 int retval;
111902ab 274 int saved_errno;
616ed36a
PMF
275
276 va_start(ap, arg);
277 ptid = va_arg(ap, pid_t *);
278 tls = va_arg(ap, struct user_desc *);
279 ctid = va_arg(ap, pid_t *);
280 va_end(ap);
281
e822f505 282 if (plibc_func == NULL) {
616ed36a 283 plibc_func = dlsym(RTLD_NEXT, "clone");
e822f505
MD
284 if (plibc_func == NULL) {
285 fprintf(stderr, "libustfork: unable to find \"clone\" symbol.\n");
3678c8aa 286 errno = ENOSYS;
616ed36a
PMF
287 return -1;
288 }
289 }
290
e822f505
MD
291 if (flags & CLONE_VM) {
292 /*
293 * Creating a thread, no need to intervene, just pass on
294 * the arguments.
295 */
296 retval = plibc_func(fn, child_stack, flags, arg, ptid,
297 tls, ctid);
111902ab 298 saved_errno = errno;
e822f505
MD
299 } else {
300 /* Creating a real process, we need to intervene. */
3fd2b913 301 struct ustfork_clone_info info = { .fn = fn, .arg = arg };
616ed36a 302
7f0aeeba 303 ust_before_fork(&info.sigset);
e822f505
MD
304 retval = plibc_func(clone_fn, child_stack, flags, &info,
305 ptid, tls, ctid);
111902ab 306 saved_errno = errno;
e822f505 307 /* The child doesn't get here. */
7f0aeeba 308 ust_after_fork_parent(&info.sigset);
616ed36a 309 }
111902ab 310 errno = saved_errno;
616ed36a
PMF
311 return retval;
312}
939c89cb 313
735bef47
MJ
314int setns(int fd, int nstype)
315{
316 static int (*plibc_func)(int fd, int nstype) = NULL;
317 int retval;
318 int saved_errno;
319
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");
324 errno = ENOSYS;
325 return -1;
326 }
327 }
328
329 /* Do the real setns */
330 retval = plibc_func(fd, nstype);
331 saved_errno = errno;
332
333 ust_after_setns();
334
335 errno = saved_errno;
336 return retval;
337}
338
339int unshare(int flags)
340{
341 static int (*plibc_func)(int flags) = NULL;
342 int retval;
343 int saved_errno;
344
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");
349 errno = ENOSYS;
350 return -1;
351 }
352 }
353
354 /* Do the real setns */
355 retval = plibc_func(flags);
356 saved_errno = errno;
357
358 ust_after_unshare();
359
360 errno = saved_errno;
361 return retval;
362}
363
fca2f191
MJ
364int setresuid(uid_t ruid, uid_t euid, uid_t suid)
365{
366 static int (*plibc_func)(uid_t ruid, uid_t euid, uid_t suid) = NULL;
367 int retval;
368 int saved_errno;
369
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");
374 errno = ENOSYS;
375 return -1;
376 }
377 }
378
379 /* Do the real setresuid */
380 retval = plibc_func(ruid, euid, suid);
381 saved_errno = errno;
382
383 ust_after_setresuid();
384
385 errno = saved_errno;
386 return retval;
387}
388
389int setresgid(gid_t rgid, gid_t egid, gid_t sgid)
390{
391 static int (*plibc_func)(gid_t rgid, gid_t egid, gid_t sgid) = NULL;
392 int retval;
393 int saved_errno;
394
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");
399 errno = ENOSYS;
400 return -1;
401 }
402 }
403
404 /* Do the real setresgid */
405 retval = plibc_func(rgid, egid, sgid);
406 saved_errno = errno;
407
408 ust_after_setresgid();
409
410 errno = saved_errno;
411 return retval;
412}
413
939c89cb
MD
414#elif defined (__FreeBSD__)
415
416pid_t rfork(int flags)
417{
b115a3fc 418 static pid_t (*plibc_func)(int flags) = NULL;
939c89cb
MD
419 sigset_t sigset;
420 pid_t retval;
111902ab 421 int saved_errno;
939c89cb
MD
422
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");
3678c8aa 427 errno = ENOSYS;
939c89cb
MD
428 return -1;
429 }
430 }
431
432 ust_before_fork(&sigset);
433 /* Do the real rfork */
b115a3fc 434 retval = plibc_func(flags);
111902ab 435 saved_errno = errno;
939c89cb
MD
436 if (retval == 0) {
437 /* child */
438 ust_after_fork_child(&sigset);
439 } else {
440 ust_after_fork_parent(&sigset);
441 }
111902ab 442 errno = saved_errno;
939c89cb
MD
443 return retval;
444}
445
446/*
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
449 * the child.
450 */
451
452#else
453#warning "Unknown OS. You might want to ensure that fork/clone/vfork/fork handling is complete."
454#endif
This page took 0.051105 seconds and 4 git commands to generate.