Re: [PATCH nftables 1/4] src: fix jumps on bigendian arches

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, Aug 13, 2019 at 08:44:06PM +0200, Florian Westphal wrote:
> table bla {
>   chain foo { }
>   chain bar { jump foo }
>  }
> }
> 
> Fails to restore on big-endian platforms:
> jump.nft:5:2-9: Error: Could not process rule: No such file or directory
>  jump foo
> 
> nft passes a 0-length name to the kernel.
> 
> This is because when we export the value (the string), we provide
> the size of the destination buffer.
> 
> In earlier versions, the parser allocated the name with the same
> fixed size and all was fine.
> 
> After the fix, the export places the name in the wrong location
> in the destination buffer.
> 
> This makes tests/shell/testcases/chains/0001jumps_0 work on s390x.
> 
> Fixes: 142350f154c78 ("src: invalid read when importing chain name")
> Signed-off-by: Florian Westphal <fw@xxxxxxxxx>
> ---
>  src/datatype.c | 26 +++++++++++++++++---------
>  src/netlink.c  | 16 +++++++++++++---
>  2 files changed, 30 insertions(+), 12 deletions(-)
> 
> diff --git a/src/datatype.c b/src/datatype.c
> index 28f726f4e84c..6908bc22d783 100644
> --- a/src/datatype.c
> +++ b/src/datatype.c
> @@ -244,10 +244,24 @@ const struct datatype invalid_type = {
>  	.print		= invalid_type_print,
>  };
>  
> -static void verdict_type_print(const struct expr *expr, struct output_ctx *octx)
> +static void verdict_jump_chain_print(const char *what, const struct expr *e,
> +				     struct output_ctx *octx)
>  {
>  	char chain[NFT_CHAIN_MAXNAMELEN];

Probably:

        chat chain[NFT_CHAIN_MAXNAMELEN + 1] = {};

to ensure space for \0.

> +	unsigned int len;
> +
> +	memset(chain, 0, sizeof(chain));

remove this memset then.

> +	len = e->len / BITS_PER_BYTE;

        div_round_up() ?

> +	if (len >= sizeof(chain))
> +		len = sizeof(chain) - 1;

Probably BUG() here instead if e->len > NFT_CHAIN_MAXNAMELEN? This
should not happen.

> +
> +	mpz_export_data(chain, e->value, BYTEORDER_HOST_ENDIAN, len);
> +	nft_print(octx, "%s %s", what, chain);
> +}
> +
> +static void verdict_type_print(const struct expr *expr, struct output_ctx *octx)
> +{
>  	switch (expr->verdict) {
>  	case NFT_CONTINUE:
>  		nft_print(octx, "continue");
> @@ -257,10 +271,7 @@ static void verdict_type_print(const struct expr *expr, struct output_ctx *octx)
>  		break;
>  	case NFT_JUMP:
>  		if (expr->chain->etype == EXPR_VALUE) {
> -			mpz_export_data(chain, expr->chain->value,
> -					BYTEORDER_HOST_ENDIAN,
> -					NFT_CHAIN_MAXNAMELEN);
> -			nft_print(octx, "jump %s", chain);
> +			verdict_jump_chain_print("jump", expr->chain, octx);
>  		} else {
>  			nft_print(octx, "jump ");
>  			expr_print(expr->chain, octx);
> @@ -268,10 +279,7 @@ static void verdict_type_print(const struct expr *expr, struct output_ctx *octx)
>  		break;
>  	case NFT_GOTO:
>  		if (expr->chain->etype == EXPR_VALUE) {
> -			mpz_export_data(chain, expr->chain->value,
> -					BYTEORDER_HOST_ENDIAN,
> -					NFT_CHAIN_MAXNAMELEN);
> -			nft_print(octx, "goto %s", chain);
> +			verdict_jump_chain_print("goto", expr->chain, octx);
>  		} else {
>  			nft_print(octx, "goto ");
>  			expr_print(expr->chain, octx);
> diff --git a/src/netlink.c b/src/netlink.c
> index aeeb12eaca93..f8e1120447d9 100644
> --- a/src/netlink.c
> +++ b/src/netlink.c
> @@ -222,17 +222,27 @@ static void netlink_gen_verdict(const struct expr *expr,
>  				struct nft_data_linearize *data)
>  {
>  	char chain[NFT_CHAIN_MAXNAMELEN];

        ...[NFT_CHAIN_MAXNAMELEN + 1] = {};

> +	unsigned int len;
>  
>  	data->verdict = expr->verdict;
>  
>  	switch (expr->verdict) {
>  	case NFT_JUMP:
>  	case NFT_GOTO:
> +		len = expr->chain->len / BITS_PER_BYTE;

                div_round_up()

> +
> +		if (!len)
> +			BUG("chain length is 0");
> +
> +		if (len > sizeof(chain))
> +			BUG("chain is too large (%u, %u max)",
> +			    len, (unsigned int)sizeof(chain));
> +
> +		memset(chain, 0, sizeof(chain));
> +
>  		mpz_export_data(chain, expr->chain->value,
> -				BYTEORDER_HOST_ENDIAN,
> -				NFT_CHAIN_MAXNAMELEN);
> +				BYTEORDER_HOST_ENDIAN, len);
>  		snprintf(data->chain, NFT_CHAIN_MAXNAMELEN, "%s", chain);
> -		data->chain[NFT_CHAIN_MAXNAMELEN-1] = '\0';
>  		break;
>  	}
>  }
> -- 
> 2.21.0
> 



[Index of Archives]     [Netfitler Users]     [Berkeley Packet Filter]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux