Skip to content

Commit cb2d794

Browse files
committed
fix(auth): unify caller authentication to isTrustedSender and remove binary path identification
Replace binary path-based caller identification (getExecutablePathAndCmdline, mapMethodCaller, checkInvokePermission, checkSenderNsMntValid) with isTrustedSender + polkit authentication across all protected interfaces (InstallPackage, RemovePackage, DistUpgradePartly, PrepareDistUpgradePartly, PrepareFullScreenUpgrade, PowerOff, SetUpdateSources, UpdateMode, CheckUpdateModeWrite). Remove hardcoded executable path constants and whitelists (allowInstallPackageExecPaths, allowRemovePackageExecPaths). Introduce manager_auth.go with allow-caller registration, lightdm trusted UID support, and persistent runtime state under /run/lastore. Export SetAllowCaller D-Bus method for deepin-security-loader integration. Add D-Bus access rules: deny SetAllowCaller/PowerOff for default policy, allow deepin-daemon and lightdm groups. Configure RuntimeDirectoryMode to 0700 with RuntimeDirectoryPreserve=yes. Add appstore_intranet.list to trusted source list. Remove deprecated deny-exec-whitelist and install-package-support-auth config items. Add isInstallLikeJobType helper. Refactor PrepareFullScreenUpgrade to use terminate() closure and add dde-update fallback path. Add unit tests for manager_auth (isTrustedSender, SetAllowCaller persistence, runtime state load/remove, bus restart cleanup) and isInstallLikeJobType. Fix appinfo_test to use t.TempDir() instead of hardcoded /tmp path.
1 parent 69ddbf6 commit cb2d794

16 files changed

Lines changed: 618 additions & 259 deletions

File tree

lib/systemd/system/lastore-daemon.service

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ ExecStart=/usr/libexec/lastore-daemon/lastore-daemon
2323
NoNewPrivileges=true
2424
ProtectClock=true
2525
RuntimeDirectory=lastore
26-
RuntimeDirectoryMode=0750
26+
RuntimeDirectoryMode=0700
27+
RuntimeDirectoryPreserve=yes
2728
StandardError=null
2829
StandardOutput=null
2930
Type=dbus

src/lastore-daemon/common.go

