Fix USB/IP import lease and attach races

This commit is contained in:
世界
2026-04-25 05:08:36 +08:00
parent ff9336435e
commit d690a17780
8 changed files with 405 additions and 35 deletions
+29 -18
View File
@@ -4,6 +4,7 @@ package usbip
import (
"context"
"errors"
"fmt"
"sync"
"time"
@@ -17,6 +18,8 @@ import (
E "github.com/sagernet/sing/common/exceptions"
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
"golang.org/x/sys/unix"
)
type ClientService struct {
@@ -215,25 +218,33 @@ func (c *ClientService) attemptAttach(ctx context.Context, busid string) (int, <
c.logger.Debug("usbip client handoff ", busid, ": ", handoff.mode())
c.portAssignAccess.Lock()
defer c.portAssignAccess.Unlock()
port, err := c.ops.vhciPickFreePort(info.Speed)
if err != nil {
return -1, nil, err
triedPorts := make(map[int]struct{})
for {
port, err := c.ops.vhciPickFreePort(info.Speed, triedPorts)
if err != nil {
return -1, nil, err
}
if !c.reservePort(port) {
triedPorts[port] = struct{}{}
continue
}
err = c.ops.vhciAttach(port, handoff.kernelFD(), info.DevID(), info.Speed)
if err != nil {
c.trackPort(port, false)
if errors.Is(err, unix.EBUSY) {
triedPorts[port] = struct{}{}
continue
}
return -1, nil, E.Cause(err, "vhci attach")
}
err = handoff.closeKernelFD()
if err != nil {
c.logger.Debug("close kernel fd ", busid, ": ", err)
}
done := handoff.startRelay(ctx, c.logger, "client", busid)
relayStarted = true
return port, done, nil
}
if !c.reservePort(port) {
return -1, nil, E.New("vhci port ", port, " already reserved")
}
err = c.ops.vhciAttach(port, handoff.kernelFD(), info.DevID(), info.Speed)
if err != nil {
c.trackPort(port, false)
return -1, nil, E.Cause(err, "vhci attach")
}
err = handoff.closeKernelFD()
if err != nil {
c.logger.Debug("close kernel fd ", busid, ": ", err)
}
done := handoff.startRelay(ctx, c.logger, "client", busid)
relayStarted = true
return port, done, nil
}
func (c *ClientService) waitPortSession(ctx context.Context, port int, busid string, done <-chan struct{}) {