Fix: pass private data to context callbacks
[lttng-ust.git] / liblttng-ust-fork / ustfork.c
CommitLineData
e822f505 1/*
c0c0989a
MJ
2 * SPDX-License-Identifier: LGPL-2.1-only
3 *
e822f505 4 * Copyright (C) 2009 Pierre-Marc Fournier
3678c8aa 5 * Copyright (C) 2011-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
2d99476b
PMF
6 */
7
ae4b659d 8#include <ust-dlfcn.h>
2d99476b
PMF
9#include <unistd.h>
10#include <stdio.h>
df793c55 11#include <signal.h>
616ed36a
PMF
12#include <sched.h>
13#include <stdarg.h>
eb2b066f 14#include <errno.h>
2d99476b 15
d0c8f180 16#include <lttng/ust-fork.h>
e822f505 17
2d99476b
PMF
18pid_t fork(void)
19{
20 static pid_t (*plibc_func)(void) = NULL;
7f0aeeba 21 sigset_t sigset;
2d99476b 22 pid_t retval;
111902ab 23 int saved_errno;
2d99476b 24
e822f505 25 if (plibc_func == NULL) {
2d99476b 26 plibc_func = dlsym(RTLD_NEXT, "fork");
e822f505
MD
27 if (plibc_func == NULL) {
28 fprintf(stderr, "libustfork: unable to find \"fork\" symbol\n");
3678c8aa 29 errno = ENOSYS;
2c10b7fd 30 return -1;
2d99476b
PMF
31 }
32 }
33
d0c8f180 34 lttng_ust_before_fork(&sigset);
df793c55 35 /* Do the real fork */
2d99476b 36 retval = plibc_func();
111902ab 37 saved_errno = errno;
e822f505 38 if (retval == 0) {
df793c55 39 /* child */
d0c8f180 40 lttng_ust_after_fork_child(&sigset);
e822f505 41 } else {
d0c8f180 42 lttng_ust_after_fork_parent(&sigset);
df793c55 43 }
111902ab 44 errno = saved_errno;
2d99476b
PMF
45 return retval;
46}
97b042a3 47
2f6150e9
MD
48int daemon(int nochdir, int noclose)
49{
50 static int (*plibc_func)(int nochdir, int noclose) = NULL;
51 sigset_t sigset;
52 int retval;
111902ab 53 int saved_errno;
2f6150e9
MD
54
55 if (plibc_func == NULL) {
56 plibc_func = dlsym(RTLD_NEXT, "daemon");
57 if (plibc_func == NULL) {
58 fprintf(stderr, "libustfork: unable to find \"daemon\" symbol\n");
59 errno = ENOSYS;
60 return -1;
61 }
62 }
63
d0c8f180 64 lttng_ust_before_fork(&sigset);
2f6150e9
MD
65 /* Do the real daemon call */
66 retval = plibc_func(nochdir, noclose);
111902ab 67 saved_errno = errno;
2f6150e9
MD
68 if (retval == 0) {
69 /* child, parent called _exit() directly */
d0c8f180 70 lttng_ust_after_fork_child(&sigset);
2f6150e9
MD
71 } else {
72 /* on error in the parent */
d0c8f180 73 lttng_ust_after_fork_parent(&sigset);
2f6150e9 74 }
111902ab 75 errno = saved_errno;
2f6150e9
MD
76 return retval;
77}
78
fca2f191
MJ
79int setuid(uid_t uid)
80{
81 static int (*plibc_func)(uid_t uid) = NULL;
82 int retval;
83 int saved_errno;
84
85 if (plibc_func == NULL) {
86 plibc_func = dlsym(RTLD_NEXT, "setuid");
87 if (plibc_func == NULL) {
88 fprintf(stderr, "libustfork: unable to find \"setuid\" symbol\n");
89 errno = ENOSYS;
90 return -1;
91 }
92 }
93
94 /* Do the real setuid */
95 retval = plibc_func(uid);
96 saved_errno = errno;
97
d0c8f180 98 lttng_ust_after_setuid();
fca2f191
MJ
99
100 errno = saved_errno;
101 return retval;
102}
103
104int setgid(gid_t gid)
105{
106 static int (*plibc_func)(gid_t gid) = NULL;
107 int retval;
108 int saved_errno;
109
110 if (plibc_func == NULL) {
111 plibc_func = dlsym(RTLD_NEXT, "setgid");
112 if (plibc_func == NULL) {
113 fprintf(stderr, "libustfork: unable to find \"setgid\" symbol\n");
114 errno = ENOSYS;
115 return -1;
116 }
117 }
118
119 /* Do the real setgid */
120 retval = plibc_func(gid);
121 saved_errno = errno;
122
d0c8f180 123 lttng_ust_after_setgid();
fca2f191
MJ
124
125 errno = saved_errno;
126 return retval;
127}
128
129int seteuid(uid_t euid)
130{
131 static int (*plibc_func)(uid_t euid) = NULL;
132 int retval;
133 int saved_errno;
134
135 if (plibc_func == NULL) {
136 plibc_func = dlsym(RTLD_NEXT, "seteuid");
137 if (plibc_func == NULL) {
138 fprintf(stderr, "libustfork: unable to find \"seteuid\" symbol\n");
139 errno = ENOSYS;
140 return -1;
141 }
142 }
143
144 /* Do the real seteuid */
145 retval = plibc_func(euid);
146 saved_errno = errno;
147
d0c8f180 148 lttng_ust_after_seteuid();
fca2f191
MJ
149
150 errno = saved_errno;
151 return retval;
152}
153
154int setegid(gid_t egid)
155{
156 static int (*plibc_func)(gid_t egid) = NULL;
157 int retval;
158 int saved_errno;
159
160 if (plibc_func == NULL) {
161 plibc_func = dlsym(RTLD_NEXT, "setegid");
162 if (plibc_func == NULL) {
163 fprintf(stderr, "libustfork: unable to find \"setegid\" symbol\n");
164 errno = ENOSYS;
165 return -1;
166 }
167 }
168
169 /* Do the real setegid */
170 retval = plibc_func(egid);
171 saved_errno = errno;
172
d0c8f180 173 lttng_ust_after_setegid();
fca2f191
MJ
174
175 errno = saved_errno;
176 return retval;
177}
178
179int setreuid(uid_t ruid, uid_t euid)
180{
181 static int (*plibc_func)(uid_t ruid, uid_t euid) = NULL;
182 int retval;
183 int saved_errno;
184
185 if (plibc_func == NULL) {
186 plibc_func = dlsym(RTLD_NEXT, "setreuid");
187 if (plibc_func == NULL) {
188 fprintf(stderr, "libustfork: unable to find \"setreuid\" symbol\n");
189 errno = ENOSYS;
190 return -1;
191 }
192 }
193
194 /* Do the real setreuid */
195 retval = plibc_func(ruid, euid);
196 saved_errno = errno;
197
d0c8f180 198 lttng_ust_after_setreuid();
fca2f191
MJ
199
200 errno = saved_errno;
201 return retval;
202}
203
204int setregid(gid_t rgid, gid_t egid)
205{
206 static int (*plibc_func)(gid_t rgid, gid_t egid) = NULL;
207 int retval;
208 int saved_errno;
209
210 if (plibc_func == NULL) {
211 plibc_func = dlsym(RTLD_NEXT, "setregid");
212 if (plibc_func == NULL) {
213 fprintf(stderr, "libustfork: unable to find \"setregid\" symbol\n");
214 errno = ENOSYS;
215 return -1;
216 }
217 }
218
219 /* Do the real setregid */
220 retval = plibc_func(rgid, egid);
221 saved_errno = errno;
222
d0c8f180 223 lttng_ust_after_setregid();
fca2f191
MJ
224
225 errno = saved_errno;
226 return retval;
227}
228
939c89cb
MD
229#ifdef __linux__
230
231struct user_desc;
232
e822f505 233struct ustfork_clone_info {
616ed36a
PMF
234 int (*fn)(void *);
235 void *arg;
7f0aeeba 236 sigset_t sigset;
616ed36a
PMF
237};
238
239static int clone_fn(void *arg)
240{
e822f505 241 struct ustfork_clone_info *info = (struct ustfork_clone_info *) arg;
616ed36a
PMF
242
243 /* clone is now done and we are in child */
d0c8f180 244 lttng_ust_after_fork_child(&info->sigset);
616ed36a
PMF
245 return info->fn(info->arg);
246}
247
248int clone(int (*fn)(void *), void *child_stack, int flags, void *arg, ...)
249{
e822f505
MD
250 static int (*plibc_func)(int (*fn)(void *), void *child_stack,
251 int flags, void *arg, pid_t *ptid,
252 struct user_desc *tls, pid_t *ctid) = NULL;
253 /* var args */
616ed36a
PMF
254 pid_t *ptid;
255 struct user_desc *tls;
256 pid_t *ctid;
e822f505 257 /* end of var args */
616ed36a 258 va_list ap;
e822f505 259 int retval;
111902ab 260 int saved_errno;
616ed36a
PMF
261
262 va_start(ap, arg);
263 ptid = va_arg(ap, pid_t *);
264 tls = va_arg(ap, struct user_desc *);
265 ctid = va_arg(ap, pid_t *);
266 va_end(ap);
267
e822f505 268 if (plibc_func == NULL) {
616ed36a 269 plibc_func = dlsym(RTLD_NEXT, "clone");
e822f505
MD
270 if (plibc_func == NULL) {
271 fprintf(stderr, "libustfork: unable to find \"clone\" symbol.\n");
3678c8aa 272 errno = ENOSYS;
616ed36a
PMF
273 return -1;
274 }
275 }
276
e822f505
MD
277 if (flags & CLONE_VM) {
278 /*
279 * Creating a thread, no need to intervene, just pass on
280 * the arguments.
281 */
282 retval = plibc_func(fn, child_stack, flags, arg, ptid,
283 tls, ctid);
111902ab 284 saved_errno = errno;
e822f505
MD
285 } else {
286 /* Creating a real process, we need to intervene. */
3fd2b913 287 struct ustfork_clone_info info = { .fn = fn, .arg = arg };
616ed36a 288
d0c8f180 289 lttng_ust_before_fork(&info.sigset);
e822f505
MD
290 retval = plibc_func(clone_fn, child_stack, flags, &info,
291 ptid, tls, ctid);
111902ab 292 saved_errno = errno;
e822f505 293 /* The child doesn't get here. */
d0c8f180 294 lttng_ust_after_fork_parent(&info.sigset);
616ed36a 295 }
111902ab 296 errno = saved_errno;
616ed36a
PMF
297 return retval;
298}
939c89cb 299
735bef47
MJ
300int setns(int fd, int nstype)
301{
302 static int (*plibc_func)(int fd, int nstype) = NULL;
303 int retval;
304 int saved_errno;
305
306 if (plibc_func == NULL) {
307 plibc_func = dlsym(RTLD_NEXT, "setns");
308 if (plibc_func == NULL) {
309 fprintf(stderr, "libustfork: unable to find \"setns\" symbol\n");
310 errno = ENOSYS;
311 return -1;
312 }
313 }
314
315 /* Do the real setns */
316 retval = plibc_func(fd, nstype);
317 saved_errno = errno;
318
d0c8f180 319 lttng_ust_after_setns();
735bef47
MJ
320
321 errno = saved_errno;
322 return retval;
323}
324
325int unshare(int flags)
326{
327 static int (*plibc_func)(int flags) = NULL;
328 int retval;
329 int saved_errno;
330
331 if (plibc_func == NULL) {
332 plibc_func = dlsym(RTLD_NEXT, "unshare");
333 if (plibc_func == NULL) {
334 fprintf(stderr, "libustfork: unable to find \"unshare\" symbol\n");
335 errno = ENOSYS;
336 return -1;
337 }
338 }
339
340 /* Do the real setns */
341 retval = plibc_func(flags);
342 saved_errno = errno;
343
d0c8f180 344 lttng_ust_after_unshare();
735bef47
MJ
345
346 errno = saved_errno;
347 return retval;
348}
349
fca2f191
MJ
350int setresuid(uid_t ruid, uid_t euid, uid_t suid)
351{
352 static int (*plibc_func)(uid_t ruid, uid_t euid, uid_t suid) = NULL;
353 int retval;
354 int saved_errno;
355
356 if (plibc_func == NULL) {
357 plibc_func = dlsym(RTLD_NEXT, "setresuid");
358 if (plibc_func == NULL) {
359 fprintf(stderr, "libustfork: unable to find \"setresuid\" symbol\n");
360 errno = ENOSYS;
361 return -1;
362 }
363 }
364
365 /* Do the real setresuid */
366 retval = plibc_func(ruid, euid, suid);
367 saved_errno = errno;
368
d0c8f180 369 lttng_ust_after_setresuid();
fca2f191
MJ
370
371 errno = saved_errno;
372 return retval;
373}
374
375int setresgid(gid_t rgid, gid_t egid, gid_t sgid)
376{
377 static int (*plibc_func)(gid_t rgid, gid_t egid, gid_t sgid) = NULL;
378 int retval;
379 int saved_errno;
380
381 if (plibc_func == NULL) {
382 plibc_func = dlsym(RTLD_NEXT, "setresgid");
383 if (plibc_func == NULL) {
384 fprintf(stderr, "libustfork: unable to find \"setresgid\" symbol\n");
385 errno = ENOSYS;
386 return -1;
387 }
388 }
389
390 /* Do the real setresgid */
391 retval = plibc_func(rgid, egid, sgid);
392 saved_errno = errno;
393
d0c8f180 394 lttng_ust_after_setresgid();
fca2f191
MJ
395
396 errno = saved_errno;
397 return retval;
398}
399
939c89cb
MD
400#elif defined (__FreeBSD__)
401
402pid_t rfork(int flags)
403{
404 static pid_t (*plibc_func)(void) = NULL;
405 sigset_t sigset;
406 pid_t retval;
111902ab 407 int saved_errno;
939c89cb
MD
408
409 if (plibc_func == NULL) {
410 plibc_func = dlsym(RTLD_NEXT, "rfork");
411 if (plibc_func == NULL) {
412 fprintf(stderr, "libustfork: unable to find \"rfork\" symbol\n");
3678c8aa 413 errno = ENOSYS;
939c89cb
MD
414 return -1;
415 }
416 }
417
d0c8f180 418 lttng_ust_before_fork(&sigset);
939c89cb
MD
419 /* Do the real rfork */
420 retval = plibc_func();
111902ab 421 saved_errno = errno;
939c89cb
MD
422 if (retval == 0) {
423 /* child */
d0c8f180 424 lttng_ust_after_fork_child(&sigset);
939c89cb 425 } else {
d0c8f180 426 lttng_ust_after_fork_parent(&sigset);
939c89cb 427 }
111902ab 428 errno = saved_errno;
939c89cb
MD
429 return retval;
430}
431
432/*
433 * On BSD, no need to override vfork, because it runs in the context of
434 * the parent, with parent waiting until execve or exit is executed in
435 * the child.
436 */
437
438#else
439#warning "Unknown OS. You might want to ensure that fork/clone/vfork/fork handling is complete."
440#endif
This page took 0.050704 seconds and 4 git commands to generate.