aboutgitcodelistschat:MatrixIRC
path: root/cooker/gluten.c
blob: ac5a4bda9f89361f280f1dc07b167fe083632a85 (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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
// SPDX-License-Identifier: GPL-2.0-or-later

/* seitan - Syscall Expressive Interpreter, Transformer and Notifier
 *
 * cooker/gluten.c - gluten (bytecode) file and layout functions
 *
 * Copyright 2023 Red Hat GmbH
 * Author: Stefano Brivio <sbrivio@redhat.com>
 */

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

size_t gluten_size[TYPE_COUNT] = {
	[USHORT]	= sizeof(unsigned short),
	[INT]		= sizeof(int),
	[U32]		= sizeof(uint32_t),
	[U64]		= sizeof(uint64_t),
	[LONG]		= sizeof(long),

	[PID]		= sizeof(pid_t),
	[PORT]		= sizeof(in_port_t),
	[IPV4]		= sizeof(struct in_addr),
	[IPV6]		= sizeof(struct in6_addr),

	[GNU_DEV_MAJOR]	= sizeof(unsigned long long int),
	[GNU_DEV_MINOR]	= sizeof(unsigned long long int),

	[FDMOUNT]	= sizeof(int),
};

const char *jump_name[JUMP_COUNT] = { "next block", "next match", "next action",
				      "end" };

/**
 * gluten_rw_alloc() - Allocate in temporary (seitan read-write) data area
 * @g:		gluten context
 * @size:	Bytes to allocate
 *
 * Return: offset to allocated area
 */
struct gluten_offset gluten_rw_alloc(struct gluten_ctx *g, size_t size)
{
	struct gluten_offset ret = g->dp;

	debug("   allocating %lu at read-write offset %i", size, g->dp.offset);
	if ((g->dp.offset += size) >= DATA_SIZE)
		die("Temporary data size exceeded");

	return ret;
}

/**
 * gluten_rw_alloc_type() - Allocate storage for given type in temporary area
 * @g:		gluten context
 * @type:	Data type
 *
 * Return: offset to allocated area
 */
struct gluten_offset gluten_rw_alloc_type(struct gluten_ctx *g, enum type type)
{
	return gluten_rw_alloc(g, gluten_size[type]);
}

/**
 * gluten_ro_alloc() - Allocate in read-only data area
 * @g:		gluten context
 * @size:	Bytes to allocate
 *
 * Return: offset to allocated area
 */
struct gluten_offset gluten_ro_alloc(struct gluten_ctx *g, size_t size)
{
	struct gluten_offset ret = g->cp;

	debug("   allocating %lu at read-only offset %i", size, g->cp.offset);
	if ((g->cp.offset += size) >= RO_DATA_SIZE)
		die("Read-only data size exceeded");

	return ret;
}

/**
 * gluten_ro_alloc_type() - Allocate storage for given type in read-only area
 * @g:		gluten context
 * @type:	Data type
 *
 * Return: offset to allocated area
 */
struct gluten_offset gluten_ro_alloc_type(struct gluten_ctx *g, enum type type)
{
	return gluten_ro_alloc(g, gluten_size[type]);
}

void gluten_add_tag(struct gluten_ctx *g, const char *name,
		    struct gluten_offset offset)
{
	int i;

	for (i = 0; i < TAGS_MAX && g->tags[i].name; i++);
	if (i == TAGS_MAX)
		die("Too many tags");

	g->tags[i].name = name;
	g->tags[i].offset = offset;

	debug("   tag '%s' now refers to %s at %i",
	      name, gluten_offset_name[offset.type], offset.offset);
}

void gluten_add_tag_post(struct gluten_ctx *g, const char *name,
			 struct gluten_offset offset)
{
	/* TODO: Mark as invalid for current rule */
	gluten_add_tag(g, name, offset);
}

struct gluten_offset gluten_get_tag(struct gluten_ctx *g, const char *name)
{
	int i;

	for (i = 0; i < TAGS_MAX && g->tags[i].name; i++) {
		if (!strcmp(g->tags[i].name, name))
			return g->tags[i].offset;
	}

	die("   tag '%s' not found", name);
	return g->tags[0].offset;	/* Pro forma, not actually happening */
}

void gluten_add_attr(struct gluten_ctx *g, enum attr_type type, intptr_t id,
		     union value v)
{
	int i;

	for (i = 0; i < ATTRS_MAX && g->attrs[i].id; i++);
	if (i == ATTRS_MAX)
		die("Too many attributes");

	g->attrs[i].type = type;
	g->attrs[i].id = id;
	g->attrs[i].v = v;

	debug("   attribute '%p' set", id);
}

union value gluten_get_attr(struct gluten_ctx *g, enum attr_type type,
			    intptr_t id)
{
	union value missing = { 0 };
	int i;

	for (i = 0; i < ATTRS_MAX && g->attrs[i].type; i++) {
		if (g->attrs[i].type == type && g->attrs[i].id == id)
			return g->attrs[i].v;
	}

	debug("   attribute '%p' not found", id);
	return missing;
}

/**
 * gluten_init() - Initialise gluten structures and layout
 * @g:		gluten context
 */
void gluten_init(struct gluten_ctx *g)
{
	g->ip.offset = g->lr.offset = g->mr.offset = 0;
	g->ip.type = g->lr.type = g->mr.type = OFFSET_INSTRUCTION;
	g->dp.type = OFFSET_DATA;
	g->cp.type = OFFSET_RO_DATA;
}

void gluten_write(struct gluten_ctx *g, const char *path)
{
	ssize_t n;
	int fd;

	fd = open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC,
		  S_IRUSR | S_IWUSR);

	if ((n = write(fd, &g->g, sizeof(g->g))) == -1)
		die("Failed to write gluten: %s", strerror(errno));

	if (n != sizeof(g->g))
		die("Failed to write %i bytes of gluten", sizeof(g->g) - n);

	close(fd);
}

void gluten_relocation_add(struct gluten_ctx *g, struct gluten_offset offset)
{
	g->g.header.relocation[g->rel_count++] = offset;
	debug("   Added relocation for %s: %u", gluten_offset_name[offset.type],
	      offset.offset);
	if (g->rel_count >= 256)
		die("Too many relocations");
}