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