Message ID | 20190821121720.22009-1-jakub@cloudflare.com |
---|---|
State | Accepted |
Delegated to: | BPF Maintainers |
Headers | show |
Series | [bpf] flow_dissector: Fix potential use-after-free on BPF_PROG_DETACH | expand |
This makes sense, thanks! Acked-by: Petar Penkov <ppenkov@google.com> On Wed, Aug 21, 2019 at 5:19 AM Jakub Sitnicki <jakub@cloudflare.com> wrote: > > Call to bpf_prog_put(), with help of call_rcu(), queues an RCU-callback to > free the program once a grace period has elapsed. The callback can run > together with new RCU readers that started after the last grace period. > New RCU readers can potentially see the "old" to-be-freed or already-freed > pointer to the program object before the RCU update-side NULLs it. > > Reorder the operations so that the RCU update-side resets the protected > pointer before the end of the grace period after which the program will be > freed. > > Fixes: d58e468b1112 ("flow_dissector: implements flow dissector BPF hook") > Reported-by: Lorenz Bauer <lmb@cloudflare.com> > Signed-off-by: Jakub Sitnicki <jakub@cloudflare.com> > --- > net/core/flow_dissector.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c > index 3e6fedb57bc1..2470b4b404e6 100644 > --- a/net/core/flow_dissector.c > +++ b/net/core/flow_dissector.c > @@ -142,8 +142,8 @@ int skb_flow_dissector_bpf_prog_detach(const union bpf_attr *attr) > mutex_unlock(&flow_dissector_mutex); > return -ENOENT; > } > - bpf_prog_put(attached); > RCU_INIT_POINTER(net->flow_dissector_prog, NULL); > + bpf_prog_put(attached); > mutex_unlock(&flow_dissector_mutex); > return 0; > } > -- > 2.20.1 >
On 8/21/19 2:17 PM, Jakub Sitnicki wrote: > Call to bpf_prog_put(), with help of call_rcu(), queues an RCU-callback to > free the program once a grace period has elapsed. The callback can run > together with new RCU readers that started after the last grace period. > New RCU readers can potentially see the "old" to-be-freed or already-freed > pointer to the program object before the RCU update-side NULLs it. > > Reorder the operations so that the RCU update-side resets the protected > pointer before the end of the grace period after which the program will be > freed. > > Fixes: d58e468b1112 ("flow_dissector: implements flow dissector BPF hook") > Reported-by: Lorenz Bauer <lmb@cloudflare.com> > Signed-off-by: Jakub Sitnicki <jakub@cloudflare.com> Applied, thanks!
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c index 3e6fedb57bc1..2470b4b404e6 100644 --- a/net/core/flow_dissector.c +++ b/net/core/flow_dissector.c @@ -142,8 +142,8 @@ int skb_flow_dissector_bpf_prog_detach(const union bpf_attr *attr) mutex_unlock(&flow_dissector_mutex); return -ENOENT; } - bpf_prog_put(attached); RCU_INIT_POINTER(net->flow_dissector_prog, NULL); + bpf_prog_put(attached); mutex_unlock(&flow_dissector_mutex); return 0; }
Call to bpf_prog_put(), with help of call_rcu(), queues an RCU-callback to free the program once a grace period has elapsed. The callback can run together with new RCU readers that started after the last grace period. New RCU readers can potentially see the "old" to-be-freed or already-freed pointer to the program object before the RCU update-side NULLs it. Reorder the operations so that the RCU update-side resets the protected pointer before the end of the grace period after which the program will be freed. Fixes: d58e468b1112 ("flow_dissector: implements flow dissector BPF hook") Reported-by: Lorenz Bauer <lmb@cloudflare.com> Signed-off-by: Jakub Sitnicki <jakub@cloudflare.com> --- net/core/flow_dissector.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)