From 6696599e104098b61e45f99d161275883885b199 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Thu, 23 Mar 2023 13:23:34 +0100 Subject: netlink_delinerize: incorrect byteorder in mark statement listing When using ip dscp in combination with bitwise operation: # nft --debug=netlink add rule ip x y 'ct mark set ip dscp | 0x4' ip x y [ payload load 1b @ network header + 1 => reg 1 ] [ bitwise reg 1 = ( reg 1 & 0x000000fc ) ^ 0x00000000 ] [ bitwise reg 1 = ( reg 1 >> 0x00000002 ) ] [ bitwise reg 1 = ( reg 1 & 0xfffffffb ) ^ 0x00000004 ] [ ct set mark with reg 1 ] the listing is showing in the incorrect byteorder: # nft list ruleset table ip x { chain y { ct mark set ip dscp | 0x4000000 } } handle and and or operations in host byteorder. The following command: # nft --debug=netlink add rule ip6 x y 'ct mark set ip6 dscp | 0x4' ip6 x y [ payload load 2b @ network header + 0 => reg 1 ] [ bitwise reg 1 = ( reg 1 & 0x0000c00f ) ^ 0x00000000 ] [ bitwise reg 1 = ( reg 1 >> 0x00000006 ) ] [ byteorder reg 1 = ntoh(reg 1, 2, 1) ] [ bitwise reg 1 = ( reg 1 & 0xfffffffb ) ^ 0x00000004 ] [ ct set mark with reg 1 ] works fine (without requiring this patch) because there is an explicit byteorder expression. However, ip dscp takes only 1-byte, so it does not require the byteorder expression. Use host byteorder if the rhs of bitwise AND OR is larger than lhs payload expression and such expression is equal or less than 1-byte. Signed-off-by: Pablo Neira Ayuso --- src/netlink_delinearize.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'src/netlink_delinearize.c') diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c index 2853297d..3d383669 100644 --- a/src/netlink_delinearize.c +++ b/src/netlink_delinearize.c @@ -2786,8 +2786,13 @@ static void expr_postprocess(struct rule_pp_ctx *ctx, struct expr **exprp) BYTEORDER_HOST_ENDIAN); break; case OP_AND: - expr_set_type(expr->right, expr->left->dtype, - expr->left->byteorder); + if (expr->right->len > expr->left->len) { + expr_set_type(expr->right, expr->left->dtype, + BYTEORDER_HOST_ENDIAN); + } else { + expr_set_type(expr->right, expr->left->dtype, + expr->left->byteorder); + } /* Do not process OP_AND in ordinary rule context. * @@ -2807,8 +2812,13 @@ static void expr_postprocess(struct rule_pp_ctx *ctx, struct expr **exprp) } break; default: - expr_set_type(expr->right, expr->left->dtype, - expr->left->byteorder); + if (expr->right->len > expr->left->len) { + expr_set_type(expr->right, expr->left->dtype, + BYTEORDER_HOST_ENDIAN); + } else { + expr_set_type(expr->right, expr->left->dtype, + expr->left->byteorder); + } } expr_postprocess(ctx, &expr->right); -- cgit v1.2.3