commit
6696599e104098b61e45f99d161275883885b199 upstream.
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 <pablo@netfilter.org>
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.
*
}
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);