From b2591d4b13ab95240216a93d682b842c28b2b884 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Fri, 3 Dec 2021 20:19:10 +0100 Subject: netlink_delinearize: zero shift removal Remove shifts-by-0. These can occur after binop postprocessing has adjusted the RHS value to account for a mask operation. Example: frag frag-off @s4 Is internally represented via: [ exthdr load ipv6 2b @ 44 + 2 => reg 1 ] [ bitwise reg 1 = ( reg 1 & 0x0000f8ff ) ^ 0x00000000 ] [ bitwise reg 1 = ( reg 1 >> 0x00000003 ) ] [ lookup reg 1 set s ] First binop masks out unwanted parts of the 16-bit field. Second binop needs to left-shift so that lookups in the set will work. When decoding, the first binop is removed after the exthdr load has been adjusted accordingly. Constant propagation adjusts the shift-value to 0 on removal. This change then gets rid of the shift-by-0 entirely. After this change, 'frag frag-off @s4' input is shown as-is. Signed-off-by: Florian Westphal --- src/netlink_delinearize.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'src/netlink_delinearize.c') diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c index e37a34f3..323e9150 100644 --- a/src/netlink_delinearize.c +++ b/src/netlink_delinearize.c @@ -2322,6 +2322,20 @@ static void map_binop_postprocess(struct rule_pp_ctx *ctx, struct expr *expr) binop_postprocess(ctx, expr, &expr->map); } +static bool is_shift_by_zero(const struct expr *binop) +{ + struct expr *rhs; + + if (binop->op != OP_RSHIFT && binop->op != OP_LSHIFT) + return false; + + rhs = binop->right; + if (rhs->etype != EXPR_VALUE || rhs->len > 64) + return false; + + return mpz_get_uint64(rhs->value) == 0; +} + static void relational_binop_postprocess(struct rule_pp_ctx *ctx, struct expr **exprp) { @@ -2421,6 +2435,13 @@ static void relational_binop_postprocess(struct rule_pp_ctx *ctx, */ binop_postprocess(ctx, binop, &binop->left); + if (is_shift_by_zero(binop)) { + struct expr *lhs = binop->left; + + expr_get(lhs); + expr_free(binop); + expr->left = lhs; + } } } -- cgit v1.2.3