Code review and cleanup.
This commit is contained in:
1 parent
bbe931335f
commit
92d6ad3cc4
23 files changed
+1497
-886
No files matched your search
@@ -0,0 +1,127 @@
|
||||
// Copyright (c) 2026 Storm Dragon
|
||||
// Authors: Storm Dragon, Angus Kola
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package wine
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
// A helperSet is a launch-local snapshot of the complete installed helper.
|
||||
// Publishing and verification use the same bytes and modes that form its digest.
|
||||
type helperSet struct {
|
||||
files []helperFile
|
||||
digest string
|
||||
}
|
||||
|
||||
type helperFile struct {
|
||||
name string
|
||||
data []byte
|
||||
mode os.FileMode
|
||||
}
|
||||
|
||||
// A pressure-vessel wineserver cannot see the host's /usr. Publish complete,
|
||||
// immutable helper sets in the home-mounted state directory. Never overwrite
|
||||
// an older set: running processes may still have its sidecar mapped.
|
||||
func stage_helper(helper string, environment map[string]string) (string, error) {
|
||||
if _, present := environment["PRESSURE_VESSEL_RUNTIME"]; !present {
|
||||
return helper, nil
|
||||
}
|
||||
stateHome := os.Getenv("XDG_STATE_HOME")
|
||||
if stateHome == "" {
|
||||
home, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
stateHome = filepath.Join(home, ".local", "state")
|
||||
}
|
||||
if !filepath.IsAbs(stateHome) {
|
||||
return "", fmt.Errorf("Wine helper state directory must be absolute")
|
||||
}
|
||||
set, err := readHelperSet(helper)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
stage, err := set.publish(filepath.Join(stateHome, "cthulhu", "wine-access", "helper"))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return filepath.Join(stage, filepath.Base(helper)), nil
|
||||
}
|
||||
|
||||
func readHelperSet(helper string) (*helperSet, error) {
|
||||
names := []string{filepath.Base(helper), filepath.Base(helper) + ".so", "wine-access-menu.dll", "wine-access-menu32.dll", "wine-access-menu-host32.exe"}
|
||||
set := &helperSet{}
|
||||
digest := sha256.New()
|
||||
for _, name := range names {
|
||||
path := filepath.Join(filepath.Dir(helper), name)
|
||||
data, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("read helper set: %w", err)
|
||||
}
|
||||
info, err := os.Stat(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
file := helperFile{name: name, data: data, mode: 0600}
|
||||
if info.Mode().Perm()&0111 != 0 {
|
||||
file.mode = 0700
|
||||
}
|
||||
fmt.Fprintf(digest, "%s\x00%d\x00%d\x00", name, len(data), file.mode)
|
||||
digest.Write(data)
|
||||
set.files = append(set.files, file)
|
||||
}
|
||||
set.digest = fmt.Sprintf("%x", digest.Sum(nil))
|
||||
return set, nil
|
||||
}
|
||||
|
||||
func (set *helperSet) publish(root string) (string, error) {
|
||||
if err := os.MkdirAll(root, 0700); err != nil {
|
||||
return "", err
|
||||
}
|
||||
stage := filepath.Join(root, set.digest)
|
||||
if _, err := os.Stat(stage); os.IsNotExist(err) {
|
||||
temporary, err := os.MkdirTemp(root, ".stage-")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer os.RemoveAll(temporary)
|
||||
for _, file := range set.files {
|
||||
if err := os.WriteFile(filepath.Join(temporary, file.name), file.data, file.mode); err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
if err := os.Rename(temporary, stage); err != nil {
|
||||
if info, statErr := os.Stat(stage); statErr != nil || !info.IsDir() {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
}
|
||||
if err := set.verify(stage); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return stage, nil
|
||||
}
|
||||
|
||||
func (set *helperSet) verify(stage string) error {
|
||||
for _, file := range set.files {
|
||||
path := filepath.Join(stage, file.name)
|
||||
data, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
info, err := os.Stat(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !bytes.Equal(data, file.data) || info.Mode().Perm() != file.mode {
|
||||
return fmt.Errorf("incomplete or modified staged Wine helper")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -5,8 +5,6 @@ package wine
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
@@ -83,81 +81,3 @@ func (manager *Manager) helper_arguments(controllerOnly bool) []string {
|
||||
}
|
||||
return arguments
|
||||
}
|
||||
|
||||
// A pressure-vessel wineserver cannot see the host's /usr. Publish complete,
|
||||
// immutable helper sets in the home-mounted state directory. Never overwrite
|
||||
// an older set: running processes may still have its sidecar mapped.
|
||||
func stage_helper(helper string, environment map[string]string) (string, error) {
|
||||
if _, present := environment["PRESSURE_VESSEL_RUNTIME"]; !present {
|
||||
return helper, nil
|
||||
}
|
||||
stateHome := os.Getenv("XDG_STATE_HOME")
|
||||
if stateHome == "" {
|
||||
home, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
stateHome = filepath.Join(home, ".local", "state")
|
||||
}
|
||||
if !filepath.IsAbs(stateHome) {
|
||||
return "", fmt.Errorf("Wine helper state directory must be absolute")
|
||||
}
|
||||
names := []string{filepath.Base(helper), filepath.Base(helper) + ".so", "wine-access-menu.dll", "wine-access-menu32.dll", "wine-access-menu-host32.exe"}
|
||||
contents := make(map[string][]byte)
|
||||
modes := make(map[string]os.FileMode)
|
||||
digest := sha256.New()
|
||||
for _, name := range names {
|
||||
path := filepath.Join(filepath.Dir(helper), name)
|
||||
data, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("read helper set: %w", err)
|
||||
}
|
||||
info, err := os.Stat(path)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
contents[name], modes[name] = data, 0600
|
||||
if info.Mode().Perm()&0111 != 0 {
|
||||
modes[name] = 0700
|
||||
}
|
||||
fmt.Fprintf(digest, "%s\x00%d\x00%d\x00", name, len(data), modes[name])
|
||||
digest.Write(data)
|
||||
}
|
||||
root := filepath.Join(stateHome, "cthulhu", "wine-access", "helper")
|
||||
if err := os.MkdirAll(root, 0700); err != nil {
|
||||
return "", err
|
||||
}
|
||||
stage := filepath.Join(root, fmt.Sprintf("%x", digest.Sum(nil)))
|
||||
if _, err := os.Stat(stage); os.IsNotExist(err) {
|
||||
temporary, err := os.MkdirTemp(root, ".stage-")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer os.RemoveAll(temporary)
|
||||
for _, name := range names {
|
||||
if err := os.WriteFile(filepath.Join(temporary, name), contents[name], modes[name]); err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
if err := os.Rename(temporary, stage); err != nil {
|
||||
if info, statErr := os.Stat(stage); statErr != nil || !info.IsDir() {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, name := range names {
|
||||
path := filepath.Join(stage, name)
|
||||
data, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
info, err := os.Stat(path)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if !bytes.Equal(data, contents[name]) || info.Mode().Perm() != modes[name] {
|
||||
return "", fmt.Errorf("incomplete or modified staged Wine helper")
|
||||
}
|
||||
}
|
||||
return filepath.Join(stage, filepath.Base(helper)), nil
|
||||
}
|
||||
Reference in new issue
Block a user