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

« back to all changes in this revision

Viewing changes to trampoline/trampoline.c

  • Committer: mattgiuca
  • Date: 2008-02-05 01:41:15 UTC
  • Revision ID: svn-v3-trunk0:2b9c9e99-6f39-0410-b283-7f802c844ae2:trunk:409
Moved www/conf and www/common to a new directory lib. This separates the "web"
part of IVLE from what is becoming less web oriented (at least from Apache's
standpoint).
Modified setup.py to install this lib directory correctly and write conf in
the right place. Also adds the lib directory to ivle.pth.

Show diffs side-by-side

added added

removed removed

Lines of Context:
22
22
 * This program runs a given program in a given working dir.
23
23
 * First, it chroots to a jail path and setuids to a given user ID.
24
24
 * This is intented to provide a safe execution environment for arbitrary
25
 
 * programs and services.
 
25
 * programs and scripts.
26
26
 *
27
27
 * Scripts (such as Python programs) should be executed by supplying
28
28
 * "/usr/bin/python" as the program, and the script as the first argument.
33
33
 *  sudo chown root:root trampoline; sudo chroot +s trampoline
34
34
 */
35
35
 
36
 
#define _XOPEN_SOURCE
37
 
 
38
36
#include <stdio.h>
39
37
#include <stdlib.h>
40
38
#include <string.h>
41
39
#include <unistd.h>
42
 
#include <syslog.h>
43
 
#include <sys/mount.h>
44
40
#include <sys/types.h>
45
41
#include <sys/stat.h>
46
 
#include <sys/time.h>
47
 
#include <sys/resource.h>
48
42
#include <limits.h>
49
 
#include <signal.h>
50
43
 
51
44
/* conf.h is admin-configured by the setup process.
52
45
 * It defines jail_base.
53
46
 */
54
47
#include "conf.h"
55
48
 
56
 
#include "norm.h"
57
 
 
58
49
/* Returns TRUE if the given uid is allowed to execute trampoline.
59
50
 * Only root or the web server should be allowed to execute.
60
51
 * This is determined by the whitelist allowed_uids in conf.h.
98
89
    /* At this point we are executing as the child process */
99
90
 
100
91
    /* Change the file mode mask */
101
 
    umask(022);
 
92
    umask(0);
102
93
 
103
94
    /* Create a new SID for the child process */
104
95
    sid = setsid();
121
112
static void usage(const char* nm)
122
113
{
123
114
    fprintf(stderr,
124
 
        "usage: %s [-d] [-u] <uid> <jail> <cwd> <program> [args...]\n", nm);
 
115
        "usage: %s [-d] <uid> <jail> <cwd> <program> [args...]\n", nm);
125
116
    exit(1);
126
117
}
127
118
 
128
 
#ifdef IVLE_AUFS_JAILS
129
 
/* Die more pleasantly if mallocs fail. */
130
 
void *die_if_null(void *ptr)
131
 
{
132
 
    if (ptr == NULL)
133
 
    {
134
 
        perror("not enough memory");
135
 
        exit(1);
136
 
    }
137
 
    return ptr;
138
 
}
139
 
 
140
 
/* Find the path of the user components of a jail, given a mountpoint. */
141
 
char *jail_src(const char* jailpath)
142
 
{
143
 
    char* src;
144
 
    int srclen;
145
 
    int dstlen;
146
 
 
147
 
    srclen = strlen(jail_src_base);
148
 
    dstlen = strlen(jail_base);
149
 
    
150
 
    src = die_if_null(malloc(strlen(jailpath) + (srclen - dstlen) + 1));
151
 
    strcpy(src, jail_src_base);
152
 
    strcat(src, jailpath+dstlen);
153
 
 
154
 
    return src;
155
 
}
156
 
 
157
 
/* Check for the validity of a jail in the given path, mounting it if it looks
158
 
 * empty.
159
 
 * TODO: Updating /etc/mtab would be nice. */
