aboutgitcodelistschat:MatrixIRC
path: root/cooker/main.c
blob: 5c099ff4158ff9450212ab9ad0814d5d0d5e366b (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// SPDX-License-Identifier: GPL-2.0-or-later

/* seitan - Syscall Expressive Interpreter, Transformer and Notifier
 *
 * cooker/main.c - Entry point of seitan-cooker, the gluten (bytecode) generator
 *
 * Copyright 2023 Red Hat GmbH
 * Author: Stefano Brivio <sbrivio@redhat.com>
 * 	   Alice Frosi <afrosi@redhat.com>
 */

#define _GNU_SOURCE
#include <getopt.h>

#include "parson.h"
#include "cooker.h"
#include "gluten.h"
#include "parse.h"
#include "filter.h"
#include "seccomp_profile.h"

/* Cooker options */
static struct option options[] = {
	{ "input", required_argument, NULL, 'i' },
	{ "gluten", required_argument, NULL, 'g' },
	{ "filter", required_argument, NULL, 'f' },
	{ "scmp-out-prof", required_argument, NULL, 'p' },
	{ "scmp-orig-prof", required_argument, NULL, 's' }, //??? is required
};

struct arguments {
	char *input_file;
	char *gluten_file;
	char *filter_file;
	char *scmp_prof_file;
	char *orig_scmp_prof_file;
};

static void usage()
{
	printf("seitan-cooker: generate the BPF filters or seccomp profile and the action byte code for seitan\n"
               "Example:  setain-cooker -i <input file> -g <gluten_file> -f <filter_file>\n"
               "Usage:\n"
               "\t-i, --input:\t\tJSON input file\n"
               "\t-g, --gluten:\t\tBytecode file for seitan action\n"
               "\t-f, --filter:\t\tBPF filter file (cannot be used together with scmp-profile)\n"
               "\t-p, --scmp-prof:\tSeccomp profile file (cannot be used together with filter)\n"
               "\t-s, --scmp-orig-prof:\tOriginal seccomp profile (ignored if used with filter)\n");
        exit(EXIT_FAILURE);
}

static void parse(int argc, char **argv, struct arguments *arguments)
{
	int option_index = 0;
	int oc;
	if (arguments == NULL)
		usage();
	while ((oc = getopt_long(argc, argv, ":i:g:f:p:s:", options,
				 &option_index)) != -1) {
		switch (oc) {
		case 'i':
			arguments->input_file = optarg;
			break;
		case 'g':
			arguments->gluten_file = optarg;
			break;
		case 'f':
			arguments->filter_file = optarg;
			break;
		case 'p':
			arguments->scmp_prof_file = optarg;
			break;
		case 's':
			arguments->orig_scmp_prof_file = optarg;
			break;
		default:
			usage();
		}
	}
	if (arguments->input_file == NULL) {
		err("missing input file");
		usage();
	}
	if (arguments->filter_file != NULL &&
	    arguments->scmp_prof_file != NULL) {
		err("the filter and scmp-profile options cannot be used together");
		usage();
	}
	if (arguments->filter_file == NULL &&
	    arguments->scmp_prof_file == NULL) {
		err("select one of the options between filter and scmp-profile");
		usage();
	}
	if (arguments->gluten_file == NULL) {
		err("missing gluten file");
		usage();
	}
}

/**
 * main() - Entry point for cooker
 * @argc:	Argument count
 * @argv:	Options: input filename, output filename
 *
 * Return: zero on success, doesn't return on failure
 */
int main(int argc, char **argv)
{
	struct arguments arguments = { 0 };
	struct gluten_ctx g = { 0 };

	parse(argc, argv, &arguments);

	if (arguments.filter_file != NULL) {
		g.mode = SCMP_FILTER;
	} else {
		g.mode = SCMP_PROFILE;
		scmp_profile_init(arguments.orig_scmp_prof_file);
	}

	gluten_init(&g);

	parse_file(&g, arguments.input_file);

	gluten_write(&g, arguments.gluten_file);
	if (arguments.filter_file != NULL)
		filter_write(arguments.filter_file);
	else
		scmp_profile_write(arguments.scmp_prof_file);

	return 0;
}