Lines changed: 0 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import (
99
"crypto/sha256"
1010
"encoding/hex"
1111
"encoding/json"
12-
"errors"
1312
"fmt"
1413
"io"
1514
"os"
@@ -23,16 +22,13 @@ import (
2322
"time"
2423
"unicode/utf8"
2524

26-
"github.com/linuxdeepin/dde-api/polkit"
2725
utils2 "github.com/linuxdeepin/go-lib/utils"
2826
"github.com/linuxdeepin/lastore-daemon/src/internal/config"
2927
"github.com/linuxdeepin/lastore-daemon/src/internal/system"
3028
"github.com/linuxdeepin/lastore-daemon/src/internal/system/apt"
3129

3230
"github.com/godbus/dbus/v5"
33-
"github.com/linuxdeepin/go-lib/dbusutil"
3431
"github.com/linuxdeepin/go-lib/procfs"
35-
"github.com/linuxdeepin/go-lib/strv"
3632
)
3733

3834
var _urlReg = regexp.MustCompile(`^[ ]*deb .*((?:https?|ftp|file|p2p|delivery)://[^ ]+)`)
@@ -270,82 +266,6 @@ func parseAutoDownloadRange(idleDownloadConfig idleDownloadConfig, now time.Time
270266
return NewTimeRange(beginTime, endTime), nil
271267
}
272268

273-
const (
274-
appStoreDaemonPath = "/usr/bin/deepin-app-store-daemon"
275-
oldAppStoreDaemonPath = "/usr/bin/deepin-appstore-daemon"
276-
printerPath = "/usr/bin/dde-printer"
277-
printerHelperPath = "/usr/bin/dde-printer-helper"
278-
sessionDaemonPath = "/usr/lib/deepin-daemon/dde-session-daemon"
279-
langSelectorPath = "/usr/lib/deepin-daemon/langselector"
280-
controlCenterPath = "/usr/bin/dde-control-center"
281-
controlCenterCmdLine = "/usr/share/applications/dde-control-center.deskto" // 缺个 p 是因为 deepin-turbo 修改命令的时候 buffer 不够用, 所以截断了.
282-
oldControlCenterPath = "/usr/lib/x86_64-linux-gnu/dde-control-center/dde-control-center-old"
283-
dataTransferPath = "/usr/bin/deepin-data-transfer"
284-
amDaemonPath = "/usr/bin/dde-application-manager"
285-
launcherPath = "/usr/bin/dde-launcher"
286-
amDaemonCompatPath = "/usr/libexec/dde-application-wizard-daemon-compat"
287-
)
288-
289-
// TODO delete
290-
var (
291-
allowInstallPackageExecPaths = strv.Strv{
292-
appStoreDaemonPath,
293-
oldAppStoreDaemonPath,
294-
printerPath,
295-
printerHelperPath,
296-
langSelectorPath,
297-
controlCenterPath,
298-
oldControlCenterPath,
299-
dataTransferPath,
300-
}
301-
allowRemovePackageExecPaths = strv.Strv{
302-
appStoreDaemonPath,
303-
oldAppStoreDaemonPath,
304-
sessionDaemonPath,
305-
langSelectorPath,
306-
controlCenterPath,
307-
oldControlCenterPath,
308-
amDaemonPath,
309-
launcherPath,
310-
amDaemonCompatPath,
311-
}
312-
)
313-
314-
// execPath和cmdLine可以有一个为空,其中一个存在即可作为判断调用者的依据
315-
func getExecutablePathAndCmdline(service *dbusutil.Service, sender dbus.Sender) (string, string, error) {
316-
pid, err := service.GetConnPID(string(sender))
317-
if err != nil {
318-
return "", "", err
319-
}
320-
321-
proc := procfs.Process(pid)
322-
execPath, err := proc.Exe()
323-
if err != nil {
324-
// 当调用者在使用过程中发生了更新,则在获取该进程的exe时,会出现lstat xxx (deleted)此类的error,如果发生的是覆盖,则该路径依旧存在,因此增加以下判断
325-
var pErr *os.PathError
326-
ok := errors.As(err, &pErr)
327-
if ok {
328-
if os.IsNotExist(pErr.Err) {
329-
errExecPath := strings.Replace(pErr.Path, "(deleted)", "", -1)
330-
oldExecPath := strings.TrimSpace(errExecPath)
331-
if system.NormalFileExists(oldExecPath) {
332-
execPath = oldExecPath
333-
err = nil
334-
}
335-
}
336-
}
337-
}
338-
339-
cmdLine, err1 := proc.Cmdline()
340-
if err != nil && err1 != nil {
341-
return "", "", errors.New(strings.Join([]string{
342-
err.Error(),
343-
err1.Error(),
344-
}, ";"))
345-
}
346-
return execPath, strings.Join(cmdLine, " "), nil
347-
}
348-
349269
// 根据类型过滤数据
350270
func getFilterPackages(infosMap map[string][]string, updateType system.UpdateType) []string {
351271
var r []string
@@ -556,62 +476,13 @@ func getCoreListOnline() []string {
556476
return pkgs
557477
}
558478

559-
var _initProcNsMnt string
560-
var _once sync.Once
561-
562-
// 通过判断/proc/pid/ns/mnt 和 /proc/1/ns/mnt是否相同,如果不相同,则进程exe字段不可信
563-
func checkSenderNsMntValid(pid uint32) bool {
564-
_once.Do(func() {
565-
out, err := os.Readlink("/proc/1/ns/mnt")
566-
if err != nil {
567-
fmt.Println(err)
568-
return
569-
}
570-
_initProcNsMnt = strings.TrimSpace(out)
571-
})
572-
c, err := os.Readlink(fmt.Sprintf("/proc/%v/ns/mnt", pid))
573-
if err != nil {
574-
fmt.Println(err)
575-
return false
576-
}
577-
defer func() {
578-
fmt.Printf("pid 1 mnt ns is %v,pid %v mnt ns is %v\n", _initProcNsMnt, pid, strings.TrimSpace(c))
579-
}()
580-
return strings.TrimSpace(c) == _initProcNsMnt
581-
}
582-
583479
const (
584480
polkitActionChangeOwnData = "com.deepin.lastore.user-administration"
585481
polkitActionChangeUpgradeDelivery = "com.deepin.lastore.doUpgradeDelivery"
586482
polkitActionEnableUpgradeDelivery = "com.deepin.lastore.enableUpgradeDelivery"
587483
polkitActionDisableUpgradeDelivery = "com.deepin.lastore.disableUpgradeDelivery"
588484
)
589485

590-
func checkInvokePermission(service *dbusutil.Service, sender dbus.Sender) error {
591-
uid, err := service.GetConnUID(string(sender))
592-
if err != nil {
593-
return fmt.Errorf("failed to get sender conn uid:%v", err)
594-
}
595-
if uid != 0 {
596-
execPath, cmdLine, err := getExecutablePathAndCmdline(service, sender)
597-
if err != nil {
598-
logger.Warning(err)
599-
return polkit.CheckAuth(polkitActionChangeOwnData, string(sender), nil)
600-
}
601-
caller := mapMethodCaller(execPath, cmdLine)
602-
if methodCallerControlCenter == caller {
603-
return nil
604-
} else {
605-
logger.Infof("not allow %v call this method ,need check auth by polkit", caller)
606-
return polkit.CheckAuth(polkitActionChangeOwnData, string(sender), nil)
607-
}
608-
609-
} else {
610-
logger.Info("caller's uid is 0,allow to call this method")
611-
return nil
612-
}
613-
}
614-
615486
type UpdateSourceConfig map[config.RepoType]*RepoInfo
616487
type RepoInfo struct {
617488
/*

src/lastore-daemon/exported_methods_auto.go

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/lastore-daemon/inhibitor.go

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -31,23 +31,6 @@ const (
3131
methodCallerAppStore
3232
)
3333

34-
func mapMethodCaller(execPath string, cmdLine string) methodCaller {
35-
logger.Debug("execPath:", execPath, "cmdLine:", cmdLine)
36-
switch execPath {
37-
case appStoreDaemonPath, oldAppStoreDaemonPath:
38-
return methodCallerAppStore
39-
case controlCenterPath:
40-
return methodCallerControlCenter
41-
default:
42-
switch cmdLine {
43-
case controlCenterCmdLine:
44-
return methodCallerControlCenter
45-
default:
46-
return methodCallerOtherCaller
47-
}
48-
}
49-
}
50-
5134
func (m *Manager) updateSystemOnChanging(onChanging bool, caller methodCaller) {
5235
if onChanging && m.inhibitFd == -1 {
5336
var why string

src/lastore-daemon/job_manager.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,20 @@ func (jm *JobManager) CreateJob(jobName, jobType string, packages []string, envi
254254
return false, job, jm.markReady(job)
255255
}
256256

257+
func isInstallLikeJobType(jobType string) bool {
258+
switch jobType {
259+
case system.InstallJobType,
260+
system.OnlyInstallJobType,
261+
system.SystemUpgradeJobType,
262+
system.SecurityUpgradeJobType,
263+
system.UnknownUpgradeJobType,
264+
system.AppStoreUpgradeJobType:
265+
return true
266+
default:
267+
return false
268+
}
269+
}
270+
257271
func (jm *JobManager) markStart(job *Job) error {
258272
jm.markDirty()
259273

src/lastore-daemon/main.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,7 @@ func main() {
8686

8787
aptImpl := dut.NewSystem(config.NonUnknownList, config.OtherSourceList, config.UseIncrementalUpdate())
8888
system.SetSystemUpdate(config.PlatformUpdate) // 设置是否通过平台更新
89-
allowInstallPackageExecPaths = append(allowInstallPackageExecPaths, config.AllowInstallRemovePkgExecPaths...)
90-
allowRemovePackageExecPaths = append(allowRemovePackageExecPaths, config.AllowInstallRemovePkgExecPaths...)
89+
// 安装/卸载接口不再追加可执行路径白名单,改由 allow-caller、特殊 uid 和 polkit 共同鉴权。
9190
manager := NewManager(service, aptImpl, config)
9291
updater := NewUpdater(service, manager, config)
9392

src/lastore-daemon/manager.go

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,9 @@ type Manager struct {
114114
logTmpFile *os.File
115115

116116
isAutoCheckTimerFirstRun bool
117+
allowCallServiceList strv.Strv
118+
// 特殊 uid 调用方直接放行,当前用于兼容 lightdm greeter 场景。
119+
trustedCallerUIDs map[uint32]struct{}
117120
}
118121

119122
/*
@@ -143,6 +146,7 @@ func NewManager(service *dbusutil.Service, updateApi system.System, c *config.Co
143146
securitySourceConfig: make(UpdateSourceConfig),
144147
systemSourceConfig: make(UpdateSourceConfig),
145148
DownloadLimitOnChanging: false,
149+
trustedCallerUIDs: initTrustedCallerUIDs(),
146150
}
147151
m.reloadOemConfig(true)
148152
m.signalLoop.Start()
@@ -206,6 +210,7 @@ func (m *Manager) initDbusSignalListen() {
206210
if m.userAgents != nil {
207211
m.userAgents.handleNameLost(name)
208212
}
213+
m.removeAllowCaller(name)
209214
}
210215
})
211216
if err != nil {
@@ -384,12 +389,6 @@ func (m *Manager) delUpdatePackage(sender dbus.Sender, jobName string, packages
384389
return nil, fmt.Errorf("invalid packages arguments %q : %v", packages, err)
385390
}
386391

387-
execPath, cmdLine, err := getExecutablePathAndCmdline(m.service, sender)
388-
if err != nil {
389-
logger.Warning(err)
390-
return nil, dbusutil.ToError(err)
391-
}
392-
caller := mapMethodCaller(execPath, cmdLine)
393392
m.ensureUpdateSourceOnce()
394393
environ, err := makeEnvironWithSender(m, sender)
395394
if err != nil {
@@ -410,7 +409,6 @@ func (m *Manager) delUpdatePackage(sender dbus.Sender, jobName string, packages
410409
return nil, err
411410
}
412411

413-
job.caller = caller
414412
return job, err
415413
}
416414

@@ -696,7 +694,7 @@ func (m *Manager) delFixError(sender dbus.Sender, errType string) (*Job, error)
696694

697695
func (m *Manager) updateModeWriteCallback(pw *dbusutil.PropertyWrite) *dbus.Error {
698696
// 调用者判断
699-
err := checkInvokePermission(m.service, pw.Sender)
697+
err := m.checkInvokePermission(pw.Sender)
700698
if err != nil {
701699
logger.Warning(err)
702700
return dbusutil.ToError(err)
@@ -757,7 +755,7 @@ func (m *Manager) syncThirdPartyDconfig() {
757755

758756
func (m *Manager) checkUpdateModeWriteCallback(pw *dbusutil.PropertyWrite) *dbus.Error {
759757
// 调用者判断
760-
err := checkInvokePermission(m.service, pw.Sender)
758+
err := m.checkInvokePermission(pw.Sender)
761759
if err != nil {
762760
logger.Warning(err)
763761
return dbusutil.ToError(err)
@@ -1337,3 +1335,22 @@ func (m *Manager) processLogFds(message string) {
13371335
// 更新logFds,只保留有效的fd
13381336
m.logFds = validFds
13391337
}
1338+
1339+
func (m *Manager) checkInvokePermission(sender dbus.Sender) error {
1340+
uid, err := m.service.GetConnUID(string(sender))
1341+
if err != nil {
1342+
return fmt.Errorf("failed to get sender conn uid:%v", err)
1343+
}
1344+
m.PropsMu.RLock()
1345+
// 控制中心等前端可能经 deepin-security-loader 启动,先按 trusted sender 放行,其余调用方再走 polkit。
1346+
if !m.isTrustedSender(uid, sender) {
1347+
err = polkit.CheckAuth(polkitActionChangeOwnData, string(sender), nil)
1348+
if err != nil {
1349+
logger.Warning(err)
1350+
m.PropsMu.RUnlock()
1351+
return dbusutil.ToError(err)
1352+
}
1353+
}
1354+
m.PropsMu.RUnlock()
1355+
return nil
1356+
}

0 commit comments

Comments
 (0)