Skip to content

Commit dfe0d4a

Browse files
committed
feat: Add security restriction configurations to all service files
- Use the deepin-daemon user to run services whenever possible, reducing privilege risks; - Add a D-Bus policy to allow the deepin-daemon user to invoke the HandleSystemEvent method; - Deny users other than root and deepin-daemon from calling HandleSystemEvent, strengthening access control; - "Remove the unused update-metadata-info related scripts and services. Task: https://pms.uniontech.com/task-view-385069.html
1 parent 2e44b10 commit dfe0d4a

18 files changed

Lines changed: 200 additions & 139 deletions

debian/lastore-daemon.postinst

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ case "$1" in
1010
[ -e /lib/systemd/dbus-org.deepin.dde.Lastore1.service ] && rm /lib/systemd/system/dbus-org.deepin.dde.Lastore1.service || true
1111
fi
1212
systemctl daemon-reload || true
13-
/var/lib/lastore/scripts/update_metadata_info || true
1413
/var/lib/lastore/scripts/build_system_info || true
1514
# Fix the problem that the machine id is the same after the system is installed.
1615
if [ -f /etc/machine-id ] && grep -q "a5fa4f1b04514009830c73f3b1f1dd4c" /etc/machine-id; then

lib/systemd/system/lastore-abort-auto-download.service

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,20 @@ Description=System Update Auto Download Abort Service
33
Wants=lastore-daemon.service
44

55
[Service]
6+
CapabilityBoundingSet=
7+
ExecStart=/usr/bin/dbus-send --system --print-reply --dest=org.deepin.dde.Lastore1 /org/deepin/dde/Lastore1 org.deepin.dde.Lastore1.Manager.HandleSystemEvent string:AbortAutoDownload
8+
InaccessiblePaths=-/etc/shadow -/etc/pam.d/ -/etc/NetworkManager/system-connections/ -/etc/security/ -/etc/selinux/ -/etc/deepin-elf-verify/ -/etc/filearmor.d/ -/etc/crypttab -/etc/fstab -/sysroot/ostree/repo/ -/persistent/ostree/repo/
9+
MemoryDenyWriteExecute=true
10+
NoNewPrivileges=true
11+
PrivateDevices=true
12+
PrivateIPC=true
13+
PrivateTmp=true
14+
ProtectClock=true
15+
ProtectHome=true
16+
ProtectKernelModules=true
17+
ProtectKernelTunables=true
18+
ProtectProc=invisible
19+
ProtectSystem=strict
20+
RestrictSUIDSGID=true
621
Type=oneshot
7-
ExecStart=/usr/bin/dbus-send --system --print-reply --dest=org.deepin.dde.Lastore1 /org/deepin/dde/Lastore1 org.deepin.dde.Lastore1.Manager.HandleSystemEvent string:AbortAutoDownload
22+
User=deepin-daemon

lib/systemd/system/lastore-after-upgrade-check.service

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,26 @@ Description=generate config file for check system
33
Before=display-manager.service
44

55
[Service]
6-
Type=oneshot
6+
7+
# PrivateTmp=true is not set because it needs to use /tmp to save state
8+
9+
CapabilityBoundingSet=
710
ExecStart=/var/lib/lastore/scripts/gen_upgrade_check_config.sh
11+
InaccessiblePaths=-/etc/shadow -/etc/pam.d/ -/etc/NetworkManager/system-connections/ -/etc/security/ -/etc/selinux/ -/etc/deepin-elf-verify/ -/etc/filearmor.d/ -/etc/crypttab -/etc/fstab -/sysroot/ostree/repo/ -/persistent/ostree/repo/
12+
MemoryDenyWriteExecute=true
13+
NoNewPrivileges=true
14+
PrivateDevices=true
15+
PrivateIPC=true
16+
ProtectClock=true
17+
ProtectHome=true
18+
ProtectKernelModules=true
19+
ProtectKernelTunables=true
20+
ProtectProc=invisible
21+
ProtectSystem=strict
22+
ReadWritePaths=/tmp/
23+
RestrictSUIDSGID=true
24+
Type=oneshot
25+
User=deepin-daemon
826

927
[Install]
1028
WantedBy=multi-user.target

lib/systemd/system/lastore-auto-download.service

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,19 @@ Description=System Update Auto Download Service
33
Wants=lastore-daemon.service
44

55
[Service]
6+
CapabilityBoundingSet=
7+
ExecStart=/usr/bin/dbus-send --system --print-reply --dest=org.deepin.dde.Lastore1 /org/deepin/dde/Lastore1 org.deepin.dde.Lastore1.Manager.HandleSystemEvent string:AutoDownload
8+
InaccessiblePaths=-/etc/shadow -/etc/pam.d/ -/etc/NetworkManager/system-connections/ -/etc/security/ -/etc/selinux/ -/etc/deepin-elf-verify/ -/etc/filearmor.d/ -/etc/crypttab -/etc/fstab -/sysroot/ostree/repo/ -/persistent/ostree/repo/
9+
MemoryDenyWriteExecute=true
10+
NoNewPrivileges=true
11+
PrivateDevices=true
12+
PrivateIPC=true
13+
PrivateTmp=true
14+
ProtectClock=true
15+
ProtectHome=true
16+
ProtectKernelModules=true
17+
ProtectKernelTunables=true
18+
ProtectSystem=strict
19+
RestrictSUIDSGID=true
620
Type=oneshot
7-
ExecStart=/usr/bin/dbus-send --system --print-reply --dest=org.deepin.dde.Lastore1 /org/deepin/dde/Lastore1 org.deepin.dde.Lastore1.Manager.HandleSystemEvent string:AutoDownload
21+
User=deepin-daemon

lib/systemd/system/lastore-build-system-info.service

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,28 @@
22
Description=Build system info
33

44
[Service]
5-
Type=idle
6-
StartLimitInterval=10s
7-
StartLimitBurst=20
8-
RestartSec=5s
9-
Restart=on-failure
5+
6+
# MemoryDenyWriteExecute=true is not set because the script calls lastore-tools (a Go program compiled with -pie option) which would fail.
7+
# ProtectProc=invisible is not set because the script uses pgrep to check if processes are running
8+
9+
CapabilityBoundingSet=
1010
ExecStart=/var/lib/lastore/scripts/build_system_info -now
11+
InaccessiblePaths=-/etc/shadow -/etc/pam.d/ -/etc/NetworkManager/system-connections/ -/etc/security/ -/etc/selinux/ -/etc/deepin-elf-verify/ -/etc/filearmor.d/ -/etc/crypttab -/etc/fstab -/sysroot/ostree/repo/ -/persistent/ostree/repo/
12+
NoNewPrivileges=true
13+
PrivateDevices=true
14+
PrivateIPC=true
15+
PrivateTmp=true
16+
ProtectClock=true
17+
ProtectHome=true
18+
ProtectKernelModules=true
19+
ProtectKernelTunables=true
20+
ProtectSystem=strict
21+
ReadWritePaths=/var/
22+
Restart=on-failure
23+
RestartSec=5s
24+
RestrictSUIDSGID=true
25+
StartLimitBurst=20
26+
StartLimitInterval=10s
27+
StateDirectory=lastore
28+
Type=idle
29+
User=deepin-daemon

lib/systemd/system/lastore-daemon.service

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,28 @@ Description=Deepin Lastore Daemon
33
After=display-manager.service
44

