Page MenuHomeFreeBSD

if_ovpn: free crp, mbuf, and release refcount on crypto_dispatch() failure
ClosedPublic

Authored by ing.castellanosdz_gmail.com on Mon, Aug 10, 7:55 AM.
Tags
None
Referenced Files
F167217957: D58754.id183779.diff
Thu, Aug 20, 12:57 AM
F167187193: D58754.id183779.diff
Wed, Aug 19, 6:04 PM
F167187140: D58754.id183778.diff
Wed, Aug 19, 6:03 PM
Unknown Object (File)
Wed, Aug 19, 2:04 AM
Unknown Object (File)
Mon, Aug 17, 1:54 AM
Unknown Object (File)
Sun, Aug 16, 7:52 PM
Unknown Object (File)
Sun, Aug 16, 10:00 AM
Unknown Object (File)
Fri, Aug 14, 9:06 PM

Details

Summary

When crypto_dispatch() or crypto_dispatch_async() returns non-zero,
the registered callback is never invoked. In both ovpn_transmit_to_peer()
and ovpn_udp_input(), if_ovpn.c did not free the cryptop request, release
the peer/sc reference count, or free the mbuf on dispatch failure.

This results in three simultaneous leaks per failed dispatch:

  • crp allocated via crypto_getreq() is never freed
  • peer->refcount (encrypt) or sc->refcount (decrypt) incremented but never decremented
  • mbuf passed to crypto_use_mbuf() is never freed

The leaks are reachable under memory pressure when the OCF scheduler
returns ENOMEM from crypto_dispatch(). The registered callbacks
(ovpn_encrypt_tx_cb, ovpn_decrypt_rx_cb) correctly handle crp_etype
for crypto operation failures; this fix addresses the separate
dispatch-level failure path where no callback is invoked.

Found during code review following FreeBSD-SA-26:52.if_wg.

PR:

Test Plan

Code inspection. Verified that crypto_dispatch() failure path does not
invoke the registered callback, confirming crp, mbuf, and refcount are
orphaned. No functional change in the success path.

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Not Applicable
Unit
Tests Not Applicable

Event Timeline

.arcconfig
1 ↗(On Diff #183773)

You probably didn't mean for this to be part of the commit.

sys/net/if_ovpn.c
2196

That seems pointless, given that it's the next line after this 'if' block.

sys/net/if_ovpn.c
2647

I think this is wrong.

The ovpn_udp_input() return value tells the udp stack whether we've grabbed the packet or not. If we return 'false' it's going to try to process the mbuf, which we've just freed.

We should still return true here, indicating that we own the mbuf now.

Address reviewer feedback from kp

  • Remove .arcconfig change (not part of this fix)
  • Remove redundant return (ret) in encrypt path
  • Change return (false) to return (true) in decrypt path: ovpn_udp_input() return value signals mbuf ownership to UDP stack; must return true even on dispatch failure since we free the mbuf

Thank you for the review, kp.

Updated in Diff 183778:

  • .arcconfig: reverted to repository original, excluded from this change
  • ovpn_transmit_to_peer(): removed redundant return (ret) inside the error block
  • ovpn_udp_input(): changed return (false) to return (true); understood that the return value signals mbuf ownership to the UDP stack, and returning false would cause a use-after-free on the mbuf we just freed
This revision was not accepted when it landed; it landed in state Needs Review.Mon, Aug 10, 1:23 PM
This revision was automatically updated to reflect the committed changes.