From 0045103d1423f24cbdecc871d3feca94b6bfb7ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=96=E7=95=8C?= Date: Mon, 23 Mar 2026 18:33:03 +0800 Subject: [PATCH] Fix `package_name` shared uid matching --- adapter/platform.go | 10 ++++---- common/process/searcher_android.go | 23 +++++++++--------- daemon/started_service.go | 10 ++++---- daemon/started_service.pb.go | 14 +++++------ daemon/started_service.proto | 2 +- .../clashapi/trafficontrol/tracker.go | 4 ++-- experimental/libbox/command_types.go | 24 +++++++++++-------- experimental/libbox/platform.go | 16 +++++++++---- experimental/libbox/service.go | 8 +++---- go.mod | 2 +- go.sum | 4 ++-- route/route.go | 4 ++-- route/rule/rule_item_package_name.go | 9 +++++-- 13 files changed, 74 insertions(+), 56 deletions(-) diff --git a/adapter/platform.go b/adapter/platform.go index 95db93c64..fa4cbc2e4 100644 --- a/adapter/platform.go +++ b/adapter/platform.go @@ -47,11 +47,11 @@ type FindConnectionOwnerRequest struct { } type ConnectionOwner struct { - ProcessID uint32 - UserId int32 - UserName string - ProcessPath string - AndroidPackageName string + ProcessID uint32 + UserId int32 + UserName string + ProcessPath string + AndroidPackageNames []string } type Notification struct { diff --git a/common/process/searcher_android.go b/common/process/searcher_android.go index 48d853cf1..287c72190 100644 --- a/common/process/searcher_android.go +++ b/common/process/searcher_android.go @@ -6,6 +6,7 @@ import ( "github.com/sagernet/sing-box/adapter" "github.com/sagernet/sing-tun" + "github.com/sagernet/sing/common" ) var _ Searcher = (*androidSearcher)(nil) @@ -31,17 +32,17 @@ func (s *androidSearcher) FindProcessInfo(ctx context.Context, network string, s if err != nil { return nil, err } - if sharedPackage, loaded := s.packageManager.SharedPackageByID(uid % 100000); loaded { - return &adapter.ConnectionOwner{ - UserId: int32(uid), - AndroidPackageName: sharedPackage, - }, nil + appID := uid % 100000 + var packageNames []string + if sharedPackage, loaded := s.packageManager.SharedPackageByID(appID); loaded { + packageNames = append(packageNames, sharedPackage) } - if packageName, loaded := s.packageManager.PackageByID(uid % 100000); loaded { - return &adapter.ConnectionOwner{ - UserId: int32(uid), - AndroidPackageName: packageName, - }, nil + if packages, loaded := s.packageManager.PackagesByID(appID); loaded { + packageNames = append(packageNames, packages...) } - return &adapter.ConnectionOwner{UserId: int32(uid)}, nil + packageNames = common.Uniq(packageNames) + return &adapter.ConnectionOwner{ + UserId: int32(uid), + AndroidPackageNames: packageNames, + }, nil } diff --git a/daemon/started_service.go b/daemon/started_service.go index e6e07511e..c260e8cb7 100644 --- a/daemon/started_service.go +++ b/daemon/started_service.go @@ -950,11 +950,11 @@ func buildConnectionProto(metadata *trafficontrol.TrackerMetadata) *Connection { var processInfo *ProcessInfo if metadata.Metadata.ProcessInfo != nil { processInfo = &ProcessInfo{ - ProcessId: metadata.Metadata.ProcessInfo.ProcessID, - UserId: metadata.Metadata.ProcessInfo.UserId, - UserName: metadata.Metadata.ProcessInfo.UserName, - ProcessPath: metadata.Metadata.ProcessInfo.ProcessPath, - PackageName: metadata.Metadata.ProcessInfo.AndroidPackageName, + ProcessId: metadata.Metadata.ProcessInfo.ProcessID, + UserId: metadata.Metadata.ProcessInfo.UserId, + UserName: metadata.Metadata.ProcessInfo.UserName, + ProcessPath: metadata.Metadata.ProcessInfo.ProcessPath, + PackageNames: metadata.Metadata.ProcessInfo.AndroidPackageNames, } } return &Connection{ diff --git a/daemon/started_service.pb.go b/daemon/started_service.pb.go index ef9ea8250..927fb5149 100644 --- a/daemon/started_service.pb.go +++ b/daemon/started_service.pb.go @@ -1460,7 +1460,7 @@ type ProcessInfo struct { UserId int32 `protobuf:"varint,2,opt,name=userId,proto3" json:"userId,omitempty"` UserName string `protobuf:"bytes,3,opt,name=userName,proto3" json:"userName,omitempty"` ProcessPath string `protobuf:"bytes,4,opt,name=processPath,proto3" json:"processPath,omitempty"` - PackageName string `protobuf:"bytes,5,opt,name=packageName,proto3" json:"packageName,omitempty"` + PackageNames []string `protobuf:"bytes,5,rep,name=packageNames,proto3" json:"packageNames,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -1523,11 +1523,11 @@ func (x *ProcessInfo) GetProcessPath() string { return "" } -func (x *ProcessInfo) GetPackageName() string { +func (x *ProcessInfo) GetPackageNames() []string { if x != nil { - return x.PackageName + return x.PackageNames } - return "" + return nil } type CloseConnectionRequest struct { @@ -1884,13 +1884,13 @@ const file_daemon_started_service_proto_rawDesc = "" + "\boutbound\x18\x13 \x01(\tR\boutbound\x12\"\n" + "\foutboundType\x18\x14 \x01(\tR\foutboundType\x12\x1c\n" + "\tchainList\x18\x15 \x03(\tR\tchainList\x125\n" + - "\vprocessInfo\x18\x16 \x01(\v2\x13.daemon.ProcessInfoR\vprocessInfo\"\xa3\x01\n" + + "\vprocessInfo\x18\x16 \x01(\v2\x13.daemon.ProcessInfoR\vprocessInfo\"\xa5\x01\n" + "\vProcessInfo\x12\x1c\n" + "\tprocessId\x18\x01 \x01(\rR\tprocessId\x12\x16\n" + "\x06userId\x18\x02 \x01(\x05R\x06userId\x12\x1a\n" + "\buserName\x18\x03 \x01(\tR\buserName\x12 \n" + - "\vprocessPath\x18\x04 \x01(\tR\vprocessPath\x12 \n" + - "\vpackageName\x18\x05 \x01(\tR\vpackageName\"(\n" + + "\vprocessPath\x18\x04 \x01(\tR\vprocessPath\x12\"\n" + + "\fpackageNames\x18\x05 \x03(\tR\fpackageNames\"(\n" + "\x16CloseConnectionRequest\x12\x0e\n" + "\x02id\x18\x01 \x01(\tR\x02id\"K\n" + "\x12DeprecatedWarnings\x125\n" + diff --git a/daemon/started_service.proto b/daemon/started_service.proto index cc778f915..8a76081ab 100644 --- a/daemon/started_service.proto +++ b/daemon/started_service.proto @@ -195,7 +195,7 @@ message ProcessInfo { int32 userId = 2; string userName = 3; string processPath = 4; - string packageName = 5; + repeated string packageNames = 5; } message CloseConnectionRequest { diff --git a/experimental/clashapi/trafficontrol/tracker.go b/experimental/clashapi/trafficontrol/tracker.go index 23500cd04..f001b77b2 100644 --- a/experimental/clashapi/trafficontrol/tracker.go +++ b/experimental/clashapi/trafficontrol/tracker.go @@ -45,8 +45,8 @@ func (t TrackerMetadata) MarshalJSON() ([]byte, error) { if t.Metadata.ProcessInfo != nil { if t.Metadata.ProcessInfo.ProcessPath != "" { processPath = t.Metadata.ProcessInfo.ProcessPath - } else if t.Metadata.ProcessInfo.AndroidPackageName != "" { - processPath = t.Metadata.ProcessInfo.AndroidPackageName + } else if len(t.Metadata.ProcessInfo.AndroidPackageNames) > 0 { + processPath = t.Metadata.ProcessInfo.AndroidPackageNames[0] } if processPath == "" { if t.Metadata.ProcessInfo.UserId != -1 { diff --git a/experimental/libbox/command_types.go b/experimental/libbox/command_types.go index 39027ac7b..c330dd4be 100644 --- a/experimental/libbox/command_types.go +++ b/experimental/libbox/command_types.go @@ -239,11 +239,15 @@ func (c *Connections) Iterator() ConnectionIterator { } type ProcessInfo struct { - ProcessID int64 - UserID int32 - UserName string - ProcessPath string - PackageName string + ProcessID int64 + UserID int32 + UserName string + ProcessPath string + packageNames []string +} + +func (p *ProcessInfo) PackageNames() StringIterator { + return newIterator(p.packageNames) } type Connection struct { @@ -339,11 +343,11 @@ func connectionFromGRPC(conn *daemon.Connection) Connection { var processInfo *ProcessInfo if conn.ProcessInfo != nil { processInfo = &ProcessInfo{ - ProcessID: int64(conn.ProcessInfo.ProcessId), - UserID: conn.ProcessInfo.UserId, - UserName: conn.ProcessInfo.UserName, - ProcessPath: conn.ProcessInfo.ProcessPath, - PackageName: conn.ProcessInfo.PackageName, + ProcessID: int64(conn.ProcessInfo.ProcessId), + UserID: conn.ProcessInfo.UserId, + UserName: conn.ProcessInfo.UserName, + ProcessPath: conn.ProcessInfo.ProcessPath, + packageNames: conn.ProcessInfo.PackageNames, } } return Connection{ diff --git a/experimental/libbox/platform.go b/experimental/libbox/platform.go index 63c54ccf2..4db32a222 100644 --- a/experimental/libbox/platform.go +++ b/experimental/libbox/platform.go @@ -24,10 +24,18 @@ type PlatformInterface interface { } type ConnectionOwner struct { - UserId int32 - UserName string - ProcessPath string - AndroidPackageName string + UserId int32 + UserName string + ProcessPath string + androidPackageNames []string +} + +func (c *ConnectionOwner) SetAndroidPackageNames(names StringIterator) { + c.androidPackageNames = iteratorToArray[string](names) +} + +func (c *ConnectionOwner) AndroidPackageNames() StringIterator { + return newIterator(c.androidPackageNames) } type InterfaceUpdateListener interface { diff --git a/experimental/libbox/service.go b/experimental/libbox/service.go index 3a13f6d16..0a841a1b2 100644 --- a/experimental/libbox/service.go +++ b/experimental/libbox/service.go @@ -201,10 +201,10 @@ func (w *platformInterfaceWrapper) FindConnectionOwner(request *adapter.FindConn return nil, err } return &adapter.ConnectionOwner{ - UserId: result.UserId, - UserName: result.UserName, - ProcessPath: result.ProcessPath, - AndroidPackageName: result.AndroidPackageName, + UserId: result.UserId, + UserName: result.UserName, + ProcessPath: result.ProcessPath, + AndroidPackageNames: result.androidPackageNames, }, nil } diff --git a/go.mod b/go.mod index 2155b956d..4072171ad 100644 --- a/go.mod +++ b/go.mod @@ -39,7 +39,7 @@ require ( github.com/sagernet/sing-shadowsocks v0.2.8 github.com/sagernet/sing-shadowsocks2 v0.2.1 github.com/sagernet/sing-shadowtls v0.2.1-0.20250503051639-fcd445d33c11 - github.com/sagernet/sing-tun v0.8.4 + github.com/sagernet/sing-tun v0.8.5 github.com/sagernet/sing-vmess v0.2.8-0.20250909125414-3aed155119a1 github.com/sagernet/smux v1.5.50-sing-box-mod.1 github.com/sagernet/tailscale v1.92.4-sing-box-1.13-mod.7 diff --git a/go.sum b/go.sum index 502e5964c..9c4f22788 100644 --- a/go.sum +++ b/go.sum @@ -248,8 +248,8 @@ github.com/sagernet/sing-shadowsocks2 v0.2.1 h1:dWV9OXCeFPuYGHb6IRqlSptVnSzOelnq github.com/sagernet/sing-shadowsocks2 v0.2.1/go.mod h1:RnXS0lExcDAovvDeniJ4IKa2IuChrdipolPYWBv9hWQ= github.com/sagernet/sing-shadowtls v0.2.1-0.20250503051639-fcd445d33c11 h1:tK+75l64tm9WvEFrYRE1t0YxoFdWQqw/h7Uhzj0vJ+w= github.com/sagernet/sing-shadowtls v0.2.1-0.20250503051639-fcd445d33c11/go.mod h1:sWqKnGlMipCHaGsw1sTTlimyUpgzP4WP3pjhCsYt9oA= -github.com/sagernet/sing-tun v0.8.4 h1:pZ/ZoBQTeVks75iS1w7Qe8brBEsPVT0ENiVvtbsFBGo= -github.com/sagernet/sing-tun v0.8.4/go.mod h1:pLCo4o+LacXEzz0bhwhJkKBjLlKOGPBNOAZ97ZVZWzs= +github.com/sagernet/sing-tun v0.8.5 h1:PiQDXJB+btQiYV2x/gZ3TC6hhXErWsmnwufYHVuu6Z8= +github.com/sagernet/sing-tun v0.8.5/go.mod h1:pLCo4o+LacXEzz0bhwhJkKBjLlKOGPBNOAZ97ZVZWzs= github.com/sagernet/sing-vmess v0.2.8-0.20250909125414-3aed155119a1 h1:aSwUNYUkVyVvdmBSufR8/nRFonwJeKSIROxHcm5br9o= github.com/sagernet/sing-vmess v0.2.8-0.20250909125414-3aed155119a1/go.mod h1:P11scgTxMxVVQ8dlM27yNm3Cro40mD0+gHbnqrNGDuY= github.com/sagernet/smux v1.5.50-sing-box-mod.1 h1:XkJcivBC9V4wBjiGXIXZ229aZCU1hzcbp6kSkkyQ478= diff --git a/route/route.go b/route/route.go index 7773ff3cb..77b66ea40 100644 --- a/route/route.go +++ b/route/route.go @@ -426,8 +426,8 @@ func (r *Router) matchRule( } else { r.logger.InfoContext(ctx, "found process path: ", processInfo.ProcessPath) } - } else if processInfo.AndroidPackageName != "" { - r.logger.InfoContext(ctx, "found package name: ", processInfo.AndroidPackageName) + } else if len(processInfo.AndroidPackageNames) > 0 { + r.logger.InfoContext(ctx, "found package name: ", strings.Join(processInfo.AndroidPackageNames, ", ")) } else if processInfo.UserId != -1 { if processInfo.UserName != "" { r.logger.InfoContext(ctx, "found user: ", processInfo.UserName) diff --git a/route/rule/rule_item_package_name.go b/route/rule/rule_item_package_name.go index fa2275874..514768de7 100644 --- a/route/rule/rule_item_package_name.go +++ b/route/rule/rule_item_package_name.go @@ -25,10 +25,15 @@ func NewPackageNameItem(packageNameList []string) *PackageNameItem { } func (r *PackageNameItem) Match(metadata *adapter.InboundContext) bool { - if metadata.ProcessInfo == nil || metadata.ProcessInfo.AndroidPackageName == "" { + if metadata.ProcessInfo == nil || len(metadata.ProcessInfo.AndroidPackageNames) == 0 { return false } - return r.packageMap[metadata.ProcessInfo.AndroidPackageName] + for _, packageName := range metadata.ProcessInfo.AndroidPackageNames { + if r.packageMap[packageName] { + return true + } + } + return false } func (r *PackageNameItem) String() string {