Skip to content

Commit 1c14dca

Browse files
nshalmangopherbot
authored andcommitted
unix: add GetPeerUcred and UcredGet for solaris
Change-Id: I74ba119fb729ef46899de04c686115f960975bb3 Reviewed-on: https://go-review.googlesource.com/c/sys/+/639755 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Auto-Submit: Ian Lance Taylor <iant@google.com> Reviewed-by: Michael Pratt <mpratt@google.com> Reviewed-by: Ian Lance Taylor <iant@google.com> Reviewed-by: Matt Layher <mdlayher@gmail.com>
1 parent d4ac05d commit 1c14dca

File tree

3 files changed

+265
-0
lines changed

3 files changed

+265
-0
lines changed

unix/syscall_solaris.go

+87
Original file line numberDiff line numberDiff line change
@@ -1102,3 +1102,90 @@ func (s *Strioctl) SetInt(i int) {
11021102
func IoctlSetStrioctlRetInt(fd int, req int, s *Strioctl) (int, error) {
11031103
return ioctlPtrRet(fd, req, unsafe.Pointer(s))
11041104
}
1105+
1106+
// Ucred Helpers
1107+
// See ucred(3c) and getpeerucred(3c)
1108+
1109+
//sys getpeerucred(fd uintptr, ucred *uintptr) (err error)
1110+
//sys ucredFree(ucred uintptr) = ucred_free
1111+
//sys ucredGet(pid int) (ucred uintptr, err error) = ucred_get
1112+
//sys ucredGeteuid(ucred uintptr) (uid int) = ucred_geteuid
1113+
//sys ucredGetegid(ucred uintptr) (gid int) = ucred_getegid
1114+
//sys ucredGetruid(ucred uintptr) (uid int) = ucred_getruid
1115+
//sys ucredGetrgid(ucred uintptr) (gid int) = ucred_getrgid
1116+
//sys ucredGetsuid(ucred uintptr) (uid int) = ucred_getsuid
1117+
//sys ucredGetsgid(ucred uintptr) (gid int) = ucred_getsgid
1118+
//sys ucredGetpid(ucred uintptr) (pid int) = ucred_getpid
1119+
1120+
// Ucred is an opaque struct that holds user credentials.
1121+
type Ucred struct {
1122+
ucred uintptr
1123+
}
1124+
1125+
// We need to ensure that ucredFree is called on the underlying ucred
1126+
// when the Ucred is garbage collected.
1127+
func ucredFinalizer(u *Ucred) {
1128+
ucredFree(u.ucred)
1129+
}
1130+
1131+
func GetPeerUcred(fd uintptr) (*Ucred, error) {
1132+
var ucred uintptr
1133+
err := getpeerucred(fd, &ucred)
1134+
if err != nil {
1135+
return nil, err
1136+
}
1137+
result := &Ucred{
1138+
ucred: ucred,
1139+
}
1140+
// set the finalizer on the result so that the ucred will be freed
1141+
runtime.SetFinalizer(result, ucredFinalizer)
1142+
return result, nil
1143+
}
1144+
1145+
func UcredGet(pid int) (*Ucred, error) {
1146+
ucred, err := ucredGet(pid)
1147+
if err != nil {
1148+
return nil, err
1149+
}
1150+
result := &Ucred{
1151+
ucred: ucred,
1152+
}
1153+
// set the finalizer on the result so that the ucred will be freed
1154+
runtime.SetFinalizer(result, ucredFinalizer)
1155+
return result, nil
1156+
}
1157+
1158+
func (u *Ucred) Geteuid() int {
1159+
defer runtime.KeepAlive(u)
1160+
return ucredGeteuid(u.ucred)
1161+
}
1162+
1163+
func (u *Ucred) Getruid() int {
1164+
defer runtime.KeepAlive(u)
1165+
return ucredGetruid(u.ucred)
1166+
}
1167+
1168+
func (u *Ucred) Getsuid() int {
1169+
defer runtime.KeepAlive(u)
1170+
return ucredGetsuid(u.ucred)
1171+
}
1172+
1173+
func (u *Ucred) Getegid() int {
1174+
defer runtime.KeepAlive(u)
1175+
return ucredGetegid(u.ucred)
1176+
}
1177+
1178+
func (u *Ucred) Getrgid() int {
1179+
defer runtime.KeepAlive(u)
1180+
return ucredGetrgid(u.ucred)
1181+
}
1182+
1183+
func (u *Ucred) Getsgid() int {
1184+
defer runtime.KeepAlive(u)
1185+
return ucredGetsgid(u.ucred)
1186+
}
1187+
1188+
func (u *Ucred) Getpid() int {
1189+
defer runtime.KeepAlive(u)
1190+
return ucredGetpid(u.ucred)
1191+
}

unix/syscall_solaris_test.go

+64
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ package unix_test
88

99
import (
1010
"fmt"
11+
"net"
1112
"os"
1213
"os/exec"
1314
"path/filepath"
@@ -420,3 +421,66 @@ func TestLifreqGetMTU(t *testing.T) {
420421
}
421422
}
422423
}
424+
425+
func TestUcredGet(t *testing.T) {
426+
euid := unix.Geteuid()
427+
creds, err := unix.UcredGet(unix.Getpid())
428+
if err != nil {
429+
t.Fatalf("unix.UcredGet failed: %v", err)
430+
}
431+
if euid != creds.Geteuid() {
432+
t.Fatalf("mismatched euid")
433+
}
434+
}
435+
436+
func TestGetPeerUcred(t *testing.T) {
437+
d := t.TempDir()
438+
path := filepath.Join(d, "foo.sock")
439+
sock, err := net.Listen("unix", path)
440+
if err != nil {
441+
t.Fatalf("net.Listen: %v", err)
442+
}
443+
defer sock.Close()
444+
445+
c1, err := net.Dial("unix", path)
446+
if err != nil {
447+
t.Error(err)
448+
return
449+
}
450+
defer c1.Close()
451+
452+
c2, err := sock.Accept()
453+
if err != nil {
454+
t.Fatalf("Accept: %v", err)
455+
}
456+
defer c2.Close()
457+
458+
switch unixconn := c2.(type) {
459+
case *net.UnixConn:
460+
raw, err := unixconn.SyscallConn()
461+
if err != nil {
462+
t.Fatalf("SyscallConn failed: %v", err)
463+
}
464+
465+
var creds *unix.Ucred
466+
cerr := raw.Control(func(fd uintptr) {
467+
creds, err = unix.GetPeerUcred(fd)
468+
if err != nil {
469+
err = fmt.Errorf("unix.GetPeerUcred: %w", err)
470+
return
471+
}
472+
})
473+
if cerr != nil {
474+
t.Fatalf("raw.Control failed: %v", err)
475+
}
476+
if creds == nil {
477+
t.Fatalf("Got a nil Ucred response")
478+
}
479+
euid := unix.Geteuid()
480+
if euid != creds.Geteuid() {
481+
t.Fatalf("mismatched euid")
482+
}
483+
default:
484+
t.Fatalf("Somehow didn't get a UnixConn")
485+
}
486+
}

unix/zsyscall_solaris_amd64.go

+114
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)