111 lines
2.8 KiB
C++
111 lines
2.8 KiB
C++
|
/* Copyright 2016 The Chromium OS Authors. All rights reserved.
|
||
|
* Use of this source code is governed by a BSD-style license that can be
|
||
|
* found in the LICENSE file.
|
||
|
*/
|
||
|
|
||
|
#include <getopt.h>
|
||
|
#include <stdio.h>
|
||
|
#include <string.h>
|
||
|
|
||
|
#include <string>
|
||
|
|
||
|
#include "bpf.h"
|
||
|
#include "syscall_filter.h"
|
||
|
#include "util.h"
|
||
|
|
||
|
namespace {
|
||
|
|
||
|
void DumpBpfProg(struct sock_fprog* fprog) {
|
||
|
struct sock_filter* filter = fprog->filter;
|
||
|
unsigned short len = fprog->len;
|
||
|
|
||
|
printf("len == %d\n", len);
|
||
|
printf("filter:\n");
|
||
|
for (size_t i = 0; i < len; i++) {
|
||
|
printf("%zu: \t{ code=%#x, jt=%u, jf=%u, k=%#x \t}\n", i, filter[i].code,
|
||
|
filter[i].jt, filter[i].jf, filter[i].k);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void Usage(const char* progn, int status) {
|
||
|
// clang-format off
|
||
|
fprintf(status ? stderr : stdout,
|
||
|
"Usage: %s [--dump[=<output.bpf>]] [<policy file>]\n"
|
||
|
"\n"
|
||
|
"With no <policy file>, or when <policy file> is -, reads from standard input.\n"
|
||
|
"\n"
|
||
|
" --dump[=<output>]: Dump the BPF program into stdout (or <output>,\n"
|
||
|
" -d[<output>]: if provided). Useful if you want to inspect it\n"
|
||
|
" with libseccomp's scmp_bpf_disasm.\n",
|
||
|
progn);
|
||
|
// clang-format on
|
||
|
exit(status);
|
||
|
}
|
||
|
|
||
|
} // namespace
|
||
|
|
||
|
int main(int argc, char** argv) {
|
||
|
init_logging(LOG_TO_FD, STDERR_FILENO, LOG_INFO);
|
||
|
|
||
|
const char* optstring = "d:h";
|
||
|
const struct option long_options[] = {
|
||
|
{"help", no_argument, 0, 'h'},
|
||
|
{"dump", optional_argument, 0, 'd'},
|
||
|
{0, 0, 0, 0},
|
||
|
};
|
||
|
|
||
|
bool dump = false;
|
||
|
std::string dump_path;
|
||
|
int opt;
|
||
|
while ((opt = getopt_long(argc, argv, optstring, long_options, NULL)) != -1) {
|
||
|
switch (opt) {
|
||
|
case 'h':
|
||
|
Usage(argv[0], 0);
|
||
|
return 0;
|
||
|
case 'd':
|
||
|
dump = true;
|
||
|
if (optarg)
|
||
|
dump_path = optarg;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
FILE* f = stdin;
|
||
|
// If there is at least one additional unparsed argument, treat it as the
|
||
|
// policy script.
|
||
|
if (argc > optind && strcmp(argv[optind], "-") != 0)
|
||
|
f = fopen(argv[optind], "re");
|
||
|
if (!f)
|
||
|
pdie("fopen(%s) failed", argv[1]);
|
||
|
|
||
|
struct filter_options fopts {
|
||
|
.action = ACTION_RET_KILL,
|
||
|
.allow_logging = 0,
|
||
|
.allow_syscalls_for_logging = 0,
|
||
|
.allow_duplicate_syscalls = allow_duplicate_syscalls(),
|
||
|
};
|
||
|
|
||
|
struct sock_fprog fp;
|
||
|
int res = compile_filter(argv[1], f, &fp, &fopts);
|
||
|
fclose(f);
|
||
|
if (res != 0)
|
||
|
die("compile_filter failed");
|
||
|
|
||
|
if (dump) {
|
||
|
FILE* out = stdout;
|
||
|
if (!dump_path.empty()) {
|
||
|
out = fopen(dump_path.c_str(), "we");
|
||
|
if (!out)
|
||
|
pdie("fopen(%s) failed", dump_path.c_str());
|
||
|
}
|
||
|
if (fwrite(fp.filter, sizeof(struct sock_filter), fp.len, out) != fp.len)
|
||
|
pdie("fwrite(%s) failed", dump_path.c_str());
|
||
|
fclose(out);
|
||
|
} else {
|
||
|
DumpBpfProg(&fp);
|
||
|
}
|
||
|
|
||
|
free(fp.filter);
|
||
|
return 0;
|
||
|
}
|