55
[Service]
6-
Type=dbus
6+
7+
# CapabilityBoundingSet= is not set because it would cause apt execution errors, such as setegid and other operations failing due to insufficient permissions.
8+
# InaccessiblePaths is not set because dpkg needs to be called to upgrade the system.
9+
# MemoryDenyWriteExecute=yes is not set because this is a Go program compiled with -pie option, which would prevent the process from starting.
10+
# PrivateDevices=true is not set because grub-mkconfig is executed when creating backup deployment.
11+
# PrivateTmp=true is not set because it relies on /tmp to record state.
12+
# ProtectHome=true is not set because sudo is needed to connect to the user Session Bus and send DDE message notifications.
13+
# ProtectKernelModules=true is not set because kernel packages need to be installed
14+
# ProtectProc=true is not set because it needs to access caller process environment variables.
15+
# ProtectSystem=strict is not set because dpkg needs to be called to upgrade the system.
16+
# RestrictSUIDSGID=true is not set because some packages may need to set SUID and SGID during installation.
17+
# StateDirectory=lastore is not set because it would conflict with the ownership of smartmirror-daemon and build-system-info services, which need to be owned by deepin-daemon, and enabling this would set the owner to root.
18+
719
BusName=org.deepin.dde.Lastore1
8-
ExecStart=/usr/libexec/lastore-daemon/lastore-daemon
9-
StandardOutput=null
10-
StandardError=null
11-
StateDirectory=lastore
1220
CacheDirectory=lastore
21+
ExecStart=/usr/libexec/lastore-daemon/lastore-daemon
22+
NoNewPrivileges=true
23+
PrivateIPC=true
24+
ProtectClock=true
25+
ProtectKernelTunables=true
1326
RuntimeDirectory=lastore
14-
RuntimeDirectoryMode=0750
27+
RuntimeDirectoryMode=0750
28+
StandardError=null
29+
StandardOutput=null
30+
Type=dbus

lib/systemd/system/lastore-smartmirror-daemon.service

Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5,35 +5,31 @@ Wants=dbus.socket
55
After=dbus.socket
66

77
[Service]
8-
Type=dbus
8+
# Cannot set PrivateNetwork=yes because network access is required.
9+
# Cannot set MemoryDenyWriteExecute=yes because this is a Go program compiled with -pie option, which would prevent the process from starting.
910
BusName=org.deepin.dde.Lastore1.Smartmirror
10-
User=deepin-daemon
11+
CapabilityBoundingSet=
1112
ExecStart=/usr/libexec/lastore-daemon/lastore-smartmirror-daemon
12-
StandardOutput=null
13-
StandardError=journal
14-
15-
ProtectSystem=strict
16-
StateDirectory=lastore
17-
InaccessiblePaths=/etc/shadow
18-
InaccessiblePaths=-/etc/NetworkManager/system-connections
19-
InaccessiblePaths=-/etc/pam.d
20-
InaccessiblePaths=-/usr/share/uadp/
21-
13+
InaccessiblePaths=-/etc/shadow -/etc/pam.d/ -/etc/NetworkManager/system-connections/ -/etc/security/ -/etc/selinux/ -/etc/deepin-elf-verify/ -/etc/filearmor.d/ -/etc/crypttab -/etc/fstab -/sysroot/ostree/repo/ -/persistent/ostree/repo/
14+
LockPersonality=yes
2215
NoNewPrivileges=yes
23-
ProtectHome=yes
24-
ProtectKernelTunables=yes
25-
ProtectKernelModules=yes
26-
ProtectControlGroups=yes
16+
PrivateDevices=yes
17+
PrivateIPC=true
2718
PrivateMounts=yes
2819
PrivateTmp=yes
29-
PrivateDevices=yes
30-
# 需要联网
31-
#PrivateNetwork=yes
3220
PrivateUsers=yes
21+
ProtectClock=true
22+
ProtectControlGroups=yes
23+
ProtectHome=yes
24+
ProtectKernelModules=yes
25+
ProtectKernelTunables=yes
26+
ProtectSystem=strict
27+
RemoveIPC=yes
3328
RestrictNamespaces=yes
34-
LockPersonality=yes
3529
RestrictRealtime=yes
36-
RemoveIPC=yes
37-
# 和golang -pie参数冲突,导致进程无法启动
38-
#MemoryDenyWriteExecute=yes
39-
#MemoryLimit=100M
30+
RestrictSUIDSGID=true
31+
StandardError=journal
32+
StandardOutput=null
33+
StateDirectory=lastore
34+
Type=dbus
35+
User=deepin-daemon

lib/systemd/system/lastore-update-metadata-info.service

Lines changed: 0 additions & 11 deletions
This file was deleted.

