diff options
Diffstat (limited to 'sd_daemon/notify.go')
-rw-r--r-- | sd_daemon/notify.go | 95 |
1 files changed, 7 insertions, 88 deletions
diff --git a/sd_daemon/notify.go b/sd_daemon/notify.go index 917e2d4..9591613 100644 --- a/sd_daemon/notify.go +++ b/sd_daemon/notify.go @@ -3,7 +3,7 @@ // // Copyright 2013, 2015 Docker, Inc. // Copyright 2014 CoreOS, Inc. -// Copyright 2015-2018 Luke Shumaker +// Copyright 2015-2019 Luke Shumaker // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -17,16 +17,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -// +build linux - package sd_daemon import ( - "bytes" - "net" "os" - - "golang.org/x/sys/unix" ) // Notification is a message to be sent to the service manager about @@ -36,6 +30,11 @@ type Notification struct { // If PID <= 0, or if the current process does not have // privileges to send messages on behalf of other processes, // then the message is simply sent from the current process. + // + // BUG(lukeshu): Spoofing the PID is not implemented on + // non-Linux kernels. If you are knowledgable about how to do + // this on other kernels, please let me know at + // <lukeshu@lukeshu.com>! PID int // State should contain a newline-separated list of variable @@ -75,85 +74,5 @@ type Notification struct { // support both service managers that support these notifications and // those that do not. func (msg Notification) Send(unsetEnv bool) error { - if unsetEnv { - defer func() { _ = os.Unsetenv("NOTIFY_SOCKET") }() - } - - socketAddr := &net.UnixAddr{ - Name: os.Getenv("NOTIFY_SOCKET"), - Net: "unixgram", - } - - if socketAddr.Name == "" { - return ErrDisabled - } - - conn, err := socketUnixgram(socketAddr.Name) - if err != nil { - return err - } - defer func() { _ = conn.Close() }() - - var cmsgs [][]byte - - if len(msg.Files) > 0 { - fds := make([]int, len(msg.Files)) - for i := range msg.Files { - fds[i] = int(msg.Files[i].Fd()) - } - cmsg := unix.UnixRights(fds...) - cmsgs = append(cmsgs, cmsg) - } - - havePid := msg.PID > 0 && msg.PID != os.Getpid() - if havePid { - cmsg := unix.UnixCredentials(&unix.Ucred{ - Pid: int32(msg.PID), - Uid: uint32(os.Getuid()), - Gid: uint32(os.Getgid()), - }) - cmsgs = append(cmsgs, cmsg) - } - - // If the 2nd argument is empty, this is equivalent to - // - // conn, _ := net.DialUnix(socketAddr.Net, nil, socketAddr) - // conn.Write([]byte(msg.State)) - _, _, err = conn.WriteMsgUnix([]byte(msg.State), bytes.Join(cmsgs, nil), socketAddr) - - if err != nil && havePid { - // Maybe it failed because we don't have privileges to - // spoof our pid; retry without spoofing the pid. - // - // I'm not too happy that we do this silently without - // notifying the caller, but that's what - // sd_pid_notify_with_fds does. - cmsgs = cmsgs[:len(cmsgs)-1] - _, _, err = conn.WriteMsgUnix([]byte(msg.State), bytes.Join(cmsgs, nil), socketAddr) - } - - return err -} - -// socketUnixgram wraps socket(2), but doesn't bind(2) or connect(2) -// the socket to anything. This is an ugly hack because none of the -// functions in "net" actually allow you to get a AF_UNIX socket not -// bound/connected to anything. -// -// At some point you begin to question if it is worth it to keep up -// the high-level interface of "net", and messing around with FileConn -// and UnixConn. Maybe we just drop to using unix.Socket and -// unix.SendmsgN directly. -func socketUnixgram(name string) (*net.UnixConn, error) { - fd, err := unix.Socket(unix.AF_UNIX, unix.SOCK_DGRAM|unix.SOCK_CLOEXEC, 0) - if err != nil { - return nil, os.NewSyscallError("socket", err) - } - defer unix.Close(fd) - conn, err := net.FileConn(os.NewFile(uintptr(fd), name)) - if err != nil { - return nil, err - } - unixConn := conn.(*net.UnixConn) - return unixConn, nil + return msg.send(unsetEnv) } |