~azzar1/unity/add-show-desktop-key

« back to all changes in this revision

Viewing changes to trampoline/trampoline.c

  • Committer: mattgiuca
  • Date: 2008-07-15 07:19:34 UTC
  • Revision ID: svn-v3-trunk0:2b9c9e99-6f39-0410-b283-7f802c844ae2:trunk:875
Added "migrations" directory, which contains incremental database update
    scripts.
Updated users.sql, uniqueness key on offering table.
Added migration matching this update to the migrations directory. Mm handy!

Show diffs side-by-side

added added

removed removed

Lines of Context:
37
37
#include <stdlib.h>
38
38
#include <string.h>
39
39
#include <unistd.h>
 
40
#include <syslog.h>
 
41
#include <sys/mount.h>
 
42
#include <sys/types.h>
 
43
#include <sys/stat.h>
 
44
#include <sys/time.h>
 
45
#include <sys/resource.h>
 
46
#include <limits.h>
40
47
 
41
48
/* conf.h is admin-configured by the setup process.
42
49
 * It defines jail_base.
43
50
 */
44
51
#include "conf.h"
45
52
 
 
53
#include "norm.h"
 
54
 
46
55
/* Returns TRUE if the given uid is allowed to execute trampoline.
47
56
 * Only root or the web server should be allowed to execute.
48
57
 * This is determined by the whitelist allowed_uids in conf.h.
86
95
    /* At this point we are executing as the child process */
87
96
 
88
97
    /* Change the file mode mask */
89
 
    umask(0);
 
98
    umask(022);
90
99
 
91
100
    /* Create a new SID for the child process */
92
101
    sid = setsid();
109
118
static void usage(const char* nm)
110
119
{
111
120
    fprintf(stderr,
112
 
        "usage: %s [-d] <uid> <jail> <cwd> <program> [args...]\n", nm);
 
121
        "usage: %s [-d] [-u] <uid> <jail> <cwd> <program> [args...]\n", nm);
113
122
    exit(1);
114
123
}
115
124
 
 
125
#ifdef IVLE_AUFS_JAILS
 
126
/* Die more pleasantly if mallocs fail. */
 
127
void *die_if_null(void *ptr)
 
128
{
 
129
    if (ptr == NULL)
 
130
    {
 
131
        perror("not enough memory");
 
132
        exit(1);
 
133
    }
 
134
    return ptr;
 
135
}
 
136
 
 
137
/* Find the path of the user components of a jail, given a mountpoint. */
 
138
char *jail_src(const char* jailpath)
 
139
{
 
140
    char* src;
 
141
    int srclen;
 
142
    int dstlen;
 
143
 
 
144
    srclen = strlen(jail_src_base);
 
145
    dstlen = strlen(jail_base);
 
146
    
 
147
    src = die_if_null(malloc(strlen(jailpath) + (srclen - dstlen) + 1));
 
148
    strcpy(src, jail_src_base);
 
149
    strcat(src, jailpath+dstlen);
 
150
 
 
151
    return src;
 
152
}
 
153
 
 
154
/* Check for the validity of a jail in the given path, mounting it if it looks
 
155
 * empty.
 
156
 * TODO: Updating /etc/mtab would be nice. */
 
157
void mount_if_needed(const char* jailpath)
 
158
{
 
159
    char *jailsrc;
 
160
    char *jaillib;
 
161
    char *mountdata;
 
162
 
 
163
    /* Check if there is something useful in the jail. If not, it's probably
 
164
     * not mounted. */
 
165
    jaillib = die_if_null(malloc(strlen(jailpath) + 5));
 
166
    sprintf(jaillib, "%s/lib", jailpath);
 
167
 
 
168
    if (access(jaillib, F_OK))
 
169
    {
 
170
        /* No /lib? Mustn't be mounted. Mount it, creating the dir if needed. */
 
171
        if (access(jailpath, F_OK))
 
172
        {
 
173
             if(mkdir(jailpath, 0755))
 
174
             {
 
175
                 syslog(LOG_ERR, "could not create mountpoint %s\n", jailpath);
 
176
                 perror("could not create jail mountpoint");
 
177
                 exit(1);
 
178
             }
 
179
             syslog(LOG_NOTICE, "created mountpoint %s\n", jailpath);
 
180
        }
 
181
       
 
182
        jailsrc = jail_src(jailpath);
 
183
        mountdata = die_if_null(malloc(3 + strlen(jailsrc) + 4 + strlen(jail_system) + 3 + 1));
 
184
        sprintf(mountdata, "br:%s=rw:%s=ro", jailsrc, jail_system);
 
185
        if (mount("none", jailpath, "aufs", 0, mountdata))
 
186
        {
 
187
            syslog(LOG_ERR, "could not mount %s\n", jailpath);
 
188
            perror("could not mount");
 
189
            exit(1);
 
190
        } 
 
191
 
 
192
        syslog(LOG_INFO, "mounted %s\n", jailpath);
 
193
 
 
194
        free(jailsrc);
 
195
        free(mountdata);
 
196
    }
 
197
 
 
198
    free(jaillib);
 
199
}
 
200
#endif /* IVLE_AUFS_JAILS */
 
201
 
