Skip to content

Commit

Permalink
feat: udev: label device nodes
Browse files Browse the repository at this point in the history
Use udev rules to assign basic device file labels based on their subsystem

Signed-off-by: Dmitry Sharshakov <[email protected]>
  • Loading branch information
dsseng committed Nov 22, 2024
1 parent e899fb3 commit a13f82c
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 5 deletions.
2 changes: 2 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -731,6 +731,7 @@ COPY --chmod=0644 hack/containerd.toml /rootfs/etc/containerd/config.toml
COPY --chmod=0644 hack/cri-containerd.toml /rootfs/etc/cri/containerd.toml
COPY --chmod=0644 hack/cri-plugin.part /rootfs/etc/cri/conf.d/00-base.part
COPY --chmod=0644 hack/udevd/80-net-name-slot.rules /rootfs/usr/lib/udev/rules.d/
COPY --chmod=0644 hack/udevd/90-selinux.rules /rootfs/usr/lib/udev/rules.d/
COPY --chmod=0644 hack/lvm.conf /rootfs/etc/lvm/lvm.conf
RUN <<END
ln -s /usr/share/zoneinfo/Etc/UTC /rootfs/etc/localtime
Expand Down Expand Up @@ -804,6 +805,7 @@ COPY --chmod=0644 hack/containerd.toml /rootfs/etc/containerd/config.toml
COPY --chmod=0644 hack/cri-containerd.toml /rootfs/etc/cri/containerd.toml
COPY --chmod=0644 hack/cri-plugin.part /rootfs/etc/cri/conf.d/00-base.part
COPY --chmod=0644 hack/udevd/80-net-name-slot.rules /rootfs/usr/lib/udev/rules.d/
COPY --chmod=0644 hack/udevd/90-selinux.rules /rootfs/usr/lib/udev/rules.d/
COPY --chmod=0644 hack/lvm.conf /rootfs/etc/lvm/lvm.conf
RUN <<END
ln -s /usr/share/zoneinfo/Etc/UTC /rootfs/etc/localtime
Expand Down
11 changes: 11 additions & 0 deletions hack/udevd/90-selinux.rules
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
SUBSYSTEM=="*",SECLABEL{selinux}="system_u:object_r:device_t:s0"

SUBSYSTEM=="rtc",SECLABEL{selinux}="system_u:object_r:rtc_device_t:s0"
SUBSYSTEM=="mtd",SECLABEL{selinux}="system_u:object_r:mtd_device_t:s0"
SUBSYSTEM=="tpm",SECLABEL{selinux}="system_u:object_r:tpm_device_t:s0"
SUBSYSTEM=="tpmrm",SECLABEL{selinux}="system_u:object_r:tpm_device_t:s0"

KERNEL=="watchdog",SECLABEL{selinux}="system_u:object_r:wdt_device_t:s0"
KERNEL=="watchdog*",SECLABEL{selinux}="system_u:object_r:wdt_device_t:s0"
KERNEL=="null",SECLABEL{selinux}="system_u:object_r:null_device_t:s0"
KERNEL=="zero",SECLABEL{selinux}="system_u:object_r:null_device_t:s0"
32 changes: 27 additions & 5 deletions internal/integration/api/selinux.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,12 +119,25 @@ func (suite *SELinuxSuite) TestFileMountLabels() {
}
maps.Copy(expectedLabelsControlPlane, expectedLabelsWorker)

suite.checkFileLabels(workers, expectedLabelsWorker)
suite.checkFileLabels(controlplanes, expectedLabelsControlPlane)
// Devices labeled by subsystems, labeled by udev
expectedLabelsDevices := map[string]string{
"/dev/rtc0": "system_u:object_r:rtc_device_t:s0",
"/dev/tpm0": "system_u:object_r:tpm_device_t:s0",
"/dev/tpmrm0": "system_u:object_r:tpm_device_t:s0",
"/dev/watchdog": "system_u:object_r:wdt_device_t:s0",
"/dev/watchdog0": "system_u:object_r:wdt_device_t:s0",
"/dev/null": "system_u:object_r:null_device_t:s0",
"/dev/zero": "system_u:object_r:null_device_t:s0",
}

suite.checkFileLabels(workers, expectedLabelsWorker, false)
suite.checkFileLabels(controlplanes, expectedLabelsControlPlane, false)
suite.checkFileLabels(workers, expectedLabelsDevices, true)
suite.checkFileLabels(controlplanes, expectedLabelsDevices, true)
}

//nolint:gocyclo
func (suite *SELinuxSuite) checkFileLabels(nodes []string, expectedLabels map[string]string) {
func (suite *SELinuxSuite) checkFileLabels(nodes []string, expectedLabels map[string]string, allowMissing bool) {
paths := make([]string, 0, len(expectedLabels))
for k := range expectedLabels {
paths = append(paths, k)
Expand Down Expand Up @@ -154,7 +167,7 @@ func (suite *SELinuxSuite) checkFileLabels(nodes []string, expectedLabels map[st

suite.Require().NoError(err)

suite.Require().NoError(helpers.ReadGRPCStream(stream, func(info *machineapi.FileInfo, node string, multipleNodes bool) error {
err = helpers.ReadGRPCStream(stream, func(info *machineapi.FileInfo, node string, multipleNodes bool) error {
// E.g. /var/lib should inherit /var label, while /var/run is a new mountpoint
if slices.Contains(paths, info.Name) && info.Name != path {
return nil
Expand All @@ -178,7 +191,16 @@ func (suite *SELinuxSuite) checkFileLabels(nodes []string, expectedLabels map[st
suite.Require().True(found)

return nil
}))
})

if allowMissing {
if err != nil {
suite.Require().Contains(err.Error(), "lstat")
suite.Require().Contains(err.Error(), "no such file or directory")
}
} else {
suite.Require().NoError(err)
}
}
}
}
Expand Down
Binary file modified internal/pkg/selinux/policy/policy.33
Binary file not shown.
14 changes: 14 additions & 0 deletions internal/pkg/selinux/policy/selinux/services/udev.cil
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,20 @@
; udevadm called by machined in its context
(allow init_t udev_t (unix_stream_socket (connectto)))

; Device subsystems, labeled by udev rules
; RTC is important for security verification
(type rtc_device_t)
(call protected_device_f (rtc_device_t))
; Could be exposed firmware storage
(type mtd_device_t)
(call protected_device_f (mtd_device_t))
; Could reset the system
(type wdt_device_t)
(call protected_device_f (wdt_device_t))
; Typically client pods must not access TPM
(type tpm_device_t)
(call protected_device_f (tpm_device_t))

(type modprobe_exec_t)
(call system_f (modprobe_exec_t))
(filecon "/sbin/modprobe" file (system_u object_r modprobe_exec_t (systemLow systemLow)))
Expand Down

0 comments on commit a13f82c

Please sign in to comment.