Re: [PATCH net] gve: fix out-of-bounds read in gve_get_flow_rule_entry()
From: Harshitha Ramamurthy
Date: Wed Oct 21 2026 - 13:55:42 EST
On Tue, Oct 20, 2026 at 3:33 PM Aamir Ahmed <elb12345@xxxxxxxxxxxxx> wrote:
>
> gve_get_flow_rule_entry() checks the requested location against the
> first and last cached rules, but rules_cache_num can be 0 while
> rules_cache_synced is true: GVE_FLOW_RULE_QUERY_RULES returns the rules
> from the requested location onwards, so a request past the last
> installed rule - or any request when no rules are installed - returns
> zero rules, which the driver accepts and marks as synced.
>
> The next query evaluates rules_cache[*cache_num - 1] with
> *cache_num == 0. The zero-initialised cache does not trip the earlier
> comparison, *cache_num - 1 wraps to 0xFFFFFFFF in u32, and the read
> faults about 352 GiB past the cache. ETHTOOL_GRXCLSRULE needs no
> capability, so an unprivileged user can trigger it:
>
> BUG: unable to handle page fault for address: ff240996c4c64fa8
> #PF: supervisor read access in kernel mode
> RIP: gve_get_flow_rule_entry+0xd4/0x110 [gve]
>
> Treat an empty cache as a cache miss and re-query.
>
> Fixes: 6f3bc487565d ("gve: Add flow steering ethtool support")
> Cc: stable@xxxxxxxxxxxxxxx
> Assisted-by: LLM
> Signed-off-by: Aamir Ahmed <elb12345@xxxxxxxxxxxxx>
Thanks for the patch!
Reviewed-by: Harshitha Ramamurthy <hramamurthy@xxxxxxxxxx>
> ---
> Reproducer available on request.
>
> drivers/net/ethernet/google/gve/gve_flow_rule.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/drivers/net/ethernet/google/gve/gve_flow_rule.c b/drivers/net/ethernet/google/gve/gve_flow_rule.c
> index 2c80cda..db8b9a3 100644
> --- a/drivers/net/ethernet/google/gve/gve_flow_rule.c
> +++ b/drivers/net/ethernet/google/gve/gve_flow_rule.c
> @@ -206,6 +206,7 @@ int gve_get_flow_rule_entry(struct gve_priv *priv, struct ethtool_rxnfc *cmd)
> return -EOPNOTSUPP;
>
> if (!priv->flow_rules_cache.rules_cache_synced ||
> + !*cache_num ||
> fsp->location < be32_to_cpu(rules_cache[0].location) ||
> fsp->location > be32_to_cpu(rules_cache[*cache_num - 1].location)) {
> err = gve_adminq_query_flow_rules(priv, GVE_FLOW_RULE_QUERY_RULES, fsp->location);
> --
> 2.55.0
>