Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
151 changes: 151 additions & 0 deletions SPECS/kubernetes/CVE-2025-31133.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
From ab41549ce869d942c4f03f34454992f198cd7bde Mon Sep 17 00:00:00 2001
From: AllSpark <[email protected]>
Date: Mon, 24 Nov 2025 07:13:56 +0000
Subject: [PATCH] Backport: handle /dev/null checks and mask multiple paths;
adjust stdio and devnull reopening logic

Signed-off-by: Azure Linux Security Servicing Account <[email protected]>
Upstream-reference: AI Backport from existing Build 989296 of https://github.com/opencontainers/runc/commit/8476df83b534a2522b878c0507b3491def48db9f.diff
---
.../runc/libcontainer/init_linux.go | 11 ++---
.../runc/libcontainer/rootfs_linux.go | 49 +++++++++++++++----
.../runc/libcontainer/standard_init_linux.go | 8 +--
3 files changed, 47 insertions(+), 21 deletions(-)

diff --git a/vendor/github.com/opencontainers/runc/libcontainer/init_linux.go b/vendor/github.com/opencontainers/runc/libcontainer/init_linux.go
index d9f18139..50c7a129 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/init_linux.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/init_linux.go
@@ -432,19 +432,16 @@ func setupUser(config *initConfig) error {
// The ownership needs to match because it is created outside of the container and needs to be
// localized.
func fixStdioPermissions(u *user.ExecUser) error {
- var null unix.Stat_t
- if err := unix.Stat("/dev/null", &null); err != nil {
- return &os.PathError{Op: "stat", Path: "/dev/null", Err: err}
- }
for _, file := range []*os.File{os.Stdin, os.Stdout, os.Stderr} {
var s unix.Stat_t
if err := unix.Fstat(int(file.Fd()), &s); err != nil {
return &os.PathError{Op: "fstat", Path: file.Name(), Err: err}
}

- // Skip chown if uid is already the one we want or any of the STDIO descriptors
- // were redirected to /dev/null.
- if int(s.Uid) == u.Uid || s.Rdev == null.Rdev {
+ // Skip chown if:
+ // - uid is already the one we want, or
+ // - fd is opened to /dev/null.
+ if int(s.Uid) == u.Uid || isDevNull(&s) {
continue
}

diff --git a/vendor/github.com/opencontainers/runc/libcontainer/rootfs_linux.go b/vendor/github.com/opencontainers/runc/libcontainer/rootfs_linux.go
index c701d6a2..abc7c5ea 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/rootfs_linux.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/rootfs_linux.go
@@ -360,7 +360,7 @@ func mountCgroupV2(m *configs.Mount, c *mountConfig) error {
// Mask `/sys/fs/cgroup` to ensure it is read-only, even when `/sys` is mounted
// with `rbind,ro` (`runc spec --rootless` produces `rbind,ro` for `/sys`).
err = utils.WithProcfd(c.root, m.Destination, func(procfd string) error {
- return maskPath(procfd, c.label)
+ return maskPaths([]string{procfd}, c.label)
})
}
return err
@@ -653,27 +653,23 @@ func setupDevSymlinks(rootfs string) error {
// needs to be called after we chroot/pivot into the container's rootfs so that any
// symlinks are resolved locally.
func reOpenDevNull() error {
- var stat, devNullStat unix.Stat_t
file, err := os.OpenFile("/dev/null", os.O_RDWR, 0)
if err != nil {
return err
}
defer file.Close() //nolint: errcheck
- if err := unix.Fstat(int(file.Fd()), &devNullStat); err != nil {
- return &os.PathError{Op: "fstat", Path: file.Name(), Err: err}
+ if err := verifyDevNull(file); err != nil {
+ return fmt.Errorf("can't reopen /dev/null: %w", err)
}
for fd := 0; fd < 3; fd++ {
+ var stat unix.Stat_t
if err := unix.Fstat(fd, &stat); err != nil {
return &os.PathError{Op: "fstat", Path: "fd " + strconv.Itoa(fd), Err: err}
}
- if stat.Rdev == devNullStat.Rdev {
+ if isDevNull(&stat) {
// Close and re-open the fd.
if err := unix.Dup3(int(file.Fd()), fd, 0); err != nil {
- return &os.PathError{
- Op: "dup3",
- Path: "fd " + strconv.Itoa(int(file.Fd())),
- Err: err,
- }
+ return err
}
}
}
@@ -1063,6 +1059,39 @@ func remountReadonly(m *configs.Mount) error {
// security issues from processes reading information from non-namespace aware
// mounts ( proc/kcore ).
// For files, maskPath bind mounts /dev/null over the top of the specified path.
+
+func isDevNull(st *unix.Stat_t) bool {
+ return st.Mode&unix.S_IFMT == unix.S_IFCHR && st.Rdev == unix.Mkdev(1, 3)
+}
+
+func verifyDevNull(f *os.File) error {
+ var st unix.Stat_t
+ if err := unix.Fstat(int(f.Fd()), &st); err != nil {
+ return &os.PathError{Op: "fstat", Path: f.Name(), Err: err}
+ }
+ if !isDevNull(&st) {
+ return errors.New("container's /dev/null is invalid")
+ }
+ return nil
+}
+
+// maskPaths masks the top of the specified paths inside a container to avoid
+func maskPaths(paths []string, mountLabel string) error {
+ for _, path := range paths {
+ if err := mount("/dev/null", path, "", "", unix.MS_BIND, ""); err != nil && !errors.Is(err, os.ErrNotExist) {
+ if errors.Is(err, unix.ENOTDIR) {
+ if err := mount("tmpfs", path, "", "tmpfs", unix.MS_RDONLY, label.FormatMountLabel("", mountLabel)); err != nil {
+ return err
+ }
+ continue
+ }
+ return err
+ }
+ }
+ return nil
+}
+
+
// For directories, maskPath mounts read-only tmpfs over the top of the specified path.
func maskPath(path string, mountLabel string) error {
if err := mount("/dev/null", path, "", "", unix.MS_BIND, ""); err != nil && !errors.Is(err, os.ErrNotExist) {
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/standard_init_linux.go b/vendor/github.com/opencontainers/runc/libcontainer/standard_init_linux.go
index d1d94352..da407620 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/standard_init_linux.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/standard_init_linux.go
@@ -141,11 +141,11 @@ func (l *linuxStandardInit) Init() error {
return fmt.Errorf("can't make %q read-only: %w", path, err)
}
}
- for _, path := range l.config.Config.MaskPaths {
- if err := maskPath(path, l.config.Config.MountLabel); err != nil {
- return fmt.Errorf("can't mask path %s: %w", path, err)
- }
+
+ if err := maskPaths(l.config.Config.MaskPaths, l.config.Config.MountLabel); err != nil {
+ return err
}
+
pdeath, err := system.GetParentDeathSignal()
if err != nil {
return fmt.Errorf("can't get pdeath signal: %w", err)
--
2.45.4

Loading
Loading