src/lastore-daemon/manager.go

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -662,9 +662,6 @@ func (m *Manager) handleAutoCheckEvent() error {
662662
return err
663663
}
664664
}
665-
if !m.config.DisableUpdateMetadata && !m.ImmutableAutoRecovery {
666-
startUpdateMetadataInfoService()
667-
}
668665
return nil
669666
}
670667

src/lastore-daemon/manager_unit.go

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import (
1010
"fmt"
1111
"math/rand"
1212
"os/exec"
13+
"os/user"
14+
"strconv"
1315
"strings"
1416
"time"
1517

@@ -26,6 +28,7 @@ const (
2628
lastoreUnitCache = "/tmp/lastoreUnitCache"
2729
run = "systemd-run"
2830
lastoreDBusCmd = "dbus-send --system --print-reply --dest=org.deepin.dde.Lastore1 /org/deepin/dde/Lastore1 org.deepin.dde.Lastore1.Manager.HandleSystemEvent"
31+
deepinDaemonUser = "deepin-daemon"
2932
)
3033

3134
// isFirstBoot startOfflineTask执行前执行有效
@@ -38,7 +41,6 @@ type systemdEventType string
3841
const (
3942
AutoCheck systemdEventType = "AutoCheck"
4043
AutoClean systemdEventType = "AutoClean"
41-
UpdateInfosChanged systemdEventType = "UpdateInfosChanged"
4244
OsVersionChanged systemdEventType = "OsVersionChanged"
4345
InitIdleDownload systemdEventType = "InitIdleDownload"
4446
AutoDownload systemdEventType = "AutoDownload"
@@ -334,20 +336,45 @@ func (m *Manager) getNextUpdateDelay() time.Duration {
334336
return remained + _minDelayTime
335337
}
336338

339+
// isAllowedToTriggerSystemEvent checks if the uid is allowed to trigger system events
340+
func isAllowedToTriggerSystemEvent(uid uint32, eventType systemdEventType) bool {
341+
// Allow regular users to trigger OsVersionChanged event
342+
// TODO: This should be fixed in the future to only allow restricted users to trigger this event.
343+
if eventType == OsVersionChanged {
344+
return true
345+
}
346+
347+
// Allow root user for all operations
348+
if uid == 0 {
349+
return true
350+
}
351+
352+
// Allow deepin-daemon user for all operations
353+
if u, err := user.Lookup(deepinDaemonUser); err == nil {
354+
if daemonUID, err := strconv.ParseUint(u.Uid, 10, 32); err == nil && uid == uint32(daemonUID) {
355+
return true
356+
}
357+
}
358+
359+
return false
360+
}
361+
337362
func (m *Manager) delHandleSystemEvent(sender dbus.Sender, eventType string) error {
338363
uid, err := m.service.GetConnUID(string(sender))
339364
if err != nil {
340365
logger.Warning(err)
341366
return dbusutil.ToError(err)
342367
}
343-
if uid != 0 && systemdEventType(eventType) != OsVersionChanged {
344-
err = fmt.Errorf("%q is not allowed to trigger system event", uid)
368+
369+
evType := systemdEventType(eventType)
370+
if !isAllowedToTriggerSystemEvent(uid, evType) {
371+
err = fmt.Errorf("uid %d is not allowed to trigger system event %v", uid, evType)
345372
logger.Warning(err)
346373
return dbusutil.ToError(err)
347374
}
375+
348376
m.service.DelayAutoQuit()
349-
typ := systemdEventType(eventType)
350-
switch typ {
377+
switch evType {
351378
case AutoCheck:
352379
go func() {
353380
err := m.handleAutoCheckEvent()
@@ -363,9 +390,6 @@ func (m *Manager) delHandleSystemEvent(sender dbus.Sender, eventType string) err
363390
logger.Warning(err)
364391
}
365392
}()
366-
// case UpdateInfosChanged:
367-
// logger.Info("UpdateInfos Changed")
368-
// m.handleUpdateInfosChanged()
369393
case OsVersionChanged:
370394
go updateplatform.UpdateTokenConfigFile(m.config.IncludeDiskInfo)
371395
case InitIdleDownload:

0 commit comments

Comments
 (0)