From 3d8eb100e4a5968a8b0c7ef9cc9aad9c0277ac31 Mon Sep 17 00:00:00 2001 From: Aleksa Sarai Date: Fri, 13 Sep 2024 14:33:48 +1000 Subject: [PATCH] utils: mkdirall: mask silently ignored mode bits to match os.MkdirAll It turns out that the suid and sgid mode bits are silently ignored by Linux (though the sticky bit is honoured), and some users are requesting mode bits that are ignored. While returning an error (as securejoin does) makes some sense, this is a regression. Ref: https://github.com/cyphar/filepath-securejoin/issues/23 Fixes: dd827f7b715a ("utils: switch to securejoin.MkdirAllHandle") Signed-off-by: Aleksa Sarai --- libcontainer/utils/utils_unix.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/libcontainer/utils/utils_unix.go b/libcontainer/utils/utils_unix.go index 6521114ba75..f82e376a165 100644 --- a/libcontainer/utils/utils_unix.go +++ b/libcontainer/utils/utils_unix.go @@ -319,6 +319,14 @@ func MkdirAllInRootOpen(root, unsafePath string, mode uint32) (_ *os.File, Err e if mode&^0o7777 != 0 { return nil, fmt.Errorf("tried to include non-mode bits in MkdirAll mode: 0o%.3o", mode) } + // Linux (and thus os.MkdirAll) silently ignores the suid and sgid bits if + // passed. While it would make sense to return an error in that case (since + // the user has asked for a mode that won't be applied), for compatibility + // reasons we have to ignore these bits. + if ignoredBits := mode &^ 0o1777; ignoredBits != 0 { + logrus.Warnf("MkdirAll called with no-op mode bits that are ignored by Linux 0o%.3o", ignoredBits) + mode &= 0o1777 + } rootDir, err := os.OpenFile(root, unix.O_DIRECTORY|unix.O_CLOEXEC, 0) if err != nil {