rc.init: fix mkchar not setting correct filemode

Commit bcfb760a1d 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 <github@gone.nl>
This commit is contained in:
Sebastiaan van Stijn 2021-04-13 13:47:53 +02:00
parent 60919fee96
commit 5020612534
No known key found for this signature in database
GPG Key ID: 76698F39D527CE8C

View File

@ -55,7 +55,7 @@ func mountSilent(source string, target string, fstype string, flags uintptr, dat
func mkchar(path string, mode, major, minor uint32) { func mkchar(path string, mode, major, minor uint32) {
// unix.Mknod only supports int dev numbers; this is ok for us // unix.Mknod only supports int dev numbers; this is ok for us
dev := int(unix.Mkdev(major, minor)) 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 != nil {
if err.Error() == "file exists" { if err.Error() == "file exists" {
return return
@ -164,6 +164,12 @@ func modalias(path string) {
} }
func doMounts() { 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 filesystem
mount("proc", "/proc", "proc", nodev|nosuid|noexec|relatime, "") mount("proc", "/proc", "proc", nodev|nosuid|noexec|relatime, "")