golang / go

The Go programming language
https://go.dev
BSD 3-Clause "New" or "Revised" License
122.98k stars 17.54k forks source link

syscall: Setuid/Setgid doesn't apply to all threads on Linux #1435

Closed gopherbot closed 3 years ago

gopherbot commented 13 years ago

by ziutek@Lnet.pl:

What steps will reproduce the problem?

Compile attached test code. Run it as root like this:

# GOMAXPROCS=4 ./test 65534 65534

and note output:

gorutine 1: uid=0 euid=0 gid=0 egid=0
gorutine 2: uid=0 euid=0 gid=0 egid=0
gorutine 3: uid=0 euid=0 gid=0 egid=0
gorutine 4: uid=0 euid=0 gid=0 egid=0
gorutine 5: uid=0 euid=0 gid=0 egid=0
gorutine 6: uid=0 euid=0 gid=0 egid=0
gorutine 7: uid=0 euid=0 gid=0 egid=0
gorutine 8: uid=0 euid=0 gid=0 egid=0
gorutine 9: uid=0 euid=0 gid=0 egid=0
gorutine 0: uid=65534 euid=65534 gid=65534 egid=65534
gorutine 1: uid=0 euid=0 gid=0 egid=0
gorutine 2: uid=0 euid=0 gid=0 egid=0
gorutine 3: uid=0 euid=0 gid=0 egid=0
gorutine 4: uid=0 euid=0 gid=0 egid=0
gorutine 5: uid=0 euid=0 gid=0 egid=0
gorutine 6: uid=0 euid=0 gid=0 egid=0
gorutine 7: uid=0 euid=0 gid=0 egid=0
gorutine 8: uid=0 euid=0 gid=0 egid=0
gorutine 9: uid=0 euid=0 gid=0 egid=0
gorutine 0: uid=65534 euid=65534 gid=65534 egid=65534

Use ps -efL during test execution and note output:

UID        PID  PPID   LWP  C NLWP STIME TTY          TIME CMD
nobody   26088 25928 26088  0   10 11:56 pts/1    00:00:00 ./test 65534 65534
root     26088 25928 26089  0   10 11:56 pts/1    00:00:00 ./test 65534 65534
root     26088 25928 26090  0   10 11:56 pts/1    00:00:00 ./test 65534 65534
root     26088 25928 26091  0   10 11:56 pts/1    00:00:00 ./test 65534 65534
root     26088 25928 26092  0   10 11:56 pts/1    00:00:00 ./test 65534 65534
root     26088 25928 26093  0   10 11:56 pts/1    00:00:00 ./test 65534 65534
root     26088 25928 26094  0   10 11:56 pts/1    00:00:00 ./test 65534 65534
root     26088 25928 26095  0   10 11:56 pts/1    00:00:00 ./test 65534 65534
root     26088 25928 26096  0   10 11:56 pts/1    00:00:00 ./test 65534 65534
root     26088 25928 26097  0   10 11:56 pts/1    00:00:00 ./test 65534 65534

What is the expected output?

All threads must have the same UID/GID: (65534, nobody user in my system).

Which compiler are you using (5g, 6g, 8g, gccgo)?

I tested this with 6g and 8g.

Which operating system are you using?

Linux (Debian 6.0 SID on i386, Ubuntu 10.10 on amd64)

Which revision are you using?  (hg identify)

d8ba80011a98 release/release.2011-01-20

Please provide any additional information below.

http://groups.google.com/group/golang-nuts/browse_thread/thread/59597aafdd84a0e

Attachments:

  1. test.go (1067 bytes)
AndrewGMorgan commented 3 years ago

FWIW Both of the above issues are now fixed at HEAD.

gopherbot commented 3 years ago

Change https://golang.org/cl/285597 mentions this issue: doc/go1.16: mention syscall.AllThreadsSyscall

lordspace commented 3 years ago

Just wanted to post an update. The following seems to work with go1.16.6 on Ubuntu linux which is pretty cool.

go build main.go
chmod 04755 main
./main 33 33

package main
import (
    "os"
    "time"
    "syscall"
    "fmt"
    "strconv"
)

// https://storage.googleapis.com/go-attachment/1435/0/test.go
// https://github.com/golang/go/issues/1435
// $ sudo /sbin/setcap cap_setuid=ep ./prog
func printIds(ii int) {
    for {
        fmt.Printf(
            "gorutine %d: uid=%d euid=%d gid=%d egid=%d\n", ii,
            syscall.Getuid(), syscall.Geteuid(),
            syscall.Getgid(), syscall.Getegid(),
        )
        time.Sleep(1e9)
    }
}

func main() {
    if len(os.Args) != 3 {
        fmt.Printf("Usage: %s UID GID\n", os.Args[0])
        os.Exit(1)
    }
    uid, err := strconv.Atoi(os.Args[1])
    if err != nil {
        fmt.Println("Wrong UID:", err)
        os.Exit(1)
    }
    gid, err := strconv.Atoi(os.Args[2])
    if err != nil {
        fmt.Println("Wrong GID:", err)
        os.Exit(1)
    }

    en := syscall.Setgid(gid)
    if en != nil {
        fmt.Println("Setgid error:",en.Error())
        os.Exit(1)
    }

    en = syscall.Setuid(uid)
    if en != nil {
        fmt.Println("Setuid error:", en.Error())
        os.Exit(1)
    }

    for ii := 1; ii < 10; ii++ {
        go printIds(ii)
        time.Sleep(1e8)
    }

    printIds(0)
}
AndrewGMorgan commented 3 years ago

Yes. I've also authored a native Go package for manipulating capabilities at runtime: "kernel.org/pub/linux/libs/security/libcap/cap". This worked example covers how to read/modify/drop runtime capabilities as well as manipulate UIDs etc.

lordspace commented 3 years ago

@AndrewGMorgan thanks for sharing.

wxiaoguang commented 1 year ago

The Milestone is "unplanned`, I guess it should be "1.16"?

ianlancetaylor commented 1 year ago

Sorry, we don't try to set the milestone when we close an issue. But, yes, this was fixed in the 1.16 release.