116
202
int main(int argc, char* const argv[])
117
203
{
118
204
    char* jailpath;
122
208
    int uid;
123
209
    int arg_num = 1;
124
210
    int daemon_mode = 0;
 
211
    int unlimited = 0;
 
212
    char canonical_jailpath[PATH_MAX];
125
213
 
126
214
    /* Disallow execution from all users but the whitelisted ones, and root */
127
215
    if (!uid_allowed(getuid()))
145
233
        daemon_mode = 1;
146
234
        arg_num++;
147
235
    }
 
236
 
 
237
    if (strcmp(argv[arg_num], "-u") == 0)
 
238
    {
 
239
        if (argc < 6)
 
240
        {
 
241
            usage(argv[0]);
 
242
        }
 
243
        unlimited = 1;
 
244
        arg_num++;
 
245
    }
148
246
    uid = atoi(argv[arg_num++]);
149
247
    jailpath = argv[arg_num++];
150
248
    work_dir = argv[arg_num++];
158
256
        exit(1);
159
257
    }
160
258
 
161
 
    /* Jail path must:
162
 
     * Be non-empty
163
 
     * Start with a '/'
164
 
     * Not contain "/.."
165
 
     * Begin with jail_base
 
259
    /* Jail path must be an absolute path,
 
260
     * and it must begin with jail_base.
166
261
     */
167
 
    if (strlen(jailpath) < 1 || jailpath[0] != '/'
168
 
            || strstr(jailpath, "/..")
169
 
            || strncmp(jailpath, jail_base, strlen(jail_base)))
170
 
    {
171
 
        fprintf(stderr, "bad jail path: %s\n", jailpath);
172
 
        exit(1);
173
 
    }
 
262
    if (norm(canonical_jailpath, PATH_MAX, jailpath) != 0)
 
263
    {
 
264
        fprintf(stderr, "bad jail path: %s\n", jailpath);
 
265
        exit(1);
 
266
    }
 
267
    if (strncmp(canonical_jailpath, jail_base, strlen(jail_base)))
 
268
    {
 
269
        fprintf(stderr, "bad jail path: %s\n", jailpath);
 
270
        exit(1);
 
271
    }
 
272
 
 
273
    openlog("trampoline", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_USER);
 
274
 
 
275
    #ifdef IVLE_AUFS_JAILS
 
276
    mount_if_needed(canonical_jailpath);
 
277
    #endif /* IVLE_AUFS_JAILS */
174
278
 
175
279
    /* chroot into the jail.
176
280
     * Henceforth this process, and its children, cannot see anything above
177
 
     * jailpath. */
178
 
    if (chroot(jailpath))
 
281
     * canoncial_jailpath. */
 
282
    if (chroot(canonical_jailpath))
179
283
    {
 
284
        syslog(LOG_ERR, "chroot to %s failed\n", canonical_jailpath);
 
285
 
180
286
        perror("could not chroot");
181
287
        exit(1);
182
288
    }
191
297
    /* setuid to the given user ID.
192
298
     * Henceforth we will be running as this user instead of root.
193
299
     */
 
300
    if (setgid(uid))
 
301
    {
 
302
        perror("could not setgid");
 
303
        exit(1);
 
304
    }
 
305
 
194
306
    if (setuid(uid))
195
307
    {
196
308
        perror("could not setuid");
202
314
        daemonize();
203
315
    }
204
316
 
 
317
    /* set user resource limits */
 
318
    if (!unlimited)
 
319
    {
 
320
        struct rlimit l;
 
321
        /* Process size in virtual memory */
 
322
        l.rlim_cur = 64 * 1024 * 1024; /* 64Mb */
 
323
        l.rlim_max = 72 * 1024 * 1024; /* 64Mb */
 
324
        if (setrlimit(RLIMIT_AS, &l))
 
325
        {
 
326
            perror("could not setrlimit/RLIMIT_AS");
 
327
            exit(1);
 
328
        }
 
329
 
 
330
        /* Core */
 
331
        l.rlim_cur = 0;
 
332
        l.rlim_max = 0;
 
333
        if (setrlimit(RLIMIT_CORE, &l))
 
334
        {
 
335
            perror("could not setrlimit/RLIMIT_CORE");
 
336
            exit(1);
 
337
        }
 
338
 
 
339
        /* CPU */
 
340
        l.rlim_cur = 25;
 
341
        l.rlim_max = 30;
 
342
        if (setrlimit(RLIMIT_CPU, &l))
 
343
        {
 
344
            perror("could not setrlimit/RLIMIT_CPU");
 
345
            exit(1);
 
346
        }
 
347
 
 
348
        /* File Size */
 
349
        l.rlim_cur = 64 * 1024 * 1024; /* 64Mb */
 
350
        l.rlim_max = 72 * 1024 * 1024; /* 72Mb */
 
351
        if (setrlimit(RLIMIT_FSIZE, &l))
 
352
        {
 
353
            perror("could not setrlimit/RLIMIT_FSIZE");
 
354
            exit(1);
 
355
        }
 
356
    }
 
357
 
205
358
    /* exec (replace this process with the a new instance of the target
206
359
     * program). Pass along all the arguments.
207
360
     * Note that for script execution, the "program" will be the interpreter,
208
361
     * and the first argument will be the script. */
209
362
    execv(prog, args);
210
363
 
211
 
    /* XXX if (daemon_mode) use syslog? */
212
364
    /* nb exec won't return unless there was an error */
 
365
    syslog(LOG_ERR, "exec of %s in %s failed", prog, canonical_jailpath);
 
366
 
213
367
    perror("could not exec");
 
368
    closelog();
214
369
    return 1;
215
370
}