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