From: Lee Jones > Sent: 17 December 2021 14:35 > > On Fri, 17 Dec 2021, David Laight wrote: > > > From: Lee Jones > > > Sent: 17 December 2021 13:46 > > > > > > net/sctp/diag.c for instance is built into its own separate module > > > (sctp_diag.ko) and requires the use of sctp_endpoint_{hold,put}() in > > > order to prevent a recently found use-after-free issue. > > > > > > In order to prevent data corruption of the pointer used to take a > > > reference on a specific endpoint, between the time of calling > > > sctp_endpoint_hold() and it returning, the API now returns a pointer > > > to the exact endpoint that was incremented. > > > > > > For example, in sctp_sock_dump(), we could have the following hunk: > > > > > > sctp_endpoint_hold(tsp->asoc->ep); > > > ep = tsp->asoc->ep; > > > sk = ep->base.sk > > > lock_sock(ep->base.sk); > > > > > > It is possible for this task to be swapped out immediately following > > > the call into sctp_endpoint_hold() that would change the address of > > > tsp->asoc->ep to point to a completely different endpoint. This means > > > a reference could be taken to the old endpoint and the new one would > > > be processed without a reference taken, moreover the new endpoint > > > could then be freed whilst still processing as a result, causing a > > > use-after-free. > > > > > > If we return the exact pointer that was held, we ensure this task > > > processes only the endpoint we have taken a reference to. The > > > resultant hunk now looks like this: > > > > > > ep = sctp_endpoint_hold(tsp->asoc->ep); > > > sk = ep->base.sk > > > lock_sock(sk); > > > > Isn't that just the same as doing things in the other order? > > ep = tsp->asoc->ep; > > sctp_endpoint_hold(ep); > > Sleep for a few milliseconds between those lines and see what happens. > > 'ep' could still be freed between the assignment and the call. It can also be freed half way through setting up the arguments to the call. So any call: xxx(tsp->asoc->ep); is only really valid if both tsp->asoc and asoc->ep are stable. So it is exactly the same as doing: ep = tsp->asoc->ep; xxx(ep); Returning the value of the argument doesn't help if any of the pointed-to items can get freed. David - Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK Registration No: 1397386 (Wales)