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