aboutgitcodelistschat:MatrixIRC
path: root/cooker/emit.c
diff options
context:
space:
mode:
authorStefano Brivio <sbrivio@redhat.com>2024-08-13 18:50:33 +0200
committerStefano Brivio <sbrivio@redhat.com>2024-08-13 19:00:35 +0200
commit9bf3b1cc7a94357c250f77f16829c96cbae801fe (patch)
tree56cbc184974b18d33aa288dda7b12e5a77c38a94 /cooker/emit.c
parentd699dac08778c597eefac1067a325059925e87e6 (diff)
downloadseitan-9bf3b1cc7a94357c250f77f16829c96cbae801fe.tar
seitan-9bf3b1cc7a94357c250f77f16829c96cbae801fe.tar.gz
seitan-9bf3b1cc7a94357c250f77f16829c96cbae801fe.tar.bz2
seitan-9bf3b1cc7a94357c250f77f16829c96cbae801fe.tar.lz
seitan-9bf3b1cc7a94357c250f77f16829c96cbae801fe.tar.xz
seitan-9bf3b1cc7a94357c250f77f16829c96cbae801fe.tar.zst
seitan-9bf3b1cc7a94357c250f77f16829c96cbae801fe.zip
call, emit, match: Add support for vectorised operations, nfnetlinkHEADmaster
We want to add and delete rules with iptables(8), and manipulate set elements with nft(8). These are the first users we encounter sending multiple netlink messages in one sendmsg(). To support matching on those, we need to iterate over several messages, looking for a matching one, or a mismatching one (depending on quantifiers and match type), but we don't want to implement program loops because of security design reasons. We can't implement a generalised instruction that vectorises existing ones, either, because we need to support universal and existential quantifiers in fields that are repeated multiple times, once per each netlink message, with bitwise operations and non-exact matching types. Add vectorisation support to OP_CMP and OP_BITWISE instead, with a generic description for a vector (only sequences of netlink messages with length in nlmsghdr are supported at the moment) so that, depending on the quantifiers, we'll repeat those operations as many times as needed. This way, we don't risk any O(n^2) explosion, and we are bound by O(m * n) instead, with m compare/bitwise operations for a given expression, and n number of netlink messages. Add demos for nft and iptables using the new concepts. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
Diffstat (limited to 'cooker/emit.c')
-rw-r--r--cooker/emit.c52
1 files changed, 43 insertions, 9 deletions
diff --git a/cooker/emit.c b/cooker/emit.c
index 33355b6..7d13a02 100644
--- a/cooker/emit.c
+++ b/cooker/emit.c
@@ -217,18 +217,19 @@ void emit_store(struct gluten_ctx *g, struct gluten_offset dst,
* @iov: Pointer to msg_iov, already stored in gluten
* @iovlen: Pointer to msg_iovlen, already stored in gluten
* @dst: gluten destination to copy dereferenced data
+ * @alloc: Allocation size (alloc - len bytes filled with zeroes)
* @len: Maximum length of data to copy altogether
*/
struct gluten_offset emit_iovload(struct gluten_ctx *g,
struct gluten_offset iov,
struct gluten_offset iovlen,
- size_t len)
+ size_t alloc, size_t len)
{
struct op *op = (struct op *)gluten_ptr(&g->g, g->ip);
struct op_iovload *load = &op->op.iovload;
struct gluten_offset dst;
- dst = gluten_rw_alloc(g, len);
+ dst = gluten_rw_alloc(g, alloc);
op->type = OP_IOVLOAD;
@@ -237,6 +238,7 @@ struct gluten_offset emit_iovload(struct gluten_ctx *g,
load->dst = dst;
load->size = len;
+ load->zero_fill = alloc - len;
debug(" %i: OP_IOVLOAD: #%i < (#%i) as iovec (size: %lu)",
g->ip.offset, dst.offset, iov.offset, len);
@@ -294,6 +296,7 @@ void emit_resolvefd(struct gluten_ctx *g, enum type type,
* emit_bitwise(): Emit OP_BITWISE instruction: bitwise operation and store
* @g: gluten context
* @type: Type of operands
+ * @vec: Description of vector structure, NULL for scalar operation
* @op_type: Type of bitwise operation
* @dst: gluten pointer to destination operand, can be OFFSET_NULL
* @x: gluten pointer to first source operand
@@ -302,6 +305,7 @@ void emit_resolvefd(struct gluten_ctx *g, enum type type,
* Return: offset to destination operand, allocated here if not given
*/
struct gluten_offset emit_bitwise(struct gluten_ctx *g, enum type type,
+ struct vec_desc *vec,
enum bitwise_type op_type,
struct gluten_offset dst,
struct gluten_offset x,
@@ -311,6 +315,7 @@ struct gluten_offset emit_bitwise(struct gluten_ctx *g, enum type type,
struct op_bitwise *op_bitwise = &op->op.bitwise;
struct gluten_offset o;
struct bitwise_desc *desc;
+ char ip_str[BUFSIZ];
op->type = OP_BITWISE;
@@ -319,21 +324,42 @@ struct gluten_offset emit_bitwise(struct gluten_ctx *g, enum type type,
desc->size = gluten_size[type];
desc->type = op_type;
- if (dst.type == OFFSET_NULL)
- desc->dst = gluten_rw_alloc(g, desc->size);
- else
+
+ if (vec)
+ desc->vec = *vec;
+
+ if (dst.type == OFFSET_NULL) {
+ size_t dst_size;
+ if (vec) /* FIXME: UIO_MAXIOV (1024) is a dubious choice */
+ dst_size = (desc->size + sizeof(uint32_t)) * 1024;
+ else
+ dst_size = desc->size;
+
+ desc->dst = gluten_rw_alloc(g, dst_size);
+ } else {
desc->dst = dst;
+ }
+
desc->x = x;
desc->y = y;
op_bitwise->desc = o;
- debug(" %i: OP_BITWISE: %s: #%lu (size: %lu) := %s: #%lu %s %s: #%lu",
- g->ip.offset,
+ snprintf(ip_str, BUFSIZ, "%i", g->ip.offset);
+
+ debug(" %s: OP_BITWISE: %s: #%lu (size: %lu) := %s: #%lu %s %s: #%lu",
+ ip_str,
gluten_offset_name[desc->dst.type], desc->dst.offset, desc->size,
gluten_offset_name[desc->x.type], desc->x.offset,
bitwise_type_str[op_type],
gluten_offset_name[desc->y.type], desc->y.offset);
+ if (vec) {
+ memset(ip_str, ' ', strlen(ip_str));
+ debug(" %s vector start: %s: #%lu, length descriptor at %lu",
+ ip_str,
+ gluten_offset_name[vec->start.type], vec->start.offset,
+ vec->len_offset);
+ }
if (++g->ip.offset > INST_MAX)
die("Too many instructions");
@@ -345,12 +371,14 @@ struct gluten_offset emit_bitwise(struct gluten_ctx *g, enum type type,
* emit_cmp(): Emit OP_CMP instruction: compare data from two offsets
* @g: gluten context
* @cmp_type: Type of comparison
+ * @vec: Description of vector structure, NULL for scalar comparison
* @x: gluten pointer to first operand of comparison
* @y: gluten pointer to second operand of comparison
* @size: Size of comparison
* @jmp: Jump direction if comparison is true
*/
void emit_cmp(struct gluten_ctx *g, enum op_cmp_type cmp_type,
+ struct vec_desc *vec,
struct gluten_offset x, struct gluten_offset y, size_t size,
enum jump_type jmp)
{
@@ -367,6 +395,11 @@ void emit_cmp(struct gluten_ctx *g, enum op_cmp_type cmp_type,
desc->x = x;
desc->y = y;
desc->size = size;
+ if (vec)
+ desc->vec = *vec;
+ else
+ desc->vec.start.type = OFFSET_NULL;
+
desc->cmp = cmp_type;
desc->jmp.type = OFFSET_INSTRUCTION;
desc->jmp.offset = jmp;
@@ -388,17 +421,18 @@ void emit_cmp(struct gluten_ctx *g, enum op_cmp_type cmp_type,
* emit_cmp_field() - Emit OP_CMP for a given field type
* @g: gluten context
* @cmp: Type of comparison
+ * @vec: Description of vector structure, NULL for scalar comparison
* @field: Description of field from system call model
* @x: gluten pointer to first operand of comparison
* @y: gluten pointer to second operand of comparison
* @jmp: Jump direction if comparison is true
*/
void emit_cmp_field(struct gluten_ctx *g, enum op_cmp_type cmp,
- struct field *field,
+ struct vec_desc *vec, struct field *field,
struct gluten_offset x, struct gluten_offset y,
enum jump_type jmp)
{
- emit_cmp(g, cmp, x, y,
+ emit_cmp(g, cmp, vec, x, y,
field->size ? field->size : gluten_size[field->type],
jmp);
}