https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=289017

            Bug ID: 289017
           Summary: [lagg] A time-of-check to time-of-use (TOCTOU) race
                    exists in the Link Aggregation (LAGG) network
                    subsystem
           Product: Base System
           Version: 14.3-RELEASE
          Hardware: Any
                OS: Any
            Status: New
          Severity: Affects Only Me
          Priority: ---
         Component: kern
          Assignee: [email protected]
          Reporter: [email protected]

A time-of-check to time-of-use (TOCTOU) race exists in the net
subsystem at several call sites of lagg_proto_start(),
lagg_proto_input(), and lagg_proto_portreq().

In the SIOCSLAGG branch of lagg_ioctl(), updating sc is performed
by calling lagg_proto_detach() followed by lagg_proto_attach(). In
the middle of this sequence, sc->sc_proto is set to
LAGG_PROTO_NONE. This change is not mutually exclusive with
NET_EPOCH read-side critical sections, so sc->sc_proto may still
change while a reader is executing under NET_EPOCH.

For example, in lagg_transmit_ethernet(), the code checks:
if (sc->sc_proto == LAGG_PROTO_NONE || sc->sc_count == 0)

Because this check is protected only by NET_EPOCH, after it passes,
sc->sc_proto may still be changed to LAGG_PROTO_NONE. As a result,
lagg_proto_start(sc, m) will index
lagg_protos[sc->sc_proto].pr_start(sc, m) with
LAGG_PROTO_NONE. Since the LAGG_PROTO_NONE entry in lagg_protos
does not provide any function pointers, this leads to a NULL function
pointer dereference. The same issue exists at the call site in
lagg_transmit_infiniband().

Similarly, the call sites of lagg_proto_input() in
lagg_input_ethernet() and lagg_input_infiniband(), and the call
sites of lagg_proto_portreq() via lagg_port2req() in
lagg_port_ioctl() and lagg_ioctl(), are subject to the same race.

We also examined call sites of the related helpers
lagg_proto_addport(), lagg_proto_delport(), lagg_proto_linkstate(),
lagg_proto_init(), lagg_proto_stop(), lagg_proto_lladdr(), and
lagg_proto_request(). Their invocations are protected by the
appropriate locks, and we did not find a TOCTOU issue there.

Suggested fix: Before invoking the above helpers, snapshot
sc->sc_proto into a local variable, validate it, and use that single
value for both the check and the subsequent function-pointer call.

-- 
You are receiving this mail because:
You are the assignee for the bug.

Reply via email to