160
 
void mount_if_needed(const char* jailpath)
161
 
{
162
 
    char *jailsrc;
163
 
    char *jaillib;
164
 
    char *mountdata;
165
 
 
166
 
    /* Check if there is something useful in the jail. If not, it's probably
167
 
     * not mounted. */
168
 
    jaillib = die_if_null(malloc(strlen(jailpath) + 5));
169
 
    sprintf(jaillib, "%s/lib", jailpath);
170
 
 
171
 
    if (access(jaillib, F_OK))
172
 
    {
173
 
        /* No /lib? Mustn't be mounted. Mount it, creating the dir if needed. */
174
 
        if (access(jailpath, F_OK))
175
 
        {
176
 
             if(mkdir(jailpath, 0755))
177
 
             {
178
 
                 syslog(LOG_ERR, "could not create mountpoint %s\n", jailpath);
179
 
                 perror("could not create jail mountpoint");
180
 
                 exit(1);
181
 
             }
182
 
             syslog(LOG_NOTICE, "created mountpoint %s\n", jailpath);
183
 
        }
184
 
       
185
 
        jailsrc = jail_src(jailpath);
186
 
        mountdata = die_if_null(malloc(3 + strlen(jailsrc) + 4 + strlen(jail_system) + 3 + 1));
187
 
        sprintf(mountdata, "br:%s=rw:%s=ro", jailsrc, jail_system);
188
 
        if (mount("none", jailpath, "aufs", 0, mountdata))
189
 
        {
190
 
            syslog(LOG_ERR, "could not mount %s\n", jailpath);
191
 
            perror("could not mount");
192
 
            exit(1);
193
 
        } 
194
 
 
195
 
        syslog(LOG_INFO, "mounted %s\n", jailpath);
196
 
 
197
 
        free(jailsrc);
198
 
        free(mountdata);
199
 
    }
200
 
 
201
 
    free(jaillib);
202
 
}
203
 
#endif /* IVLE_AUFS_JAILS */
204
 
 
205
 
/* Unsets any signal mask applied by the parent process */
206
 
int unmask_signals(void)
207
 
{
208
 
    int result;
209
 
    sigset_t* sigset;
210
 
    sigset = die_if_null(malloc(sizeof(sigset_t)));
211
 
    sigemptyset(sigset);
212
 
    result = sigprocmask(SIG_SETMASK, sigset, NULL);
213
 
    free(sigset);
214
 
    printf("%d", result);
215
 
    return result;
216
 
}
217
 
 
218
119
int main(int argc, char* const argv[])
219
120
{
220
121
    char* jailpath;
224
125
    int uid;
225
126
    int arg_num = 1;
226
127
    int daemon_mode = 0;
227
 
    int unlimited = 0;
228
128
    char canonical_jailpath[PATH_MAX];
229
129
 
230
130
    /* Disallow execution from all users but the whitelisted ones, and root */
249
149
        daemon_mode = 1;
250
150
        arg_num++;
251
151
    }
252
 
 
253
 
    if (strcmp(argv[arg_num], "-u") == 0)
254
 
    {
255
 
        if (argc < 6)
256
 
        {
257
 
            usage(argv[0]);
258
 
        }
259
 
        unlimited = 1;
260
 
        arg_num++;
261
 
    }
262
152
    uid = atoi(argv[arg_num++]);
263
153
    jailpath = argv[arg_num++];
264
154
    work_dir = argv[arg_num++];
286
176
        exit(1);
287
177
    }
288
178
 
289
 
    openlog("trampoline", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_USER);
290
 
 
291
 
    #ifdef IVLE_AUFS_JAILS
292
 
    mount_if_needed(canonical_jailpath);
293
 
    #endif /* IVLE_AUFS_JAILS */
294
 
 
295
179
    /* chroot into the jail.
296
180
     * Henceforth this process, and its children, cannot see anything above
297
181
     * canoncial_jailpath. */
