Skip to content

Commit

Permalink
socket: add Conn.Pidfd* wrappers
Browse files Browse the repository at this point in the history
Signed-off-by: Matt Layher <mdlayher@gmail.com>
  • Loading branch information
mdlayher committed Mar 19, 2022
1 parent 5823d04 commit a425d96
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 13 deletions.
25 changes: 16 additions & 9 deletions conn.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ func socket(domain, typ, proto int, name string) (*Conn, error) {
}

// No error, prepare the Conn.
return newConn(fd, name)
return New(fd, name)
case !ready(err):
// System call interrupted or not ready, try again.
continue
Expand All @@ -211,7 +211,7 @@ func socket(domain, typ, proto int, name string) (*Conn, error) {
unix.CloseOnExec(fd)
syscall.ForkLock.RUnlock()

return newConn(fd, name)
return New(fd, name)
default:
// Unhandled error.
return nil, os.NewSyscallError("socket", err)
Expand All @@ -230,7 +230,7 @@ func FileConn(f *os.File, name string) (*Conn, error) {
switch err {
case nil:
// OK, ready to set up non-blocking I/O.
return newConn(fd, name)
return New(fd, name)
case unix.EINVAL:
// The kernel rejected our fcntl(2), fall back to separate dup(2) and
// setting close on exec.
Expand All @@ -248,18 +248,25 @@ func FileConn(f *os.File, name string) (*Conn, error) {
unix.CloseOnExec(fd)
syscall.ForkLock.RUnlock()

return newConn(fd, name)
return New(fd, name)
default:
// Any other errors.
return nil, os.NewSyscallError("fcntl", err)
}
}

// TODO(mdlayher): consider exporting newConn as New?

// newConn wraps an existing file descriptor to create a Conn. name should be a
// New wraps an existing file descriptor to create a Conn. name should be a
// unique name for the socket type such as "netlink" or "vsock".
func newConn(fd int, name string) (*Conn, error) {
//
// Most callers should use Socket or FileConn to construct a Conn. New is
// intended for integrating with specific system calls which provide a file
// descriptor that supports asynchronous I/O. The file descriptor is immediately
// set to nonblocking mode and registered with Go's runtime network poller for
// future I/O operations.
//
// Unlike FileConn, New does not duplicate the existing file descriptor in any
// way. The returned Conn takes ownership of the underlying file descriptor.
func New(fd int, name string) (*Conn, error) {
// All Conn I/O is nonblocking for integration with Go's runtime network
// poller. Depending on the OS this might already be set but it can't hurt
// to set it again.
Expand Down Expand Up @@ -318,7 +325,7 @@ func (c *Conn) Accept(flags int) (*Conn, unix.Sockaddr, error) {

// Successfully accepted a connection, wrap it in a Conn for use by the
// caller.
ac, err := newConn(nfd, c.name)
ac, err := New(nfd, c.name)
if err != nil {
return nil, nil, err
}
Expand Down
35 changes: 34 additions & 1 deletion conn_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ func (c *Conn) IoctlKCMClone() (*Conn, error) {
}

// Successful clone, wrap in a Conn for use by the caller.
return newConn(int(info.Fd), c.name)
return New(int(info.Fd), c.name)
}

// IoctlKCMAttach wraps ioctl(2) for unix.KCMAttach values.
Expand All @@ -50,6 +50,39 @@ func (c *Conn) IoctlKCMUnattach(info unix.KCMUnattach) error {
})
}

// PidfdGetfd wraps pidfd_getfd(2) for a Conn which wraps a pidfd, but returns a
// Conn rather than a raw file descriptor.
func (c *Conn) PidfdGetfd(targetFD, flags int) (*Conn, error) {
const op = "pidfd_getfd"

var (
outFD int
err error
)

doErr := c.control(op, func(fd int) error {
outFD, err = unix.PidfdGetfd(fd, targetFD, flags)
return err
})
if doErr != nil {
return nil, doErr
}
if err != nil {
return nil, os.NewSyscallError(op, err)
}

// Successful getfd, wrap in a Conn for use by the caller.
return New(outFD, c.name)
}

// PidfdSendSignal wraps pidfd_send_signal(2) for a Conn which wraps a Linux
// pidfd.
func (c *Conn) PidfdSendSignal(sig unix.Signal, info *unix.Siginfo, flags int) error {
return c.controlErr("pidfd_send_signal", func(fd int) error {
return unix.PidfdSendSignal(fd, sig, info, flags)
})
}

// SetBPF attaches an assembled BPF program to a Conn.
func (c *Conn) SetBPF(filter []bpf.RawInstruction) error {
// We can't point to the first instruction in the array if no instructions
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ go 1.17
require (
github.com/google/go-cmp v0.5.7
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
golang.org/x/sys v0.0.0-20220224120231-95c6836cb0e7
golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8
)

// Intentional pin to an older release; we don't need new features and would
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20220224120231-95c6836cb0e7 h1:BXxu8t6QN0G1uff4bzZzSkpsax8+ALqTGUtz08QrV00=
golang.org/x/sys v0.0.0-20220224120231-95c6836cb0e7/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8 h1:OH54vjqzRWmbJ62fjuhxy7AxFFgoHN0/DPc/UrL8cAs=
golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

0 comments on commit a425d96

Please sign in to comment.