On Tue, Apr 02, 2019 at 04:30:38PM +0300, Dan Carpenter wrote:
> I believe that "hook->num" can be up to UINT_MAX so the shift has to
> be unsigned or shifting more than 31 is undefined.  It's possible that
> this leads to array overflow in nf_tables_addchain():
> 
>       ops->hook       = hook.type->hooks[ops->hooknum];
> 
> Fixes: fe19c04ca137 ("netfilter: nf_tables: remove nhooks field from struct 
> nft_af_info")
> Signed-off-by: Dan Carpenter <[email protected]>
> ---
>  net/netfilter/nf_tables_api.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
> index ef7772e976cc..b6e48fe7c776 100644
> --- a/net/netfilter/nf_tables_api.c
> +++ b/net/netfilter/nf_tables_api.c
> @@ -1545,7 +1545,7 @@ static int nft_chain_parse_hook(struct net *net,
>               if (IS_ERR(type))
>                       return PTR_ERR(type);
>       }
> -     if (!(type->hook_mask & (1 << hook->num)))
> +     if (!(type->hook_mask & (1U << hook->num)))

Ugh...  No this doesn't work.  It's still undefined behavoir even if we
make it unsigned.  It has to be:

        if (hook->num > 31 || !(type->hook_mask & (1 << hook->num)))

which seems like a slightly ugly magic number but it fixes the buffer
overflow.

regards,
dan carpenter

Reply via email to