From c6f9fb0d24ae5718fb37f14e1560a463374e4487 Mon Sep 17 00:00:00 2001 From: fuleyi Date: Wed, 19 Aug 2026 13:26:37 +0800 Subject: [PATCH 1/9] =?UTF-8?q?Revert=20"refactor:=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E7=9F=AD=E4=BC=91=E7=9C=A0=E7=8A=B6=E6=80=81=E8=AE=BE=E7=BD=AE?= =?UTF-8?q?=E6=96=B9=E5=BC=8F=E4=B8=BA=E5=86=85=E9=83=A8=E6=A8=A1=E5=9D=97?= =?UTF-8?q?=E8=B0=83=E7=94=A8"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit c4c26c6a511f03e488c69567c80b158c2d10de13. --- bin/dde-system-daemon/main.go | 5 +- bin/dde-system-daemon/power.go | 70 ++------ bin/dde-system-daemon/power_test.go | 237 ------------------------- system/power1/daemon.go | 107 ++++------- system/power1/exported_methods_auto.go | 5 + system/power1/manager.go | 52 ++---- system/power1/manager_ifc.go | 6 + system/power1/manager_powersave.go | 2 +- system/power1/power_test.go | 38 +--- 9 files changed, 82 insertions(+), 440 deletions(-) delete mode 100644 bin/dde-system-daemon/power_test.go diff --git a/bin/dde-system-daemon/main.go b/bin/dde-system-daemon/main.go index fb44257e3..445b497b8 100644 --- a/bin/dde-system-daemon/main.go +++ b/bin/dde-system-daemon/main.go @@ -6,9 +6,9 @@ package main import ( "os" - "sync" configManager "github.com/linuxdeepin/go-dbus-factory/org.desktopspec.ConfigManager" + systemPower "github.com/linuxdeepin/go-dbus-factory/system/org.deepin.dde.power1" // modules: _ "github.com/linuxdeepin/dde-daemon/accounts1" @@ -50,7 +50,7 @@ type Daemon struct { systemd systemd1.Manager dsSystem configManager.Manager allowCallers *securityloader.AllowCallerRegistry - idleStateMu sync.Mutex + systemPower systemPower.Power idleStatePath string idleScreenStatePath string signals *struct { // nolint @@ -125,6 +125,7 @@ func main() { systemSigLoop: dbusutil.NewSignalLoop(service.Conn(), 10), systemd: systemd1.NewManager(service.Conn()), allowCallers: allowCallers, + systemPower: systemPower.NewPower(service.Conn()), idleStatePath: IdleFile, idleScreenStatePath: IdleScreenFile, } diff --git a/bin/dde-system-daemon/power.go b/bin/dde-system-daemon/power.go index a995d6159..991b03a40 100644 --- a/bin/dde-system-daemon/power.go +++ b/bin/dde-system-daemon/power.go @@ -7,14 +7,13 @@ package main import ( "errors" "fmt" - "os" + "io/ioutil" "os/exec" "strconv" "strings" "syscall" "github.com/godbus/dbus/v5" - "github.com/linuxdeepin/dde-daemon/loader" "github.com/linuxdeepin/dde-daemon/securityloader" configManager "github.com/linuxdeepin/go-dbus-factory/org.desktopspec.ConfigManager" @@ -117,69 +116,30 @@ func (d *Daemon) forwardPrepareForSleepSignal(service *dbusutil.Service) error { return nil } -type shortIdleController interface { - ShortIdleState() (bool, error) - SetShortIdleState(bool) error -} - -func getShortIdleController() (shortIdleController, error) { - module := loader.GetModule("power") - if module == nil { - return nil, errors.New("power module is not registered") - } - if !module.IsEnable() { - return nil, errors.New("power module is not enabled") - } - controller, ok := module.(shortIdleController) - if !ok { - return nil, errors.New("power module does not support short idle control") - } - return controller, nil -} - -func systemPowerSetShortIdleState(controller shortIdleController, state bool) error { +func (d *Daemon) systemPowerSetShortIdleState(state bool) { logger.Info("systemPowerSetShortIdleState : ", state) - if err := controller.SetShortIdleState(state); err != nil { - return fmt.Errorf("failed to set short idle mode: %w", err) + if d.systemPower != nil { + err := d.systemPower.SetShortIdleState(0, state) + if err != nil { + logger.Warning("failed to SetShortIdleState, err : ", err) + } } - return nil } -// 1.设置 system/power 模块的短 idle 状态 -// 2.写file内核文件 func (d *Daemon) setState(file string, state bool) error { - if file != d.idleStatePath { - return d.writeStateFile(file, state) - } - - controller, err := getShortIdleController() - if err != nil { - return fmt.Errorf("failed to get short idle controller: %w", err) - } - return d.setStateWithController(controller, file, state) -} - -func (d *Daemon) setStateWithController(controller shortIdleController, file string, state bool) error { - d.idleStateMu.Lock() - defer d.idleStateMu.Unlock() - - shortIdleState, err := controller.ShortIdleState() + shortIdleState, err := d.systemPower.ShortIdleState().Get(0) if err != nil { - return fmt.Errorf("failed to get short idle state: %w", err) + logger.Warning("Get systemPower.ShortIdleState err :", err) } logger.Infof("##### setState shortIdleState : %v, state : %v", shortIdleState, state) if shortIdleState == state { logger.Info("shortIdleState is same with state : ", state) - return d.writeStateFile(file, state) + return errors.New("Short idle state not exchange.") } - // 设置 system/power 模块的短 idle 状态 - if err := systemPowerSetShortIdleState(controller, state); err != nil { - return err + if file == d.idleStatePath { + d.systemPowerSetShortIdleState(state) } - return d.writeStateFile(file, state) -} -func (d *Daemon) writeStateFile(file string, state bool) error { // 写file内核文件 if !utils.IsFileExist(file) { err := fmt.Errorf("%s not found", file) @@ -188,7 +148,7 @@ func (d *Daemon) writeStateFile(file string, state bool) error { } // 读取file文件内容 - content, err := os.ReadFile(file) + content, err := ioutil.ReadFile(file) if err != nil { logger.Errorf("Failed to read file %s: %v", file, err) return err @@ -204,7 +164,7 @@ func (d *Daemon) writeStateFile(file string, state bool) error { logger.Infof("Current content=%s, will set %v", contentStr, newValue) // 将值写入文件 newContent := strconv.Itoa(newValue) - err = os.WriteFile(file, []byte(newContent), 0644) + err = ioutil.WriteFile(file, []byte(newContent), 0644) if err != nil { logger.Errorf("Failed to write file %s: %v", file, err) return err @@ -244,4 +204,4 @@ func (d *Daemon) SetScreenState(sender dbus.Sender, state bool) *dbus.Error { } logger.Infof("SetScreenState %s try set state: %v", d.idleScreenStatePath, state) return dbusutil.ToError(d.setState(d.idleScreenStatePath, state)) -} \ No newline at end of file +} diff --git a/bin/dde-system-daemon/power_test.go b/bin/dde-system-daemon/power_test.go deleted file mode 100644 index 6e3f86f39..000000000 --- a/bin/dde-system-daemon/power_test.go +++ /dev/null @@ -1,237 +0,0 @@ -// SPDX-FileCopyrightText: 2026 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: GPL-3.0-or-later - -package main - -import ( - "errors" - "os" - "path/filepath" - "sync" - "testing" - "time" -) - -type fakeShortIdleController struct { - state bool - getErr error - setErr error - setCalls int -} - -func (c *fakeShortIdleController) ShortIdleState() (bool, error) { - return c.state, c.getErr -} - -func (c *fakeShortIdleController) SetShortIdleState(state bool) error { - c.setCalls++ - if c.setErr != nil { - return c.setErr - } - c.state = state - return nil -} - -type blockingShortIdleController struct { - mu sync.Mutex - state bool - getCalls int - firstSet sync.Once - firstSetStarted chan struct{} - releaseFirstSet chan struct{} - secondGetCalled chan struct{} -} - -func (c *blockingShortIdleController) ShortIdleState() (bool, error) { - c.mu.Lock() - defer c.mu.Unlock() - - c.getCalls++ - if c.getCalls == 2 { - close(c.secondGetCalled) - } - return c.state, nil -} - -func (c *blockingShortIdleController) SetShortIdleState(state bool) error { - c.mu.Lock() - c.state = state - c.mu.Unlock() - - c.firstSet.Do(func() { - close(c.firstSetStarted) - <-c.releaseFirstSet - }) - return nil -} - -func (c *blockingShortIdleController) currentState() bool { - c.mu.Lock() - defer c.mu.Unlock() - return c.state -} - -func TestSetStateWithControllerGetErrorDoesNotWrite(t *testing.T) { - stateFile := filepath.Join(t.TempDir(), "relax_state") - if err := os.WriteFile(stateFile, []byte("0"), 0644); err != nil { - t.Fatal(err) - } - - controller := &fakeShortIdleController{getErr: errors.New("get failed")} - d := &Daemon{idleStatePath: stateFile} - if err := d.setStateWithController(controller, stateFile, true); err == nil { - t.Fatal("expected get state error") - } - - content, err := os.ReadFile(stateFile) - if err != nil { - t.Fatal(err) - } - if string(content) != "0" { - t.Fatalf("state file changed after getter failure: %q", content) - } - if controller.setCalls != 0 { - t.Fatalf("setter called after getter failure: %d", controller.setCalls) - } -} - -func TestSetStateWithControllerSetErrorDoesNotWrite(t *testing.T) { - stateFile := filepath.Join(t.TempDir(), "relax_state") - if err := os.WriteFile(stateFile, []byte("0"), 0644); err != nil { - t.Fatal(err) - } - - controller := &fakeShortIdleController{setErr: errors.New("set failed")} - d := &Daemon{idleStatePath: stateFile} - if err := d.setStateWithController(controller, stateFile, true); err == nil { - t.Fatal("expected set state error") - } - - content, err := os.ReadFile(stateFile) - if err != nil { - t.Fatal(err) - } - if string(content) != "0" { - t.Fatalf("state file changed after setter failure: %q", content) - } - if controller.setCalls != 1 { - t.Fatalf("unexpected setter call count: %d", controller.setCalls) - } -} - -func TestSetScreenStateWritesWithoutController(t *testing.T) { - screenStateFile := filepath.Join(t.TempDir(), "idle_state") - if err := os.WriteFile(screenStateFile, []byte("1"), 0644); err != nil { - t.Fatal(err) - } - - d := &Daemon{ - idleStatePath: filepath.Join(t.TempDir(), "relax_state"), - idleScreenStatePath: screenStateFile, - } - if err := d.setState(screenStateFile, false); err != nil { - t.Fatalf("set screen state: %v", err) - } - - content, err := os.ReadFile(screenStateFile) - if err != nil { - t.Fatal(err) - } - if string(content) != "0" { - t.Fatalf("screen state file = %q, want %q", content, "0") - } -} - -func TestSetStateWithControllerRetryRepairsFile(t *testing.T) { - stateFile := filepath.Join(t.TempDir(), "relax_state") - controller := new(fakeShortIdleController) - d := &Daemon{idleStatePath: stateFile} - - if err := d.setStateWithController(controller, stateFile, true); err == nil { - t.Fatal("expected first write to fail") - } - if !controller.state { - t.Fatal("controller state was not updated before the write failure") - } - - if err := os.WriteFile(stateFile, []byte("0"), 0644); err != nil { - t.Fatal(err) - } - if err := d.setStateWithController(controller, stateFile, true); err != nil { - t.Fatalf("retry state file write: %v", err) - } - - content, err := os.ReadFile(stateFile) - if err != nil { - t.Fatal(err) - } - if string(content) != "1" { - t.Fatalf("state file = %q, want %q", content, "1") - } - if controller.setCalls != 1 { - t.Fatalf("unexpected setter call count: %d", controller.setCalls) - } -} - -func TestSetStateWithControllerSerializesTransitions(t *testing.T) { - stateFile := filepath.Join(t.TempDir(), "relax_state") - if err := os.WriteFile(stateFile, []byte("0"), 0644); err != nil { - t.Fatal(err) - } - - controller := &blockingShortIdleController{ - firstSetStarted: make(chan struct{}), - releaseFirstSet: make(chan struct{}), - secondGetCalled: make(chan struct{}), - } - d := &Daemon{idleStatePath: stateFile} - - firstErr := make(chan error, 1) - go func() { - firstErr <- d.setStateWithController(controller, stateFile, true) - }() - - select { - case <-controller.firstSetStarted: - case <-time.After(time.Second): - t.Fatal("first transition did not reach the setter") - } - - secondErr := make(chan error, 1) - secondStarted := make(chan struct{}) - go func() { - close(secondStarted) - secondErr <- d.setStateWithController(controller, stateFile, false) - }() - <-secondStarted - - serialized := true - select { - case <-controller.secondGetCalled: - serialized = false - case <-time.After(100 * time.Millisecond): - } - - close(controller.releaseFirstSet) - if err := <-firstErr; err != nil { - t.Fatalf("first transition: %v", err) - } - if err := <-secondErr; err != nil { - t.Fatalf("second transition: %v", err) - } - if !serialized { - t.Fatal("second transition entered before the first transition completed") - } - - content, err := os.ReadFile(stateFile) - if err != nil { - t.Fatal(err) - } - if string(content) != "0" { - t.Fatalf("state file = %q, want %q", content, "0") - } - if controller.currentState() { - t.Fatal("controller state and state file are inconsistent") - } -} \ No newline at end of file diff --git a/system/power1/daemon.go b/system/power1/daemon.go index 8219a4b33..73c84dede 100644 --- a/system/power1/daemon.go +++ b/system/power1/daemon.go @@ -5,12 +5,10 @@ package power import ( - "errors" "github.com/godbus/dbus/v5" "github.com/linuxdeepin/dde-daemon/loader" "github.com/linuxdeepin/go-lib/dbusutil" "github.com/linuxdeepin/go-lib/log" - "sync" ) var logger = log.NewLogger("daemon/system/power") @@ -21,8 +19,7 @@ func init() { type Daemon struct { *loader.ModuleBase - managerMu sync.RWMutex - manager *Manager + manager *Manager } func NewDaemon(logger *log.Logger) *Daemon { @@ -30,59 +27,33 @@ func NewDaemon(logger *log.Logger) *Daemon { daemon.ModuleBase = loader.NewModuleBase("power", daemon, logger) return daemon } -func (d *Daemon) ShortIdleState() (bool, error) { - d.managerMu.RLock() - defer d.managerMu.RUnlock() - - manager := d.manager - if manager == nil { - return false, errors.New("power manager is not initialized") - } - return manager.getShortIdleState(), nil -} - -func (d *Daemon) SetShortIdleState(state bool) error { - d.managerMu.RLock() - defer d.managerMu.RUnlock() - - manager := d.manager - if manager == nil { - return errors.New("power manager is not initialized") - } - return manager.setShortIdleState(state) -} - func (d *Daemon) GetDependencies() []string { return []string{} } func (d *Daemon) Start() (err error) { - d.managerMu.Lock() - defer d.managerMu.Unlock() - service := loader.GetService() - manager, err := newManager(service) + d.manager, err = newManager(service) if err != nil { return } - d.manager = manager - manager.batteriesMu.Lock() - for _, bat := range manager.batteries { + d.manager.batteriesMu.Lock() + for _, bat := range d.manager.batteries { err := service.Export(bat.getObjPath(), bat) if err != nil { logger.Warning("failed to export battery:", err) } } - manager.batteriesMu.Unlock() - serverObj, err := service.NewServerObject(dbusPath, manager) + d.manager.batteriesMu.Unlock() + serverObj, err := service.NewServerObject(dbusPath, d.manager) if err != nil { return } - err = serverObj.ConnectChanged(manager, "PowerSavingModeAuto", func(change *dbusutil.PropertyChanged) { - manager.updatePowerMode(false) // PowerSavingModeAuto change - err := manager.saveDsgConfig("PowerSavingModeAuto") + err = serverObj.ConnectChanged(d.manager, "PowerSavingModeAuto", func(change *dbusutil.PropertyChanged) { + d.manager.updatePowerMode(false) // PowerSavingModeAuto change + err := d.manager.saveDsgConfig("PowerSavingModeAuto") if err != nil { logger.Warning(err) } @@ -91,18 +62,18 @@ func (d *Daemon) Start() (err error) { logger.Warning(err) } - err = serverObj.ConnectChanged(manager, "PowerSavingModeEnabled", func(change *dbusutil.PropertyChanged) { + err = serverObj.ConnectChanged(d.manager, "PowerSavingModeEnabled", func(change *dbusutil.PropertyChanged) { enabled := change.Value.(bool) - manager.PropsMu.Lock() - manager.updatePowerSavingState(false) - manager.PropsMu.Unlock() + d.manager.PropsMu.Lock() + d.manager.updatePowerSavingState(false) + d.manager.PropsMu.Unlock() // 历史版本只有节能和平衡之间的切换 if enabled { - manager.doSetMode(ddePowerSave) + d.manager.doSetMode(ddePowerSave) } else { - manager.doSetMode(ddeBalance) + d.manager.doSetMode(ddeBalance) } - err := manager.saveDsgConfig("PowerSavingModeEnabled") + err := d.manager.saveDsgConfig("PowerSavingModeEnabled") if err != nil { logger.Warning(err) } @@ -112,10 +83,10 @@ func (d *Daemon) Start() (err error) { } // 属性改变后的回调函数 - err = serverObj.ConnectChanged(manager, "PowerSavingModeAutoWhenBatteryLow", func(change *dbusutil.PropertyChanged) { - manager.refreshBatteryDisplay() - manager.updatePowerMode(false) // PowerSavingModeAutoWhenBatteryLow change - err := manager.saveDsgConfig("PowerSavingModeAutoWhenBatteryLow") + err = serverObj.ConnectChanged(d.manager, "PowerSavingModeAutoWhenBatteryLow", func(change *dbusutil.PropertyChanged) { + d.manager.refreshBatteryDisplay() + d.manager.updatePowerMode(false) // PowerSavingModeAutoWhenBatteryLow change + err := d.manager.saveDsgConfig("PowerSavingModeAutoWhenBatteryLow") if err != nil { logger.Warning(err) } @@ -124,8 +95,8 @@ func (d *Daemon) Start() (err error) { logger.Warning(err) } - err = serverObj.ConnectChanged(manager, "PowerSavingModeBrightnessDropPercent", func(change *dbusutil.PropertyChanged) { - err := manager.saveDsgConfig("PowerSavingModeBrightnessDropPercent") + err = serverObj.ConnectChanged(d.manager, "PowerSavingModeBrightnessDropPercent", func(change *dbusutil.PropertyChanged) { + err := d.manager.saveDsgConfig("PowerSavingModeBrightnessDropPercent") if err != nil { logger.Warning(err) } @@ -134,10 +105,10 @@ func (d *Daemon) Start() (err error) { logger.Warning(err) } - err = serverObj.ConnectChanged(manager, "PowerSavingModeAutoBatteryPercent", func(change *dbusutil.PropertyChanged) { - manager.refreshBatteryDisplay() - manager.updatePowerMode(false) // PowerSavingModeAutoBatteryPercent change - err := manager.saveDsgConfig("PowerSavingModeAutoBatteryPercent") + err = serverObj.ConnectChanged(d.manager, "PowerSavingModeAutoBatteryPercent", func(change *dbusutil.PropertyChanged) { + d.manager.refreshBatteryDisplay() + d.manager.updatePowerMode(false) // PowerSavingModeAutoBatteryPercent change + err := d.manager.saveDsgConfig("PowerSavingModeAutoBatteryPercent") if err != nil { logger.Warning(err) } @@ -145,18 +116,18 @@ func (d *Daemon) Start() (err error) { if err != nil { logger.Warning(err) } - if manager.enablePerformanceInBoot() { + if d.manager.enablePerformanceInBoot() { var handlerId dbusutil.SignalHandlerId - handlerId, err = manager.displayManager.ConnectSessionAdded(func(session dbus.ObjectPath) { + handlerId, err = d.manager.displayManager.ConnectSessionAdded(func(session dbus.ObjectPath) { // 登录前tlpMode都是performance,不设置电源模式,直到有第一个用户登录了才设置电源模式 - displaySessions, err := manager.displayManager.Sessions().Get(0) + displaySessions, err := d.manager.displayManager.Sessions().Get(0) if err != nil { logger.Warning(err) } if len(displaySessions) == 1 { - manager.updatePowerMode(true) + d.manager.updatePowerMode(true) } - manager.displayManager.RemoveHandler(handlerId) + d.manager.displayManager.RemoveHandler(handlerId) }) if err != nil { logger.Warning(err) @@ -173,30 +144,26 @@ func (d *Daemon) Start() (err error) { } func (d *Daemon) Stop() error { - d.managerMu.Lock() - defer d.managerMu.Unlock() - - manager := d.manager - if manager == nil { + if d.manager == nil { return nil } service := loader.GetService() - manager.batteriesMu.Lock() - for _, bat := range manager.batteries { + d.manager.batteriesMu.Lock() + for _, bat := range d.manager.batteries { err := service.StopExport(bat) if err != nil { logger.Warning(err) } } - manager.batteriesMu.Unlock() + d.manager.batteriesMu.Unlock() - err := service.StopExport(manager) + err := service.StopExport(d.manager) if err != nil { logger.Warning(err) } - manager.destroy() + d.manager.destroy() d.manager = nil return nil } diff --git a/system/power1/exported_methods_auto.go b/system/power1/exported_methods_auto.go index efbd96693..8120dbd0a 100644 --- a/system/power1/exported_methods_auto.go +++ b/system/power1/exported_methods_auto.go @@ -58,5 +58,10 @@ func (v *Manager) GetExportedMethods() dbusutil.ExportedMethods { Fn: v.SetTlpMode, InArgs: []string{"mode"}, }, + { + Name: "SetShortIdleState", + Fn: v.SetShortIdleState, + InArgs: []string{"state"}, + }, } } diff --git a/system/power1/manager.go b/system/power1/manager.go index 424ea546e..53657ab3c 100644 --- a/system/power1/manager.go +++ b/system/power1/manager.go @@ -96,12 +96,10 @@ type Manager struct { PowerSavingModeBrightnessData string `prop:"access:rw"` // 当前短idle状态 - ShortIdleState bool - ShortIdleStateMu sync.RWMutex + ShortIdleState bool // 是否支持短idle方案 - shortIdleEnableMu sync.RWMutex - shortIdleEnable bool + shortIdleEnable bool // 直接设置tlp配置 TlpMode string @@ -443,8 +441,8 @@ func (m *Manager) initDsgConfig() error { logger.Warning(err) return } - m.setShortIdleEnable(data) - logger.Info("dsg of shortIdleEnable : ", data) + m.shortIdleEnable = data + logger.Info("dsg of shortIdleEnable : ", m.shortIdleEnable) } getShortIdleEnable() @@ -777,36 +775,15 @@ func (m *Manager) setTlpMode(mode string) error { return nil } -func (m *Manager) getShortIdleEnable() bool { - m.shortIdleEnableMu.RLock() - defer m.shortIdleEnableMu.RUnlock() - return m.shortIdleEnable -} - -func (m *Manager) setShortIdleEnable(enabled bool) { - m.shortIdleEnableMu.Lock() - m.shortIdleEnable = enabled - m.shortIdleEnableMu.Unlock() -} - -func (m *Manager) getShortIdleState() bool { - m.ShortIdleStateMu.RLock() - defer m.ShortIdleStateMu.RUnlock() - return m.ShortIdleState -} - -//仅对性能模式做设置,不记录状态 -//deepin-power-control idle wifi -func (m *Manager) setShortIdleState(state bool) error { +// 仅对性能模式做设置,不记录状态 +// deepin-power-control idle wifi +func (m *Manager) setShortIdleState(state bool) { logger.Info(" setShortIdleState state : ", state) - if !m.getShortIdleEnable() { + if !m.shortIdleEnable { logger.Info("System not open dsg of shortIdleEnable.") - return nil + return } - m.ShortIdleStateMu.Lock() - defer m.ShortIdleStateMu.Unlock() - if m.ShortIdleState != state { m.ShortIdleState = state if m.dsgPower != nil { @@ -817,7 +794,7 @@ func (m *Manager) setShortIdleState(state bool) error { } } else { logger.Info("setShortIdleState the same state : ", state) - return nil + return } // 进入短idle: @@ -829,7 +806,7 @@ func (m *Manager) setShortIdleState(state bool) error { if m.batteryLow { powerState = ddeLowBattery } - if !state { + if !m.ShortIdleState { // 退出短idle: // 1. deepin-power-control idle wifi off : 执行 `wifi off` 时,停止守护进程,恢复网卡默认行为 // 2. 电源模式切换为节能模式 @@ -849,7 +826,6 @@ func (m *Manager) setShortIdleState(state bool) error { // 设置wifi短idle模式 m.setDPCWifiState(wifiState) }() - return nil } func (m *Manager) doSetMode(mode string) { @@ -884,13 +860,13 @@ func (m *Manager) doSetMode(mode string) { _ = m.setDsgData(dsettingsMode, fixMode, m.dsgPower) } - logger.Info(" doSetMode, shortIdleState : ", m.getShortIdleState()) + logger.Info(" doSetMode, shortIdleState : ", m.ShortIdleState) // 如果恢复性能模式时,当前处于短idle状态,则需要恢复模式后,将TlpMode设置为节能模式 // 在延时回调中重新检查短idle状态,避免在延时期间短idle退出后,错误地恢复节能模式 - if m.getShortIdleState() { + if m.ShortIdleState { // 连续两次调用deepin-power-control,有概率会设置失败,因此使用延时500ms time.AfterFunc(500*time.Millisecond, func() { - if !m.getShortIdleState() { + if !m.ShortIdleState { logger.Info("shortIdle state has changed, skip restoring power save mode") return } diff --git a/system/power1/manager_ifc.go b/system/power1/manager_ifc.go index 2b6ae192d..ba52cbde3 100644 --- a/system/power1/manager_ifc.go +++ b/system/power1/manager_ifc.go @@ -128,6 +128,12 @@ func (m *Manager) SetTlpMode(sender dbus.Sender, mode string) *dbus.Error { return dbusutil.ToError(m.setTlpMode(mode)) } +func (m *Manager) SetShortIdleState(state bool) *dbus.Error { + logger.Info(" SetShortIdleState : ", state) + m.setShortIdleState(state) + return nil +} + func (m *Manager) LockCpuFreq(governor string, lockTime int32) *dbus.Error { // TODO 改用tlp // currentGovernor, err := m.cpus.GetGovernor() diff --git a/system/power1/manager_powersave.go b/system/power1/manager_powersave.go index 3eaf503d8..bb5710b3b 100644 --- a/system/power1/manager_powersave.go +++ b/system/power1/manager_powersave.go @@ -125,7 +125,7 @@ func (m *Manager) updatePowerMode(init bool) { } logger.Infof("PowerSavingModeAuto: %v\n OnBattery:%v \n PowerSavingModeAutoWhenBatteryLow:%v \n batteryLow:%v \n", m.PowerSavingModeAuto, m.OnBattery, m.PowerSavingModeAutoWhenBatteryLow, m.batteryLow) - logger.Infof("lastMode: %v, ShortIdleState : %v", m.lastMode, m.getShortIdleState()) + logger.Infof("lastMode: %v, ShortIdleState : %v", m.lastMode, m.ShortIdleState) if !m.PowerSavingModeAuto && !m.PowerSavingModeAutoWhenBatteryLow && !init { return } diff --git a/system/power1/power_test.go b/system/power1/power_test.go index 7e6359034..a6a9b415b 100644 --- a/system/power1/power_test.go +++ b/system/power1/power_test.go @@ -1,11 +1,10 @@ -// SPDX-FileCopyrightText: 2018 - 2026 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: GPL-3.0-or-later package power import ( - "sync" "testing" "github.com/godbus/dbus/v5" @@ -20,38 +19,3 @@ func Test_getValidName(t *testing.T) { assert.True(t, path.IsValid()) } } -func TestSetShortIdleStateDisabledIsNoOp(t *testing.T) { - m := new(Manager) - - if err := m.setShortIdleState(true); err != nil { - t.Fatalf("setShortIdleState returned error while disabled: %v", err) - } - if m.getShortIdleState() { - t.Fatal("short idle state changed while disabled") - } -} - -func TestShortIdleEnableConcurrentAccess(t *testing.T) { - m := new(Manager) - - var wg sync.WaitGroup - wg.Add(2) - go func() { - defer wg.Done() - for i := 0; i < 10000; i++ { - m.setShortIdleEnable(i%2 == 0) - } - }() - go func() { - defer wg.Done() - for i := 0; i < 10000; i++ { - _ = m.getShortIdleEnable() - } - }() - wg.Wait() - - m.setShortIdleEnable(true) - if !m.getShortIdleEnable() { - t.Fatal("short idle enable state was not updated") - } -} From 322dc9a381a60fbc3ded7ef3c3a0d3832fb56498 Mon Sep 17 00:00:00 2001 From: fuleyi Date: Wed, 19 Aug 2026 13:26:47 +0800 Subject: [PATCH 2/9] Revert "fix: correct security-loader authorization fallback" This reverts commit 1f4a4415f624924f33625c225e4423a21d071ce4. --- Makefile | 21 +- bin/dde-session-daemon/main.go | 4 +- bin/dde-system-daemon/power.go | 54 +++-- bin/langselector/main.go | 4 +- debian/control | 1 + langselector1/securityloader.go | 20 +- misc/conf/org.deepin.dde.Daemon1.conf | 4 - misc/conf/org.deepin.dde.Power1.conf | 3 - .../scripts/dde-session-daemon-loader-wrapper | 7 +- misc/scripts/langselector-loader-wrapper | 30 +-- .../services/system/dde-system-daemon.service | 2 +- .../user/org.dde.session.Daemon1.service | 2 + rpm/dde-daemon.spec | 11 +- securityloader/allowcaller.go | 220 ++++++------------ securityloader/allowcaller_test.go | 194 +++------------ securityloader/handshake.go | 4 +- securityloader/handshake_test.go | 2 +- securityloader/polkit.go | 54 ----- system/airplane_mode1/manager.go | 74 ++++-- system/inputdevices1/inputdevices_ifc.go | 2 +- system/inputdevices1/touchpad.go | 58 +++-- system/power1/manager_ifc.go | 38 ++- 22 files changed, 299 insertions(+), 510 deletions(-) delete mode 100644 securityloader/polkit.go diff --git a/Makefile b/Makefile index 83cb08811..cde901863 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,4 @@ PREFIX = /usr -DAEMON_LIBDIR ?= ${PREFIX}/lib/deepin-daemon GOPATH_DIR = gopath GOPKG_PREFIX = github.com/linuxdeepin/dde-daemon GOBUILD = go build $(GO_BUILD_FLAGS) @@ -164,19 +163,19 @@ print_gopath: prepare GOPATH="${CURDIR}/${GOPATH_DIR}:${GOPATH}" install: build install-dde-data install-icons - mkdir -pv ${DESTDIR}${DAEMON_LIBDIR} - cp -f out/bin/* ${DESTDIR}${DAEMON_LIBDIR}/ + mkdir -pv ${DESTDIR}${PREFIX}/lib/deepin-daemon + cp -f out/bin/* ${DESTDIR}${PREFIX}/lib/deepin-daemon/ - rm -f ${DESTDIR}${DAEMON_LIBDIR}/dde-session-daemon + rm -f ${DESTDIR}${PREFIX}/lib/deepin-daemon/dde-session-daemon mkdir -pv ${DESTDIR}${PREFIX}/libexec/deepin cp -f out/bin/dde-session-daemon ${DESTDIR}${PREFIX}/libexec/deepin/ install -m755 misc/scripts/dde-session-daemon-loader-wrapper \ - ${DESTDIR}${DAEMON_LIBDIR}/dde-session-daemon + ${DESTDIR}${PREFIX}/lib/deepin-daemon/dde-session-daemon - rm -f ${DESTDIR}${DAEMON_LIBDIR}/langselector + rm -f ${DESTDIR}${PREFIX}/lib/deepin-daemon/langselector cp -f out/bin/langselector ${DESTDIR}${PREFIX}/libexec/deepin/ install -m755 misc/scripts/langselector-loader-wrapper \ - ${DESTDIR}${DAEMON_LIBDIR}/langselector + ${DESTDIR}${PREFIX}/lib/deepin-daemon/langselector mkdir -pv ${DESTDIR}${PREFIX}/share/locale cp -r out/locale/* ${DESTDIR}${PREFIX}/share/locale @@ -219,8 +218,8 @@ install: build install-dde-data install-icons mkdir -pv ${DESTDIR}/etc/pulse/daemon.conf.d cp -f misc/etc/pulse/daemon.conf.d/*.conf ${DESTDIR}/etc/pulse/daemon.conf.d/ - mkdir -pv ${DESTDIR}${DAEMON_LIBDIR}/service-trigger - cp -f misc/service-trigger/*.json ${DESTDIR}${DAEMON_LIBDIR}/service-trigger/ + mkdir -pv ${DESTDIR}${PREFIX}/lib/deepin-daemon/service-trigger + cp -f misc/service-trigger/*.json ${DESTDIR}${PREFIX}/lib/deepin-daemon/service-trigger/ mkdir -pv ${DESTDIR}${PREFIX}/libexec/dde-daemon/ cp -r misc/libexec/dde-daemon/* ${DESTDIR}${PREFIX}/libexec/dde-daemon/ @@ -231,8 +230,8 @@ install: build install-dde-data install-icons mkdir -pv ${DESTDIR}${PREFIX}/share/dsg/configs/org.deepin.dde.lightdm-deepin-greeter cp -r misc/dsg-configs/org.deepin.dde.lightdm-deepin-greeter/*.json ${DESTDIR}${PREFIX}/share/dsg/configs/org.deepin.dde.lightdm-deepin-greeter/ - cp -f misc/scripts/dde-lock.sh ${DESTDIR}${DAEMON_LIBDIR}/ - cp -f misc/scripts/dde-shutdown.sh ${DESTDIR}${DAEMON_LIBDIR}/ + cp -f misc/scripts/dde-lock.sh ${DESTDIR}${PREFIX}/lib/deepin-daemon/ + cp -f misc/scripts/dde-shutdown.sh ${DESTDIR}${PREFIX}/lib/deepin-daemon/ install-dde-data: mkdir -pv ${DESTDIR}${PREFIX}/share/dde/ cp -r misc/data misc/zoneinfo ${DESTDIR}${PREFIX}/share/dde/ diff --git a/bin/dde-session-daemon/main.go b/bin/dde-session-daemon/main.go index bd42a0156..17c2d599d 100755 --- a/bin/dde-session-daemon/main.go +++ b/bin/dde-session-daemon/main.go @@ -182,10 +182,10 @@ func main() { os.Args = cleanedArgs if err != nil { if loadedBySecurityLoader { - logger.Errorf("security-loader handshake failed, refusing to start: %q", err.Error()) + logger.Error("security-loader handshake failed, refusing to start:", err) os.Exit(1) } - logger.Warningf("security-loader handshake failed: %q", err.Error()) + logger.Warning("security-loader handshake failed:", err) } logger.SetLogLevel(log.LevelInfo) diff --git a/bin/dde-system-daemon/power.go b/bin/dde-system-daemon/power.go index 991b03a40..52a8e1837 100644 --- a/bin/dde-system-daemon/power.go +++ b/bin/dde-system-daemon/power.go @@ -14,9 +14,9 @@ import ( "syscall" "github.com/godbus/dbus/v5" - "github.com/linuxdeepin/dde-daemon/securityloader" configManager "github.com/linuxdeepin/go-dbus-factory/org.desktopspec.ConfigManager" - + "github.com/linuxdeepin/dde-daemon/securityloader" + polkit "github.com/linuxdeepin/go-dbus-factory/system/org.freedesktop.policykit1" "github.com/linuxdeepin/go-lib/dbusutil" "github.com/linuxdeepin/go-lib/utils" ) @@ -178,30 +178,48 @@ func (d *Daemon) SetAllowCaller(sender dbus.Sender, uniqueName string) *dbus.Err return dbusutil.ToError(d.allowCallers.AddCaller(securityloader.DaemonScope, sender, uniqueName)) } -func (d *Daemon) authorize(sender dbus.Sender, actionID string) error { - return securityloader.AuthorizeWithPolkit( - d.allowCallers, - securityloader.DaemonScope, - sender, - d.service.Conn(), - actionID, - ) -} - func (d *Daemon) SetIdleState(sender dbus.Sender, state bool) *dbus.Error { - if err := d.authorize(sender, "org.deepin.dde.daemon.set-idle-state"); err != nil { - logger.Warningf("SetIdleState authorization failed: %q", err.Error()) - return dbusutil.ToError(err) + result, _ := d.allowCallers.Authorize(securityloader.DaemonScope, sender) + switch result { + case securityloader.AuthDenied: + logger.Warning("SetIdleState access denied") + return dbusutil.ToError(errors.New("access denied")) + case securityloader.AuthNotEnabled: + if ok, er := checkDaemonAuth(string(sender), "org.deepin.dde.daemon.set-idle-state"); !ok || er != nil { + return dbusutil.ToError(er) + } } logger.Infof("SetIdleState %s try set state: %v", d.idleStatePath, state) return dbusutil.ToError(d.setState(d.idleStatePath, state)) } func (d *Daemon) SetScreenState(sender dbus.Sender, state bool) *dbus.Error { - if err := d.authorize(sender, "org.deepin.dde.daemon.set-screen-state"); err != nil { - logger.Warningf("SetScreenState authorization failed: %q", err.Error()) - return dbusutil.ToError(err) + result, _ := d.allowCallers.Authorize(securityloader.DaemonScope, sender) + switch result { + case securityloader.AuthDenied: + logger.Warning("SetScreenState access denied") + return dbusutil.ToError(errors.New("access denied")) + case securityloader.AuthNotEnabled: + if ok, er := checkDaemonAuth(string(sender), "org.deepin.dde.daemon.set-screen-state"); !ok || er != nil { + return dbusutil.ToError(er) + } } logger.Infof("SetScreenState %s try set state: %v", d.idleScreenStatePath, state) return dbusutil.ToError(d.setState(d.idleScreenStatePath, state)) } + +func checkDaemonAuth(sysBusName, actionId string) (bool, error) { + systemBus, err := dbus.SystemBus() + if err != nil { + return false, err + } + authority := polkit.NewAuthority(systemBus) + subject := polkit.MakeSubject(polkit.SubjectKindSystemBusName) + subject.SetDetail("name", sysBusName) + result, err := authority.CheckAuthorization(0, subject, actionId, + nil, polkit.CheckAuthorizationFlagsAllowUserInteraction, "") + if err != nil { + return false, err + } + return result.IsAuthorized, nil +} diff --git a/bin/langselector/main.go b/bin/langselector/main.go index 6022bf118..6260f63e8 100644 --- a/bin/langselector/main.go +++ b/bin/langselector/main.go @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2018-2026 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: GPL-3.0-or-later @@ -18,4 +18,4 @@ func main() { gettext.BindTextdomainCodeset("dde-daemon", "UTF-8") gettext.Textdomain("dde-daemon") langselector.Run() -} +} \ No newline at end of file diff --git a/debian/control b/debian/control index ba6db003e..bef3cdb42 100644 --- a/debian/control +++ b/debian/control @@ -53,6 +53,7 @@ Build-Depends: libxtst-dev, libddcutil-dev, python3, + deepin-security-loader, Standards-Version: 4.5.1 Homepage: http://www.deepin.org diff --git a/langselector1/securityloader.go b/langselector1/securityloader.go index d9a2e4b33..ceca6d74d 100644 --- a/langselector1/securityloader.go +++ b/langselector1/securityloader.go @@ -6,7 +6,6 @@ package langselector import ( "fmt" - "os" "os/user" "github.com/godbus/dbus/v5" @@ -31,14 +30,13 @@ func DoSecurityLoader(args []string) { destList := buildDestList() _, loaded, err := securityloader.Handshake(args, destList) - if err == nil { - return - } - if loaded { - logger.Errorf("security loader handshake failed, refusing to start: %q", err.Error()) - os.Exit(1) + if err != nil { + if loaded { + logger.Warning("security loader handshake failed:", err) + } else { + logger.Warning("security loader handshake skipped:", err) + } } - logger.Warningf("security loader handshake skipped: %q", err.Error()) } // buildDestList 构建需要授权的 D-Bus 接口列表 @@ -75,6 +73,10 @@ func getCurrentUserAccountsPath() (string, error) { return "", err } + if currentUser == nil { + return "", fmt.Errorf("current user is nil") + } + // 通过 D-Bus 调用 FindUserById obj := systemConn.Object("org.deepin.dde.Accounts1", "/org/deepin/dde/Accounts1") var userPath string @@ -88,4 +90,4 @@ func getCurrentUserAccountsPath() (string, error) { } return userPath, nil -} +} \ No newline at end of file diff --git a/misc/conf/org.deepin.dde.Daemon1.conf b/misc/conf/org.deepin.dde.Daemon1.conf index 7d754e104..0fb89c33a 100644 --- a/misc/conf/org.deepin.dde.Daemon1.conf +++ b/misc/conf/org.deepin.dde.Daemon1.conf @@ -9,10 +9,6 @@ - - diff --git a/misc/conf/org.deepin.dde.Power1.conf b/misc/conf/org.deepin.dde.Power1.conf index fa9c4e8a2..edfd934c8 100644 --- a/misc/conf/org.deepin.dde.Power1.conf +++ b/misc/conf/org.deepin.dde.Power1.conf @@ -8,9 +8,6 @@ - diff --git a/misc/scripts/dde-session-daemon-loader-wrapper b/misc/scripts/dde-session-daemon-loader-wrapper index 465360684..a3117e742 100755 --- a/misc/scripts/dde-session-daemon-loader-wrapper +++ b/misc/scripts/dde-session-daemon-loader-wrapper @@ -10,8 +10,9 @@ LOADER_EXEC="/usr/bin/deepin-security-loader-exec" if [ -x "$LOADER" ] && [ -x "$LOADER_EXEC" ] && \ getcap "$LOADER_EXEC" 2>/dev/null | grep -q cap_setgid; then - logger -t dde-session-daemon "starting via deepin-security-loader" exec "$LOADER" --group deepin-daemon -- "$REAL_BINARY" "$@" fi -logger -t dde-session-daemon "starting directly" -exec "$REAL_BINARY" "$@" + +# Type=forking requires the wrapper to leave a child for systemd to adopt. +"$REAL_BINARY" "$@" & +exit 0 diff --git a/misc/scripts/langselector-loader-wrapper b/misc/scripts/langselector-loader-wrapper index 0951a8c97..21444fc42 100755 --- a/misc/scripts/langselector-loader-wrapper +++ b/misc/scripts/langselector-loader-wrapper @@ -1,30 +1,4 @@ #!/bin/bash -set -u -PATH=/usr/sbin:/usr/bin:/sbin:/bin -export PATH - -REAL_BINARY="/usr/libexec/deepin/langselector" -LOADER="/usr/bin/deepin-security-loader" -LOADER_EXEC="/usr/bin/deepin-security-loader-exec" -LOGGER="/usr/bin/logger" - -log_to_journal() { - priority="$1" - message="$2" - if [ -x "$LOGGER" ]; then - "$LOGGER" -t dde-langselector -p "$priority" -- "$message" - fi -} - -if [ -x "$LOADER" ] && [ -x "$LOADER_EXEC" ] && \ - getcap "$LOADER_EXEC" 2>/dev/null | grep -q 'cap_setgid'; then - log_to_journal user.info "Starting through deepin-security-loader." - exec "$LOADER" --group deepin-daemon -- "$REAL_BINARY" "$@" -fi - -# Without loader-injected file descriptors, Handshake treats this as a normal -# launch and protected system-service calls fall back to Polkit authorization. -log_to_journal user.warning \ - "deepin-security-loader unavailable; falling back to Polkit." -exec "$REAL_BINARY" "$@" +exec /usr/bin/deepin-security-loader --group deepin-daemon -- \ + /usr/libexec/deepin/langselector "$@" \ No newline at end of file diff --git a/misc/systemd/services/system/dde-system-daemon.service b/misc/systemd/services/system/dde-system-daemon.service index e10f0bb75..46fccf339 100644 --- a/misc/systemd/services/system/dde-system-daemon.service +++ b/misc/systemd/services/system/dde-system-daemon.service @@ -19,7 +19,7 @@ Environment=GVFS_REMOTE_VOLUME_MONITOR_IGNORE=1 ProtectSystem=strict RuntimeDirectory=dde-daemon -RuntimeDirectoryMode=0750 +RuntimeDirectoryMode=0777 RuntimeDirectoryPreserve=yes ReadWritePaths=/run/dde-daemon diff --git a/misc/systemd/services/user/org.dde.session.Daemon1.service b/misc/systemd/services/user/org.dde.session.Daemon1.service index 31685a6f6..ff1ed8a86 100644 --- a/misc/systemd/services/user/org.dde.session.Daemon1.service +++ b/misc/systemd/services/user/org.dde.session.Daemon1.service @@ -15,6 +15,8 @@ After=treeland-xwayland.service Type=forking GuessMainPID=yes ExecStart=/usr/lib/deepin-daemon/dde-session-daemon +# Keep the original D-Bus readiness semantics before starting dependent units. +ExecStartPost=/usr/bin/gdbus wait --session --timeout=30 org.deepin.dde.Daemon1 Slice=app.slice Restart=on-failure RestartSec=1s \ No newline at end of file diff --git a/rpm/dde-daemon.spec b/rpm/dde-daemon.spec index 7af31ceba..dc790bbc7 100644 --- a/rpm/dde-daemon.spec +++ b/rpm/dde-daemon.spec @@ -79,8 +79,10 @@ Daemon handling the DDE session settings patch langselector/locale.go < rpm/locale.go.patch patch accounts/users/passwd.go < rpm/passwd.go.patch -# Select the RPM daemon directory explicitly. Security-loader targets remain -# under /usr/libexec/deepin and are not rewritten. +# Fix library exec path while preserving security-loader targets under +# /usr/libexec/deepin. +sed -i '/${DESTDIR}\/usr\/lib\/deepin-daemon\/service-trigger/s|${DESTDIR}/usr/lib/deepin-daemon/service-trigger|${DESTDIR}/usr/libexec/deepin-daemon/service-trigger|g' Makefile +sed -i 's|${DESTDIR}${PREFIX}/lib/deepin-daemon|${DESTDIR}${PREFIX}/libexec/deepin-daemon|g' Makefile sed -i 's|lib/NetworkManager|libexec|' network/utils_test.go for file in $(grep "/usr/lib/deepin-daemon" * -nR |awk -F: '{print $1}') @@ -109,7 +111,8 @@ After=user.slice dbus.socket [Service] Type=dbus BusName=org.deepin.dde.LockService1 -ExecStart=%{_libexecdir}/deepin/dde-lockservice +ExecStart=%{_libexecdir}/%{sname}/ +%{_libexecdir}/deepin/dde-lockservice [Install] WantedBy=graphical.target @@ -127,7 +130,7 @@ export GOPATH=/usr/share/gocode %install BUILDID="0x$(head -c20 /dev/urandom|od -An -tx1|tr -d ' \n')" export GOPATH=/usr/share/gocode -%make_install PAM_MODULE_DIR=%{_libdir}/security DAEMON_LIBDIR=%{_libexecdir}/%{sname} GOBUILD="go build -compiler gc -ldflags \"-B $BUILDID\"" +%make_install PAM_MODULE_DIR=%{_libdir}/security GOBUILD="go build -compiler gc -ldflags \"-B $BUILDID\"" # fix systemd/logind config install -d %{buildroot}/usr/lib/systemd/logind.conf.d/ diff --git a/securityloader/allowcaller.go b/securityloader/allowcaller.go index 60263d8be..62c98e2f4 100644 --- a/securityloader/allowcaller.go +++ b/securityloader/allowcaller.go @@ -5,15 +5,14 @@ package securityloader import ( - "crypto/rand" - "encoding/hex" "encoding/json" "errors" "fmt" - + "io/ioutil" "os" "os/user" "path/filepath" + "sort" "strconv" "strings" "sync" @@ -36,19 +35,18 @@ const ( invalidGroupID = ^uint32(0) ) -// AuthResult describes how a caller should be authorized. +// AuthResult describes the result of an Authorize call. type AuthResult int const ( - // AuthError means the registry could not determine whether the caller is - // authorized. err describes the internal authorization failure. - AuthError AuthResult = iota - // AuthOK means the caller is authorized by the allow-caller registry and - // does not need the service's original authorization mechanism. + // AuthDenied means the caller is explicitly rejected. err is the reason. + AuthDenied AuthResult = iota + // AuthOK means the caller is authorized by the allow-caller registry. AuthOK - // AuthPolkit means the caller is not registered for the requested scope. - // Callers should fall back to their original Polkit authorization. - AuthPolkit + // AuthNotEnabled means no caller has been registered for this scope. + // The service was not started via deepin-security-loader. + // Callers should fall back to their original authorization mechanism. + AuthNotEnabled ) var logger = log.NewLogger("daemon/security-loader") @@ -79,17 +77,9 @@ func (s serviceBus) GetConnGroups(name string) ([]uint32, error) { return getProcessGroups(pid) } -// callerInfo stores the credentials recorded for an authorized D-Bus -// connection. Checking both fields prevents a recycled name owned by another -// process, including one under the same UID, from inheriting authorization. -type callerInfo struct { - UID uint32 `json:"uid"` - PID uint32 `json:"pid"` -} - type persistedState struct { - BusID string `json:"busId"` - Callers map[string]map[string]callerInfo `json:"callers"` + BusID string `json:"busId"` + Callers map[string][]string `json:"callers"` } // AllowCallerRegistry stores the exact system-bus unique names authorized by @@ -102,7 +92,7 @@ type AllowCallerRegistry struct { processParent func(uint32) (uint32, error) mu sync.RWMutex - callers map[string]map[string]callerInfo + callers map[string]map[string]struct{} persistMu sync.Mutex signalLoop *dbusutil.SignalLoop @@ -152,7 +142,7 @@ func newAllowCallerRegistry(service busService, stateFile string, privilegedGrou busID: busID, privilegedGroupID: privilegedGroupID, processParent: getProcessParentPID, - callers: make(map[string]map[string]callerInfo), + callers: make(map[string]map[string]struct{}), } } @@ -169,7 +159,7 @@ func lookupGroupID(name string) (uint32, error) { } func getProcessGroups(pid uint32) ([]uint32, error) { - content, err := os.ReadFile(fmt.Sprintf("/proc/%d/status", pid)) + content, err := ioutil.ReadFile(fmt.Sprintf("/proc/%d/status", pid)) if err != nil { return nil, err } @@ -194,7 +184,7 @@ func getProcessGroups(pid uint32) ([]uint32, error) { } func getProcessParentPID(pid uint32) (uint32, error) { - content, err := os.ReadFile(fmt.Sprintf("/proc/%d/status", pid)) + content, err := ioutil.ReadFile(fmt.Sprintf("/proc/%d/status", pid)) if err != nil { return 0, err } @@ -281,17 +271,7 @@ func (r *AllowCallerRegistry) AddCaller(scope string, sender dbus.Sender, unique if !hasOwner { return fmt.Errorf("D-Bus caller %q has no owner", uniqueName) } - - targetUID, err := r.service.GetConnUID(uniqueName) - if err != nil { - return fmt.Errorf("get target caller %q UID failed: %w", uniqueName, err) - } - targetPID, err := r.service.GetConnPID(uniqueName) - if err != nil { - return fmt.Errorf("get target caller %q PID failed: %w", uniqueName, err) - } - info := callerInfo{UID: targetUID, PID: targetPID} - if err := r.authorizeRegistrar(sender, uniqueName, info); err != nil { + if err := r.authorizeRegistrar(sender, uniqueName); err != nil { return err } @@ -301,72 +281,76 @@ func (r *AllowCallerRegistry) AddCaller(scope string, sender dbus.Sender, unique r.mu.Lock() callers := r.callers[scope] if callers == nil { - callers = make(map[string]callerInfo) + callers = make(map[string]struct{}) r.callers[scope] = callers } - previous, existed := callers[uniqueName] - if existed && previous == info { + if _, exists := callers[uniqueName]; exists { r.mu.Unlock() return nil } - callers[uniqueName] = info + callers[uniqueName] = struct{}{} if err := r.saveLocked(); err != nil { - if existed { - callers[uniqueName] = previous - } else { - delete(callers, uniqueName) - if len(callers) == 0 { - delete(r.callers, scope) - } + delete(r.callers[scope], uniqueName) + if len(r.callers[scope]) == 0 { + delete(r.callers, scope) } r.mu.Unlock() return err } r.mu.Unlock() - logger.Infof("registered security-loader caller %q for %q", uniqueName, scope) + logger.Infof("registered security-loader caller %s for %s", uniqueName, scope) return nil } -func (r *AllowCallerRegistry) authorizeRegistrar(sender dbus.Sender, uniqueName string, target callerInfo) error { +func (r *AllowCallerRegistry) authorizeRegistrar(sender dbus.Sender, uniqueName string) error { senderUID, err := r.service.GetConnUID(string(sender)) if err != nil { - return fmt.Errorf("get SetAllowCaller sender %q UID failed: %w", sender, err) + return fmt.Errorf("get SetAllowCaller sender %s UID failed: %w", sender, err) } // Root is trusted to register a process running under another account. if senderUID == 0 { return nil } if r.privilegedGroupID == invalidGroupID { - return fmt.Errorf("privileged group %q is unavailable", privilegedGroup) + return fmt.Errorf("privileged group %s is unavailable", privilegedGroup) } groups, err := r.service.GetConnGroups(string(sender)) if err != nil { - return fmt.Errorf("get SetAllowCaller sender %q groups failed: %w", sender, err) + return fmt.Errorf("get SetAllowCaller sender %s groups failed: %w", sender, err) } if !containsGroup(groups, r.privilegedGroupID) { - return fmt.Errorf("D-Bus caller %q is not in privileged group %q", sender, privilegedGroup) + return fmt.Errorf("D-Bus caller %s is not in privileged group %s", sender, privilegedGroup) } - if target.UID != senderUID { - return fmt.Errorf("SetAllowCaller sender UID %d does not own target %q with UID %d", senderUID, uniqueName, target.UID) + + targetUID, err := r.service.GetConnUID(uniqueName) + if err != nil { + return fmt.Errorf("get target caller %s UID failed: %w", uniqueName, err) + } + if targetUID != senderUID { + return fmt.Errorf("SetAllowCaller sender UID %d does not own target %s with UID %d", senderUID, uniqueName, targetUID) } senderPID, err := r.service.GetConnPID(string(sender)) if err != nil { - return fmt.Errorf("get SetAllowCaller sender %q PID failed: %w", sender, err) + return fmt.Errorf("get SetAllowCaller sender %s PID failed: %w", sender, err) + } + targetPID, err := r.service.GetConnPID(uniqueName) + if err != nil { + return fmt.Errorf("get target caller %s PID failed: %w", uniqueName, err) } if r.processParent == nil { return errors.New("process ancestry resolver is unavailable") } - isDescendant, err := isProcessDescendant(target.PID, senderPID, r.processParent) + isDescendant, err := isProcessDescendant(targetPID, senderPID, r.processParent) if err != nil { - return fmt.Errorf("verify target caller %q process ancestry failed: %w", uniqueName, err) + return fmt.Errorf("verify target caller %s process ancestry failed: %w", uniqueName, err) } if !isDescendant { return fmt.Errorf( - "target caller %q PID %d is not a descendant of SetAllowCaller sender %q PID %d", - uniqueName, target.PID, sender, senderPID, + "target caller %s PID %d is not a descendant of SetAllowCaller sender %s PID %d", + uniqueName, targetPID, sender, senderPID, ) } return nil @@ -381,76 +365,36 @@ func containsGroup(groups []uint32, target uint32) bool { return false } -// Authorize checks whether the caller identified by its D-Bus sender is -// authorized for the given scope. Registered UID and PID are both rechecked -// to prevent a recycled D-Bus name from inheriting authorization. func (r *AllowCallerRegistry) Authorize(scope string, sender dbus.Sender) (AuthResult, error) { if r == nil { - return AuthError, errors.New("security-loader caller registry is nil") + return AuthDenied, errors.New("security-loader caller registry is nil") } if sender == "" { - return AuthError, errors.New("D-Bus sender is empty") + return AuthDenied, errors.New("D-Bus sender is empty") } uid, err := r.service.GetConnUID(string(sender)) if err != nil { - return AuthError, fmt.Errorf("get caller %q UID failed: %w", sender, err) + return AuthDenied, fmt.Errorf("get caller %s UID failed: %w", sender, err) } if uid == 0 { return AuthOK, nil } r.mu.RLock() - registered, callerExists := r.callers[scope][string(sender)] + scopeCallers, scopeExists := r.callers[scope] + _, callerExists := scopeCallers[string(sender)] r.mu.RUnlock() - if !callerExists { - return AuthPolkit, nil - } - pid, err := r.service.GetConnPID(string(sender)) - if err != nil { - return AuthError, fmt.Errorf("get caller %q PID failed: %w", sender, err) + if !scopeExists || len(scopeCallers) == 0 { + return AuthNotEnabled, nil } - if registered.UID != uid || registered.PID != pid { - logger.Warningf( - "security-loader credentials changed for caller %q in scope %q; falling back to Polkit", - sender, scope, - ) - r.removeCallerIfMatches(scope, string(sender), registered) - return AuthPolkit, nil + if !callerExists { + return AuthDenied, fmt.Errorf("D-Bus caller %s is not authorized for %s", sender, scope) } - return AuthOK, nil } -// removeCallerIfMatches removes only the registration observed by Authorize. -// A concurrent AddCaller may replace it before cleanup starts; comparing the -// recorded credentials prevents that newer registration from being deleted. -// Locks follow the registry-wide persistMu -> mu order to avoid deadlocks. -func (r *AllowCallerRegistry) removeCallerIfMatches(scope, uniqueName string, expected callerInfo) bool { - r.persistMu.Lock() - defer r.persistMu.Unlock() - - r.mu.Lock() - callers := r.callers[scope] - current, exists := callers[uniqueName] - if !exists || current != expected { - r.mu.Unlock() - return false - } - delete(callers, uniqueName) - if len(callers) == 0 { - delete(r.callers, scope) - } - saveErr := r.saveLocked() - r.mu.Unlock() - - if saveErr != nil { - logger.Warningf("failed to persist removal of security-loader caller %q: %q", uniqueName, saveErr.Error()) - } - return true -} - func (r *AllowCallerRegistry) RemoveCaller(uniqueName string) { if r == nil || uniqueName == "" { return @@ -476,18 +420,20 @@ func (r *AllowCallerRegistry) RemoveCaller(uniqueName string) { return } if err := r.saveLocked(); err != nil { - logger.Warningf("failed to persist removal of security-loader caller %q: %q", uniqueName, err.Error()) + logger.Warningf("failed to persist removal of security-loader caller %s: %v", uniqueName, err) } r.mu.Unlock() } func (r *AllowCallerRegistry) saveLocked() error { - state := make(map[string]map[string]callerInfo, len(r.callers)) + state := make(map[string][]string, len(r.callers)) for scope, callers := range r.callers { - state[scope] = make(map[string]callerInfo, len(callers)) - for uniqueName, info := range callers { - state[scope][uniqueName] = info + uniqueNames := make([]string, 0, len(callers)) + for uniqueName := range callers { + uniqueNames = append(uniqueNames, uniqueName) } + sort.Strings(uniqueNames) + state[scope] = uniqueNames } if r.busID == "" { @@ -500,25 +446,6 @@ func (r *AllowCallerRegistry) saveLocked() error { return r.writeState(persisted) } -func createPrivateTempFile(dir string) (*os.File, error) { - const maxAttempts = 10 - var random [16]byte - for attempt := 0; attempt < maxAttempts; attempt++ { - if _, err := rand.Read(random[:]); err != nil { - return nil, fmt.Errorf("generate security-loader state file name failed: %w", err) - } - name := filepath.Join(dir, ".allow-callers-"+hex.EncodeToString(random[:])) - file, err := os.OpenFile(name, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0600) - if err == nil { - return file, nil - } - if !os.IsExist(err) { - return nil, err - } - } - return nil, errors.New("create unique security-loader state file failed") -} - func (r *AllowCallerRegistry) writeState(state persistedState) error { content, err := json.Marshal(state) if err != nil { @@ -529,12 +456,17 @@ func (r *AllowCallerRegistry) writeState(state persistedState) error { if err := os.MkdirAll(dir, 0700); err != nil { return fmt.Errorf("create security-loader runtime directory failed: %w", err) } - tmp, err := createPrivateTempFile(dir) + tmp, err := ioutil.TempFile(dir, ".allow-callers-") if err != nil { return fmt.Errorf("create security-loader state file failed: %w", err) } tmpName := tmp.Name() defer os.Remove(tmpName) + + if err := tmp.Chmod(0600); err != nil { + tmp.Close() + return err + } if _, err := tmp.Write(content); err != nil { tmp.Close() return fmt.Errorf("write security-loader state failed: %w", err) @@ -549,7 +481,7 @@ func (r *AllowCallerRegistry) writeState(state persistedState) error { } func (r *AllowCallerRegistry) load() error { - content, err := os.ReadFile(r.stateFile) + content, err := ioutil.ReadFile(r.stateFile) if err != nil { if os.IsNotExist(err) { return nil @@ -569,7 +501,7 @@ func (r *AllowCallerRegistry) load() error { if scope == "" { continue } - for uniqueName, registered := range callers { + for _, uniqueName := range callers { if !strings.HasPrefix(uniqueName, ":") { continue } @@ -577,19 +509,11 @@ func (r *AllowCallerRegistry) load() error { if err != nil || !hasOwner { continue } - uid, err := r.service.GetConnUID(uniqueName) - if err != nil || uid != registered.UID { - continue - } - pid, err := r.service.GetConnPID(uniqueName) - if err != nil || pid != registered.PID { - continue - } if r.callers[scope] == nil { - r.callers[scope] = make(map[string]callerInfo) + r.callers[scope] = make(map[string]struct{}) } - r.callers[scope][uniqueName] = registered + r.callers[scope][uniqueName] = struct{}{} } } return nil -} +} \ No newline at end of file diff --git a/securityloader/allowcaller_test.go b/securityloader/allowcaller_test.go index 946a07e9c..19d8a3af2 100644 --- a/securityloader/allowcaller_test.go +++ b/securityloader/allowcaller_test.go @@ -8,6 +8,7 @@ import ( "encoding/json" "errors" "fmt" + "io/ioutil" "os" "path/filepath" "strconv" @@ -19,13 +20,12 @@ import ( ) type fakeBusService struct { - owners map[string]bool - uids map[string]uint32 - uidErrors map[string]error - groups map[string][]uint32 - pids map[string]uint32 - parents map[uint32]uint32 - busID string + owners map[string]bool + uids map[string]uint32 + groups map[string][]uint32 + pids map[string]uint32 + parents map[uint32]uint32 + busID string } const testPrivilegedGroupID = 996 @@ -35,9 +35,6 @@ func (s *fakeBusService) NameHasOwner(name string) (bool, error) { } func (s *fakeBusService) GetConnUID(name string) (uint32, error) { - if err := s.uidErrors[name]; err != nil { - return 0, err - } return s.uids[name], nil } @@ -84,47 +81,21 @@ func TestAllowCallerRegistryAuthorize(t *testing.T) { if err := registry.AddCaller(DaemonScope, dbus.Sender(":1.1"), ":1.10"); err != nil { t.Fatal(err) } - result, err := registry.Authorize(DaemonScope, dbus.Sender(":1.10")) - if result != AuthOK || err != nil { - t.Fatalf("registered caller authorization = (%v, %v), want (AuthOK, nil)", result, err) - } - result, err = registry.Authorize(DaemonScope, dbus.Sender(":1.11")) - if result != AuthPolkit || err != nil { - t.Fatalf("unregistered caller authorization = (%v, %v), want (AuthPolkit, nil)", result, err) - } - result, err = registry.Authorize(PowerScope, dbus.Sender(":1.10")) - if result != AuthPolkit || err != nil { - t.Fatalf("caller in unregistered scope authorization = (%v, %v), want (AuthPolkit, nil)", result, err) + result, _ := registry.Authorize(DaemonScope, dbus.Sender(":1.10")) + if result != AuthOK { + t.Fatalf("registered caller was denied") } - result, err = registry.Authorize(PowerScope, dbus.Sender(":1.12")) - if result != AuthOK || err != nil { - t.Fatalf("root caller authorization = (%v, %v), want (AuthOK, nil)", result, err) + result, _ = registry.Authorize(DaemonScope, dbus.Sender(":1.11")) + if result != AuthDenied { + t.Fatal("same-UID unregistered caller was allowed") } -} - -func TestAllowCallerRegistryAuthorizationErrorsDoNotFallBack(t *testing.T) { - uidErr := errors.New("UID lookup failed") - registry := newTestAllowCallerRegistry(&fakeBusService{ - uids: make(map[string]uint32), - uidErrors: map[string]error{":1.20": uidErr}, - }, filepath.Join(t.TempDir(), "allow-callers.json"), testPrivilegedGroupID) - - tests := []struct { - name string - registry *AllowCallerRegistry - sender dbus.Sender - }{ - {name: "nil registry", sender: ":1.20"}, - {name: "empty sender", registry: registry}, - {name: "UID lookup failure", registry: registry, sender: ":1.20"}, + result, _ = registry.Authorize(PowerScope, dbus.Sender(":1.10")) + if result != AuthNotEnabled { + t.Fatal("caller registered for another scope should return AuthNotEnabled") } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - result, err := tt.registry.Authorize(DaemonScope, tt.sender) - if result != AuthError || err == nil { - t.Fatalf("authorization = (%v, %v), want (AuthError, non-nil error)", result, err) - } - }) + result, _ = registry.Authorize(PowerScope, dbus.Sender(":1.12")) + if result != AuthOK { + t.Fatalf("root caller was denied") } } @@ -133,20 +104,19 @@ func TestAllowCallerRegistryPersistenceAndRemoval(t *testing.T) { service := &fakeBusService{ owners: map[string]bool{":1.20": true, ":1.21": false}, uids: map[string]uint32{":1.20": 1000}, - pids: map[string]uint32{":1.20": 120}, groups: make(map[string][]uint32), busID: "bus-a", } content, err := json.Marshal(persistedState{ BusID: "bus-a", - Callers: map[string]map[string]callerInfo{ - DaemonScope: {":1.20": {UID: 1000, PID: 120}, ":1.21": {}}, + Callers: map[string][]string{ + DaemonScope: {":1.20", ":1.21"}, }, }) if err != nil { t.Fatal(err) } - if err := os.WriteFile(stateFile, content, 0600); err != nil { + if err := ioutil.WriteFile(stateFile, content, 0600); err != nil { t.Fatal(err) } @@ -165,39 +135,18 @@ func TestAllowCallerRegistryPersistenceAndRemoval(t *testing.T) { } } -func TestWriteStateUsesPrivatePermissions(t *testing.T) { - dir := t.TempDir() - stateFile := filepath.Join(dir, "allow-callers.json") - registry := &AllowCallerRegistry{stateFile: stateFile, busID: "bus-a"} - if err := registry.writeState(persistedState{BusID: "bus-a"}); err != nil { - t.Fatal(err) - } - info, err := os.Stat(stateFile) - if err != nil { - t.Fatal(err) - } - if got := info.Mode().Perm(); got != 0600 { - t.Fatalf("state file mode = %o, want 600", got) - } - if leftovers, err := filepath.Glob(filepath.Join(dir, ".allow-callers-*")); err != nil { - t.Fatal(err) - } else if len(leftovers) != 0 { - t.Fatalf("temporary state files remain: %v", leftovers) - } -} - func TestAllowCallerRegistryRejectsStateFromAnotherBus(t *testing.T) { stateFile := filepath.Join(t.TempDir(), "allow-callers.json") content, err := json.Marshal(persistedState{ BusID: "old-bus", - Callers: map[string]map[string]callerInfo{ - DaemonScope: {":1.30": {UID: 1000, PID: 130}}, + Callers: map[string][]string{ + DaemonScope: {":1.30"}, }, }) if err != nil { t.Fatal(err) } - if err := os.WriteFile(stateFile, content, 0600); err != nil { + if err := ioutil.WriteFile(stateFile, content, 0600); err != nil { t.Fatal(err) } @@ -255,7 +204,7 @@ func TestAllowCallerRegistryConcurrentAddsPersistAllCallers(t *testing.T) { } } - content, err := os.ReadFile(stateFile) + content, err := ioutil.ReadFile(stateFile) if err != nil { t.Fatal(err) } @@ -388,95 +337,6 @@ func TestAddCallerIsNotVisibleBeforePersistenceSucceeds(t *testing.T) { } } -func TestAllowCallerRegistryTOCTOUProtection(t *testing.T) { - tests := []struct { - name string - mutate func(*fakeBusService) - }{ - { - name: "different UID", - mutate: func(service *fakeBusService) { - service.uids[":1.10"] = 1001 - }, - }, - { - name: "same UID different process", - mutate: func(service *fakeBusService) { - service.pids[":1.10"] = 111 - }, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - service := &fakeBusService{ - owners: map[string]bool{":1.1": true, ":1.10": true}, - uids: map[string]uint32{":1.1": 1000, ":1.10": 1000}, - groups: map[string][]uint32{":1.1": {testPrivilegedGroupID}}, - pids: map[string]uint32{":1.1": 101, ":1.10": 110}, - parents: map[uint32]uint32{110: 101}, - busID: "bus-a", - } - registry := newTestAllowCallerRegistry( - service, - filepath.Join(t.TempDir(), "allow-callers.json"), - testPrivilegedGroupID, - ) - - if err := registry.AddCaller(DaemonScope, dbus.Sender(":1.1"), ":1.10"); err != nil { - t.Fatal(err) - } - result, err := registry.Authorize(DaemonScope, dbus.Sender(":1.10")) - if result != AuthOK || err != nil { - t.Fatalf("authorization before recycling = (%v, %v), want (AuthOK, nil)", result, err) - } - - tt.mutate(service) - result, err = registry.Authorize(DaemonScope, dbus.Sender(":1.10")) - if result != AuthPolkit || err != nil { - t.Fatalf("authorization after recycling = (%v, %v), want (AuthPolkit, nil)", result, err) - } - }) - } -} - -func TestRemoveCallerIfMatchesPreservesReregistration(t *testing.T) { - service := &fakeBusService{ - owners: map[string]bool{":1.1": true, ":1.10": true}, - uids: map[string]uint32{":1.1": 1000, ":1.10": 1000}, - groups: map[string][]uint32{":1.1": {testPrivilegedGroupID}}, - pids: map[string]uint32{":1.1": 101, ":1.10": 110}, - parents: map[uint32]uint32{110: 101}, - busID: "bus-a", - } - registry := newTestAllowCallerRegistry( - service, - filepath.Join(t.TempDir(), "allow-callers.json"), - testPrivilegedGroupID, - ) - if err := registry.AddCaller(DaemonScope, dbus.Sender(":1.1"), ":1.10"); err != nil { - t.Fatal(err) - } - - registry.mu.RLock() - stale := registry.callers[DaemonScope][":1.10"] - registry.mu.RUnlock() - - service.pids[":1.10"] = 111 - service.parents[111] = 101 - if err := registry.AddCaller(DaemonScope, dbus.Sender(":1.1"), ":1.10"); err != nil { - t.Fatal(err) - } - if registry.removeCallerIfMatches(DaemonScope, ":1.10", stale) { - t.Fatal("stale cleanup removed a newer registration") - } - - result, err := registry.Authorize(DaemonScope, dbus.Sender(":1.10")) - if result != AuthOK || err != nil { - t.Fatalf("new registration authorization = (%v, %v), want (AuthOK, nil)", result, err) - } -} - func TestIsProcessDescendant(t *testing.T) { parents := map[uint32]uint32{400: 300, 300: 200, 200: 1, 1: 0} processParent := func(pid uint32) (uint32, error) { @@ -532,4 +392,4 @@ func TestGetProcessGroupsIncludesEffectiveGroup(t *testing.T) { if !containsGroup(groups, uint32(os.Getegid())) { t.Fatalf("effective gid %d was not found in process credentials %v", os.Getegid(), groups) } -} +} \ No newline at end of file diff --git a/securityloader/handshake.go b/securityloader/handshake.go index 901930e68..fbb7f400b 100644 --- a/securityloader/handshake.go +++ b/securityloader/handshake.go @@ -129,7 +129,7 @@ func Handshake(args []string, destinations []Destination) ([]string, bool, error return cleanedArgs, true, fmt.Errorf("decode security-loader response failed: %w", err) } if !response.Result { - return cleanedArgs, true, fmt.Errorf("security-loader authorization failed: %q", response.Message) + return cleanedArgs, true, fmt.Errorf("security-loader authorization failed: %s", response.Message) } return cleanedArgs, true, nil } @@ -208,4 +208,4 @@ func readSecurityLoaderResponse(reader io.Reader) ([]byte, error) { return nil, fmt.Errorf("response exceeds %d bytes", maxSecurityLoaderResponseSize) } return data, nil -} +} \ No newline at end of file diff --git a/securityloader/handshake_test.go b/securityloader/handshake_test.go index 4962627d5..825505b36 100644 --- a/securityloader/handshake_test.go +++ b/securityloader/handshake_test.go @@ -121,4 +121,4 @@ func TestHandshakeReportsLoaderState(t *testing.T) { if !loaded { t.Fatal("invalid injected arguments did not report security-loader invocation") } -} +} \ No newline at end of file diff --git a/securityloader/polkit.go b/securityloader/polkit.go deleted file mode 100644 index 04bd8669a..000000000 --- a/securityloader/polkit.go +++ /dev/null @@ -1,54 +0,0 @@ -// SPDX-FileCopyrightText: 2026 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: GPL-3.0-or-later - -package securityloader - -import ( - "errors" - - "github.com/godbus/dbus/v5" - polkit "github.com/linuxdeepin/go-dbus-factory/system/org.freedesktop.policykit1" -) - -// CheckPolkitAuth checks whether the caller on the given system bus connection -// is authorized for the specified Polkit action. Returns true if authorized, -// false if denied, and any error encountered. -// -// This is a shared helper that replaces duplicated per-package auth functions. -// Callers should pass their existing service.Conn() to avoid re-establishing -// a system bus connection on every call. -func CheckPolkitAuth(conn *dbus.Conn, sysBusName, actionID string) (bool, error) { - authority := polkit.NewAuthority(conn) - subject := polkit.MakeSubject(polkit.SubjectKindSystemBusName) - subject.SetDetail("name", sysBusName) - result, err := authority.CheckAuthorization(0, subject, actionID, - nil, polkit.CheckAuthorizationFlagsAllowUserInteraction, "") - if err != nil { - return false, err - } - return result.IsAuthorized, nil -} - -// AuthorizeWithPolkit applies the caller registry and falls back to Polkit -// only when the caller is not registered by security-loader. -func AuthorizeWithPolkit(registry *AllowCallerRegistry, scope string, sender dbus.Sender, conn *dbus.Conn, actionID string) error { - result, err := registry.Authorize(scope, sender) - switch result { - case AuthError: - return err - case AuthPolkit: - ok, err := CheckPolkitAuth(conn, string(sender), actionID) - if err != nil { - return err - } - if !ok { - return errors.New("access denied") - } - return nil - case AuthOK: - return nil - default: - return errors.New("unknown security-loader authorization result") - } -} diff --git a/system/airplane_mode1/manager.go b/system/airplane_mode1/manager.go index 0b0e10131..e41568a06 100644 --- a/system/airplane_mode1/manager.go +++ b/system/airplane_mode1/manager.go @@ -1,17 +1,18 @@ -// SPDX-FileCopyrightText: 2022-2026 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: GPL-3.0-or-later package airplane_mode import ( + "errors" "sync" "time" "github.com/godbus/dbus/v5" "github.com/linuxdeepin/dde-daemon/securityloader" networkmanager "github.com/linuxdeepin/go-dbus-factory/system/org.freedesktop.networkmanager" - + polkit "github.com/linuxdeepin/go-dbus-factory/system/org.freedesktop.policykit1" "github.com/linuxdeepin/go-lib/dbusutil" ) @@ -79,21 +80,19 @@ func (mgr *Manager) SetAllowCaller(sender dbus.Sender, uniqueName string) *dbus. return dbusutil.ToError(mgr.allowCallers.AddCaller(securityloader.AirplaneModeScope, sender, uniqueName)) } -func (mgr *Manager) authorize(sender dbus.Sender) error { - return securityloader.AuthorizeWithPolkit( - mgr.allowCallers, - securityloader.AirplaneModeScope, - sender, - mgr.service.Conn(), - actionId, - ) -} - // Enable enable or disable *Airplane Mode*, isn't enable the devices func (mgr *Manager) Enable(sender dbus.Sender, enableAirplaneMode bool) *dbus.Error { - if err := mgr.authorize(sender); err != nil { - logger.Warningf("Enable authorization failed: %q", err.Error()) - return dbusutil.ToError(err) + result, _ := mgr.allowCallers.Authorize(securityloader.AirplaneModeScope, sender) + switch result { + case securityloader.AuthDenied: + logger.Warning("Enable access denied") + return dbusutil.ToError(errors.New("access denied")) + case securityloader.AuthNotEnabled: + // Fall back to Polkit when not launched via security-loader. + if er := checkAuthorization(actionId, string(sender)); er != nil { + logger.Warningf("checkAuthorization failed, err: %v, actionId=%v", er, actionId) + return dbusutil.ToError(er) + } } // try to block @@ -108,9 +107,15 @@ func (mgr *Manager) Enable(sender dbus.Sender, enableAirplaneMode bool) *dbus.Er // EnableWifi enable or disable *Airplane Mode* for wlan, isn't enable the wlan devices func (mgr *Manager) EnableWifi(sender dbus.Sender, enableAirplaneMode bool) *dbus.Error { - if err := mgr.authorize(sender); err != nil { - logger.Warningf("EnableWifi authorization failed: %q", err.Error()) - return dbusutil.ToError(err) + result, _ := mgr.allowCallers.Authorize(securityloader.AirplaneModeScope, sender) + switch result { + case securityloader.AuthDenied: + logger.Warning("EnableWifi access denied") + return dbusutil.ToError(errors.New("access denied")) + case securityloader.AuthNotEnabled: + if er := checkAuthorization(actionId, string(sender)); er != nil { + return dbusutil.ToError(er) + } } // try to block @@ -125,9 +130,15 @@ func (mgr *Manager) EnableWifi(sender dbus.Sender, enableAirplaneMode bool) *dbu // EnableBluetooth enable or disable *Airplane Mode* for bluetooth, isn't enable the bluetooth devices func (mgr *Manager) EnableBluetooth(sender dbus.Sender, enableAirplaneMode bool) *dbus.Error { - if err := mgr.authorize(sender); err != nil { - logger.Warningf("EnableBluetooth authorization failed: %q", err.Error()) - return dbusutil.ToError(err) + result, _ := mgr.allowCallers.Authorize(securityloader.AirplaneModeScope, sender) + switch result { + case securityloader.AuthDenied: + logger.Warning("EnableBluetooth access denied") + return dbusutil.ToError(errors.New("access denied")) + case securityloader.AuthNotEnabled: + if er := checkAuthorization(actionId, string(sender)); er != nil { + return dbusutil.ToError(er) + } } // try to block @@ -215,6 +226,27 @@ func (mgr *Manager) block(typ rfkillType, enableAirplaneMode bool) error { return rfkillAction(typ, state) } + +func checkAuthorization(actionId string, sysBusName string) error { + systemBus, err := dbus.SystemBus() + if err != nil { + return err + } + authority := polkit.NewAuthority(systemBus) + subject := polkit.MakeSubject(polkit.SubjectKindSystemBusName) + subject.SetDetail("name", sysBusName) + + ret, err := authority.CheckAuthorization(0, subject, actionId, + nil, polkit.CheckAuthorizationFlagsAllowUserInteraction, "") + if err != nil { + return err + } + if !ret.IsAuthorized { + return errors.New("not authorized") + } + return nil +} + func (mgr *Manager) listenWirelessEnabled() { _ = mgr.nmManager.WirelessEnabled().ConnectChanged(func(hasValue bool, wifiEnable bool) { if !hasValue { diff --git a/system/inputdevices1/inputdevices_ifc.go b/system/inputdevices1/inputdevices_ifc.go index f8631c9b5..2e4af663c 100644 --- a/system/inputdevices1/inputdevices_ifc.go +++ b/system/inputdevices1/inputdevices_ifc.go @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2018-2026 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/system/inputdevices1/touchpad.go b/system/inputdevices1/touchpad.go index 681f08598..6bb927937 100644 --- a/system/inputdevices1/touchpad.go +++ b/system/inputdevices1/touchpad.go @@ -5,15 +5,16 @@ package inputdevices1 import ( + "errors" "os" "os/exec" "path/filepath" "strings" "github.com/godbus/dbus/v5" - "github.com/linuxdeepin/dde-daemon/securityloader" configManager "github.com/linuxdeepin/go-dbus-factory/org.desktopspec.ConfigManager" - + "github.com/linuxdeepin/dde-daemon/securityloader" + polkit "github.com/linuxdeepin/go-dbus-factory/system/org.freedesktop.policykit1" "github.com/linuxdeepin/go-lib/dbusutil" ) @@ -48,18 +49,18 @@ SUBSYSTEM=="input", KERNEL=="event*", ATTRS{name}=="*ps/2*", ENV{LIBINPUT_IGNORE } type Touchpad struct { - service *dbusutil.Service - allowCallers *securityloader.AllowCallerRegistry - Enable bool - DeviceList []string - udevMonitor *udevMonitor + service *dbusutil.Service + allowCallers *securityloader.AllowCallerRegistry + Enable bool + DeviceList []string + udevMonitor *udevMonitor } func newTouchpad(service *dbusutil.Service, allowCallers *securityloader.AllowCallerRegistry) *Touchpad { t := &Touchpad{ - service: service, + service: service, allowCallers: allowCallers, - Enable: getDsgConf(), + Enable: getDsgConf(), } // 初始化 udev 监听器 @@ -84,18 +85,18 @@ func (t *Touchpad) handleDeviceChange(devices []string) { } func (t *Touchpad) SetTouchpadEnable(sender dbus.Sender, enabled bool) *dbus.Error { - err := securityloader.AuthorizeWithPolkit( - t.allowCallers, - securityloader.InputDevicesScope, - sender, - t.service.Conn(), - "org.deepin.dde.inputdevices.set-touchpad", - ) - if err != nil { - logger.Warningf("SetTouchpadEnable authorization failed: %q", err.Error()) - return dbusutil.ToError(err) + result, _ := t.allowCallers.Authorize(securityloader.InputDevicesScope, sender) + switch result { + case securityloader.AuthDenied: + logger.Warning("SetTouchpadEnable access denied") + return dbusutil.ToError(errors.New("access denied")) + case securityloader.AuthNotEnabled: + if ok, er := checkTouchpadAuth(string(sender)); !ok || er != nil { + return dbusutil.ToError(er) + } } - return dbusutil.ToError(t.setTouchpadEnable(enabled)) + err := t.setTouchpadEnable(enabled) + return dbusutil.ToError(err) } func (t *Touchpad) setTouchpadEnable(enabled bool) error { @@ -327,3 +328,20 @@ func (t *Touchpad) destroy() { t.udevMonitor = nil } } + +func checkTouchpadAuth(sysBusName string) (bool, error) { + systemBus, err := dbus.SystemBus() + if err != nil { + return false, err + } + authority := polkit.NewAuthority(systemBus) + subject := polkit.MakeSubject(polkit.SubjectKindSystemBusName) + subject.SetDetail("name", sysBusName) + result, err := authority.CheckAuthorization(0, subject, + "org.deepin.dde.inputdevices.set-touchpad", + nil, polkit.CheckAuthorizationFlagsAllowUserInteraction, "") + if err != nil { + return false, err + } + return result.IsAuthorized, nil +} diff --git a/system/power1/manager_ifc.go b/system/power1/manager_ifc.go index ba52cbde3..6b71ed481 100644 --- a/system/power1/manager_ifc.go +++ b/system/power1/manager_ifc.go @@ -10,7 +10,7 @@ import ( dbus "github.com/godbus/dbus/v5" "github.com/linuxdeepin/dde-daemon/securityloader" - + polkit "github.com/linuxdeepin/go-dbus-factory/system/org.freedesktop.policykit1" "github.com/linuxdeepin/go-lib/dbusutil" ) @@ -113,16 +113,15 @@ func (m *Manager) SetAllowCaller(sender dbus.Sender, uniqueName string) *dbus.Er } func (m *Manager) SetTlpMode(sender dbus.Sender, mode string) *dbus.Error { - err := securityloader.AuthorizeWithPolkit( - m.allowCallers, - securityloader.PowerScope, - sender, - m.service.Conn(), - "org.deepin.dde.power.doAction", - ) - if err != nil { - logger.Warningf("SetTlpMode authorization failed: %q", err.Error()) - return dbusutil.ToError(err) + result, _ := m.allowCallers.Authorize(securityloader.PowerScope, sender) + switch result { + case securityloader.AuthDenied: + logger.Warning("SetTlpMode access denied") + return dbusutil.ToError(errors.New("access denied")) + case securityloader.AuthNotEnabled: + if ok, er := checkPowerAuth(string(sender)); !ok || er != nil { + return dbusutil.ToError(er) + } } logger.Info("SetTlpMode : ", mode) return dbusutil.ToError(m.setTlpMode(mode)) @@ -134,6 +133,23 @@ func (m *Manager) SetShortIdleState(state bool) *dbus.Error { return nil } +func checkPowerAuth(sysBusName string) (bool, error) { + systemBus, err := dbus.SystemBus() + if err != nil { + return false, err + } + authority := polkit.NewAuthority(systemBus) + subject := polkit.MakeSubject(polkit.SubjectKindSystemBusName) + subject.SetDetail("name", sysBusName) + result, err := authority.CheckAuthorization(0, subject, + "org.deepin.dde.power.doAction", + nil, polkit.CheckAuthorizationFlagsAllowUserInteraction, "") + if err != nil { + return false, err + } + return result.IsAuthorized, nil +} + func (m *Manager) LockCpuFreq(governor string, lockTime int32) *dbus.Error { // TODO 改用tlp // currentGovernor, err := m.cpus.GetGovernor() From 426f311afd2efc95e9ed7f021e4e2669269ece98 Mon Sep 17 00:00:00 2001 From: fuleyi Date: Wed, 19 Aug 2026 13:26:59 +0800 Subject: [PATCH 3/9] =?UTF-8?q?Revert=20"fix:=20=E4=BF=AE=E5=A4=8D=20dde-s?= =?UTF-8?q?ession-daemon=20=E7=9A=84=20security-loader=20=E5=90=AF?= =?UTF-8?q?=E5=8A=A8=E6=B5=81=E7=A8=8B"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit ee600cd3994ce25b575ba737cba481ec9d7266bf. --- misc/scripts/dde-session-daemon-loader-wrapper | 18 ++---------------- .../services/system/dde-system-daemon.service | 5 ----- .../user/org.dde.session.Daemon1.service | 8 +++----- 3 files changed, 5 insertions(+), 26 deletions(-) diff --git a/misc/scripts/dde-session-daemon-loader-wrapper b/misc/scripts/dde-session-daemon-loader-wrapper index a3117e742..2b528d62f 100755 --- a/misc/scripts/dde-session-daemon-loader-wrapper +++ b/misc/scripts/dde-session-daemon-loader-wrapper @@ -1,18 +1,4 @@ #!/bin/bash -set -u -PATH=/usr/sbin:/usr/bin:/sbin:/bin -export PATH - -REAL_BINARY="/usr/libexec/deepin/dde-session-daemon" -LOADER="/usr/bin/deepin-security-loader" -LOADER_EXEC="/usr/bin/deepin-security-loader-exec" - -if [ -x "$LOADER" ] && [ -x "$LOADER_EXEC" ] && \ - getcap "$LOADER_EXEC" 2>/dev/null | grep -q cap_setgid; then - exec "$LOADER" --group deepin-daemon -- "$REAL_BINARY" "$@" -fi - -# Type=forking requires the wrapper to leave a child for systemd to adopt. -"$REAL_BINARY" "$@" & -exit 0 +exec /usr/bin/deepin-security-loader --group deepin-daemon -- \ + /usr/libexec/deepin/dde-session-daemon "$@" diff --git a/misc/systemd/services/system/dde-system-daemon.service b/misc/systemd/services/system/dde-system-daemon.service index 46fccf339..8f006c303 100644 --- a/misc/systemd/services/system/dde-system-daemon.service +++ b/misc/systemd/services/system/dde-system-daemon.service @@ -18,11 +18,6 @@ Environment=GVFS_REMOTE_VOLUME_MONITOR_IGNORE=1 ProtectSystem=strict -RuntimeDirectory=dde-daemon -RuntimeDirectoryMode=0777 -RuntimeDirectoryPreserve=yes -ReadWritePaths=/run/dde-daemon - # TODO runuser 需要改配置 # NoNewPrivileges=yes # 部分数据需要写到home下 diff --git a/misc/systemd/services/user/org.dde.session.Daemon1.service b/misc/systemd/services/user/org.dde.session.Daemon1.service index ff1ed8a86..31c0b7f74 100644 --- a/misc/systemd/services/user/org.dde.session.Daemon1.service +++ b/misc/systemd/services/user/org.dde.session.Daemon1.service @@ -11,12 +11,10 @@ Wants=treeland-xwayland.service After=treeland-xwayland.service [Service] -# deepin-security-loader exits after authorization; adopt the remaining daemon. -Type=forking -GuessMainPID=yes +Type=dbus +BusName=org.deepin.dde.Daemon1 ExecStart=/usr/lib/deepin-daemon/dde-session-daemon -# Keep the original D-Bus readiness semantics before starting dependent units. -ExecStartPost=/usr/bin/gdbus wait --session --timeout=30 org.deepin.dde.Daemon1 Slice=app.slice Restart=on-failure +NotifyAccess=main RestartSec=1s \ No newline at end of file From 00aa2c072d9ce29393c9edc542f38e506f8d3647 Mon Sep 17 00:00:00 2001 From: fuleyi Date: Wed, 19 Aug 2026 13:27:12 +0800 Subject: [PATCH 4/9] =?UTF-8?q?Revert=20"feat:=20=E4=B8=BA=E6=9C=AA?= =?UTF-8?q?=E5=90=AF=E7=94=A8=20security-loader=20=E7=9A=84=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=E5=A2=9E=E5=8A=A0=20polkit=20=E6=8F=90=E6=9D=83?= =?UTF-8?q?=E5=9B=9E=E9=80=80"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 62b0cb35b690456d2836826dce8f253fca983e31. --- Makefile | 2 +- bin/dde-system-daemon/power.go | 39 +++---------------- .../org.deepin.dde.airplane.policy | 2 +- .../org.deepin.dde.hardware-control.policy.in | 38 ------------------ .../polkit-action/org.deepin.dde.power.policy | 2 +- system/inputdevices1/touchpad.go | 29 ++------------ system/power1/manager_ifc.go | 29 ++------------ 7 files changed, 15 insertions(+), 126 deletions(-) delete mode 100644 misc/polkit-action/org.deepin.dde.hardware-control.policy.in diff --git a/Makefile b/Makefile index cde901863..8ca8b4cfc 100644 --- a/Makefile +++ b/Makefile @@ -141,7 +141,7 @@ clean-po: mv "$$po.tmp" "$$po"; \ done -POLICIES=accounts grub2 daemon.system hardware-control +POLICIES=accounts grub2 daemon.system ts: for i in $(POLICIES); do \ deepin-policy-ts-convert policy2ts misc/polkit-action/org.deepin.dde.$$i.policy.in misc/ts/org.deepin.dde.$$i.policy; \ diff --git a/bin/dde-system-daemon/power.go b/bin/dde-system-daemon/power.go index 52a8e1837..439c7e2ee 100644 --- a/bin/dde-system-daemon/power.go +++ b/bin/dde-system-daemon/power.go @@ -16,7 +16,6 @@ import ( "github.com/godbus/dbus/v5" configManager "github.com/linuxdeepin/go-dbus-factory/org.desktopspec.ConfigManager" "github.com/linuxdeepin/dde-daemon/securityloader" - polkit "github.com/linuxdeepin/go-dbus-factory/system/org.freedesktop.policykit1" "github.com/linuxdeepin/go-lib/dbusutil" "github.com/linuxdeepin/go-lib/utils" ) @@ -180,14 +179,9 @@ func (d *Daemon) SetAllowCaller(sender dbus.Sender, uniqueName string) *dbus.Err func (d *Daemon) SetIdleState(sender dbus.Sender, state bool) *dbus.Error { result, _ := d.allowCallers.Authorize(securityloader.DaemonScope, sender) - switch result { - case securityloader.AuthDenied: - logger.Warning("SetIdleState access denied") - return dbusutil.ToError(errors.New("access denied")) - case securityloader.AuthNotEnabled: - if ok, er := checkDaemonAuth(string(sender), "org.deepin.dde.daemon.set-idle-state"); !ok || er != nil { - return dbusutil.ToError(er) - } + if result == securityloader.AuthDenied { + logger.Warning("SetIdleState access denied:", err) + return dbusutil.ToError(err) } logger.Infof("SetIdleState %s try set state: %v", d.idleStatePath, state) return dbusutil.ToError(d.setState(d.idleStatePath, state)) @@ -195,31 +189,10 @@ func (d *Daemon) SetIdleState(sender dbus.Sender, state bool) *dbus.Error { func (d *Daemon) SetScreenState(sender dbus.Sender, state bool) *dbus.Error { result, _ := d.allowCallers.Authorize(securityloader.DaemonScope, sender) - switch result { - case securityloader.AuthDenied: - logger.Warning("SetScreenState access denied") - return dbusutil.ToError(errors.New("access denied")) - case securityloader.AuthNotEnabled: - if ok, er := checkDaemonAuth(string(sender), "org.deepin.dde.daemon.set-screen-state"); !ok || er != nil { - return dbusutil.ToError(er) - } + if result == securityloader.AuthDenied { + logger.Warning("SetScreenState access denied:", err) + return dbusutil.ToError(err) } logger.Infof("SetScreenState %s try set state: %v", d.idleScreenStatePath, state) return dbusutil.ToError(d.setState(d.idleScreenStatePath, state)) } - -func checkDaemonAuth(sysBusName, actionId string) (bool, error) { - systemBus, err := dbus.SystemBus() - if err != nil { - return false, err - } - authority := polkit.NewAuthority(systemBus) - subject := polkit.MakeSubject(polkit.SubjectKindSystemBusName) - subject.SetDetail("name", sysBusName) - result, err := authority.CheckAuthorization(0, subject, actionId, - nil, polkit.CheckAuthorizationFlagsAllowUserInteraction, "") - if err != nil { - return false, err - } - return result.IsAuthorized, nil -} diff --git a/misc/polkit-action/org.deepin.dde.airplane.policy b/misc/polkit-action/org.deepin.dde.airplane.policy index 0aa41788e..14833a94c 100644 --- a/misc/polkit-action/org.deepin.dde.airplane.policy +++ b/misc/polkit-action/org.deepin.dde.airplane.policy @@ -12,7 +12,7 @@ no no - auth_admin_keep + yes diff --git a/misc/polkit-action/org.deepin.dde.hardware-control.policy.in b/misc/polkit-action/org.deepin.dde.hardware-control.policy.in deleted file mode 100644 index 21cd4e5b3..000000000 --- a/misc/polkit-action/org.deepin.dde.hardware-control.policy.in +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - Set idle state - Authentication is required to set idle state - - no - no - auth_admin_keep - - - - - Set screen state - Authentication is required to set screen state - - no - no - auth_admin_keep - - - - - Enable or disable touchpad - Authentication is required to enable or disable touchpad - - no - no - auth_admin_keep - - - \ No newline at end of file diff --git a/misc/polkit-action/org.deepin.dde.power.policy b/misc/polkit-action/org.deepin.dde.power.policy index ea6fc4587..418e0aff4 100644 --- a/misc/polkit-action/org.deepin.dde.power.policy +++ b/misc/polkit-action/org.deepin.dde.power.policy @@ -10,7 +10,7 @@ no no - auth_admin_keep + auth_admin Check Authentication Authentication is required to perform this action diff --git a/system/inputdevices1/touchpad.go b/system/inputdevices1/touchpad.go index 6bb927937..df6a78a13 100644 --- a/system/inputdevices1/touchpad.go +++ b/system/inputdevices1/touchpad.go @@ -14,7 +14,6 @@ import ( "github.com/godbus/dbus/v5" configManager "github.com/linuxdeepin/go-dbus-factory/org.desktopspec.ConfigManager" "github.com/linuxdeepin/dde-daemon/securityloader" - polkit "github.com/linuxdeepin/go-dbus-factory/system/org.freedesktop.policykit1" "github.com/linuxdeepin/go-lib/dbusutil" ) @@ -86,14 +85,9 @@ func (t *Touchpad) handleDeviceChange(devices []string) { func (t *Touchpad) SetTouchpadEnable(sender dbus.Sender, enabled bool) *dbus.Error { result, _ := t.allowCallers.Authorize(securityloader.InputDevicesScope, sender) - switch result { - case securityloader.AuthDenied: - logger.Warning("SetTouchpadEnable access denied") - return dbusutil.ToError(errors.New("access denied")) - case securityloader.AuthNotEnabled: - if ok, er := checkTouchpadAuth(string(sender)); !ok || er != nil { - return dbusutil.ToError(er) - } + if result == securityloader.AuthDenied { + logger.Warning("SetTouchpadEnable access denied:", err) + return dbusutil.ToError(err) } err := t.setTouchpadEnable(enabled) return dbusutil.ToError(err) @@ -328,20 +322,3 @@ func (t *Touchpad) destroy() { t.udevMonitor = nil } } - -func checkTouchpadAuth(sysBusName string) (bool, error) { - systemBus, err := dbus.SystemBus() - if err != nil { - return false, err - } - authority := polkit.NewAuthority(systemBus) - subject := polkit.MakeSubject(polkit.SubjectKindSystemBusName) - subject.SetDetail("name", sysBusName) - result, err := authority.CheckAuthorization(0, subject, - "org.deepin.dde.inputdevices.set-touchpad", - nil, polkit.CheckAuthorizationFlagsAllowUserInteraction, "") - if err != nil { - return false, err - } - return result.IsAuthorized, nil -} diff --git a/system/power1/manager_ifc.go b/system/power1/manager_ifc.go index 6b71ed481..fd51bea71 100644 --- a/system/power1/manager_ifc.go +++ b/system/power1/manager_ifc.go @@ -10,7 +10,6 @@ import ( dbus "github.com/godbus/dbus/v5" "github.com/linuxdeepin/dde-daemon/securityloader" - polkit "github.com/linuxdeepin/go-dbus-factory/system/org.freedesktop.policykit1" "github.com/linuxdeepin/go-lib/dbusutil" ) @@ -114,14 +113,9 @@ func (m *Manager) SetAllowCaller(sender dbus.Sender, uniqueName string) *dbus.Er func (m *Manager) SetTlpMode(sender dbus.Sender, mode string) *dbus.Error { result, _ := m.allowCallers.Authorize(securityloader.PowerScope, sender) - switch result { - case securityloader.AuthDenied: - logger.Warning("SetTlpMode access denied") - return dbusutil.ToError(errors.New("access denied")) - case securityloader.AuthNotEnabled: - if ok, er := checkPowerAuth(string(sender)); !ok || er != nil { - return dbusutil.ToError(er) - } + if result == securityloader.AuthDenied { + logger.Warning("SetTlpMode access denied:", err) + return dbusutil.ToError(err) } logger.Info("SetTlpMode : ", mode) return dbusutil.ToError(m.setTlpMode(mode)) @@ -133,23 +127,6 @@ func (m *Manager) SetShortIdleState(state bool) *dbus.Error { return nil } -func checkPowerAuth(sysBusName string) (bool, error) { - systemBus, err := dbus.SystemBus() - if err != nil { - return false, err - } - authority := polkit.NewAuthority(systemBus) - subject := polkit.MakeSubject(polkit.SubjectKindSystemBusName) - subject.SetDetail("name", sysBusName) - result, err := authority.CheckAuthorization(0, subject, - "org.deepin.dde.power.doAction", - nil, polkit.CheckAuthorizationFlagsAllowUserInteraction, "") - if err != nil { - return false, err - } - return result.IsAuthorized, nil -} - func (m *Manager) LockCpuFreq(governor string, lockTime int32) *dbus.Error { // TODO 改用tlp // currentGovernor, err := m.cpus.GetGovernor() From ba17b772e25c837d8af46e28176375281e5f317b Mon Sep 17 00:00:00 2001 From: fuleyi Date: Wed, 19 Aug 2026 13:27:23 +0800 Subject: [PATCH 5/9] =?UTF-8?q?Revert=20"feat:=20=E6=B7=BB=E5=8A=A0=20org.?= =?UTF-8?q?deepin.dde.LocaleHelper1=20=E5=88=B0=E5=AE=89=E5=85=A8=E5=8A=A0?= =?UTF-8?q?=E8=BD=BD=E7=9B=AE=E6=A0=87=E5=88=97=E8=A1=A8"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 24b3140ca1d1418ecc5c3878c7a75374ecc8d02a. --- Makefile | 6 -- bin/langselector/main.go | 6 +- debian/dde-daemon.lintian-overrides | 2 +- langselector1/securityloader.go | 93 ------------------------ misc/scripts/langselector-loader-wrapper | 4 - rpm/dde-daemon.spec | 10 +-- 6 files changed, 6 insertions(+), 115 deletions(-) delete mode 100644 langselector1/securityloader.go delete mode 100755 misc/scripts/langselector-loader-wrapper diff --git a/Makefile b/Makefile index 8ca8b4cfc..121a26419 100644 --- a/Makefile +++ b/Makefile @@ -167,16 +167,10 @@ install: build install-dde-data install-icons cp -f out/bin/* ${DESTDIR}${PREFIX}/lib/deepin-daemon/ rm -f ${DESTDIR}${PREFIX}/lib/deepin-daemon/dde-session-daemon - mkdir -pv ${DESTDIR}${PREFIX}/libexec/deepin cp -f out/bin/dde-session-daemon ${DESTDIR}${PREFIX}/libexec/deepin/ install -m755 misc/scripts/dde-session-daemon-loader-wrapper \ ${DESTDIR}${PREFIX}/lib/deepin-daemon/dde-session-daemon - rm -f ${DESTDIR}${PREFIX}/lib/deepin-daemon/langselector - cp -f out/bin/langselector ${DESTDIR}${PREFIX}/libexec/deepin/ - install -m755 misc/scripts/langselector-loader-wrapper \ - ${DESTDIR}${PREFIX}/lib/deepin-daemon/langselector - mkdir -pv ${DESTDIR}${PREFIX}/share/locale cp -r out/locale/* ${DESTDIR}${PREFIX}/share/locale diff --git a/bin/langselector/main.go b/bin/langselector/main.go index 6260f63e8..459f36d23 100644 --- a/bin/langselector/main.go +++ b/bin/langselector/main.go @@ -5,17 +5,13 @@ package main import ( - "os" - "github.com/linuxdeepin/dde-daemon/langselector1" "github.com/linuxdeepin/go-lib/gettext" ) func main() { - langselector.DoSecurityLoader(os.Args) - gettext.InitI18n() gettext.BindTextdomainCodeset("dde-daemon", "UTF-8") gettext.Textdomain("dde-daemon") langselector.Run() -} \ No newline at end of file +} diff --git a/debian/dde-daemon.lintian-overrides b/debian/dde-daemon.lintian-overrides index 610add317..86ba68772 100644 --- a/debian/dde-daemon.lintian-overrides +++ b/debian/dde-daemon.lintian-overrides @@ -7,7 +7,7 @@ dde-daemon: unstripped-binary-or-object usr/lib/deepin-daemon/default-file-manag dde-daemon: unstripped-binary-or-object usr/lib/deepin-daemon/default-terminal dde-daemon: unstripped-binary-or-object usr/lib/deepin-daemon/desktop-toggle dde-daemon: unstripped-binary-or-object usr/lib/deepin-daemon/grub2 -dde-daemon: unstripped-binary-or-object usr/libexec/deepin/langselector +dde-daemon: unstripped-binary-or-object usr/lib/deepin-daemon/langselector dde-daemon: unstripped-binary-or-object usr/lib/deepin-daemon/search dde-daemon: unstripped-binary-or-object usr/lib/deepin-daemon/soundeffect dde-daemon: unstripped-binary-or-object usr/lib/deepin-daemon/theme-thumb-tool diff --git a/langselector1/securityloader.go b/langselector1/securityloader.go deleted file mode 100644 index ceca6d74d..000000000 --- a/langselector1/securityloader.go +++ /dev/null @@ -1,93 +0,0 @@ -// SPDX-FileCopyrightText: 2026 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: GPL-3.0-or-later - -package langselector - -import ( - "fmt" - "os/user" - - "github.com/godbus/dbus/v5" - "github.com/linuxdeepin/dde-daemon/securityloader" -) - -var defaultDestList = []securityloader.Destination{ - { - DBusName: "org.deepin.dde.LocaleHelper1", - DBusPath: "/org/deepin/dde/LocaleHelper1", - DBusInterface: "org.deepin.dde.LocaleHelper1", - }, - { - DBusName: "org.deepin.dde.Lastore1", - DBusPath: "/org/deepin/dde/Lastore1", - DBusInterface: "org.deepin.dde.Lastore1.Manager", - }, -} - -func DoSecurityLoader(args []string) { - // 构建 destList,包括 lastore 和 accounts - destList := buildDestList() - - _, loaded, err := securityloader.Handshake(args, destList) - if err != nil { - if loaded { - logger.Warning("security loader handshake failed:", err) - } else { - logger.Warning("security loader handshake skipped:", err) - } - } -} - -// buildDestList 构建需要授权的 D-Bus 接口列表 -func buildDestList() []securityloader.Destination { - destList := make([]securityloader.Destination, len(defaultDestList)) - copy(destList, defaultDestList) - - // 获取当前用户的 Accounts.User 路径 - userPath, err := getCurrentUserAccountsPath() - if err != nil { - logger.Warning("failed to get current user accounts path:", err) - return destList - } - - destList = append(destList, securityloader.Destination{ - DBusName: "org.deepin.dde.Accounts1", - DBusPath: userPath, - DBusInterface: "org.deepin.dde.Accounts1.User", - }) - - return destList -} - -// getCurrentUserAccountsPath 获取当前用户在 Accounts 服务中的路径 -func getCurrentUserAccountsPath() (string, error) { - systemConn, err := dbus.SystemBus() - if err != nil { - return "", err - } - - // 获取当前用户 UID - currentUser, err := user.Current() - if err != nil { - return "", err - } - - if currentUser == nil { - return "", fmt.Errorf("current user is nil") - } - - // 通过 D-Bus 调用 FindUserById - obj := systemConn.Object("org.deepin.dde.Accounts1", "/org/deepin/dde/Accounts1") - var userPath string - err = obj.Call("org.deepin.dde.Accounts1.FindUserById", 0, currentUser.Uid).Store(&userPath) - if err != nil { - return "", fmt.Errorf("dbus call FindUserById failed: %w", err) - } - - if userPath == "" { - return "", fmt.Errorf("received empty user path for uid: %s", currentUser.Uid) - } - - return userPath, nil -} \ No newline at end of file diff --git a/misc/scripts/langselector-loader-wrapper b/misc/scripts/langselector-loader-wrapper deleted file mode 100755 index 21444fc42..000000000 --- a/misc/scripts/langselector-loader-wrapper +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash - -exec /usr/bin/deepin-security-loader --group deepin-daemon -- \ - /usr/libexec/deepin/langselector "$@" \ No newline at end of file diff --git a/rpm/dde-daemon.spec b/rpm/dde-daemon.spec index dc790bbc7..de4d6653d 100644 --- a/rpm/dde-daemon.spec +++ b/rpm/dde-daemon.spec @@ -63,7 +63,6 @@ Requires: xdotool Requires: gnome-keyring-pam Requires: imwheel Requires: deepin-installer-timezones -Requires: deepin-security-loader Recommends: lshw Recommends: iso-codes @@ -79,10 +78,10 @@ Daemon handling the DDE session settings patch langselector/locale.go < rpm/locale.go.patch patch accounts/users/passwd.go < rpm/passwd.go.patch -# Fix library exec path while preserving security-loader targets under -# /usr/libexec/deepin. +# Fix library exec path +sed -i '/deepin/s|lib|libexec|' Makefile sed -i '/${DESTDIR}\/usr\/lib\/deepin-daemon\/service-trigger/s|${DESTDIR}/usr/lib/deepin-daemon/service-trigger|${DESTDIR}/usr/libexec/deepin-daemon/service-trigger|g' Makefile -sed -i 's|${DESTDIR}${PREFIX}/lib/deepin-daemon|${DESTDIR}${PREFIX}/libexec/deepin-daemon|g' Makefile +sed -i '/${DESTDIR}${PREFIX}\/lib\/deepin-daemon/s|${DESTDIR}${PREFIX}/lib/deepin-daemon|${DESTDIR}${PREFIX}/usr/libexec/deepin-daemon|g' Makefile sed -i 's|lib/NetworkManager|libexec|' network/utils_test.go for file in $(grep "/usr/lib/deepin-daemon" * -nR |awk -F: '{print $1}') @@ -111,8 +110,7 @@ After=user.slice dbus.socket [Service] Type=dbus BusName=org.deepin.dde.LockService1 -ExecStart=%{_libexecdir}/%{sname}/ -%{_libexecdir}/deepin/dde-lockservice +ExecStart=%{_libexecdir}/%{sname}/dde-lockservice [Install] WantedBy=graphical.target From 1c7acf78bd0741d8c79395a2376ced2ab39cd6a2 Mon Sep 17 00:00:00 2001 From: fuleyi Date: Wed, 19 Aug 2026 13:27:47 +0800 Subject: [PATCH 6/9] =?UTF-8?q?Revert=20"feat:=20=E4=B8=BA=20lastore=20Age?= =?UTF-8?q?nt=20=E6=B3=A8=E5=86=8C=E9=80=82=E9=85=8D=20security-loader"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 2761c2a3372fbebfa94de189ba9418c6e3c97f7e. --- bin/dde-session-daemon/main.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/bin/dde-session-daemon/main.go b/bin/dde-session-daemon/main.go index 17c2d599d..e3a1eb868 100755 --- a/bin/dde-session-daemon/main.go +++ b/bin/dde-session-daemon/main.go @@ -163,11 +163,6 @@ func main() { DBusPath: "/org/deepin/dde/Daemon1", DBusInterface: "org.deepin.dde.Daemon1", }, - { - DBusName: "org.deepin.dde.Lastore1", - DBusPath: "/org/deepin/dde/Lastore1", - DBusInterface: "org.deepin.dde.Lastore1.Manager", - }, { DBusName: "org.deepin.dde.InputDevices1", DBusPath: "/org/deepin/dde/InputDevices1", From 3f5082cd69204dabe67334bf69188f0853480b3f Mon Sep 17 00:00:00 2001 From: fuleyi Date: Wed, 19 Aug 2026 13:28:02 +0800 Subject: [PATCH 7/9] =?UTF-8?q?Revert=20"refactor:=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E9=A3=9E=E8=A1=8C=E6=A8=A1=E5=BC=8F=E9=89=B4=E6=9D=83=E6=9C=BA?= =?UTF-8?q?=E5=88=B6"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 478098da6539becf0993e580526548321b86154e. --- bin/dde-session-daemon/main.go | 5 -- misc/conf/org.deepin.dde.AirplaneMode1.conf | 16 +----- securityloader/allowcaller.go | 1 - .../airplane_mode1/exported_methods_auto.go | 5 -- system/airplane_mode1/manager.go | 54 +++++-------------- 5 files changed, 15 insertions(+), 66 deletions(-) diff --git a/bin/dde-session-daemon/main.go b/bin/dde-session-daemon/main.go index e3a1eb868..e22b31574 100755 --- a/bin/dde-session-daemon/main.go +++ b/bin/dde-session-daemon/main.go @@ -168,11 +168,6 @@ func main() { DBusPath: "/org/deepin/dde/InputDevices1", DBusInterface: "org.deepin.dde.InputDevices1", }, - { - DBusName: "org.deepin.dde.AirplaneMode1", - DBusPath: "/org/deepin/dde/AirplaneMode1", - DBusInterface: "org.deepin.dde.AirplaneMode1", - }, }) os.Args = cleanedArgs if err != nil { diff --git a/misc/conf/org.deepin.dde.AirplaneMode1.conf b/misc/conf/org.deepin.dde.AirplaneMode1.conf index 59b6aabc8..c0825f458 100644 --- a/misc/conf/org.deepin.dde.AirplaneMode1.conf +++ b/misc/conf/org.deepin.dde.AirplaneMode1.conf @@ -8,25 +8,11 @@ - - - - - - - - - \ No newline at end of file + diff --git a/securityloader/allowcaller.go b/securityloader/allowcaller.go index 62c98e2f4..2d559a459 100644 --- a/securityloader/allowcaller.go +++ b/securityloader/allowcaller.go @@ -27,7 +27,6 @@ const ( DaemonScope = "org.deepin.dde.Daemon1:/org/deepin/dde/Daemon1" PowerScope = "org.deepin.dde.Power1:/org/deepin/dde/Power1" InputDevicesScope = "org.deepin.dde.InputDevices1:/org/deepin/dde/InputDevices1" - AirplaneModeScope = "org.deepin.dde.AirplaneMode1:/org/deepin/dde/AirplaneMode1" defaultRuntimeDir = "/run/dde-daemon" defaultStateFile = defaultRuntimeDir + "/security_loader_allow_callers.json" diff --git a/system/airplane_mode1/exported_methods_auto.go b/system/airplane_mode1/exported_methods_auto.go index c19945b94..25326b4e0 100644 --- a/system/airplane_mode1/exported_methods_auto.go +++ b/system/airplane_mode1/exported_methods_auto.go @@ -27,10 +27,5 @@ func (v *Manager) GetExportedMethods() dbusutil.ExportedMethods { Fn: v.EnableWifi, InArgs: []string{"enableAirplaneMode"}, }, - { - Name: "SetAllowCaller", - Fn: v.SetAllowCaller, - InArgs: []string{"uniqueName"}, - }, } } diff --git a/system/airplane_mode1/manager.go b/system/airplane_mode1/manager.go index e41568a06..1d31d1968 100644 --- a/system/airplane_mode1/manager.go +++ b/system/airplane_mode1/manager.go @@ -10,7 +10,6 @@ import ( "time" "github.com/godbus/dbus/v5" - "github.com/linuxdeepin/dde-daemon/securityloader" networkmanager "github.com/linuxdeepin/go-dbus-factory/system/org.freedesktop.networkmanager" polkit "github.com/linuxdeepin/go-dbus-factory/system/org.freedesktop.policykit1" "github.com/linuxdeepin/go-lib/dbusutil" @@ -35,7 +34,6 @@ type device struct { type Manager struct { service *dbusutil.Service - allowCallers *securityloader.AllowCallerRegistry btRfkillDevices map[uint32]device btDevicesMu sync.RWMutex // Airplane Mode status @@ -56,7 +54,6 @@ type Manager struct { func newManager(service *dbusutil.Service) *Manager { mgr := &Manager{ service: service, - allowCallers: securityloader.DefaultRegistry(), btRfkillDevices: make(map[uint32]device), config: NewConfig(), } @@ -76,27 +73,17 @@ func (mgr *Manager) DumpState() *dbus.Error { return nil } -func (mgr *Manager) SetAllowCaller(sender dbus.Sender, uniqueName string) *dbus.Error { - return dbusutil.ToError(mgr.allowCallers.AddCaller(securityloader.AirplaneModeScope, sender, uniqueName)) -} - // Enable enable or disable *Airplane Mode*, isn't enable the devices func (mgr *Manager) Enable(sender dbus.Sender, enableAirplaneMode bool) *dbus.Error { - result, _ := mgr.allowCallers.Authorize(securityloader.AirplaneModeScope, sender) - switch result { - case securityloader.AuthDenied: - logger.Warning("Enable access denied") - return dbusutil.ToError(errors.New("access denied")) - case securityloader.AuthNotEnabled: - // Fall back to Polkit when not launched via security-loader. - if er := checkAuthorization(actionId, string(sender)); er != nil { - logger.Warningf("checkAuthorization failed, err: %v, actionId=%v", er, actionId) - return dbusutil.ToError(er) - } + // check auth + err := checkAuthorization(actionId, string(sender)) + if err != nil { + logger.Warningf("checkAuthorization failed, err: %v, actionId=%v", err, actionId) + return dbusutil.ToError(err) } // try to block - err := mgr.block(rfkillTypeAll, enableAirplaneMode) + err = mgr.block(rfkillTypeAll, enableAirplaneMode) if err != nil { logger.Warningf("block all radio failed, err: %v", err) return dbusutil.ToError(err) @@ -107,19 +94,13 @@ func (mgr *Manager) Enable(sender dbus.Sender, enableAirplaneMode bool) *dbus.Er // EnableWifi enable or disable *Airplane Mode* for wlan, isn't enable the wlan devices func (mgr *Manager) EnableWifi(sender dbus.Sender, enableAirplaneMode bool) *dbus.Error { - result, _ := mgr.allowCallers.Authorize(securityloader.AirplaneModeScope, sender) - switch result { - case securityloader.AuthDenied: - logger.Warning("EnableWifi access denied") - return dbusutil.ToError(errors.New("access denied")) - case securityloader.AuthNotEnabled: - if er := checkAuthorization(actionId, string(sender)); er != nil { - return dbusutil.ToError(er) - } + err := checkAuthorization(actionId, string(sender)) + if err != nil { + return dbusutil.ToError(err) } // try to block - err := mgr.block(rfkillTypeWifi, enableAirplaneMode) + err = mgr.block(rfkillTypeWifi, enableAirplaneMode) if err != nil { logger.Warningf("block wifi radio failed, err: %v", err) return dbusutil.ToError(err) @@ -130,19 +111,13 @@ func (mgr *Manager) EnableWifi(sender dbus.Sender, enableAirplaneMode bool) *dbu // EnableBluetooth enable or disable *Airplane Mode* for bluetooth, isn't enable the bluetooth devices func (mgr *Manager) EnableBluetooth(sender dbus.Sender, enableAirplaneMode bool) *dbus.Error { - result, _ := mgr.allowCallers.Authorize(securityloader.AirplaneModeScope, sender) - switch result { - case securityloader.AuthDenied: - logger.Warning("EnableBluetooth access denied") - return dbusutil.ToError(errors.New("access denied")) - case securityloader.AuthNotEnabled: - if er := checkAuthorization(actionId, string(sender)); er != nil { - return dbusutil.ToError(er) - } + err := checkAuthorization(actionId, string(sender)) + if err != nil { + return dbusutil.ToError(err) } // try to block - err := mgr.block(rfkillTypeBT, enableAirplaneMode) + err = mgr.block(rfkillTypeBT, enableAirplaneMode) if err != nil { logger.Warningf("block bluetooth radio failed, err: %v", err) return dbusutil.ToError(err) @@ -226,7 +201,6 @@ func (mgr *Manager) block(typ rfkillType, enableAirplaneMode bool) error { return rfkillAction(typ, state) } - func checkAuthorization(actionId string, sysBusName string) error { systemBus, err := dbus.SystemBus() if err != nil { From 4d24887794111e331ee152df58dc776836a1f156 Mon Sep 17 00:00:00 2001 From: fuleyi Date: Wed, 19 Aug 2026 13:28:29 +0800 Subject: [PATCH 8/9] =?UTF-8?q?Revert=20"feat:=20=E4=B8=BA=E8=BE=93?= =?UTF-8?q?=E5=85=A5=E8=AE=BE=E5=A4=87=20org.deepin.dde.InputDevices1=20?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=20AllowCaller=20=E6=9D=83=E9=99=90=E6=8E=A7?= =?UTF-8?q?=E5=88=B6"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit fa1f1b67898298a7cd32a898248fdce9ec25855f. --- bin/dde-session-daemon/main.go | 5 ----- misc/conf/org.deepin.dde.InputDevices1.conf | 16 +--------------- securityloader/allowcaller.go | 5 ++--- system/inputdevices1/exported_methods_auto.go | 5 ----- system/inputdevices1/inputdevices.go | 6 +----- system/inputdevices1/inputdevices_ifc.go | 5 ----- system/inputdevices1/touchpad.go | 15 +++------------ 7 files changed, 7 insertions(+), 50 deletions(-) diff --git a/bin/dde-session-daemon/main.go b/bin/dde-session-daemon/main.go index e22b31574..e1093e332 100755 --- a/bin/dde-session-daemon/main.go +++ b/bin/dde-session-daemon/main.go @@ -163,11 +163,6 @@ func main() { DBusPath: "/org/deepin/dde/Daemon1", DBusInterface: "org.deepin.dde.Daemon1", }, - { - DBusName: "org.deepin.dde.InputDevices1", - DBusPath: "/org/deepin/dde/InputDevices1", - DBusInterface: "org.deepin.dde.InputDevices1", - }, }) os.Args = cleanedArgs if err != nil { diff --git a/misc/conf/org.deepin.dde.InputDevices1.conf b/misc/conf/org.deepin.dde.InputDevices1.conf index 3e07c4327..2566c06fe 100644 --- a/misc/conf/org.deepin.dde.InputDevices1.conf +++ b/misc/conf/org.deepin.dde.InputDevices1.conf @@ -8,25 +8,11 @@ - - - - - - - - - \ No newline at end of file + diff --git a/securityloader/allowcaller.go b/securityloader/allowcaller.go index 2d559a459..16800ac9e 100644 --- a/securityloader/allowcaller.go +++ b/securityloader/allowcaller.go @@ -24,9 +24,8 @@ import ( ) const ( - DaemonScope = "org.deepin.dde.Daemon1:/org/deepin/dde/Daemon1" - PowerScope = "org.deepin.dde.Power1:/org/deepin/dde/Power1" - InputDevicesScope = "org.deepin.dde.InputDevices1:/org/deepin/dde/InputDevices1" + DaemonScope = "org.deepin.dde.Daemon1:/org/deepin/dde/Daemon1" + PowerScope = "org.deepin.dde.Power1:/org/deepin/dde/Power1" defaultRuntimeDir = "/run/dde-daemon" defaultStateFile = defaultRuntimeDir + "/security_loader_allow_callers.json" diff --git a/system/inputdevices1/exported_methods_auto.go b/system/inputdevices1/exported_methods_auto.go index 9f0847940..92f9c92bd 100644 --- a/system/inputdevices1/exported_methods_auto.go +++ b/system/inputdevices1/exported_methods_auto.go @@ -8,11 +8,6 @@ import ( func (v *InputDevices) GetExportedMethods() dbusutil.ExportedMethods { return dbusutil.ExportedMethods{ - { - Name: "SetAllowCaller", - Fn: v.SetAllowCaller, - InArgs: []string{"uniqueName"}, - }, { Name: "SetWakeupDevices", Fn: v.SetWakeupDevices, diff --git a/system/inputdevices1/inputdevices.go b/system/inputdevices1/inputdevices.go index 8727a17a6..423941795 100644 --- a/system/inputdevices1/inputdevices.go +++ b/system/inputdevices1/inputdevices.go @@ -15,7 +15,6 @@ import ( "github.com/godbus/dbus/v5" configManager "github.com/linuxdeepin/go-dbus-factory/org.desktopspec.ConfigManager" - "github.com/linuxdeepin/dde-daemon/securityloader" "github.com/linuxdeepin/go-lib/dbusutil" dutils "github.com/linuxdeepin/go-lib/utils" ) @@ -34,7 +33,6 @@ const ( //go:generate dbusutil-gen em -type InputDevices,Touchpad type InputDevices struct { service *dbusutil.Service - allowCallers *securityloader.AllowCallerRegistry systemSigLoop *dbusutil.SignalLoop l *libinput @@ -72,7 +70,6 @@ type InputDevices struct { func newInputDevices() *InputDevices { return &InputDevices{ touchscreens: make(map[dbus.ObjectPath]*Touchscreen), - allowCallers: securityloader.DefaultRegistry(), } } @@ -80,7 +77,6 @@ func (*InputDevices) GetInterfaceName() string { return dbusInterface } - func (m *InputDevices) init() { m.initDSettings(m.service) m.l = newLibinput(m) @@ -404,7 +400,7 @@ func (m *InputDevices) newTouchpad() { m.touchpadMu.Lock() defer m.touchpadMu.Unlock() - t := newTouchpad(m.service, m.allowCallers) + t := newTouchpad(m.service) err := t.export(dbus.ObjectPath(touchpadDBusPath)) if err != nil { logger.Warning(err) diff --git a/system/inputdevices1/inputdevices_ifc.go b/system/inputdevices1/inputdevices_ifc.go index 2e4af663c..2e13291fb 100644 --- a/system/inputdevices1/inputdevices_ifc.go +++ b/system/inputdevices1/inputdevices_ifc.go @@ -6,14 +6,9 @@ package inputdevices1 import ( "github.com/godbus/dbus/v5" - "github.com/linuxdeepin/dde-daemon/securityloader" "github.com/linuxdeepin/go-lib/dbusutil" ) -func (m *InputDevices) SetAllowCaller(sender dbus.Sender, uniqueName string) *dbus.Error { - return dbusutil.ToError(m.allowCallers.AddCaller(securityloader.InputDevicesScope, sender, uniqueName)) -} - func (m *InputDevices) SetWakeupDevices(sender dbus.Sender, path string, value string) *dbus.Error { err := m.setWakeupDevices(path, value) return dbusutil.ToError(err) diff --git a/system/inputdevices1/touchpad.go b/system/inputdevices1/touchpad.go index df6a78a13..6f1a77993 100644 --- a/system/inputdevices1/touchpad.go +++ b/system/inputdevices1/touchpad.go @@ -5,7 +5,6 @@ package inputdevices1 import ( - "errors" "os" "os/exec" "path/filepath" @@ -13,7 +12,6 @@ import ( "github.com/godbus/dbus/v5" configManager "github.com/linuxdeepin/go-dbus-factory/org.desktopspec.ConfigManager" - "github.com/linuxdeepin/dde-daemon/securityloader" "github.com/linuxdeepin/go-lib/dbusutil" ) @@ -49,16 +47,14 @@ SUBSYSTEM=="input", KERNEL=="event*", ATTRS{name}=="*ps/2*", ENV{LIBINPUT_IGNORE type Touchpad struct { service *dbusutil.Service - allowCallers *securityloader.AllowCallerRegistry Enable bool DeviceList []string udevMonitor *udevMonitor } -func newTouchpad(service *dbusutil.Service, allowCallers *securityloader.AllowCallerRegistry) *Touchpad { +func newTouchpad(service *dbusutil.Service) *Touchpad { t := &Touchpad{ - service: service, - allowCallers: allowCallers, + service: service, Enable: getDsgConf(), } @@ -83,12 +79,7 @@ func (t *Touchpad) handleDeviceChange(devices []string) { logger.Infof("touchpad devices updated: %d device(s)", len(devices)) } -func (t *Touchpad) SetTouchpadEnable(sender dbus.Sender, enabled bool) *dbus.Error { - result, _ := t.allowCallers.Authorize(securityloader.InputDevicesScope, sender) - if result == securityloader.AuthDenied { - logger.Warning("SetTouchpadEnable access denied:", err) - return dbusutil.ToError(err) - } +func (t *Touchpad) SetTouchpadEnable(enabled bool) *dbus.Error { err := t.setTouchpadEnable(enabled) return dbusutil.ToError(err) } From cbcdf1ec7d9294a408a0eb45c5a6f3a9f25fbb86 Mon Sep 17 00:00:00 2001 From: fuleyi Date: Wed, 19 Aug 2026 13:30:40 +0800 Subject: [PATCH 9/9] =?UTF-8?q?Revert=20"feat:=20=E9=9B=86=E6=88=90=20secu?= =?UTF-8?q?rity-loader=20=E5=8A=A0=E5=BC=BA=E5=AE=89=E5=85=A8"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 46ad889dffce4bf2a740e68543174fd395aec63e. --- Makefile | 5 - bin/dde-session-daemon/main.go | 17 - .../exported_methods_auto.go | 5 - bin/dde-system-daemon/main.go | 7 - bin/dde-system-daemon/power.go | 19 +- debian/control | 2 - debian/dde-daemon.lintian-overrides | 2 +- misc/conf/org.deepin.dde.Daemon1.conf | 11 - misc/conf/org.deepin.dde.Power1.conf | 10 - .../scripts/dde-session-daemon-loader-wrapper | 4 - securityloader/allowcaller.go | 517 ------------------ securityloader/allowcaller_test.go | 395 ------------- securityloader/handshake.go | 211 ------- securityloader/handshake_test.go | 124 ----- system/power1/exported_methods_auto.go | 5 - system/power1/manager.go | 4 +- system/power1/manager_ifc.go | 12 +- 17 files changed, 5 insertions(+), 1345 deletions(-) delete mode 100755 misc/scripts/dde-session-daemon-loader-wrapper delete mode 100644 securityloader/allowcaller.go delete mode 100644 securityloader/allowcaller_test.go delete mode 100644 securityloader/handshake.go delete mode 100644 securityloader/handshake_test.go diff --git a/Makefile b/Makefile index 121a26419..7a7d48bf2 100644 --- a/Makefile +++ b/Makefile @@ -166,11 +166,6 @@ install: build install-dde-data install-icons mkdir -pv ${DESTDIR}${PREFIX}/lib/deepin-daemon cp -f out/bin/* ${DESTDIR}${PREFIX}/lib/deepin-daemon/ - rm -f ${DESTDIR}${PREFIX}/lib/deepin-daemon/dde-session-daemon - cp -f out/bin/dde-session-daemon ${DESTDIR}${PREFIX}/libexec/deepin/ - install -m755 misc/scripts/dde-session-daemon-loader-wrapper \ - ${DESTDIR}${PREFIX}/lib/deepin-daemon/dde-session-daemon - mkdir -pv ${DESTDIR}${PREFIX}/share/locale cp -r out/locale/* ${DESTDIR}${PREFIX}/share/locale diff --git a/bin/dde-session-daemon/main.go b/bin/dde-session-daemon/main.go index e1093e332..18329e8df 100755 --- a/bin/dde-session-daemon/main.go +++ b/bin/dde-session-daemon/main.go @@ -26,7 +26,6 @@ import ( "github.com/linuxdeepin/dde-api/userenv" "github.com/linuxdeepin/dde-daemon/common/dconfig" "github.com/linuxdeepin/dde-daemon/loader" - "github.com/linuxdeepin/dde-daemon/securityloader" soundthemeplayer "github.com/linuxdeepin/go-dbus-factory/system/org.deepin.dde.soundthemeplayer1" login1 "github.com/linuxdeepin/go-dbus-factory/system/org.freedesktop.login1" "github.com/linuxdeepin/go-lib/dbusutil" @@ -157,22 +156,6 @@ func init() { } func main() { - cleanedArgs, loadedBySecurityLoader, err := securityloader.Handshake(os.Args, []securityloader.Destination{ - { - DBusName: "org.deepin.dde.Daemon1", - DBusPath: "/org/deepin/dde/Daemon1", - DBusInterface: "org.deepin.dde.Daemon1", - }, - }) - os.Args = cleanedArgs - if err != nil { - if loadedBySecurityLoader { - logger.Error("security-loader handshake failed, refusing to start:", err) - os.Exit(1) - } - logger.Warning("security-loader handshake failed:", err) - } - logger.SetLogLevel(log.LevelInfo) if isInShutdown() { diff --git a/bin/dde-system-daemon/exported_methods_auto.go b/bin/dde-system-daemon/exported_methods_auto.go index fad8fe7cd..498c08e46 100644 --- a/bin/dde-system-daemon/exported_methods_auto.go +++ b/bin/dde-system-daemon/exported_methods_auto.go @@ -71,11 +71,6 @@ func (v *Daemon) GetExportedMethods() dbusutil.ExportedMethods { Fn: v.SetReadOnlyProtection, InArgs: []string{"enable"}, }, - { - Name: "SetAllowCaller", - Fn: v.SetAllowCaller, - InArgs: []string{"uniqueName"}, - }, { Name: "SetIdleState", Fn: v.SetIdleState, diff --git a/bin/dde-system-daemon/main.go b/bin/dde-system-daemon/main.go index 445b497b8..66976bf60 100644 --- a/bin/dde-system-daemon/main.go +++ b/bin/dde-system-daemon/main.go @@ -33,7 +33,6 @@ import ( systemd1 "github.com/linuxdeepin/go-dbus-factory/system/org.freedesktop.systemd1" "github.com/linuxdeepin/dde-daemon/loader" - "github.com/linuxdeepin/dde-daemon/securityloader" login1 "github.com/linuxdeepin/go-dbus-factory/system/org.freedesktop.login1" glib "github.com/linuxdeepin/go-gir/glib-2.0" "github.com/linuxdeepin/go-lib/dbusutil" @@ -49,7 +48,6 @@ type Daemon struct { service *dbusutil.Service systemd systemd1.Manager dsSystem configManager.Manager - allowCallers *securityloader.AllowCallerRegistry systemPower systemPower.Power idleStatePath string idleScreenStatePath string @@ -113,10 +111,6 @@ func main() { BindTextdomainCodeset("dde-daemon", "UTF-8") Textdomain("dde-daemon") - allowCallers := securityloader.NewAllowCallerRegistry(service) - securityloader.SetDefaultRegistry(allowCallers) - defer allowCallers.Close() - logger.SetRestartCommand("/usr/lib/deepin-daemon/dde-system-daemon") _daemon = &Daemon{ @@ -124,7 +118,6 @@ func main() { service: service, systemSigLoop: dbusutil.NewSignalLoop(service.Conn(), 10), systemd: systemd1.NewManager(service.Conn()), - allowCallers: allowCallers, systemPower: systemPower.NewPower(service.Conn()), idleStatePath: IdleFile, idleScreenStatePath: IdleScreenFile, diff --git a/bin/dde-system-daemon/power.go b/bin/dde-system-daemon/power.go index 439c7e2ee..528697af6 100644 --- a/bin/dde-system-daemon/power.go +++ b/bin/dde-system-daemon/power.go @@ -15,7 +15,6 @@ import ( "github.com/godbus/dbus/v5" configManager "github.com/linuxdeepin/go-dbus-factory/org.desktopspec.ConfigManager" - "github.com/linuxdeepin/dde-daemon/securityloader" "github.com/linuxdeepin/go-lib/dbusutil" "github.com/linuxdeepin/go-lib/utils" ) @@ -173,26 +172,12 @@ func (d *Daemon) setState(file string, state bool) error { return nil } -func (d *Daemon) SetAllowCaller(sender dbus.Sender, uniqueName string) *dbus.Error { - return dbusutil.ToError(d.allowCallers.AddCaller(securityloader.DaemonScope, sender, uniqueName)) -} - -func (d *Daemon) SetIdleState(sender dbus.Sender, state bool) *dbus.Error { - result, _ := d.allowCallers.Authorize(securityloader.DaemonScope, sender) - if result == securityloader.AuthDenied { - logger.Warning("SetIdleState access denied:", err) - return dbusutil.ToError(err) - } +func (d *Daemon) SetIdleState(state bool) *dbus.Error { logger.Infof("SetIdleState %s try set state: %v", d.idleStatePath, state) return dbusutil.ToError(d.setState(d.idleStatePath, state)) } -func (d *Daemon) SetScreenState(sender dbus.Sender, state bool) *dbus.Error { - result, _ := d.allowCallers.Authorize(securityloader.DaemonScope, sender) - if result == securityloader.AuthDenied { - logger.Warning("SetScreenState access denied:", err) - return dbusutil.ToError(err) - } +func (d *Daemon) SetScreenState(state bool) *dbus.Error { logger.Infof("SetScreenState %s try set state: %v", d.idleScreenStatePath, state) return dbusutil.ToError(d.setState(d.idleScreenStatePath, state)) } diff --git a/debian/control b/debian/control index bef3cdb42..1042d3702 100644 --- a/debian/control +++ b/debian/control @@ -53,7 +53,6 @@ Build-Depends: libxtst-dev, libddcutil-dev, python3, - deepin-security-loader, Standards-Version: 4.5.1 Homepage: http://www.deepin.org @@ -68,7 +67,6 @@ Depends: deepin-desktop-schemas (>> 5.1.2+), deepin-installer-timezones, deepin-sound-theme, - deepin-security-loader, dmidecode, libglib2.0-bin, hwinfo, diff --git a/debian/dde-daemon.lintian-overrides b/debian/dde-daemon.lintian-overrides index 86ba68772..a62e163b6 100644 --- a/debian/dde-daemon.lintian-overrides +++ b/debian/dde-daemon.lintian-overrides @@ -1,7 +1,7 @@ dde-daemon: unstripped-binary-or-object usr/lib/deepin-daemon/dde-authority dde-daemon: unstripped-binary-or-object usr/lib/deepin-daemon/dde-greeter-setter dde-daemon: unstripped-binary-or-object usr/lib/deepin-daemon/dde-lockservice -dde-daemon: unstripped-binary-or-object usr/libexec/deepin/dde-session-daemon +dde-daemon: unstripped-binary-or-object usr/lib/deepin-daemon/dde-session-daemon dde-daemon: unstripped-binary-or-object usr/lib/deepin-daemon/dde-system-daemon dde-daemon: unstripped-binary-or-object usr/lib/deepin-daemon/default-file-manager dde-daemon: unstripped-binary-or-object usr/lib/deepin-daemon/default-terminal diff --git a/misc/conf/org.deepin.dde.Daemon1.conf b/misc/conf/org.deepin.dde.Daemon1.conf index 0fb89c33a..8d06ab7bb 100644 --- a/misc/conf/org.deepin.dde.Daemon1.conf +++ b/misc/conf/org.deepin.dde.Daemon1.conf @@ -12,13 +12,6 @@ - - - - - @@ -29,10 +22,6 @@ send_interface="org.freedesktop.DBus.Properties"/> - - diff --git a/misc/conf/org.deepin.dde.Power1.conf b/misc/conf/org.deepin.dde.Power1.conf index edfd934c8..181ba374d 100644 --- a/misc/conf/org.deepin.dde.Power1.conf +++ b/misc/conf/org.deepin.dde.Power1.conf @@ -10,13 +10,6 @@ - - - - - - diff --git a/misc/scripts/dde-session-daemon-loader-wrapper b/misc/scripts/dde-session-daemon-loader-wrapper deleted file mode 100755 index 2b528d62f..000000000 --- a/misc/scripts/dde-session-daemon-loader-wrapper +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash - -exec /usr/bin/deepin-security-loader --group deepin-daemon -- \ - /usr/libexec/deepin/dde-session-daemon "$@" diff --git a/securityloader/allowcaller.go b/securityloader/allowcaller.go deleted file mode 100644 index 16800ac9e..000000000 --- a/securityloader/allowcaller.go +++ /dev/null @@ -1,517 +0,0 @@ -// SPDX-FileCopyrightText: 2026 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: GPL-3.0-or-later - -package securityloader - -import ( - "encoding/json" - "errors" - "fmt" - "io/ioutil" - "os" - "os/user" - "path/filepath" - "sort" - "strconv" - "strings" - "sync" - - "github.com/godbus/dbus/v5" - ofdbus "github.com/linuxdeepin/go-dbus-factory/system/org.freedesktop.dbus" - "github.com/linuxdeepin/go-lib/dbusutil" - "github.com/linuxdeepin/go-lib/log" -) - -const ( - DaemonScope = "org.deepin.dde.Daemon1:/org/deepin/dde/Daemon1" - PowerScope = "org.deepin.dde.Power1:/org/deepin/dde/Power1" - - defaultRuntimeDir = "/run/dde-daemon" - defaultStateFile = defaultRuntimeDir + "/security_loader_allow_callers.json" - privilegedGroup = "deepin-daemon" - invalidGroupID = ^uint32(0) -) - -// AuthResult describes the result of an Authorize call. -type AuthResult int - -const ( - // AuthDenied means the caller is explicitly rejected. err is the reason. - AuthDenied AuthResult = iota - // AuthOK means the caller is authorized by the allow-caller registry. - AuthOK - // AuthNotEnabled means no caller has been registered for this scope. - // The service was not started via deepin-security-loader. - // Callers should fall back to their original authorization mechanism. - AuthNotEnabled -) - -var logger = log.NewLogger("daemon/security-loader") - -type busService interface { - NameHasOwner(name string) (bool, error) - GetConnUID(name string) (uint32, error) - GetConnPID(name string) (uint32, error) - GetConnGroups(name string) ([]uint32, error) - GetBusID() (string, error) -} - -type serviceBus struct { - *dbusutil.Service -} - -func (s serviceBus) GetBusID() (string, error) { - var id string - err := s.Conn().BusObject().Call("org.freedesktop.DBus.GetId", 0).Store(&id) - return id, err -} - -func (s serviceBus) GetConnGroups(name string) ([]uint32, error) { - pid, err := s.GetConnPID(name) - if err != nil { - return nil, err - } - return getProcessGroups(pid) -} - -type persistedState struct { - BusID string `json:"busId"` - Callers map[string][]string `json:"callers"` -} - -// AllowCallerRegistry stores the exact system-bus unique names authorized by -// deepin-security-loader for each exported D-Bus object. -type AllowCallerRegistry struct { - service busService - stateFile string - busID string - privilegedGroupID uint32 - processParent func(uint32) (uint32, error) - - mu sync.RWMutex - callers map[string]map[string]struct{} - persistMu sync.Mutex - - signalLoop *dbusutil.SignalLoop - persistState func(persistedState) error -} - -var ( - defaultRegistryMu sync.RWMutex - defaultRegistry *AllowCallerRegistry -) - -func NewAllowCallerRegistry(service *dbusutil.Service) *AllowCallerRegistry { - groupID, err := lookupGroupID(privilegedGroup) - if err != nil { - logger.Warningf("failed to resolve privileged group %s: %v", privilegedGroup, err) - groupID = invalidGroupID - } - registry := newAllowCallerRegistry(serviceBus{service}, defaultStateFile, groupID) - if err := registry.load(); err != nil { - logger.Warning("failed to load security-loader callers:", err) - } - - registry.signalLoop = dbusutil.NewSignalLoop(service.Conn(), 10) - registry.signalLoop.Start() - dbusDaemon := ofdbus.NewDBus(service.Conn()) - dbusDaemon.InitSignalExt(registry.signalLoop, true) - _, err = dbusDaemon.ConnectNameOwnerChanged(func(name, oldOwner, newOwner string) { - if strings.HasPrefix(name, ":") && oldOwner != "" && newOwner == "" { - registry.RemoveCaller(name) - } - }) - if err != nil { - logger.Warning("failed to watch security-loader callers:", err) - } - - return registry -} - -func newAllowCallerRegistry(service busService, stateFile string, privilegedGroupID uint32) *AllowCallerRegistry { - busID, err := service.GetBusID() - if err != nil { - logger.Warning("failed to get system bus ID:", err) - } - return &AllowCallerRegistry{ - service: service, - stateFile: stateFile, - busID: busID, - privilegedGroupID: privilegedGroupID, - processParent: getProcessParentPID, - callers: make(map[string]map[string]struct{}), - } -} - -func lookupGroupID(name string) (uint32, error) { - group, err := user.LookupGroup(name) - if err != nil { - return 0, err - } - value, err := strconv.ParseUint(group.Gid, 10, 32) - if err != nil { - return 0, fmt.Errorf("invalid gid %q for group %s: %w", group.Gid, name, err) - } - return uint32(value), nil -} - -func getProcessGroups(pid uint32) ([]uint32, error) { - content, err := ioutil.ReadFile(fmt.Sprintf("/proc/%d/status", pid)) - if err != nil { - return nil, err - } - - var groups []uint32 - for _, line := range strings.Split(string(content), "\n") { - if !strings.HasPrefix(line, "Gid:") && !strings.HasPrefix(line, "Groups:") { - continue - } - for _, value := range strings.Fields(strings.SplitN(line, ":", 2)[1]) { - gid, err := strconv.ParseUint(value, 10, 32) - if err != nil { - return nil, fmt.Errorf("invalid process gid %q: %w", value, err) - } - groups = append(groups, uint32(gid)) - } - } - if len(groups) == 0 { - return nil, fmt.Errorf("no group credentials found for pid %d", pid) - } - return groups, nil -} - -func getProcessParentPID(pid uint32) (uint32, error) { - content, err := ioutil.ReadFile(fmt.Sprintf("/proc/%d/status", pid)) - if err != nil { - return 0, err - } - - for _, line := range strings.Split(string(content), "\n") { - if !strings.HasPrefix(line, "PPid:") { - continue - } - fields := strings.Fields(strings.TrimPrefix(line, "PPid:")) - if len(fields) != 1 { - return 0, fmt.Errorf("invalid PPid entry for pid %d", pid) - } - parentPID, err := strconv.ParseUint(fields[0], 10, 32) - if err != nil { - return 0, fmt.Errorf("invalid parent pid %q for pid %d: %w", fields[0], pid, err) - } - return uint32(parentPID), nil - } - return 0, fmt.Errorf("no PPid entry found for pid %d", pid) -} - -func isProcessDescendant(pid, ancestorPID uint32, processParent func(uint32) (uint32, error)) (bool, error) { - if pid == 0 || ancestorPID == 0 || pid == ancestorPID { - return false, nil - } - - visited := make(map[uint32]struct{}) - currentPID := pid - for currentPID != 0 { - if _, exists := visited[currentPID]; exists { - return false, fmt.Errorf("cycle detected in process ancestry at pid %d", currentPID) - } - visited[currentPID] = struct{}{} - - parentPID, err := processParent(currentPID) - if err != nil { - return false, err - } - if parentPID == ancestorPID { - return true, nil - } - currentPID = parentPID - } - return false, nil -} - -func SetDefaultRegistry(registry *AllowCallerRegistry) { - defaultRegistryMu.Lock() - defaultRegistry = registry - defaultRegistryMu.Unlock() -} - -func DefaultRegistry() *AllowCallerRegistry { - defaultRegistryMu.RLock() - registry := defaultRegistry - defaultRegistryMu.RUnlock() - return registry -} - -func (r *AllowCallerRegistry) Close() { - if r != nil && r.signalLoop != nil { - r.signalLoop.Stop() - } -} - -func (r *AllowCallerRegistry) AddCaller(scope string, sender dbus.Sender, uniqueName string) error { - if r == nil { - return errors.New("security-loader caller registry is nil") - } - if scope == "" { - return errors.New("scope is empty") - } - if sender == "" { - return errors.New("D-Bus sender is empty") - } - if !strings.HasPrefix(uniqueName, ":") { - return fmt.Errorf("invalid D-Bus unique name %q", uniqueName) - } - - hasOwner, err := r.service.NameHasOwner(uniqueName) - if err != nil { - return fmt.Errorf("check D-Bus owner %q failed: %w", uniqueName, err) - } - if !hasOwner { - return fmt.Errorf("D-Bus caller %q has no owner", uniqueName) - } - if err := r.authorizeRegistrar(sender, uniqueName); err != nil { - return err - } - - r.persistMu.Lock() - defer r.persistMu.Unlock() - - r.mu.Lock() - callers := r.callers[scope] - if callers == nil { - callers = make(map[string]struct{}) - r.callers[scope] = callers - } - if _, exists := callers[uniqueName]; exists { - r.mu.Unlock() - return nil - } - callers[uniqueName] = struct{}{} - if err := r.saveLocked(); err != nil { - delete(r.callers[scope], uniqueName) - if len(r.callers[scope]) == 0 { - delete(r.callers, scope) - } - r.mu.Unlock() - return err - } - r.mu.Unlock() - - logger.Infof("registered security-loader caller %s for %s", uniqueName, scope) - return nil -} - -func (r *AllowCallerRegistry) authorizeRegistrar(sender dbus.Sender, uniqueName string) error { - senderUID, err := r.service.GetConnUID(string(sender)) - if err != nil { - return fmt.Errorf("get SetAllowCaller sender %s UID failed: %w", sender, err) - } - // Root is trusted to register a process running under another account. - if senderUID == 0 { - return nil - } - if r.privilegedGroupID == invalidGroupID { - return fmt.Errorf("privileged group %s is unavailable", privilegedGroup) - } - - groups, err := r.service.GetConnGroups(string(sender)) - if err != nil { - return fmt.Errorf("get SetAllowCaller sender %s groups failed: %w", sender, err) - } - if !containsGroup(groups, r.privilegedGroupID) { - return fmt.Errorf("D-Bus caller %s is not in privileged group %s", sender, privilegedGroup) - } - - targetUID, err := r.service.GetConnUID(uniqueName) - if err != nil { - return fmt.Errorf("get target caller %s UID failed: %w", uniqueName, err) - } - if targetUID != senderUID { - return fmt.Errorf("SetAllowCaller sender UID %d does not own target %s with UID %d", senderUID, uniqueName, targetUID) - } - - senderPID, err := r.service.GetConnPID(string(sender)) - if err != nil { - return fmt.Errorf("get SetAllowCaller sender %s PID failed: %w", sender, err) - } - targetPID, err := r.service.GetConnPID(uniqueName) - if err != nil { - return fmt.Errorf("get target caller %s PID failed: %w", uniqueName, err) - } - if r.processParent == nil { - return errors.New("process ancestry resolver is unavailable") - } - isDescendant, err := isProcessDescendant(targetPID, senderPID, r.processParent) - if err != nil { - return fmt.Errorf("verify target caller %s process ancestry failed: %w", uniqueName, err) - } - if !isDescendant { - return fmt.Errorf( - "target caller %s PID %d is not a descendant of SetAllowCaller sender %s PID %d", - uniqueName, targetPID, sender, senderPID, - ) - } - return nil -} - -func containsGroup(groups []uint32, target uint32) bool { - for _, group := range groups { - if group == target { - return true - } - } - return false -} - -func (r *AllowCallerRegistry) Authorize(scope string, sender dbus.Sender) (AuthResult, error) { - if r == nil { - return AuthDenied, errors.New("security-loader caller registry is nil") - } - if sender == "" { - return AuthDenied, errors.New("D-Bus sender is empty") - } - - uid, err := r.service.GetConnUID(string(sender)) - if err != nil { - return AuthDenied, fmt.Errorf("get caller %s UID failed: %w", sender, err) - } - if uid == 0 { - return AuthOK, nil - } - - r.mu.RLock() - scopeCallers, scopeExists := r.callers[scope] - _, callerExists := scopeCallers[string(sender)] - r.mu.RUnlock() - - if !scopeExists || len(scopeCallers) == 0 { - return AuthNotEnabled, nil - } - if !callerExists { - return AuthDenied, fmt.Errorf("D-Bus caller %s is not authorized for %s", sender, scope) - } - return AuthOK, nil -} - -func (r *AllowCallerRegistry) RemoveCaller(uniqueName string) { - if r == nil || uniqueName == "" { - return - } - - r.persistMu.Lock() - defer r.persistMu.Unlock() - - changed := false - r.mu.Lock() - for scope, callers := range r.callers { - if _, exists := callers[uniqueName]; !exists { - continue - } - delete(callers, uniqueName) - changed = true - if len(callers) == 0 { - delete(r.callers, scope) - } - } - if !changed { - r.mu.Unlock() - return - } - if err := r.saveLocked(); err != nil { - logger.Warningf("failed to persist removal of security-loader caller %s: %v", uniqueName, err) - } - r.mu.Unlock() -} - -func (r *AllowCallerRegistry) saveLocked() error { - state := make(map[string][]string, len(r.callers)) - for scope, callers := range r.callers { - uniqueNames := make([]string, 0, len(callers)) - for uniqueName := range callers { - uniqueNames = append(uniqueNames, uniqueName) - } - sort.Strings(uniqueNames) - state[scope] = uniqueNames - } - - if r.busID == "" { - return errors.New("system bus ID is empty") - } - persisted := persistedState{BusID: r.busID, Callers: state} - if r.persistState != nil { - return r.persistState(persisted) - } - return r.writeState(persisted) -} - -func (r *AllowCallerRegistry) writeState(state persistedState) error { - content, err := json.Marshal(state) - if err != nil { - return fmt.Errorf("marshal security-loader callers failed: %w", err) - } - - dir := filepath.Dir(r.stateFile) - if err := os.MkdirAll(dir, 0700); err != nil { - return fmt.Errorf("create security-loader runtime directory failed: %w", err) - } - tmp, err := ioutil.TempFile(dir, ".allow-callers-") - if err != nil { - return fmt.Errorf("create security-loader state file failed: %w", err) - } - tmpName := tmp.Name() - defer os.Remove(tmpName) - - if err := tmp.Chmod(0600); err != nil { - tmp.Close() - return err - } - if _, err := tmp.Write(content); err != nil { - tmp.Close() - return fmt.Errorf("write security-loader state failed: %w", err) - } - if err := tmp.Close(); err != nil { - return fmt.Errorf("close security-loader state failed: %w", err) - } - if err := os.Rename(tmpName, r.stateFile); err != nil { - return fmt.Errorf("replace security-loader state failed: %w", err) - } - return nil -} - -func (r *AllowCallerRegistry) load() error { - content, err := ioutil.ReadFile(r.stateFile) - if err != nil { - if os.IsNotExist(err) { - return nil - } - return err - } - - var state persistedState - if err := json.Unmarshal(content, &state); err != nil { - return err - } - if state.BusID == "" || state.BusID != r.busID { - return nil - } - - for scope, callers := range state.Callers { - if scope == "" { - continue - } - for _, uniqueName := range callers { - if !strings.HasPrefix(uniqueName, ":") { - continue - } - hasOwner, err := r.service.NameHasOwner(uniqueName) - if err != nil || !hasOwner { - continue - } - if r.callers[scope] == nil { - r.callers[scope] = make(map[string]struct{}) - } - r.callers[scope][uniqueName] = struct{}{} - } - } - return nil -} \ No newline at end of file diff --git a/securityloader/allowcaller_test.go b/securityloader/allowcaller_test.go deleted file mode 100644 index 19d8a3af2..000000000 --- a/securityloader/allowcaller_test.go +++ /dev/null @@ -1,395 +0,0 @@ -// SPDX-FileCopyrightText: 2026 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: GPL-3.0-or-later - -package securityloader - -import ( - "encoding/json" - "errors" - "fmt" - "io/ioutil" - "os" - "path/filepath" - "strconv" - "sync" - "testing" - "time" - - "github.com/godbus/dbus/v5" -) - -type fakeBusService struct { - owners map[string]bool - uids map[string]uint32 - groups map[string][]uint32 - pids map[string]uint32 - parents map[uint32]uint32 - busID string -} - -const testPrivilegedGroupID = 996 - -func (s *fakeBusService) NameHasOwner(name string) (bool, error) { - return s.owners[name], nil -} - -func (s *fakeBusService) GetConnUID(name string) (uint32, error) { - return s.uids[name], nil -} - -func (s *fakeBusService) GetConnPID(name string) (uint32, error) { - pid, ok := s.pids[name] - if !ok { - return 0, fmt.Errorf("PID for %s is unavailable", name) - } - return pid, nil -} - -func (s *fakeBusService) GetConnGroups(name string) ([]uint32, error) { - return s.groups[name], nil -} - -func (s *fakeBusService) GetBusID() (string, error) { - return s.busID, nil -} - -func newTestAllowCallerRegistry(service *fakeBusService, stateFile string, privilegedGroupID uint32) *AllowCallerRegistry { - registry := newAllowCallerRegistry(service, stateFile, privilegedGroupID) - registry.processParent = func(pid uint32) (uint32, error) { - parentPID, ok := service.parents[pid] - if !ok { - return 0, fmt.Errorf("parent PID for %d is unavailable", pid) - } - return parentPID, nil - } - return registry -} - -func TestAllowCallerRegistryAuthorize(t *testing.T) { - stateFile := filepath.Join(t.TempDir(), "allow-callers.json") - service := &fakeBusService{ - owners: map[string]bool{":1.1": true, ":1.10": true, ":1.11": true, ":1.12": true}, - uids: map[string]uint32{":1.1": 1000, ":1.10": 1000, ":1.11": 1000, ":1.12": 0}, - groups: map[string][]uint32{":1.1": {testPrivilegedGroupID}}, - pids: map[string]uint32{":1.1": 101, ":1.10": 110}, - parents: map[uint32]uint32{110: 101}, - busID: "bus-a", - } - registry := newTestAllowCallerRegistry(service, stateFile, testPrivilegedGroupID) - - if err := registry.AddCaller(DaemonScope, dbus.Sender(":1.1"), ":1.10"); err != nil { - t.Fatal(err) - } - result, _ := registry.Authorize(DaemonScope, dbus.Sender(":1.10")) - if result != AuthOK { - t.Fatalf("registered caller was denied") - } - result, _ = registry.Authorize(DaemonScope, dbus.Sender(":1.11")) - if result != AuthDenied { - t.Fatal("same-UID unregistered caller was allowed") - } - result, _ = registry.Authorize(PowerScope, dbus.Sender(":1.10")) - if result != AuthNotEnabled { - t.Fatal("caller registered for another scope should return AuthNotEnabled") - } - result, _ = registry.Authorize(PowerScope, dbus.Sender(":1.12")) - if result != AuthOK { - t.Fatalf("root caller was denied") - } -} - -func TestAllowCallerRegistryPersistenceAndRemoval(t *testing.T) { - stateFile := filepath.Join(t.TempDir(), "allow-callers.json") - service := &fakeBusService{ - owners: map[string]bool{":1.20": true, ":1.21": false}, - uids: map[string]uint32{":1.20": 1000}, - groups: make(map[string][]uint32), - busID: "bus-a", - } - content, err := json.Marshal(persistedState{ - BusID: "bus-a", - Callers: map[string][]string{ - DaemonScope: {":1.20", ":1.21"}, - }, - }) - if err != nil { - t.Fatal(err) - } - if err := ioutil.WriteFile(stateFile, content, 0600); err != nil { - t.Fatal(err) - } - - registry := newTestAllowCallerRegistry(service, stateFile, testPrivilegedGroupID) - if err := registry.load(); err != nil { - t.Fatal(err) - } - result, _ := registry.Authorize(DaemonScope, dbus.Sender(":1.20")) - if result != AuthOK { - t.Fatalf("live persisted caller was denied") - } - registry.RemoveCaller(":1.20") - result, _ = registry.Authorize(DaemonScope, dbus.Sender(":1.20")) - if result == AuthOK { - t.Fatal("removed caller was allowed") - } -} - -func TestAllowCallerRegistryRejectsStateFromAnotherBus(t *testing.T) { - stateFile := filepath.Join(t.TempDir(), "allow-callers.json") - content, err := json.Marshal(persistedState{ - BusID: "old-bus", - Callers: map[string][]string{ - DaemonScope: {":1.30"}, - }, - }) - if err != nil { - t.Fatal(err) - } - if err := ioutil.WriteFile(stateFile, content, 0600); err != nil { - t.Fatal(err) - } - - service := &fakeBusService{ - owners: map[string]bool{":1.30": true}, - uids: map[string]uint32{":1.30": 1000}, - groups: make(map[string][]uint32), - busID: "new-bus", - } - registry := newTestAllowCallerRegistry(service, stateFile, testPrivilegedGroupID) - if err := registry.load(); err != nil { - t.Fatal(err) - } - result, _ := registry.Authorize(DaemonScope, dbus.Sender(":1.30")) - if result == AuthOK { - t.Fatal("caller restored from a different system-bus lifetime") - } -} - -func TestAllowCallerRegistryConcurrentAddsPersistAllCallers(t *testing.T) { - stateFile := filepath.Join(t.TempDir(), "allow-callers.json") - service := &fakeBusService{ - owners: map[string]bool{":1.1": true}, - uids: map[string]uint32{":1.1": 1000}, - groups: map[string][]uint32{":1.1": {testPrivilegedGroupID}}, - pids: map[string]uint32{":1.1": 101}, - parents: make(map[uint32]uint32), - busID: "bus-a", - } - const callerCount = 20 - for i := 0; i < callerCount; i++ { - name := ":1." + strconv.Itoa(100+i) - service.owners[name] = true - service.uids[name] = 1000 - service.pids[name] = uint32(200 + i) - service.parents[uint32(200+i)] = 101 - } - - registry := newTestAllowCallerRegistry(service, stateFile, testPrivilegedGroupID) - errCh := make(chan error, callerCount) - var wg sync.WaitGroup - for i := 0; i < callerCount; i++ { - name := ":1." + strconv.Itoa(100+i) - wg.Add(1) - go func(name string) { - defer wg.Done() - errCh <- registry.AddCaller(DaemonScope, dbus.Sender(":1.1"), name) - }(name) - } - wg.Wait() - close(errCh) - for err := range errCh { - if err != nil { - t.Fatal(err) - } - } - - content, err := ioutil.ReadFile(stateFile) - if err != nil { - t.Fatal(err) - } - var state persistedState - if err := json.Unmarshal(content, &state); err != nil { - t.Fatal(err) - } - if got := len(state.Callers[DaemonScope]); got != callerCount { - t.Fatalf("persisted caller count = %d, want %d", got, callerCount) - } -} - -func TestAllowCallerRegistryValidatesRegistrar(t *testing.T) { - tests := []struct { - name string - sender dbus.Sender - target string - uids map[string]uint32 - groups map[string][]uint32 - descendant bool - wantError bool - }{ - { - name: "privileged same uid", - sender: dbus.Sender(":1.1"), - target: ":1.10", - uids: map[string]uint32{":1.1": 1000, ":1.10": 1000}, - groups: map[string][]uint32{":1.1": {testPrivilegedGroupID}}, - descendant: true, - }, - { - name: "same uid unrelated process", - sender: dbus.Sender(":1.5"), - target: ":1.50", - uids: map[string]uint32{":1.5": 1000, ":1.50": 1000}, - groups: map[string][]uint32{":1.5": {testPrivilegedGroupID}}, - wantError: true, - }, - { - name: "missing privileged group", - sender: dbus.Sender(":1.2"), - target: ":1.20", - uids: map[string]uint32{":1.2": 1000, ":1.20": 1000}, - groups: map[string][]uint32{":1.2": {1000}}, - wantError: true, - }, - { - name: "cross uid target", - sender: dbus.Sender(":1.3"), - target: ":1.30", - uids: map[string]uint32{":1.3": 1000, ":1.30": 1001}, - groups: map[string][]uint32{":1.3": {testPrivilegedGroupID}}, - wantError: true, - }, - { - name: "root cross uid target", - sender: dbus.Sender(":1.4"), - target: ":1.40", - uids: map[string]uint32{":1.4": 0, ":1.40": 1001}, - groups: make(map[string][]uint32), - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - service := &fakeBusService{ - owners: map[string]bool{tt.target: true}, - uids: tt.uids, - groups: tt.groups, - pids: map[string]uint32{string(tt.sender): 101, tt.target: 110}, - parents: map[uint32]uint32{110: 1, 1: 0}, - busID: "bus-a", - } - if tt.descendant { - service.parents[110] = 101 - } - registry := newTestAllowCallerRegistry(service, filepath.Join(t.TempDir(), "allow-callers.json"), testPrivilegedGroupID) - err := registry.AddCaller(DaemonScope, tt.sender, tt.target) - if tt.wantError && err == nil { - t.Fatal("expected registration to be denied") - } - if !tt.wantError && err != nil { - t.Fatalf("registration was denied: %v", err) - } - }) - } -} - -func TestAddCallerIsNotVisibleBeforePersistenceSucceeds(t *testing.T) { - service := &fakeBusService{ - owners: map[string]bool{":1.1": true, ":1.50": true}, - uids: map[string]uint32{":1.1": 1000, ":1.50": 1000}, - groups: map[string][]uint32{":1.1": {testPrivilegedGroupID}}, - pids: map[string]uint32{":1.1": 101, ":1.50": 150}, - parents: map[uint32]uint32{150: 101}, - busID: "bus-a", - } - registry := newTestAllowCallerRegistry(service, filepath.Join(t.TempDir(), "allow-callers.json"), testPrivilegedGroupID) - persistStarted := make(chan struct{}) - releasePersist := make(chan struct{}) - registry.persistState = func(persistedState) error { - close(persistStarted) - <-releasePersist - return errors.New("persist failed") - } - - addResult := make(chan error, 1) - go func() { - addResult <- registry.AddCaller(DaemonScope, dbus.Sender(":1.1"), ":1.50") - }() - <-persistStarted - - authorizeResult := make(chan AuthResult, 1) - go func() { - result, _ := registry.Authorize(DaemonScope, dbus.Sender(":1.50")) - authorizeResult <- result - }() - select { - case <-authorizeResult: - t.Fatalf("authorization completed before registration commit") - case <-time.After(50 * time.Millisecond): - } - - close(releasePersist) - if err := <-addResult; err == nil { - t.Fatal("expected persistence failure") - } - if result := <-authorizeResult; result == AuthOK { - t.Fatal("failed registration became authorized") - } -} - -func TestIsProcessDescendant(t *testing.T) { - parents := map[uint32]uint32{400: 300, 300: 200, 200: 1, 1: 0} - processParent := func(pid uint32) (uint32, error) { - parentPID, ok := parents[pid] - if !ok { - return 0, fmt.Errorf("parent PID for %d is unavailable", pid) - } - return parentPID, nil - } - - isDescendant, err := isProcessDescendant(400, 200, processParent) - if err != nil { - t.Fatal(err) - } - if !isDescendant { - t.Fatal("multi-level descendant was rejected") - } - - isDescendant, err = isProcessDescendant(400, 999, processParent) - if err != nil { - t.Fatal(err) - } - if isDescendant { - t.Fatal("unrelated process was accepted as a descendant") - } - - cyclicParent := func(pid uint32) (uint32, error) { - if pid == 10 { - return 11, nil - } - return 10, nil - } - if _, err := isProcessDescendant(10, 99, cyclicParent); err == nil { - t.Fatal("cyclic process ancestry was accepted") - } -} - -func TestGetProcessParentPID(t *testing.T) { - parentPID, err := getProcessParentPID(uint32(os.Getpid())) - if err != nil { - t.Fatal(err) - } - if want := uint32(os.Getppid()); parentPID != want { - t.Fatalf("parent PID = %d, want %d", parentPID, want) - } -} - -func TestGetProcessGroupsIncludesEffectiveGroup(t *testing.T) { - groups, err := getProcessGroups(uint32(os.Getpid())) - if err != nil { - t.Fatal(err) - } - if !containsGroup(groups, uint32(os.Getegid())) { - t.Fatalf("effective gid %d was not found in process credentials %v", os.Getegid(), groups) - } -} \ No newline at end of file diff --git a/securityloader/handshake.go b/securityloader/handshake.go deleted file mode 100644 index fbb7f400b..000000000 --- a/securityloader/handshake.go +++ /dev/null @@ -1,211 +0,0 @@ -// SPDX-FileCopyrightText: 2026 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: GPL-3.0-or-later - -package securityloader - -import ( - "encoding/json" - "fmt" - "io" - "io/ioutil" - "os" - "strconv" - "strings" - "syscall" - "time" - - "github.com/godbus/dbus/v5" -) - -type Destination struct { - DBusName string `json:"DbusName"` - DBusPath string `json:"DbusPath"` - DBusInterface string `json:"DbusInterface"` -} - -type loaderInfo struct { - fd1 int - fd2 int - loaded bool -} - -type handshakeRequest struct { - UniqueName string `json:"UniqueName"` - DestList []Destination `json:"DestList"` -} - -const maxSecurityLoaderResponseSize = int64(5 << 20) - -// Handshake consumes deepin-security-loader's injected arguments and registers -// the process system-bus unique name for the requested destinations. -func Handshake(args []string, destinations []Destination) ([]string, bool, error) { - info, cleanedArgs, err := parseLoaderArgs(args) - if err != nil || !info.loaded { - return cleanedArgs, info.loaded, err - } - if len(destinations) == 0 { - return cleanedArgs, true, fmt.Errorf("security-loader destination list is empty") - } - - conn, err := dbus.SystemBus() - if err != nil { - return cleanedArgs, true, fmt.Errorf("connect to system bus failed: %w", err) - } - uniqueName := "" - for _, name := range conn.Names() { - if strings.HasPrefix(name, ":") { - uniqueName = name - break - } - } - if uniqueName == "" { - return cleanedArgs, true, fmt.Errorf("system bus unique name is unavailable") - } - - request := handshakeRequest{UniqueName: uniqueName, DestList: destinations} - requestData, err := json.Marshal(request) - if err != nil { - return cleanedArgs, true, fmt.Errorf("marshal security-loader request failed: %w", err) - } - - requestFile := os.NewFile(uintptr(info.fd1), "security-loader-request") - if requestFile == nil { - return cleanedArgs, true, fmt.Errorf("open security-loader request fd failed") - } - defer requestFile.Close() - - responseFile := os.NewFile(uintptr(info.fd2), "security-loader-response") - if responseFile == nil { - return cleanedArgs, true, fmt.Errorf("open security-loader response fd failed") - } - defer responseFile.Close() - - if err := validateSecurityLoaderFile(requestFile, syscall.O_WRONLY); err != nil { - return cleanedArgs, true, fmt.Errorf("invalid security-loader request fd: %w", err) - } - if err := validateSecurityLoaderFile(responseFile, syscall.O_RDONLY); err != nil { - return cleanedArgs, true, fmt.Errorf("invalid security-loader response fd: %w", err) - } - - if _, err := requestFile.Write(requestData); err != nil { - return cleanedArgs, true, fmt.Errorf("write security-loader request failed: %w", err) - } - if err := requestFile.Close(); err != nil { - return cleanedArgs, true, fmt.Errorf("close security-loader request fd failed: %w", err) - } - - type readResult struct { - data []byte - err error - } - resultCh := make(chan readResult, 1) - go func() { - data, err := readSecurityLoaderResponse(responseFile) - resultCh <- readResult{data: data, err: err} - }() - - timer := time.NewTimer(5 * time.Second) - defer timer.Stop() - - var responseData []byte - select { - case result := <-resultCh: - responseFile.Close() - if result.err != nil { - return cleanedArgs, true, fmt.Errorf("read security-loader response failed: %w", result.err) - } - responseData = result.data - case <-timer.C: - responseFile.Close() - return cleanedArgs, true, fmt.Errorf("timeout waiting for security-loader response") - } - - var response struct { - Result bool `json:"Result"` - Message string `json:"Message"` - } - if err := json.Unmarshal(responseData, &response); err != nil { - return cleanedArgs, true, fmt.Errorf("decode security-loader response failed: %w", err) - } - if !response.Result { - return cleanedArgs, true, fmt.Errorf("security-loader authorization failed: %s", response.Message) - } - return cleanedArgs, true, nil -} - -func parseLoaderArgs(args []string) (loaderInfo, []string, error) { - info := loaderInfo{fd1: -1, fd2: -1} - if len(args) == 0 { - return info, nil, nil - } - - cleaned := []string{args[0]} - seenFD1 := false - seenFD2 := false - for i := 1; i < len(args); i++ { - if args[i] != "--fd1" && args[i] != "--fd2" { - cleaned = append(cleaned, args[i]) - continue - } - info.loaded = true - if i+1 >= len(args) { - return info, cleaned, fmt.Errorf("%s requires a file descriptor", args[i]) - } - value, err := strconv.Atoi(args[i+1]) - if err != nil || value < 0 { - return info, cleaned, fmt.Errorf("invalid %s value %q", args[i], args[i+1]) - } - if args[i] == "--fd1" { - if seenFD1 { - return info, cleaned, fmt.Errorf("duplicate --fd1 argument") - } - seenFD1 = true - info.fd1 = value - } else { - if seenFD2 { - return info, cleaned, fmt.Errorf("duplicate --fd2 argument") - } - seenFD2 = true - info.fd2 = value - } - i++ - } - if info.loaded && (info.fd1 < 0 || info.fd2 < 0) { - return info, cleaned, fmt.Errorf("security-loader requires both --fd1 and --fd2") - } - if info.loaded && info.fd1 == info.fd2 { - return info, cleaned, fmt.Errorf("security-loader requires distinct --fd1 and --fd2") - } - return info, cleaned, nil -} - -func validateSecurityLoaderFile(file *os.File, expectedAccessMode int) error { - info, err := file.Stat() - if err != nil { - return err - } - if info.Mode()&os.ModeNamedPipe == 0 { - return fmt.Errorf("descriptor is not a pipe") - } - - flags, _, errno := syscall.Syscall(syscall.SYS_FCNTL, file.Fd(), uintptr(syscall.F_GETFL), 0) - if errno != 0 { - return errno - } - if int(flags)&syscall.O_ACCMODE != expectedAccessMode { - return fmt.Errorf("unexpected descriptor access mode") - } - return nil -} - -func readSecurityLoaderResponse(reader io.Reader) ([]byte, error) { - data, err := ioutil.ReadAll(io.LimitReader(reader, maxSecurityLoaderResponseSize+1)) - if err != nil { - return nil, err - } - if int64(len(data)) > maxSecurityLoaderResponseSize { - return nil, fmt.Errorf("response exceeds %d bytes", maxSecurityLoaderResponseSize) - } - return data, nil -} \ No newline at end of file diff --git a/securityloader/handshake_test.go b/securityloader/handshake_test.go deleted file mode 100644 index 825505b36..000000000 --- a/securityloader/handshake_test.go +++ /dev/null @@ -1,124 +0,0 @@ -// SPDX-FileCopyrightText: 2026 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: GPL-3.0-or-later - -package securityloader - -import ( - "bytes" - "io/ioutil" - "os" - "reflect" - "syscall" - "testing" -) - -func TestParseLoaderArgs(t *testing.T) { - info, args, err := parseLoaderArgs([]string{ - "dde-session-daemon", "--verbose", "--fd1", "7", "--fd2", "8", "--force", - }) - if err != nil { - t.Fatal(err) - } - if !info.loaded || info.fd1 != 7 || info.fd2 != 8 { - t.Fatalf("unexpected loader info: %+v", info) - } - want := []string{"dde-session-daemon", "--verbose", "--force"} - if !reflect.DeepEqual(args, want) { - t.Fatalf("unexpected cleaned args: got %v, want %v", args, want) - } -} - -func TestParseLoaderArgsRequiresBothFDs(t *testing.T) { - _, _, err := parseLoaderArgs([]string{"startdde", "--fd1", "7"}) - if err == nil { - t.Fatal("expected incomplete loader arguments to fail") - } -} - -func TestParseLoaderArgsRejectsDuplicateFDs(t *testing.T) { - tests := [][]string{ - {"dde-session-daemon", "--fd1", "7", "--fd1", "9", "--fd2", "8"}, - {"dde-session-daemon", "--fd1", "7", "--fd2", "8", "--fd2", "9"}, - } - for _, args := range tests { - if _, _, err := parseLoaderArgs(args); err == nil { - t.Fatalf("expected duplicate loader arguments to fail: %v", args) - } - } -} - -func TestParseLoaderArgsRequiresDistinctFDs(t *testing.T) { - _, _, err := parseLoaderArgs([]string{ - "dde-session-daemon", "--fd1", "7", "--fd2", "7", - }) - if err == nil { - t.Fatal("expected identical loader file descriptors to fail") - } -} - -func TestReadSecurityLoaderResponseLimit(t *testing.T) { - valid := bytes.Repeat([]byte{'a'}, int(maxSecurityLoaderResponseSize)) - data, err := readSecurityLoaderResponse(bytes.NewReader(valid)) - if err != nil { - t.Fatal(err) - } - if len(data) != len(valid) { - t.Fatalf("unexpected response length: got %d, want %d", len(data), len(valid)) - } - - oversized := bytes.Repeat([]byte{'a'}, int(maxSecurityLoaderResponseSize)+1) - if _, err := readSecurityLoaderResponse(bytes.NewReader(oversized)); err == nil { - t.Fatal("expected oversized loader response to fail") - } -} - -func TestValidateSecurityLoaderFile(t *testing.T) { - reader, writer, err := os.Pipe() - if err != nil { - t.Fatal(err) - } - defer reader.Close() - defer writer.Close() - - if err := validateSecurityLoaderFile(writer, syscall.O_WRONLY); err != nil { - t.Fatalf("expected pipe writer to be valid: %v", err) - } - if err := validateSecurityLoaderFile(reader, syscall.O_RDONLY); err != nil { - t.Fatalf("expected pipe reader to be valid: %v", err) - } - if err := validateSecurityLoaderFile(reader, syscall.O_WRONLY); err == nil { - t.Fatal("expected pipe access mode mismatch to fail") - } - - regularFile, err := ioutil.TempFile(t.TempDir(), "security-loader") - if err != nil { - t.Fatal(err) - } - defer regularFile.Close() - if err := validateSecurityLoaderFile(regularFile, syscall.O_RDWR); err == nil { - t.Fatal("expected regular file descriptor to fail") - } -} - -func TestHandshakeReportsLoaderState(t *testing.T) { - args, loaded, err := Handshake([]string{"dde-session-daemon", "--verbose"}, []Destination{{}}) - if err != nil { - t.Fatal(err) - } - if loaded { - t.Fatal("direct invocation was reported as security-loader invocation") - } - want := []string{"dde-session-daemon", "--verbose"} - if !reflect.DeepEqual(args, want) { - t.Fatalf("unexpected args: got %v, want %v", args, want) - } - - _, loaded, err = Handshake([]string{"dde-session-daemon", "--fd1", "7"}, []Destination{{}}) - if err == nil { - t.Fatal("expected incomplete loader arguments to fail") - } - if !loaded { - t.Fatal("invalid injected arguments did not report security-loader invocation") - } -} \ No newline at end of file diff --git a/system/power1/exported_methods_auto.go b/system/power1/exported_methods_auto.go index 8120dbd0a..b3fda635e 100644 --- a/system/power1/exported_methods_auto.go +++ b/system/power1/exported_methods_auto.go @@ -33,11 +33,6 @@ func (v *Manager) GetExportedMethods() dbusutil.ExportedMethods { Name: "RefreshMains", Fn: v.RefreshMains, }, - { - Name: "SetAllowCaller", - Fn: v.SetAllowCaller, - InArgs: []string{"uniqueName"}, - }, { Name: "SetCpuBoost", Fn: v.SetCpuBoost, diff --git a/system/power1/manager.go b/system/power1/manager.go index 53657ab3c..15996fe82 100644 --- a/system/power1/manager.go +++ b/system/power1/manager.go @@ -17,7 +17,6 @@ import ( "github.com/linuxdeepin/dde-api/powersupply" "github.com/linuxdeepin/dde-api/powersupply/battery" "github.com/linuxdeepin/dde-daemon/common/dconfig" - "github.com/linuxdeepin/dde-daemon/securityloader" DisplayManager "github.com/linuxdeepin/go-dbus-factory/system/org.freedesktop.DisplayManager" gudev "github.com/linuxdeepin/go-gir/gudev-1.0" "github.com/linuxdeepin/go-lib/dbusutil" @@ -50,7 +49,6 @@ type supportMode struct { // https://www.kernel.org/doc/Documentation/power/power_supply_class.txt type Manager struct { service *dbusutil.Service - allowCallers *securityloader.AllowCallerRegistry systemSigLoop *dbusutil.SignalLoop batteries map[string]*Battery batteriesMu sync.Mutex @@ -175,6 +173,7 @@ var _validPowerModeArray = strv.Strv{ ddePerformance, ddeLowBattery, } + func newManager(service *dbusutil.Service) (*Manager, error) { m := &Manager{ service: service, @@ -184,7 +183,6 @@ func newManager(service *dbusutil.Service) (*Manager, error) { IsBalanceSupported: true, IsPowerSaveSupported: true, CpuBoost: true, - allowCallers: securityloader.DefaultRegistry(), } err := m.init() diff --git a/system/power1/manager_ifc.go b/system/power1/manager_ifc.go index fd51bea71..4e663d136 100644 --- a/system/power1/manager_ifc.go +++ b/system/power1/manager_ifc.go @@ -9,7 +9,6 @@ import ( "fmt" dbus "github.com/godbus/dbus/v5" - "github.com/linuxdeepin/dde-daemon/securityloader" "github.com/linuxdeepin/go-lib/dbusutil" ) @@ -107,16 +106,7 @@ func (m *Manager) SetMode(mode string) *dbus.Error { return nil } -func (m *Manager) SetAllowCaller(sender dbus.Sender, uniqueName string) *dbus.Error { - return dbusutil.ToError(m.allowCallers.AddCaller(securityloader.PowerScope, sender, uniqueName)) -} - -func (m *Manager) SetTlpMode(sender dbus.Sender, mode string) *dbus.Error { - result, _ := m.allowCallers.Authorize(securityloader.PowerScope, sender) - if result == securityloader.AuthDenied { - logger.Warning("SetTlpMode access denied:", err) - return dbusutil.ToError(err) - } +func (m *Manager) SetTlpMode(mode string) *dbus.Error { logger.Info("SetTlpMode : ", mode) return dbusutil.ToError(m.setTlpMode(mode)) }