Pull request: 2231 autoupdate

Merge in DNS/adguard-home from 2231-autoupdate to master

Updates #2231.

Squashed commit of the following:

commit 4ee9148ee7a38f2759898302a2109aa982fb4ee9
Author: Eugene Burkov <e.burkov@adguard.com>
Date:   Mon Nov 30 19:08:14 2020 +0300

    sysutil: provide os-independent interface

commit 778097c5fdeb1dec94f4cfc6443d08f92d9db0ba
Author: Eugene Burkov <e.burkov@adguard.com>
Date:   Mon Nov 30 16:40:33 2020 +0300

    all: add sysutil package
This commit is contained in:
Eugene Burkov 2020-11-30 19:23:14 +03:00
parent 6e615c6eaa
commit 641db73a86
13 changed files with 158 additions and 88 deletions

View file

@ -26,12 +26,14 @@ and this project adheres to
### Changed
- Make the mobileconfig HTTP API more robust and predictable, add parameters and
- Post-updating relaunch possibility is now determined OS-dependently ([#2231]).
- Made the mobileconfig HTTP API more robust and predictable, add parameters and
improve error response ([#2358]).
- Improved HTTP requests handling and timeouts. ([#2343]).
- Our snap package now uses the `core20` image as its base [#2306].
- Various internal improvements ([#2271], [#2297]).
[#2231]: https://github.com/AdguardTeam/AdGuardHome/issues/2231
[#2271]: https://github.com/AdguardTeam/AdGuardHome/issues/2271
[#2297]: https://github.com/AdguardTeam/AdGuardHome/issues/2297
[#2306]: https://github.com/AdguardTeam/AdGuardHome/issues/2306

View file

@ -10,8 +10,8 @@ import (
"strings"
"syscall"
"github.com/AdguardTeam/AdGuardHome/internal/sysutil"
"github.com/AdguardTeam/AdGuardHome/internal/update"
"github.com/AdguardTeam/AdGuardHome/internal/util"
"github.com/AdguardTeam/golibs/log"
)
@ -104,12 +104,7 @@ func getVersionResp(info update.VersionInfo) []byte {
tlsConf.PortDNSOverQUIC < 1024)) ||
config.BindPort < 1024 ||
config.DNS.Port < 1024) {
// On UNIX, if we're running under a regular user,
// but with CAP_NET_BIND_SERVICE set on a binary file,
// and we're listening on ports <1024,
// we won't be able to restart after we replace the binary file,
// because we'll lose CAP_NET_BIND_SERVICE capability.
canUpdate, _ = util.HaveAdminRights()
canUpdate, _ = sysutil.CanBindPrivilegedPorts()
}
ret["can_autoupdate"] = canUpdate
}

View file

@ -26,6 +26,7 @@ import (
"github.com/AdguardTeam/AdGuardHome/internal/dnsforward"
"github.com/AdguardTeam/AdGuardHome/internal/querylog"
"github.com/AdguardTeam/AdGuardHome/internal/stats"
"github.com/AdguardTeam/AdGuardHome/internal/sysutil"
"github.com/AdguardTeam/AdGuardHome/internal/update"
"github.com/AdguardTeam/AdGuardHome/internal/util"
"github.com/AdguardTeam/golibs/log"
@ -222,7 +223,7 @@ func setupConfig(args options) {
if (runtime.GOOS == "linux" || runtime.GOOS == "darwin") &&
config.RlimitNoFile != 0 {
util.SetRlimit(config.RlimitNoFile)
sysutil.SetRlimit(config.RlimitNoFile)
}
// override bind host/port from the console
@ -376,7 +377,7 @@ func checkPermissions() {
if runtime.GOOS == "windows" {
// On Windows we need to have admin rights to run properly
admin, _ := util.HaveAdminRights()
admin, _ := sysutil.HaveAdminRights()
if admin {
return
}
@ -493,7 +494,7 @@ func configureLogger(args options) {
if ls.LogFile == configSyslog {
// Use syslog where it is possible and eventlog on Windows
err := util.ConfigureSyslog(serviceName)
err := sysutil.ConfigureSyslog(serviceName)
if err != nil {
log.Fatalf("cannot initialize syslog: %s", err)
}

View file

@ -9,6 +9,7 @@ import (
"strings"
"syscall"
"github.com/AdguardTeam/AdGuardHome/internal/sysutil"
"github.com/AdguardTeam/AdGuardHome/internal/util"
"github.com/AdguardTeam/golibs/log"
"github.com/kardianos/service"
@ -109,7 +110,7 @@ func sendSigReload() {
log.Error("Can't read PID file %s: %s", pidfile, err)
return
}
err = util.SendProcessSignal(pid, syscall.SIGHUP)
err = sysutil.SendProcessSignal(pid, syscall.SIGHUP)
if err != nil {
log.Error("Can't send signal to PID %d: %s", pid, err)
return

View file

@ -0,0 +1,32 @@
//+build freebsd
package sysutil
import (
"os"
"syscall"
"github.com/AdguardTeam/golibs/log"
)
func canBindPrivilegedPorts() (can bool, err error) {
return HaveAdminRights()
}
func setRlimit(val uint) {
var rlim syscall.Rlimit
rlim.Max = int64(val)
rlim.Cur = int64(val)
err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, &rlim)
if err != nil {
log.Error("Setrlimit() failed: %v", err)
}
}
func haveAdminRights() (bool, error) {
return os.Getuid() == 0, nil
}
func sendProcessSignal(pid int, sig syscall.Signal) error {
return syscall.Kill(pid, sig)
}

View file

@ -0,0 +1,34 @@
//+build linux
package sysutil
import (
"os"
"syscall"
"github.com/AdguardTeam/golibs/log"
"golang.org/x/sys/unix"
)
func canBindPrivilegedPorts() (can bool, err error) {
cnbs, err := unix.PrctlRetInt(unix.PR_CAP_AMBIENT, unix.PR_CAP_AMBIENT_IS_SET, unix.CAP_NET_BIND_SERVICE, 0, 0)
return cnbs == 1, err
}
func setRlimit(val uint) {
var rlim syscall.Rlimit
rlim.Max = uint64(val)
rlim.Cur = uint64(val)
err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, &rlim)
if err != nil {
log.Error("Setrlimit() failed: %v", err)
}
}
func haveAdminRights() (bool, error) {
return os.Getuid() == 0, nil
}
func sendProcessSignal(pid int, sig syscall.Signal) error {
return syscall.Kill(pid, sig)
}

View file

@ -0,0 +1,32 @@
//+build aix darwin dragonfly netbsd openbsd solaris
package sysutil
import (
"os"
"syscall"
"github.com/AdguardTeam/golibs/log"
)
func canBindPrivilegedPorts() (can bool, err error) {
return HaveAdminRights()
}
func setRlimit(val uint) {
var rlim syscall.Rlimit
rlim.Max = uint64(val)
rlim.Cur = uint64(val)
err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, &rlim)
if err != nil {
log.Error("Setrlimit() failed: %v", err)
}
}
func haveAdminRights() (bool, error) {
return os.Getuid() == 0, nil
}
func sendProcessSignal(pid int, sig syscall.Signal) error {
return syscall.Kill(pid, sig)
}

View file

@ -1,4 +1,6 @@
package util
//+build windows
package sysutil
import (
"fmt"
@ -7,11 +9,14 @@ import (
"golang.org/x/sys/windows"
)
// Set user-specified limit of how many fd's we can use
func SetRlimit(val uint) {
func canBindPrivilegedPorts() (can bool, err error) {
return HaveAdminRights()
}
func HaveAdminRights() (bool, error) {
func setRlimit(val uint) {
}
func haveAdminRights() (bool, error) {
var token windows.Token
h := windows.CurrentProcess()
err := windows.OpenProcessToken(h, windows.TOKEN_QUERY, &token)
@ -32,6 +37,6 @@ func HaveAdminRights() (bool, error) {
return true, nil
}
func SendProcessSignal(pid int, sig syscall.Signal) error {
func sendProcessSignal(pid int, sig syscall.Signal) error {
return fmt.Errorf("not supported on Windows")
}

View file

@ -1,14 +1,13 @@
// +build !windows,!nacl,!plan9
//+build !windows,!nacl,!plan9
package util
package sysutil
import (
"log"
"log/syslog"
)
// ConfigureSyslog reroutes standard logger output to syslog
func ConfigureSyslog(serviceName string) error {
func configureSyslog(serviceName string) error {
w, err := syslog.New(syslog.LOG_NOTICE|syslog.LOG_USER, serviceName)
if err != nil {
return err

View file

@ -1,4 +1,6 @@
package util
//+build windows nacl plan9
package sysutil
import (
"log"
@ -12,12 +14,12 @@ type eventLogWriter struct {
el *eventlog.Log
}
// Write sends a log message to the Event Log.
// Write implements io.Writer interface for eventLogWriter.
func (w *eventLogWriter) Write(b []byte) (int, error) {
return len(b), w.el.Info(1, string(b))
}
func ConfigureSyslog(serviceName string) error {
func configureSyslog(serviceName string) error {
// Note that the eventlog src is the same as the service name
// Otherwise, we will get "the description for event id cannot be found" warning in every log record

View file

@ -0,0 +1,31 @@
// Package sysutil contains utilities for functions requiring system calls.
package sysutil
import "syscall"
// CanBindPrivilegedPorts checks if current process can bind to privileged
// ports.
func CanBindPrivilegedPorts() (can bool, err error) {
return canBindPrivilegedPorts()
}
// SetRlimit sets user-specified limit of how many fd's we can use
// https://github.com/AdguardTeam/AdGuardHome/internal/issues/659.
func SetRlimit(val uint) {
setRlimit(val)
}
// HaveAdminRights checks if the current user has root (administrator) rights.
func HaveAdminRights() (bool, error) {
return haveAdminRights()
}
// SendProcessSignal sends signal to a process.
func SendProcessSignal(pid int, sig syscall.Signal) error {
return sendProcessSignal(pid, sig)
}
// ConfigureSyslog reroutes standard logger output to syslog.
func ConfigureSyslog(serviceName string) error {
return configureSyslog(serviceName)
}

View file

@ -1,32 +0,0 @@
// +build freebsd
package util
import (
"os"
"syscall"
"github.com/AdguardTeam/golibs/log"
)
// Set user-specified limit of how many fd's we can use
// https://github.com/AdguardTeam/AdGuardHome/internal/issues/659
func SetRlimit(val uint) {
var rlim syscall.Rlimit
rlim.Max = int64(val)
rlim.Cur = int64(val)
err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, &rlim)
if err != nil {
log.Error("Setrlimit() failed: %v", err)
}
}
// Check if the current user has root (administrator) rights
func HaveAdminRights() (bool, error) {
return os.Getuid() == 0, nil
}
// SendProcessSignal - send signal to a process
func SendProcessSignal(pid int, sig syscall.Signal) error {
return syscall.Kill(pid, sig)
}

View file

@ -1,32 +0,0 @@
// +build aix darwin dragonfly linux netbsd openbsd solaris
package util
import (
"os"
"syscall"
"github.com/AdguardTeam/golibs/log"
)
// Set user-specified limit of how many fd's we can use
// https://github.com/AdguardTeam/AdGuardHome/internal/issues/659
func SetRlimit(val uint) {
var rlim syscall.Rlimit
rlim.Max = uint64(val)
rlim.Cur = uint64(val)
err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, &rlim)
if err != nil {
log.Error("Setrlimit() failed: %v", err)
}
}
// Check if the current user has root (administrator) rights
func HaveAdminRights() (bool, error) {
return os.Getuid() == 0, nil
}
// SendProcessSignal - send signal to a process
func SendProcessSignal(pid int, sig syscall.Signal) error {
return syscall.Kill(pid, sig)
}