1*4b9c6d91SCole Faust /* libminijailpreload.c - preload hack library
2*4b9c6d91SCole Faust * Copyright 2011 The ChromiumOS Authors
3*4b9c6d91SCole Faust * Use of this source code is governed by a BSD-style license that can be
4*4b9c6d91SCole Faust * found in the LICENSE file.
5*4b9c6d91SCole Faust *
6*4b9c6d91SCole Faust * This library is preloaded into every program launched by minijail_run().
7*4b9c6d91SCole Faust * DO NOT EXPORT ANY SYMBOLS FROM THIS LIBRARY. They will replace other symbols
8*4b9c6d91SCole Faust * in the programs it is preloaded into and cause impossible-to-debug failures.
9*4b9c6d91SCole Faust * See the minijail0.1 for a design explanation.
10*4b9c6d91SCole Faust */
11*4b9c6d91SCole Faust
12*4b9c6d91SCole Faust #include "libminijail.h"
13*4b9c6d91SCole Faust #include "libminijail-private.h"
14*4b9c6d91SCole Faust #include "util.h"
15*4b9c6d91SCole Faust
16*4b9c6d91SCole Faust #include <dlfcn.h>
17*4b9c6d91SCole Faust #include <stdio.h>
18*4b9c6d91SCole Faust #include <stdlib.h>
19*4b9c6d91SCole Faust #include <string.h>
20*4b9c6d91SCole Faust #include <sys/types.h>
21*4b9c6d91SCole Faust #include <syslog.h>
22*4b9c6d91SCole Faust #include <unistd.h>
23*4b9c6d91SCole Faust
24*4b9c6d91SCole Faust static int (*real_main) (int, char **, char **);
25*4b9c6d91SCole Faust static void *libc_handle;
26*4b9c6d91SCole Faust
truncate_preload_env(char ** envp,const char * name)27*4b9c6d91SCole Faust static void truncate_preload_env(char **envp, const char *name)
28*4b9c6d91SCole Faust {
29*4b9c6d91SCole Faust char *env_value = minijail_getenv(envp, name);
30*4b9c6d91SCole Faust if (env_value) {
31*4b9c6d91SCole Faust /*
32*4b9c6d91SCole Faust * if we have more than just libminijailpreload.so in
33*4b9c6d91SCole Faust * LD_PRELOAD, cut out libminijailpreload.so from it,
34*4b9c6d91SCole Faust * as it is guaranteed to always be last in the
35*4b9c6d91SCole Faust * LD_PRELOAD list.
36*4b9c6d91SCole Faust */
37*4b9c6d91SCole Faust char *last_space = strrchr(env_value, ' ');
38*4b9c6d91SCole Faust if (last_space) {
39*4b9c6d91SCole Faust *last_space = '\0';
40*4b9c6d91SCole Faust } else {
41*4b9c6d91SCole Faust /* Only our lib was in LD_PRELOAD, just unset it. */
42*4b9c6d91SCole Faust minijail_unsetenv(envp, name);
43*4b9c6d91SCole Faust }
44*4b9c6d91SCole Faust }
45*4b9c6d91SCole Faust }
46*4b9c6d91SCole Faust
47*4b9c6d91SCole Faust /** @brief Fake main(), spliced in before the real call to main() by
48*4b9c6d91SCole Faust * __libc_start_main (see below).
49*4b9c6d91SCole Faust * We get serialized commands from our invoking process over an fd specified
50*4b9c6d91SCole Faust * by an environment variable (kFdEnvVar). The environment variable is a list
51*4b9c6d91SCole Faust * of key=value pairs (see move_commands_to_env); we use them to construct a
52*4b9c6d91SCole Faust * jail, then enter it.
53*4b9c6d91SCole Faust */
fake_main(int argc,char ** argv,char ** envp)54*4b9c6d91SCole Faust static int fake_main(int argc, char **argv, char **envp)
55*4b9c6d91SCole Faust {
56*4b9c6d91SCole Faust char *fd_name = getenv(kFdEnvVar);
57*4b9c6d91SCole Faust int fd = -1;
58*4b9c6d91SCole Faust struct minijail *j;
59*4b9c6d91SCole Faust if (geteuid() != getuid() || getegid() != getgid()) {
60*4b9c6d91SCole Faust /*
61*4b9c6d91SCole Faust * If we didn't do this check, an attacker could set kFdEnvVar
62*4b9c6d91SCole Faust * for any setuid program that uses libminijail to cause it to
63*4b9c6d91SCole Faust * get capabilities or a uid it did not expect.
64*4b9c6d91SCole Faust */
65*4b9c6d91SCole Faust /* TODO(wad): why would libminijail interact here? */
66*4b9c6d91SCole Faust return MINIJAIL_ERR_PRELOAD;
67*4b9c6d91SCole Faust }
68*4b9c6d91SCole Faust if (!fd_name)
69*4b9c6d91SCole Faust return MINIJAIL_ERR_PRELOAD;
70*4b9c6d91SCole Faust fd = atoi(fd_name);
71*4b9c6d91SCole Faust if (fd < 0)
72*4b9c6d91SCole Faust return MINIJAIL_ERR_PRELOAD;
73*4b9c6d91SCole Faust
74*4b9c6d91SCole Faust j = minijail_new();
75*4b9c6d91SCole Faust if (!j)
76*4b9c6d91SCole Faust die("preload: out of memory");
77*4b9c6d91SCole Faust if (minijail_from_fd(fd, j))
78*4b9c6d91SCole Faust die("preload: failed to parse minijail from parent");
79*4b9c6d91SCole Faust close(fd);
80*4b9c6d91SCole Faust
81*4b9c6d91SCole Faust minijail_unsetenv(envp, kFdEnvVar);
82*4b9c6d91SCole Faust
83*4b9c6d91SCole Faust truncate_preload_env(envp, kLdPreloadEnvVar);
84*4b9c6d91SCole Faust
85*4b9c6d91SCole Faust /* Strip out flags meant for the parent. */
86*4b9c6d91SCole Faust minijail_preenter(j);
87*4b9c6d91SCole Faust minijail_enter(j);
88*4b9c6d91SCole Faust minijail_destroy(j);
89*4b9c6d91SCole Faust dlclose(libc_handle);
90*4b9c6d91SCole Faust return real_main(argc, argv, envp);
91*4b9c6d91SCole Faust }
92*4b9c6d91SCole Faust
93*4b9c6d91SCole Faust /** @brief LD_PRELOAD override of __libc_start_main.
94*4b9c6d91SCole Faust *
95*4b9c6d91SCole Faust * It is really best if you do not look too closely at this function. We need
96*4b9c6d91SCole Faust * to ensure that some of our code runs before the target program (see the
97*4b9c6d91SCole Faust * minijail0.1 file in this directory for high-level details about this), and
98*4b9c6d91SCole Faust * the only available place to hook is this function, which is normally
99*4b9c6d91SCole Faust * responsible for calling main(). Our LD_PRELOAD will overwrite the real
100*4b9c6d91SCole Faust * __libc_start_main with this one, so we have to look up the real one from
101*4b9c6d91SCole Faust * libc and invoke it with a pointer to the fake main() we'd like to run before
102*4b9c6d91SCole Faust * the real main(). We can't just run our setup code *here* because
103*4b9c6d91SCole Faust * __libc_start_main is responsible for setting up the C runtime environment,
104*4b9c6d91SCole Faust * so we can't rely on things like malloc() being available yet.
105*4b9c6d91SCole Faust */
106*4b9c6d91SCole Faust
__libc_start_main(int (* main)(int,char **,char **),int argc,char ** ubp_av,void (* init)(void),void (* fini)(void),void (* rtld_fini)(void),void (* stack_end))107*4b9c6d91SCole Faust int API __libc_start_main(int (*main)(int, char **, char **), int argc,
108*4b9c6d91SCole Faust char **ubp_av, void (*init)(void), void (*fini)(void),
109*4b9c6d91SCole Faust void (*rtld_fini)(void), void(*stack_end))
110*4b9c6d91SCole Faust {
111*4b9c6d91SCole Faust void *sym;
112*4b9c6d91SCole Faust /*
113*4b9c6d91SCole Faust * This hack is unfortunately required by C99 - casting directly from
114*4b9c6d91SCole Faust * void* to function pointers is left undefined. See POSIX.1-2003, the
115*4b9c6d91SCole Faust * Rationale for the specification of dlsym(), and dlsym(3). This
116*4b9c6d91SCole Faust * deliberately violates strict-aliasing rules, but gcc can't tell.
117*4b9c6d91SCole Faust */
118*4b9c6d91SCole Faust union {
119*4b9c6d91SCole Faust int (*fn)(int (*main)(int, char **, char **), int argc,
120*4b9c6d91SCole Faust char **ubp_av, void (*init)(void), void (*fini)(void),
121*4b9c6d91SCole Faust void (*rtld_fini)(void), void(*stack_end));
122*4b9c6d91SCole Faust void *symval;
123*4b9c6d91SCole Faust } real_libc_start_main;
124*4b9c6d91SCole Faust
125*4b9c6d91SCole Faust /*
126*4b9c6d91SCole Faust * We hold this handle for the duration of the real __libc_start_main()
127*4b9c6d91SCole Faust * and drop it just before calling the real main().
128*4b9c6d91SCole Faust */
129*4b9c6d91SCole Faust libc_handle = dlopen("libc.so.6", RTLD_NOW);
130*4b9c6d91SCole Faust
131*4b9c6d91SCole Faust if (!libc_handle) {
132*4b9c6d91SCole Faust syslog(LOG_ERR, "can't dlopen() libc");
133*4b9c6d91SCole Faust /*
134*4b9c6d91SCole Faust * We dare not use abort() here because it will run atexit()
135*4b9c6d91SCole Faust * handlers and try to flush stdio.
136*4b9c6d91SCole Faust */
137*4b9c6d91SCole Faust _exit(1);
138*4b9c6d91SCole Faust }
139*4b9c6d91SCole Faust sym = dlsym(libc_handle, "__libc_start_main");
140*4b9c6d91SCole Faust if (!sym) {
141*4b9c6d91SCole Faust syslog(LOG_ERR, "can't find the real __libc_start_main()");
142*4b9c6d91SCole Faust _exit(1);
143*4b9c6d91SCole Faust }
144*4b9c6d91SCole Faust real_libc_start_main.symval = sym;
145*4b9c6d91SCole Faust real_main = main;
146*4b9c6d91SCole Faust
147*4b9c6d91SCole Faust /*
148*4b9c6d91SCole Faust * Note that we swap fake_main in for main - fake_main knows that it
149*4b9c6d91SCole Faust * should call real_main after it's done.
150*4b9c6d91SCole Faust */
151*4b9c6d91SCole Faust return real_libc_start_main.fn(fake_main, argc, ubp_av, init, fini,
152*4b9c6d91SCole Faust rtld_fini, stack_end);
153*4b9c6d91SCole Faust }
154