diff options
Diffstat (limited to 'operations.c')
-rw-r--r-- | operations.c | 149 |
1 files changed, 119 insertions, 30 deletions
diff --git a/operations.c b/operations.c index eb8d614..4438879 100644 --- a/operations.c +++ b/operations.c @@ -459,6 +459,8 @@ int op_iovload(const struct seccomp_notif *req, int notifier, struct gluten *g, close(fd); + memset(dst + count, 0, load->size - count + load->zero_fill); + return 0; } @@ -592,8 +594,11 @@ int op_bitwise(const struct seccomp_notif *req, int notifier, struct gluten *g, struct op_bitwise *op) { const struct bitwise_desc *desc = gluten_ptr(&req->data, g, op->desc); - const unsigned char *x, *y; - unsigned char *dst; + const struct vec_desc vec = desc->vec; + const unsigned char *x_ptr, *y_ptr; + struct gluten_offset x, dst; + unsigned char *dst_ptr; + uint32_t *vlen; unsigned i; (void)notifier; @@ -601,10 +606,6 @@ int op_bitwise(const struct seccomp_notif *req, int notifier, struct gluten *g, if (!desc) return -1; - dst = gluten_write_ptr( g, desc->dst); - x = gluten_ptr(&req->data, g, desc->x); - y = gluten_ptr(&req->data, g, desc->y); - /* if (!dst || !src || !mask || !check_gluten_limits(desc->dst, desc->size) || @@ -612,6 +613,7 @@ int op_bitwise(const struct seccomp_notif *req, int notifier, struct gluten *g, !check_gluten_limits(desc->mask, desc->size)) return -1; */ + debug(" op_bitwise: dst=(%s %d) := x=(%s %d) %s y=(%s %d) size=%d", gluten_offset_name[desc->dst.type], desc->dst.offset, gluten_offset_name[desc->x.type], desc->x.offset, @@ -619,13 +621,37 @@ int op_bitwise(const struct seccomp_notif *req, int notifier, struct gluten *g, gluten_offset_name[desc->y.type], desc->y.offset, desc->size); - for (i = 0; i < desc->size; i++) { - if (desc->type == BITWISE_AND) - dst[i] = x[i] & y[i]; - else if (desc->type == BITWISE_OR) - dst[i] = x[i] | y[i]; - else - return -1; + if (vec.start.type != OFFSET_NULL) { + debug(" vector start=(%s %d), length offset: %i", + gluten_offset_name[vec.start.type], vec.start.offset, + vec.len_offset); + } + + if (vec.start.type == OFFSET_NULL) + vlen = &((uint32_t){ 1 }); + else + vlen = (uint32_t *)gluten_ptr(&req->data, g, vec.start); + + y_ptr = gluten_ptr(&req->data, g, desc->y); + + for (x = desc->x, dst = desc->dst; + *vlen; + x.offset += *vlen, vlen += *vlen, dst.offset += desc->size) { + + x_ptr = gluten_ptr(&req->data, g, x); + dst_ptr = gluten_write_ptr( g, dst); + + for (i = 0; i < desc->size; i++) { + if (desc->type == BITWISE_AND) + dst_ptr[i] = x_ptr[i] & y_ptr[i]; + else if (desc->type == BITWISE_OR) + dst_ptr[i] = x_ptr[i] | y_ptr[i]; + else + return -1; + } + + if (vec.start.type == OFFSET_NULL) + break; } return 0; @@ -683,9 +709,13 @@ int op_cmp(const struct seccomp_notif *req, int notifier, struct gluten *g, struct op_cmp *op) { const struct cmp_desc *desc = gluten_ptr(&req->data, g, op->desc); + bool some = false, all = true, verdict; + const struct vec_desc vec = desc->vec; char str_x[PATH_MAX], str_y[PATH_MAX]; + const void *x_ptr, *y_ptr; + struct gluten_offset x; enum op_cmp_type cmp; - const void *px, *py; + uint32_t *vlen; int res; (void)notifier; @@ -693,29 +723,88 @@ int op_cmp(const struct seccomp_notif *req, int notifier, struct gluten *g, if (!desc) return -1; - px = gluten_ptr(&req->data, g, desc->x); - py = gluten_ptr(&req->data, g, desc->y); - cmp = desc->cmp; - - if (!px || !py || - !check_gluten_limits(desc->x, desc->size) || - !check_gluten_limits(desc->y, desc->size)) - return -1; str_offset_value(req, g, &desc->x, desc->size, str_x, PATH_MAX); str_offset_value(req, g, &desc->y, desc->size, str_y, PATH_MAX); debug(" op_cmp: operands x=%s y=%s", str_x, str_y); - res = memcmp(px, py, desc->size); + if (vec.start.type != OFFSET_NULL) { + debug(" vector start=(%s %d), length offset: %i", + gluten_offset_name[vec.start.type], vec.start.offset, + vec.len_offset); + } + + if (vec.start.type == OFFSET_NULL) + vlen = &((uint32_t){ 1 }); + else + vlen = (uint32_t *)gluten_ptr(&req->data, g, vec.start); + + y_ptr = gluten_ptr(&req->data, g, desc->y); - if ((res == 0 && (cmp == CMP_EQ || cmp == CMP_LE || cmp == CMP_GE)) || - (res < 0 && (cmp == CMP_LT || cmp == CMP_LE)) || - (res > 0 && (cmp == CMP_GT || cmp == CMP_GE)) || - (res != 0 && (cmp == CMP_NE))) { - debug(" op_cmp: successful comparison, jump to %d", - desc->jmp.offset); + if (!y_ptr || !check_gluten_limits(desc->y, desc->size)) + return -1; + + cmp = desc->cmp; + + for (x = desc->x; + *vlen; + x.offset += *vlen, vlen = (uint32_t *)((uint8_t *)vlen + *vlen)) { + unsigned char *c; + int __i; + + debug(" in loop, vlen: %u", *vlen); + + x_ptr = gluten_ptr(&req->data, g, x); + + if (!x_ptr || !check_gluten_limits(x, desc->size)) + return -1; + + debug(" in loop #2"); + + res = memcmp(x_ptr, y_ptr, desc->size); + + debug("=== x: %04x, y: %04x", *(uint16_t *)x_ptr, *(uint16_t *)y_ptr); + + c = (unsigned char *)x_ptr; + for (__i = 0; __i < 32; __i += 4) + debug("%02x %02x %02x %02x", c[__i], c[__i + 1], c[__i + 2], c[__i + 3]); + + if ((res == 0 && + (cmp == CMP_EQ || cmp == CMP_LE || cmp == CMP_GE)) || + (res < 0 && + (cmp == CMP_LT || cmp == CMP_LE)) || + (res > 0 && + (cmp == CMP_GT || cmp == CMP_GE)) || + (res != 0 && + (cmp == CMP_NE))) + some = true; + else + all = false; + + if (vec.start.type == OFFSET_NULL) + break; + + debug(" in loop #3"); + } + + /* FIXME: vectors always imply the existential quantifier for now: + * CMP_NE and all non-equal: jump + * CMP_EQ and some equal: jump + */ + if (vec.start.type == OFFSET_NULL) + verdict = some; + else if (cmp == CMP_NE) + verdict = all; + else + verdict = some; + + debug(" op_cmp: comparison: %s for some, %s for all, verdict: %s", + some ? "true" : "false", all ? "true" : "false", + verdict ? "true" : "false"); + + if (verdict) { + debug(" -> jump to %d", desc->jmp.offset); return desc->jmp.offset; } - debug(" op_cmp: comparison is false"); return 0; } |