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

Annotation of src/usr.bin/ssh/sandbox-systrace.c, Revision 1.1

1.1     ! djm         1: /*
        !             2:  * Copyright (c) 2011 Damien Miller <djm@mindrot.org>
        !             3:  *
        !             4:  * Permission to use, copy, modify, and distribute this software for any
        !             5:  * purpose with or without fee is hereby granted, provided that the above
        !             6:  * copyright notice and this permission notice appear in all copies.
        !             7:  *
        !             8:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
        !             9:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
        !            10:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
        !            11:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
        !            12:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
        !            13:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
        !            14:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
        !            15:  */
        !            16:
        !            17: #include <sys/types.h>
        !            18: #include <sys/param.h>
        !            19: #include <sys/ioctl.h>
        !            20: #include <sys/syscall.h>
        !            21: #include <sys/socket.h>
        !            22:
        !            23: #include <dev/systrace.h>
        !            24:
        !            25: #include <errno.h>
        !            26: #include <fcntl.h>
        !            27: #include <limits.h>
        !            28: #include <stdarg.h>
        !            29: #include <stdio.h>
        !            30: #include <stdlib.h>
        !            31: #include <string.h>
        !            32: #include <unistd.h>
        !            33:
        !            34: #include "atomicio.h"
        !            35: #include "log.h"
        !            36: #include "sandbox.h"
        !            37: #include "xmalloc.h"
        !            38:
        !            39: static const int preauth_policy[] = {
        !            40:        SYS___sysctl,
        !            41:        SYS_close,
        !            42:        SYS_exit,
        !            43:        SYS_getpid,
        !            44:        SYS_gettimeofday,
        !            45:        SYS_madvise,
        !            46:        SYS_mmap,
        !            47:        SYS_mprotect,
        !            48:        SYS_poll,
        !            49:        SYS_munmap,
        !            50:        SYS_read,
        !            51:        SYS_select,
        !            52:        SYS_sigprocmask,
        !            53:        SYS_write,
        !            54:        -1
        !            55: };
        !            56:
        !            57: struct ssh_sandbox {
        !            58:        int child_sock;
        !            59:        int parent_sock;
        !            60:        int systrace_fd;
        !            61:        pid_t child_pid;
        !            62:        struct systrace_policy policy;
        !            63: };
        !            64:
        !            65: struct ssh_sandbox *
        !            66: ssh_sandbox_init(void)
        !            67: {
        !            68:        struct ssh_sandbox *box;
        !            69:        int s[2];
        !            70:
        !            71:        debug3("%s: preparing systrace sandbox", __func__);
        !            72:        box = xcalloc(1, sizeof(*box));
        !            73:        if (socketpair(AF_UNIX, SOCK_STREAM, 0, s) == -1)
        !            74:                fatal("%s: socketpair: %s", __func__, strerror(errno));
        !            75:        box->child_sock = s[0];
        !            76:        box->parent_sock = s[1];
        !            77:        box->systrace_fd = -1;
        !            78:        box->child_pid = 0;
        !            79:
        !            80:        return box;
        !            81: }
        !            82:
        !            83: void
        !            84: ssh_sandbox_child(struct ssh_sandbox *box)
        !            85: {
        !            86:        char whatever = 0;
        !            87:
        !            88:        close(box->parent_sock);
        !            89:        /* Signal parent that we are ready */
        !            90:        debug3("%s: ready", __func__);
        !            91:        if (atomicio(vwrite, box->child_sock, &whatever, 1) != 1)
        !            92:                fatal("%s: write: %s", __func__, strerror(errno));
        !            93:        /* Wait for parent to signal for us to go */
        !            94:        if (atomicio(read, box->child_sock, &whatever, 1) != 1)
        !            95:                fatal("%s: read: %s", __func__, strerror(errno));
        !            96:        debug3("%s: started", __func__);
        !            97:        close(box->child_sock);
        !            98: }
        !            99:
        !           100: static void
        !           101: ssh_sandbox_parent(struct ssh_sandbox *box, pid_t child_pid,
        !           102:     const int *allowed_syscalls)
        !           103: {
        !           104:        int dev_systrace, i, j, found;
        !           105:        char whatever = 0;
        !           106:
        !           107:        debug3("%s: wait for child %ld", __func__, (long)child_pid);
        !           108:        box->child_pid = child_pid;
        !           109:        close(box->child_sock);
        !           110:        /* Wait for child to signal that it is ready */
        !           111:        if (atomicio(read, box->parent_sock, &whatever, 1) != 1)
        !           112:                fatal("%s: read: %s", __func__, strerror(errno));
        !           113:        debug3("%s: child %ld ready", __func__, (long)child_pid);
        !           114:
        !           115:        /* Set up systracing of child */
        !           116:        if ((dev_systrace = open("/dev/systrace", O_RDONLY)) == -1)
        !           117:                fatal("%s: open(\"/dev/systrace\"): %s", __func__,
        !           118:                    strerror(errno));
        !           119:        if (ioctl(dev_systrace, STRIOCCLONE, &box->systrace_fd) == -1)
        !           120:                fatal("%s: ioctl(STRIOCCLONE, %d): %s", __func__,
        !           121:                    dev_systrace, strerror(errno));
        !           122:        close(dev_systrace);
        !           123:        debug3("%s: systrace attach, fd=%d", __func__, box->systrace_fd);
        !           124:        if (ioctl(box->systrace_fd, STRIOCATTACH, &child_pid) == -1)
        !           125:                fatal("%s: ioctl(%d, STRIOCATTACH, %d): %s", __func__,
        !           126:                    box->systrace_fd, child_pid, strerror(errno));
        !           127:
        !           128:        /* Allocate and assign policy */
        !           129:        bzero(&box->policy, sizeof(box->policy));
        !           130:        box->policy.strp_op = SYSTR_POLICY_NEW;
        !           131:        box->policy.strp_maxents = SYS_MAXSYSCALL;
        !           132:        if (ioctl(box->systrace_fd, STRIOCPOLICY, &box->policy) == -1)
        !           133:                fatal("%s: ioctl(%d, STRIOCPOLICY (new)): %s", __func__,
        !           134:                    box->systrace_fd, strerror(errno));
        !           135:
        !           136:        box->policy.strp_op = SYSTR_POLICY_ASSIGN;
        !           137:        box->policy.strp_pid = box->child_pid;
        !           138:        if (ioctl(box->systrace_fd, STRIOCPOLICY, &box->policy) == -1)
        !           139:                fatal("%s: ioctl(%d, STRIOCPOLICY (assign)): %s",
        !           140:                    __func__, box->systrace_fd, strerror(errno));
        !           141:
        !           142:        /* Set per-syscall policy */
        !           143:        for (i = 0; i < SYS_MAXSYSCALL; i++) {
        !           144:                for (j = found = 0; allowed_syscalls[j] != -1 && !found; j++) {
        !           145:                        if (allowed_syscalls[j] == i)
        !           146:                                found = 1;
        !           147:                }
        !           148:                box->policy.strp_op = SYSTR_POLICY_MODIFY;
        !           149:                box->policy.strp_code = i;
        !           150:                box->policy.strp_policy = found ?
        !           151:                    SYSTR_POLICY_PERMIT : SYSTR_POLICY_KILL;
        !           152:                if (found)
        !           153:                        debug3("%s: policy: enable syscall %d", __func__, i);
        !           154:                if (ioctl(box->systrace_fd, STRIOCPOLICY,
        !           155:                    &box->policy) == -1)
        !           156:                        fatal("%s: ioctl(%d, STRIOCPOLICY (modify)): %s",
        !           157:                            __func__, box->systrace_fd, strerror(errno));
        !           158:        }
        !           159:
        !           160:        /* Signal the child to start running */
        !           161:        debug3("%s: start child %ld", __func__, (long)child_pid);
        !           162:        if (atomicio(vwrite, box->parent_sock, &whatever, 1) != 1)
        !           163:                fatal("%s: write: %s", __func__, strerror(errno));
        !           164:        close(box->parent_sock);
        !           165: }
        !           166:
        !           167: void
        !           168: ssh_sandbox_parent_finish(struct ssh_sandbox *box)
        !           169: {
        !           170:        /* Closing this before the child exits will terminate it */
        !           171:        close(box->systrace_fd);
        !           172:
        !           173:        free(box);
        !           174:        debug3("%s: finished", __func__);
        !           175: }
        !           176:
        !           177: void
        !           178: ssh_sandbox_parent_preauth(struct ssh_sandbox *box, pid_t child_pid)
        !           179: {
        !           180:        ssh_sandbox_parent(box, child_pid, preauth_policy);
        !           181: }