From 5020612534bb4892d9f4dcd1171873530630ad6f Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Tue, 13 Apr 2021 13:47:53 +0200 Subject: [PATCH] rc.init: fix mkchar not setting correct filemode Commit bcfb760a1d83a33da0331555006b7c1a7d84b595 rewrote the init from a shell script to a go implementation. However, unlike `mknod`, the active umask is applied when using Go's unix.Mknod(). This patch: - sets the correct mode when calling unix.Mknod() - temporarily overrides the umask during doMounts() Steps I used to reproduce the original issue, and to verify the changes in this patch (tried inside a container): docker run -it --rm -w /app golang bash cat > mknod.go <<'EOF' package main import ( "log" "golang.org/x/sys/unix" ) func main() { mkchar("/dev/null2", 0666, 1, 3) umask := unix.Umask(0000) defer unix.Umask(umask) mkchar2("/dev/null3", 0666, 1, 3) } // make a character device func mkchar(path string, mode, major, minor uint32) { // unix.Mknod only supports int dev numbers; this is ok for us dev := int(unix.Mkdev(major, minor)) err := unix.Mknod(path, mode, dev) if err != nil { if err.Error() == "file exists" { return } log.Printf("error making device %s: %v", path, err) } } // make a character device func mkchar2(path string, mode, major, minor uint32) { // unix.Mknod only supports int dev numbers; this is ok for us dev := int(unix.Mkdev(major, minor)) err := unix.Mknod(path, mode|unix.S_IFCHR, dev) if err != nil { if err.Error() == "file exists" { return } log.Printf("error making device %s: %v", path, err) } } EOF Initialize module and fetch dependencies: go mod init foo && go mod tidy Check active umask: umask 0022 Run the test code: go run mknod.go Check the results: ls -la /dev/null* crw-rw-rw- 1 root root 1, 3 Apr 13 11:45 /dev/null -rw-r--r-- 1 root root 0 Apr 13 11:45 /dev/null2 crw-rw-rw- 1 root root 1, 3 Apr 13 11:45 /dev/null3 Notice that: - `/dev/null2` (before) was created with active umask (`0022`) applied, and did not create a character device - `/dev/null3` (after) has both the correct (0666) permissions and mode Signed-off-by: Sebastiaan van Stijn --- pkg/init/cmd/rc.init/main.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/pkg/init/cmd/rc.init/main.go b/pkg/init/cmd/rc.init/main.go index a4fd27e51..06e0e1b56 100644 --- a/pkg/init/cmd/rc.init/main.go +++ b/pkg/init/cmd/rc.init/main.go @@ -55,7 +55,7 @@ func mountSilent(source string, target string, fstype string, flags uintptr, dat func mkchar(path string, mode, major, minor uint32) { // unix.Mknod only supports int dev numbers; this is ok for us dev := int(unix.Mkdev(major, minor)) - err := unix.Mknod(path, mode, dev) + err := unix.Mknod(path, mode|unix.S_IFCHR, dev) if err != nil { if err.Error() == "file exists" { return @@ -164,6 +164,12 @@ func modalias(path string) { } func doMounts() { + // Disable umask to make sure permissions are applied as specified, + // and restore original umask after we're done. This assumes no other + // processes run concurrently. + umask := unix.Umask(0000) + defer unix.Umask(umask) + // mount proc filesystem mount("proc", "/proc", "proc", nodev|nosuid|noexec|relatime, "")