From 1e4db61fd42019dcf98cc08ca747f0692ec88ba2 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Thu, 19 Jan 2017 04:52:23 -0500 Subject: Fix. --- systemd-timesyncd-wait.go | 97 ++++++++++++++++++++++++++++++----- systemd-timesyncd-wait.socket | 4 +- systemd-timesyncd-wrap.go | 37 +++++++++---- systemd-timesyncd.service.d-wait.conf | 4 ++ 4 files changed, 119 insertions(+), 23 deletions(-) diff --git a/systemd-timesyncd-wait.go b/systemd-timesyncd-wait.go index 9275502..f5327ff 100644 --- a/systemd-timesyncd-wait.go +++ b/systemd-timesyncd-wait.go @@ -1,29 +1,100 @@ +// Copyright 2017 Luke Shumaker +// +// For just ListenFds: +// +// Copyright 2015 CoreOS, Inc. +// Copyright 2015-2016 Luke Shumaker +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package main import ( + "fmt" "net" "os" + "strconv" + "strings" + + unix "syscall" ) +// ListenFds returns a list of file descriptors passed in by the +// service manager as part of the socket-based activation logic. +// +// If unsetEnv is true, then (regardless of whether the function call +// itself succeeds or not) it will unset the environmental variables +// LISTEN_FDS and LISTEN_PID, which will cause further calls to this +// function to fail. +// +// In the case of an error, this function returns nil. +func ListenFds(unsetEnv bool) []*os.File { + if unsetEnv { + defer func() { + _ = os.Unsetenv("LISTEN_PID") + _ = os.Unsetenv("LISTEN_FDS") + _ = os.Unsetenv("LISTEN_FDNAMES") + }() + } + + pid, err := strconv.Atoi(os.Getenv("LISTEN_PID")) + if err != nil || pid != os.Getpid() { + return nil + } + + nfds, err := strconv.Atoi(os.Getenv("LISTEN_FDS")) + if err != nil || nfds < 1 { + return nil + } + + names := strings.Split(os.Getenv("LISTEN_FDNAMES"), ":") + + files := make([]*os.File, 0, nfds) + for i := 0; i < nfds; i++ { + fd := i + 3 + unix.CloseOnExec(fd) + name := "unknown" + if i < len(names) { + name = names[i] + } + files = append(files, os.NewFile(uintptr(fd), name)) + } + + return files +} + func main() { - sync_sockname := "/run/timesyncd/time-sync.sock" + files := ListenFds(false) + if len(files) != 1 { + fmt.Fprintf(os.Stderr, "expected 1 fd, got %d\n", len(files)) + os.Exit(1) + } - sync_sock, err := net.ListenUnixgram("unixgram", &net.UnixAddr{Net: "unixgram", Name: sync_sockname}) + sync_sock, err := net.FileConn(files[0]) if err != nil { - os.Stderr.WriteString(err.Error()) - os.Stderr.Write([]byte{'\n'}) + fmt.Fprintln(os.Stderr, err) os.Exit(127) } var dat [4096]byte - n, err := sync_sock.Read(dat[:]) - if err != nil { - os.Stderr.WriteString(err.Error()) - os.Stderr.Write([]byte{'\n'}) - os.Exit(127) - } - if string(dat[:n]) != "READY=1" { - os.Exit(127) + for { + n, err := sync_sock.Read(dat[:]) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(127) + } + if n > 0 { + os.Exit(0) + } } - os.Exit(0) } diff --git a/systemd-timesyncd-wait.socket b/systemd-timesyncd-wait.socket index 3112218..f7a35c8 100644 --- a/systemd-timesyncd-wait.socket +++ b/systemd-timesyncd-wait.socket @@ -1,7 +1,9 @@ [Unit] Description=Network Time Synchronized Socket DefaultDependencies=no -After=systemd-remount-fs.service systemd-tmpfiles-setup.service +After=systemd-remount-fs.service systemd-tmpfiles-setup.service systemd-sysusers.service [Socket] ListenDatagram=/run/timesyncd/time-sync.sock +SocketUser=systemd-timesync +SocketMode=0200 diff --git a/systemd-timesyncd-wrap.go b/systemd-timesyncd-wrap.go index 3d5971b..76914a4 100644 --- a/systemd-timesyncd-wrap.go +++ b/systemd-timesyncd-wrap.go @@ -1,8 +1,11 @@ package main import ( + "fmt" "net" "os" + "os/user" + "strconv" "strings" "sync" "syscall" @@ -35,18 +38,27 @@ func main() { fake_sockname := "/run/timesyncd/notify.sock" real_sockname := os.Getenv("NOTIFY_SOCKET") + user, err := user.Lookup("systemd-timesync") + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(127) + } + uid, _ := strconv.Atoi(user.Uid) + gid, _ := strconv.Atoi(user.Gid) + + umask := syscall.Umask(0577) fake_sock, err := net.ListenUnixgram("unixgram", &net.UnixAddr{Net: "unixgram", Name: fake_sockname}) + syscall.Umask(umask) if err != nil { - os.Stderr.WriteString(err.Error()) - os.Stderr.Write([]byte{'\n'}) + fmt.Fprintln(os.Stderr, err) os.Exit(127) } + os.Chown(fake_sockname, uid, gid) os.Setenv("NOTIFY_SOCKET", fake_sockname) - proc, err := os.StartProcess(os.Args[1], os.Args[1:], &os.ProcAttr{}) + proc, err := os.StartProcess(os.Args[1], os.Args[1:], &os.ProcAttr{Files: []*os.File{os.Stdin, os.Stdout, os.Stderr}}) if err != nil { - os.Stderr.WriteString(err.Error()) - os.Stderr.Write([]byte{'\n'}) + fmt.Fprintln(os.Stderr, err) os.Exit(127) } @@ -59,21 +71,29 @@ func main() { for { n, oobn, flags, _, err := fake_sock.ReadMsgUnix(dat[:], oob[:]) if err != nil { + fmt.Fprintln(os.Stderr, err) break } if flags&syscall.MSG_TRUNC != 0 { + fmt.Fprintln(os.Stderr, "Received notify message exceeded maximum size. Ignoring.") continue } if !synced { for _, line := range strings.Split(string(dat[:n]), "\n") { if strings.HasPrefix(line, "STATUS=Synchronized") { - _ = sendmsg([]byte(line), nil, sync_sockname) + err = sendmsg([]byte(line), nil, sync_sockname) + if err != nil { + fmt.Fprintln(os.Stderr, err) + } synced = true break } } } - _ = sendmsg(dat[:n], oob[:oobn], real_sockname) + err = sendmsg(dat[:n], oob[:oobn], real_sockname) + if err != nil { + fmt.Fprintln(os.Stderr, err) + } } wg.Done() }() @@ -83,8 +103,7 @@ func main() { wg.Wait() if err != nil { - os.Stderr.WriteString(err.Error()) - os.Stderr.Write([]byte{'\n'}) + fmt.Println(os.Stderr, err) os.Exit(127) } status := state.Sys().(syscall.WaitStatus) diff --git a/systemd-timesyncd.service.d-wait.conf b/systemd-timesyncd.service.d-wait.conf index 8342e53..2775888 100644 --- a/systemd-timesyncd.service.d-wait.conf +++ b/systemd-timesyncd.service.d-wait.conf @@ -4,4 +4,8 @@ After=systemd-timesyncd-wait.socket [Service] Sockets= +ExecStart= ExecStart=/usr/lib/systemd/systemd-timesyncd-wrap /usr/lib/systemd/systemd-timesyncd +ExecStopPost=/usr/bin/rm -f -- /run/timesyncd/notify.sock +ExecStartPre=/usr/bin/rm -f -- /run/timesyncd/notify.sock +NotifyAccess=all -- cgit v1.1-4-g5e80