298
182
    if (chroot(canonical_jailpath))
299
183
    {
300
 
        syslog(LOG_ERR, "chroot to %s failed\n", canonical_jailpath);
301
 
 
302
184
        perror("could not chroot");
303
185
        exit(1);
304
186
    }
313
195
    /* setuid to the given user ID.
314
196
     * Henceforth we will be running as this user instead of root.
315
197
     */
316
 
    if (setgid(uid))
317
 
    {
318
 
        perror("could not setgid");
319
 
        exit(1);
320
 
    }
321
 
 
322
198
    if (setuid(uid))
323
199
    {
324
200
        perror("could not setuid");
325
201
        exit(1);
326
202
    }
327
203
 
328
 
    /* set user resource limits */
329
 
    if (!unlimited)
330
 
    {
331
 
        struct rlimit l;
332
 
        /* Process adress space in memory */
333
 
        l.rlim_cur = 192 * 1024 * 1024; /* 192MiB */
334
 
        l.rlim_max = 256 * 1024 * 1024; /* 256MiB */
335
 
        if (setrlimit(RLIMIT_AS, &l))
336
 
        {
337
 
            perror("could not setrlimit/RLIMIT_AS");
338
 
            exit(1);
339
 
        }
340
 
        
341
 
        /* Process data segment in memory
342
 
         * Note: This requires a kernel patch to work correctly otherwise it is  
343
 
         * ineffective (thus you are only limited by RLIMIT_AS)
344
 
         */
345
 
        l.rlim_cur = 192 * 1024 * 1024; /* 192MiB */
346
 
        l.rlim_max = 256 * 1024 * 1024; /* 256MiB */
347
 
        if (setrlimit(RLIMIT_DATA, &l))
348
 
        {
349
 
            perror("could not setrlimit/RLIMIT_DATA");
350
 
            exit(1);
351
 
        }
352
 
 
353
 
        /* Core */
354
 
        l.rlim_cur = 0; /* No core files */
355
 
        l.rlim_max = 0; /* No core files */
356
 
        if (setrlimit(RLIMIT_CORE, &l))
357
 
        {
358
 
            perror("could not setrlimit/RLIMIT_CORE");
359
 
            exit(1);
360
 
        }
361
 
 
362
 
        /* CPU */
363
 
        l.rlim_cur = 25; /* 25 Seconds */
364
 
        l.rlim_max = 30; /* 30 Seconds */
365
 
        if (setrlimit(RLIMIT_CPU, &l))
366
 
        {
367
 
            perror("could not setrlimit/RLIMIT_CPU");
368
 
            exit(1);
369
 
        }
370
 
 
371
 
        /* File Size */
372
 
        l.rlim_cur = 64 * 1024 * 1024; /* 64MiB */
373
 
        l.rlim_max = 72 * 1024 * 1024; /* 72MiB */
374
 
if (setrlimit(RLIMIT_FSIZE, &l))
375
 
        {
376
 
            perror("could not setrlimit/RLIMIT_FSIZE");
377
 
            exit(1);
378
 
        }
379
 
    }
380
 
 
381
 
    /* Remove any signal handler masks so we can send signals to the child */
382
 
    if(unmask_signals())
383
 
    {
384
 
        perror("could not unmask signals");
385
 
        exit(1);
386
 
    }
387
 
 
388
 
    /* If everything was OK daemonize (if required) */
389
204
    if (daemon_mode)
390
205
    {
391
206
        daemonize();
397
212
     * and the first argument will be the script. */
398
213
    execv(prog, args);
399
214
 
 
215
    /* XXX if (daemon_mode) use syslog? */
400
216
    /* nb exec won't return unless there was an error */
401
 
    syslog(LOG_ERR, "exec of %s in %s failed", prog, canonical_jailpath);
402
 
 
403
217
    perror("could not exec");
404
 
    closelog();
405
218
    return 1;
406
219
}