internal/hookd/peercred_linux.go
38 lines · 754 bytes
1//go:build linux
2
3package hookd
4
5import (
6 "errors"
7 "fmt"
8 "net"
9 "os"
10 "syscall"
11)
12
13// checkPeer refuses a connection from any uid but the daemon's: git,
14// and so every hook, runs as the daemon's user.
15func checkPeer(conn net.Conn) error {
16 uc, ok := conn.(*net.UnixConn)
17 if !ok {
18 return fmt.Errorf("not a unix socket connection")
19 }
20 raw, err := uc.SyscallConn()
21 if err != nil {
22 return err
23 }
24 var cred *syscall.Ucred
25 var credErr error
26 if err := raw.Control(func(fd uintptr) {
27 cred, credErr = syscall.GetsockoptUcred(int(fd), syscall.SOL_SOCKET, syscall.SO_PEERCRED)
28 }); err != nil {
29 return err
30 }
31 if credErr != nil {
32 return credErr
33 }
34 if int(cred.Uid) != os.Getuid() {
35 return errors.New("peer uid not permitted")
36 }
37 return nil
38}