[BACK]Return to sandbox.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / file

Annotation of src/usr.bin/file/sandbox.c, Revision 1.5

1.5     ! deraadt     1: /* $OpenBSD: sandbox.c,v 1.4 2015/04/30 14:30:53 nicm Exp $ */
1.1       nicm        2:
                      3: /*
                      4:  * Copyright (c) 2015 Nicholas Marriott <nicm@openbsd.org>
                      5:  *
                      6:  * Permission to use, copy, modify, and distribute this software for any
                      7:  * purpose with or without fee is hereby granted, provided that the above
                      8:  * copyright notice and this permission notice appear in all copies.
                      9:  *
                     10:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     11:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     12:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     13:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     14:  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
                     15:  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
                     16:  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     17:  */
                     18:
                     19: #include <sys/types.h>
                     20: #include <sys/ioctl.h>
                     21: #include <sys/syscall.h>
                     22: #include <sys/wait.h>
                     23:
                     24: #include <dev/systrace.h>
                     25:
                     26: #include <errno.h>
                     27: #include <fcntl.h>
                     28: #include <pwd.h>
                     29: #include <signal.h>
                     30: #include <unistd.h>
                     31:
                     32: #include "file.h"
                     33: #include "magic.h"
                     34: #include "xmalloc.h"
                     35:
                     36: static const struct
                     37: {
                     38:        int syscallnum;
                     39:        int action;
                     40: } allowed_syscalls[] = {
                     41:        { SYS_open, SYSTR_POLICY_NEVER }, /* for strerror */
                     42:
                     43:        { SYS_close, SYSTR_POLICY_PERMIT },
                     44:        { SYS_exit, SYSTR_POLICY_PERMIT },
1.5     ! deraadt    45:        { SYS_fcntl, SYSTR_POLICY_PERMIT },
        !            46:        { SYS_fstat, SYSTR_POLICY_PERMIT },
1.1       nicm       47:        { SYS_getdtablecount, SYSTR_POLICY_PERMIT },
                     48:        { SYS_getentropy, SYSTR_POLICY_PERMIT },
                     49:        { SYS_getpid, SYSTR_POLICY_PERMIT },
                     50:        { SYS_getrlimit, SYSTR_POLICY_PERMIT },
                     51:        { SYS_issetugid, SYSTR_POLICY_PERMIT },
                     52:        { SYS_madvise, SYSTR_POLICY_PERMIT },
                     53:        { SYS_mmap, SYSTR_POLICY_PERMIT },
                     54:        { SYS_mprotect, SYSTR_POLICY_PERMIT },
                     55:        { SYS_mquery, SYSTR_POLICY_PERMIT },
                     56:        { SYS_munmap, SYSTR_POLICY_PERMIT },
                     57:        { SYS_read, SYSTR_POLICY_PERMIT },
                     58:        { SYS_recvmsg, SYSTR_POLICY_PERMIT },
                     59:        { SYS_sendmsg, SYSTR_POLICY_PERMIT },
                     60:        { SYS_sigprocmask, SYSTR_POLICY_PERMIT },
                     61:        { SYS_write, SYSTR_POLICY_PERMIT },
                     62:
                     63:        { -1, -1 }
                     64: };
                     65:
                     66: static int
                     67: sandbox_find(int syscallnum)
                     68: {
                     69:        int     i;
                     70:
                     71:        for (i = 0; allowed_syscalls[i].syscallnum != -1; i++) {
                     72:                if (allowed_syscalls[i].syscallnum == syscallnum)
                     73:                        return (allowed_syscalls[i].action);
                     74:        }
                     75:        return (SYSTR_POLICY_KILL);
                     76: }
                     77:
                     78: static int
                     79: sandbox_child(const char *user)
                     80: {
                     81:        struct passwd   *pw;
                     82:
                     83:        if (geteuid() == 0) {
                     84:                pw = getpwnam(user);
                     85:                if (pw == NULL)
                     86:                        errx(1, "unknown user %s", user);
                     87:                if (setgroups(1, &pw->pw_gid) != 0)
                     88:                        err(1, "setgroups");
                     89:                if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) != 0)
                     90:                        err(1, "setresgid");
                     91:                if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) != 0)
                     92:                        err(1, "setresuid");
                     93:        }
                     94:
                     95:        if (kill(getpid(), SIGSTOP) != 0)
                     96:                err(1, "kill(SIGSTOP)");
                     97:        return (0);
                     98: }
                     99:
                    100: int
                    101: sandbox_fork(const char *user)
                    102: {
                    103:        pid_t                    pid;
                    104:        int                      status, devfd, fd, i;
                    105:        struct systrace_policy   policy;
                    106:
                    107:        switch (pid = fork()) {
                    108:        case -1:
                    109:                err(1, "fork");
                    110:        case 0:
                    111:                return (sandbox_child(user));
                    112:        }
                    113:
1.4       nicm      114:        /*
                    115:         * Wait for the child to stop itself with SIGSTOP before assigning the
                    116:         * policy, before that it might still be calling syscalls the policy
                    117:         * would block.
                    118:         */
1.2       deraadt   119:        do {
1.1       nicm      120:                pid = waitpid(pid, &status, WUNTRACED);
1.2       deraadt   121:        } while (pid == -1 && errno == EINTR);
1.1       nicm      122:        if (!WIFSTOPPED(status))
                    123:                errx(1, "child not stopped");
                    124:
                    125:        devfd = open("/dev/systrace", O_RDONLY);
                    126:        if (devfd == -1)
                    127:                err(1, "open(\"/dev/systrace\")");
                    128:        if (ioctl(devfd, STRIOCCLONE, &fd) == -1)
                    129:                err(1, "ioctl(STRIOCCLONE)");
                    130:        close(devfd);
                    131:
                    132:        if (ioctl(fd, STRIOCATTACH, &pid) == -1)
                    133:                err(1, "ioctl(STRIOCATTACH)");
                    134:
                    135:        memset(&policy, 0, sizeof policy);
                    136:        policy.strp_op = SYSTR_POLICY_NEW;
                    137:        policy.strp_maxents = SYS_MAXSYSCALL;
                    138:        if (ioctl(fd, STRIOCPOLICY, &policy) == -1)
                    139:                err(1, "ioctl(STRIOCPOLICY/NEW)");
                    140:        policy.strp_op = SYSTR_POLICY_ASSIGN;
                    141:        policy.strp_pid = pid;
                    142:        if (ioctl(fd, STRIOCPOLICY, &policy) == -1)
                    143:                err(1, "ioctl(STRIOCPOLICY/ASSIGN)");
                    144:
                    145:        for (i = 0; i < SYS_MAXSYSCALL; i++) {
                    146:                policy.strp_op = SYSTR_POLICY_MODIFY;
                    147:                policy.strp_code = i;
                    148:                policy.strp_policy = sandbox_find(i);
                    149:                if (ioctl(fd, STRIOCPOLICY, &policy) == -1)
                    150:                        err(1, "ioctl(STRIOCPOLICY/MODIFY)");
                    151:        }
                    152:
                    153:        if (kill(pid, SIGCONT) != 0)
                    154:                err(1, "kill(SIGCONT)");
                    155:        return (pid);
                    156: }