Skip to content

Commit

Permalink
unix: add GetPeerUcred and UcredGet for solaris
Browse files Browse the repository at this point in the history
Change-Id: I74ba119fb729ef46899de04c686115f960975bb3
Reviewed-on: https://go-review.googlesource.com/c/sys/+/639755
LUCI-TryBot-Result: Go LUCI <[email protected]>
Auto-Submit: Ian Lance Taylor <[email protected]>
Reviewed-by: Michael Pratt <[email protected]>
Reviewed-by: Ian Lance Taylor <[email protected]>
Reviewed-by: Matt Layher <[email protected]>
  • Loading branch information
nshalman authored and gopherbot committed Jan 7, 2025
1 parent d4ac05d commit 1c14dca
Show file tree
Hide file tree
Showing 3 changed files with 265 additions and 0 deletions.
87 changes: 87 additions & 0 deletions unix/syscall_solaris.go
Original file line number Diff line number Diff line change
Expand Up @@ -1102,3 +1102,90 @@ func (s *Strioctl) SetInt(i int) {
func IoctlSetStrioctlRetInt(fd int, req int, s *Strioctl) (int, error) {
return ioctlPtrRet(fd, req, unsafe.Pointer(s))
}

// Ucred Helpers
// See ucred(3c) and getpeerucred(3c)

//sys getpeerucred(fd uintptr, ucred *uintptr) (err error)
//sys ucredFree(ucred uintptr) = ucred_free
//sys ucredGet(pid int) (ucred uintptr, err error) = ucred_get
//sys ucredGeteuid(ucred uintptr) (uid int) = ucred_geteuid
//sys ucredGetegid(ucred uintptr) (gid int) = ucred_getegid
//sys ucredGetruid(ucred uintptr) (uid int) = ucred_getruid
//sys ucredGetrgid(ucred uintptr) (gid int) = ucred_getrgid
//sys ucredGetsuid(ucred uintptr) (uid int) = ucred_getsuid
//sys ucredGetsgid(ucred uintptr) (gid int) = ucred_getsgid
//sys ucredGetpid(ucred uintptr) (pid int) = ucred_getpid

// Ucred is an opaque struct that holds user credentials.
type Ucred struct {
ucred uintptr
}

// We need to ensure that ucredFree is called on the underlying ucred
// when the Ucred is garbage collected.
func ucredFinalizer(u *Ucred) {
ucredFree(u.ucred)
}

func GetPeerUcred(fd uintptr) (*Ucred, error) {
var ucred uintptr
err := getpeerucred(fd, &ucred)
if err != nil {
return nil, err
}
result := &Ucred{
ucred: ucred,
}
// set the finalizer on the result so that the ucred will be freed
runtime.SetFinalizer(result, ucredFinalizer)
return result, nil
}

func UcredGet(pid int) (*Ucred, error) {
ucred, err := ucredGet(pid)
if err != nil {
return nil, err
}
result := &Ucred{
ucred: ucred,
}
// set the finalizer on the result so that the ucred will be freed
runtime.SetFinalizer(result, ucredFinalizer)
return result, nil
}

func (u *Ucred) Geteuid() int {
defer runtime.KeepAlive(u)
return ucredGeteuid(u.ucred)
}

func (u *Ucred) Getruid() int {
defer runtime.KeepAlive(u)
return ucredGetruid(u.ucred)
}

func (u *Ucred) Getsuid() int {
defer runtime.KeepAlive(u)
return ucredGetsuid(u.ucred)
}

func (u *Ucred) Getegid() int {
defer runtime.KeepAlive(u)
return ucredGetegid(u.ucred)
}

func (u *Ucred) Getrgid() int {
defer runtime.KeepAlive(u)
return ucredGetrgid(u.ucred)
}

func (u *Ucred) Getsgid() int {
defer runtime.KeepAlive(u)
return ucredGetsgid(u.ucred)
}

func (u *Ucred) Getpid() int {
defer runtime.KeepAlive(u)
return ucredGetpid(u.ucred)
}
64 changes: 64 additions & 0 deletions unix/syscall_solaris_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ package unix_test

import (
"fmt"
"net"
"os"
"os/exec"
"path/filepath"
Expand Down Expand Up @@ -420,3 +421,66 @@ func TestLifreqGetMTU(t *testing.T) {
}
}
}

func TestUcredGet(t *testing.T) {
euid := unix.Geteuid()
creds, err := unix.UcredGet(unix.Getpid())
if err != nil {
t.Fatalf("unix.UcredGet failed: %v", err)
}
if euid != creds.Geteuid() {
t.Fatalf("mismatched euid")
}
}

func TestGetPeerUcred(t *testing.T) {
d := t.TempDir()
path := filepath.Join(d, "foo.sock")
sock, err := net.Listen("unix", path)
if err != nil {
t.Fatalf("net.Listen: %v", err)
}
defer sock.Close()

c1, err := net.Dial("unix", path)
if err != nil {
t.Error(err)
return
}
defer c1.Close()

c2, err := sock.Accept()
if err != nil {
t.Fatalf("Accept: %v", err)
}
defer c2.Close()

switch unixconn := c2.(type) {
case *net.UnixConn:
raw, err := unixconn.SyscallConn()
if err != nil {
t.Fatalf("SyscallConn failed: %v", err)
}

var creds *unix.Ucred
cerr := raw.Control(func(fd uintptr) {
creds, err = unix.GetPeerUcred(fd)
if err != nil {
err = fmt.Errorf("unix.GetPeerUcred: %w", err)
return
}
})
if cerr != nil {
t.Fatalf("raw.Control failed: %v", err)
}
if creds == nil {
t.Fatalf("Got a nil Ucred response")
}
euid := unix.Geteuid()
if euid != creds.Geteuid() {
t.Fatalf("mismatched euid")
}
default:
t.Fatalf("Somehow didn't get a UnixConn")
}
}
114 changes: 114 additions & 0 deletions unix/zsyscall_solaris_amd64.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 1c14dca

Please sign in to comment.