iop/apps/agent/internal/localcontrol/peercred_linux.go

56 lines
1.3 KiB
Go

//go:build linux
package localcontrol
import (
"fmt"
"net"
"os"
"syscall"
"golang.org/x/sys/unix"
)
func (kernelPeerCredentialSource) Supported() bool {
return true
}
// UID obtains the peer identity from the kernel SO_PEERCRED record.
func (kernelPeerCredentialSource) UID(conn net.Conn) (uint32, error) {
syscallConn, ok := conn.(syscall.Conn)
if !ok {
return 0, fmt.Errorf("localcontrol: connection does not expose a syscall handle")
}
raw, err := syscallConn.SyscallConn()
if err != nil {
return 0, fmt.Errorf("localcontrol: obtain peer syscall handle: %w", err)
}
var (
credential *unix.Ucred
socketErr error
)
if err := raw.Control(func(fileDescriptor uintptr) {
credential, socketErr = unix.GetsockoptUcred(
int(fileDescriptor),
unix.SOL_SOCKET,
unix.SO_PEERCRED,
)
}); err != nil {
return 0, fmt.Errorf("localcontrol: inspect peer credentials: %w", err)
}
if socketErr != nil {
return 0, fmt.Errorf("localcontrol: inspect SO_PEERCRED: %w", socketErr)
}
if credential == nil {
return 0, fmt.Errorf("localcontrol: SO_PEERCRED returned no identity")
}
return credential.Uid, nil
}
func fileOwnerUID(info os.FileInfo) (uint32, error) {
stat, ok := info.Sys().(*syscall.Stat_t)
if !ok {
return 0, fmt.Errorf("localcontrol: filesystem owner is unavailable")
}
return stat.Uid, nil
}