• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/procd/jail/seccomp.c

  1 /*
  2  * seccomp example with syscall reporting
  3  *
  4  * Copyright (c) 2012 The Chromium OS Authors <chromium-os-dev@chromium.org>
  5  * Authors:
  6  *  Kees Cook <keescook@chromium.org>
  7  *  Will Drewry <wad@chromium.org>
  8  *
  9  * Use of this source code is governed by a BSD-style license that can be
 10  * found in the LICENSE file.
 11  */
 12 #define _GNU_SOURCE 1
 13 #include <stddef.h>
 14 #include <stdlib.h>
 15 #include <unistd.h>
 16 
 17 #include <libubox/utils.h>
 18 #include <libubox/blobmsg.h>
 19 #include <libubox/blobmsg_json.h>
 20 
 21 #include "seccomp-bpf.h"
 22 #include "seccomp.h"
 23 #include "../syscall-names.h"
 24 #include "seccomp-syscalls-helpers.h"
 25 
 26 int install_syscall_filter(const char *argv, const char *file)
 27 {
 28         enum {
 29                 SECCOMP_WHITELIST,
 30                 SECCOMP_POLICY,
 31                 __SECCOMP_MAX
 32         };
 33         static const struct blobmsg_policy policy[__SECCOMP_MAX] = {
 34                 [SECCOMP_WHITELIST] = { .name = "whitelist", .type = BLOBMSG_TYPE_ARRAY },
 35                 [SECCOMP_POLICY] = { .name = "policy", .type = BLOBMSG_TYPE_INT32 },
 36         };
 37         struct blob_buf b = { 0 };
 38         struct blob_attr *tb[__SECCOMP_MAX];
 39         struct blob_attr *cur;
 40         int rem;
 41 
 42         struct sock_filter *filter;
 43         struct sock_fprog prog = { 0 };
 44         int sz = 5, idx = 0, default_policy = 0;
 45 
 46         INFO("%s: setting up syscall filter\n", argv);
 47 
 48         blob_buf_init(&b, 0);
 49         if (!blobmsg_add_json_from_file(&b, file)) {
 50                 ERROR("%s: failed to load %s\n", argv, file);
 51                 return -1;
 52         }
 53 
 54         blobmsg_parse(policy, __SECCOMP_MAX, tb, blob_data(b.head), blob_len(b.head));
 55         if (!tb[SECCOMP_WHITELIST]) {
 56                 ERROR("%s: %s is missing the syscall table\n", argv, file);
 57                 return -1;
 58         }
 59 
 60         if (tb[SECCOMP_POLICY])
 61                 default_policy = blobmsg_get_u32(tb[SECCOMP_POLICY]);
 62 
 63         blobmsg_for_each_attr(cur, tb[SECCOMP_WHITELIST], rem)
 64                 sz += 2;
 65 
 66         filter = calloc(sz, sizeof(struct sock_filter));
 67         if (!filter) {
 68                 ERROR("failed to allocate filter memory\n");
 69                 return -1;
 70         }
 71 
 72         /* validate arch */
 73         set_filter(&filter[idx++], BPF_LD + BPF_W + BPF_ABS, 0, 0, arch_nr);
 74         set_filter(&filter[idx++], BPF_JMP + BPF_JEQ + BPF_K, 1, 0, ARCH_NR);
 75         set_filter(&filter[idx++], BPF_RET + BPF_K, 0, 0, SECCOMP_RET_KILL);
 76 
 77         /* get syscall */
 78         set_filter(&filter[idx++], BPF_LD + BPF_W + BPF_ABS, 0, 0, syscall_nr);
 79 
 80         blobmsg_for_each_attr(cur, tb[SECCOMP_WHITELIST], rem) {
 81                 char *name = blobmsg_get_string(cur);
 82                 int nr;
 83 
 84                 if (!name) {
 85                         INFO("%s: invalid syscall name\n", argv);
 86                         continue;
 87                 }
 88 
 89                 nr  = find_syscall(name);
 90                 if (nr == -1) {
 91                         INFO("%s: unknown syscall %s\n", argv, name);
 92                         continue;
 93                 }
 94 
 95                 /* add whitelist */
 96                 set_filter(&filter[idx++], BPF_JMP + BPF_JEQ + BPF_K, 0, 1, nr);
 97                 set_filter(&filter[idx++], BPF_RET + BPF_K, 0, 0, SECCOMP_RET_ALLOW);
 98         }
 99 
100         if (default_policy)
101                 /* notify tracer; without tracer return -1 and set errno to ENOSYS */
102                 set_filter(&filter[idx], BPF_RET + BPF_K, 0, 0, SECCOMP_RET_TRACE);
103         else
104                 /* kill the process */
105                 set_filter(&filter[idx], BPF_RET + BPF_K, 0, 0, SECCOMP_RET_KILL);
106 
107         if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
108                 ERROR("%s: prctl(PR_SET_NO_NEW_PRIVS) failed: %m\n", argv);
109                 goto errout;
110         }
111 
112         prog.len = (unsigned short) idx + 1;
113         prog.filter = filter;
114 
115         if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) {
116                 ERROR("%s: prctl(PR_SET_SECCOMP) failed: %m\n", argv);
117                 goto errout;
118         }
119         return 0;
120 
121 errout:
122         free(filter);
123         return errno;
124 }
125 

This page was automatically generated by LXR 0.3.1.  •  OpenWrt