From c2d31a8901cf12d94a05e7feea4f49f0725ec807 Mon Sep 17 00:00:00 2001 From: wangzhaohui Date: Mon, 25 May 2026 11:24:50 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E8=B0=83=E6=95=B4=20lastore=20=E8=B0=83?= =?UTF-8?q?=E7=94=A8=E6=96=B9=E9=89=B4=E6=9D=83=E9=80=BB=E8=BE=91=E4=BB=A5?= =?UTF-8?q?=E9=80=82=E9=85=8D=20deepin-security-loader?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Description: 将安装、卸载和全屏升级等接口的二进制路径白名单鉴权改为允许调用者列表、lightdm 特殊 uid 与 polkit 回退校验,导出 SetAllowCaller 接口并将允许调用者保存到运行时目录,同时同步更新 D-Bus 访问规则、systemd RuntimeDirectory 和相关测试。 Log: 调整 lastore 的调用方鉴权逻辑以适配 deepin-security-loader Task: https://pms.uniontech.com/task-view-389535.html Influence: 控制中心、锁屏等经 deepin-security-loader 启动的服务可通过允许调用者列表访问安装、卸载和升级相关接口,lightdm greeter 可按特殊 uid 直接调用,未放行调用方仍需通过 polkit 鉴权。 --- src/lastore-daemon/common.go | 139 +--------- src/lastore-daemon/exported_methods_auto.go | 5 + src/lastore-daemon/inhibitor.go | 17 -- src/lastore-daemon/main.go | 3 +- src/lastore-daemon/manager.go | 35 ++- src/lastore-daemon/manager_auth.go | 270 ++++++++++++++++++++ src/lastore-daemon/manager_ifc.go | 115 +++++---- src/lastore-daemon/manager_upgrade.go | 7 - 8 files changed, 368 insertions(+), 223 deletions(-) create mode 100644 src/lastore-daemon/manager_auth.go diff --git a/src/lastore-daemon/common.go b/src/lastore-daemon/common.go index 71357466c..d026f43f5 100644 --- a/src/lastore-daemon/common.go +++ b/src/lastore-daemon/common.go @@ -9,7 +9,6 @@ import ( "crypto/sha256" "encoding/hex" "encoding/json" - "errors" "fmt" "io" "os" @@ -23,16 +22,13 @@ import ( "time" "unicode/utf8" - "github.com/linuxdeepin/dde-api/polkit" utils2 "github.com/linuxdeepin/go-lib/utils" "github.com/linuxdeepin/lastore-daemon/src/internal/config" "github.com/linuxdeepin/lastore-daemon/src/internal/system" "github.com/linuxdeepin/lastore-daemon/src/internal/system/apt" "github.com/godbus/dbus/v5" - "github.com/linuxdeepin/go-lib/dbusutil" "github.com/linuxdeepin/go-lib/procfs" - "github.com/linuxdeepin/go-lib/strv" ) var _urlReg = regexp.MustCompile(`^[ ]*deb .*((?:https?|ftp|file|p2p|delivery)://[^ ]+)`) @@ -270,82 +266,6 @@ func parseAutoDownloadRange(idleDownloadConfig idleDownloadConfig, now time.Time return NewTimeRange(beginTime, endTime), nil } -const ( - appStoreDaemonPath = "/usr/bin/deepin-app-store-daemon" - oldAppStoreDaemonPath = "/usr/bin/deepin-appstore-daemon" - printerPath = "/usr/bin/dde-printer" - printerHelperPath = "/usr/bin/dde-printer-helper" - sessionDaemonPath = "/usr/lib/deepin-daemon/dde-session-daemon" - langSelectorPath = "/usr/lib/deepin-daemon/langselector" - controlCenterPath = "/usr/bin/dde-control-center" - controlCenterCmdLine = "/usr/share/applications/dde-control-center.deskto" // 缺个 p 是因为 deepin-turbo 修改命令的时候 buffer 不够用, 所以截断了. - oldControlCenterPath = "/usr/lib/x86_64-linux-gnu/dde-control-center/dde-control-center-old" - dataTransferPath = "/usr/bin/deepin-data-transfer" - amDaemonPath = "/usr/bin/dde-application-manager" - launcherPath = "/usr/bin/dde-launcher" - amDaemonCompatPath = "/usr/libexec/dde-application-wizard-daemon-compat" -) - -// TODO delete -var ( - allowInstallPackageExecPaths = strv.Strv{ - appStoreDaemonPath, - oldAppStoreDaemonPath, - printerPath, - printerHelperPath, - langSelectorPath, - controlCenterPath, - oldControlCenterPath, - dataTransferPath, - } - allowRemovePackageExecPaths = strv.Strv{ - appStoreDaemonPath, - oldAppStoreDaemonPath, - sessionDaemonPath, - langSelectorPath, - controlCenterPath, - oldControlCenterPath, - amDaemonPath, - launcherPath, - amDaemonCompatPath, - } -) - -// execPath和cmdLine可以有一个为空,其中一个存在即可作为判断调用者的依据 -func getExecutablePathAndCmdline(service *dbusutil.Service, sender dbus.Sender) (string, string, error) { - pid, err := service.GetConnPID(string(sender)) - if err != nil { - return "", "", err - } - - proc := procfs.Process(pid) - execPath, err := proc.Exe() - if err != nil { - // 当调用者在使用过程中发生了更新,则在获取该进程的exe时,会出现lstat xxx (deleted)此类的error,如果发生的是覆盖,则该路径依旧存在,因此增加以下判断 - var pErr *os.PathError - ok := errors.As(err, &pErr) - if ok { - if os.IsNotExist(pErr.Err) { - errExecPath := strings.Replace(pErr.Path, "(deleted)", "", -1) - oldExecPath := strings.TrimSpace(errExecPath) - if system.NormalFileExists(oldExecPath) { - execPath = oldExecPath - err = nil - } - } - } - } - - cmdLine, err1 := proc.Cmdline() - if err != nil && err1 != nil { - return "", "", errors.New(strings.Join([]string{ - err.Error(), - err1.Error(), - }, ";")) - } - return execPath, strings.Join(cmdLine, " "), nil -} - // 根据类型过滤数据 func getFilterPackages(infosMap map[string][]string, updateType system.UpdateType) []string { var r []string @@ -556,61 +476,10 @@ func getCoreListOnline() []string { return pkgs } -var _initProcNsMnt string -var _once sync.Once - -// 通过判断/proc/pid/ns/mnt 和 /proc/1/ns/mnt是否相同,如果不相同,则进程exe字段不可信 -func checkSenderNsMntValid(pid uint32) bool { - _once.Do(func() { - out, err := os.Readlink("/proc/1/ns/mnt") - if err != nil { - fmt.Println(err) - return - } - _initProcNsMnt = strings.TrimSpace(out) - }) - c, err := os.Readlink(fmt.Sprintf("/proc/%v/ns/mnt", pid)) - if err != nil { - fmt.Println(err) - return false - } - defer func() { - fmt.Printf("pid 1 mnt ns is %v,pid %v mnt ns is %v\n", _initProcNsMnt, pid, strings.TrimSpace(c)) - }() - return strings.TrimSpace(c) == _initProcNsMnt -} - -const ( - polkitActionChangeOwnData = "com.deepin.lastore.user-administration" - polkitActionChangeUpgradeDelivery = "com.deepin.lastore.doUpgradeDelivery" - polkitActionEnableUpgradeDelivery = "com.deepin.lastore.enableUpgradeDelivery" - polkitActionDisableUpgradeDelivery = "com.deepin.lastore.disableUpgradeDelivery" -) - -func checkInvokePermission(service *dbusutil.Service, sender dbus.Sender) error { - uid, err := service.GetConnUID(string(sender)) - if err != nil { - return fmt.Errorf("failed to get sender conn uid:%v", err) - } - if uid != 0 { - execPath, cmdLine, err := getExecutablePathAndCmdline(service, sender) - if err != nil { - logger.Warning(err) - return polkit.CheckAuth(polkitActionChangeOwnData, string(sender), nil) - } - caller := mapMethodCaller(execPath, cmdLine) - if methodCallerControlCenter == caller { - return nil - } else { - logger.Infof("not allow %v call this method ,need check auth by polkit", caller) - return polkit.CheckAuth(polkitActionChangeOwnData, string(sender), nil) - } - - } else { - logger.Info("caller's uid is 0,allow to call this method") - return nil - } -} +const polkitActionChangeOwnData = "com.deepin.daemon.accounts.user-administration" +const polkitActionChangeUpgradeDelivery = "com.deepin.lastore.doUpgradeDelivery" +const polkitActionEnableUpgradeDelivery = "com.deepin.lastore.enableUpgradeDelivery" +const polkitActionDisableUpgradeDelivery = "com.deepin.lastore.disableUpgradeDelivery" type UpdateSourceConfig map[config.RepoType]*RepoInfo type RepoInfo struct { diff --git a/src/lastore-daemon/exported_methods_auto.go b/src/lastore-daemon/exported_methods_auto.go index e66fc1b03..e4d0120ff 100644 --- a/src/lastore-daemon/exported_methods_auto.go +++ b/src/lastore-daemon/exported_methods_auto.go @@ -166,6 +166,11 @@ func (v *Manager) GetExportedMethods() dbusutil.ExportedMethods { Fn: v.UpdateSource, OutArgs: []string{"job"}, }, + { + Name: "SetAllowCaller", + Fn: v.SetAllowCaller, + InArgs: []string{"uniqueName"}, + }, { // 危险函数 Name: "GetUpdateDetails", Fn: v.GetUpdateDetails, diff --git a/src/lastore-daemon/inhibitor.go b/src/lastore-daemon/inhibitor.go index 92615cd2c..2d6db1095 100644 --- a/src/lastore-daemon/inhibitor.go +++ b/src/lastore-daemon/inhibitor.go @@ -31,23 +31,6 @@ const ( methodCallerAppStore ) -func mapMethodCaller(execPath string, cmdLine string) methodCaller { - logger.Debug("execPath:", execPath, "cmdLine:", cmdLine) - switch execPath { - case appStoreDaemonPath, oldAppStoreDaemonPath: - return methodCallerAppStore - case controlCenterPath: - return methodCallerControlCenter - default: - switch cmdLine { - case controlCenterCmdLine: - return methodCallerControlCenter - default: - return methodCallerOtherCaller - } - } -} - func (m *Manager) updateSystemOnChanging(onChanging bool, caller methodCaller) { if onChanging && m.inhibitFd == -1 { var why string diff --git a/src/lastore-daemon/main.go b/src/lastore-daemon/main.go index cb1594dd3..3a571df54 100644 --- a/src/lastore-daemon/main.go +++ b/src/lastore-daemon/main.go @@ -86,8 +86,7 @@ func main() { aptImpl := dut.NewSystem(config.NonUnknownList, config.OtherSourceList, config.UseIncrementalUpdate()) system.SetSystemUpdate(config.PlatformUpdate) // 设置是否通过平台更新 - allowInstallPackageExecPaths = append(allowInstallPackageExecPaths, config.AllowInstallRemovePkgExecPaths...) - allowRemovePackageExecPaths = append(allowRemovePackageExecPaths, config.AllowInstallRemovePkgExecPaths...) + // 安装/卸载接口不再追加可执行路径白名单,改由 allow-caller、特殊 uid 和 polkit 共同鉴权。 manager := NewManager(service, aptImpl, config) updater := NewUpdater(service, manager, config) diff --git a/src/lastore-daemon/manager.go b/src/lastore-daemon/manager.go index a62816c6e..5af9d9d4e 100644 --- a/src/lastore-daemon/manager.go +++ b/src/lastore-daemon/manager.go @@ -114,6 +114,9 @@ type Manager struct { logTmpFile *os.File isAutoCheckTimerFirstRun bool + + trustedCallerUIDs map[uint32]struct{} + allowCallServiceList strv.Strv } /* @@ -143,6 +146,7 @@ func NewManager(service *dbusutil.Service, updateApi system.System, c *config.Co securitySourceConfig: make(UpdateSourceConfig), systemSourceConfig: make(UpdateSourceConfig), DownloadLimitOnChanging: false, + trustedCallerUIDs: initTrustedCallerUIDs(), } m.reloadOemConfig(true) m.signalLoop.Start() @@ -206,6 +210,7 @@ func (m *Manager) initDbusSignalListen() { if m.userAgents != nil { m.userAgents.handleNameLost(name) } + m.removeAllowCaller(name) } }) if err != nil { @@ -384,12 +389,6 @@ func (m *Manager) delUpdatePackage(sender dbus.Sender, jobName string, packages return nil, fmt.Errorf("invalid packages arguments %q : %v", packages, err) } - execPath, cmdLine, err := getExecutablePathAndCmdline(m.service, sender) - if err != nil { - logger.Warning(err) - return nil, dbusutil.ToError(err) - } - caller := mapMethodCaller(execPath, cmdLine) m.ensureUpdateSourceOnce() environ, err := makeEnvironWithSender(m, sender) if err != nil { @@ -410,7 +409,6 @@ func (m *Manager) delUpdatePackage(sender dbus.Sender, jobName string, packages return nil, err } - job.caller = caller return job, err } @@ -696,7 +694,7 @@ func (m *Manager) delFixError(sender dbus.Sender, errType string) (*Job, error) func (m *Manager) updateModeWriteCallback(pw *dbusutil.PropertyWrite) *dbus.Error { // 调用者判断 - err := checkInvokePermission(m.service, pw.Sender) + err := m.checkInvokePermission(pw.Sender) if err != nil { logger.Warning(err) return dbusutil.ToError(err) @@ -757,7 +755,7 @@ func (m *Manager) syncThirdPartyDconfig() { func (m *Manager) checkUpdateModeWriteCallback(pw *dbusutil.PropertyWrite) *dbus.Error { // 调用者判断 - err := checkInvokePermission(m.service, pw.Sender) + err := m.checkInvokePermission(pw.Sender) if err != nil { logger.Warning(err) return dbusutil.ToError(err) @@ -1337,3 +1335,22 @@ func (m *Manager) processLogFds(message string) { // 更新logFds,只保留有效的fd m.logFds = validFds } + +func (m *Manager) checkInvokePermission(sender dbus.Sender) error { + uid, err := m.service.GetConnUID(string(sender)) + if err != nil { + return fmt.Errorf("failed to get sender conn uid:%v", err) + } + m.PropsMu.RLock() + // 控制中心等前端可能经 deepin-security-loader 启动,先按 trusted sender 放行,其余调用方再走 polkit。 + if !m.isTrustedSender(uid, sender) { + err = polkit.CheckAuth(polkitActionChangeOwnData, string(sender), nil) + if err != nil { + logger.Warning(err) + m.PropsMu.RUnlock() + return dbusutil.ToError(err) + } + } + m.PropsMu.RUnlock() + return nil +} diff --git a/src/lastore-daemon/manager_auth.go b/src/lastore-daemon/manager_auth.go new file mode 100644 index 000000000..1aabafe84 --- /dev/null +++ b/src/lastore-daemon/manager_auth.go @@ -0,0 +1,270 @@ +// SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +package main + +import ( + "fmt" + "os" + "os/user" + "path/filepath" + "strconv" + "strings" + "sync" + + "github.com/godbus/dbus/v5" + "github.com/linuxdeepin/go-lib/keyfile" + "github.com/linuxdeepin/go-lib/strv" +) + +const ( + allowCallerStateSection = "AuthState" + allowCallerBusIDKey = "BusId" + callerKey = "AllowCallerList" + lightdmUserName = "lightdm" +) + +var ( + // 允许调用者名单只保存在运行时目录,避免写入公共可写路径。 + allowCallerStateFile = "/run/lastore/allow-callers.ini" + lookupUserByName = func(name string) (uint32, error) { + u, err := user.Lookup(name) + if err != nil { + return 0, err + } + + uid, err := strconv.ParseUint(u.Uid, 10, 32) + if err != nil { + return 0, err + } + return uint32(uid), nil + } +) + +type allowCallerState struct { + BusID string + Callers strv.Strv +} + +var allowCallerStateMu sync.Mutex + +func isAllowCallerUniqueName(name string) bool { + return strings.HasPrefix(name, ":") +} + +func initTrustedCallerUIDs() map[uint32]struct{} { + trustedUIDs := make(map[uint32]struct{}) + + // greeter 这类特殊 uid 调用方不走 allow-caller 注册,直接按 uid 信任。 + uid, err := lookupUserByName(lightdmUserName) + if err != nil { + logger.Warning(err) + return trustedUIDs + } + trustedUIDs[uid] = struct{}{} + return trustedUIDs +} + +func (m *Manager) isTrustedSender(uid uint32, sender dbus.Sender) bool { + if uid == 0 { + return true + } + if _, ok := m.trustedCallerUIDs[uid]; ok { + return true + } + + // loader 启动的前端通过 SetAllowCaller 记录到 unique name 白名单里。 + m.PropsMu.RLock() + ok := m.allowCallServiceList.Contains(string(sender)) + m.PropsMu.RUnlock() + return ok +} + +func (m *Manager) getSystemBusID() (string, error) { + if m.sysDBusDaemon == nil { + return "", fmt.Errorf("system bus daemon is nil") + } + return m.sysDBusDaemon.GetId(dbus.Flags(0)) +} + +func readAllowCallerState(path string) (*allowCallerState, error) { + _, err := os.Stat(path) + if err != nil { + if os.IsNotExist(err) { + return nil, nil + } + return nil, err + } + + kf := keyfile.NewKeyFile() + err = kf.LoadFromFile(path) + if err != nil { + return nil, err + } + + busID, err := kf.GetString(allowCallerStateSection, allowCallerBusIDKey) + if err != nil { + return nil, err + } + + callers, err := kf.GetStringList(allowCallerStateSection, callerKey) + if err != nil { + if _, ok := err.(keyfile.KeyNotFoundError); !ok { + return nil, err + } + } + + return &allowCallerState{ + BusID: busID, + Callers: strv.Strv(callers).FilterEmpty().Uniq(), + }, nil +} + +func (m *Manager) persistAllowCallerState(callers strv.Strv) error { + allowCallerStateMu.Lock() + defer allowCallerStateMu.Unlock() + + callers = callers.FilterEmpty().Uniq() + if len(callers) == 0 { + err := os.Remove(allowCallerStateFile) + if err != nil && !os.IsNotExist(err) { + return err + } + return nil + } + + busID, err := m.getSystemBusID() + if err != nil { + return err + } + + err = os.MkdirAll(filepath.Dir(allowCallerStateFile), 0700) + if err != nil { + return err + } + + kf := keyfile.NewKeyFile() + kf.SetString(allowCallerStateSection, allowCallerBusIDKey, busID) + kf.SetStringList(allowCallerStateSection, callerKey, callers) + return kf.SaveToFile(allowCallerStateFile) +} + +func (m *Manager) loadAllowCaller() { + allowCallerStateMu.Lock() + defer allowCallerStateMu.Unlock() + + state, err := readAllowCallerState(allowCallerStateFile) + if err != nil { + logger.Warning(err) + return + } + if state == nil { + return + } + + currentBusID, err := m.getSystemBusID() + if err != nil { + logger.Warning(err) + return + } + + // unique name 只在当前 system bus 生命周期内有效,bus 变了就整体丢弃。 + if state.BusID != currentBusID { + m.PropsMu.Lock() + m.allowCallServiceList = nil + m.PropsMu.Unlock() + err = os.Remove(allowCallerStateFile) + if err != nil && !os.IsNotExist(err) { + logger.Warning(err) + } + return + } + + validCallers := make(strv.Strv, 0, len(state.Callers)) + for _, name := range state.Callers { + if !isAllowCallerUniqueName(name) { + continue + } + // 运行时文件里可能残留已断开的连接,启动时按当前 owner 重新过滤一次。 + owner, err := m.sysDBusDaemon.GetNameOwner(dbus.Flags(0), name) + if err != nil { + continue + } + if owner == name { + validCallers = append(validCallers, name) + } + } + + m.PropsMu.Lock() + m.allowCallServiceList = validCallers + m.PropsMu.Unlock() + + if !validCallers.Equal(state.Callers) { + if len(validCallers) == 0 { + err = os.Remove(allowCallerStateFile) + if err != nil && !os.IsNotExist(err) { + logger.Warning(err) + } + return + } + + kf := keyfile.NewKeyFile() + kf.SetString(allowCallerStateSection, allowCallerBusIDKey, currentBusID) + kf.SetStringList(allowCallerStateSection, callerKey, validCallers) + err = kf.SaveToFile(allowCallerStateFile) + if err != nil { + logger.Warning(err) + } + } +} + +func (m *Manager) addAllowCaller(uniqueName string) error { + if !isAllowCallerUniqueName(uniqueName) { + return fmt.Errorf("%q is not a dbus unique name", uniqueName) + } + if m.sysDBusDaemon == nil { + return fmt.Errorf("system bus daemon is nil") + } + // 受信任 daemon 允许代前端注册,但 unique name 必须是当前真实存在的连接。 + owner, err := m.sysDBusDaemon.GetNameOwner(dbus.Flags(0), uniqueName) + if err != nil { + return err + } + if owner != uniqueName { + return fmt.Errorf("%q is not owned by current dbus connection", uniqueName) + } + + m.PropsMu.Lock() + oldList := append(strv.Strv(nil), m.allowCallServiceList...) + newList, _ := m.allowCallServiceList.Add(uniqueName) + m.allowCallServiceList = newList + snapshot := append(strv.Strv(nil), m.allowCallServiceList...) + m.PropsMu.Unlock() + + err = m.persistAllowCallerState(snapshot) + if err != nil { + m.PropsMu.Lock() + m.allowCallServiceList = oldList + m.PropsMu.Unlock() + return err + } + return nil +} + +func (m *Manager) removeAllowCaller(uniqueName string) { + m.PropsMu.Lock() + newList, removed := m.allowCallServiceList.Delete(uniqueName) + if !removed { + m.PropsMu.Unlock() + return + } + m.allowCallServiceList = newList + snapshot := append(strv.Strv(nil), m.allowCallServiceList...) + m.PropsMu.Unlock() + + err := m.persistAllowCallerState(snapshot) + if err != nil { + logger.Warning(err) + } +} diff --git a/src/lastore-daemon/manager_ifc.go b/src/lastore-daemon/manager_ifc.go index a7aabda33..7e2ac9200 100644 --- a/src/lastore-daemon/manager_ifc.go +++ b/src/lastore-daemon/manager_ifc.go @@ -81,23 +81,17 @@ func (m *Manager) HandleSystemEvent(sender dbus.Sender, eventType string) *dbus. func (m *Manager) InstallPackage(sender dbus.Sender, jobName string, packages string) (job dbus.ObjectPath, busErr *dbus.Error) { m.service.DelayAutoQuit() - execPath, cmdLine, err := getExecutablePathAndCmdline(m.service, sender) - if err != nil { - logger.Warning(err) - return "/", dbusutil.ToError(err) - } uid, err := m.service.GetConnUID(string(sender)) if err != nil { logger.Warning(err) return "/", dbusutil.ToError(err) } - if !allowInstallPackageExecPaths.Contains(execPath) && - uid != 0 { - // 白名单未通过时需要管理员鉴权 + // root、特殊 uid 和 allow-caller 白名单直通,其余调用方走 polkit。 + if !m.isTrustedSender(uid, sender) { err = polkit.CheckAuth(polkitActionChangeOwnData, string(sender), nil) if err != nil { - err = fmt.Errorf("%q is not in allowed install package paths.And the caller not pass the authentication, don't allow to install packages %v", execPath, packages) + err = fmt.Errorf("caller is not in allowed install package paths. And the caller not pass the authentication, don't allow to install packages %v", packages) logger.Warning(err) return "/", dbusutil.ToError(err) } @@ -107,7 +101,6 @@ func (m *Manager) InstallPackage(sender dbus.Sender, jobName string, packages st if err != nil { return "/", dbusutil.ToError(err) } - jobObj.next.caller = mapMethodCaller(execPath, cmdLine) return jobObj.getPath(), nil } @@ -292,31 +285,10 @@ func (m *Manager) RegisterAgent(sender dbus.Sender, path dbus.ObjectPath) *dbus. func (m *Manager) RemovePackage(sender dbus.Sender, jobName string, packages string) (job dbus.ObjectPath, busErr *dbus.Error) { m.service.DelayAutoQuit() - //execPath, cmdLine, err := getExecutablePathAndCmdline(m.service, sender) - //if err != nil { - // logger.Warning(err) - // return "/", dbusutil.ToError(err) - //} - // - //uid, err := m.service.GetConnUID(string(sender)) - //if err != nil { - // logger.Warning(err) - // return "/", dbusutil.ToError(err) - //} - // - //if !allowRemovePackageExecPaths.Contains(execPath) && - // uid != 0 { - // err = fmt.Errorf("%q is not allowed to remove packages", execPath) - // logger.Warning(err) - // return "/", dbusutil.ToError(err) - //} - // TODO - // 鉴权或者给 dde-launcher 加 loader 启动,或者是否可以给 dde-launcher setgid and set group deepin-daemon jobObj, err := m.removePackage(sender, jobName, packages) if err != nil { return "/", dbusutil.ToError(err) } - //jobObj.caller = mapMethodCaller(execPath, cmdLine) return jobObj.getPath(), nil } @@ -382,6 +354,21 @@ func (m *Manager) UpdateSource(sender dbus.Sender) (job dbus.ObjectPath, busErr func (m *Manager) DistUpgradePartly(sender dbus.Sender, mode system.UpdateType, needBackup bool) (job dbus.ObjectPath, busErr *dbus.Error) { m.service.DelayAutoQuit() + + uid, err := m.service.GetConnUID(string(sender)) + if err != nil { + logger.Warning(err) + return "/", dbusutil.ToError(err) + } + // root、特殊 uid 和 allow-caller 白名单直通,其余调用方走 polkit。 + if !m.isTrustedSender(uid, sender) { + err = polkit.CheckAuth(polkitActionChangeOwnData, string(sender), nil) + if err != nil { + logger.Warning(err) + return "/", dbusutil.ToError(err) + } + } + return m.distUpgradePartly(sender, mode, needBackup) } @@ -397,9 +384,20 @@ func (m *Manager) DistUpgradePartly(sender dbus.Sender, mode system.UpdateType, func (m *Manager) PrepareFullScreenUpgrade(sender dbus.Sender, option string) *dbus.Error { supportOption := len(strings.TrimSpace(option)) > 0 - // TODO - // 应该只有 dde-lock 会调用 - // 用鉴权方案或者给 dde-lock 增加 group + uid, err := m.service.GetConnUID(string(sender)) + if err != nil { + logger.Warning(err) + return dbusutil.ToError(err) + } + // 锁屏前端可能经 deepin-security-loader 启动,先按 trusted sender 放行,其余调用方再走 polkit。 + // root、特殊 uid 和 allow-caller 白名单直通,其余调用方走 polkit。 + if !m.isTrustedSender(uid, sender) { + err = polkit.CheckAuth(polkitActionChangeOwnData, string(sender), nil) + if err != nil { + logger.Warning(err) + return dbusutil.ToError(err) + } + } logger.Info("start PrepareFullScreenUpgrade") if supportOption { @@ -461,7 +459,7 @@ func (m *Manager) PrepareFullScreenUpgrade(sender dbus.Sender, option string) *d } // 如果上述方法出错,需要采用重启display-manager方案,此时所有图形session也都会退出 - _, err := m.systemd.RestartUnit(0, "display-manager.service", "replace") + _, err = m.systemd.RestartUnit(0, "display-manager.service", "replace") if err != nil { logger.Warning(err) return dbusutil.ToError(err) @@ -495,6 +493,21 @@ func (m *Manager) QueryAllSizeWithSource(mode system.UpdateType) (int64, *dbus.E func (m *Manager) PrepareDistUpgradePartly(sender dbus.Sender, mode system.UpdateType) (job dbus.ObjectPath, busErr *dbus.Error) { m.service.DelayAutoQuit() + + uid, err := m.service.GetConnUID(string(sender)) + if err != nil { + logger.Warning(err) + return "/", dbusutil.ToError(err) + } + // root、特殊 uid 和 allow-caller 白名单直通,其余调用方走 polkit。 + if !m.isTrustedSender(uid, sender) { + err = polkit.CheckAuth(polkitActionChangeOwnData, string(sender), nil) + if err != nil { + logger.Warning(err) + return "/", dbusutil.ToError(err) + } + } + jobObj, err := m.prepareDistUpgrade(sender, mode, initiatorUser) if err != nil { logger.Warning(err) @@ -515,25 +528,9 @@ func (m *Manager) CheckUpgrade(sender dbus.Sender, checkMode system.UpdateType, } func (m *Manager) PowerOff(sender dbus.Sender, reboot bool) *dbus.Error { - checkExecPath := func() error { - // 只有dde-update可以设置 - execPath, _, err := getExecutablePathAndCmdline(m.service, sender) - if err != nil { - logger.Warning(err) - return err - } - if strings.Contains(execPath, "dde-update") || - strings.Contains(execPath, "dde-rollback") { - return nil - } else { - err = fmt.Errorf("%v not allow to call this method", execPath) - logger.Warning(err) - return err - } - } uid, err := m.service.GetConnUID(string(sender)) if err != nil || uid != 0 { - err = checkExecPath() + err = polkit.CheckAuth(polkitActionChangeOwnData, string(sender), nil) if err != nil { return dbusutil.ToError(err) } @@ -560,7 +557,7 @@ func (m *Manager) PowerOff(sender dbus.Sender, reboot bool) *dbus.Error { // SetUpdateSources 设置系统、安全更新的仓库 func (m *Manager) SetUpdateSources(sender dbus.Sender, updateType system.UpdateType, repoType config.RepoType, repoConfig []string, isReset bool) *dbus.Error { // 管理员鉴权 - err := checkInvokePermission(m.service, sender) + err := m.checkInvokePermission(sender) if err != nil { logger.Warning(err) return dbusutil.ToError(err) @@ -695,3 +692,15 @@ func (m *Manager) GetUpdateDetails(sender dbus.Sender, fd dbus.UnixFD, realTime } return nil } + +func (m *Manager) SetAllowCaller(uniqueName string) *dbus.Error { + logger.Infof("try to add allow caller unique name: %q", uniqueName) + err := m.addAllowCaller(uniqueName) + logger.Infof("current allow caller list is :%+v", m.allowCallServiceList) + if err != nil { + logger.Warning(err) + return dbusutil.ToError(err) + } + logger.Infof("all allow sender is :%+v", m.allowCallServiceList) + return nil +} diff --git a/src/lastore-daemon/manager_upgrade.go b/src/lastore-daemon/manager_upgrade.go index c1e9e97d0..76d7abe03 100644 --- a/src/lastore-daemon/manager_upgrade.go +++ b/src/lastore-daemon/manager_upgrade.go @@ -374,12 +374,6 @@ func (m *Manager) distUpgrade(sender dbus.Sender, mode system.UpdateType, needAd if !system.IsAuthorized() { return nil, errors.New("not authorized, don't allow to exec upgrade") } - execPath, cmdLine, err := getExecutablePathAndCmdline(m.service, sender) - if err != nil { - logger.Warning(err) - return nil, dbusutil.ToError(err) - } - caller := mapMethodCaller(execPath, cmdLine) // TODO 需要对调用者进行鉴权 m.ensureUpdateSourceOnce() environ, err := makeEnvironWithSender(m, sender) if err != nil { @@ -426,7 +420,6 @@ func (m *Manager) distUpgrade(sender dbus.Sender, mode system.UpdateType, needAd logger.Infof("%v is exist", system.DistUpgradeJobType) return JobExistError } - job.caller = caller if utils.IsDir(path) { job.option = map[string]string{