aboutgitcodelistschat:MatrixIRC
path: root/cooker/emit.c
blob: 8c35f1d9339bc48c3e45a31bf0149aa213276bb0 (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
// SPDX-License-Identifier: GPL-3.0-or-later

/* seitan - Syscall Expressive Interpreter, Transformer and Notifier
 *
 * cooker/emit.c - Generate gluten (bytecode) instructions and read-only data
 *
 * Copyright 2023 Red Hat GmbH
 * Author: Stefano Brivio <sbrivio@redhat.com>
 */

#include "cooker.h"
#include "gluten.h"
#include "util.h"
#include "emit.h"

static const char *type_str[] = {
	"INT",  "INTMASK",  "INTFLAGS",
	"U32",  "U32MASK",  "U32FLAGS",
	"LONG", "LONGMASK", "LONGFLAGS",
	"STRING",
	"STRUCT", "SELECT",
	"PID",
	"PORT", "IPV4", "IPV6",
	"FDPATH",
	NULL
};

static const char *cmp_type_str[] = { "EQ", "GT", "GE", "LT", "LE", NULL };

void emit_nr(struct gluten_ctx *g, long number)
{
	struct op_nr *nr = (struct op_nr *)gluten_ptr(&g->g, g->ip);

	nr->nr = number;
	nr->no_match.type = OFFSET_INSTRUCTION;
	nr->no_match.offset = NEXT_BLOCK;

	debug("   %i: OP_NR %li, < >", g->ip.offset, number);

	if (++g->ip.offset > INST_MAX)
		die("Too many instructions");
}

void emit_load(struct gluten_ctx *g, struct gluten_offset dst,
	       int index, size_t len)
{
	struct op_load *load = (struct op_load *)gluten_ptr(&g->g, g->ip);

	load->src.type = OFFSET_SECCOMP_DATA;
	load->src.offset = index;

	load->dst = dst;

	debug("   %i: OP_LOAD #%i < %i (%lu)", g->ip.offset, dst.offset,
					       index, len);

	if (++g->ip.offset > INST_MAX)
		die("Too many instructions");
}

void emit_cmp(struct gluten_ctx *g, enum op_cmp_type cmp,
	      struct gluten_offset x, struct gluten_offset y, size_t size,
	      enum jump_type jmp)
{
	struct op_cmp *op = (struct op_cmp *)gluten_ptr(&g->g, g->ip);

	op->x = x;
	op->y = y;
	op->size = size;
	op->cmp = cmp;
	op->jmp = jmp;

	debug("   %i: OP_CMP (#%lu) %%%lu %s %%%lu", g->ip.offset, size,
	      x.offset, cmp_type_str[cmp], y.offset);

	if (++g->ip.offset > INST_MAX)
		die("Too many instructions");
}

void emit_cmp_field(struct gluten_ctx *g, enum op_cmp_type cmp,
		    struct field *field,
		    struct gluten_offset base, struct gluten_offset match,
		    enum jump_type jmp)
{
	base.offset += field->offset;

	emit_cmp(g, cmp, base, match,
		 field->strlen ? field->strlen : gluten_size[field->type],
		 jmp);
}

struct gluten_offset emit_data(struct gluten_ctx *g, enum type type,
			       union value *value)
{
	void *p = gluten_ptr(&g->g, g->cp);
	struct gluten_offset ret = g->cp;

	if (type == INT) {
		*(int *)p = value->v_int;
		debug("   C#%i: (%s) %i", g->cp.offset, type_str[type],
		      value->v_int);
		if ((g->cp.offset += sizeof(int)) > RO_DATA_SIZE)
			die("   Read-only data section exceeded");
	}

	return ret;
}