[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[tor-commits] [sandboxed-tor-browser/master] Bug #20899: Dunlib/PulseAudio fixes.
commit e68ab9154e73f2fde78ffaf556f39670e4a807f5
Author: Yawning Angel <yawning@xxxxxxxxxxxxxxx>
Date: Wed Dec 7 01:05:28 2016 +0000
Bug #20899: Dunlib/PulseAudio fixes.
* Try even harder to avoid sticking libraries with the wrong architecture
in the container.
* If libpulsecore can't be found, don't bindmount libpulse.so, since it
will abort() in the stub. No audio, but it beats crashing.
---
.../sandboxed-tor-browser/internal/dynlib/cache.go | 4 +-
.../sandboxed-tor-browser/internal/dynlib/ldso.go | 30 +++++++-
.../internal/sandbox/application.go | 70 ++++++------------
.../internal/sandbox/pulse.go | 85 +++++++++++++++++++++-
4 files changed, 135 insertions(+), 54 deletions(-)
diff --git a/src/cmd/sandboxed-tor-browser/internal/dynlib/cache.go b/src/cmd/sandboxed-tor-browser/internal/dynlib/cache.go
index 4bcc60d..11f1ee3 100644
--- a/src/cmd/sandboxed-tor-browser/internal/dynlib/cache.go
+++ b/src/cmd/sandboxed-tor-browser/internal/dynlib/cache.go
@@ -94,7 +94,7 @@ func (c *Cache) ResolveLibraries(binaries []string, extraLibs []string, ldLibrar
break
}
for _, fn := range toCheck {
- impLibs, err := GetLibraries(fn)
+ impLibs, err := getLibraries(fn)
if err != nil {
return nil, err
}
@@ -373,6 +373,8 @@ func LoadCache() (*Cache, error) {
// osVersion, or hwcap.
if ourOsVersion < e.osVersion {
Debugf("dynlib: ignoring library: %v (osVersion: %x)", e.key, e.osVersion)
+ } else if err = ValidateLibraryClass(e.value); err != nil {
+ Debugf("dynlib: ignoring library %v (%v)", e.key, err)
} else if flagCheckFn(e.flags) && capCheckFn(e.hwcap) {
vec := c.store[e.key]
vec = append(vec, e)
diff --git a/src/cmd/sandboxed-tor-browser/internal/dynlib/ldso.go b/src/cmd/sandboxed-tor-browser/internal/dynlib/ldso.go
index 812a5a6..92e16c1 100644
--- a/src/cmd/sandboxed-tor-browser/internal/dynlib/ldso.go
+++ b/src/cmd/sandboxed-tor-browser/internal/dynlib/ldso.go
@@ -19,6 +19,7 @@ package dynlib
import (
"debug/elf"
"errors"
+ "fmt"
"os"
"path/filepath"
"runtime"
@@ -26,9 +27,7 @@ import (
var errUnsupported = errors.New("dynlib: unsupported os/architecture")
-// GetLibraries returns the dynamic libraries imported by the given file at
-// dynamic link time.
-func GetLibraries(fn string) ([]string, error) {
+func getLibraries(fn string) ([]string, error) {
f, err := elf.Open(fn)
if err != nil {
return nil, err
@@ -38,6 +37,31 @@ func GetLibraries(fn string) ([]string, error) {
return f.ImportedLibraries()
}
+// ValidateLibraryClass ensures that the library matches the current
+// architecture.
+func ValidateLibraryClass(fn string) error {
+ f, err := elf.Open(fn)
+ if err != nil {
+ return err
+ }
+ defer f.Close()
+
+ var expectedClass elf.Class
+ switch runtime.GOARCH {
+ case "amd64":
+ expectedClass = elf.ELFCLASS64
+ case "386":
+ expectedClass = elf.ELFCLASS32
+ default:
+ return errUnsupported
+ }
+
+ if f.Class != expectedClass {
+ return fmt.Errorf("unsupported class: %v", fn, f.Class)
+ }
+ return nil
+}
+
// FindLdSo returns the path to the `ld.so` dynamic linker for the current
// architecture, which is usually a symlink
func FindLdSo(cache *Cache) (string, string, error) {
diff --git a/src/cmd/sandboxed-tor-browser/internal/sandbox/application.go b/src/cmd/sandboxed-tor-browser/internal/sandbox/application.go
index 939d805..4cd4ca0 100644
--- a/src/cmd/sandboxed-tor-browser/internal/sandbox/application.go
+++ b/src/cmd/sandboxed-tor-browser/internal/sandbox/application.go
@@ -28,7 +28,6 @@ import (
"path/filepath"
"runtime"
"sort"
- "strings"
"syscall"
"cmd/sandboxed-tor-browser/internal/dynlib"
@@ -220,54 +219,13 @@ func RunTorBrowser(cfg *config.Config, manif *config.Manifest, tor *tor.Tor) (cm
ldLibraryPath = ldLibraryPath + glLibPaths
if cfg.Sandbox.EnablePulseAudio && pulseAudioWorks {
- const libPulse = "libpulse.so.0"
-
- paLibsPath := findDistributionDependentLibs(nil, "", "pulseaudio")
- if paLibsPath != "" && cache.GetLibraryPath(libPulse) != "" {
- const restrictedPulseDir = "/usr/lib/pulseaudio"
-
- // The library search path ("/usr/lib/pulseaudio"), is
- // hardcoded into libpulse.so.0, because you suck, and we hate
- // you.
- extraLibs = append(extraLibs, libPulse)
- ldLibraryPath = ldLibraryPath + ":" + paLibsPath
- h.dir(restrictedPulseDir)
- extraLdLibraryPath = extraLdLibraryPath + ":" + restrictedPulseDir
-
- boundPulseCore := false
- matches, err := filepath.Glob(paLibsPath + "/*.so")
- if err != nil {
- return nil, err
- }
- for _, v := range matches {
- _, f := filepath.Split(v)
- if strings.HasPrefix(f, "libpulsecore") {
- boundPulseCore = true
- }
- h.roBind(v, filepath.Join(restrictedPulseDir, f), false)
- extraLibs = append(extraLibs, f)
- }
-
- if !boundPulseCore {
- // Debian sticks libpulsecore-blah.so in /usr/lib, unlike
- // everyone else who sticks it in /usr/lib/pulseaudo,
- // because fuck you.
- matches, err = filepath.Glob("/usr/lib/libpulsecore-*.so")
- if err != nil {
- return nil, err
- }
- if len(matches) == 0 {
- log.Printf("sandbox: Failed to find `libpulsecore-<version>.so`, audio will crash the browser.")
- } else {
- for _, v := range matches {
- _, f := filepath.Split(v)
- h.roBind(v, filepath.Join(restrictedPulseDir, f), false)
- extraLibs = append(extraLibs, f)
- }
- }
- }
+ paLibs, paPath, paExtraPath, err := h.appendRestrictedPulseAudio(cache)
+ if err != nil {
+ log.Printf("sandbox: Failed to find PulseAudio libraries: %v", err)
} else {
- log.Printf("sandbox: Failed to find pulse audio libraries.")
+ extraLibs = append(extraLibs, paLibs...)
+ ldLibraryPath = ldLibraryPath + paPath
+ extraLdLibraryPath = extraLdLibraryPath + paExtraPath
}
}
if codec := findBestCodec(cache); codec != "" {
@@ -588,7 +546,21 @@ func findDistributionDependentLibs(extraSearch []string, subDir, fn string) stri
for _, base := range searchPaths {
candidate := filepath.Join(base, subDir, fn)
- if FileExists(candidate) {
+ if FileExists(candidate) && dynlib.ValidateLibraryClass(candidate) == nil {
+ return candidate
+ }
+ }
+ return ""
+}
+
+func findDistributionDependentDir(extraSearch []string, subDir, fn string) string {
+ var searchPaths []string
+ searchPaths = append(searchPaths, extraSearch...)
+ searchPaths = append(searchPaths, distributionDependentLibSearchPath...)
+
+ for _, base := range searchPaths {
+ candidate := filepath.Join(base, subDir, fn)
+ if DirExists(candidate) {
return candidate
}
}
diff --git a/src/cmd/sandboxed-tor-browser/internal/sandbox/pulse.go b/src/cmd/sandboxed-tor-browser/internal/sandbox/pulse.go
index 0b2fd6d..c58843b 100644
--- a/src/cmd/sandboxed-tor-browser/internal/sandbox/pulse.go
+++ b/src/cmd/sandboxed-tor-browser/internal/sandbox/pulse.go
@@ -24,6 +24,9 @@ import (
"strings"
xdg "github.com/cep21/xdgbasedir"
+
+ "cmd/sandboxed-tor-browser/internal/dynlib"
+ . "cmd/sandboxed-tor-browser/internal/utils"
)
func (h *hugbox) enablePulseAudio() error {
@@ -48,7 +51,7 @@ func (h *hugbox) enablePulseAudio() error {
}
if fi, err := os.Stat(sockPath); err != nil {
- // No pulse Audio socket.
+ // No PulseAudio socket.
return fmt.Errorf("sandbox: no PulseAudio socket")
} else if fi.Mode()&os.ModeSocket == 0 {
// Not an AF_LOCAL socket.
@@ -93,3 +96,83 @@ func (h *hugbox) enablePulseAudio() error {
return nil
}
+
+func (h *hugbox) appendRestrictedPulseAudio(cache *dynlib.Cache) ([]string, string, string, error) {
+ const libPulse = "libpulse.so.0"
+
+ type roBindEnt struct {
+ src, dst string
+ }
+ toRoBind := []roBindEnt{}
+
+ extraLibs := []string{}
+ ldLibraryPath := ""
+ extraLdLibraryPath := ""
+
+ paLibsPath := findDistributionDependentDir(nil, "", "pulseaudio")
+ if paLibsPath != "" && cache.GetLibraryPath(libPulse) != "" {
+ const restrictedPulseDir = "/usr/lib/pulseaudio"
+
+ // The library search path ("/usr/lib/pulseaudio"), is
+ // hardcoded into libpulse.so.0, because you suck, and we hate
+ // you.
+
+ extraLibs = append(extraLibs, libPulse)
+ ldLibraryPath = ldLibraryPath + ":" + paLibsPath
+ extraLdLibraryPath = extraLdLibraryPath + ":" + restrictedPulseDir
+
+ // The special handling for libpulsecore is because, we need to dlopen
+ // it in our stub.
+
+ boundPulseCore := false
+ matches, err := filepath.Glob(paLibsPath + "/*.so")
+ if err != nil {
+ return nil, "", "", err
+ }
+ for _, v := range matches {
+ if dynlib.ValidateLibraryClass(v) != nil {
+ Debugf("sandbox: Unsuitable PulseAudio so: %v", v)
+ continue
+ }
+ _, f := filepath.Split(v)
+ if strings.HasPrefix(f, "libpulsecore") {
+ boundPulseCore = true
+ }
+ toRoBind = append(toRoBind, roBindEnt{v, filepath.Join(restrictedPulseDir, f)})
+ extraLibs = append(extraLibs, f)
+ }
+
+ // Debian sticks libpulsecore-blah.so in /usr/lib, unlike
+ // everyone else who sticks it in /usr/lib/pulseaudo,
+ // because fuck you.
+ if !boundPulseCore {
+ matches, err = filepath.Glob("/usr/lib/libpulsecore-*.so")
+ if err != nil {
+ return nil, "", "", err
+ }
+ for _, v := range matches {
+ if dynlib.ValidateLibraryClass(v) != nil {
+ Debugf("sandbox: Unsuitable pulsecore: %v", v)
+ continue
+ }
+ _, f := filepath.Split(v)
+ toRoBind = append(toRoBind, roBindEnt{v, filepath.Join(restrictedPulseDir, f)})
+ extraLibs = append(extraLibs, f)
+ boundPulseCore = true
+ break
+ }
+ }
+
+ // Now that we're done trying to find all the PulseAudio bits,
+ // actually bindmount everything into the sandbox.
+ if boundPulseCore {
+ h.dir(restrictedPulseDir)
+ for _, ent := range toRoBind {
+ h.roBind(ent.src, ent.dst, false)
+ }
+ return extraLibs, ldLibraryPath, extraLdLibraryPath, nil
+ }
+ }
+
+ return nil, "", "", fmt.Errorf("failed to find PulseAudio libraries")
+}
_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits