• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright 2016 The ChromiumOS Authors
2  * Use of this source code is governed by a BSD-style license that can be
3  * found in the LICENSE file.
4  */
5 
6 #include <getopt.h>
7 #include <stdio.h>
8 #include <string.h>
9 
10 #include <string>
11 
12 #include "bpf.h"
13 #include "syscall_filter.h"
14 #include "util.h"
15 
16 namespace {
17 
DumpBpfProg(struct sock_fprog * fprog)18 void DumpBpfProg(struct sock_fprog* fprog) {
19   struct sock_filter* filter = fprog->filter;
20   unsigned short len = fprog->len;
21 
22   printf("len == %d\n", len);
23   printf("filter:\n");
24   for (size_t i = 0; i < len; i++) {
25     printf("%zu: \t{ code=%#x, jt=%u, jf=%u, k=%#x \t}\n", i, filter[i].code,
26            filter[i].jt, filter[i].jf, filter[i].k);
27   }
28 }
29 
Usage(const char * progn,int status)30 void Usage(const char* progn, int status) {
31   // clang-format off
32   fprintf(status ? stderr : stdout,
33           "Usage: %s [--dump[=<output.bpf>]] [<policy file>]\n"
34           "\n"
35           "With no <policy file>, or when <policy file> is -, reads from standard input.\n"
36           "\n"
37           " --dump[=<output>]:  Dump the BPF program into stdout (or <output>,\n"
38           "      -d[<output>]:  if provided). Useful if you want to inspect it\n"
39           "                     with libseccomp's scmp_bpf_disasm.\n",
40           progn);
41   // clang-format on
42   exit(status);
43 }
44 
45 }  // namespace
46 
main(int argc,char ** argv)47 int main(int argc, char** argv) {
48   init_logging(LOG_TO_FD, STDERR_FILENO, LOG_INFO);
49 
50   static const char optstring[] = "d:h";
51   static const struct option long_options[] = {
52       {"help", no_argument, 0, 'h'},
53       {"dump", optional_argument, 0, 'd'},
54       {0, 0, 0, 0},
55   };
56 
57   bool dump = false;
58   std::string dump_path;
59   int opt;
60   while ((opt = getopt_long(argc, argv, optstring, long_options, NULL)) != -1) {
61     switch (opt) {
62       case 'h':
63         Usage(argv[0], 0);
64         return 0;
65       case 'd':
66         dump = true;
67         if (optarg)
68           dump_path = optarg;
69         break;
70     }
71   }
72 
73   FILE* f = stdin;
74   // If there is at least one additional unparsed argument, treat it as the
75   // policy script.
76   if (argc > optind && !streq(argv[optind], "-"))
77     f = fopen(argv[optind], "re");
78   if (!f)
79     pdie("fopen(%s) failed", argv[1]);
80 
81   struct filter_options fopts {
82     .action = ACTION_RET_KILL,
83     .allow_logging = 0,
84     .allow_syscalls_for_logging = 0,
85     .allow_duplicate_syscalls = allow_duplicate_syscalls(),
86   };
87 
88   struct sock_fprog fp;
89   int res = compile_filter(argv[1], f, &fp, &fopts);
90   fclose(f);
91   if (res != 0)
92     die("compile_filter failed");
93 
94   if (dump) {
95     FILE* out = stdout;
96     if (!dump_path.empty()) {
97       out = fopen(dump_path.c_str(), "we");
98       if (!out)
99         pdie("fopen(%s) failed", dump_path.c_str());
100     }
101     if (fwrite(fp.filter, sizeof(struct sock_filter), fp.len, out) != fp.len)
102       pdie("fwrite(%s) failed", dump_path.c_str());
103     fclose(out);
104   } else {
105     DumpBpfProg(&fp);
106   }
107 
108   free(fp.filter);
109   return 0;
110 }
111