Automatically fix chrome-sandbox permissions on older kernels
This commit is contained in:
@@ -12,6 +12,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/safing/portmaster/updates/helper"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/tevino/abool"
|
"github.com/tevino/abool"
|
||||||
)
|
)
|
||||||
@@ -283,7 +284,9 @@ func persistOutputStreams(opts *Options, version string, cmd *exec.Cmd) (chan st
|
|||||||
}
|
}
|
||||||
|
|
||||||
func execute(opts *Options, args []string) (cont bool, err error) {
|
func execute(opts *Options, args []string) (cont bool, err error) {
|
||||||
file, err := registry.GetFile(platform(opts.Identifier))
|
file, err := registry.GetFile(
|
||||||
|
helper.PlatformIdentifier(opts.Identifier),
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return true, fmt.Errorf("could not get component: %w", err)
|
return true, fmt.Errorf("could not get component: %w", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/safing/portmaster/updates/helper"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -30,7 +31,9 @@ func show(opts *Options, cmdArgs []string) error {
|
|||||||
opts.Identifier += exeSuffix
|
opts.Identifier += exeSuffix
|
||||||
}
|
}
|
||||||
|
|
||||||
file, err := registry.GetFile(platform(opts.Identifier))
|
file, err := registry.GetFile(
|
||||||
|
helper.PlatformIdentifier(opts.Identifier),
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("could not get component: %s", err)
|
return fmt.Errorf("could not get component: %s", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"runtime"
|
|
||||||
|
|
||||||
"github.com/safing/portbase/log"
|
"github.com/safing/portbase/log"
|
||||||
|
"github.com/safing/portmaster/updates/helper"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -52,31 +52,31 @@ func downloadUpdates() error {
|
|||||||
// mark required updates
|
// mark required updates
|
||||||
if onWindows {
|
if onWindows {
|
||||||
registry.MandatoryUpdates = []string{
|
registry.MandatoryUpdates = []string{
|
||||||
platform("core/portmaster-core.exe"),
|
helper.PlatformIdentifier("core/portmaster-core.exe"),
|
||||||
platform("kext/portmaster-kext.dll"),
|
helper.PlatformIdentifier("kext/portmaster-kext.dll"),
|
||||||
platform("kext/portmaster-kext.sys"),
|
helper.PlatformIdentifier("kext/portmaster-kext.sys"),
|
||||||
platform("start/portmaster-start.exe"),
|
helper.PlatformIdentifier("start/portmaster-start.exe"),
|
||||||
platform("notifier/portmaster-notifier.exe"),
|
helper.PlatformIdentifier("notifier/portmaster-notifier.exe"),
|
||||||
platform("notifier/portmaster-snoretoast.exe"),
|
helper.PlatformIdentifier("notifier/portmaster-snoretoast.exe"),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
registry.MandatoryUpdates = []string{
|
registry.MandatoryUpdates = []string{
|
||||||
platform("core/portmaster-core"),
|
helper.PlatformIdentifier("core/portmaster-core"),
|
||||||
platform("start/portmaster-start"),
|
helper.PlatformIdentifier("start/portmaster-start"),
|
||||||
platform("notifier/portmaster-notifier"),
|
helper.PlatformIdentifier("notifier/portmaster-notifier"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// add updates that we require on all platforms.
|
// add updates that we require on all helper.PlatformIdentifiers.
|
||||||
registry.MandatoryUpdates = append(
|
registry.MandatoryUpdates = append(
|
||||||
registry.MandatoryUpdates,
|
registry.MandatoryUpdates,
|
||||||
platform("app/portmaster-app.zip"),
|
helper.PlatformIdentifier("app/portmaster-app.zip"),
|
||||||
"all/ui/modules/portmaster.zip",
|
"all/ui/modules/portmaster.zip",
|
||||||
)
|
)
|
||||||
|
|
||||||
// Add assets that need unpacking.
|
// Add assets that need unpacking.
|
||||||
registry.AutoUnpack = []string{
|
registry.AutoUnpack = []string{
|
||||||
platform("app/portmaster-app.zip"),
|
helper.PlatformIdentifier("app/portmaster-app.zip"),
|
||||||
}
|
}
|
||||||
|
|
||||||
// logging is configured as a persistent pre-run method inherited from
|
// logging is configured as a persistent pre-run method inherited from
|
||||||
@@ -93,11 +93,11 @@ func downloadUpdates() error {
|
|||||||
// Delete storage.
|
// Delete storage.
|
||||||
err = os.RemoveAll(registry.StorageDir().Path)
|
err = os.RemoveAll(registry.StorageDir().Path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to reset update dir: %s", err)
|
return fmt.Errorf("failed to reset update dir: %w", err)
|
||||||
}
|
}
|
||||||
err = registry.StorageDir().Ensure()
|
err = registry.StorageDir().Ensure()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to create update dir: %s", err)
|
return fmt.Errorf("failed to create update dir: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset registry state.
|
// Reset registry state.
|
||||||
@@ -120,7 +120,12 @@ func downloadUpdates() error {
|
|||||||
registry.SelectVersions()
|
registry.SelectVersions()
|
||||||
err = registry.UnpackResources()
|
err = registry.UnpackResources()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to unpack resources: %s", err)
|
return fmt.Errorf("failed to unpack resources: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fix chrome-sandbox permissions
|
||||||
|
if err := helper.EnsureChromeSandboxPermissions(registry); err != nil {
|
||||||
|
return fmt.Errorf("failed to fix electron permissions: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@@ -141,7 +146,3 @@ func purge() error {
|
|||||||
registry.Purge(3)
|
registry.Purge(3)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func platform(identifier string) string {
|
|
||||||
return fmt.Sprintf("%s_%s/%s", runtime.GOOS, runtime.GOARCH, identifier)
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,19 +1,15 @@
|
|||||||
package updates
|
package updates
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"path"
|
"path"
|
||||||
"runtime"
|
|
||||||
|
|
||||||
"github.com/safing/portbase/updater"
|
"github.com/safing/portbase/updater"
|
||||||
|
"github.com/safing/portmaster/updates/helper"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetPlatformFile returns the latest platform specific file identified by the given identifier.
|
// GetPlatformFile returns the latest platform specific file identified by the given identifier.
|
||||||
func GetPlatformFile(identifier string) (*updater.File, error) {
|
func GetPlatformFile(identifier string) (*updater.File, error) {
|
||||||
identifier = path.Join(fmt.Sprintf("%s_%s", runtime.GOOS, runtime.GOARCH), identifier)
|
identifier = helper.PlatformIdentifier(identifier)
|
||||||
// From https://golang.org/pkg/runtime/#GOARCH
|
|
||||||
// GOOS is the running program's operating system target: one of darwin, freebsd, linux, and so on.
|
|
||||||
// GOARCH is the running program's architecture target: one of 386, amd64, arm, s390x, and so on.
|
|
||||||
|
|
||||||
file, err := registry.GetFile(identifier)
|
file, err := registry.GetFile(identifier)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
84
updates/helper/electron.go
Normal file
84
updates/helper/electron.go
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
package helper
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/safing/portbase/log"
|
||||||
|
"github.com/safing/portbase/updater"
|
||||||
|
)
|
||||||
|
|
||||||
|
var pmElectronUpdate *updater.File
|
||||||
|
|
||||||
|
// EnsureChromeSandboxPermissions makes sure the chrome-sandbox distributed
|
||||||
|
// by our app-electron package has the SUID bit set on systems that do not
|
||||||
|
// allow unprivileged CLONE_NEWUSER (clone(3)).
|
||||||
|
// On non-linux systems or systems that have kernel.unprivileged_userns_clone
|
||||||
|
// set to 1 EnsureChromeSandboPermissions is a NO-OP
|
||||||
|
func EnsureChromeSandboxPermissions(reg *updater.ResourceRegistry) error {
|
||||||
|
if runtime.GOOS != "linux" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if checkSysctl("kernel.unprivileged_userns_clone", '1') {
|
||||||
|
log.Infof("Kernel support for unprivileged USERNS_CLONE enabled.")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if pmElectronUpdate != nil && !pmElectronUpdate.UpgradeAvailable() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
identifier := PlatformIdentifier("app/portmaster-app.zip")
|
||||||
|
|
||||||
|
log.Infof("Kernel support for unprivileged USERNS_CLONE disabled.")
|
||||||
|
|
||||||
|
var err error
|
||||||
|
pmElectronUpdate, err = reg.GetFile(identifier)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
unpackedPath := strings.TrimSuffix(
|
||||||
|
pmElectronUpdate.Path(),
|
||||||
|
filepath.Ext(pmElectronUpdate.Path()),
|
||||||
|
)
|
||||||
|
sandboxFile := filepath.Join(unpackedPath, "chrome-sandbox")
|
||||||
|
if err := os.Chmod(sandboxFile, 0755|os.ModeSetuid); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
log.Infof("Fixed SUID permissions for chrome-sandbox")
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PlatformIdentifier converts identifier for the current platform.
|
||||||
|
func PlatformIdentifier(identifier string) string {
|
||||||
|
// From https://golang.org/pkg/runtime/#GOARCH
|
||||||
|
// GOOS is the running program's operating system target: one of darwin, freebsd, linux, and so on.
|
||||||
|
// GOARCH is the running program's architecture target: one of 386, amd64, arm, s390x, and so on.
|
||||||
|
return fmt.Sprintf("%s_%s/%s", runtime.GOOS, runtime.GOARCH, identifier)
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkSysctl(setting string, value byte) bool {
|
||||||
|
c, err := sysctl(setting)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if len(c) < 1 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return c[0] == value
|
||||||
|
}
|
||||||
|
|
||||||
|
func sysctl(setting string) ([]byte, error) {
|
||||||
|
parts := append([]string{"/proc", "sys"}, strings.Split(setting, ".")...)
|
||||||
|
path := filepath.Join(parts...)
|
||||||
|
content, err := ioutil.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return content, nil
|
||||||
|
}
|
||||||
@@ -21,6 +21,7 @@ import (
|
|||||||
"github.com/safing/portbase/notifications"
|
"github.com/safing/portbase/notifications"
|
||||||
"github.com/safing/portbase/rng"
|
"github.com/safing/portbase/rng"
|
||||||
"github.com/safing/portbase/updater"
|
"github.com/safing/portbase/updater"
|
||||||
|
"github.com/safing/portmaster/updates/helper"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -65,14 +66,16 @@ func upgrader(_ context.Context, _ interface{}) error {
|
|||||||
binBaseName := strings.Split(filepath.Base(os.Args[0]), "_")[0]
|
binBaseName := strings.Split(filepath.Base(os.Args[0]), "_")[0]
|
||||||
switch binBaseName {
|
switch binBaseName {
|
||||||
case "portmaster-core":
|
case "portmaster-core":
|
||||||
err = upgradeCoreNotify()
|
if err := upgradeCoreNotify(); err != nil {
|
||||||
if err != nil {
|
|
||||||
log.Warningf("updates: failed to notify about core upgrade: %s", err)
|
log.Warningf("updates: failed to notify about core upgrade: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := helper.EnsureChromeSandboxPermissions(registry); err != nil {
|
||||||
|
log.Warningf("updates: failed to handle electron upgrade: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
case "spn-hub":
|
case "spn-hub":
|
||||||
err = upgradeHub()
|
if err := upgradeHub(); err != nil {
|
||||||
if err != nil {
|
|
||||||
log.Warningf("updates: failed to initiate hub upgrade: %s", err)
|
log.Warningf("updates: failed to initiate hub upgrade: %s", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user