Compare commits
18 Commits
699c19e972
...
c5aefe5e9d
| Author | SHA1 | Date | |
|---|---|---|---|
|
c5aefe5e9d
|
|||
|
0f8ffee44d
|
|||
|
1685a4d000
|
|||
|
6c338b433a
|
|||
|
8accd3b219
|
|||
|
c5f59c5488
|
|||
|
fcd9becf9a
|
|||
|
622f945c22
|
|||
|
e94acc424c
|
|||
|
b1a4d801be
|
|||
|
56beae17fe
|
|||
|
ea978101b1
|
|||
|
fbd1638e7f
|
|||
|
d42067df7c
|
|||
|
b9459a80c7
|
|||
|
f8189d1488
|
|||
|
5063b774c1
|
|||
|
766dd89ffa
|
@@ -2,7 +2,6 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
@@ -51,7 +50,7 @@ func buildCommand(ctx context.Context, msg message.Msg, early *earlyHardeningErr
|
|||||||
Flag(&flagVerbose, "v", command.BoolFlag(false), "Increase log verbosity").
|
Flag(&flagVerbose, "v", command.BoolFlag(false), "Increase log verbosity").
|
||||||
Flag(&flagJSON, "json", command.BoolFlag(false), "Serialise output in JSON when applicable")
|
Flag(&flagJSON, "json", command.BoolFlag(false), "Serialise output in JSON when applicable")
|
||||||
|
|
||||||
c.Command("shim", command.UsageInternal, func([]string) error { app.ShimMain(); return errSuccess })
|
c.Command("shim", command.UsageInternal, func([]string) error { app.Shim(msg); return errSuccess })
|
||||||
|
|
||||||
c.Command("app", "Load and start container from configuration file", func(args []string) error {
|
c.Command("app", "Load and start container from configuration file", func(args []string) error {
|
||||||
if len(args) < 1 {
|
if len(args) < 1 {
|
||||||
@@ -227,8 +226,11 @@ func buildCommand(ctx context.Context, msg message.Msg, early *earlyHardeningErr
|
|||||||
} else {
|
} else {
|
||||||
if f, err := os.Open(flagDBusConfigSession); err != nil {
|
if f, err := os.Open(flagDBusConfigSession); err != nil {
|
||||||
log.Fatal(err.Error())
|
log.Fatal(err.Error())
|
||||||
} else if err = json.NewDecoder(f).Decode(&config.SessionBus); err != nil {
|
} else {
|
||||||
log.Fatalf("cannot load session bus proxy config from %q: %s", flagDBusConfigSession, err)
|
decodeJSON(log.Fatal, "load session bus proxy config", f, &config.SessionBus)
|
||||||
|
if err = f.Close(); err != nil {
|
||||||
|
log.Fatal(err.Error())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -236,8 +238,11 @@ func buildCommand(ctx context.Context, msg message.Msg, early *earlyHardeningErr
|
|||||||
if flagDBusConfigSystem != "nil" {
|
if flagDBusConfigSystem != "nil" {
|
||||||
if f, err := os.Open(flagDBusConfigSystem); err != nil {
|
if f, err := os.Open(flagDBusConfigSystem); err != nil {
|
||||||
log.Fatal(err.Error())
|
log.Fatal(err.Error())
|
||||||
} else if err = json.NewDecoder(f).Decode(&config.SystemBus); err != nil {
|
} else {
|
||||||
log.Fatalf("cannot load system bus proxy config from %q: %s", flagDBusConfigSystem, err)
|
decodeJSON(log.Fatal, "load system bus proxy config", f, &config.SystemBus)
|
||||||
|
if err = f.Close(); err != nil {
|
||||||
|
log.Fatal(err.Error())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -323,7 +328,7 @@ func buildCommand(ctx context.Context, msg message.Msg, early *earlyHardeningErr
|
|||||||
|
|
||||||
c.Command("version", "Display version information", func(args []string) error { fmt.Println(internal.Version()); return errSuccess })
|
c.Command("version", "Display version information", func(args []string) error { fmt.Println(internal.Version()); return errSuccess })
|
||||||
c.Command("license", "Show full license text", func(args []string) error { fmt.Println(license); return errSuccess })
|
c.Command("license", "Show full license text", func(args []string) error { fmt.Println(license); return errSuccess })
|
||||||
c.Command("template", "Produce a config template", func(args []string) error { printJSON(os.Stdout, false, hst.Template()); return errSuccess })
|
c.Command("template", "Produce a config template", func(args []string) error { encodeJSON(log.Fatal, os.Stdout, false, hst.Template()); return errSuccess })
|
||||||
c.Command("help", "Show this help message", func([]string) error { c.PrintHelp(); return errSuccess })
|
c.Command("help", "Show this help message", func([]string) error { c.PrintHelp(); return errSuccess })
|
||||||
|
|
||||||
return c
|
return c
|
||||||
|
|||||||
60
cmd/hakurei/json.go
Normal file
60
cmd/hakurei/json.go
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"io"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
// decodeJSON decodes json from r and stores it in v. A non-nil error results in a call to fatal.
|
||||||
|
func decodeJSON(fatal func(v ...any), op string, r io.Reader, v any) {
|
||||||
|
err := json.NewDecoder(r).Decode(v)
|
||||||
|
if err == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
syntaxError *json.SyntaxError
|
||||||
|
unmarshalTypeError *json.UnmarshalTypeError
|
||||||
|
|
||||||
|
msg string
|
||||||
|
)
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case errors.As(err, &syntaxError) && syntaxError != nil:
|
||||||
|
msg = syntaxError.Error() +
|
||||||
|
" at byte " + strconv.FormatInt(syntaxError.Offset, 10)
|
||||||
|
|
||||||
|
case errors.As(err, &unmarshalTypeError) && unmarshalTypeError != nil:
|
||||||
|
msg = "inappropriate " + unmarshalTypeError.Value +
|
||||||
|
" at byte " + strconv.FormatInt(unmarshalTypeError.Offset, 10)
|
||||||
|
|
||||||
|
default:
|
||||||
|
// InvalidUnmarshalError: incorrect usage, does not need to be handled
|
||||||
|
// io.ErrUnexpectedEOF: no additional error information available
|
||||||
|
msg = err.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
fatal("cannot " + op + ": " + msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// encodeJSON encodes v to output. A non-nil error results in a call to fatal.
|
||||||
|
func encodeJSON(fatal func(v ...any), output io.Writer, short bool, v any) {
|
||||||
|
encoder := json.NewEncoder(output)
|
||||||
|
if !short {
|
||||||
|
encoder.SetIndent("", " ")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := encoder.Encode(v); err != nil {
|
||||||
|
var marshalerError *json.MarshalerError
|
||||||
|
if errors.As(err, &marshalerError) && marshalerError != nil {
|
||||||
|
// this likely indicates an implementation error in hst
|
||||||
|
fatal("cannot encode json for " + marshalerError.Type.String() + ": " + marshalerError.Err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnsupportedTypeError, UnsupportedValueError: incorrect usage, does not need to be handled
|
||||||
|
fatal("cannot write json: " + err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
107
cmd/hakurei/json_test.go
Normal file
107
cmd/hakurei/json_test.go
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
package main_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
_ "unsafe"
|
||||||
|
|
||||||
|
"hakurei.app/container/stub"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:linkname decodeJSON hakurei.app/cmd/hakurei.decodeJSON
|
||||||
|
func decodeJSON(fatal func(v ...any), op string, r io.Reader, v any)
|
||||||
|
|
||||||
|
func TestDecodeJSON(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
t reflect.Type
|
||||||
|
data string
|
||||||
|
want any
|
||||||
|
msg string
|
||||||
|
}{
|
||||||
|
{"success", reflect.TypeFor[uintptr](), "3735928559\n", uintptr(0xdeadbeef), ""},
|
||||||
|
|
||||||
|
{"syntax", reflect.TypeFor[*int](), "\x00", nil,
|
||||||
|
`cannot load sample: invalid character '\x00' looking for beginning of value at byte 1`},
|
||||||
|
{"type", reflect.TypeFor[uintptr](), "-1", nil,
|
||||||
|
`cannot load sample: inappropriate number -1 at byte 2`},
|
||||||
|
{"default", reflect.TypeFor[*int](), "{", nil,
|
||||||
|
"cannot load sample: unexpected EOF"},
|
||||||
|
}
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
var (
|
||||||
|
gotP = reflect.New(tc.t)
|
||||||
|
gotMsg *string
|
||||||
|
)
|
||||||
|
decodeJSON(func(v ...any) {
|
||||||
|
if gotMsg != nil {
|
||||||
|
t.Fatal("fatal called twice")
|
||||||
|
}
|
||||||
|
msg := v[0].(string)
|
||||||
|
gotMsg = &msg
|
||||||
|
}, "load sample", strings.NewReader(tc.data), gotP.Interface())
|
||||||
|
if tc.msg != "" {
|
||||||
|
if gotMsg == nil {
|
||||||
|
t.Errorf("decodeJSON: success, want fatal %q", tc.msg)
|
||||||
|
} else if *gotMsg != tc.msg {
|
||||||
|
t.Errorf("decodeJSON: fatal = %q, want %q", *gotMsg, tc.msg)
|
||||||
|
}
|
||||||
|
} else if gotMsg != nil {
|
||||||
|
t.Errorf("decodeJSON: fatal = %q", *gotMsg)
|
||||||
|
} else if !reflect.DeepEqual(gotP.Elem().Interface(), tc.want) {
|
||||||
|
t.Errorf("decodeJSON: %#v, want %#v", gotP.Elem().Interface(), tc.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:linkname encodeJSON hakurei.app/cmd/hakurei.encodeJSON
|
||||||
|
func encodeJSON(fatal func(v ...any), output io.Writer, short bool, v any)
|
||||||
|
|
||||||
|
func TestEncodeJSON(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
v any
|
||||||
|
want string
|
||||||
|
}{
|
||||||
|
{"marshaler", errorJSONMarshaler{},
|
||||||
|
`cannot encode json for main_test.errorJSONMarshaler: unique error 3735928559 injected by the test suite`},
|
||||||
|
{"default", func() {},
|
||||||
|
`cannot write json: json: unsupported type: func()`},
|
||||||
|
}
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
var called bool
|
||||||
|
encodeJSON(func(v ...any) {
|
||||||
|
if called {
|
||||||
|
t.Fatal("fatal called twice")
|
||||||
|
}
|
||||||
|
called = true
|
||||||
|
|
||||||
|
if v[0].(string) != tc.want {
|
||||||
|
t.Errorf("encodeJSON: fatal = %q, want %q", v[0].(string), tc.want)
|
||||||
|
}
|
||||||
|
}, nil, false, tc.v)
|
||||||
|
|
||||||
|
if !called {
|
||||||
|
t.Errorf("encodeJSON: success, want fatal %q", tc.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// errorJSONMarshaler implements json.Marshaler.
|
||||||
|
type errorJSONMarshaler struct{}
|
||||||
|
|
||||||
|
func (errorJSONMarshaler) MarshalJSON() ([]byte, error) { return nil, stub.UniqueError(0xdeadbeef) }
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
@@ -17,7 +16,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func tryPath(msg message.Msg, name string) (config *hst.Config) {
|
func tryPath(msg message.Msg, name string) (config *hst.Config) {
|
||||||
var r io.Reader
|
var r io.ReadCloser
|
||||||
config = new(hst.Config)
|
config = new(hst.Config)
|
||||||
|
|
||||||
if name != "-" {
|
if name != "-" {
|
||||||
@@ -26,26 +25,20 @@ func tryPath(msg message.Msg, name string) (config *hst.Config) {
|
|||||||
msg.Verbose("load configuration from file")
|
msg.Verbose("load configuration from file")
|
||||||
|
|
||||||
if f, err := os.Open(name); err != nil {
|
if f, err := os.Open(name); err != nil {
|
||||||
log.Fatalf("cannot access configuration file %q: %s", name, err)
|
log.Fatal(err.Error())
|
||||||
|
return
|
||||||
} else {
|
} else {
|
||||||
// finalizer closes f
|
|
||||||
r = f
|
r = f
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
defer func() {
|
|
||||||
if err := r.(io.ReadCloser).Close(); err != nil {
|
|
||||||
log.Printf("cannot close config fd: %v", err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
r = os.Stdin
|
r = os.Stdin
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := json.NewDecoder(r).Decode(&config); err != nil {
|
decodeJSON(log.Fatal, "load configuration", r, &config)
|
||||||
log.Fatalf("cannot load configuration: %v", err)
|
if err := r.Close(); err != nil {
|
||||||
|
log.Fatal(err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
@@ -12,23 +11,26 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"hakurei.app/hst"
|
"hakurei.app/hst"
|
||||||
|
"hakurei.app/internal"
|
||||||
"hakurei.app/internal/app"
|
"hakurei.app/internal/app"
|
||||||
"hakurei.app/internal/app/state"
|
"hakurei.app/internal/app/state"
|
||||||
"hakurei.app/message"
|
"hakurei.app/message"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// printShowSystem populates and writes a representation of [hst.Info] to output.
|
||||||
func printShowSystem(output io.Writer, short, flagJSON bool) {
|
func printShowSystem(output io.Writer, short, flagJSON bool) {
|
||||||
t := newPrinter(output)
|
t := newPrinter(output)
|
||||||
defer t.MustFlush()
|
defer t.MustFlush()
|
||||||
|
|
||||||
info := &hst.Info{User: new(app.Hsu).MustID(nil)}
|
info := &hst.Info{Version: internal.Version(), User: new(app.Hsu).MustID(nil)}
|
||||||
app.CopyPaths().Copy(&info.Paths, info.User)
|
app.CopyPaths().Copy(&info.Paths, info.User)
|
||||||
|
|
||||||
if flagJSON {
|
if flagJSON {
|
||||||
printJSON(output, short, info)
|
encodeJSON(log.Fatal, output, short, info)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
t.Printf("Version:\t%s\n", info.Version)
|
||||||
t.Printf("User:\t%d\n", info.User)
|
t.Printf("User:\t%d\n", info.User)
|
||||||
t.Printf("TempDir:\t%s\n", info.TempDir)
|
t.Printf("TempDir:\t%s\n", info.TempDir)
|
||||||
t.Printf("SharePath:\t%s\n", info.SharePath)
|
t.Printf("SharePath:\t%s\n", info.SharePath)
|
||||||
@@ -36,6 +38,7 @@ func printShowSystem(output io.Writer, short, flagJSON bool) {
|
|||||||
t.Printf("RunDirPath:\t%s\n", info.RunDirPath)
|
t.Printf("RunDirPath:\t%s\n", info.RunDirPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// printShowInstance writes a representation of [state.State] or [hst.Config] to output.
|
||||||
func printShowInstance(
|
func printShowInstance(
|
||||||
output io.Writer, now time.Time,
|
output io.Writer, now time.Time,
|
||||||
instance *state.State, config *hst.Config,
|
instance *state.State, config *hst.Config,
|
||||||
@@ -44,9 +47,9 @@ func printShowInstance(
|
|||||||
|
|
||||||
if flagJSON {
|
if flagJSON {
|
||||||
if instance != nil {
|
if instance != nil {
|
||||||
printJSON(output, short, instance)
|
encodeJSON(log.Fatal, output, short, instance)
|
||||||
} else {
|
} else {
|
||||||
printJSON(output, short, config)
|
encodeJSON(log.Fatal, output, short, config)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -86,24 +89,19 @@ func printShowInstance(
|
|||||||
if params.Hostname != "" {
|
if params.Hostname != "" {
|
||||||
t.Printf(" Hostname:\t%s\n", params.Hostname)
|
t.Printf(" Hostname:\t%s\n", params.Hostname)
|
||||||
}
|
}
|
||||||
flags := make([]string, 0, 7)
|
flags := params.Flags.String()
|
||||||
writeFlag := func(name string, flag uintptr, force bool) {
|
|
||||||
if params.Flags&flag != 0 || force {
|
// this is included in the upper hst.Config struct but is relevant here
|
||||||
flags = append(flags, name)
|
const flagDirectWayland = "directwl"
|
||||||
|
if config.DirectWayland {
|
||||||
|
// hardcoded value when every flag is unset
|
||||||
|
if flags == "none" {
|
||||||
|
flags = flagDirectWayland
|
||||||
|
} else {
|
||||||
|
flags += ", " + flagDirectWayland
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
writeFlag("userns", hst.FUserns, false)
|
t.Printf(" Flags:\t%s\n", flags)
|
||||||
writeFlag("devel", hst.FDevel, false)
|
|
||||||
writeFlag("net", hst.FHostNet, false)
|
|
||||||
writeFlag("abstract", hst.FHostAbstract, false)
|
|
||||||
writeFlag("device", hst.FDevice, false)
|
|
||||||
writeFlag("tty", hst.FTty, false)
|
|
||||||
writeFlag("mapuid", hst.FMapRealUID, false)
|
|
||||||
writeFlag("directwl", 0, config.DirectWayland)
|
|
||||||
if len(flags) == 0 {
|
|
||||||
flags = append(flags, "none")
|
|
||||||
}
|
|
||||||
t.Printf(" Flags:\t%s\n", strings.Join(flags, " "))
|
|
||||||
|
|
||||||
if params.Path != nil {
|
if params.Path != nil {
|
||||||
t.Printf(" Path:\t%s\n", params.Path)
|
t.Printf(" Path:\t%s\n", params.Path)
|
||||||
@@ -168,6 +166,7 @@ func printShowInstance(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// printPs writes a representation of active instances to output.
|
||||||
func printPs(output io.Writer, now time.Time, s state.Store, short, flagJSON bool) {
|
func printPs(output io.Writer, now time.Time, s state.Store, short, flagJSON bool) {
|
||||||
var entries state.Entries
|
var entries state.Entries
|
||||||
if e, err := state.Join(s); err != nil {
|
if e, err := state.Join(s); err != nil {
|
||||||
@@ -184,7 +183,7 @@ func printPs(output io.Writer, now time.Time, s state.Store, short, flagJSON boo
|
|||||||
for id, instance := range entries {
|
for id, instance := range entries {
|
||||||
es[id.String()] = instance
|
es[id.String()] = instance
|
||||||
}
|
}
|
||||||
printJSON(output, short, es)
|
encodeJSON(log.Fatal, output, short, es)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -213,7 +212,7 @@ func printPs(output io.Writer, now time.Time, s state.Store, short, flagJSON boo
|
|||||||
for i, e := range exp {
|
for i, e := range exp {
|
||||||
v[i] = e.s
|
v[i] = e.s
|
||||||
}
|
}
|
||||||
printJSON(output, short, v)
|
encodeJSON(log.Fatal, output, short, v)
|
||||||
} else {
|
} else {
|
||||||
for _, e := range exp {
|
for _, e := range exp {
|
||||||
mustPrintln(output, e.s[:8])
|
mustPrintln(output, e.s[:8])
|
||||||
@@ -247,40 +246,39 @@ func printPs(output io.Writer, now time.Time, s state.Store, short, flagJSON boo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// expandedStateEntry stores [state.State] alongside a string representation of its [state.ID].
|
||||||
type expandedStateEntry struct {
|
type expandedStateEntry struct {
|
||||||
s string
|
s string
|
||||||
*state.State
|
*state.State
|
||||||
}
|
}
|
||||||
|
|
||||||
func printJSON(output io.Writer, short bool, v any) {
|
// newPrinter returns a configured, wrapped [tabwriter.Writer].
|
||||||
encoder := json.NewEncoder(output)
|
|
||||||
if !short {
|
|
||||||
encoder.SetIndent("", " ")
|
|
||||||
}
|
|
||||||
if err := encoder.Encode(v); err != nil {
|
|
||||||
log.Fatalf("cannot serialise: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func newPrinter(output io.Writer) *tp { return &tp{tabwriter.NewWriter(output, 0, 1, 4, ' ', 0)} }
|
func newPrinter(output io.Writer) *tp { return &tp{tabwriter.NewWriter(output, 0, 1, 4, ' ', 0)} }
|
||||||
|
|
||||||
|
// tp wraps [tabwriter.Writer] to provide additional formatting methods.
|
||||||
type tp struct{ *tabwriter.Writer }
|
type tp struct{ *tabwriter.Writer }
|
||||||
|
|
||||||
|
// Printf calls [fmt.Fprintf] on the underlying [tabwriter.Writer].
|
||||||
func (p *tp) Printf(format string, a ...any) {
|
func (p *tp) Printf(format string, a ...any) {
|
||||||
if _, err := fmt.Fprintf(p, format, a...); err != nil {
|
if _, err := fmt.Fprintf(p, format, a...); err != nil {
|
||||||
log.Fatalf("cannot write to tabwriter: %v", err)
|
log.Fatalf("cannot write to tabwriter: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Println calls [fmt.Fprintln] on the underlying [tabwriter.Writer].
|
||||||
func (p *tp) Println(a ...any) {
|
func (p *tp) Println(a ...any) {
|
||||||
if _, err := fmt.Fprintln(p, a...); err != nil {
|
if _, err := fmt.Fprintln(p, a...); err != nil {
|
||||||
log.Fatalf("cannot write to tabwriter: %v", err)
|
log.Fatalf("cannot write to tabwriter: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MustFlush calls the Flush method of [tabwriter.Writer] and calls [log.Fatalf] on a non-nil error.
|
||||||
func (p *tp) MustFlush() {
|
func (p *tp) MustFlush() {
|
||||||
if err := p.Writer.Flush(); err != nil {
|
if err := p.Writer.Flush(); err != nil {
|
||||||
log.Fatalf("cannot flush tabwriter: %v", err)
|
log.Fatalf("cannot flush tabwriter: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func mustPrint(output io.Writer, a ...any) {
|
func mustPrint(output io.Writer, a ...any) {
|
||||||
if _, err := fmt.Fprint(output, a...); err != nil {
|
if _, err := fmt.Fprint(output, a...); err != nil {
|
||||||
log.Fatalf("cannot print: %v", err)
|
log.Fatalf("cannot print: %v", err)
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ func TestPrintShowInstance(t *testing.T) {
|
|||||||
Groups: video, dialout, plugdev
|
Groups: video, dialout, plugdev
|
||||||
Home: /data/data/org.chromium.Chromium
|
Home: /data/data/org.chromium.Chromium
|
||||||
Hostname: localhost
|
Hostname: localhost
|
||||||
Flags: userns devel net abstract device tty mapuid
|
Flags: multiarch, compat, devel, userns, net, abstract, tty, mapuid, device, runtime, tmpdir
|
||||||
Path: /run/current-system/sw/bin/chromium
|
Path: /run/current-system/sw/bin/chromium
|
||||||
Arguments: chromium --ignore-gpu-blocklist --disable-smooth-scrolling --enable-features=UseOzonePlatform --ozone-platform=wayland
|
Arguments: chromium --ignore-gpu-blocklist --disable-smooth-scrolling --enable-features=UseOzonePlatform --ozone-platform=wayland
|
||||||
|
|
||||||
@@ -87,6 +87,22 @@ App
|
|||||||
Enablements: (no enablements)
|
Enablements: (no enablements)
|
||||||
Flags: none
|
Flags: none
|
||||||
|
|
||||||
|
`, false},
|
||||||
|
{"config flag none directwl", nil, &hst.Config{DirectWayland: true, Container: new(hst.ContainerConfig)}, false, false, `Error: container configuration missing path to home directory!
|
||||||
|
|
||||||
|
App
|
||||||
|
Identity: 0
|
||||||
|
Enablements: (no enablements)
|
||||||
|
Flags: directwl
|
||||||
|
|
||||||
|
`, false},
|
||||||
|
{"config flag directwl", nil, &hst.Config{DirectWayland: true, Container: &hst.ContainerConfig{Flags: hst.FMultiarch}}, false, false, `Error: container configuration missing path to home directory!
|
||||||
|
|
||||||
|
App
|
||||||
|
Identity: 0
|
||||||
|
Enablements: (no enablements)
|
||||||
|
Flags: multiarch, directwl
|
||||||
|
|
||||||
`, false},
|
`, false},
|
||||||
{"config nil entries", nil, &hst.Config{Container: &hst.ContainerConfig{Filesystem: make([]hst.FilesystemConfigJSON, 1)}, ExtraPerms: make([]hst.ExtraPermConfig, 1)}, false, false, `Error: container configuration missing path to home directory!
|
{"config nil entries", nil, &hst.Config{Container: &hst.ContainerConfig{Filesystem: make([]hst.FilesystemConfigJSON, 1)}, ExtraPerms: make([]hst.ExtraPermConfig, 1)}, false, false, `Error: container configuration missing path to home directory!
|
||||||
|
|
||||||
@@ -124,7 +140,7 @@ App
|
|||||||
Groups: video, dialout, plugdev
|
Groups: video, dialout, plugdev
|
||||||
Home: /data/data/org.chromium.Chromium
|
Home: /data/data/org.chromium.Chromium
|
||||||
Hostname: localhost
|
Hostname: localhost
|
||||||
Flags: userns devel net abstract device tty mapuid
|
Flags: multiarch, compat, devel, userns, net, abstract, tty, mapuid, device, runtime, tmpdir
|
||||||
Path: /run/current-system/sw/bin/chromium
|
Path: /run/current-system/sw/bin/chromium
|
||||||
Arguments: chromium --ignore-gpu-blocklist --disable-smooth-scrolling --enable-features=UseOzonePlatform --ozone-platform=wayland
|
Arguments: chromium --ignore-gpu-blocklist --disable-smooth-scrolling --enable-features=UseOzonePlatform --ozone-platform=wayland
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import (
|
|||||||
"hakurei.app/message"
|
"hakurei.app/message"
|
||||||
)
|
)
|
||||||
|
|
||||||
var hakureiPath = internal.MustHakureiPath()
|
var hakureiPathVal = internal.MustHakureiPath().String()
|
||||||
|
|
||||||
func mustRunApp(ctx context.Context, msg message.Msg, config *hst.Config, beforeFail func()) {
|
func mustRunApp(ctx context.Context, msg message.Msg, config *hst.Config, beforeFail func()) {
|
||||||
var (
|
var (
|
||||||
@@ -27,9 +27,9 @@ func mustRunApp(ctx context.Context, msg message.Msg, config *hst.Config, before
|
|||||||
log.Fatalf("cannot pipe: %v", err)
|
log.Fatalf("cannot pipe: %v", err)
|
||||||
} else {
|
} else {
|
||||||
if msg.IsVerbose() {
|
if msg.IsVerbose() {
|
||||||
cmd = exec.CommandContext(ctx, hakureiPath.String(), "-v", "app", "3")
|
cmd = exec.CommandContext(ctx, hakureiPathVal, "-v", "app", "3")
|
||||||
} else {
|
} else {
|
||||||
cmd = exec.CommandContext(ctx, hakureiPath.String(), "app", "3")
|
cmd = exec.CommandContext(ctx, hakureiPathVal, "app", "3")
|
||||||
}
|
}
|
||||||
cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
|
cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
|
||||||
cmd.ExtraFiles = []*os.File{r}
|
cmd.ExtraFiles = []*os.File{r}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
"runtime"
|
||||||
"slices"
|
"slices"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -26,7 +27,14 @@ const (
|
|||||||
identityMax = 9999
|
identityMax = 9999
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// hakureiPath is the absolute path to Hakurei.
|
||||||
|
//
|
||||||
|
// This is set by the linker.
|
||||||
|
var hakureiPath string
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
runtime.LockOSThread()
|
||||||
|
|
||||||
log.SetFlags(0)
|
log.SetFlags(0)
|
||||||
log.SetPrefix("hsu: ")
|
log.SetPrefix("hsu: ")
|
||||||
log.SetOutput(os.Stderr)
|
log.SetOutput(os.Stderr)
|
||||||
@@ -43,13 +51,18 @@ func main() {
|
|||||||
log.Fatal("this program must not be started by root")
|
log.Fatal("this program must not be started by root")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !path.IsAbs(hakureiPath) {
|
||||||
|
log.Fatal("this program is compiled incorrectly")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
var toolPath string
|
var toolPath string
|
||||||
pexe := path.Join("/proc", strconv.Itoa(os.Getppid()), "exe")
|
pexe := path.Join("/proc", strconv.Itoa(os.Getppid()), "exe")
|
||||||
if p, err := os.Readlink(pexe); err != nil {
|
if p, err := os.Readlink(pexe); err != nil {
|
||||||
log.Fatalf("cannot read parent executable path: %v", err)
|
log.Fatalf("cannot read parent executable path: %v", err)
|
||||||
} else if strings.HasSuffix(p, " (deleted)") {
|
} else if strings.HasSuffix(p, " (deleted)") {
|
||||||
log.Fatal("hakurei executable has been deleted")
|
log.Fatal("hakurei executable has been deleted")
|
||||||
} else if p != mustCheckPath(hmain) {
|
} else if p != hakureiPath {
|
||||||
log.Fatal("this program must be started by hakurei")
|
log.Fatal("this program must be started by hakurei")
|
||||||
} else {
|
} else {
|
||||||
toolPath = p
|
toolPath = p
|
||||||
|
|||||||
@@ -19,5 +19,5 @@ buildGoModule {
|
|||||||
ldflags = lib.attrsets.foldlAttrs (
|
ldflags = lib.attrsets.foldlAttrs (
|
||||||
ldflags: name: value:
|
ldflags: name: value:
|
||||||
ldflags ++ [ "-X main.${name}=${value}" ]
|
ldflags ++ [ "-X main.${name}=${value}" ]
|
||||||
) [ "-s -w" ] { hmain = "${hakurei}/libexec/hakurei"; };
|
) [ "-s -w" ] { hakureiPath = "${hakurei}/libexec/hakurei"; };
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ func TestParseUint32Fast(t *testing.T) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("full range", func(t *testing.T) {
|
t.Run("range", func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
testRange := func(i, end int) {
|
testRange := func(i, end int) {
|
||||||
@@ -61,11 +61,9 @@ func TestParseUint32Fast(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
testRange(0, 5000)
|
testRange(0, 2500)
|
||||||
testRange(105000, 110000)
|
testRange(23002500, 23005000)
|
||||||
testRange(23005000, 23010000)
|
testRange(7890002500, 7890005000)
|
||||||
testRange(456005000, 456010000)
|
|
||||||
testRange(7890005000, 7890010000)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"log"
|
|
||||||
"path"
|
|
||||||
)
|
|
||||||
|
|
||||||
const compPoison = "INVALIDINVALIDINVALIDINVALIDINVALID"
|
|
||||||
|
|
||||||
var (
|
|
||||||
hmain = compPoison
|
|
||||||
)
|
|
||||||
|
|
||||||
func mustCheckPath(p string) string {
|
|
||||||
if p != compPoison && p != "" && path.IsAbs(p) {
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
log.Fatal("this program is compiled incorrectly")
|
|
||||||
return compPoison
|
|
||||||
}
|
|
||||||
@@ -5,8 +5,8 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"hakurei.app/container/bits"
|
|
||||||
"hakurei.app/container/check"
|
"hakurei.app/container/check"
|
||||||
|
"hakurei.app/container/comp"
|
||||||
"hakurei.app/container/stub"
|
"hakurei.app/container/stub"
|
||||||
"hakurei.app/message"
|
"hakurei.app/message"
|
||||||
)
|
)
|
||||||
@@ -23,14 +23,14 @@ func TestAutoRootOp(t *testing.T) {
|
|||||||
checkOpBehaviour(t, []opBehaviourTestCase{
|
checkOpBehaviour(t, []opBehaviourTestCase{
|
||||||
{"readdir", &Params{ParentPerm: 0750}, &AutoRootOp{
|
{"readdir", &Params{ParentPerm: 0750}, &AutoRootOp{
|
||||||
Host: check.MustAbs("/"),
|
Host: check.MustAbs("/"),
|
||||||
Flags: bits.BindWritable,
|
Flags: comp.BindWritable,
|
||||||
}, []stub.Call{
|
}, []stub.Call{
|
||||||
call("readdir", stub.ExpectArgs{"/"}, stubDir(), stub.UniqueError(2)),
|
call("readdir", stub.ExpectArgs{"/"}, stubDir(), stub.UniqueError(2)),
|
||||||
}, stub.UniqueError(2), nil, nil},
|
}, stub.UniqueError(2), nil, nil},
|
||||||
|
|
||||||
{"early", &Params{ParentPerm: 0750}, &AutoRootOp{
|
{"early", &Params{ParentPerm: 0750}, &AutoRootOp{
|
||||||
Host: check.MustAbs("/"),
|
Host: check.MustAbs("/"),
|
||||||
Flags: bits.BindWritable,
|
Flags: comp.BindWritable,
|
||||||
}, []stub.Call{
|
}, []stub.Call{
|
||||||
call("readdir", stub.ExpectArgs{"/"}, stubDir("bin", "dev", "etc", "home", "lib64",
|
call("readdir", stub.ExpectArgs{"/"}, stubDir("bin", "dev", "etc", "home", "lib64",
|
||||||
"lost+found", "mnt", "nix", "proc", "root", "run", "srv", "sys", "tmp", "usr", "var"), nil),
|
"lost+found", "mnt", "nix", "proc", "root", "run", "srv", "sys", "tmp", "usr", "var"), nil),
|
||||||
@@ -39,7 +39,7 @@ func TestAutoRootOp(t *testing.T) {
|
|||||||
|
|
||||||
{"apply", &Params{ParentPerm: 0750}, &AutoRootOp{
|
{"apply", &Params{ParentPerm: 0750}, &AutoRootOp{
|
||||||
Host: check.MustAbs("/"),
|
Host: check.MustAbs("/"),
|
||||||
Flags: bits.BindWritable,
|
Flags: comp.BindWritable,
|
||||||
}, []stub.Call{
|
}, []stub.Call{
|
||||||
call("readdir", stub.ExpectArgs{"/"}, stubDir("bin", "dev", "etc", "home", "lib64",
|
call("readdir", stub.ExpectArgs{"/"}, stubDir("bin", "dev", "etc", "home", "lib64",
|
||||||
"lost+found", "mnt", "nix", "proc", "root", "run", "srv", "sys", "tmp", "usr", "var"), nil),
|
"lost+found", "mnt", "nix", "proc", "root", "run", "srv", "sys", "tmp", "usr", "var"), nil),
|
||||||
@@ -60,7 +60,7 @@ func TestAutoRootOp(t *testing.T) {
|
|||||||
|
|
||||||
{"success pd", &Params{ParentPerm: 0750}, &AutoRootOp{
|
{"success pd", &Params{ParentPerm: 0750}, &AutoRootOp{
|
||||||
Host: check.MustAbs("/"),
|
Host: check.MustAbs("/"),
|
||||||
Flags: bits.BindWritable,
|
Flags: comp.BindWritable,
|
||||||
}, []stub.Call{
|
}, []stub.Call{
|
||||||
call("readdir", stub.ExpectArgs{"/"}, stubDir("bin", "dev", "etc", "home", "lib64",
|
call("readdir", stub.ExpectArgs{"/"}, stubDir("bin", "dev", "etc", "home", "lib64",
|
||||||
"lost+found", "mnt", "nix", "proc", "root", "run", "srv", "sys", "tmp", "usr", "var"), nil),
|
"lost+found", "mnt", "nix", "proc", "root", "run", "srv", "sys", "tmp", "usr", "var"), nil),
|
||||||
@@ -127,10 +127,10 @@ func TestAutoRootOp(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
checkOpsBuilder(t, []opsBuilderTestCase{
|
checkOpsBuilder(t, []opsBuilderTestCase{
|
||||||
{"pd", new(Ops).Root(check.MustAbs("/"), bits.BindWritable), Ops{
|
{"pd", new(Ops).Root(check.MustAbs("/"), comp.BindWritable), Ops{
|
||||||
&AutoRootOp{
|
&AutoRootOp{
|
||||||
Host: check.MustAbs("/"),
|
Host: check.MustAbs("/"),
|
||||||
Flags: bits.BindWritable,
|
Flags: comp.BindWritable,
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
})
|
})
|
||||||
@@ -140,42 +140,42 @@ func TestAutoRootOp(t *testing.T) {
|
|||||||
|
|
||||||
{"internal ne", &AutoRootOp{
|
{"internal ne", &AutoRootOp{
|
||||||
Host: check.MustAbs("/"),
|
Host: check.MustAbs("/"),
|
||||||
Flags: bits.BindWritable,
|
Flags: comp.BindWritable,
|
||||||
}, &AutoRootOp{
|
}, &AutoRootOp{
|
||||||
Host: check.MustAbs("/"),
|
Host: check.MustAbs("/"),
|
||||||
Flags: bits.BindWritable,
|
Flags: comp.BindWritable,
|
||||||
resolved: []*BindMountOp{new(BindMountOp)},
|
resolved: []*BindMountOp{new(BindMountOp)},
|
||||||
}, true},
|
}, true},
|
||||||
|
|
||||||
{"flags differs", &AutoRootOp{
|
{"flags differs", &AutoRootOp{
|
||||||
Host: check.MustAbs("/"),
|
Host: check.MustAbs("/"),
|
||||||
Flags: bits.BindWritable | bits.BindDevice,
|
Flags: comp.BindWritable | comp.BindDevice,
|
||||||
}, &AutoRootOp{
|
}, &AutoRootOp{
|
||||||
Host: check.MustAbs("/"),
|
Host: check.MustAbs("/"),
|
||||||
Flags: bits.BindWritable,
|
Flags: comp.BindWritable,
|
||||||
}, false},
|
}, false},
|
||||||
|
|
||||||
{"host differs", &AutoRootOp{
|
{"host differs", &AutoRootOp{
|
||||||
Host: check.MustAbs("/tmp/"),
|
Host: check.MustAbs("/tmp/"),
|
||||||
Flags: bits.BindWritable,
|
Flags: comp.BindWritable,
|
||||||
}, &AutoRootOp{
|
}, &AutoRootOp{
|
||||||
Host: check.MustAbs("/"),
|
Host: check.MustAbs("/"),
|
||||||
Flags: bits.BindWritable,
|
Flags: comp.BindWritable,
|
||||||
}, false},
|
}, false},
|
||||||
|
|
||||||
{"equals", &AutoRootOp{
|
{"equals", &AutoRootOp{
|
||||||
Host: check.MustAbs("/"),
|
Host: check.MustAbs("/"),
|
||||||
Flags: bits.BindWritable,
|
Flags: comp.BindWritable,
|
||||||
}, &AutoRootOp{
|
}, &AutoRootOp{
|
||||||
Host: check.MustAbs("/"),
|
Host: check.MustAbs("/"),
|
||||||
Flags: bits.BindWritable,
|
Flags: comp.BindWritable,
|
||||||
}, true},
|
}, true},
|
||||||
})
|
})
|
||||||
|
|
||||||
checkOpMeta(t, []opMetaTestCase{
|
checkOpMeta(t, []opMetaTestCase{
|
||||||
{"root", &AutoRootOp{
|
{"root", &AutoRootOp{
|
||||||
Host: check.MustAbs("/"),
|
Host: check.MustAbs("/"),
|
||||||
Flags: bits.BindWritable,
|
Flags: comp.BindWritable,
|
||||||
}, "setting up", `auto root "/" flags 0x2`},
|
}, "setting up", `auto root "/" flags 0x2`},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
// Package bits contains constants for configuring the container.
|
|
||||||
package bits
|
|
||||||
|
|
||||||
const (
|
|
||||||
// BindOptional skips nonexistent host paths.
|
|
||||||
BindOptional = 1 << iota
|
|
||||||
// BindWritable mounts filesystem read-write.
|
|
||||||
BindWritable
|
|
||||||
// BindDevice allows access to devices (special files) on this filesystem.
|
|
||||||
BindDevice
|
|
||||||
// BindEnsure attempts to create the host path if it does not exist.
|
|
||||||
BindEnsure
|
|
||||||
)
|
|
||||||
@@ -49,41 +49,10 @@ func capset(hdrp *capHeader, datap *[2]capData) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// capBoundingSetDrop drops a capability from the calling thread's capability bounding set.
|
// capBoundingSetDrop drops a capability from the calling thread's capability bounding set.
|
||||||
func capBoundingSetDrop(cap uintptr) error {
|
func capBoundingSetDrop(cap uintptr) error { return Prctl(syscall.PR_CAPBSET_DROP, cap, 0) }
|
||||||
r, _, errno := syscall.Syscall(
|
|
||||||
syscall.SYS_PRCTL,
|
|
||||||
syscall.PR_CAPBSET_DROP,
|
|
||||||
cap, 0,
|
|
||||||
)
|
|
||||||
if r != 0 {
|
|
||||||
return errno
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// capAmbientClearAll clears the ambient capability set of the calling thread.
|
// capAmbientClearAll clears the ambient capability set of the calling thread.
|
||||||
func capAmbientClearAll() error {
|
func capAmbientClearAll() error { return Prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL, 0) }
|
||||||
r, _, errno := syscall.Syscall(
|
|
||||||
syscall.SYS_PRCTL,
|
|
||||||
PR_CAP_AMBIENT,
|
|
||||||
PR_CAP_AMBIENT_CLEAR_ALL, 0,
|
|
||||||
)
|
|
||||||
if r != 0 {
|
|
||||||
return errno
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// capAmbientRaise adds to the ambient capability set of the calling thread.
|
// capAmbientRaise adds to the ambient capability set of the calling thread.
|
||||||
func capAmbientRaise(cap uintptr) error {
|
func capAmbientRaise(cap uintptr) error { return Prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, cap) }
|
||||||
r, _, errno := syscall.Syscall(
|
|
||||||
syscall.SYS_PRCTL,
|
|
||||||
PR_CAP_AMBIENT,
|
|
||||||
PR_CAP_AMBIENT_RAISE,
|
|
||||||
cap,
|
|
||||||
)
|
|
||||||
if r != 0 {
|
|
||||||
return errno
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,4 +1,16 @@
|
|||||||
package bits
|
// Package comp contains constants from container packages without depending on cgo.
|
||||||
|
package comp
|
||||||
|
|
||||||
|
const (
|
||||||
|
// BindOptional skips nonexistent host paths.
|
||||||
|
BindOptional = 1 << iota
|
||||||
|
// BindWritable mounts filesystem read-write.
|
||||||
|
BindWritable
|
||||||
|
// BindDevice allows access to devices (special files) on this filesystem.
|
||||||
|
BindDevice
|
||||||
|
// BindEnsure attempts to create the host path if it does not exist.
|
||||||
|
BindEnsure
|
||||||
|
)
|
||||||
|
|
||||||
// FilterPreset specifies parts of the syscall filter preset to enable.
|
// FilterPreset specifies parts of the syscall filter preset to enable.
|
||||||
type FilterPreset int
|
type FilterPreset int
|
||||||
@@ -14,8 +14,8 @@ import (
|
|||||||
. "syscall"
|
. "syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"hakurei.app/container/bits"
|
|
||||||
"hakurei.app/container/check"
|
"hakurei.app/container/check"
|
||||||
|
"hakurei.app/container/comp"
|
||||||
"hakurei.app/container/fhs"
|
"hakurei.app/container/fhs"
|
||||||
"hakurei.app/container/seccomp"
|
"hakurei.app/container/seccomp"
|
||||||
"hakurei.app/message"
|
"hakurei.app/message"
|
||||||
@@ -86,7 +86,7 @@ type (
|
|||||||
// Extra seccomp flags.
|
// Extra seccomp flags.
|
||||||
SeccompFlags seccomp.ExportFlag
|
SeccompFlags seccomp.ExportFlag
|
||||||
// Seccomp presets. Has no effect unless SeccompRules is zero-length.
|
// Seccomp presets. Has no effect unless SeccompRules is zero-length.
|
||||||
SeccompPresets bits.FilterPreset
|
SeccompPresets comp.FilterPreset
|
||||||
// Do not load seccomp program.
|
// Do not load seccomp program.
|
||||||
SeccompDisable bool
|
SeccompDisable bool
|
||||||
|
|
||||||
@@ -174,7 +174,7 @@ func (p *Container) Start() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !p.RetainSession {
|
if !p.RetainSession {
|
||||||
p.SeccompPresets |= bits.PresetDenyTTY
|
p.SeccompPresets |= comp.PresetDenyTTY
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.AdoptWaitDelay == 0 {
|
if p.AdoptWaitDelay == 0 {
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ import (
|
|||||||
|
|
||||||
"hakurei.app/command"
|
"hakurei.app/command"
|
||||||
"hakurei.app/container"
|
"hakurei.app/container"
|
||||||
"hakurei.app/container/bits"
|
|
||||||
"hakurei.app/container/check"
|
"hakurei.app/container/check"
|
||||||
|
"hakurei.app/container/comp"
|
||||||
"hakurei.app/container/seccomp"
|
"hakurei.app/container/seccomp"
|
||||||
"hakurei.app/container/vfs"
|
"hakurei.app/container/vfs"
|
||||||
"hakurei.app/hst"
|
"hakurei.app/hst"
|
||||||
@@ -206,20 +206,20 @@ var containerTestCases = []struct {
|
|||||||
|
|
||||||
rules []seccomp.NativeRule
|
rules []seccomp.NativeRule
|
||||||
flags seccomp.ExportFlag
|
flags seccomp.ExportFlag
|
||||||
presets bits.FilterPreset
|
presets comp.FilterPreset
|
||||||
}{
|
}{
|
||||||
{"minimal", true, false, false, true,
|
{"minimal", true, false, false, true,
|
||||||
emptyOps, emptyMnt,
|
emptyOps, emptyMnt,
|
||||||
1000, 100, nil, 0, bits.PresetStrict},
|
1000, 100, nil, 0, comp.PresetStrict},
|
||||||
{"allow", true, true, true, false,
|
{"allow", true, true, true, false,
|
||||||
emptyOps, emptyMnt,
|
emptyOps, emptyMnt,
|
||||||
1000, 100, nil, 0, bits.PresetExt | bits.PresetDenyDevel},
|
1000, 100, nil, 0, comp.PresetExt | comp.PresetDenyDevel},
|
||||||
{"no filter", false, true, true, true,
|
{"no filter", false, true, true, true,
|
||||||
emptyOps, emptyMnt,
|
emptyOps, emptyMnt,
|
||||||
1000, 100, nil, 0, bits.PresetExt},
|
1000, 100, nil, 0, comp.PresetExt},
|
||||||
{"custom rules", true, true, true, false,
|
{"custom rules", true, true, true, false,
|
||||||
emptyOps, emptyMnt,
|
emptyOps, emptyMnt,
|
||||||
1, 31, []seccomp.NativeRule{{Syscall: seccomp.ScmpSyscall(syscall.SYS_SETUID), Errno: seccomp.ScmpErrno(syscall.EPERM)}}, 0, bits.PresetExt},
|
1, 31, []seccomp.NativeRule{{Syscall: seccomp.ScmpSyscall(syscall.SYS_SETUID), Errno: seccomp.ScmpErrno(syscall.EPERM)}}, 0, comp.PresetExt},
|
||||||
|
|
||||||
{"tmpfs", true, false, false, true,
|
{"tmpfs", true, false, false, true,
|
||||||
earlyOps(new(container.Ops).
|
earlyOps(new(container.Ops).
|
||||||
@@ -228,7 +228,7 @@ var containerTestCases = []struct {
|
|||||||
earlyMnt(
|
earlyMnt(
|
||||||
ent("/", hst.PrivateTmp, "rw,nosuid,nodev,relatime", "tmpfs", "ephemeral", ignore),
|
ent("/", hst.PrivateTmp, "rw,nosuid,nodev,relatime", "tmpfs", "ephemeral", ignore),
|
||||||
),
|
),
|
||||||
9, 9, nil, 0, bits.PresetStrict},
|
9, 9, nil, 0, comp.PresetStrict},
|
||||||
|
|
||||||
{"dev", true, true /* go test output is not a tty */, false, false,
|
{"dev", true, true /* go test output is not a tty */, false, false,
|
||||||
earlyOps(new(container.Ops).
|
earlyOps(new(container.Ops).
|
||||||
@@ -246,7 +246,7 @@ var containerTestCases = []struct {
|
|||||||
ent("/", "/dev/mqueue", "rw,nosuid,nodev,noexec,relatime", "mqueue", "mqueue", "rw"),
|
ent("/", "/dev/mqueue", "rw,nosuid,nodev,noexec,relatime", "mqueue", "mqueue", "rw"),
|
||||||
ent("/", "/dev/shm", "rw,nosuid,nodev,relatime", "tmpfs", "tmpfs", ignore),
|
ent("/", "/dev/shm", "rw,nosuid,nodev,relatime", "tmpfs", "tmpfs", ignore),
|
||||||
),
|
),
|
||||||
1971, 100, nil, 0, bits.PresetStrict},
|
1971, 100, nil, 0, comp.PresetStrict},
|
||||||
|
|
||||||
{"dev no mqueue", true, true /* go test output is not a tty */, false, false,
|
{"dev no mqueue", true, true /* go test output is not a tty */, false, false,
|
||||||
earlyOps(new(container.Ops).
|
earlyOps(new(container.Ops).
|
||||||
@@ -263,7 +263,7 @@ var containerTestCases = []struct {
|
|||||||
ent("/", "/dev/pts", "rw,nosuid,noexec,relatime", "devpts", "devpts", "rw,mode=620,ptmxmode=666"),
|
ent("/", "/dev/pts", "rw,nosuid,noexec,relatime", "devpts", "devpts", "rw,mode=620,ptmxmode=666"),
|
||||||
ent("/", "/dev/shm", "rw,nosuid,nodev,relatime", "tmpfs", "tmpfs", ignore),
|
ent("/", "/dev/shm", "rw,nosuid,nodev,relatime", "tmpfs", "tmpfs", ignore),
|
||||||
),
|
),
|
||||||
1971, 100, nil, 0, bits.PresetStrict},
|
1971, 100, nil, 0, comp.PresetStrict},
|
||||||
|
|
||||||
{"overlay", true, false, false, true,
|
{"overlay", true, false, false, true,
|
||||||
func(t *testing.T) (*container.Ops, context.Context) {
|
func(t *testing.T) (*container.Ops, context.Context) {
|
||||||
@@ -300,7 +300,7 @@ var containerTestCases = []struct {
|
|||||||
",redirect_dir=nofollow,uuid=on,userxattr"),
|
",redirect_dir=nofollow,uuid=on,userxattr"),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
1 << 3, 1 << 14, nil, 0, bits.PresetStrict},
|
1 << 3, 1 << 14, nil, 0, comp.PresetStrict},
|
||||||
|
|
||||||
{"overlay ephemeral", true, false, false, true,
|
{"overlay ephemeral", true, false, false, true,
|
||||||
func(t *testing.T) (*container.Ops, context.Context) {
|
func(t *testing.T) (*container.Ops, context.Context) {
|
||||||
@@ -324,7 +324,7 @@ var containerTestCases = []struct {
|
|||||||
ent("/", hst.PrivateTmp, "rw", "overlay", "overlay", ignore),
|
ent("/", hst.PrivateTmp, "rw", "overlay", "overlay", ignore),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
1 << 3, 1 << 14, nil, 0, bits.PresetStrict},
|
1 << 3, 1 << 14, nil, 0, comp.PresetStrict},
|
||||||
|
|
||||||
{"overlay readonly", true, false, false, true,
|
{"overlay readonly", true, false, false, true,
|
||||||
func(t *testing.T) (*container.Ops, context.Context) {
|
func(t *testing.T) (*container.Ops, context.Context) {
|
||||||
@@ -352,7 +352,7 @@ var containerTestCases = []struct {
|
|||||||
",redirect_dir=nofollow,userxattr"),
|
",redirect_dir=nofollow,userxattr"),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
1 << 3, 1 << 14, nil, 0, bits.PresetStrict},
|
1 << 3, 1 << 14, nil, 0, comp.PresetStrict},
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestContainer(t *testing.T) {
|
func TestContainer(t *testing.T) {
|
||||||
@@ -560,9 +560,9 @@ func TestContainerString(t *testing.T) {
|
|||||||
c := container.NewCommand(t.Context(), msg, check.MustAbs("/run/current-system/sw/bin/ldd"), "ldd", "/usr/bin/env")
|
c := container.NewCommand(t.Context(), msg, check.MustAbs("/run/current-system/sw/bin/ldd"), "ldd", "/usr/bin/env")
|
||||||
c.SeccompFlags |= seccomp.AllowMultiarch
|
c.SeccompFlags |= seccomp.AllowMultiarch
|
||||||
c.SeccompRules = seccomp.Preset(
|
c.SeccompRules = seccomp.Preset(
|
||||||
bits.PresetExt|bits.PresetDenyNS|bits.PresetDenyTTY,
|
comp.PresetExt|comp.PresetDenyNS|comp.PresetDenyTTY,
|
||||||
c.SeccompFlags)
|
c.SeccompFlags)
|
||||||
c.SeccompPresets = bits.PresetStrict
|
c.SeccompPresets = comp.PresetStrict
|
||||||
want := `argv: ["ldd" "/usr/bin/env"], filter: true, rules: 65, flags: 0x1, presets: 0xf`
|
want := `argv: ["ldd" "/usr/bin/env"], filter: true, rules: 65, flags: 0x1, presets: 0xf`
|
||||||
if got := c.String(); got != want {
|
if got := c.String(); got != want {
|
||||||
t.Errorf("String: %s, want %s", got, want)
|
t.Errorf("String: %s, want %s", got, want)
|
||||||
|
|||||||
@@ -96,16 +96,15 @@ type initParams struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Init is called by [TryArgv0] if the current process is the container init.
|
// Init is called by [TryArgv0] if the current process is the container init.
|
||||||
func Init(msg message.Msg) {
|
func Init(msg message.Msg) { initEntrypoint(direct{}, msg) }
|
||||||
if msg == nil {
|
|
||||||
panic("attempting to call initEntrypoint with nil msg")
|
|
||||||
}
|
|
||||||
initEntrypoint(direct{}, msg)
|
|
||||||
}
|
|
||||||
|
|
||||||
func initEntrypoint(k syscallDispatcher, msg message.Msg) {
|
func initEntrypoint(k syscallDispatcher, msg message.Msg) {
|
||||||
k.lockOSThread()
|
k.lockOSThread()
|
||||||
|
|
||||||
|
if msg == nil {
|
||||||
|
panic("attempting to call initEntrypoint with nil msg")
|
||||||
|
}
|
||||||
|
|
||||||
if k.getpid() != 1 {
|
if k.getpid() != 1 {
|
||||||
k.fatal(msg, "this process must run as pid 1")
|
k.fatal(msg, "this process must run as pid 1")
|
||||||
}
|
}
|
||||||
@@ -451,6 +450,7 @@ func initEntrypoint(k syscallDispatcher, msg message.Msg) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// initName is the prefix used by log.std in the init process.
|
||||||
const initName = "init"
|
const initName = "init"
|
||||||
|
|
||||||
// TryArgv0 calls [Init] if the last element of argv0 is "init".
|
// TryArgv0 calls [Init] if the last element of argv0 is "init".
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"hakurei.app/container/bits"
|
|
||||||
"hakurei.app/container/check"
|
"hakurei.app/container/check"
|
||||||
|
"hakurei.app/container/comp"
|
||||||
"hakurei.app/container/seccomp"
|
"hakurei.app/container/seccomp"
|
||||||
"hakurei.app/container/stub"
|
"hakurei.app/container/stub"
|
||||||
)
|
)
|
||||||
@@ -70,7 +70,7 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
Gid: 1 << 31,
|
Gid: 1 << 31,
|
||||||
Hostname: "hakurei-check",
|
Hostname: "hakurei-check",
|
||||||
SeccompRules: make([]seccomp.NativeRule, 0),
|
SeccompRules: make([]seccomp.NativeRule, 0),
|
||||||
SeccompPresets: bits.PresetStrict,
|
SeccompPresets: comp.PresetStrict,
|
||||||
RetainSession: true,
|
RetainSession: true,
|
||||||
Privileged: true,
|
Privileged: true,
|
||||||
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(79), nil),
|
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(79), nil),
|
||||||
@@ -95,7 +95,7 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
Hostname: "hakurei-check",
|
Hostname: "hakurei-check",
|
||||||
Ops: (*Ops)(sliceAddr(make(Ops, 1))),
|
Ops: (*Ops)(sliceAddr(make(Ops, 1))),
|
||||||
SeccompRules: make([]seccomp.NativeRule, 0),
|
SeccompRules: make([]seccomp.NativeRule, 0),
|
||||||
SeccompPresets: bits.PresetStrict,
|
SeccompPresets: comp.PresetStrict,
|
||||||
RetainSession: true,
|
RetainSession: true,
|
||||||
Privileged: true,
|
Privileged: true,
|
||||||
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(78), nil),
|
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(78), nil),
|
||||||
@@ -123,7 +123,7 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
Hostname: "hakurei-check",
|
Hostname: "hakurei-check",
|
||||||
Ops: (*Ops)(sliceAddr(make(Ops, 1))),
|
Ops: (*Ops)(sliceAddr(make(Ops, 1))),
|
||||||
SeccompRules: make([]seccomp.NativeRule, 0),
|
SeccompRules: make([]seccomp.NativeRule, 0),
|
||||||
SeccompPresets: bits.PresetStrict,
|
SeccompPresets: comp.PresetStrict,
|
||||||
RetainSession: true,
|
RetainSession: true,
|
||||||
Privileged: true,
|
Privileged: true,
|
||||||
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(76), nil),
|
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(76), nil),
|
||||||
@@ -152,7 +152,7 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
Hostname: "hakurei-check",
|
Hostname: "hakurei-check",
|
||||||
Ops: (*Ops)(sliceAddr(make(Ops, 1))),
|
Ops: (*Ops)(sliceAddr(make(Ops, 1))),
|
||||||
SeccompRules: make([]seccomp.NativeRule, 0),
|
SeccompRules: make([]seccomp.NativeRule, 0),
|
||||||
SeccompPresets: bits.PresetStrict,
|
SeccompPresets: comp.PresetStrict,
|
||||||
RetainSession: true,
|
RetainSession: true,
|
||||||
Privileged: true,
|
Privileged: true,
|
||||||
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(74), nil),
|
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(74), nil),
|
||||||
@@ -182,7 +182,7 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
Hostname: "hakurei-check",
|
Hostname: "hakurei-check",
|
||||||
Ops: (*Ops)(sliceAddr(make(Ops, 1))),
|
Ops: (*Ops)(sliceAddr(make(Ops, 1))),
|
||||||
SeccompRules: make([]seccomp.NativeRule, 0),
|
SeccompRules: make([]seccomp.NativeRule, 0),
|
||||||
SeccompPresets: bits.PresetStrict,
|
SeccompPresets: comp.PresetStrict,
|
||||||
RetainSession: true,
|
RetainSession: true,
|
||||||
Privileged: true,
|
Privileged: true,
|
||||||
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(72), nil),
|
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(72), nil),
|
||||||
@@ -213,7 +213,7 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
Hostname: "hakurei-check",
|
Hostname: "hakurei-check",
|
||||||
Ops: (*Ops)(sliceAddr(make(Ops, 1))),
|
Ops: (*Ops)(sliceAddr(make(Ops, 1))),
|
||||||
SeccompRules: make([]seccomp.NativeRule, 0),
|
SeccompRules: make([]seccomp.NativeRule, 0),
|
||||||
SeccompPresets: bits.PresetStrict,
|
SeccompPresets: comp.PresetStrict,
|
||||||
RetainSession: true,
|
RetainSession: true,
|
||||||
Privileged: true,
|
Privileged: true,
|
||||||
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(70), nil),
|
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(70), nil),
|
||||||
@@ -245,7 +245,7 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
Hostname: "hakurei-check",
|
Hostname: "hakurei-check",
|
||||||
Ops: (*Ops)(sliceAddr(make(Ops, 1))),
|
Ops: (*Ops)(sliceAddr(make(Ops, 1))),
|
||||||
SeccompRules: make([]seccomp.NativeRule, 0),
|
SeccompRules: make([]seccomp.NativeRule, 0),
|
||||||
SeccompPresets: bits.PresetStrict,
|
SeccompPresets: comp.PresetStrict,
|
||||||
RetainSession: true,
|
RetainSession: true,
|
||||||
Privileged: true,
|
Privileged: true,
|
||||||
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(68), nil),
|
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(68), nil),
|
||||||
@@ -279,7 +279,7 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
Hostname: "hakurei-check",
|
Hostname: "hakurei-check",
|
||||||
Ops: (*Ops)(sliceAddr(make(Ops, 1))),
|
Ops: (*Ops)(sliceAddr(make(Ops, 1))),
|
||||||
SeccompRules: make([]seccomp.NativeRule, 0),
|
SeccompRules: make([]seccomp.NativeRule, 0),
|
||||||
SeccompPresets: bits.PresetStrict,
|
SeccompPresets: comp.PresetStrict,
|
||||||
RetainSession: true,
|
RetainSession: true,
|
||||||
Privileged: true,
|
Privileged: true,
|
||||||
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(66), nil),
|
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(66), nil),
|
||||||
@@ -315,7 +315,7 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
Hostname: "hakurei-check",
|
Hostname: "hakurei-check",
|
||||||
Ops: (*Ops)(sliceAddr(make(Ops, 1))),
|
Ops: (*Ops)(sliceAddr(make(Ops, 1))),
|
||||||
SeccompRules: make([]seccomp.NativeRule, 0),
|
SeccompRules: make([]seccomp.NativeRule, 0),
|
||||||
SeccompPresets: bits.PresetStrict,
|
SeccompPresets: comp.PresetStrict,
|
||||||
RetainSession: true,
|
RetainSession: true,
|
||||||
Privileged: true,
|
Privileged: true,
|
||||||
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(64), nil),
|
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(64), nil),
|
||||||
@@ -351,9 +351,9 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
Uid: 1 << 32,
|
Uid: 1 << 32,
|
||||||
Gid: 1 << 31,
|
Gid: 1 << 31,
|
||||||
Hostname: "hakurei-check",
|
Hostname: "hakurei-check",
|
||||||
Ops: new(Ops).Bind(nil, nil, bits.BindDevice),
|
Ops: new(Ops).Bind(nil, nil, comp.BindDevice),
|
||||||
SeccompRules: make([]seccomp.NativeRule, 0),
|
SeccompRules: make([]seccomp.NativeRule, 0),
|
||||||
SeccompPresets: bits.PresetStrict,
|
SeccompPresets: comp.PresetStrict,
|
||||||
RetainSession: true,
|
RetainSession: true,
|
||||||
Privileged: true,
|
Privileged: true,
|
||||||
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(63), nil),
|
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(63), nil),
|
||||||
@@ -389,9 +389,9 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
Uid: 1 << 32,
|
Uid: 1 << 32,
|
||||||
Gid: 1 << 31,
|
Gid: 1 << 31,
|
||||||
Hostname: "hakurei-check",
|
Hostname: "hakurei-check",
|
||||||
Ops: new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), bits.BindDevice).Proc(check.MustAbs("/proc/")),
|
Ops: new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), comp.BindDevice).Proc(check.MustAbs("/proc/")),
|
||||||
SeccompRules: make([]seccomp.NativeRule, 0),
|
SeccompRules: make([]seccomp.NativeRule, 0),
|
||||||
SeccompPresets: bits.PresetStrict,
|
SeccompPresets: comp.PresetStrict,
|
||||||
RetainSession: true,
|
RetainSession: true,
|
||||||
Privileged: true,
|
Privileged: true,
|
||||||
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(62), nil),
|
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(62), nil),
|
||||||
@@ -428,9 +428,9 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
Uid: 1 << 32,
|
Uid: 1 << 32,
|
||||||
Gid: 1 << 31,
|
Gid: 1 << 31,
|
||||||
Hostname: "hakurei-check",
|
Hostname: "hakurei-check",
|
||||||
Ops: new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), bits.BindDevice).Proc(check.MustAbs("/proc/")),
|
Ops: new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), comp.BindDevice).Proc(check.MustAbs("/proc/")),
|
||||||
SeccompRules: make([]seccomp.NativeRule, 0),
|
SeccompRules: make([]seccomp.NativeRule, 0),
|
||||||
SeccompPresets: bits.PresetStrict,
|
SeccompPresets: comp.PresetStrict,
|
||||||
RetainSession: true,
|
RetainSession: true,
|
||||||
Privileged: true,
|
Privileged: true,
|
||||||
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(60), nil),
|
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(60), nil),
|
||||||
@@ -467,9 +467,9 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
Uid: 1 << 32,
|
Uid: 1 << 32,
|
||||||
Gid: 1 << 31,
|
Gid: 1 << 31,
|
||||||
Hostname: "hakurei-check",
|
Hostname: "hakurei-check",
|
||||||
Ops: new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), bits.BindDevice).Proc(check.MustAbs("/proc/")),
|
Ops: new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), comp.BindDevice).Proc(check.MustAbs("/proc/")),
|
||||||
SeccompRules: make([]seccomp.NativeRule, 0),
|
SeccompRules: make([]seccomp.NativeRule, 0),
|
||||||
SeccompPresets: bits.PresetStrict,
|
SeccompPresets: comp.PresetStrict,
|
||||||
RetainSession: true,
|
RetainSession: true,
|
||||||
Privileged: true,
|
Privileged: true,
|
||||||
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(59), nil),
|
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(59), nil),
|
||||||
@@ -507,9 +507,9 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
Uid: 1 << 32,
|
Uid: 1 << 32,
|
||||||
Gid: 1 << 31,
|
Gid: 1 << 31,
|
||||||
Hostname: "hakurei-check",
|
Hostname: "hakurei-check",
|
||||||
Ops: new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), bits.BindDevice).Proc(check.MustAbs("/proc/")),
|
Ops: new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), comp.BindDevice).Proc(check.MustAbs("/proc/")),
|
||||||
SeccompRules: make([]seccomp.NativeRule, 0),
|
SeccompRules: make([]seccomp.NativeRule, 0),
|
||||||
SeccompPresets: bits.PresetStrict,
|
SeccompPresets: comp.PresetStrict,
|
||||||
RetainSession: true,
|
RetainSession: true,
|
||||||
Privileged: true,
|
Privileged: true,
|
||||||
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(57), nil),
|
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(57), nil),
|
||||||
@@ -548,9 +548,9 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
Uid: 1 << 32,
|
Uid: 1 << 32,
|
||||||
Gid: 1 << 31,
|
Gid: 1 << 31,
|
||||||
Hostname: "hakurei-check",
|
Hostname: "hakurei-check",
|
||||||
Ops: new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), bits.BindDevice).Proc(check.MustAbs("/proc/")),
|
Ops: new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), comp.BindDevice).Proc(check.MustAbs("/proc/")),
|
||||||
SeccompRules: make([]seccomp.NativeRule, 0),
|
SeccompRules: make([]seccomp.NativeRule, 0),
|
||||||
SeccompPresets: bits.PresetStrict,
|
SeccompPresets: comp.PresetStrict,
|
||||||
RetainSession: true,
|
RetainSession: true,
|
||||||
Privileged: true,
|
Privileged: true,
|
||||||
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(55), nil),
|
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(55), nil),
|
||||||
@@ -590,9 +590,9 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
Uid: 1 << 32,
|
Uid: 1 << 32,
|
||||||
Gid: 1 << 31,
|
Gid: 1 << 31,
|
||||||
Hostname: "hakurei-check",
|
Hostname: "hakurei-check",
|
||||||
Ops: new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), bits.BindDevice).Proc(check.MustAbs("/proc/")),
|
Ops: new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), comp.BindDevice).Proc(check.MustAbs("/proc/")),
|
||||||
SeccompRules: make([]seccomp.NativeRule, 0),
|
SeccompRules: make([]seccomp.NativeRule, 0),
|
||||||
SeccompPresets: bits.PresetStrict,
|
SeccompPresets: comp.PresetStrict,
|
||||||
RetainSession: true,
|
RetainSession: true,
|
||||||
Privileged: true,
|
Privileged: true,
|
||||||
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(53), nil),
|
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(53), nil),
|
||||||
@@ -633,9 +633,9 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
Uid: 1 << 32,
|
Uid: 1 << 32,
|
||||||
Gid: 1 << 31,
|
Gid: 1 << 31,
|
||||||
Hostname: "hakurei-check",
|
Hostname: "hakurei-check",
|
||||||
Ops: new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), bits.BindDevice).Proc(check.MustAbs("/proc/")),
|
Ops: new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), comp.BindDevice).Proc(check.MustAbs("/proc/")),
|
||||||
SeccompRules: make([]seccomp.NativeRule, 0),
|
SeccompRules: make([]seccomp.NativeRule, 0),
|
||||||
SeccompPresets: bits.PresetStrict,
|
SeccompPresets: comp.PresetStrict,
|
||||||
RetainSession: true,
|
RetainSession: true,
|
||||||
Privileged: true,
|
Privileged: true,
|
||||||
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(51), nil),
|
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(51), nil),
|
||||||
@@ -677,9 +677,9 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
Uid: 1 << 32,
|
Uid: 1 << 32,
|
||||||
Gid: 1 << 31,
|
Gid: 1 << 31,
|
||||||
Hostname: "hakurei-check",
|
Hostname: "hakurei-check",
|
||||||
Ops: new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), bits.BindDevice).Proc(check.MustAbs("/proc/")),
|
Ops: new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), comp.BindDevice).Proc(check.MustAbs("/proc/")),
|
||||||
SeccompRules: make([]seccomp.NativeRule, 0),
|
SeccompRules: make([]seccomp.NativeRule, 0),
|
||||||
SeccompPresets: bits.PresetStrict,
|
SeccompPresets: comp.PresetStrict,
|
||||||
RetainSession: true,
|
RetainSession: true,
|
||||||
Privileged: true,
|
Privileged: true,
|
||||||
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(49), nil),
|
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(49), nil),
|
||||||
@@ -722,9 +722,9 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
Uid: 1 << 32,
|
Uid: 1 << 32,
|
||||||
Gid: 1 << 31,
|
Gid: 1 << 31,
|
||||||
Hostname: "hakurei-check",
|
Hostname: "hakurei-check",
|
||||||
Ops: new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), bits.BindDevice).Proc(check.MustAbs("/proc/")),
|
Ops: new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), comp.BindDevice).Proc(check.MustAbs("/proc/")),
|
||||||
SeccompRules: make([]seccomp.NativeRule, 0),
|
SeccompRules: make([]seccomp.NativeRule, 0),
|
||||||
SeccompPresets: bits.PresetStrict,
|
SeccompPresets: comp.PresetStrict,
|
||||||
RetainSession: true,
|
RetainSession: true,
|
||||||
Privileged: true,
|
Privileged: true,
|
||||||
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(47), nil),
|
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(47), nil),
|
||||||
@@ -768,9 +768,9 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
Uid: 1 << 32,
|
Uid: 1 << 32,
|
||||||
Gid: 1 << 31,
|
Gid: 1 << 31,
|
||||||
Hostname: "hakurei-check",
|
Hostname: "hakurei-check",
|
||||||
Ops: new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), bits.BindDevice).Proc(check.MustAbs("/proc/")),
|
Ops: new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), comp.BindDevice).Proc(check.MustAbs("/proc/")),
|
||||||
SeccompRules: make([]seccomp.NativeRule, 0),
|
SeccompRules: make([]seccomp.NativeRule, 0),
|
||||||
SeccompPresets: bits.PresetStrict,
|
SeccompPresets: comp.PresetStrict,
|
||||||
RetainSession: true,
|
RetainSession: true,
|
||||||
Privileged: true,
|
Privileged: true,
|
||||||
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(45), nil),
|
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(45), nil),
|
||||||
@@ -823,9 +823,9 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
Uid: 1 << 32,
|
Uid: 1 << 32,
|
||||||
Gid: 1 << 31,
|
Gid: 1 << 31,
|
||||||
Hostname: "hakurei-check",
|
Hostname: "hakurei-check",
|
||||||
Ops: new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), bits.BindDevice).Proc(check.MustAbs("/proc/")),
|
Ops: new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), comp.BindDevice).Proc(check.MustAbs("/proc/")),
|
||||||
SeccompRules: make([]seccomp.NativeRule, 0),
|
SeccompRules: make([]seccomp.NativeRule, 0),
|
||||||
SeccompPresets: bits.PresetStrict,
|
SeccompPresets: comp.PresetStrict,
|
||||||
RetainSession: true,
|
RetainSession: true,
|
||||||
Privileged: true,
|
Privileged: true,
|
||||||
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(43), nil),
|
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(43), nil),
|
||||||
@@ -878,9 +878,9 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
Uid: 1 << 32,
|
Uid: 1 << 32,
|
||||||
Gid: 1 << 31,
|
Gid: 1 << 31,
|
||||||
Hostname: "hakurei-check",
|
Hostname: "hakurei-check",
|
||||||
Ops: new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), bits.BindDevice).Proc(check.MustAbs("/proc/")),
|
Ops: new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), comp.BindDevice).Proc(check.MustAbs("/proc/")),
|
||||||
SeccompRules: make([]seccomp.NativeRule, 0),
|
SeccompRules: make([]seccomp.NativeRule, 0),
|
||||||
SeccompPresets: bits.PresetStrict,
|
SeccompPresets: comp.PresetStrict,
|
||||||
RetainSession: true,
|
RetainSession: true,
|
||||||
Privileged: true,
|
Privileged: true,
|
||||||
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(42), nil),
|
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(42), nil),
|
||||||
@@ -934,9 +934,9 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
Uid: 1 << 32,
|
Uid: 1 << 32,
|
||||||
Gid: 1 << 31,
|
Gid: 1 << 31,
|
||||||
Hostname: "hakurei-check",
|
Hostname: "hakurei-check",
|
||||||
Ops: new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), bits.BindDevice).Proc(check.MustAbs("/proc/")),
|
Ops: new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), comp.BindDevice).Proc(check.MustAbs("/proc/")),
|
||||||
SeccompRules: make([]seccomp.NativeRule, 0),
|
SeccompRules: make([]seccomp.NativeRule, 0),
|
||||||
SeccompPresets: bits.PresetStrict,
|
SeccompPresets: comp.PresetStrict,
|
||||||
RetainSession: true,
|
RetainSession: true,
|
||||||
Privileged: true,
|
Privileged: true,
|
||||||
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(40), nil),
|
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(40), nil),
|
||||||
@@ -991,9 +991,9 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
Uid: 1 << 32,
|
Uid: 1 << 32,
|
||||||
Gid: 1 << 31,
|
Gid: 1 << 31,
|
||||||
Hostname: "hakurei-check",
|
Hostname: "hakurei-check",
|
||||||
Ops: new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), bits.BindDevice).Proc(check.MustAbs("/proc/")),
|
Ops: new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), comp.BindDevice).Proc(check.MustAbs("/proc/")),
|
||||||
SeccompRules: make([]seccomp.NativeRule, 0),
|
SeccompRules: make([]seccomp.NativeRule, 0),
|
||||||
SeccompPresets: bits.PresetStrict,
|
SeccompPresets: comp.PresetStrict,
|
||||||
RetainSession: true,
|
RetainSession: true,
|
||||||
Privileged: true,
|
Privileged: true,
|
||||||
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(38), nil),
|
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(38), nil),
|
||||||
@@ -1029,8 +1029,8 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
/* end apply */
|
/* end apply */
|
||||||
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
||||||
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, syscall.EINTR),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, syscall.EINTR),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, stub.UniqueError(37)),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, stub.UniqueError(37)),
|
||||||
call("fatalf", stub.ExpectArgs{"cannot open intermediate root: %v", []any{stub.UniqueError(37)}}, nil, nil),
|
call("fatalf", stub.ExpectArgs{"cannot open intermediate root: %v", []any{stub.UniqueError(37)}}, nil, nil),
|
||||||
},
|
},
|
||||||
}, nil},
|
}, nil},
|
||||||
@@ -1050,9 +1050,9 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
Uid: 1 << 32,
|
Uid: 1 << 32,
|
||||||
Gid: 1 << 31,
|
Gid: 1 << 31,
|
||||||
Hostname: "hakurei-check",
|
Hostname: "hakurei-check",
|
||||||
Ops: new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), bits.BindDevice).Proc(check.MustAbs("/proc/")),
|
Ops: new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), comp.BindDevice).Proc(check.MustAbs("/proc/")),
|
||||||
SeccompRules: make([]seccomp.NativeRule, 0),
|
SeccompRules: make([]seccomp.NativeRule, 0),
|
||||||
SeccompPresets: bits.PresetStrict,
|
SeccompPresets: comp.PresetStrict,
|
||||||
RetainSession: true,
|
RetainSession: true,
|
||||||
Privileged: true,
|
Privileged: true,
|
||||||
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(36), nil),
|
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(36), nil),
|
||||||
@@ -1088,8 +1088,8 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
/* end apply */
|
/* end apply */
|
||||||
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
||||||
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, syscall.EINTR),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, syscall.EINTR),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, nil),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, nil),
|
||||||
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, stub.UniqueError(35)),
|
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, stub.UniqueError(35)),
|
||||||
call("fatalf", stub.ExpectArgs{"cannot enter sysroot: %v", []any{stub.UniqueError(35)}}, nil, nil),
|
call("fatalf", stub.ExpectArgs{"cannot enter sysroot: %v", []any{stub.UniqueError(35)}}, nil, nil),
|
||||||
},
|
},
|
||||||
@@ -1110,9 +1110,9 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
Uid: 1 << 32,
|
Uid: 1 << 32,
|
||||||
Gid: 1 << 31,
|
Gid: 1 << 31,
|
||||||
Hostname: "hakurei-check",
|
Hostname: "hakurei-check",
|
||||||
Ops: new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), bits.BindDevice).Proc(check.MustAbs("/proc/")),
|
Ops: new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), comp.BindDevice).Proc(check.MustAbs("/proc/")),
|
||||||
SeccompRules: make([]seccomp.NativeRule, 0),
|
SeccompRules: make([]seccomp.NativeRule, 0),
|
||||||
SeccompPresets: bits.PresetStrict,
|
SeccompPresets: comp.PresetStrict,
|
||||||
RetainSession: true,
|
RetainSession: true,
|
||||||
Privileged: true,
|
Privileged: true,
|
||||||
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(34), nil),
|
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(34), nil),
|
||||||
@@ -1148,8 +1148,8 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
/* end apply */
|
/* end apply */
|
||||||
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
||||||
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, syscall.EINTR),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, syscall.EINTR),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, nil),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, nil),
|
||||||
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
||||||
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, stub.UniqueError(33)),
|
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, stub.UniqueError(33)),
|
||||||
call("fatalf", stub.ExpectArgs{"cannot pivot into sysroot: %v", []any{stub.UniqueError(33)}}, nil, nil),
|
call("fatalf", stub.ExpectArgs{"cannot pivot into sysroot: %v", []any{stub.UniqueError(33)}}, nil, nil),
|
||||||
@@ -1171,9 +1171,9 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
Uid: 1 << 32,
|
Uid: 1 << 32,
|
||||||
Gid: 1 << 31,
|
Gid: 1 << 31,
|
||||||
Hostname: "hakurei-check",
|
Hostname: "hakurei-check",
|
||||||
Ops: new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), bits.BindDevice).Proc(check.MustAbs("/proc/")),
|
Ops: new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), comp.BindDevice).Proc(check.MustAbs("/proc/")),
|
||||||
SeccompRules: make([]seccomp.NativeRule, 0),
|
SeccompRules: make([]seccomp.NativeRule, 0),
|
||||||
SeccompPresets: bits.PresetStrict,
|
SeccompPresets: comp.PresetStrict,
|
||||||
RetainSession: true,
|
RetainSession: true,
|
||||||
Privileged: true,
|
Privileged: true,
|
||||||
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(32), nil),
|
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(32), nil),
|
||||||
@@ -1209,8 +1209,8 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
/* end apply */
|
/* end apply */
|
||||||
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
||||||
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, syscall.EINTR),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, syscall.EINTR),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, nil),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, nil),
|
||||||
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
||||||
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil),
|
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil),
|
||||||
call("fchdir", stub.ExpectArgs{1 << 35}, nil, stub.UniqueError(31)),
|
call("fchdir", stub.ExpectArgs{1 << 35}, nil, stub.UniqueError(31)),
|
||||||
@@ -1233,9 +1233,9 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
Uid: 1 << 32,
|
Uid: 1 << 32,
|
||||||
Gid: 1 << 31,
|
Gid: 1 << 31,
|
||||||
Hostname: "hakurei-check",
|
Hostname: "hakurei-check",
|
||||||
Ops: new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), bits.BindDevice).Proc(check.MustAbs("/proc/")),
|
Ops: new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), comp.BindDevice).Proc(check.MustAbs("/proc/")),
|
||||||
SeccompRules: make([]seccomp.NativeRule, 0),
|
SeccompRules: make([]seccomp.NativeRule, 0),
|
||||||
SeccompPresets: bits.PresetStrict,
|
SeccompPresets: comp.PresetStrict,
|
||||||
RetainSession: true,
|
RetainSession: true,
|
||||||
Privileged: true,
|
Privileged: true,
|
||||||
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(30), nil),
|
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(30), nil),
|
||||||
@@ -1271,8 +1271,8 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
/* end apply */
|
/* end apply */
|
||||||
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
||||||
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, syscall.EINTR),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, syscall.EINTR),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, nil),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, nil),
|
||||||
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
||||||
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil),
|
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil),
|
||||||
call("fchdir", stub.ExpectArgs{1 << 35}, nil, nil),
|
call("fchdir", stub.ExpectArgs{1 << 35}, nil, nil),
|
||||||
@@ -1296,9 +1296,9 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
Uid: 1 << 32,
|
Uid: 1 << 32,
|
||||||
Gid: 1 << 31,
|
Gid: 1 << 31,
|
||||||
Hostname: "hakurei-check",
|
Hostname: "hakurei-check",
|
||||||
Ops: new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), bits.BindDevice).Proc(check.MustAbs("/proc/")),
|
Ops: new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), comp.BindDevice).Proc(check.MustAbs("/proc/")),
|
||||||
SeccompRules: make([]seccomp.NativeRule, 0),
|
SeccompRules: make([]seccomp.NativeRule, 0),
|
||||||
SeccompPresets: bits.PresetStrict,
|
SeccompPresets: comp.PresetStrict,
|
||||||
RetainSession: true,
|
RetainSession: true,
|
||||||
Privileged: true,
|
Privileged: true,
|
||||||
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(28), nil),
|
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(28), nil),
|
||||||
@@ -1334,8 +1334,8 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
/* end apply */
|
/* end apply */
|
||||||
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
||||||
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, syscall.EINTR),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, syscall.EINTR),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, nil),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, nil),
|
||||||
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
||||||
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil),
|
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil),
|
||||||
call("fchdir", stub.ExpectArgs{1 << 35}, nil, nil),
|
call("fchdir", stub.ExpectArgs{1 << 35}, nil, nil),
|
||||||
@@ -1360,9 +1360,9 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
Uid: 1 << 32,
|
Uid: 1 << 32,
|
||||||
Gid: 1 << 31,
|
Gid: 1 << 31,
|
||||||
Hostname: "hakurei-check",
|
Hostname: "hakurei-check",
|
||||||
Ops: new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), bits.BindDevice).Proc(check.MustAbs("/proc/")),
|
Ops: new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), comp.BindDevice).Proc(check.MustAbs("/proc/")),
|
||||||
SeccompRules: make([]seccomp.NativeRule, 0),
|
SeccompRules: make([]seccomp.NativeRule, 0),
|
||||||
SeccompPresets: bits.PresetStrict,
|
SeccompPresets: comp.PresetStrict,
|
||||||
RetainSession: true,
|
RetainSession: true,
|
||||||
Privileged: true,
|
Privileged: true,
|
||||||
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(26), nil),
|
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(26), nil),
|
||||||
@@ -1398,8 +1398,8 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
/* end apply */
|
/* end apply */
|
||||||
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
||||||
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, syscall.EINTR),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, syscall.EINTR),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, nil),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, nil),
|
||||||
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
||||||
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil),
|
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil),
|
||||||
call("fchdir", stub.ExpectArgs{1 << 35}, nil, nil),
|
call("fchdir", stub.ExpectArgs{1 << 35}, nil, nil),
|
||||||
@@ -1425,9 +1425,9 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
Uid: 1 << 32,
|
Uid: 1 << 32,
|
||||||
Gid: 1 << 31,
|
Gid: 1 << 31,
|
||||||
Hostname: "hakurei-check",
|
Hostname: "hakurei-check",
|
||||||
Ops: new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), bits.BindDevice).Proc(check.MustAbs("/proc/")),
|
Ops: new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), comp.BindDevice).Proc(check.MustAbs("/proc/")),
|
||||||
SeccompRules: make([]seccomp.NativeRule, 0),
|
SeccompRules: make([]seccomp.NativeRule, 0),
|
||||||
SeccompPresets: bits.PresetStrict,
|
SeccompPresets: comp.PresetStrict,
|
||||||
RetainSession: true,
|
RetainSession: true,
|
||||||
Privileged: true,
|
Privileged: true,
|
||||||
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(24), nil),
|
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(24), nil),
|
||||||
@@ -1463,8 +1463,8 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
/* end apply */
|
/* end apply */
|
||||||
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
||||||
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, syscall.EINTR),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, syscall.EINTR),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, nil),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, nil),
|
||||||
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
||||||
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil),
|
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil),
|
||||||
call("fchdir", stub.ExpectArgs{1 << 35}, nil, nil),
|
call("fchdir", stub.ExpectArgs{1 << 35}, nil, nil),
|
||||||
@@ -1491,9 +1491,9 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
Uid: 1 << 32,
|
Uid: 1 << 32,
|
||||||
Gid: 1 << 31,
|
Gid: 1 << 31,
|
||||||
Hostname: "hakurei-check",
|
Hostname: "hakurei-check",
|
||||||
Ops: new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), bits.BindDevice).Proc(check.MustAbs("/proc/")),
|
Ops: new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), comp.BindDevice).Proc(check.MustAbs("/proc/")),
|
||||||
SeccompRules: make([]seccomp.NativeRule, 0),
|
SeccompRules: make([]seccomp.NativeRule, 0),
|
||||||
SeccompPresets: bits.PresetStrict,
|
SeccompPresets: comp.PresetStrict,
|
||||||
RetainSession: true,
|
RetainSession: true,
|
||||||
Privileged: true,
|
Privileged: true,
|
||||||
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(22), nil),
|
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(22), nil),
|
||||||
@@ -1529,8 +1529,8 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
/* end apply */
|
/* end apply */
|
||||||
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
||||||
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, syscall.EINTR),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, syscall.EINTR),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, nil),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, nil),
|
||||||
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
||||||
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil),
|
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil),
|
||||||
call("fchdir", stub.ExpectArgs{1 << 35}, nil, nil),
|
call("fchdir", stub.ExpectArgs{1 << 35}, nil, nil),
|
||||||
@@ -1565,9 +1565,9 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
Uid: 1 << 32,
|
Uid: 1 << 32,
|
||||||
Gid: 1 << 31,
|
Gid: 1 << 31,
|
||||||
Hostname: "hakurei-check",
|
Hostname: "hakurei-check",
|
||||||
Ops: new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), bits.BindDevice).Proc(check.MustAbs("/proc/")),
|
Ops: new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), comp.BindDevice).Proc(check.MustAbs("/proc/")),
|
||||||
SeccompRules: make([]seccomp.NativeRule, 0),
|
SeccompRules: make([]seccomp.NativeRule, 0),
|
||||||
SeccompPresets: bits.PresetStrict,
|
SeccompPresets: comp.PresetStrict,
|
||||||
RetainSession: true,
|
RetainSession: true,
|
||||||
Privileged: true,
|
Privileged: true,
|
||||||
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(20), nil),
|
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(20), nil),
|
||||||
@@ -1603,8 +1603,8 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
/* end apply */
|
/* end apply */
|
||||||
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
||||||
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, syscall.EINTR),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, syscall.EINTR),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, nil),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, nil),
|
||||||
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
||||||
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil),
|
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil),
|
||||||
call("fchdir", stub.ExpectArgs{1 << 35}, nil, nil),
|
call("fchdir", stub.ExpectArgs{1 << 35}, nil, nil),
|
||||||
@@ -1672,9 +1672,9 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
Uid: 1 << 32,
|
Uid: 1 << 32,
|
||||||
Gid: 1 << 31,
|
Gid: 1 << 31,
|
||||||
Hostname: "hakurei-check",
|
Hostname: "hakurei-check",
|
||||||
Ops: new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), bits.BindDevice).Proc(check.MustAbs("/proc/")),
|
Ops: new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), comp.BindDevice).Proc(check.MustAbs("/proc/")),
|
||||||
SeccompRules: make([]seccomp.NativeRule, 0),
|
SeccompRules: make([]seccomp.NativeRule, 0),
|
||||||
SeccompPresets: bits.PresetStrict,
|
SeccompPresets: comp.PresetStrict,
|
||||||
RetainSession: true,
|
RetainSession: true,
|
||||||
Privileged: true,
|
Privileged: true,
|
||||||
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(18), nil),
|
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(18), nil),
|
||||||
@@ -1710,8 +1710,8 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
/* end apply */
|
/* end apply */
|
||||||
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
||||||
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, syscall.EINTR),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, syscall.EINTR),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, nil),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, nil),
|
||||||
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
||||||
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil),
|
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil),
|
||||||
call("fchdir", stub.ExpectArgs{1 << 35}, nil, nil),
|
call("fchdir", stub.ExpectArgs{1 << 35}, nil, nil),
|
||||||
@@ -1780,9 +1780,9 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
Uid: 1 << 32,
|
Uid: 1 << 32,
|
||||||
Gid: 1 << 31,
|
Gid: 1 << 31,
|
||||||
Hostname: "hakurei-check",
|
Hostname: "hakurei-check",
|
||||||
Ops: new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), bits.BindDevice).Proc(check.MustAbs("/proc/")),
|
Ops: new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), comp.BindDevice).Proc(check.MustAbs("/proc/")),
|
||||||
SeccompRules: make([]seccomp.NativeRule, 0),
|
SeccompRules: make([]seccomp.NativeRule, 0),
|
||||||
SeccompPresets: bits.PresetStrict,
|
SeccompPresets: comp.PresetStrict,
|
||||||
RetainSession: true,
|
RetainSession: true,
|
||||||
Privileged: true,
|
Privileged: true,
|
||||||
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(16), nil),
|
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(16), nil),
|
||||||
@@ -1818,8 +1818,8 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
/* end apply */
|
/* end apply */
|
||||||
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
||||||
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, syscall.EINTR),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, syscall.EINTR),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, nil),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, nil),
|
||||||
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
||||||
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil),
|
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil),
|
||||||
call("fchdir", stub.ExpectArgs{1 << 35}, nil, nil),
|
call("fchdir", stub.ExpectArgs{1 << 35}, nil, nil),
|
||||||
@@ -1869,7 +1869,7 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x28)}, nil, nil),
|
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x28)}, nil, nil),
|
||||||
call("capAmbientRaise", stub.ExpectArgs{uintptr(0x15)}, nil, nil),
|
call("capAmbientRaise", stub.ExpectArgs{uintptr(0x15)}, nil, nil),
|
||||||
call("capset", stub.ExpectArgs{&capHeader{_LINUX_CAPABILITY_VERSION_3, 0}, &[2]capData{{0, 0x200000, 0x200000}, {0, 0, 0}}}, nil, nil),
|
call("capset", stub.ExpectArgs{&capHeader{_LINUX_CAPABILITY_VERSION_3, 0}, &[2]capData{{0, 0x200000, 0x200000}, {0, 0, 0}}}, nil, nil),
|
||||||
call("verbosef", stub.ExpectArgs{"resolving presets %#x", []any{bits.FilterPreset(0xf)}}, nil, nil),
|
call("verbosef", stub.ExpectArgs{"resolving presets %#x", []any{comp.FilterPreset(0xf)}}, nil, nil),
|
||||||
call("seccompLoad", stub.ExpectArgs{seccomp.Preset(0xf, 0), seccomp.ExportFlag(0)}, nil, stub.UniqueError(15)),
|
call("seccompLoad", stub.ExpectArgs{seccomp.Preset(0xf, 0), seccomp.ExportFlag(0)}, nil, stub.UniqueError(15)),
|
||||||
call("fatalf", stub.ExpectArgs{"cannot load syscall filter: %v", []any{stub.UniqueError(15)}}, nil, nil),
|
call("fatalf", stub.ExpectArgs{"cannot load syscall filter: %v", []any{stub.UniqueError(15)}}, nil, nil),
|
||||||
},
|
},
|
||||||
@@ -1890,7 +1890,7 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
Uid: 1 << 24,
|
Uid: 1 << 24,
|
||||||
Gid: 1 << 47,
|
Gid: 1 << 47,
|
||||||
Hostname: "hakurei-check",
|
Hostname: "hakurei-check",
|
||||||
Ops: new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), bits.BindDevice).Proc(check.MustAbs("/proc/")),
|
Ops: new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), comp.BindDevice).Proc(check.MustAbs("/proc/")),
|
||||||
SeccompRules: make([]seccomp.NativeRule, 0),
|
SeccompRules: make([]seccomp.NativeRule, 0),
|
||||||
SeccompDisable: true,
|
SeccompDisable: true,
|
||||||
ParentPerm: 0750,
|
ParentPerm: 0750,
|
||||||
@@ -1927,8 +1927,8 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
/* end apply */
|
/* end apply */
|
||||||
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
||||||
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, syscall.EINTR),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, syscall.EINTR),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, nil),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, nil),
|
||||||
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
||||||
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil),
|
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil),
|
||||||
call("fchdir", stub.ExpectArgs{1 << 35}, nil, nil),
|
call("fchdir", stub.ExpectArgs{1 << 35}, nil, nil),
|
||||||
@@ -2004,7 +2004,7 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
Uid: 1 << 24,
|
Uid: 1 << 24,
|
||||||
Gid: 1 << 47,
|
Gid: 1 << 47,
|
||||||
Hostname: "hakurei-check",
|
Hostname: "hakurei-check",
|
||||||
Ops: new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), bits.BindDevice).Proc(check.MustAbs("/proc/")),
|
Ops: new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), comp.BindDevice).Proc(check.MustAbs("/proc/")),
|
||||||
SeccompRules: make([]seccomp.NativeRule, 0),
|
SeccompRules: make([]seccomp.NativeRule, 0),
|
||||||
SeccompDisable: true,
|
SeccompDisable: true,
|
||||||
ParentPerm: 0750,
|
ParentPerm: 0750,
|
||||||
@@ -2041,8 +2041,8 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
/* end apply */
|
/* end apply */
|
||||||
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
||||||
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, syscall.EINTR),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, syscall.EINTR),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, nil),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, nil),
|
||||||
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
||||||
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil),
|
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil),
|
||||||
call("fchdir", stub.ExpectArgs{1 << 35}, nil, nil),
|
call("fchdir", stub.ExpectArgs{1 << 35}, nil, nil),
|
||||||
@@ -2106,7 +2106,7 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
Uid: 1 << 24,
|
Uid: 1 << 24,
|
||||||
Gid: 1 << 47,
|
Gid: 1 << 47,
|
||||||
Hostname: "hakurei-check",
|
Hostname: "hakurei-check",
|
||||||
Ops: new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), bits.BindDevice).Proc(check.MustAbs("/proc/")),
|
Ops: new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), comp.BindDevice).Proc(check.MustAbs("/proc/")),
|
||||||
SeccompRules: make([]seccomp.NativeRule, 0),
|
SeccompRules: make([]seccomp.NativeRule, 0),
|
||||||
SeccompDisable: true,
|
SeccompDisable: true,
|
||||||
ParentPerm: 0750,
|
ParentPerm: 0750,
|
||||||
@@ -2143,8 +2143,8 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
/* end apply */
|
/* end apply */
|
||||||
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
||||||
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, syscall.EINTR),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, syscall.EINTR),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, nil),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, nil),
|
||||||
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
||||||
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil),
|
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil),
|
||||||
call("fchdir", stub.ExpectArgs{1 << 35}, nil, nil),
|
call("fchdir", stub.ExpectArgs{1 << 35}, nil, nil),
|
||||||
@@ -2199,7 +2199,7 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
Uid: 1 << 24,
|
Uid: 1 << 24,
|
||||||
Gid: 1 << 47,
|
Gid: 1 << 47,
|
||||||
Hostname: "hakurei-check",
|
Hostname: "hakurei-check",
|
||||||
Ops: new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), bits.BindDevice).Proc(check.MustAbs("/proc/")),
|
Ops: new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), comp.BindDevice).Proc(check.MustAbs("/proc/")),
|
||||||
SeccompRules: make([]seccomp.NativeRule, 0),
|
SeccompRules: make([]seccomp.NativeRule, 0),
|
||||||
SeccompDisable: true,
|
SeccompDisable: true,
|
||||||
ParentPerm: 0750,
|
ParentPerm: 0750,
|
||||||
@@ -2236,8 +2236,8 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
/* end apply */
|
/* end apply */
|
||||||
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
||||||
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, syscall.EINTR),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, syscall.EINTR),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, nil),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, nil),
|
||||||
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
||||||
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil),
|
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil),
|
||||||
call("fchdir", stub.ExpectArgs{1 << 35}, nil, nil),
|
call("fchdir", stub.ExpectArgs{1 << 35}, nil, nil),
|
||||||
@@ -2294,7 +2294,7 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
Uid: 1 << 24,
|
Uid: 1 << 24,
|
||||||
Gid: 1 << 47,
|
Gid: 1 << 47,
|
||||||
Hostname: "hakurei-check",
|
Hostname: "hakurei-check",
|
||||||
Ops: new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), bits.BindDevice).Proc(check.MustAbs("/proc/")),
|
Ops: new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), comp.BindDevice).Proc(check.MustAbs("/proc/")),
|
||||||
SeccompRules: make([]seccomp.NativeRule, 0),
|
SeccompRules: make([]seccomp.NativeRule, 0),
|
||||||
SeccompDisable: true,
|
SeccompDisable: true,
|
||||||
ParentPerm: 0750,
|
ParentPerm: 0750,
|
||||||
@@ -2331,8 +2331,8 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
/* end apply */
|
/* end apply */
|
||||||
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
||||||
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, syscall.EINTR),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, syscall.EINTR),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, nil),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, nil),
|
||||||
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
||||||
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil),
|
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil),
|
||||||
call("fchdir", stub.ExpectArgs{1 << 35}, nil, nil),
|
call("fchdir", stub.ExpectArgs{1 << 35}, nil, nil),
|
||||||
@@ -2396,7 +2396,7 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
Uid: 1 << 24,
|
Uid: 1 << 24,
|
||||||
Gid: 1 << 47,
|
Gid: 1 << 47,
|
||||||
Hostname: "hakurei-check",
|
Hostname: "hakurei-check",
|
||||||
Ops: new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), bits.BindDevice).Proc(check.MustAbs("/proc/")),
|
Ops: new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), comp.BindDevice).Proc(check.MustAbs("/proc/")),
|
||||||
SeccompRules: make([]seccomp.NativeRule, 0),
|
SeccompRules: make([]seccomp.NativeRule, 0),
|
||||||
SeccompDisable: true,
|
SeccompDisable: true,
|
||||||
ParentPerm: 0750,
|
ParentPerm: 0750,
|
||||||
@@ -2433,8 +2433,8 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
/* end apply */
|
/* end apply */
|
||||||
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
||||||
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, syscall.EINTR),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, syscall.EINTR),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, nil),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, nil),
|
||||||
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
||||||
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil),
|
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil),
|
||||||
call("fchdir", stub.ExpectArgs{1 << 35}, nil, nil),
|
call("fchdir", stub.ExpectArgs{1 << 35}, nil, nil),
|
||||||
@@ -2534,9 +2534,9 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
Uid: 1 << 32,
|
Uid: 1 << 32,
|
||||||
Gid: 1 << 31,
|
Gid: 1 << 31,
|
||||||
Hostname: "hakurei-check",
|
Hostname: "hakurei-check",
|
||||||
Ops: new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), bits.BindDevice).Proc(check.MustAbs("/proc/")),
|
Ops: new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), comp.BindDevice).Proc(check.MustAbs("/proc/")),
|
||||||
SeccompRules: make([]seccomp.NativeRule, 0),
|
SeccompRules: make([]seccomp.NativeRule, 0),
|
||||||
SeccompPresets: bits.PresetStrict,
|
SeccompPresets: comp.PresetStrict,
|
||||||
RetainSession: true,
|
RetainSession: true,
|
||||||
Privileged: true,
|
Privileged: true,
|
||||||
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(0), nil),
|
}, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(0), nil),
|
||||||
@@ -2572,8 +2572,8 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
/* end apply */
|
/* end apply */
|
||||||
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil),
|
||||||
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
call("unmount", stub.ExpectArgs{"host", 2}, nil, nil),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, syscall.EINTR),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, syscall.EINTR),
|
||||||
call("open", stub.ExpectArgs{"/", 0x10000, uint32(0)}, 1<<35, nil),
|
call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, nil),
|
||||||
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil),
|
||||||
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil),
|
call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil),
|
||||||
call("fchdir", stub.ExpectArgs{1 << 35}, nil, nil),
|
call("fchdir", stub.ExpectArgs{1 << 35}, nil, nil),
|
||||||
@@ -2623,7 +2623,7 @@ func TestInitEntrypoint(t *testing.T) {
|
|||||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x28)}, nil, nil),
|
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x28)}, nil, nil),
|
||||||
call("capAmbientRaise", stub.ExpectArgs{uintptr(0x15)}, nil, nil),
|
call("capAmbientRaise", stub.ExpectArgs{uintptr(0x15)}, nil, nil),
|
||||||
call("capset", stub.ExpectArgs{&capHeader{_LINUX_CAPABILITY_VERSION_3, 0}, &[2]capData{{0, 0x200000, 0x200000}, {0, 0, 0}}}, nil, nil),
|
call("capset", stub.ExpectArgs{&capHeader{_LINUX_CAPABILITY_VERSION_3, 0}, &[2]capData{{0, 0x200000, 0x200000}, {0, 0, 0}}}, nil, nil),
|
||||||
call("verbosef", stub.ExpectArgs{"resolving presets %#x", []any{bits.FilterPreset(0xf)}}, nil, nil),
|
call("verbosef", stub.ExpectArgs{"resolving presets %#x", []any{comp.FilterPreset(0xf)}}, nil, nil),
|
||||||
call("seccompLoad", stub.ExpectArgs{seccomp.Preset(0xf, 0), seccomp.ExportFlag(0)}, nil, nil),
|
call("seccompLoad", stub.ExpectArgs{seccomp.Preset(0xf, 0), seccomp.ExportFlag(0)}, nil, nil),
|
||||||
call("verbosef", stub.ExpectArgs{"%d filter rules loaded", []any{73}}, nil, nil),
|
call("verbosef", stub.ExpectArgs{"%d filter rules loaded", []any{73}}, nil, nil),
|
||||||
call("newFile", stub.ExpectArgs{uintptr(10), "extra file 0"}, (*os.File)(nil), nil),
|
call("newFile", stub.ExpectArgs{uintptr(10), "extra file 0"}, (*os.File)(nil), nil),
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"hakurei.app/container/bits"
|
|
||||||
"hakurei.app/container/check"
|
"hakurei.app/container/check"
|
||||||
|
"hakurei.app/container/comp"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() { gob.Register(new(BindMountOp)) }
|
func init() { gob.Register(new(BindMountOp)) }
|
||||||
@@ -29,18 +29,18 @@ type BindMountOp struct {
|
|||||||
func (b *BindMountOp) Valid() bool {
|
func (b *BindMountOp) Valid() bool {
|
||||||
return b != nil &&
|
return b != nil &&
|
||||||
b.Source != nil && b.Target != nil &&
|
b.Source != nil && b.Target != nil &&
|
||||||
b.Flags&(bits.BindOptional|bits.BindEnsure) != (bits.BindOptional|bits.BindEnsure)
|
b.Flags&(comp.BindOptional|comp.BindEnsure) != (comp.BindOptional|comp.BindEnsure)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *BindMountOp) early(_ *setupState, k syscallDispatcher) error {
|
func (b *BindMountOp) early(_ *setupState, k syscallDispatcher) error {
|
||||||
if b.Flags&bits.BindEnsure != 0 {
|
if b.Flags&comp.BindEnsure != 0 {
|
||||||
if err := k.mkdirAll(b.Source.String(), 0700); err != nil {
|
if err := k.mkdirAll(b.Source.String(), 0700); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if pathname, err := k.evalSymlinks(b.Source.String()); err != nil {
|
if pathname, err := k.evalSymlinks(b.Source.String()); err != nil {
|
||||||
if os.IsNotExist(err) && b.Flags&bits.BindOptional != 0 {
|
if os.IsNotExist(err) && b.Flags&comp.BindOptional != 0 {
|
||||||
// leave sourceFinal as nil
|
// leave sourceFinal as nil
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -53,7 +53,7 @@ func (b *BindMountOp) early(_ *setupState, k syscallDispatcher) error {
|
|||||||
|
|
||||||
func (b *BindMountOp) apply(state *setupState, k syscallDispatcher) error {
|
func (b *BindMountOp) apply(state *setupState, k syscallDispatcher) error {
|
||||||
if b.sourceFinal == nil {
|
if b.sourceFinal == nil {
|
||||||
if b.Flags&bits.BindOptional == 0 {
|
if b.Flags&comp.BindOptional == 0 {
|
||||||
// unreachable
|
// unreachable
|
||||||
return OpStateError("bind")
|
return OpStateError("bind")
|
||||||
}
|
}
|
||||||
@@ -76,10 +76,10 @@ func (b *BindMountOp) apply(state *setupState, k syscallDispatcher) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var flags uintptr = syscall.MS_REC
|
var flags uintptr = syscall.MS_REC
|
||||||
if b.Flags&bits.BindWritable == 0 {
|
if b.Flags&comp.BindWritable == 0 {
|
||||||
flags |= syscall.MS_RDONLY
|
flags |= syscall.MS_RDONLY
|
||||||
}
|
}
|
||||||
if b.Flags&bits.BindDevice == 0 {
|
if b.Flags&comp.BindDevice == 0 {
|
||||||
flags |= syscall.MS_NODEV
|
flags |= syscall.MS_NODEV
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"hakurei.app/container/bits"
|
|
||||||
"hakurei.app/container/check"
|
"hakurei.app/container/check"
|
||||||
|
"hakurei.app/container/comp"
|
||||||
"hakurei.app/container/stub"
|
"hakurei.app/container/stub"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -25,7 +25,7 @@ func TestBindMountOp(t *testing.T) {
|
|||||||
{"skip optional", new(Params), &BindMountOp{
|
{"skip optional", new(Params), &BindMountOp{
|
||||||
Source: check.MustAbs("/bin/"),
|
Source: check.MustAbs("/bin/"),
|
||||||
Target: check.MustAbs("/bin/"),
|
Target: check.MustAbs("/bin/"),
|
||||||
Flags: bits.BindOptional,
|
Flags: comp.BindOptional,
|
||||||
}, []stub.Call{
|
}, []stub.Call{
|
||||||
call("evalSymlinks", stub.ExpectArgs{"/bin/"}, "", syscall.ENOENT),
|
call("evalSymlinks", stub.ExpectArgs{"/bin/"}, "", syscall.ENOENT),
|
||||||
}, nil, nil, nil},
|
}, nil, nil, nil},
|
||||||
@@ -33,7 +33,7 @@ func TestBindMountOp(t *testing.T) {
|
|||||||
{"success optional", new(Params), &BindMountOp{
|
{"success optional", new(Params), &BindMountOp{
|
||||||
Source: check.MustAbs("/bin/"),
|
Source: check.MustAbs("/bin/"),
|
||||||
Target: check.MustAbs("/bin/"),
|
Target: check.MustAbs("/bin/"),
|
||||||
Flags: bits.BindOptional,
|
Flags: comp.BindOptional,
|
||||||
}, []stub.Call{
|
}, []stub.Call{
|
||||||
call("evalSymlinks", stub.ExpectArgs{"/bin/"}, "/usr/bin", nil),
|
call("evalSymlinks", stub.ExpectArgs{"/bin/"}, "/usr/bin", nil),
|
||||||
}, nil, []stub.Call{
|
}, nil, []stub.Call{
|
||||||
@@ -46,7 +46,7 @@ func TestBindMountOp(t *testing.T) {
|
|||||||
{"ensureFile device", new(Params), &BindMountOp{
|
{"ensureFile device", new(Params), &BindMountOp{
|
||||||
Source: check.MustAbs("/dev/null"),
|
Source: check.MustAbs("/dev/null"),
|
||||||
Target: check.MustAbs("/dev/null"),
|
Target: check.MustAbs("/dev/null"),
|
||||||
Flags: bits.BindWritable | bits.BindDevice,
|
Flags: comp.BindWritable | comp.BindDevice,
|
||||||
}, []stub.Call{
|
}, []stub.Call{
|
||||||
call("evalSymlinks", stub.ExpectArgs{"/dev/null"}, "/dev/null", nil),
|
call("evalSymlinks", stub.ExpectArgs{"/dev/null"}, "/dev/null", nil),
|
||||||
}, nil, []stub.Call{
|
}, nil, []stub.Call{
|
||||||
@@ -57,7 +57,7 @@ func TestBindMountOp(t *testing.T) {
|
|||||||
{"mkdirAll ensure", new(Params), &BindMountOp{
|
{"mkdirAll ensure", new(Params), &BindMountOp{
|
||||||
Source: check.MustAbs("/bin/"),
|
Source: check.MustAbs("/bin/"),
|
||||||
Target: check.MustAbs("/bin/"),
|
Target: check.MustAbs("/bin/"),
|
||||||
Flags: bits.BindEnsure,
|
Flags: comp.BindEnsure,
|
||||||
}, []stub.Call{
|
}, []stub.Call{
|
||||||
call("mkdirAll", stub.ExpectArgs{"/bin/", os.FileMode(0700)}, nil, stub.UniqueError(4)),
|
call("mkdirAll", stub.ExpectArgs{"/bin/", os.FileMode(0700)}, nil, stub.UniqueError(4)),
|
||||||
}, stub.UniqueError(4), nil, nil},
|
}, stub.UniqueError(4), nil, nil},
|
||||||
@@ -65,7 +65,7 @@ func TestBindMountOp(t *testing.T) {
|
|||||||
{"success ensure", new(Params), &BindMountOp{
|
{"success ensure", new(Params), &BindMountOp{
|
||||||
Source: check.MustAbs("/bin/"),
|
Source: check.MustAbs("/bin/"),
|
||||||
Target: check.MustAbs("/usr/bin/"),
|
Target: check.MustAbs("/usr/bin/"),
|
||||||
Flags: bits.BindEnsure,
|
Flags: comp.BindEnsure,
|
||||||
}, []stub.Call{
|
}, []stub.Call{
|
||||||
call("mkdirAll", stub.ExpectArgs{"/bin/", os.FileMode(0700)}, nil, nil),
|
call("mkdirAll", stub.ExpectArgs{"/bin/", os.FileMode(0700)}, nil, nil),
|
||||||
call("evalSymlinks", stub.ExpectArgs{"/bin/"}, "/usr/bin", nil),
|
call("evalSymlinks", stub.ExpectArgs{"/bin/"}, "/usr/bin", nil),
|
||||||
@@ -79,7 +79,7 @@ func TestBindMountOp(t *testing.T) {
|
|||||||
{"success device ro", new(Params), &BindMountOp{
|
{"success device ro", new(Params), &BindMountOp{
|
||||||
Source: check.MustAbs("/dev/null"),
|
Source: check.MustAbs("/dev/null"),
|
||||||
Target: check.MustAbs("/dev/null"),
|
Target: check.MustAbs("/dev/null"),
|
||||||
Flags: bits.BindDevice,
|
Flags: comp.BindDevice,
|
||||||
}, []stub.Call{
|
}, []stub.Call{
|
||||||
call("evalSymlinks", stub.ExpectArgs{"/dev/null"}, "/dev/null", nil),
|
call("evalSymlinks", stub.ExpectArgs{"/dev/null"}, "/dev/null", nil),
|
||||||
}, nil, []stub.Call{
|
}, nil, []stub.Call{
|
||||||
@@ -92,7 +92,7 @@ func TestBindMountOp(t *testing.T) {
|
|||||||
{"success device", new(Params), &BindMountOp{
|
{"success device", new(Params), &BindMountOp{
|
||||||
Source: check.MustAbs("/dev/null"),
|
Source: check.MustAbs("/dev/null"),
|
||||||
Target: check.MustAbs("/dev/null"),
|
Target: check.MustAbs("/dev/null"),
|
||||||
Flags: bits.BindWritable | bits.BindDevice,
|
Flags: comp.BindWritable | comp.BindDevice,
|
||||||
}, []stub.Call{
|
}, []stub.Call{
|
||||||
call("evalSymlinks", stub.ExpectArgs{"/dev/null"}, "/dev/null", nil),
|
call("evalSymlinks", stub.ExpectArgs{"/dev/null"}, "/dev/null", nil),
|
||||||
}, nil, []stub.Call{
|
}, nil, []stub.Call{
|
||||||
@@ -182,7 +182,7 @@ func TestBindMountOp(t *testing.T) {
|
|||||||
{"zero", new(BindMountOp), false},
|
{"zero", new(BindMountOp), false},
|
||||||
{"nil source", &BindMountOp{Target: check.MustAbs("/")}, false},
|
{"nil source", &BindMountOp{Target: check.MustAbs("/")}, false},
|
||||||
{"nil target", &BindMountOp{Source: check.MustAbs("/")}, false},
|
{"nil target", &BindMountOp{Source: check.MustAbs("/")}, false},
|
||||||
{"flag optional ensure", &BindMountOp{Source: check.MustAbs("/"), Target: check.MustAbs("/"), Flags: bits.BindOptional | bits.BindEnsure}, false},
|
{"flag optional ensure", &BindMountOp{Source: check.MustAbs("/"), Target: check.MustAbs("/"), Flags: comp.BindOptional | comp.BindEnsure}, false},
|
||||||
{"valid", &BindMountOp{Source: check.MustAbs("/"), Target: check.MustAbs("/")}, true},
|
{"valid", &BindMountOp{Source: check.MustAbs("/"), Target: check.MustAbs("/")}, true},
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -217,7 +217,7 @@ func TestBindMountOp(t *testing.T) {
|
|||||||
}, &BindMountOp{
|
}, &BindMountOp{
|
||||||
Source: check.MustAbs("/etc/"),
|
Source: check.MustAbs("/etc/"),
|
||||||
Target: check.MustAbs("/etc/.host/048090b6ed8f9ebb10e275ff5d8c0659"),
|
Target: check.MustAbs("/etc/.host/048090b6ed8f9ebb10e275ff5d8c0659"),
|
||||||
Flags: bits.BindOptional,
|
Flags: comp.BindOptional,
|
||||||
}, false},
|
}, false},
|
||||||
|
|
||||||
{"source differs", &BindMountOp{
|
{"source differs", &BindMountOp{
|
||||||
@@ -256,7 +256,7 @@ func TestBindMountOp(t *testing.T) {
|
|||||||
{"hostdev", &BindMountOp{
|
{"hostdev", &BindMountOp{
|
||||||
Source: check.MustAbs("/dev/"),
|
Source: check.MustAbs("/dev/"),
|
||||||
Target: check.MustAbs("/dev/"),
|
Target: check.MustAbs("/dev/"),
|
||||||
Flags: bits.BindWritable | bits.BindDevice,
|
Flags: comp.BindWritable | comp.BindDevice,
|
||||||
}, "mounting", `"/dev/" flags 0x6`},
|
}, "mounting", `"/dev/" flags 0x6`},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package seccomp_test
|
package seccomp_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
. "hakurei.app/container/bits"
|
. "hakurei.app/container/comp"
|
||||||
. "hakurei.app/container/seccomp"
|
. "hakurei.app/container/seccomp"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package seccomp_test
|
package seccomp_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
. "hakurei.app/container/bits"
|
. "hakurei.app/container/comp"
|
||||||
. "hakurei.app/container/seccomp"
|
. "hakurei.app/container/seccomp"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -4,14 +4,14 @@ import (
|
|||||||
"crypto/sha512"
|
"crypto/sha512"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
|
||||||
"hakurei.app/container/bits"
|
"hakurei.app/container/comp"
|
||||||
"hakurei.app/container/seccomp"
|
"hakurei.app/container/seccomp"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
bpfPreset = struct {
|
bpfPreset = struct {
|
||||||
seccomp.ExportFlag
|
seccomp.ExportFlag
|
||||||
bits.FilterPreset
|
comp.FilterPreset
|
||||||
}
|
}
|
||||||
bpfLookup map[bpfPreset][sha512.Size]byte
|
bpfLookup map[bpfPreset][sha512.Size]byte
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
. "hakurei.app/container/bits"
|
. "hakurei.app/container/comp"
|
||||||
. "hakurei.app/container/seccomp"
|
. "hakurei.app/container/seccomp"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -5,32 +5,32 @@ package seccomp
|
|||||||
import (
|
import (
|
||||||
. "syscall"
|
. "syscall"
|
||||||
|
|
||||||
"hakurei.app/container/bits"
|
"hakurei.app/container/comp"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Preset(presets bits.FilterPreset, flags ExportFlag) (rules []NativeRule) {
|
func Preset(presets comp.FilterPreset, flags ExportFlag) (rules []NativeRule) {
|
||||||
allowedPersonality := PersonaLinux
|
allowedPersonality := PersonaLinux
|
||||||
if presets&bits.PresetLinux32 != 0 {
|
if presets&comp.PresetLinux32 != 0 {
|
||||||
allowedPersonality = PersonaLinux32
|
allowedPersonality = PersonaLinux32
|
||||||
}
|
}
|
||||||
presetDevelFinal := presetDevel(ScmpDatum(allowedPersonality))
|
presetDevelFinal := presetDevel(ScmpDatum(allowedPersonality))
|
||||||
|
|
||||||
l := len(presetCommon)
|
l := len(presetCommon)
|
||||||
if presets&bits.PresetDenyNS != 0 {
|
if presets&comp.PresetDenyNS != 0 {
|
||||||
l += len(presetNamespace)
|
l += len(presetNamespace)
|
||||||
}
|
}
|
||||||
if presets&bits.PresetDenyTTY != 0 {
|
if presets&comp.PresetDenyTTY != 0 {
|
||||||
l += len(presetTTY)
|
l += len(presetTTY)
|
||||||
}
|
}
|
||||||
if presets&bits.PresetDenyDevel != 0 {
|
if presets&comp.PresetDenyDevel != 0 {
|
||||||
l += len(presetDevelFinal)
|
l += len(presetDevelFinal)
|
||||||
}
|
}
|
||||||
if flags&AllowMultiarch == 0 {
|
if flags&AllowMultiarch == 0 {
|
||||||
l += len(presetEmu)
|
l += len(presetEmu)
|
||||||
}
|
}
|
||||||
if presets&bits.PresetExt != 0 {
|
if presets&comp.PresetExt != 0 {
|
||||||
l += len(presetCommonExt)
|
l += len(presetCommonExt)
|
||||||
if presets&bits.PresetDenyNS != 0 {
|
if presets&comp.PresetDenyNS != 0 {
|
||||||
l += len(presetNamespaceExt)
|
l += len(presetNamespaceExt)
|
||||||
}
|
}
|
||||||
if flags&AllowMultiarch == 0 {
|
if flags&AllowMultiarch == 0 {
|
||||||
@@ -40,21 +40,21 @@ func Preset(presets bits.FilterPreset, flags ExportFlag) (rules []NativeRule) {
|
|||||||
|
|
||||||
rules = make([]NativeRule, 0, l)
|
rules = make([]NativeRule, 0, l)
|
||||||
rules = append(rules, presetCommon...)
|
rules = append(rules, presetCommon...)
|
||||||
if presets&bits.PresetDenyNS != 0 {
|
if presets&comp.PresetDenyNS != 0 {
|
||||||
rules = append(rules, presetNamespace...)
|
rules = append(rules, presetNamespace...)
|
||||||
}
|
}
|
||||||
if presets&bits.PresetDenyTTY != 0 {
|
if presets&comp.PresetDenyTTY != 0 {
|
||||||
rules = append(rules, presetTTY...)
|
rules = append(rules, presetTTY...)
|
||||||
}
|
}
|
||||||
if presets&bits.PresetDenyDevel != 0 {
|
if presets&comp.PresetDenyDevel != 0 {
|
||||||
rules = append(rules, presetDevelFinal...)
|
rules = append(rules, presetDevelFinal...)
|
||||||
}
|
}
|
||||||
if flags&AllowMultiarch == 0 {
|
if flags&AllowMultiarch == 0 {
|
||||||
rules = append(rules, presetEmu...)
|
rules = append(rules, presetEmu...)
|
||||||
}
|
}
|
||||||
if presets&bits.PresetExt != 0 {
|
if presets&comp.PresetExt != 0 {
|
||||||
rules = append(rules, presetCommonExt...)
|
rules = append(rules, presetCommonExt...)
|
||||||
if presets&bits.PresetDenyNS != 0 {
|
if presets&comp.PresetDenyNS != 0 {
|
||||||
rules = append(rules, presetNamespaceExt...)
|
rules = append(rules, presetNamespaceExt...)
|
||||||
}
|
}
|
||||||
if flags&AllowMultiarch == 0 {
|
if flags&AllowMultiarch == 0 {
|
||||||
|
|||||||
@@ -1,50 +1,41 @@
|
|||||||
package container
|
package container
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"syscall"
|
. "syscall"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SetPtracer allows processes to ptrace(2) the calling process.
|
// Prctl manipulates various aspects of the behavior of the calling thread or process.
|
||||||
func SetPtracer(pid uintptr) error {
|
func Prctl(op, arg2, arg3 uintptr) error {
|
||||||
_, _, errno := syscall.Syscall(syscall.SYS_PRCTL, syscall.PR_SET_PTRACER, pid, 0)
|
r, _, errno := Syscall(SYS_PRCTL, op, arg2, arg3)
|
||||||
if errno == 0 {
|
if r < 0 {
|
||||||
return nil
|
return errno
|
||||||
}
|
}
|
||||||
return errno
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetPtracer allows processes to ptrace(2) the calling process.
|
||||||
|
func SetPtracer(pid uintptr) error { return Prctl(PR_SET_PTRACER, pid, 0) }
|
||||||
|
|
||||||
|
// linux/sched/coredump.h
|
||||||
const (
|
const (
|
||||||
SUID_DUMP_DISABLE = iota
|
SUID_DUMP_DISABLE = iota
|
||||||
SUID_DUMP_USER
|
SUID_DUMP_USER
|
||||||
)
|
)
|
||||||
|
|
||||||
// SetDumpable sets the "dumpable" attribute of the calling process.
|
// SetDumpable sets the "dumpable" attribute of the calling process.
|
||||||
func SetDumpable(dumpable uintptr) error {
|
func SetDumpable(dumpable uintptr) error { return Prctl(PR_SET_DUMPABLE, dumpable, 0) }
|
||||||
// linux/sched/coredump.h
|
|
||||||
if _, _, errno := syscall.Syscall(syscall.SYS_PRCTL, syscall.PR_SET_DUMPABLE, dumpable, 0); errno != 0 {
|
|
||||||
return errno
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetNoNewPrivs sets the calling thread's no_new_privs attribute.
|
// SetNoNewPrivs sets the calling thread's no_new_privs attribute.
|
||||||
func SetNoNewPrivs() error {
|
func SetNoNewPrivs() error { return Prctl(PR_SET_NO_NEW_PRIVS, 1, 0) }
|
||||||
_, _, errno := syscall.Syscall(syscall.SYS_PRCTL, PR_SET_NO_NEW_PRIVS, 1, 0)
|
|
||||||
if errno == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return errno
|
|
||||||
}
|
|
||||||
|
|
||||||
// Isatty tests whether a file descriptor refers to a terminal.
|
// Isatty tests whether a file descriptor refers to a terminal.
|
||||||
func Isatty(fd int) bool {
|
func Isatty(fd int) bool {
|
||||||
var buf [8]byte
|
var buf [8]byte
|
||||||
r, _, _ := syscall.Syscall(
|
r, _, _ := Syscall(
|
||||||
syscall.SYS_IOCTL,
|
SYS_IOCTL,
|
||||||
uintptr(fd),
|
uintptr(fd),
|
||||||
syscall.TIOCGWINSZ,
|
TIOCGWINSZ,
|
||||||
uintptr(unsafe.Pointer(&buf[0])),
|
uintptr(unsafe.Pointer(&buf[0])),
|
||||||
)
|
)
|
||||||
return r == 0
|
return r == 0
|
||||||
@@ -60,7 +51,7 @@ func Isatty(fd int) bool {
|
|||||||
func IgnoringEINTR(fn func() error) error {
|
func IgnoringEINTR(fn func() error) error {
|
||||||
for {
|
for {
|
||||||
err := fn()
|
err := fn()
|
||||||
if err != syscall.EINTR {
|
if err != EINTR {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
8
dist/release.sh
vendored
8
dist/release.sh
vendored
@@ -10,10 +10,10 @@ cp -rv "dist/comp" "${out}"
|
|||||||
|
|
||||||
go generate ./...
|
go generate ./...
|
||||||
go build -trimpath -v -o "${out}/bin/" -ldflags "-s -w -buildid= -extldflags '-static'
|
go build -trimpath -v -o "${out}/bin/" -ldflags "-s -w -buildid= -extldflags '-static'
|
||||||
-X hakurei.app/internal.version=${VERSION}
|
-X hakurei.app/internal.buildVersion=${VERSION}
|
||||||
-X hakurei.app/internal.hmain=/usr/bin/hakurei
|
-X hakurei.app/internal.hakureiPath=/usr/bin/hakurei
|
||||||
-X hakurei.app/internal.hsu=/usr/bin/hsu
|
-X hakurei.app/internal.hsuPath=/usr/bin/hsu
|
||||||
-X main.hmain=/usr/bin/hakurei" ./...
|
-X main.hakureiPath=/usr/bin/hakurei" ./...
|
||||||
|
|
||||||
rm -f "./${out}.tar.gz" && tar -C dist -czf "${out}.tar.gz" "${pname}"
|
rm -f "./${out}.tar.gz" && tar -C dist -czf "${out}.tar.gz" "${pname}"
|
||||||
rm -rf "./${out}"
|
rm -rf "./${out}"
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package hst
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -38,9 +39,12 @@ const (
|
|||||||
ExitRequest = 254
|
ExitRequest = 254
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Flags are options held by [ContainerConfig].
|
||||||
|
type Flags uintptr
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// FMultiarch unblocks syscalls required for multiarch to work on applicable targets.
|
// FMultiarch unblocks syscalls required for multiarch to work on applicable targets.
|
||||||
FMultiarch uintptr = 1 << iota
|
FMultiarch Flags = 1 << iota
|
||||||
|
|
||||||
// FSeccompCompat changes emitted seccomp filter programs to be identical to that of Flatpak.
|
// FSeccompCompat changes emitted seccomp filter programs to be identical to that of Flatpak.
|
||||||
FSeccompCompat
|
FSeccompCompat
|
||||||
@@ -74,6 +78,45 @@ const (
|
|||||||
FAll = fMax - 1
|
FAll = fMax - 1
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func (flags Flags) String() string {
|
||||||
|
switch flags {
|
||||||
|
case FMultiarch:
|
||||||
|
return "multiarch"
|
||||||
|
case FSeccompCompat:
|
||||||
|
return "compat"
|
||||||
|
case FDevel:
|
||||||
|
return "devel"
|
||||||
|
case FUserns:
|
||||||
|
return "userns"
|
||||||
|
case FHostNet:
|
||||||
|
return "net"
|
||||||
|
case FHostAbstract:
|
||||||
|
return "abstract"
|
||||||
|
case FTty:
|
||||||
|
return "tty"
|
||||||
|
case FMapRealUID:
|
||||||
|
return "mapuid"
|
||||||
|
case FDevice:
|
||||||
|
return "device"
|
||||||
|
case FShareRuntime:
|
||||||
|
return "runtime"
|
||||||
|
case FShareTmpdir:
|
||||||
|
return "tmpdir"
|
||||||
|
|
||||||
|
default:
|
||||||
|
s := make([]string, 0, 1<<4)
|
||||||
|
for f := Flags(1); f < fMax; f <<= 1 {
|
||||||
|
if flags&f != 0 {
|
||||||
|
s = append(s, f.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(s) == 0 {
|
||||||
|
return "none"
|
||||||
|
}
|
||||||
|
return strings.Join(s, ", ")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ContainerConfig describes the container configuration to be applied to an underlying [container].
|
// ContainerConfig describes the container configuration to be applied to an underlying [container].
|
||||||
type ContainerConfig struct {
|
type ContainerConfig struct {
|
||||||
// Container UTS namespace hostname.
|
// Container UTS namespace hostname.
|
||||||
@@ -106,7 +149,7 @@ type ContainerConfig struct {
|
|||||||
Args []string `json:"args"`
|
Args []string `json:"args"`
|
||||||
|
|
||||||
// Flags holds boolean options of [ContainerConfig].
|
// Flags holds boolean options of [ContainerConfig].
|
||||||
Flags uintptr `json:"-"`
|
Flags Flags `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ContainerConfigF is [ContainerConfig] stripped of its methods.
|
// ContainerConfigF is [ContainerConfig] stripped of its methods.
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package hst_test
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
|
"math"
|
||||||
"reflect"
|
"reflect"
|
||||||
"syscall"
|
"syscall"
|
||||||
"testing"
|
"testing"
|
||||||
@@ -10,6 +11,30 @@ import (
|
|||||||
"hakurei.app/hst"
|
"hakurei.app/hst"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func TestFlagsString(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
flags hst.Flags
|
||||||
|
want string
|
||||||
|
}{
|
||||||
|
{"none", 0, "none"},
|
||||||
|
{"none high", hst.FAll + 1, "none"},
|
||||||
|
{"all", hst.FAll, "multiarch, compat, devel, userns, net, abstract, tty, mapuid, device, runtime, tmpdir"},
|
||||||
|
{"all high", math.MaxUint, "multiarch, compat, devel, userns, net, abstract, tty, mapuid, device, runtime, tmpdir"},
|
||||||
|
}
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
if got := tc.flags.String(); got != tc.want {
|
||||||
|
t.Errorf("String(%#b): %q, want %q", tc.flags, got, tc.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestContainerConfig(t *testing.T) {
|
func TestContainerConfig(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import (
|
|||||||
"encoding/gob"
|
"encoding/gob"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"hakurei.app/container/bits"
|
|
||||||
"hakurei.app/container/check"
|
"hakurei.app/container/check"
|
||||||
|
"hakurei.app/container/comp"
|
||||||
"hakurei.app/container/fhs"
|
"hakurei.app/container/fhs"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -97,16 +97,16 @@ func (b *FSBind) Apply(z *ApplyState) {
|
|||||||
}
|
}
|
||||||
var flags int
|
var flags int
|
||||||
if b.Write {
|
if b.Write {
|
||||||
flags |= bits.BindWritable
|
flags |= comp.BindWritable
|
||||||
}
|
}
|
||||||
if b.Device {
|
if b.Device {
|
||||||
flags |= bits.BindDevice | bits.BindWritable
|
flags |= comp.BindDevice | comp.BindWritable
|
||||||
}
|
}
|
||||||
if b.Ensure {
|
if b.Ensure {
|
||||||
flags |= bits.BindEnsure
|
flags |= comp.BindEnsure
|
||||||
}
|
}
|
||||||
if b.Optional {
|
if b.Optional {
|
||||||
flags |= bits.BindOptional
|
flags |= comp.BindOptional
|
||||||
}
|
}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"hakurei.app/container"
|
"hakurei.app/container"
|
||||||
"hakurei.app/container/bits"
|
"hakurei.app/container/comp"
|
||||||
"hakurei.app/hst"
|
"hakurei.app/hst"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -24,7 +24,7 @@ func TestFSBind(t *testing.T) {
|
|||||||
}, true, container.Ops{&container.BindMountOp{
|
}, true, container.Ops{&container.BindMountOp{
|
||||||
Source: m("/mnt/dev"),
|
Source: m("/mnt/dev"),
|
||||||
Target: m("/dev"),
|
Target: m("/dev"),
|
||||||
Flags: bits.BindWritable | bits.BindDevice | bits.BindOptional,
|
Flags: comp.BindWritable | comp.BindDevice | comp.BindOptional,
|
||||||
}}, m("/dev"), ms("/mnt/dev"),
|
}}, m("/dev"), ms("/mnt/dev"),
|
||||||
"d+/mnt/dev:/dev"},
|
"d+/mnt/dev:/dev"},
|
||||||
|
|
||||||
@@ -36,7 +36,7 @@ func TestFSBind(t *testing.T) {
|
|||||||
}, true, container.Ops{&container.BindMountOp{
|
}, true, container.Ops{&container.BindMountOp{
|
||||||
Source: m("/mnt/dev"),
|
Source: m("/mnt/dev"),
|
||||||
Target: m("/dev"),
|
Target: m("/dev"),
|
||||||
Flags: bits.BindWritable | bits.BindDevice | bits.BindEnsure,
|
Flags: comp.BindWritable | comp.BindDevice | comp.BindEnsure,
|
||||||
}}, m("/dev"), ms("/mnt/dev"),
|
}}, m("/dev"), ms("/mnt/dev"),
|
||||||
"d-/mnt/dev:/dev"},
|
"d-/mnt/dev:/dev"},
|
||||||
|
|
||||||
@@ -48,7 +48,7 @@ func TestFSBind(t *testing.T) {
|
|||||||
}, true, container.Ops{&container.BindMountOp{
|
}, true, container.Ops{&container.BindMountOp{
|
||||||
Source: m("/mnt/dev"),
|
Source: m("/mnt/dev"),
|
||||||
Target: m("/dev"),
|
Target: m("/dev"),
|
||||||
Flags: bits.BindWritable | bits.BindDevice,
|
Flags: comp.BindWritable | comp.BindDevice,
|
||||||
}}, m("/dev"), ms("/mnt/dev"),
|
}}, m("/dev"), ms("/mnt/dev"),
|
||||||
"d*/mnt/dev:/dev"},
|
"d*/mnt/dev:/dev"},
|
||||||
|
|
||||||
@@ -59,7 +59,7 @@ func TestFSBind(t *testing.T) {
|
|||||||
}, true, container.Ops{&container.BindMountOp{
|
}, true, container.Ops{&container.BindMountOp{
|
||||||
Source: m("/mnt/tmp"),
|
Source: m("/mnt/tmp"),
|
||||||
Target: m("/tmp"),
|
Target: m("/tmp"),
|
||||||
Flags: bits.BindWritable,
|
Flags: comp.BindWritable,
|
||||||
}}, m("/tmp"), ms("/mnt/tmp"),
|
}}, m("/tmp"), ms("/mnt/tmp"),
|
||||||
"w*/mnt/tmp:/tmp"},
|
"w*/mnt/tmp:/tmp"},
|
||||||
|
|
||||||
@@ -98,7 +98,7 @@ func TestFSBind(t *testing.T) {
|
|||||||
Special: true,
|
Special: true,
|
||||||
}, true, container.Ops{&container.AutoRootOp{
|
}, true, container.Ops{&container.AutoRootOp{
|
||||||
Host: m("/"),
|
Host: m("/"),
|
||||||
Flags: bits.BindWritable,
|
Flags: comp.BindWritable,
|
||||||
}}, m("/"), ms("/"), "autoroot:w"},
|
}}, m("/"), ms("/"), "autoroot:w"},
|
||||||
|
|
||||||
{"autoroot silly", &hst.FSBind{
|
{"autoroot silly", &hst.FSBind{
|
||||||
@@ -108,7 +108,7 @@ func TestFSBind(t *testing.T) {
|
|||||||
Special: true,
|
Special: true,
|
||||||
}, true, container.Ops{&container.AutoRootOp{
|
}, true, container.Ops{&container.AutoRootOp{
|
||||||
Host: m("/etc"),
|
Host: m("/etc"),
|
||||||
Flags: bits.BindWritable,
|
Flags: comp.BindWritable,
|
||||||
}}, m("/"), ms("/etc"), "autoroot:w:/etc"},
|
}}, m("/"), ms("/etc"), "autoroot:w:/etc"},
|
||||||
|
|
||||||
{"autoetc", &hst.FSBind{
|
{"autoetc", &hst.FSBind{
|
||||||
|
|||||||
@@ -52,7 +52,10 @@ type Paths struct {
|
|||||||
RunDirPath *check.Absolute `json:"run_dir_path"`
|
RunDirPath *check.Absolute `json:"run_dir_path"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Info holds basic system information collected from the implementation.
|
||||||
type Info struct {
|
type Info struct {
|
||||||
|
// Version is a hardcoded version string.
|
||||||
|
Version string `json:"version"`
|
||||||
// User is the userid according to hsu.
|
// User is the userid according to hsu.
|
||||||
User int `json:"user"`
|
User int `json:"user"`
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ func Main(ctx context.Context, msg message.Msg, config *hst.Config) {
|
|||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
seal := outcome{syscallDispatcher: direct{}}
|
seal := outcome{syscallDispatcher: direct{msg}}
|
||||||
if err := seal.finalise(ctx, msg, &id, config); err != nil {
|
if err := seal.finalise(ctx, msg, &id, config); err != nil {
|
||||||
printMessageError("cannot seal app:", err)
|
printMessageError("cannot seal app:", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
|
|||||||
@@ -17,9 +17,10 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"hakurei.app/container"
|
"hakurei.app/container"
|
||||||
"hakurei.app/container/bits"
|
|
||||||
"hakurei.app/container/check"
|
"hakurei.app/container/check"
|
||||||
|
"hakurei.app/container/comp"
|
||||||
"hakurei.app/container/fhs"
|
"hakurei.app/container/fhs"
|
||||||
|
"hakurei.app/container/seccomp"
|
||||||
"hakurei.app/hst"
|
"hakurei.app/hst"
|
||||||
"hakurei.app/internal/app/state"
|
"hakurei.app/internal/app/state"
|
||||||
"hakurei.app/message"
|
"hakurei.app/message"
|
||||||
@@ -41,9 +42,267 @@ func TestApp(t *testing.T) {
|
|||||||
wantSys *system.I
|
wantSys *system.I
|
||||||
wantParams *container.Params
|
wantParams *container.Params
|
||||||
}{
|
}{
|
||||||
{
|
{"template", new(stubNixOS), hst.Template(), checkExpectInstanceId, system.New(panicMsgContext{}, message.NewMsg(nil), 1000009).
|
||||||
"nixos permissive defaults no enablements", new(stubNixOS),
|
// spParamsOp
|
||||||
&hst.Config{Container: &hst.ContainerConfig{
|
Ensure(m("/tmp/hakurei.0"), 0711).
|
||||||
|
|
||||||
|
// spRuntimeOp
|
||||||
|
Ensure(m("/tmp/hakurei.0/runtime"), 0700).
|
||||||
|
UpdatePermType(system.User, m("/tmp/hakurei.0/runtime"), acl.Execute).
|
||||||
|
Ensure(m("/tmp/hakurei.0/runtime/9"), 0700).
|
||||||
|
UpdatePermType(system.User, m("/tmp/hakurei.0/runtime/9"), acl.Read, acl.Write, acl.Execute).
|
||||||
|
|
||||||
|
// spTmpdirOp
|
||||||
|
Ensure(m("/tmp/hakurei.0/tmpdir"), 0700).
|
||||||
|
UpdatePermType(system.User, m("/tmp/hakurei.0/tmpdir"), acl.Execute).
|
||||||
|
Ensure(m("/tmp/hakurei.0/tmpdir/9"), 01700).
|
||||||
|
UpdatePermType(system.User, m("/tmp/hakurei.0/tmpdir/9"), acl.Read, acl.Write, acl.Execute).
|
||||||
|
|
||||||
|
// instance
|
||||||
|
Ephemeral(system.Process, m("/tmp/hakurei.0/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), 0711).
|
||||||
|
|
||||||
|
// spWaylandOp
|
||||||
|
Wayland(
|
||||||
|
m("/tmp/hakurei.0/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/wayland"),
|
||||||
|
m("/run/user/1971/wayland-0"),
|
||||||
|
"org.chromium.Chromium",
|
||||||
|
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||||
|
).
|
||||||
|
|
||||||
|
// ensureRuntimeDir
|
||||||
|
Ensure(m("/run/user/1971/hakurei"), 0700).
|
||||||
|
UpdatePermType(system.User, m("/run/user/1971/hakurei"), acl.Execute).
|
||||||
|
Ensure(m("/run/user/1971"), 0700).
|
||||||
|
UpdatePermType(system.User, m("/run/user/1971"), acl.Execute).
|
||||||
|
|
||||||
|
// runtime
|
||||||
|
Ephemeral(system.Process, m("/run/user/1971/hakurei/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), 0700).
|
||||||
|
UpdatePerm(m("/run/user/1971/hakurei/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), acl.Execute).
|
||||||
|
|
||||||
|
// spPulseOp
|
||||||
|
Link(m("/run/user/1971/pulse/native"), m("/run/user/1971/hakurei/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/pulse")).
|
||||||
|
|
||||||
|
// spDBusOp
|
||||||
|
MustProxyDBus(
|
||||||
|
hst.Template().SessionBus,
|
||||||
|
hst.Template().SystemBus, dbus.ProxyPair{
|
||||||
|
"unix:path=/run/user/1971/bus",
|
||||||
|
"/tmp/hakurei.0/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bus",
|
||||||
|
}, dbus.ProxyPair{
|
||||||
|
"unix:path=/var/run/dbus/system_bus_socket",
|
||||||
|
"/tmp/hakurei.0/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/system_bus_socket",
|
||||||
|
},
|
||||||
|
).UpdatePerm(m("/tmp/hakurei.0/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bus"), acl.Read, acl.Write).
|
||||||
|
UpdatePerm(m("/tmp/hakurei.0/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/system_bus_socket"), acl.Read, acl.Write).
|
||||||
|
|
||||||
|
// spFilesystemOp
|
||||||
|
Ensure(m("/var/lib/hakurei/u0"), 0700).
|
||||||
|
UpdatePermType(system.User, m("/var/lib/hakurei/u0"), acl.Execute).
|
||||||
|
UpdatePermType(system.User, m("/var/lib/hakurei/u0/org.chromium.Chromium"), acl.Read, acl.Write, acl.Execute), &container.Params{
|
||||||
|
|
||||||
|
Dir: m("/data/data/org.chromium.Chromium"),
|
||||||
|
Env: []string{
|
||||||
|
"DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1971/bus",
|
||||||
|
"DBUS_SYSTEM_BUS_ADDRESS=unix:path=/var/run/dbus/system_bus_socket",
|
||||||
|
"GOOGLE_API_KEY=AIzaSyBHDrl33hwRp4rMQY0ziRbj8K9LPA6vUCY",
|
||||||
|
"GOOGLE_DEFAULT_CLIENT_ID=77185425430.apps.googleusercontent.com",
|
||||||
|
"GOOGLE_DEFAULT_CLIENT_SECRET=OTJgUOQcT7lO7GsGZq2G4IlT",
|
||||||
|
"HOME=/data/data/org.chromium.Chromium",
|
||||||
|
"PULSE_COOKIE=/.hakurei/pulse-cookie",
|
||||||
|
"PULSE_SERVER=unix:/run/user/1971/pulse/native",
|
||||||
|
"SHELL=/run/current-system/sw/bin/zsh",
|
||||||
|
"TERM=xterm-256color",
|
||||||
|
"USER=chronos",
|
||||||
|
"WAYLAND_DISPLAY=wayland-0",
|
||||||
|
"XDG_RUNTIME_DIR=/run/user/1971",
|
||||||
|
"XDG_SESSION_CLASS=user",
|
||||||
|
"XDG_SESSION_TYPE=wayland",
|
||||||
|
},
|
||||||
|
|
||||||
|
// spParamsOp
|
||||||
|
Hostname: "localhost",
|
||||||
|
RetainSession: true,
|
||||||
|
HostNet: true,
|
||||||
|
HostAbstract: true,
|
||||||
|
Path: m("/run/current-system/sw/bin/chromium"),
|
||||||
|
Args: []string{
|
||||||
|
"chromium",
|
||||||
|
"--ignore-gpu-blocklist",
|
||||||
|
"--disable-smooth-scrolling",
|
||||||
|
"--enable-features=UseOzonePlatform",
|
||||||
|
"--ozone-platform=wayland",
|
||||||
|
},
|
||||||
|
SeccompFlags: seccomp.AllowMultiarch,
|
||||||
|
Uid: 1971,
|
||||||
|
Gid: 100,
|
||||||
|
|
||||||
|
Ops: new(container.Ops).
|
||||||
|
// resolveRoot
|
||||||
|
Root(m("/var/lib/hakurei/base/org.debian"), comp.BindWritable).
|
||||||
|
// spParamsOp
|
||||||
|
Proc(fhs.AbsProc).
|
||||||
|
Tmpfs(hst.AbsPrivateTmp, 1<<12, 0755).
|
||||||
|
Bind(fhs.AbsDev, fhs.AbsDev, comp.BindWritable|comp.BindDevice).
|
||||||
|
Tmpfs(fhs.AbsDev.Append("shm"), 0, 01777).
|
||||||
|
|
||||||
|
// spRuntimeOp
|
||||||
|
Tmpfs(fhs.AbsRunUser, 1<<12, 0755).
|
||||||
|
Bind(m("/tmp/hakurei.0/runtime/9"), m("/run/user/1971"), comp.BindWritable).
|
||||||
|
|
||||||
|
// spTmpdirOp
|
||||||
|
Bind(m("/tmp/hakurei.0/tmpdir/9"), fhs.AbsTmp, comp.BindWritable).
|
||||||
|
|
||||||
|
// spAccountOp
|
||||||
|
Place(m("/etc/passwd"), []byte("chronos:x:1971:100:Hakurei:/data/data/org.chromium.Chromium:/run/current-system/sw/bin/zsh\n")).
|
||||||
|
Place(m("/etc/group"), []byte("hakurei:x:100:\n")).
|
||||||
|
|
||||||
|
// spWaylandOp
|
||||||
|
Bind(m("/tmp/hakurei.0/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/wayland"), m("/run/user/1971/wayland-0"), 0).
|
||||||
|
|
||||||
|
// spPulseOp
|
||||||
|
Bind(m("/run/user/1971/hakurei/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/pulse"), m("/run/user/1971/pulse/native"), 0).
|
||||||
|
Place(m("/.hakurei/pulse-cookie"), bytes.Repeat([]byte{0}, pulseCookieSizeMax)).
|
||||||
|
|
||||||
|
// spDBusOp
|
||||||
|
Bind(m("/tmp/hakurei.0/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bus"), m("/run/user/1971/bus"), 0).
|
||||||
|
Bind(m("/tmp/hakurei.0/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/system_bus_socket"), m("/var/run/dbus/system_bus_socket"), 0).
|
||||||
|
|
||||||
|
// spFilesystemOp
|
||||||
|
Etc(fhs.AbsEtc, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa").
|
||||||
|
Tmpfs(fhs.AbsTmp, 0, 0755).
|
||||||
|
Overlay(m("/nix/store"),
|
||||||
|
fhs.AbsVarLib.Append("hakurei/nix/u0/org.chromium.Chromium/rw-store/upper"),
|
||||||
|
fhs.AbsVarLib.Append("hakurei/nix/u0/org.chromium.Chromium/rw-store/work"),
|
||||||
|
fhs.AbsVarLib.Append("hakurei/base/org.nixos/ro-store")).
|
||||||
|
Link(m("/run/current-system"), "/run/current-system", true).
|
||||||
|
Link(m("/run/opengl-driver"), "/run/opengl-driver", true).
|
||||||
|
Bind(fhs.AbsVarLib.Append("hakurei/u0/org.chromium.Chromium"),
|
||||||
|
m("/data/data/org.chromium.Chromium"),
|
||||||
|
comp.BindWritable|comp.BindEnsure).
|
||||||
|
Bind(fhs.AbsDev.Append("dri"), fhs.AbsDev.Append("dri"),
|
||||||
|
comp.BindOptional|comp.BindWritable|comp.BindDevice).
|
||||||
|
Remount(fhs.AbsRoot, syscall.MS_RDONLY),
|
||||||
|
}},
|
||||||
|
|
||||||
|
{"nixos permissive defaults no enablements", new(stubNixOS), &hst.Config{Container: &hst.ContainerConfig{
|
||||||
|
Filesystem: []hst.FilesystemConfigJSON{
|
||||||
|
{FilesystemConfig: &hst.FSBind{
|
||||||
|
Target: fhs.AbsRoot,
|
||||||
|
Source: fhs.AbsRoot,
|
||||||
|
Write: true,
|
||||||
|
Special: true,
|
||||||
|
}},
|
||||||
|
{FilesystemConfig: &hst.FSBind{
|
||||||
|
Source: fhs.AbsDev.Append("kvm"),
|
||||||
|
Device: true,
|
||||||
|
Optional: true,
|
||||||
|
}},
|
||||||
|
{FilesystemConfig: &hst.FSBind{
|
||||||
|
Target: fhs.AbsEtc,
|
||||||
|
Source: fhs.AbsEtc,
|
||||||
|
Special: true,
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
|
||||||
|
Username: "chronos",
|
||||||
|
Shell: m("/run/current-system/sw/bin/zsh"),
|
||||||
|
Home: m("/home/chronos"),
|
||||||
|
|
||||||
|
Path: m("/run/current-system/sw/bin/zsh"),
|
||||||
|
Args: []string{"/run/current-system/sw/bin/zsh"},
|
||||||
|
|
||||||
|
Flags: hst.FUserns | hst.FHostNet | hst.FHostAbstract | hst.FTty | hst.FShareRuntime | hst.FShareTmpdir,
|
||||||
|
}}, state.ID{
|
||||||
|
0x4a, 0x45, 0x0b, 0x65,
|
||||||
|
0x96, 0xd7, 0xbc, 0x15,
|
||||||
|
0xbd, 0x01, 0x78, 0x0e,
|
||||||
|
0xb9, 0xa6, 0x07, 0xac,
|
||||||
|
}, system.New(t.Context(), msg, 1000000).
|
||||||
|
Ensure(m("/tmp/hakurei.0"), 0711).
|
||||||
|
Ensure(m("/tmp/hakurei.0/runtime"), 0700).
|
||||||
|
UpdatePermType(system.User, m("/tmp/hakurei.0/runtime"), acl.Execute).
|
||||||
|
Ensure(m("/tmp/hakurei.0/runtime/0"), 0700).
|
||||||
|
UpdatePermType(system.User, m("/tmp/hakurei.0/runtime/0"), acl.Read, acl.Write, acl.Execute).
|
||||||
|
Ensure(m("/tmp/hakurei.0/tmpdir"), 0700).
|
||||||
|
UpdatePermType(system.User, m("/tmp/hakurei.0/tmpdir"), acl.Execute).
|
||||||
|
Ensure(m("/tmp/hakurei.0/tmpdir/0"), 01700).
|
||||||
|
UpdatePermType(system.User, m("/tmp/hakurei.0/tmpdir/0"), acl.Read, acl.Write, acl.Execute), &container.Params{
|
||||||
|
|
||||||
|
Dir: m("/home/chronos"),
|
||||||
|
Path: m("/run/current-system/sw/bin/zsh"),
|
||||||
|
Args: []string{"/run/current-system/sw/bin/zsh"},
|
||||||
|
Env: []string{
|
||||||
|
"HOME=/home/chronos",
|
||||||
|
"SHELL=/run/current-system/sw/bin/zsh",
|
||||||
|
"TERM=xterm-256color",
|
||||||
|
"USER=chronos",
|
||||||
|
"XDG_RUNTIME_DIR=/run/user/65534",
|
||||||
|
"XDG_SESSION_CLASS=user",
|
||||||
|
"XDG_SESSION_TYPE=tty",
|
||||||
|
},
|
||||||
|
Ops: new(container.Ops).
|
||||||
|
Root(m("/"), comp.BindWritable).
|
||||||
|
Proc(m("/proc/")).
|
||||||
|
Tmpfs(hst.AbsPrivateTmp, 4096, 0755).
|
||||||
|
DevWritable(m("/dev/"), true).
|
||||||
|
Tmpfs(m("/dev/shm"), 0, 01777).
|
||||||
|
Tmpfs(m("/run/user/"), 4096, 0755).
|
||||||
|
Bind(m("/tmp/hakurei.0/runtime/0"), m("/run/user/65534"), comp.BindWritable).
|
||||||
|
Bind(m("/tmp/hakurei.0/tmpdir/0"), m("/tmp/"), comp.BindWritable).
|
||||||
|
Place(m("/etc/passwd"), []byte("chronos:x:65534:65534:Hakurei:/home/chronos:/run/current-system/sw/bin/zsh\n")).
|
||||||
|
Place(m("/etc/group"), []byte("hakurei:x:65534:\n")).
|
||||||
|
Bind(m("/dev/kvm"), m("/dev/kvm"), comp.BindWritable|comp.BindDevice|comp.BindOptional).
|
||||||
|
Etc(m("/etc/"), "4a450b6596d7bc15bd01780eb9a607ac").
|
||||||
|
Tmpfs(m("/run/user/1971"), 8192, 0755).
|
||||||
|
Tmpfs(m("/run/nscd"), 8192, 0755).
|
||||||
|
Tmpfs(m("/run/dbus"), 8192, 0755).
|
||||||
|
Remount(m("/dev/"), syscall.MS_RDONLY).
|
||||||
|
Remount(m("/"), syscall.MS_RDONLY),
|
||||||
|
SeccompPresets: comp.PresetExt | comp.PresetDenyDevel,
|
||||||
|
HostNet: true,
|
||||||
|
HostAbstract: true,
|
||||||
|
RetainSession: true,
|
||||||
|
ForwardCancel: true,
|
||||||
|
}},
|
||||||
|
|
||||||
|
{"nixos permissive defaults chromium", new(stubNixOS), &hst.Config{
|
||||||
|
ID: "org.chromium.Chromium",
|
||||||
|
Identity: 9,
|
||||||
|
Groups: []string{"video"},
|
||||||
|
SessionBus: &hst.BusConfig{
|
||||||
|
Talk: []string{
|
||||||
|
"org.freedesktop.Notifications",
|
||||||
|
"org.freedesktop.FileManager1",
|
||||||
|
"org.freedesktop.ScreenSaver",
|
||||||
|
"org.freedesktop.secrets",
|
||||||
|
"org.kde.kwalletd5",
|
||||||
|
"org.kde.kwalletd6",
|
||||||
|
"org.gnome.SessionManager",
|
||||||
|
},
|
||||||
|
Own: []string{
|
||||||
|
"org.chromium.Chromium.*",
|
||||||
|
"org.mpris.MediaPlayer2.org.chromium.Chromium.*",
|
||||||
|
"org.mpris.MediaPlayer2.chromium.*",
|
||||||
|
},
|
||||||
|
Call: map[string]string{
|
||||||
|
"org.freedesktop.portal.*": "*",
|
||||||
|
},
|
||||||
|
Broadcast: map[string]string{
|
||||||
|
"org.freedesktop.portal.*": "@/org/freedesktop/portal/*",
|
||||||
|
},
|
||||||
|
Filter: true,
|
||||||
|
},
|
||||||
|
SystemBus: &hst.BusConfig{
|
||||||
|
Talk: []string{
|
||||||
|
"org.bluez",
|
||||||
|
"org.freedesktop.Avahi",
|
||||||
|
"org.freedesktop.UPower",
|
||||||
|
},
|
||||||
|
Filter: true,
|
||||||
|
},
|
||||||
|
Enablements: hst.NewEnablements(hst.EWayland | hst.EDBus | hst.EPulse),
|
||||||
|
|
||||||
|
Container: &hst.ContainerConfig{
|
||||||
Filesystem: []hst.FilesystemConfigJSON{
|
Filesystem: []hst.FilesystemConfigJSON{
|
||||||
{FilesystemConfig: &hst.FSBind{
|
{FilesystemConfig: &hst.FSBind{
|
||||||
Target: fhs.AbsRoot,
|
Target: fhs.AbsRoot,
|
||||||
@@ -51,6 +310,11 @@ func TestApp(t *testing.T) {
|
|||||||
Write: true,
|
Write: true,
|
||||||
Special: true,
|
Special: true,
|
||||||
}},
|
}},
|
||||||
|
{FilesystemConfig: &hst.FSBind{
|
||||||
|
Source: fhs.AbsDev.Append("dri"),
|
||||||
|
Device: true,
|
||||||
|
Optional: true,
|
||||||
|
}},
|
||||||
{FilesystemConfig: &hst.FSBind{
|
{FilesystemConfig: &hst.FSBind{
|
||||||
Source: fhs.AbsDev.Append("kvm"),
|
Source: fhs.AbsDev.Append("kvm"),
|
||||||
Device: true,
|
Device: true,
|
||||||
@@ -68,395 +332,264 @@ func TestApp(t *testing.T) {
|
|||||||
Home: m("/home/chronos"),
|
Home: m("/home/chronos"),
|
||||||
|
|
||||||
Path: m("/run/current-system/sw/bin/zsh"),
|
Path: m("/run/current-system/sw/bin/zsh"),
|
||||||
Args: []string{"/run/current-system/sw/bin/zsh"},
|
Args: []string{"zsh", "-c", "exec chromium "},
|
||||||
|
|
||||||
Flags: hst.FUserns | hst.FHostNet | hst.FHostAbstract | hst.FTty | hst.FShareRuntime | hst.FShareTmpdir,
|
Flags: hst.FUserns | hst.FHostNet | hst.FHostAbstract | hst.FTty | hst.FShareRuntime | hst.FShareTmpdir,
|
||||||
}},
|
|
||||||
state.ID{
|
|
||||||
0x4a, 0x45, 0x0b, 0x65,
|
|
||||||
0x96, 0xd7, 0xbc, 0x15,
|
|
||||||
0xbd, 0x01, 0x78, 0x0e,
|
|
||||||
0xb9, 0xa6, 0x07, 0xac,
|
|
||||||
},
|
},
|
||||||
system.New(t.Context(), msg, 1000000).
|
}, state.ID{
|
||||||
Ensure(m("/tmp/hakurei.0"), 0711).
|
0xeb, 0xf0, 0x83, 0xd1,
|
||||||
Ensure(m("/tmp/hakurei.0/runtime"), 0700).UpdatePermType(system.User, m("/tmp/hakurei.0/runtime"), acl.Execute).
|
0xb1, 0x75, 0x91, 0x17,
|
||||||
Ensure(m("/tmp/hakurei.0/runtime/0"), 0700).UpdatePermType(system.User, m("/tmp/hakurei.0/runtime/0"), acl.Read, acl.Write, acl.Execute).
|
0x82, 0xd4, 0x13, 0x36,
|
||||||
Ensure(m("/tmp/hakurei.0/tmpdir"), 0700).UpdatePermType(system.User, m("/tmp/hakurei.0/tmpdir"), acl.Execute).
|
0x9b, 0x64, 0xce, 0x7c,
|
||||||
Ensure(m("/tmp/hakurei.0/tmpdir/0"), 01700).UpdatePermType(system.User, m("/tmp/hakurei.0/tmpdir/0"), acl.Read, acl.Write, acl.Execute),
|
}, system.New(t.Context(), msg, 1000009).
|
||||||
&container.Params{
|
Ensure(m("/tmp/hakurei.0"), 0711).
|
||||||
Dir: m("/home/chronos"),
|
Ensure(m("/tmp/hakurei.0/runtime"), 0700).UpdatePermType(system.User, m("/tmp/hakurei.0/runtime"), acl.Execute).
|
||||||
Path: m("/run/current-system/sw/bin/zsh"),
|
Ensure(m("/tmp/hakurei.0/runtime/9"), 0700).UpdatePermType(system.User, m("/tmp/hakurei.0/runtime/9"), acl.Read, acl.Write, acl.Execute).
|
||||||
Args: []string{"/run/current-system/sw/bin/zsh"},
|
Ensure(m("/tmp/hakurei.0/tmpdir"), 0700).UpdatePermType(system.User, m("/tmp/hakurei.0/tmpdir"), acl.Execute).
|
||||||
Env: []string{
|
Ensure(m("/tmp/hakurei.0/tmpdir/9"), 01700).UpdatePermType(system.User, m("/tmp/hakurei.0/tmpdir/9"), acl.Read, acl.Write, acl.Execute).
|
||||||
"HOME=/home/chronos",
|
Ephemeral(system.Process, m("/tmp/hakurei.0/ebf083d1b175911782d413369b64ce7c"), 0711).
|
||||||
"SHELL=/run/current-system/sw/bin/zsh",
|
Wayland(m("/tmp/hakurei.0/ebf083d1b175911782d413369b64ce7c/wayland"), m("/run/user/1971/wayland-0"), "org.chromium.Chromium", "ebf083d1b175911782d413369b64ce7c").
|
||||||
"TERM=xterm-256color",
|
Ensure(m("/run/user/1971/hakurei"), 0700).UpdatePermType(system.User, m("/run/user/1971/hakurei"), acl.Execute).
|
||||||
"USER=chronos",
|
Ensure(m("/run/user/1971"), 0700).UpdatePermType(system.User, m("/run/user/1971"), acl.Execute). // this is ordered as is because the previous Ensure only calls mkdir if XDG_RUNTIME_DIR is unset
|
||||||
"XDG_RUNTIME_DIR=/run/user/65534",
|
Ephemeral(system.Process, m("/run/user/1971/hakurei/ebf083d1b175911782d413369b64ce7c"), 0700).UpdatePermType(system.Process, m("/run/user/1971/hakurei/ebf083d1b175911782d413369b64ce7c"), acl.Execute).
|
||||||
"XDG_SESSION_CLASS=user",
|
Link(m("/run/user/1971/pulse/native"), m("/run/user/1971/hakurei/ebf083d1b175911782d413369b64ce7c/pulse")).
|
||||||
"XDG_SESSION_TYPE=tty",
|
MustProxyDBus(&hst.BusConfig{
|
||||||
|
Talk: []string{
|
||||||
|
"org.freedesktop.Notifications",
|
||||||
|
"org.freedesktop.FileManager1",
|
||||||
|
"org.freedesktop.ScreenSaver",
|
||||||
|
"org.freedesktop.secrets",
|
||||||
|
"org.kde.kwalletd5",
|
||||||
|
"org.kde.kwalletd6",
|
||||||
|
"org.gnome.SessionManager",
|
||||||
},
|
},
|
||||||
Ops: new(container.Ops).
|
Own: []string{
|
||||||
Root(m("/"), bits.BindWritable).
|
"org.chromium.Chromium.*",
|
||||||
Proc(m("/proc/")).
|
"org.mpris.MediaPlayer2.org.chromium.Chromium.*",
|
||||||
Tmpfs(hst.AbsPrivateTmp, 4096, 0755).
|
"org.mpris.MediaPlayer2.chromium.*",
|
||||||
DevWritable(m("/dev/"), true).
|
},
|
||||||
Tmpfs(m("/dev/shm"), 0, 01777).
|
Call: map[string]string{
|
||||||
Tmpfs(m("/run/user/"), 4096, 0755).
|
"org.freedesktop.portal.*": "*",
|
||||||
Bind(m("/tmp/hakurei.0/runtime/0"), m("/run/user/65534"), bits.BindWritable).
|
},
|
||||||
Bind(m("/tmp/hakurei.0/tmpdir/0"), m("/tmp/"), bits.BindWritable).
|
Broadcast: map[string]string{
|
||||||
Place(m("/etc/passwd"), []byte("chronos:x:65534:65534:Hakurei:/home/chronos:/run/current-system/sw/bin/zsh\n")).
|
"org.freedesktop.portal.*": "@/org/freedesktop/portal/*",
|
||||||
Place(m("/etc/group"), []byte("hakurei:x:65534:\n")).
|
},
|
||||||
Bind(m("/dev/kvm"), m("/dev/kvm"), bits.BindWritable|bits.BindDevice|bits.BindOptional).
|
Filter: true,
|
||||||
Etc(m("/etc/"), "4a450b6596d7bc15bd01780eb9a607ac").
|
}, &hst.BusConfig{
|
||||||
Tmpfs(m("/run/user/1971"), 8192, 0755).
|
Talk: []string{
|
||||||
Tmpfs(m("/run/nscd"), 8192, 0755).
|
"org.bluez",
|
||||||
Tmpfs(m("/run/dbus"), 8192, 0755).
|
"org.freedesktop.Avahi",
|
||||||
Remount(m("/dev/"), syscall.MS_RDONLY).
|
"org.freedesktop.UPower",
|
||||||
Remount(m("/"), syscall.MS_RDONLY),
|
},
|
||||||
SeccompPresets: bits.PresetExt | bits.PresetDenyDevel,
|
Filter: true,
|
||||||
HostNet: true,
|
}, dbus.ProxyPair{
|
||||||
HostAbstract: true,
|
"unix:path=/run/user/1971/bus",
|
||||||
RetainSession: true,
|
"/tmp/hakurei.0/ebf083d1b175911782d413369b64ce7c/bus",
|
||||||
ForwardCancel: true,
|
}, dbus.ProxyPair{
|
||||||
|
"unix:path=/var/run/dbus/system_bus_socket",
|
||||||
|
"/tmp/hakurei.0/ebf083d1b175911782d413369b64ce7c/system_bus_socket",
|
||||||
|
}).
|
||||||
|
UpdatePerm(m("/tmp/hakurei.0/ebf083d1b175911782d413369b64ce7c/bus"), acl.Read, acl.Write).
|
||||||
|
UpdatePerm(m("/tmp/hakurei.0/ebf083d1b175911782d413369b64ce7c/system_bus_socket"), acl.Read, acl.Write), &container.Params{
|
||||||
|
|
||||||
|
Dir: m("/home/chronos"),
|
||||||
|
Path: m("/run/current-system/sw/bin/zsh"),
|
||||||
|
Args: []string{"zsh", "-c", "exec chromium "},
|
||||||
|
Env: []string{
|
||||||
|
"DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/65534/bus",
|
||||||
|
"DBUS_SYSTEM_BUS_ADDRESS=unix:path=/var/run/dbus/system_bus_socket",
|
||||||
|
"HOME=/home/chronos",
|
||||||
|
"PULSE_COOKIE=" + hst.PrivateTmp + "/pulse-cookie",
|
||||||
|
"PULSE_SERVER=unix:/run/user/65534/pulse/native",
|
||||||
|
"SHELL=/run/current-system/sw/bin/zsh",
|
||||||
|
"TERM=xterm-256color",
|
||||||
|
"USER=chronos",
|
||||||
|
"WAYLAND_DISPLAY=wayland-0",
|
||||||
|
"XDG_RUNTIME_DIR=/run/user/65534",
|
||||||
|
"XDG_SESSION_CLASS=user",
|
||||||
|
"XDG_SESSION_TYPE=wayland",
|
||||||
},
|
},
|
||||||
},
|
Ops: new(container.Ops).
|
||||||
{
|
Root(m("/"), comp.BindWritable).
|
||||||
"nixos permissive defaults chromium", new(stubNixOS),
|
Proc(m("/proc/")).
|
||||||
&hst.Config{
|
Tmpfs(hst.AbsPrivateTmp, 4096, 0755).
|
||||||
ID: "org.chromium.Chromium",
|
DevWritable(m("/dev/"), true).
|
||||||
Identity: 9,
|
Tmpfs(m("/dev/shm"), 0, 01777).
|
||||||
Groups: []string{"video"},
|
Tmpfs(m("/run/user/"), 4096, 0755).
|
||||||
SessionBus: &hst.BusConfig{
|
Bind(m("/tmp/hakurei.0/runtime/9"), m("/run/user/65534"), comp.BindWritable).
|
||||||
Talk: []string{
|
Bind(m("/tmp/hakurei.0/tmpdir/9"), m("/tmp/"), comp.BindWritable).
|
||||||
"org.freedesktop.Notifications",
|
Place(m("/etc/passwd"), []byte("chronos:x:65534:65534:Hakurei:/home/chronos:/run/current-system/sw/bin/zsh\n")).
|
||||||
"org.freedesktop.FileManager1",
|
Place(m("/etc/group"), []byte("hakurei:x:65534:\n")).
|
||||||
"org.freedesktop.ScreenSaver",
|
Bind(m("/tmp/hakurei.0/ebf083d1b175911782d413369b64ce7c/wayland"), m("/run/user/65534/wayland-0"), 0).
|
||||||
"org.freedesktop.secrets",
|
Bind(m("/run/user/1971/hakurei/ebf083d1b175911782d413369b64ce7c/pulse"), m("/run/user/65534/pulse/native"), 0).
|
||||||
"org.kde.kwalletd5",
|
Place(m(hst.PrivateTmp+"/pulse-cookie"), bytes.Repeat([]byte{0}, pulseCookieSizeMax)).
|
||||||
"org.kde.kwalletd6",
|
Bind(m("/tmp/hakurei.0/ebf083d1b175911782d413369b64ce7c/bus"), m("/run/user/65534/bus"), 0).
|
||||||
"org.gnome.SessionManager",
|
Bind(m("/tmp/hakurei.0/ebf083d1b175911782d413369b64ce7c/system_bus_socket"), m("/var/run/dbus/system_bus_socket"), 0).
|
||||||
},
|
Bind(m("/dev/dri"), m("/dev/dri"), comp.BindWritable|comp.BindDevice|comp.BindOptional).
|
||||||
Own: []string{
|
Bind(m("/dev/kvm"), m("/dev/kvm"), comp.BindWritable|comp.BindDevice|comp.BindOptional).
|
||||||
"org.chromium.Chromium.*",
|
Etc(m("/etc/"), "ebf083d1b175911782d413369b64ce7c").
|
||||||
"org.mpris.MediaPlayer2.org.chromium.Chromium.*",
|
Tmpfs(m("/run/user/1971"), 8192, 0755).
|
||||||
"org.mpris.MediaPlayer2.chromium.*",
|
Tmpfs(m("/run/nscd"), 8192, 0755).
|
||||||
},
|
Tmpfs(m("/run/dbus"), 8192, 0755).
|
||||||
Call: map[string]string{
|
Remount(m("/dev/"), syscall.MS_RDONLY).
|
||||||
"org.freedesktop.portal.*": "*",
|
Remount(m("/"), syscall.MS_RDONLY),
|
||||||
},
|
SeccompPresets: comp.PresetExt | comp.PresetDenyDevel,
|
||||||
Broadcast: map[string]string{
|
HostNet: true,
|
||||||
"org.freedesktop.portal.*": "@/org/freedesktop/portal/*",
|
HostAbstract: true,
|
||||||
},
|
RetainSession: true,
|
||||||
Filter: true,
|
ForwardCancel: true,
|
||||||
|
}},
|
||||||
|
|
||||||
|
{"nixos chromium direct wayland", new(stubNixOS), &hst.Config{
|
||||||
|
ID: "org.chromium.Chromium",
|
||||||
|
Enablements: hst.NewEnablements(hst.EWayland | hst.EDBus | hst.EPulse),
|
||||||
|
Container: &hst.ContainerConfig{
|
||||||
|
Env: nil,
|
||||||
|
Filesystem: []hst.FilesystemConfigJSON{
|
||||||
|
f(&hst.FSBind{Source: m("/bin")}),
|
||||||
|
f(&hst.FSBind{Source: m("/usr/bin/")}),
|
||||||
|
f(&hst.FSBind{Source: m("/nix/store")}),
|
||||||
|
f(&hst.FSBind{Source: m("/run/current-system")}),
|
||||||
|
f(&hst.FSBind{Source: m("/sys/block"), Optional: true}),
|
||||||
|
f(&hst.FSBind{Source: m("/sys/bus"), Optional: true}),
|
||||||
|
f(&hst.FSBind{Source: m("/sys/class"), Optional: true}),
|
||||||
|
f(&hst.FSBind{Source: m("/sys/dev"), Optional: true}),
|
||||||
|
f(&hst.FSBind{Source: m("/sys/devices"), Optional: true}),
|
||||||
|
f(&hst.FSBind{Source: m("/run/opengl-driver")}),
|
||||||
|
f(&hst.FSBind{Source: m("/dev/dri"), Device: true, Optional: true}),
|
||||||
|
f(&hst.FSBind{Source: m("/etc/"), Target: m("/etc/"), Special: true}),
|
||||||
|
f(&hst.FSBind{Source: m("/var/lib/persist/module/hakurei/0/1"), Write: true, Ensure: true}),
|
||||||
},
|
},
|
||||||
SystemBus: &hst.BusConfig{
|
|
||||||
Talk: []string{
|
|
||||||
"org.bluez",
|
|
||||||
"org.freedesktop.Avahi",
|
|
||||||
"org.freedesktop.UPower",
|
|
||||||
},
|
|
||||||
Filter: true,
|
|
||||||
},
|
|
||||||
Enablements: hst.NewEnablements(hst.EWayland | hst.EDBus | hst.EPulse),
|
|
||||||
|
|
||||||
Container: &hst.ContainerConfig{
|
Username: "u0_a1",
|
||||||
Filesystem: []hst.FilesystemConfigJSON{
|
Shell: m("/run/current-system/sw/bin/zsh"),
|
||||||
{FilesystemConfig: &hst.FSBind{
|
Home: m("/var/lib/persist/module/hakurei/0/1"),
|
||||||
Target: fhs.AbsRoot,
|
|
||||||
Source: fhs.AbsRoot,
|
|
||||||
Write: true,
|
|
||||||
Special: true,
|
|
||||||
}},
|
|
||||||
{FilesystemConfig: &hst.FSBind{
|
|
||||||
Source: fhs.AbsDev.Append("dri"),
|
|
||||||
Device: true,
|
|
||||||
Optional: true,
|
|
||||||
}},
|
|
||||||
{FilesystemConfig: &hst.FSBind{
|
|
||||||
Source: fhs.AbsDev.Append("kvm"),
|
|
||||||
Device: true,
|
|
||||||
Optional: true,
|
|
||||||
}},
|
|
||||||
{FilesystemConfig: &hst.FSBind{
|
|
||||||
Target: fhs.AbsEtc,
|
|
||||||
Source: fhs.AbsEtc,
|
|
||||||
Special: true,
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
|
|
||||||
Username: "chronos",
|
|
||||||
Shell: m("/run/current-system/sw/bin/zsh"),
|
|
||||||
Home: m("/home/chronos"),
|
|
||||||
|
|
||||||
Path: m("/run/current-system/sw/bin/zsh"),
|
|
||||||
Args: []string{"zsh", "-c", "exec chromium "},
|
|
||||||
|
|
||||||
Flags: hst.FUserns | hst.FHostNet | hst.FHostAbstract | hst.FTty | hst.FShareRuntime | hst.FShareTmpdir,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
state.ID{
|
|
||||||
0xeb, 0xf0, 0x83, 0xd1,
|
|
||||||
0xb1, 0x75, 0x91, 0x17,
|
|
||||||
0x82, 0xd4, 0x13, 0x36,
|
|
||||||
0x9b, 0x64, 0xce, 0x7c,
|
|
||||||
},
|
|
||||||
system.New(t.Context(), msg, 1000009).
|
|
||||||
Ensure(m("/tmp/hakurei.0"), 0711).
|
|
||||||
Ensure(m("/tmp/hakurei.0/runtime"), 0700).UpdatePermType(system.User, m("/tmp/hakurei.0/runtime"), acl.Execute).
|
|
||||||
Ensure(m("/tmp/hakurei.0/runtime/9"), 0700).UpdatePermType(system.User, m("/tmp/hakurei.0/runtime/9"), acl.Read, acl.Write, acl.Execute).
|
|
||||||
Ensure(m("/tmp/hakurei.0/tmpdir"), 0700).UpdatePermType(system.User, m("/tmp/hakurei.0/tmpdir"), acl.Execute).
|
|
||||||
Ensure(m("/tmp/hakurei.0/tmpdir/9"), 01700).UpdatePermType(system.User, m("/tmp/hakurei.0/tmpdir/9"), acl.Read, acl.Write, acl.Execute).
|
|
||||||
Ephemeral(system.Process, m("/tmp/hakurei.0/ebf083d1b175911782d413369b64ce7c"), 0711).
|
|
||||||
Wayland(m("/tmp/hakurei.0/ebf083d1b175911782d413369b64ce7c/wayland"), m("/run/user/1971/wayland-0"), "org.chromium.Chromium", "ebf083d1b175911782d413369b64ce7c").
|
|
||||||
Ensure(m("/run/user/1971/hakurei"), 0700).UpdatePermType(system.User, m("/run/user/1971/hakurei"), acl.Execute).
|
|
||||||
Ensure(m("/run/user/1971"), 0700).UpdatePermType(system.User, m("/run/user/1971"), acl.Execute). // this is ordered as is because the previous Ensure only calls mkdir if XDG_RUNTIME_DIR is unset
|
|
||||||
Ephemeral(system.Process, m("/run/user/1971/hakurei/ebf083d1b175911782d413369b64ce7c"), 0700).UpdatePermType(system.Process, m("/run/user/1971/hakurei/ebf083d1b175911782d413369b64ce7c"), acl.Execute).
|
|
||||||
Link(m("/run/user/1971/pulse/native"), m("/run/user/1971/hakurei/ebf083d1b175911782d413369b64ce7c/pulse")).
|
|
||||||
MustProxyDBus(&hst.BusConfig{
|
|
||||||
Talk: []string{
|
|
||||||
"org.freedesktop.Notifications",
|
|
||||||
"org.freedesktop.FileManager1",
|
|
||||||
"org.freedesktop.ScreenSaver",
|
|
||||||
"org.freedesktop.secrets",
|
|
||||||
"org.kde.kwalletd5",
|
|
||||||
"org.kde.kwalletd6",
|
|
||||||
"org.gnome.SessionManager",
|
|
||||||
},
|
|
||||||
Own: []string{
|
|
||||||
"org.chromium.Chromium.*",
|
|
||||||
"org.mpris.MediaPlayer2.org.chromium.Chromium.*",
|
|
||||||
"org.mpris.MediaPlayer2.chromium.*",
|
|
||||||
},
|
|
||||||
Call: map[string]string{
|
|
||||||
"org.freedesktop.portal.*": "*",
|
|
||||||
},
|
|
||||||
Broadcast: map[string]string{
|
|
||||||
"org.freedesktop.portal.*": "@/org/freedesktop/portal/*",
|
|
||||||
},
|
|
||||||
Filter: true,
|
|
||||||
}, &hst.BusConfig{
|
|
||||||
Talk: []string{
|
|
||||||
"org.bluez",
|
|
||||||
"org.freedesktop.Avahi",
|
|
||||||
"org.freedesktop.UPower",
|
|
||||||
},
|
|
||||||
Filter: true,
|
|
||||||
}, dbus.ProxyPair{
|
|
||||||
"unix:path=/run/user/1971/bus",
|
|
||||||
"/tmp/hakurei.0/ebf083d1b175911782d413369b64ce7c/bus",
|
|
||||||
}, dbus.ProxyPair{
|
|
||||||
"unix:path=/var/run/dbus/system_bus_socket",
|
|
||||||
"/tmp/hakurei.0/ebf083d1b175911782d413369b64ce7c/system_bus_socket",
|
|
||||||
}).
|
|
||||||
UpdatePerm(m("/tmp/hakurei.0/ebf083d1b175911782d413369b64ce7c/bus"), acl.Read, acl.Write).
|
|
||||||
UpdatePerm(m("/tmp/hakurei.0/ebf083d1b175911782d413369b64ce7c/system_bus_socket"), acl.Read, acl.Write),
|
|
||||||
&container.Params{
|
|
||||||
Dir: m("/home/chronos"),
|
|
||||||
Path: m("/run/current-system/sw/bin/zsh"),
|
|
||||||
Args: []string{"zsh", "-c", "exec chromium "},
|
|
||||||
Env: []string{
|
|
||||||
"DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/65534/bus",
|
|
||||||
"DBUS_SYSTEM_BUS_ADDRESS=unix:path=/var/run/dbus/system_bus_socket",
|
|
||||||
"HOME=/home/chronos",
|
|
||||||
"PULSE_COOKIE=" + hst.PrivateTmp + "/pulse-cookie",
|
|
||||||
"PULSE_SERVER=unix:/run/user/65534/pulse/native",
|
|
||||||
"SHELL=/run/current-system/sw/bin/zsh",
|
|
||||||
"TERM=xterm-256color",
|
|
||||||
"USER=chronos",
|
|
||||||
"WAYLAND_DISPLAY=wayland-0",
|
|
||||||
"XDG_RUNTIME_DIR=/run/user/65534",
|
|
||||||
"XDG_SESSION_CLASS=user",
|
|
||||||
"XDG_SESSION_TYPE=wayland",
|
|
||||||
},
|
|
||||||
Ops: new(container.Ops).
|
|
||||||
Root(m("/"), bits.BindWritable).
|
|
||||||
Proc(m("/proc/")).
|
|
||||||
Tmpfs(hst.AbsPrivateTmp, 4096, 0755).
|
|
||||||
DevWritable(m("/dev/"), true).
|
|
||||||
Tmpfs(m("/dev/shm"), 0, 01777).
|
|
||||||
Tmpfs(m("/run/user/"), 4096, 0755).
|
|
||||||
Bind(m("/tmp/hakurei.0/runtime/9"), m("/run/user/65534"), bits.BindWritable).
|
|
||||||
Bind(m("/tmp/hakurei.0/tmpdir/9"), m("/tmp/"), bits.BindWritable).
|
|
||||||
Place(m("/etc/passwd"), []byte("chronos:x:65534:65534:Hakurei:/home/chronos:/run/current-system/sw/bin/zsh\n")).
|
|
||||||
Place(m("/etc/group"), []byte("hakurei:x:65534:\n")).
|
|
||||||
Bind(m("/tmp/hakurei.0/ebf083d1b175911782d413369b64ce7c/wayland"), m("/run/user/65534/wayland-0"), 0).
|
|
||||||
Bind(m("/run/user/1971/hakurei/ebf083d1b175911782d413369b64ce7c/pulse"), m("/run/user/65534/pulse/native"), 0).
|
|
||||||
Place(m(hst.PrivateTmp+"/pulse-cookie"), bytes.Repeat([]byte{0}, pulseCookieSizeMax)).
|
|
||||||
Bind(m("/tmp/hakurei.0/ebf083d1b175911782d413369b64ce7c/bus"), m("/run/user/65534/bus"), 0).
|
|
||||||
Bind(m("/tmp/hakurei.0/ebf083d1b175911782d413369b64ce7c/system_bus_socket"), m("/var/run/dbus/system_bus_socket"), 0).
|
|
||||||
Bind(m("/dev/dri"), m("/dev/dri"), bits.BindWritable|bits.BindDevice|bits.BindOptional).
|
|
||||||
Bind(m("/dev/kvm"), m("/dev/kvm"), bits.BindWritable|bits.BindDevice|bits.BindOptional).
|
|
||||||
Etc(m("/etc/"), "ebf083d1b175911782d413369b64ce7c").
|
|
||||||
Tmpfs(m("/run/user/1971"), 8192, 0755).
|
|
||||||
Tmpfs(m("/run/nscd"), 8192, 0755).
|
|
||||||
Tmpfs(m("/run/dbus"), 8192, 0755).
|
|
||||||
Remount(m("/dev/"), syscall.MS_RDONLY).
|
|
||||||
Remount(m("/"), syscall.MS_RDONLY),
|
|
||||||
SeccompPresets: bits.PresetExt | bits.PresetDenyDevel,
|
|
||||||
HostNet: true,
|
|
||||||
HostAbstract: true,
|
|
||||||
RetainSession: true,
|
|
||||||
ForwardCancel: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"nixos chromium direct wayland", new(stubNixOS),
|
|
||||||
&hst.Config{
|
|
||||||
ID: "org.chromium.Chromium",
|
|
||||||
Enablements: hst.NewEnablements(hst.EWayland | hst.EDBus | hst.EPulse),
|
|
||||||
Container: &hst.ContainerConfig{
|
|
||||||
Env: nil,
|
|
||||||
Filesystem: []hst.FilesystemConfigJSON{
|
|
||||||
f(&hst.FSBind{Source: m("/bin")}),
|
|
||||||
f(&hst.FSBind{Source: m("/usr/bin/")}),
|
|
||||||
f(&hst.FSBind{Source: m("/nix/store")}),
|
|
||||||
f(&hst.FSBind{Source: m("/run/current-system")}),
|
|
||||||
f(&hst.FSBind{Source: m("/sys/block"), Optional: true}),
|
|
||||||
f(&hst.FSBind{Source: m("/sys/bus"), Optional: true}),
|
|
||||||
f(&hst.FSBind{Source: m("/sys/class"), Optional: true}),
|
|
||||||
f(&hst.FSBind{Source: m("/sys/dev"), Optional: true}),
|
|
||||||
f(&hst.FSBind{Source: m("/sys/devices"), Optional: true}),
|
|
||||||
f(&hst.FSBind{Source: m("/run/opengl-driver")}),
|
|
||||||
f(&hst.FSBind{Source: m("/dev/dri"), Device: true, Optional: true}),
|
|
||||||
f(&hst.FSBind{Source: m("/etc/"), Target: m("/etc/"), Special: true}),
|
|
||||||
f(&hst.FSBind{Source: m("/var/lib/persist/module/hakurei/0/1"), Write: true, Ensure: true}),
|
|
||||||
},
|
|
||||||
|
|
||||||
Username: "u0_a1",
|
|
||||||
Shell: m("/run/current-system/sw/bin/zsh"),
|
|
||||||
Home: m("/var/lib/persist/module/hakurei/0/1"),
|
|
||||||
|
|
||||||
Path: m("/nix/store/yqivzpzzn7z5x0lq9hmbzygh45d8rhqd-chromium-start"),
|
|
||||||
|
|
||||||
Flags: hst.FUserns | hst.FHostNet | hst.FMapRealUID | hst.FShareRuntime | hst.FShareTmpdir,
|
|
||||||
},
|
|
||||||
SystemBus: &hst.BusConfig{
|
|
||||||
Talk: []string{"org.bluez", "org.freedesktop.Avahi", "org.freedesktop.UPower"},
|
|
||||||
Filter: true,
|
|
||||||
},
|
|
||||||
SessionBus: &hst.BusConfig{
|
|
||||||
Talk: []string{
|
|
||||||
"org.freedesktop.FileManager1", "org.freedesktop.Notifications",
|
|
||||||
"org.freedesktop.ScreenSaver", "org.freedesktop.secrets",
|
|
||||||
"org.kde.kwalletd5", "org.kde.kwalletd6",
|
|
||||||
},
|
|
||||||
Own: []string{
|
|
||||||
"org.chromium.Chromium.*",
|
|
||||||
"org.mpris.MediaPlayer2.org.chromium.Chromium.*",
|
|
||||||
"org.mpris.MediaPlayer2.chromium.*",
|
|
||||||
},
|
|
||||||
Call: map[string]string{}, Broadcast: map[string]string{},
|
|
||||||
Filter: true,
|
|
||||||
},
|
|
||||||
DirectWayland: true,
|
|
||||||
|
|
||||||
Identity: 1, Groups: []string{},
|
|
||||||
},
|
|
||||||
state.ID{
|
|
||||||
0x8e, 0x2c, 0x76, 0xb0,
|
|
||||||
0x66, 0xda, 0xbe, 0x57,
|
|
||||||
0x4c, 0xf0, 0x73, 0xbd,
|
|
||||||
0xb4, 0x6e, 0xb5, 0xc1,
|
|
||||||
},
|
|
||||||
system.New(t.Context(), msg, 1000001).
|
|
||||||
Ensure(m("/tmp/hakurei.0"), 0711).
|
|
||||||
Ensure(m("/tmp/hakurei.0/runtime"), 0700).UpdatePermType(system.User, m("/tmp/hakurei.0/runtime"), acl.Execute).
|
|
||||||
Ensure(m("/tmp/hakurei.0/runtime/1"), 0700).UpdatePermType(system.User, m("/tmp/hakurei.0/runtime/1"), acl.Read, acl.Write, acl.Execute).
|
|
||||||
Ensure(m("/tmp/hakurei.0/tmpdir"), 0700).UpdatePermType(system.User, m("/tmp/hakurei.0/tmpdir"), acl.Execute).
|
|
||||||
Ensure(m("/tmp/hakurei.0/tmpdir/1"), 01700).UpdatePermType(system.User, m("/tmp/hakurei.0/tmpdir/1"), acl.Read, acl.Write, acl.Execute).
|
|
||||||
Ensure(m("/run/user/1971/hakurei"), 0700).UpdatePermType(system.User, m("/run/user/1971/hakurei"), acl.Execute).
|
|
||||||
Ensure(m("/run/user/1971"), 0700).UpdatePermType(system.User, m("/run/user/1971"), acl.Execute). // this is ordered as is because the previous Ensure only calls mkdir if XDG_RUNTIME_DIR is unset
|
|
||||||
UpdatePermType(hst.EWayland, m("/run/user/1971/wayland-0"), acl.Read, acl.Write, acl.Execute).
|
|
||||||
Ephemeral(system.Process, m("/run/user/1971/hakurei/8e2c76b066dabe574cf073bdb46eb5c1"), 0700).UpdatePermType(system.Process, m("/run/user/1971/hakurei/8e2c76b066dabe574cf073bdb46eb5c1"), acl.Execute).
|
|
||||||
Link(m("/run/user/1971/pulse/native"), m("/run/user/1971/hakurei/8e2c76b066dabe574cf073bdb46eb5c1/pulse")).
|
|
||||||
Ephemeral(system.Process, m("/tmp/hakurei.0/8e2c76b066dabe574cf073bdb46eb5c1"), 0711).
|
|
||||||
MustProxyDBus(&hst.BusConfig{
|
|
||||||
Talk: []string{
|
|
||||||
"org.freedesktop.FileManager1", "org.freedesktop.Notifications",
|
|
||||||
"org.freedesktop.ScreenSaver", "org.freedesktop.secrets",
|
|
||||||
"org.kde.kwalletd5", "org.kde.kwalletd6",
|
|
||||||
},
|
|
||||||
Own: []string{
|
|
||||||
"org.chromium.Chromium.*",
|
|
||||||
"org.mpris.MediaPlayer2.org.chromium.Chromium.*",
|
|
||||||
"org.mpris.MediaPlayer2.chromium.*",
|
|
||||||
},
|
|
||||||
Call: map[string]string{}, Broadcast: map[string]string{},
|
|
||||||
Filter: true,
|
|
||||||
}, &hst.BusConfig{
|
|
||||||
Talk: []string{
|
|
||||||
"org.bluez",
|
|
||||||
"org.freedesktop.Avahi",
|
|
||||||
"org.freedesktop.UPower",
|
|
||||||
},
|
|
||||||
Filter: true,
|
|
||||||
}, dbus.ProxyPair{
|
|
||||||
"unix:path=/run/user/1971/bus",
|
|
||||||
"/tmp/hakurei.0/8e2c76b066dabe574cf073bdb46eb5c1/bus",
|
|
||||||
}, dbus.ProxyPair{
|
|
||||||
"unix:path=/var/run/dbus/system_bus_socket",
|
|
||||||
"/tmp/hakurei.0/8e2c76b066dabe574cf073bdb46eb5c1/system_bus_socket",
|
|
||||||
}).
|
|
||||||
UpdatePerm(m("/tmp/hakurei.0/8e2c76b066dabe574cf073bdb46eb5c1/bus"), acl.Read, acl.Write).
|
|
||||||
UpdatePerm(m("/tmp/hakurei.0/8e2c76b066dabe574cf073bdb46eb5c1/system_bus_socket"), acl.Read, acl.Write),
|
|
||||||
&container.Params{
|
|
||||||
Uid: 1971,
|
|
||||||
Gid: 100,
|
|
||||||
Dir: m("/var/lib/persist/module/hakurei/0/1"),
|
|
||||||
Path: m("/nix/store/yqivzpzzn7z5x0lq9hmbzygh45d8rhqd-chromium-start"),
|
Path: m("/nix/store/yqivzpzzn7z5x0lq9hmbzygh45d8rhqd-chromium-start"),
|
||||||
Args: []string{"/nix/store/yqivzpzzn7z5x0lq9hmbzygh45d8rhqd-chromium-start"},
|
|
||||||
Env: []string{
|
Flags: hst.FUserns | hst.FHostNet | hst.FMapRealUID | hst.FShareRuntime | hst.FShareTmpdir,
|
||||||
"DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1971/bus",
|
|
||||||
"DBUS_SYSTEM_BUS_ADDRESS=unix:path=/var/run/dbus/system_bus_socket",
|
|
||||||
"HOME=/var/lib/persist/module/hakurei/0/1",
|
|
||||||
"PULSE_COOKIE=" + hst.PrivateTmp + "/pulse-cookie",
|
|
||||||
"PULSE_SERVER=unix:/run/user/1971/pulse/native",
|
|
||||||
"SHELL=/run/current-system/sw/bin/zsh",
|
|
||||||
"TERM=xterm-256color",
|
|
||||||
"USER=u0_a1",
|
|
||||||
"WAYLAND_DISPLAY=wayland-0",
|
|
||||||
"XDG_RUNTIME_DIR=/run/user/1971",
|
|
||||||
"XDG_SESSION_CLASS=user",
|
|
||||||
"XDG_SESSION_TYPE=wayland",
|
|
||||||
},
|
|
||||||
Ops: new(container.Ops).
|
|
||||||
Proc(m("/proc/")).
|
|
||||||
Tmpfs(hst.AbsPrivateTmp, 4096, 0755).
|
|
||||||
DevWritable(m("/dev/"), true).
|
|
||||||
Tmpfs(m("/dev/shm"), 0, 01777).
|
|
||||||
Tmpfs(m("/run/user/"), 4096, 0755).
|
|
||||||
Bind(m("/tmp/hakurei.0/runtime/1"), m("/run/user/1971"), bits.BindWritable).
|
|
||||||
Bind(m("/tmp/hakurei.0/tmpdir/1"), m("/tmp/"), bits.BindWritable).
|
|
||||||
Place(m("/etc/passwd"), []byte("u0_a1:x:1971:100:Hakurei:/var/lib/persist/module/hakurei/0/1:/run/current-system/sw/bin/zsh\n")).
|
|
||||||
Place(m("/etc/group"), []byte("hakurei:x:100:\n")).
|
|
||||||
Bind(m("/run/user/1971/wayland-0"), m("/run/user/1971/wayland-0"), 0).
|
|
||||||
Bind(m("/run/user/1971/hakurei/8e2c76b066dabe574cf073bdb46eb5c1/pulse"), m("/run/user/1971/pulse/native"), 0).
|
|
||||||
Place(m(hst.PrivateTmp+"/pulse-cookie"), bytes.Repeat([]byte{0}, pulseCookieSizeMax)).
|
|
||||||
Bind(m("/tmp/hakurei.0/8e2c76b066dabe574cf073bdb46eb5c1/bus"), m("/run/user/1971/bus"), 0).
|
|
||||||
Bind(m("/tmp/hakurei.0/8e2c76b066dabe574cf073bdb46eb5c1/system_bus_socket"), m("/var/run/dbus/system_bus_socket"), 0).
|
|
||||||
Bind(m("/bin"), m("/bin"), 0).
|
|
||||||
Bind(m("/usr/bin/"), m("/usr/bin/"), 0).
|
|
||||||
Bind(m("/nix/store"), m("/nix/store"), 0).
|
|
||||||
Bind(m("/run/current-system"), m("/run/current-system"), 0).
|
|
||||||
Bind(m("/sys/block"), m("/sys/block"), bits.BindOptional).
|
|
||||||
Bind(m("/sys/bus"), m("/sys/bus"), bits.BindOptional).
|
|
||||||
Bind(m("/sys/class"), m("/sys/class"), bits.BindOptional).
|
|
||||||
Bind(m("/sys/dev"), m("/sys/dev"), bits.BindOptional).
|
|
||||||
Bind(m("/sys/devices"), m("/sys/devices"), bits.BindOptional).
|
|
||||||
Bind(m("/run/opengl-driver"), m("/run/opengl-driver"), 0).
|
|
||||||
Bind(m("/dev/dri"), m("/dev/dri"), bits.BindDevice|bits.BindWritable|bits.BindOptional).
|
|
||||||
Etc(m("/etc/"), "8e2c76b066dabe574cf073bdb46eb5c1").
|
|
||||||
Bind(m("/var/lib/persist/module/hakurei/0/1"), m("/var/lib/persist/module/hakurei/0/1"), bits.BindWritable|bits.BindEnsure).
|
|
||||||
Remount(m("/dev/"), syscall.MS_RDONLY).
|
|
||||||
Remount(m("/"), syscall.MS_RDONLY),
|
|
||||||
SeccompPresets: bits.PresetExt | bits.PresetDenyTTY | bits.PresetDenyDevel,
|
|
||||||
HostNet: true,
|
|
||||||
ForwardCancel: true,
|
|
||||||
},
|
},
|
||||||
},
|
SystemBus: &hst.BusConfig{
|
||||||
|
Talk: []string{"org.bluez", "org.freedesktop.Avahi", "org.freedesktop.UPower"},
|
||||||
|
Filter: true,
|
||||||
|
},
|
||||||
|
SessionBus: &hst.BusConfig{
|
||||||
|
Talk: []string{
|
||||||
|
"org.freedesktop.FileManager1", "org.freedesktop.Notifications",
|
||||||
|
"org.freedesktop.ScreenSaver", "org.freedesktop.secrets",
|
||||||
|
"org.kde.kwalletd5", "org.kde.kwalletd6",
|
||||||
|
},
|
||||||
|
Own: []string{
|
||||||
|
"org.chromium.Chromium.*",
|
||||||
|
"org.mpris.MediaPlayer2.org.chromium.Chromium.*",
|
||||||
|
"org.mpris.MediaPlayer2.chromium.*",
|
||||||
|
},
|
||||||
|
Call: map[string]string{}, Broadcast: map[string]string{},
|
||||||
|
Filter: true,
|
||||||
|
},
|
||||||
|
DirectWayland: true,
|
||||||
|
|
||||||
|
Identity: 1, Groups: []string{},
|
||||||
|
}, state.ID{
|
||||||
|
0x8e, 0x2c, 0x76, 0xb0,
|
||||||
|
0x66, 0xda, 0xbe, 0x57,
|
||||||
|
0x4c, 0xf0, 0x73, 0xbd,
|
||||||
|
0xb4, 0x6e, 0xb5, 0xc1,
|
||||||
|
}, system.New(t.Context(), msg, 1000001).
|
||||||
|
Ensure(m("/tmp/hakurei.0"), 0711).
|
||||||
|
Ensure(m("/tmp/hakurei.0/runtime"), 0700).UpdatePermType(system.User, m("/tmp/hakurei.0/runtime"), acl.Execute).
|
||||||
|
Ensure(m("/tmp/hakurei.0/runtime/1"), 0700).UpdatePermType(system.User, m("/tmp/hakurei.0/runtime/1"), acl.Read, acl.Write, acl.Execute).
|
||||||
|
Ensure(m("/tmp/hakurei.0/tmpdir"), 0700).UpdatePermType(system.User, m("/tmp/hakurei.0/tmpdir"), acl.Execute).
|
||||||
|
Ensure(m("/tmp/hakurei.0/tmpdir/1"), 01700).UpdatePermType(system.User, m("/tmp/hakurei.0/tmpdir/1"), acl.Read, acl.Write, acl.Execute).
|
||||||
|
Ensure(m("/run/user/1971/hakurei"), 0700).UpdatePermType(system.User, m("/run/user/1971/hakurei"), acl.Execute).
|
||||||
|
Ensure(m("/run/user/1971"), 0700).UpdatePermType(system.User, m("/run/user/1971"), acl.Execute). // this is ordered as is because the previous Ensure only calls mkdir if XDG_RUNTIME_DIR is unset
|
||||||
|
UpdatePermType(hst.EWayland, m("/run/user/1971/wayland-0"), acl.Read, acl.Write, acl.Execute).
|
||||||
|
Ephemeral(system.Process, m("/run/user/1971/hakurei/8e2c76b066dabe574cf073bdb46eb5c1"), 0700).UpdatePermType(system.Process, m("/run/user/1971/hakurei/8e2c76b066dabe574cf073bdb46eb5c1"), acl.Execute).
|
||||||
|
Link(m("/run/user/1971/pulse/native"), m("/run/user/1971/hakurei/8e2c76b066dabe574cf073bdb46eb5c1/pulse")).
|
||||||
|
Ephemeral(system.Process, m("/tmp/hakurei.0/8e2c76b066dabe574cf073bdb46eb5c1"), 0711).
|
||||||
|
MustProxyDBus(&hst.BusConfig{
|
||||||
|
Talk: []string{
|
||||||
|
"org.freedesktop.FileManager1", "org.freedesktop.Notifications",
|
||||||
|
"org.freedesktop.ScreenSaver", "org.freedesktop.secrets",
|
||||||
|
"org.kde.kwalletd5", "org.kde.kwalletd6",
|
||||||
|
},
|
||||||
|
Own: []string{
|
||||||
|
"org.chromium.Chromium.*",
|
||||||
|
"org.mpris.MediaPlayer2.org.chromium.Chromium.*",
|
||||||
|
"org.mpris.MediaPlayer2.chromium.*",
|
||||||
|
},
|
||||||
|
Call: map[string]string{}, Broadcast: map[string]string{},
|
||||||
|
Filter: true,
|
||||||
|
}, &hst.BusConfig{
|
||||||
|
Talk: []string{
|
||||||
|
"org.bluez",
|
||||||
|
"org.freedesktop.Avahi",
|
||||||
|
"org.freedesktop.UPower",
|
||||||
|
},
|
||||||
|
Filter: true,
|
||||||
|
}, dbus.ProxyPair{
|
||||||
|
"unix:path=/run/user/1971/bus",
|
||||||
|
"/tmp/hakurei.0/8e2c76b066dabe574cf073bdb46eb5c1/bus",
|
||||||
|
}, dbus.ProxyPair{
|
||||||
|
"unix:path=/var/run/dbus/system_bus_socket",
|
||||||
|
"/tmp/hakurei.0/8e2c76b066dabe574cf073bdb46eb5c1/system_bus_socket",
|
||||||
|
}).
|
||||||
|
UpdatePerm(m("/tmp/hakurei.0/8e2c76b066dabe574cf073bdb46eb5c1/bus"), acl.Read, acl.Write).
|
||||||
|
UpdatePerm(m("/tmp/hakurei.0/8e2c76b066dabe574cf073bdb46eb5c1/system_bus_socket"), acl.Read, acl.Write), &container.Params{
|
||||||
|
|
||||||
|
Uid: 1971,
|
||||||
|
Gid: 100,
|
||||||
|
Dir: m("/var/lib/persist/module/hakurei/0/1"),
|
||||||
|
Path: m("/nix/store/yqivzpzzn7z5x0lq9hmbzygh45d8rhqd-chromium-start"),
|
||||||
|
Args: []string{"/nix/store/yqivzpzzn7z5x0lq9hmbzygh45d8rhqd-chromium-start"},
|
||||||
|
Env: []string{
|
||||||
|
"DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1971/bus",
|
||||||
|
"DBUS_SYSTEM_BUS_ADDRESS=unix:path=/var/run/dbus/system_bus_socket",
|
||||||
|
"HOME=/var/lib/persist/module/hakurei/0/1",
|
||||||
|
"PULSE_COOKIE=" + hst.PrivateTmp + "/pulse-cookie",
|
||||||
|
"PULSE_SERVER=unix:/run/user/1971/pulse/native",
|
||||||
|
"SHELL=/run/current-system/sw/bin/zsh",
|
||||||
|
"TERM=xterm-256color",
|
||||||
|
"USER=u0_a1",
|
||||||
|
"WAYLAND_DISPLAY=wayland-0",
|
||||||
|
"XDG_RUNTIME_DIR=/run/user/1971",
|
||||||
|
"XDG_SESSION_CLASS=user",
|
||||||
|
"XDG_SESSION_TYPE=wayland",
|
||||||
|
},
|
||||||
|
Ops: new(container.Ops).
|
||||||
|
Proc(m("/proc/")).
|
||||||
|
Tmpfs(hst.AbsPrivateTmp, 4096, 0755).
|
||||||
|
DevWritable(m("/dev/"), true).
|
||||||
|
Tmpfs(m("/dev/shm"), 0, 01777).
|
||||||
|
Tmpfs(m("/run/user/"), 4096, 0755).
|
||||||
|
Bind(m("/tmp/hakurei.0/runtime/1"), m("/run/user/1971"), comp.BindWritable).
|
||||||
|
Bind(m("/tmp/hakurei.0/tmpdir/1"), m("/tmp/"), comp.BindWritable).
|
||||||
|
Place(m("/etc/passwd"), []byte("u0_a1:x:1971:100:Hakurei:/var/lib/persist/module/hakurei/0/1:/run/current-system/sw/bin/zsh\n")).
|
||||||
|
Place(m("/etc/group"), []byte("hakurei:x:100:\n")).
|
||||||
|
Bind(m("/run/user/1971/wayland-0"), m("/run/user/1971/wayland-0"), 0).
|
||||||
|
Bind(m("/run/user/1971/hakurei/8e2c76b066dabe574cf073bdb46eb5c1/pulse"), m("/run/user/1971/pulse/native"), 0).
|
||||||
|
Place(m(hst.PrivateTmp+"/pulse-cookie"), bytes.Repeat([]byte{0}, pulseCookieSizeMax)).
|
||||||
|
Bind(m("/tmp/hakurei.0/8e2c76b066dabe574cf073bdb46eb5c1/bus"), m("/run/user/1971/bus"), 0).
|
||||||
|
Bind(m("/tmp/hakurei.0/8e2c76b066dabe574cf073bdb46eb5c1/system_bus_socket"), m("/var/run/dbus/system_bus_socket"), 0).
|
||||||
|
Bind(m("/bin"), m("/bin"), 0).
|
||||||
|
Bind(m("/usr/bin/"), m("/usr/bin/"), 0).
|
||||||
|
Bind(m("/nix/store"), m("/nix/store"), 0).
|
||||||
|
Bind(m("/run/current-system"), m("/run/current-system"), 0).
|
||||||
|
Bind(m("/sys/block"), m("/sys/block"), comp.BindOptional).
|
||||||
|
Bind(m("/sys/bus"), m("/sys/bus"), comp.BindOptional).
|
||||||
|
Bind(m("/sys/class"), m("/sys/class"), comp.BindOptional).
|
||||||
|
Bind(m("/sys/dev"), m("/sys/dev"), comp.BindOptional).
|
||||||
|
Bind(m("/sys/devices"), m("/sys/devices"), comp.BindOptional).
|
||||||
|
Bind(m("/run/opengl-driver"), m("/run/opengl-driver"), 0).
|
||||||
|
Bind(m("/dev/dri"), m("/dev/dri"), comp.BindDevice|comp.BindWritable|comp.BindOptional).
|
||||||
|
Etc(m("/etc/"), "8e2c76b066dabe574cf073bdb46eb5c1").
|
||||||
|
Bind(m("/var/lib/persist/module/hakurei/0/1"), m("/var/lib/persist/module/hakurei/0/1"), comp.BindWritable|comp.BindEnsure).
|
||||||
|
Remount(m("/dev/"), syscall.MS_RDONLY).
|
||||||
|
Remount(m("/"), syscall.MS_RDONLY),
|
||||||
|
SeccompPresets: comp.PresetExt | comp.PresetDenyTTY | comp.PresetDenyDevel,
|
||||||
|
HostNet: true,
|
||||||
|
ForwardCancel: true,
|
||||||
|
}},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
@@ -574,10 +707,9 @@ func (s stubOsFileReadCloser) Stat() (fs.FileInfo, error) { panic("attempting to
|
|||||||
|
|
||||||
type stubNixOS struct {
|
type stubNixOS struct {
|
||||||
usernameErr map[string]error
|
usernameErr map[string]error
|
||||||
|
panicDispatcher
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k *stubNixOS) new(func(k syscallDispatcher)) { panic("not implemented") }
|
|
||||||
|
|
||||||
func (k *stubNixOS) getpid() int { return 0xdeadbeef }
|
func (k *stubNixOS) getpid() int { return 0xdeadbeef }
|
||||||
func (k *stubNixOS) getuid() int { return 1971 }
|
func (k *stubNixOS) getuid() int { return 1971 }
|
||||||
func (k *stubNixOS) getgid() int { return 100 }
|
func (k *stubNixOS) getgid() int { return 100 }
|
||||||
@@ -659,6 +791,10 @@ func (k *stubNixOS) readdir(name string) ([]fs.DirEntry, error) {
|
|||||||
"tmpfiles.d", "udev", "udisks2", "UPower", "vconsole.conf", "X11", "zfs", "zinputrc",
|
"tmpfiles.d", "udev", "udisks2", "UPower", "vconsole.conf", "X11", "zfs", "zinputrc",
|
||||||
"zoneinfo", "zprofile", "zshenv", "zshrc")
|
"zoneinfo", "zprofile", "zshenv", "zshrc")
|
||||||
|
|
||||||
|
case "/var/lib/hakurei/base/org.debian":
|
||||||
|
return stubDirEntries("bin", "dev", "etc", "home", "lib64", "lost+found",
|
||||||
|
"mnt", "nix", "proc", "root", "run", "srv", "sys", "tmp", "usr", "var")
|
||||||
|
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("attempted to read unexpected directory %q", name))
|
panic(fmt.Sprintf("attempted to read unexpected directory %q", name))
|
||||||
}
|
}
|
||||||
@@ -726,6 +862,38 @@ func (k *stubNixOS) evalSymlinks(path string) (string, error) {
|
|||||||
return "/nix/store/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-graphics-drivers", nil
|
return "/nix/store/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-graphics-drivers", nil
|
||||||
case "/var/lib/persist/module/hakurei/0/1":
|
case "/var/lib/persist/module/hakurei/0/1":
|
||||||
return "/var/lib/persist/module/hakurei/0/1", nil
|
return "/var/lib/persist/module/hakurei/0/1", nil
|
||||||
|
|
||||||
|
case "/var/lib/hakurei/nix/u0/org.chromium.Chromium/rw-store/upper":
|
||||||
|
return "/var/lib/hakurei/nix/u0/org.chromium.Chromium/rw-store/upper", nil
|
||||||
|
case "/var/lib/hakurei/nix/u0/org.chromium.Chromium/rw-store/work":
|
||||||
|
return "/var/lib/hakurei/nix/u0/org.chromium.Chromium/rw-store/work", nil
|
||||||
|
case "/var/lib/hakurei/base/org.nixos/ro-store":
|
||||||
|
return "/var/lib/hakurei/base/org.nixos/ro-store", nil
|
||||||
|
case "/var/lib/hakurei/u0/org.chromium.Chromium":
|
||||||
|
return "/var/lib/hakurei/u0/org.chromium.Chromium", nil
|
||||||
|
case "/var/lib/hakurei/base/org.debian/bin":
|
||||||
|
return "/var/lib/hakurei/base/org.debian/bin", nil
|
||||||
|
case "/var/lib/hakurei/base/org.debian/home":
|
||||||
|
return "/var/lib/hakurei/base/org.debian/home", nil
|
||||||
|
case "/var/lib/hakurei/base/org.debian/lib64":
|
||||||
|
return "/var/lib/hakurei/base/org.debian/lib64", nil
|
||||||
|
case "/var/lib/hakurei/base/org.debian/lost+found":
|
||||||
|
return "/var/lib/hakurei/base/org.debian/lost+found", nil
|
||||||
|
case "/var/lib/hakurei/base/org.debian/nix":
|
||||||
|
return "/var/lib/hakurei/base/org.debian/nix", nil
|
||||||
|
case "/var/lib/hakurei/base/org.debian/root":
|
||||||
|
return "/var/lib/hakurei/base/org.debian/root", nil
|
||||||
|
case "/var/lib/hakurei/base/org.debian/run":
|
||||||
|
return "/var/lib/hakurei/base/org.debian/run", nil
|
||||||
|
case "/var/lib/hakurei/base/org.debian/srv":
|
||||||
|
return "/var/lib/hakurei/base/org.debian/srv", nil
|
||||||
|
case "/var/lib/hakurei/base/org.debian/sys":
|
||||||
|
return "/var/lib/hakurei/base/org.debian/sys", nil
|
||||||
|
case "/var/lib/hakurei/base/org.debian/usr":
|
||||||
|
return "/var/lib/hakurei/base/org.debian/usr", nil
|
||||||
|
case "/var/lib/hakurei/base/org.debian/var":
|
||||||
|
return "/var/lib/hakurei/base/org.debian/var", nil
|
||||||
|
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("attempted to evaluate unexpected path %q", path))
|
panic(fmt.Sprintf("attempted to evaluate unexpected path %q", path))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,18 @@
|
|||||||
package app
|
package app
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"io"
|
"io"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"log"
|
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"os/signal"
|
||||||
"os/user"
|
"os/user"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"hakurei.app/container"
|
"hakurei.app/container"
|
||||||
"hakurei.app/container/check"
|
"hakurei.app/container/check"
|
||||||
|
"hakurei.app/container/seccomp"
|
||||||
"hakurei.app/internal"
|
"hakurei.app/internal"
|
||||||
"hakurei.app/message"
|
"hakurei.app/message"
|
||||||
"hakurei.app/system/dbus"
|
"hakurei.app/system/dbus"
|
||||||
@@ -28,7 +30,7 @@ type syscallDispatcher interface {
|
|||||||
// new starts a goroutine with a new instance of syscallDispatcher.
|
// new starts a goroutine with a new instance of syscallDispatcher.
|
||||||
// A syscallDispatcher must never be used in any goroutine other than the one owning it,
|
// A syscallDispatcher must never be used in any goroutine other than the one owning it,
|
||||||
// just synchronising access is not enough, as this is for test instrumentation.
|
// just synchronising access is not enough, as this is for test instrumentation.
|
||||||
new(f func(k syscallDispatcher))
|
new(f func(k syscallDispatcher, msg message.Msg))
|
||||||
|
|
||||||
// getpid provides [os.Getpid].
|
// getpid provides [os.Getpid].
|
||||||
getpid() int
|
getpid() int
|
||||||
@@ -38,6 +40,8 @@ type syscallDispatcher interface {
|
|||||||
getgid() int
|
getgid() int
|
||||||
// lookupEnv provides [os.LookupEnv].
|
// lookupEnv provides [os.LookupEnv].
|
||||||
lookupEnv(key string) (string, bool)
|
lookupEnv(key string) (string, bool)
|
||||||
|
// pipe provides os.Pipe.
|
||||||
|
pipe() (r, w *os.File, err error)
|
||||||
// stat provides [os.Stat].
|
// stat provides [os.Stat].
|
||||||
stat(name string) (os.FileInfo, error)
|
stat(name string) (os.FileInfo, error)
|
||||||
// open provides [os.Open].
|
// open provides [os.Open].
|
||||||
@@ -46,6 +50,8 @@ type syscallDispatcher interface {
|
|||||||
readdir(name string) ([]os.DirEntry, error)
|
readdir(name string) ([]os.DirEntry, error)
|
||||||
// tempdir provides [os.TempDir].
|
// tempdir provides [os.TempDir].
|
||||||
tempdir() string
|
tempdir() string
|
||||||
|
// exit provides [os.Exit].
|
||||||
|
exit(code int)
|
||||||
|
|
||||||
// evalSymlinks provides [filepath.EvalSymlinks].
|
// evalSymlinks provides [filepath.EvalSymlinks].
|
||||||
evalSymlinks(path string) (string, error)
|
evalSymlinks(path string) (string, error)
|
||||||
@@ -56,10 +62,29 @@ type syscallDispatcher interface {
|
|||||||
// cmdOutput provides the Output method of [exec.Cmd].
|
// cmdOutput provides the Output method of [exec.Cmd].
|
||||||
cmdOutput(cmd *exec.Cmd) ([]byte, error)
|
cmdOutput(cmd *exec.Cmd) ([]byte, error)
|
||||||
|
|
||||||
|
// notifyContext provides [signal.NotifyContext].
|
||||||
|
notifyContext(parent context.Context, signals ...os.Signal) (ctx context.Context, stop context.CancelFunc)
|
||||||
|
|
||||||
|
// prctl provides [container.Prctl].
|
||||||
|
prctl(op, arg2, arg3 uintptr) error
|
||||||
// overflowUid provides [container.OverflowUid].
|
// overflowUid provides [container.OverflowUid].
|
||||||
overflowUid(msg message.Msg) int
|
overflowUid(msg message.Msg) int
|
||||||
// overflowGid provides [container.OverflowGid].
|
// overflowGid provides [container.OverflowGid].
|
||||||
overflowGid(msg message.Msg) int
|
overflowGid(msg message.Msg) int
|
||||||
|
// setDumpable provides [container.SetDumpable].
|
||||||
|
setDumpable(dumpable uintptr) error
|
||||||
|
// receive provides [container.Receive].
|
||||||
|
receive(key string, e any, fdp *uintptr) (closeFunc func() error, err error)
|
||||||
|
|
||||||
|
// containerStart provides the Start method of [container.Container].
|
||||||
|
containerStart(z *container.Container) error
|
||||||
|
// containerStart provides the Serve method of [container.Container].
|
||||||
|
containerServe(z *container.Container) error
|
||||||
|
// containerStart provides the Wait method of [container.Container].
|
||||||
|
containerWait(z *container.Container) error
|
||||||
|
|
||||||
|
// seccompLoad provides [seccomp.Load].
|
||||||
|
seccompLoad(rules []seccomp.NativeRule, flags seccomp.ExportFlag) error
|
||||||
|
|
||||||
// mustHsuPath provides [internal.MustHsuPath].
|
// mustHsuPath provides [internal.MustHsuPath].
|
||||||
mustHsuPath() *check.Absolute
|
mustHsuPath() *check.Absolute
|
||||||
@@ -67,23 +92,32 @@ type syscallDispatcher interface {
|
|||||||
// dbusAddress provides [dbus.Address].
|
// dbusAddress provides [dbus.Address].
|
||||||
dbusAddress() (session, system string)
|
dbusAddress() (session, system string)
|
||||||
|
|
||||||
|
// setupContSignal provides setupContSignal.
|
||||||
|
setupContSignal(pid int) (io.ReadCloser, func(), error)
|
||||||
|
|
||||||
|
// getMsg returns the [message.Msg] held by syscallDispatcher.
|
||||||
|
getMsg() message.Msg
|
||||||
|
// fatal provides [log.Fatal].
|
||||||
|
fatal(v ...any)
|
||||||
// fatalf provides [log.Fatalf].
|
// fatalf provides [log.Fatalf].
|
||||||
fatalf(format string, v ...any)
|
fatalf(format string, v ...any)
|
||||||
}
|
}
|
||||||
|
|
||||||
// direct implements syscallDispatcher on the current kernel.
|
// direct implements syscallDispatcher on the current kernel.
|
||||||
type direct struct{}
|
type direct struct{ msg message.Msg }
|
||||||
|
|
||||||
func (k direct) new(f func(k syscallDispatcher)) { go f(k) }
|
func (k direct) new(f func(k syscallDispatcher, msg message.Msg)) { go f(k, k.msg) }
|
||||||
|
|
||||||
func (direct) getpid() int { return os.Getpid() }
|
func (direct) getpid() int { return os.Getpid() }
|
||||||
func (direct) getuid() int { return os.Getuid() }
|
func (direct) getuid() int { return os.Getuid() }
|
||||||
func (direct) getgid() int { return os.Getgid() }
|
func (direct) getgid() int { return os.Getgid() }
|
||||||
func (direct) lookupEnv(key string) (string, bool) { return os.LookupEnv(key) }
|
func (direct) lookupEnv(key string) (string, bool) { return os.LookupEnv(key) }
|
||||||
|
func (direct) pipe() (r, w *os.File, err error) { return os.Pipe() }
|
||||||
func (direct) stat(name string) (os.FileInfo, error) { return os.Stat(name) }
|
func (direct) stat(name string) (os.FileInfo, error) { return os.Stat(name) }
|
||||||
func (direct) open(name string) (osFile, error) { return os.Open(name) }
|
func (direct) open(name string) (osFile, error) { return os.Open(name) }
|
||||||
func (direct) readdir(name string) ([]os.DirEntry, error) { return os.ReadDir(name) }
|
func (direct) readdir(name string) ([]os.DirEntry, error) { return os.ReadDir(name) }
|
||||||
func (direct) tempdir() string { return os.TempDir() }
|
func (direct) tempdir() string { return os.TempDir() }
|
||||||
|
func (direct) exit(code int) { os.Exit(code) }
|
||||||
|
|
||||||
func (direct) evalSymlinks(path string) (string, error) { return filepath.EvalSymlinks(path) }
|
func (direct) evalSymlinks(path string) (string, error) { return filepath.EvalSymlinks(path) }
|
||||||
|
|
||||||
@@ -98,11 +132,32 @@ func (direct) lookupGroupId(name string) (gid string, err error) {
|
|||||||
|
|
||||||
func (direct) cmdOutput(cmd *exec.Cmd) ([]byte, error) { return cmd.Output() }
|
func (direct) cmdOutput(cmd *exec.Cmd) ([]byte, error) { return cmd.Output() }
|
||||||
|
|
||||||
func (direct) overflowUid(msg message.Msg) int { return container.OverflowUid(msg) }
|
func (direct) notifyContext(parent context.Context, signals ...os.Signal) (ctx context.Context, stop context.CancelFunc) {
|
||||||
func (direct) overflowGid(msg message.Msg) int { return container.OverflowGid(msg) }
|
return signal.NotifyContext(parent, signals...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (direct) prctl(op, arg2, arg3 uintptr) error { return container.Prctl(op, arg2, arg3) }
|
||||||
|
func (direct) overflowUid(msg message.Msg) int { return container.OverflowUid(msg) }
|
||||||
|
func (direct) overflowGid(msg message.Msg) int { return container.OverflowGid(msg) }
|
||||||
|
func (direct) setDumpable(dumpable uintptr) error { return container.SetDumpable(dumpable) }
|
||||||
|
func (direct) receive(key string, e any, fdp *uintptr) (func() error, error) {
|
||||||
|
return container.Receive(key, e, fdp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (direct) containerStart(z *container.Container) error { return z.Start() }
|
||||||
|
func (direct) containerServe(z *container.Container) error { return z.Serve() }
|
||||||
|
func (direct) containerWait(z *container.Container) error { return z.Wait() }
|
||||||
|
|
||||||
|
func (direct) seccompLoad(rules []seccomp.NativeRule, flags seccomp.ExportFlag) error {
|
||||||
|
return seccomp.Load(rules, flags)
|
||||||
|
}
|
||||||
|
|
||||||
func (direct) mustHsuPath() *check.Absolute { return internal.MustHsuPath() }
|
func (direct) mustHsuPath() *check.Absolute { return internal.MustHsuPath() }
|
||||||
|
|
||||||
func (k direct) dbusAddress() (session, system string) { return dbus.Address() }
|
func (direct) dbusAddress() (session, system string) { return dbus.Address() }
|
||||||
|
|
||||||
func (direct) fatalf(format string, v ...any) { log.Fatalf(format, v...) }
|
func (direct) setupContSignal(pid int) (io.ReadCloser, func(), error) { return setupContSignal(pid) }
|
||||||
|
|
||||||
|
func (k direct) getMsg() message.Msg { return k.msg }
|
||||||
|
func (k direct) fatal(v ...any) { k.msg.GetLogger().Fatal(v...) }
|
||||||
|
func (k direct) fatalf(format string, v ...any) { k.msg.GetLogger().Fatalf(format, v...) }
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package app
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"io"
|
"io"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"log"
|
"log"
|
||||||
@@ -10,11 +11,14 @@ import (
|
|||||||
"os/exec"
|
"os/exec"
|
||||||
"reflect"
|
"reflect"
|
||||||
"slices"
|
"slices"
|
||||||
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
"hakurei.app/container"
|
"hakurei.app/container"
|
||||||
"hakurei.app/container/check"
|
"hakurei.app/container/check"
|
||||||
|
"hakurei.app/container/seccomp"
|
||||||
"hakurei.app/container/stub"
|
"hakurei.app/container/stub"
|
||||||
"hakurei.app/hst"
|
"hakurei.app/hst"
|
||||||
"hakurei.app/internal/app/state"
|
"hakurei.app/internal/app/state"
|
||||||
@@ -312,6 +316,10 @@ type kstub struct {
|
|||||||
*stub.Stub[syscallDispatcher]
|
*stub.Stub[syscallDispatcher]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (k *kstub) new(f func(k syscallDispatcher, msg message.Msg)) {
|
||||||
|
k.New(func(k syscallDispatcher) { f(k, k.(*kstub)) })
|
||||||
|
}
|
||||||
|
|
||||||
func (k *kstub) getpid() int { k.Helper(); return k.Expects("getpid").Ret.(int) }
|
func (k *kstub) getpid() int { k.Helper(); return k.Expects("getpid").Ret.(int) }
|
||||||
func (k *kstub) getuid() int { k.Helper(); return k.Expects("getuid").Ret.(int) }
|
func (k *kstub) getuid() int { k.Helper(); return k.Expects("getuid").Ret.(int) }
|
||||||
func (k *kstub) getgid() int { k.Helper(); return k.Expects("getgid").Ret.(int) }
|
func (k *kstub) getgid() int { k.Helper(); return k.Expects("getgid").Ret.(int) }
|
||||||
@@ -353,6 +361,61 @@ func (k *kstub) evalSymlinks(path string) (string, error) {
|
|||||||
stub.CheckArg(k.Stub, "path", path, 0))
|
stub.CheckArg(k.Stub, "path", path, 0))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (k *kstub) prctl(op, arg2, arg3 uintptr) error {
|
||||||
|
k.Helper()
|
||||||
|
return k.Expects("prctl").Error(
|
||||||
|
stub.CheckArg(k.Stub, "op", op, 0),
|
||||||
|
stub.CheckArg(k.Stub, "arg2", arg2, 1),
|
||||||
|
stub.CheckArg(k.Stub, "arg3", arg3, 2))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k *kstub) setDumpable(dumpable uintptr) error {
|
||||||
|
k.Helper()
|
||||||
|
return k.Expects("setDumpable").Error(
|
||||||
|
stub.CheckArg(k.Stub, "dumpable", dumpable, 0))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k *kstub) receive(key string, e any, fdp *uintptr) (closeFunc func() error, err error) {
|
||||||
|
k.Helper()
|
||||||
|
expect := k.Expects("receive")
|
||||||
|
reflect.ValueOf(e).Elem().Set(reflect.ValueOf(expect.Args[1]))
|
||||||
|
if expect.Args[2] != nil {
|
||||||
|
*fdp = expect.Args[2].(uintptr)
|
||||||
|
}
|
||||||
|
return func() error { return k.Expects("closeReceive").Err }, expect.Error(
|
||||||
|
stub.CheckArg(k.Stub, "key", key, 0))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k *kstub) expectCheckContainer(expect *stub.Call, z *container.Container) error {
|
||||||
|
k.Helper()
|
||||||
|
err := expect.Error(
|
||||||
|
stub.CheckArgReflect(k.Stub, "params", &z.Params, 0))
|
||||||
|
if err != nil {
|
||||||
|
k.Errorf("params:\n%s\n%s", mustMarshal(&z.Params), mustMarshal(expect.Args[0]))
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k *kstub) containerStart(z *container.Container) error {
|
||||||
|
k.Helper()
|
||||||
|
return k.expectCheckContainer(k.Expects("containerStart"), z)
|
||||||
|
}
|
||||||
|
func (k *kstub) containerServe(z *container.Container) error {
|
||||||
|
k.Helper()
|
||||||
|
return k.expectCheckContainer(k.Expects("containerServe"), z)
|
||||||
|
}
|
||||||
|
func (k *kstub) containerWait(z *container.Container) error {
|
||||||
|
k.Helper()
|
||||||
|
return k.expectCheckContainer(k.Expects("containerWait"), z)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k *kstub) seccompLoad(rules []seccomp.NativeRule, flags seccomp.ExportFlag) error {
|
||||||
|
k.Helper()
|
||||||
|
return k.Expects("seccompLoad").Error(
|
||||||
|
stub.CheckArgReflect(k.Stub, "rules", rules, 0),
|
||||||
|
stub.CheckArg(k.Stub, "flags", flags, 1))
|
||||||
|
}
|
||||||
|
|
||||||
func (k *kstub) cmdOutput(cmd *exec.Cmd) ([]byte, error) {
|
func (k *kstub) cmdOutput(cmd *exec.Cmd) ([]byte, error) {
|
||||||
k.Helper()
|
k.Helper()
|
||||||
expect := k.Expects("cmdOutput")
|
expect := k.Expects("cmdOutput")
|
||||||
@@ -363,6 +426,16 @@ func (k *kstub) cmdOutput(cmd *exec.Cmd) ([]byte, error) {
|
|||||||
stub.CheckArg(k.Stub, "cmd.Dir", cmd.Dir, 3))
|
stub.CheckArg(k.Stub, "cmd.Dir", cmd.Dir, 3))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (k *kstub) notifyContext(parent context.Context, signals ...os.Signal) (ctx context.Context, stop context.CancelFunc) {
|
||||||
|
k.Helper()
|
||||||
|
if k.Expects("notifyContext").Error(
|
||||||
|
stub.CheckArgReflect(k.Stub, "parent", parent, 0),
|
||||||
|
stub.CheckArgReflect(k.Stub, "signals", signals, 1)) != nil {
|
||||||
|
k.FailNow()
|
||||||
|
}
|
||||||
|
return k.Context(), func() { k.Helper(); k.Expects("notifyContextStop") }
|
||||||
|
}
|
||||||
|
|
||||||
func (k *kstub) mustHsuPath() *check.Absolute {
|
func (k *kstub) mustHsuPath() *check.Absolute {
|
||||||
k.Helper()
|
k.Helper()
|
||||||
return k.Expects("mustHsuPath").Ret.(*check.Absolute)
|
return k.Expects("mustHsuPath").Ret.(*check.Absolute)
|
||||||
@@ -374,9 +447,52 @@ func (k *kstub) dbusAddress() (session, system string) {
|
|||||||
return ret[0], ret[1]
|
return ret[0], ret[1]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k *kstub) GetLogger() *log.Logger { panic("unreachable") }
|
// stubTrackReader embeds kstub but switches the underlying [stub.Stub] index to sub on its first Read.
|
||||||
|
// The resulting kstub does not share any state with the instance passed to the instrumented goroutine.
|
||||||
|
// Therefore, any method making use of such must not be called.
|
||||||
|
type stubTrackReader struct {
|
||||||
|
sub int
|
||||||
|
subOnce sync.Once
|
||||||
|
|
||||||
func (k *kstub) IsVerbose() bool { k.Helper(); return k.Expects("isVerbose").Ret.(bool) }
|
*kstub
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *stubTrackReader) Read(p []byte) (n int, err error) {
|
||||||
|
r.subOnce.Do(func() {
|
||||||
|
subVal := reflect.ValueOf(r.kstub.Stub).Elem().FieldByName("sub")
|
||||||
|
r.kstub = &kstub{panicDispatcher{}, reflect.
|
||||||
|
NewAt(subVal.Type(), unsafe.Pointer(subVal.UnsafeAddr())).Elem().
|
||||||
|
Interface().([]*stub.Stub[syscallDispatcher])[r.sub]}
|
||||||
|
})
|
||||||
|
|
||||||
|
return r.kstub.Read(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k *kstub) setupContSignal(pid int) (io.ReadCloser, func(), error) {
|
||||||
|
k.Helper()
|
||||||
|
expect := k.Expects("setupContSignal")
|
||||||
|
return &stubTrackReader{sub: expect.Ret.(int), kstub: k}, func() { k.Expects("wKeepAlive") }, expect.Error(
|
||||||
|
stub.CheckArg(k.Stub, "pid", pid, 0))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k *kstub) getMsg() message.Msg { k.Helper(); k.Expects("getMsg"); return k }
|
||||||
|
|
||||||
|
func (k *kstub) Close() error { k.Helper(); return k.Expects("rcClose").Err }
|
||||||
|
func (k *kstub) Read(p []byte) (n int, err error) {
|
||||||
|
k.Helper()
|
||||||
|
expect := k.Expects("rcRead")
|
||||||
|
|
||||||
|
// special case to terminate exit outcomes goroutine
|
||||||
|
// to proceed with further testing of the entrypoint
|
||||||
|
if expect.Ret == nil {
|
||||||
|
panic(stub.PanicExit)
|
||||||
|
}
|
||||||
|
|
||||||
|
return copy(p, expect.Ret.([]byte)), expect.Err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k *kstub) GetLogger() *log.Logger { k.Helper(); return k.Expects("getLogger").Ret.(*log.Logger) }
|
||||||
|
func (k *kstub) IsVerbose() bool { k.Helper(); return k.Expects("isVerbose").Ret.(bool) }
|
||||||
func (k *kstub) SwapVerbose(verbose bool) bool {
|
func (k *kstub) SwapVerbose(verbose bool) bool {
|
||||||
k.Helper()
|
k.Helper()
|
||||||
expect := k.Expects("swapVerbose")
|
expect := k.Expects("swapVerbose")
|
||||||
@@ -492,20 +608,38 @@ func (panicMsgContext) Value(any) any { panic("unreachable") }
|
|||||||
// This type is meant to be embedded in partial syscallDispatcher implementations.
|
// This type is meant to be embedded in partial syscallDispatcher implementations.
|
||||||
type panicDispatcher struct{}
|
type panicDispatcher struct{}
|
||||||
|
|
||||||
func (panicDispatcher) new(func(k syscallDispatcher)) { panic("unreachable") }
|
func (panicDispatcher) new(func(k syscallDispatcher, msg message.Msg)) { panic("unreachable") }
|
||||||
func (panicDispatcher) getpid() int { panic("unreachable") }
|
func (panicDispatcher) getpid() int { panic("unreachable") }
|
||||||
func (panicDispatcher) getuid() int { panic("unreachable") }
|
func (panicDispatcher) getuid() int { panic("unreachable") }
|
||||||
func (panicDispatcher) getgid() int { panic("unreachable") }
|
func (panicDispatcher) getgid() int { panic("unreachable") }
|
||||||
func (panicDispatcher) lookupEnv(string) (string, bool) { panic("unreachable") }
|
func (panicDispatcher) lookupEnv(string) (string, bool) { panic("unreachable") }
|
||||||
func (panicDispatcher) stat(string) (os.FileInfo, error) { panic("unreachable") }
|
func (panicDispatcher) pipe() (*os.File, *os.File, error) { panic("unreachable") }
|
||||||
func (panicDispatcher) open(string) (osFile, error) { panic("unreachable") }
|
func (panicDispatcher) stat(string) (os.FileInfo, error) { panic("unreachable") }
|
||||||
func (panicDispatcher) readdir(string) ([]os.DirEntry, error) { panic("unreachable") }
|
func (panicDispatcher) open(string) (osFile, error) { panic("unreachable") }
|
||||||
func (panicDispatcher) tempdir() string { panic("unreachable") }
|
func (panicDispatcher) readdir(string) ([]os.DirEntry, error) { panic("unreachable") }
|
||||||
func (panicDispatcher) evalSymlinks(string) (string, error) { panic("unreachable") }
|
func (panicDispatcher) tempdir() string { panic("unreachable") }
|
||||||
func (panicDispatcher) lookupGroupId(string) (string, error) { panic("unreachable") }
|
func (panicDispatcher) exit(int) { panic("unreachable") }
|
||||||
func (panicDispatcher) cmdOutput(*exec.Cmd) ([]byte, error) { panic("unreachable") }
|
func (panicDispatcher) evalSymlinks(string) (string, error) { panic("unreachable") }
|
||||||
func (panicDispatcher) overflowUid(message.Msg) int { panic("unreachable") }
|
func (panicDispatcher) prctl(uintptr, uintptr, uintptr) error { panic("unreachable") }
|
||||||
func (panicDispatcher) overflowGid(message.Msg) int { panic("unreachable") }
|
func (panicDispatcher) lookupGroupId(string) (string, error) { panic("unreachable") }
|
||||||
func (panicDispatcher) mustHsuPath() *check.Absolute { panic("unreachable") }
|
func (panicDispatcher) cmdOutput(*exec.Cmd) ([]byte, error) { panic("unreachable") }
|
||||||
func (panicDispatcher) dbusAddress() (string, string) { panic("unreachable") }
|
func (panicDispatcher) overflowUid(message.Msg) int { panic("unreachable") }
|
||||||
func (panicDispatcher) fatalf(string, ...any) { panic("unreachable") }
|
func (panicDispatcher) overflowGid(message.Msg) int { panic("unreachable") }
|
||||||
|
func (panicDispatcher) setDumpable(uintptr) error { panic("unreachable") }
|
||||||
|
func (panicDispatcher) receive(string, any, *uintptr) (func() error, error) { panic("unreachable") }
|
||||||
|
func (panicDispatcher) containerStart(*container.Container) error { panic("unreachable") }
|
||||||
|
func (panicDispatcher) containerServe(*container.Container) error { panic("unreachable") }
|
||||||
|
func (panicDispatcher) containerWait(*container.Container) error { panic("unreachable") }
|
||||||
|
func (panicDispatcher) mustHsuPath() *check.Absolute { panic("unreachable") }
|
||||||
|
func (panicDispatcher) dbusAddress() (string, string) { panic("unreachable") }
|
||||||
|
func (panicDispatcher) setupContSignal(int) (io.ReadCloser, func(), error) { panic("unreachable") }
|
||||||
|
func (panicDispatcher) getMsg() message.Msg { panic("unreachable") }
|
||||||
|
func (panicDispatcher) fatal(...any) { panic("unreachable") }
|
||||||
|
func (panicDispatcher) fatalf(string, ...any) { panic("unreachable") }
|
||||||
|
|
||||||
|
func (panicDispatcher) notifyContext(context.Context, ...os.Signal) (context.Context, context.CancelFunc) {
|
||||||
|
panic("unreachable")
|
||||||
|
}
|
||||||
|
func (panicDispatcher) seccompLoad([]seccomp.NativeRule, seccomp.ExportFlag) error {
|
||||||
|
panic("unreachable")
|
||||||
|
}
|
||||||
|
|||||||
@@ -21,7 +21,9 @@ type Hsu struct {
|
|||||||
id int
|
id int
|
||||||
|
|
||||||
kOnce sync.Once
|
kOnce sync.Once
|
||||||
k syscallDispatcher
|
|
||||||
|
// msg is not populated
|
||||||
|
k syscallDispatcher
|
||||||
}
|
}
|
||||||
|
|
||||||
var ErrHsuAccess = errors.New("current user is not in the hsurc file")
|
var ErrHsuAccess = errors.New("current user is not in the hsurc file")
|
||||||
|
|||||||
@@ -7,14 +7,13 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"os/signal"
|
|
||||||
"runtime"
|
"runtime"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"hakurei.app/container"
|
"hakurei.app/container"
|
||||||
"hakurei.app/container/bits"
|
"hakurei.app/container/comp"
|
||||||
"hakurei.app/container/seccomp"
|
"hakurei.app/container/seccomp"
|
||||||
"hakurei.app/hst"
|
"hakurei.app/hst"
|
||||||
"hakurei.app/message"
|
"hakurei.app/message"
|
||||||
@@ -23,6 +22,20 @@ import (
|
|||||||
//#include "shim-signal.h"
|
//#include "shim-signal.h"
|
||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
|
// setupContSignal sets up the SIGCONT signal handler for the cross-uid shim exit hack.
|
||||||
|
// The signal handler is implemented in C, signals can be processed by reading from the returned reader.
|
||||||
|
// The returned function must be called after all signal processing concludes.
|
||||||
|
func setupContSignal(pid int) (io.ReadCloser, func(), error) {
|
||||||
|
if r, w, err := os.Pipe(); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
} else if _, err = C.hakurei_shim_setup_cont_signal(C.pid_t(pid), C.int(w.Fd())); err != nil {
|
||||||
|
_, _ = r.Close(), w.Close()
|
||||||
|
return nil, nil, err
|
||||||
|
} else {
|
||||||
|
return r, func() { runtime.KeepAlive(w) }, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// shimEnv is the name of the environment variable storing decimal representation of
|
// shimEnv is the name of the environment variable storing decimal representation of
|
||||||
// setup pipe fd for [container.Receive].
|
// setup pipe fd for [container.Receive].
|
||||||
const shimEnv = "HAKUREI_SHIM"
|
const shimEnv = "HAKUREI_SHIM"
|
||||||
@@ -46,76 +59,102 @@ type shimParams struct {
|
|||||||
// valid checks shimParams to be safe for use.
|
// valid checks shimParams to be safe for use.
|
||||||
func (p *shimParams) valid() bool { return p != nil && p.PrivPID > 0 }
|
func (p *shimParams) valid() bool { return p != nil && p.PrivPID > 0 }
|
||||||
|
|
||||||
// ShimMain is the main function of the shim process and runs as the unconstrained target user.
|
// shimName is the prefix used by log.std in the shim process.
|
||||||
func ShimMain() {
|
const shimName = "shim"
|
||||||
log.SetPrefix("shim: ")
|
|
||||||
log.SetFlags(0)
|
|
||||||
msg := message.NewMsg(log.Default())
|
|
||||||
|
|
||||||
if err := container.SetDumpable(container.SUID_DUMP_DISABLE); err != nil {
|
// Shim is called by the main function of the shim process and runs as the unconstrained target user.
|
||||||
log.Fatalf("cannot set SUID_DUMP_DISABLE: %s", err)
|
// Shim does not return.
|
||||||
|
func Shim(msg message.Msg) {
|
||||||
|
if msg == nil {
|
||||||
|
msg = message.NewMsg(log.Default())
|
||||||
|
}
|
||||||
|
shimEntrypoint(direct{msg})
|
||||||
|
}
|
||||||
|
|
||||||
|
func shimEntrypoint(k syscallDispatcher) {
|
||||||
|
msg := k.getMsg()
|
||||||
|
if msg == nil {
|
||||||
|
panic("attempting to call shimEntrypoint with nil msg")
|
||||||
|
} else if logger := msg.GetLogger(); logger != nil {
|
||||||
|
logger.SetPrefix(shimName + ": ")
|
||||||
|
logger.SetFlags(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := k.setDumpable(container.SUID_DUMP_DISABLE); err != nil {
|
||||||
|
k.fatalf("cannot set SUID_DUMP_DISABLE: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
state outcomeState
|
state outcomeState
|
||||||
closeSetup func() error
|
closeSetup func() error
|
||||||
)
|
)
|
||||||
if f, err := container.Receive(shimEnv, &state, nil); err != nil {
|
if f, err := k.receive(shimEnv, &state, nil); err != nil {
|
||||||
if errors.Is(err, syscall.EBADF) {
|
if errors.Is(err, syscall.EBADF) {
|
||||||
log.Fatal("invalid config descriptor")
|
k.fatal("invalid config descriptor")
|
||||||
}
|
}
|
||||||
if errors.Is(err, container.ErrReceiveEnv) {
|
if errors.Is(err, container.ErrReceiveEnv) {
|
||||||
log.Fatal(shimEnv + " not set")
|
k.fatal(shimEnv + " not set")
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Fatalf("cannot receive shim setup params: %v", err)
|
k.fatalf("cannot receive shim setup params: %v", err)
|
||||||
} else {
|
} else {
|
||||||
msg.SwapVerbose(state.Shim.Verbose)
|
msg.SwapVerbose(state.Shim.Verbose)
|
||||||
closeSetup = f
|
closeSetup = f
|
||||||
|
|
||||||
if err = state.populateLocal(direct{}, msg); err != nil {
|
if err = state.populateLocal(k, msg); err != nil {
|
||||||
if m, ok := message.GetMessage(err); ok {
|
if m, ok := message.GetMessage(err); ok {
|
||||||
log.Fatal(m)
|
k.fatal(m)
|
||||||
} else {
|
} else {
|
||||||
log.Fatalf("cannot populate local state: %v", err)
|
k.fatalf("cannot populate local state: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// the Go runtime does not expose siginfo_t so SIGCONT is handled in C to check si_pid
|
// the Go runtime does not expose siginfo_t so SIGCONT is handled in C to check si_pid
|
||||||
var signalPipe io.ReadCloser
|
var signalPipe io.ReadCloser
|
||||||
if r, w, err := os.Pipe(); err != nil {
|
if r, wKeepAlive, err := k.setupContSignal(state.Shim.PrivPID); err != nil {
|
||||||
log.Fatalf("cannot pipe: %v", err)
|
switch {
|
||||||
} else if _, err = C.hakurei_shim_setup_cont_signal(C.pid_t(state.Shim.PrivPID), C.int(w.Fd())); err != nil {
|
case errors.As(err, new(*os.SyscallError)): // returned by os.Pipe
|
||||||
log.Fatalf("cannot install SIGCONT handler: %v", err)
|
k.fatal(err.Error())
|
||||||
|
return
|
||||||
|
|
||||||
|
case errors.As(err, new(syscall.Errno)): // returned by hakurei_shim_setup_cont_signal
|
||||||
|
k.fatalf("cannot install SIGCONT handler: %v", err)
|
||||||
|
return
|
||||||
|
|
||||||
|
default: // unreachable
|
||||||
|
k.fatalf("cannot set up exit request: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
defer runtime.KeepAlive(w)
|
defer wKeepAlive()
|
||||||
signalPipe = r
|
signalPipe = r
|
||||||
}
|
}
|
||||||
|
|
||||||
// pdeath_signal delivery is checked as if the dying process called kill(2), see kernel/exit.c
|
// pdeath_signal delivery is checked as if the dying process called kill(2), see kernel/exit.c
|
||||||
if _, _, errno := syscall.Syscall(syscall.SYS_PRCTL, syscall.PR_SET_PDEATHSIG, uintptr(syscall.SIGCONT), 0); errno != 0 {
|
if err := k.prctl(syscall.PR_SET_PDEATHSIG, uintptr(syscall.SIGCONT), 0); err != nil {
|
||||||
log.Fatalf("cannot set parent-death signal: %v", errno)
|
k.fatalf("cannot set parent-death signal: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
stateParams := state.newParams()
|
stateParams := state.newParams()
|
||||||
for _, op := range state.Shim.Ops {
|
for _, op := range state.Shim.Ops {
|
||||||
if err := op.toContainer(stateParams); err != nil {
|
if err := op.toContainer(stateParams); err != nil {
|
||||||
if m, ok := message.GetMessage(err); ok {
|
if m, ok := message.GetMessage(err); ok {
|
||||||
log.Fatal(m)
|
k.fatal(m)
|
||||||
} else {
|
} else {
|
||||||
log.Fatalf("cannot create container state: %v", err)
|
k.fatalf("cannot create container state: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// shim exit outcomes
|
// shim exit outcomes
|
||||||
var cancelContainer atomic.Pointer[context.CancelFunc]
|
var cancelContainer atomic.Pointer[context.CancelFunc]
|
||||||
go func() {
|
k.new(func(k syscallDispatcher, msg message.Msg) {
|
||||||
buf := make([]byte, 1)
|
buf := make([]byte, 1)
|
||||||
for {
|
for {
|
||||||
if _, err := signalPipe.Read(buf); err != nil {
|
if _, err := signalPipe.Read(buf); err != nil {
|
||||||
log.Fatalf("cannot read from signal pipe: %v", err)
|
k.fatalf("cannot read from signal pipe: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch buf[0] {
|
switch buf[0] {
|
||||||
@@ -128,37 +167,37 @@ func ShimMain() {
|
|||||||
|
|
||||||
// setup has not completed, terminate immediately
|
// setup has not completed, terminate immediately
|
||||||
msg.Resume()
|
msg.Resume()
|
||||||
os.Exit(hst.ExitRequest)
|
k.exit(hst.ExitRequest)
|
||||||
return
|
return
|
||||||
|
|
||||||
case 1: // got SIGCONT after adoption: monitor died before delivering signal
|
case 1: // got SIGCONT after adoption: monitor died before delivering signal
|
||||||
msg.BeforeExit()
|
msg.BeforeExit()
|
||||||
os.Exit(hst.ExitOrphan)
|
k.exit(hst.ExitOrphan)
|
||||||
return
|
return
|
||||||
|
|
||||||
case 2: // unreachable
|
case 2: // unreachable
|
||||||
log.Println("sa_sigaction got invalid siginfo")
|
msg.Verbose("sa_sigaction got invalid siginfo")
|
||||||
|
|
||||||
case 3: // got SIGCONT from unexpected process: hopefully the terminal driver
|
case 3: // got SIGCONT from unexpected process: hopefully the terminal driver
|
||||||
log.Println("got SIGCONT from unexpected process")
|
msg.Verbose("got SIGCONT from unexpected process")
|
||||||
|
|
||||||
default: // unreachable
|
default: // unreachable
|
||||||
log.Fatalf("got invalid message %d from signal handler", buf[0])
|
k.fatalf("got invalid message %d from signal handler", buf[0])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
})
|
||||||
|
|
||||||
if stateParams.params.Ops == nil {
|
if stateParams.params.Ops == nil {
|
||||||
log.Fatal("invalid container params")
|
k.fatal("invalid container params")
|
||||||
}
|
}
|
||||||
|
|
||||||
// close setup socket
|
// close setup socket
|
||||||
if err := closeSetup(); err != nil {
|
if err := closeSetup(); err != nil {
|
||||||
log.Printf("cannot close setup pipe: %v", err)
|
msg.Verbosef("cannot close setup pipe: %v", err)
|
||||||
// not fatal
|
// not fatal
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
|
ctx, stop := k.notifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
|
||||||
cancelContainer.Store(&stop)
|
cancelContainer.Store(&stop)
|
||||||
z := container.New(ctx, msg)
|
z := container.New(ctx, msg)
|
||||||
z.Params = *stateParams.params
|
z.Params = *stateParams.params
|
||||||
@@ -167,30 +206,30 @@ func ShimMain() {
|
|||||||
// bounds and default enforced in finalise.go
|
// bounds and default enforced in finalise.go
|
||||||
z.WaitDelay = state.Shim.WaitDelay
|
z.WaitDelay = state.Shim.WaitDelay
|
||||||
|
|
||||||
if err := z.Start(); err != nil {
|
if err := k.containerStart(z); err != nil {
|
||||||
printMessageError("cannot start container:", err)
|
printMessageError("cannot start container:", err)
|
||||||
os.Exit(hst.ExitFailure)
|
k.exit(hst.ExitFailure)
|
||||||
}
|
}
|
||||||
if err := z.Serve(); err != nil {
|
if err := k.containerServe(z); err != nil {
|
||||||
printMessageError("cannot configure container:", err)
|
printMessageError("cannot configure container:", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := seccomp.Load(
|
if err := k.seccompLoad(
|
||||||
seccomp.Preset(bits.PresetStrict, seccomp.AllowMultiarch),
|
seccomp.Preset(comp.PresetStrict, seccomp.AllowMultiarch),
|
||||||
seccomp.AllowMultiarch,
|
seccomp.AllowMultiarch,
|
||||||
); err != nil {
|
); err != nil {
|
||||||
log.Fatalf("cannot load syscall filter: %v", err)
|
k.fatalf("cannot load syscall filter: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := z.Wait(); err != nil {
|
if err := k.containerWait(z); err != nil {
|
||||||
var exitError *exec.ExitError
|
var exitError *exec.ExitError
|
||||||
if !errors.As(err, &exitError) {
|
if !errors.As(err, &exitError) {
|
||||||
if errors.Is(err, context.Canceled) {
|
if errors.Is(err, context.Canceled) {
|
||||||
os.Exit(hst.ExitCancel)
|
k.exit(hst.ExitCancel)
|
||||||
}
|
}
|
||||||
log.Printf("wait: %v", err)
|
msg.Verbosef("cannot wait: %v", err)
|
||||||
os.Exit(127)
|
k.exit(127)
|
||||||
}
|
}
|
||||||
os.Exit(exitError.ExitCode())
|
k.exit(exitError.ExitCode())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
155
internal/app/shim_test.go
Normal file
155
internal/app/shim_test.go
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
package app
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"context"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"syscall"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"hakurei.app/container"
|
||||||
|
"hakurei.app/container/comp"
|
||||||
|
"hakurei.app/container/fhs"
|
||||||
|
"hakurei.app/container/seccomp"
|
||||||
|
"hakurei.app/container/stub"
|
||||||
|
"hakurei.app/hst"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestShimEntrypoint(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
shimPreset := seccomp.Preset(comp.PresetStrict, seccomp.AllowMultiarch)
|
||||||
|
templateParams := &container.Params{
|
||||||
|
Dir: m("/data/data/org.chromium.Chromium"),
|
||||||
|
Env: []string{
|
||||||
|
"DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus",
|
||||||
|
"DBUS_SYSTEM_BUS_ADDRESS=unix:path=/var/run/dbus/system_bus_socket",
|
||||||
|
"GOOGLE_API_KEY=AIzaSyBHDrl33hwRp4rMQY0ziRbj8K9LPA6vUCY",
|
||||||
|
"GOOGLE_DEFAULT_CLIENT_ID=77185425430.apps.googleusercontent.com",
|
||||||
|
"GOOGLE_DEFAULT_CLIENT_SECRET=OTJgUOQcT7lO7GsGZq2G4IlT",
|
||||||
|
"HOME=/data/data/org.chromium.Chromium",
|
||||||
|
"PULSE_COOKIE=/.hakurei/pulse-cookie",
|
||||||
|
"PULSE_SERVER=unix:/run/user/1000/pulse/native",
|
||||||
|
"SHELL=/run/current-system/sw/bin/zsh",
|
||||||
|
"TERM=xterm-256color",
|
||||||
|
"USER=chronos",
|
||||||
|
"WAYLAND_DISPLAY=wayland-0",
|
||||||
|
"XDG_RUNTIME_DIR=/run/user/1000",
|
||||||
|
"XDG_SESSION_CLASS=user",
|
||||||
|
"XDG_SESSION_TYPE=wayland",
|
||||||
|
},
|
||||||
|
|
||||||
|
// spParamsOp
|
||||||
|
Hostname: "localhost",
|
||||||
|
RetainSession: true,
|
||||||
|
HostNet: true,
|
||||||
|
HostAbstract: true,
|
||||||
|
ForwardCancel: true,
|
||||||
|
Path: m("/run/current-system/sw/bin/chromium"),
|
||||||
|
Args: []string{
|
||||||
|
"chromium",
|
||||||
|
"--ignore-gpu-blocklist",
|
||||||
|
"--disable-smooth-scrolling",
|
||||||
|
"--enable-features=UseOzonePlatform",
|
||||||
|
"--ozone-platform=wayland",
|
||||||
|
},
|
||||||
|
SeccompFlags: seccomp.AllowMultiarch,
|
||||||
|
Uid: 1000,
|
||||||
|
Gid: 100,
|
||||||
|
|
||||||
|
Ops: new(container.Ops).
|
||||||
|
// resolveRoot
|
||||||
|
Root(m("/var/lib/hakurei/base/org.debian"), comp.BindWritable).
|
||||||
|
// spParamsOp
|
||||||
|
Proc(fhs.AbsProc).
|
||||||
|
Tmpfs(hst.AbsPrivateTmp, 1<<12, 0755).
|
||||||
|
Bind(fhs.AbsDev, fhs.AbsDev, comp.BindWritable|comp.BindDevice).
|
||||||
|
Tmpfs(fhs.AbsDev.Append("shm"), 0, 01777).
|
||||||
|
|
||||||
|
// spRuntimeOp
|
||||||
|
Tmpfs(fhs.AbsRunUser, 1<<12, 0755).
|
||||||
|
Bind(m("/tmp/hakurei.10/runtime/9999"), m("/run/user/1000"), comp.BindWritable).
|
||||||
|
|
||||||
|
// spTmpdirOp
|
||||||
|
Bind(m("/tmp/hakurei.10/tmpdir/9999"), fhs.AbsTmp, comp.BindWritable).
|
||||||
|
|
||||||
|
// spAccountOp
|
||||||
|
Place(m("/etc/passwd"), []byte("chronos:x:1000:100:Hakurei:/data/data/org.chromium.Chromium:/run/current-system/sw/bin/zsh\n")).
|
||||||
|
Place(m("/etc/group"), []byte("hakurei:x:100:\n")).
|
||||||
|
|
||||||
|
// spWaylandOp
|
||||||
|
Bind(m("/tmp/hakurei.10/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/wayland"), m("/run/user/1000/wayland-0"), 0).
|
||||||
|
|
||||||
|
// spPulseOp
|
||||||
|
Bind(m("/run/user/1000/hakurei/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/pulse"), m("/run/user/1000/pulse/native"), 0).
|
||||||
|
Place(m("/.hakurei/pulse-cookie"), bytes.Repeat([]byte{0}, pulseCookieSizeMax)).
|
||||||
|
|
||||||
|
// spDBusOp
|
||||||
|
Bind(m("/tmp/hakurei.10/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bus"), m("/run/user/1000/bus"), 0).
|
||||||
|
Bind(m("/tmp/hakurei.10/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/system_bus_socket"), m("/var/run/dbus/system_bus_socket"), 0).
|
||||||
|
|
||||||
|
// spFilesystemOp
|
||||||
|
Etc(fhs.AbsEtc, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa").
|
||||||
|
Tmpfs(fhs.AbsTmp, 0, 0755).
|
||||||
|
Overlay(m("/nix/store"),
|
||||||
|
fhs.AbsVarLib.Append("hakurei/nix/u0/org.chromium.Chromium/rw-store/upper"),
|
||||||
|
fhs.AbsVarLib.Append("hakurei/nix/u0/org.chromium.Chromium/rw-store/work"),
|
||||||
|
fhs.AbsVarLib.Append("hakurei/base/org.nixos/ro-store")).
|
||||||
|
Link(m("/run/current-system"), "/run/current-system", true).
|
||||||
|
Link(m("/run/opengl-driver"), "/run/opengl-driver", true).
|
||||||
|
Bind(fhs.AbsVarLib.Append("hakurei/u0/org.chromium.Chromium"),
|
||||||
|
m("/data/data/org.chromium.Chromium"),
|
||||||
|
comp.BindWritable|comp.BindEnsure).
|
||||||
|
Bind(fhs.AbsDev.Append("dri"), fhs.AbsDev.Append("dri"),
|
||||||
|
comp.BindOptional|comp.BindWritable|comp.BindDevice).
|
||||||
|
Remount(fhs.AbsRoot, syscall.MS_RDONLY),
|
||||||
|
}
|
||||||
|
|
||||||
|
checkSimple(t, "shimEntrypoint", []simpleTestCase{
|
||||||
|
{"success", func(k *kstub) error { shimEntrypoint(k); return nil }, stub.Expect{Calls: []stub.Call{
|
||||||
|
call("getMsg", stub.ExpectArgs{}, nil, nil),
|
||||||
|
call("getLogger", stub.ExpectArgs{}, (*log.Logger)(nil), nil),
|
||||||
|
call("setDumpable", stub.ExpectArgs{uintptr(container.SUID_DUMP_DISABLE)}, nil, nil),
|
||||||
|
call("receive", stub.ExpectArgs{"HAKUREI_SHIM", outcomeState{
|
||||||
|
Shim: &shimParams{PrivPID: 0xbad, WaitDelay: 0xf, Verbose: true, Ops: []outcomeOp{
|
||||||
|
&spParamsOp{"xterm-256color", true},
|
||||||
|
&spRuntimeOp{sessionTypeWayland},
|
||||||
|
spTmpdirOp{},
|
||||||
|
spAccountOp{},
|
||||||
|
&spWaylandOp{},
|
||||||
|
&spPulseOp{(*[256]byte)(bytes.Repeat([]byte{0}, pulseCookieSizeMax)), pulseCookieSizeMax},
|
||||||
|
&spDBusOp{true},
|
||||||
|
&spFilesystemOp{},
|
||||||
|
}},
|
||||||
|
|
||||||
|
ID: &checkExpectInstanceId,
|
||||||
|
Identity: hst.IdentityMax,
|
||||||
|
UserID: 10,
|
||||||
|
Container: hst.Template().Container,
|
||||||
|
Mapuid: 1000,
|
||||||
|
Mapgid: 100,
|
||||||
|
EnvPaths: &EnvPaths{TempDir: fhs.AbsTmp, RuntimePath: fhs.AbsRunUser.Append("1000")},
|
||||||
|
}, nil}, nil, nil),
|
||||||
|
call("swapVerbose", stub.ExpectArgs{true}, false, nil),
|
||||||
|
call("verbosef", stub.ExpectArgs{"process share directory at %q, runtime directory at %q", []any{m("/tmp/hakurei.10"), m("/run/user/1000/hakurei")}}, nil, nil),
|
||||||
|
call("setupContSignal", stub.ExpectArgs{0xbad}, 0, nil),
|
||||||
|
call("prctl", stub.ExpectArgs{uintptr(syscall.PR_SET_PDEATHSIG), uintptr(syscall.SIGCONT), uintptr(0)}, nil, nil),
|
||||||
|
call("New", stub.ExpectArgs{}, nil, nil),
|
||||||
|
call("closeReceive", stub.ExpectArgs{}, nil, nil),
|
||||||
|
call("notifyContext", stub.ExpectArgs{context.Background(), []os.Signal{os.Interrupt, syscall.SIGTERM}}, nil, nil),
|
||||||
|
call("containerStart", stub.ExpectArgs{templateParams}, nil, nil),
|
||||||
|
call("containerServe", stub.ExpectArgs{templateParams}, nil, nil),
|
||||||
|
call("seccompLoad", stub.ExpectArgs{shimPreset, seccomp.AllowMultiarch}, nil, nil),
|
||||||
|
call("containerWait", stub.ExpectArgs{templateParams}, nil, nil),
|
||||||
|
|
||||||
|
// deferred
|
||||||
|
call("wKeepAlive", stub.ExpectArgs{}, nil, nil),
|
||||||
|
}, Tracks: []stub.Expect{{Calls: []stub.Call{
|
||||||
|
call("rcRead", stub.ExpectArgs{}, []byte{2}, nil),
|
||||||
|
call("verbose", stub.ExpectArgs{[]any{"sa_sigaction got invalid siginfo"}}, nil, nil),
|
||||||
|
call("rcRead", stub.ExpectArgs{}, []byte{3}, nil),
|
||||||
|
call("verbose", stub.ExpectArgs{[]any{"got SIGCONT from unexpected process"}}, nil, nil),
|
||||||
|
call("rcRead", stub.ExpectArgs{}, nil, nil), // stub terminates this goroutine
|
||||||
|
}}}}, nil},
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -11,8 +11,8 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"hakurei.app/container"
|
"hakurei.app/container"
|
||||||
"hakurei.app/container/bits"
|
|
||||||
"hakurei.app/container/check"
|
"hakurei.app/container/check"
|
||||||
|
"hakurei.app/container/comp"
|
||||||
"hakurei.app/container/fhs"
|
"hakurei.app/container/fhs"
|
||||||
"hakurei.app/container/seccomp"
|
"hakurei.app/container/seccomp"
|
||||||
"hakurei.app/hst"
|
"hakurei.app/hst"
|
||||||
@@ -75,16 +75,16 @@ func (s *spParamsOp) toContainer(state *outcomeStateParams) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if state.Container.Flags&hst.FSeccompCompat == 0 {
|
if state.Container.Flags&hst.FSeccompCompat == 0 {
|
||||||
state.params.SeccompPresets |= bits.PresetExt
|
state.params.SeccompPresets |= comp.PresetExt
|
||||||
}
|
}
|
||||||
if state.Container.Flags&hst.FDevel == 0 {
|
if state.Container.Flags&hst.FDevel == 0 {
|
||||||
state.params.SeccompPresets |= bits.PresetDenyDevel
|
state.params.SeccompPresets |= comp.PresetDenyDevel
|
||||||
}
|
}
|
||||||
if state.Container.Flags&hst.FUserns == 0 {
|
if state.Container.Flags&hst.FUserns == 0 {
|
||||||
state.params.SeccompPresets |= bits.PresetDenyNS
|
state.params.SeccompPresets |= comp.PresetDenyNS
|
||||||
}
|
}
|
||||||
if state.Container.Flags&hst.FTty == 0 {
|
if state.Container.Flags&hst.FTty == 0 {
|
||||||
state.params.SeccompPresets |= bits.PresetDenyTTY
|
state.params.SeccompPresets |= comp.PresetDenyTTY
|
||||||
}
|
}
|
||||||
|
|
||||||
if state.Container.Flags&hst.FMapRealUID != 0 {
|
if state.Container.Flags&hst.FMapRealUID != 0 {
|
||||||
@@ -112,7 +112,7 @@ func (s *spParamsOp) toContainer(state *outcomeStateParams) error {
|
|||||||
if state.Container.Flags&hst.FDevice == 0 {
|
if state.Container.Flags&hst.FDevice == 0 {
|
||||||
state.params.DevWritable(fhs.AbsDev, true)
|
state.params.DevWritable(fhs.AbsDev, true)
|
||||||
} else {
|
} else {
|
||||||
state.params.Bind(fhs.AbsDev, fhs.AbsDev, bits.BindWritable|bits.BindDevice)
|
state.params.Bind(fhs.AbsDev, fhs.AbsDev, comp.BindWritable|comp.BindDevice)
|
||||||
}
|
}
|
||||||
// /dev is mounted readonly later on, this prevents /dev/shm from going readonly with it
|
// /dev is mounted readonly later on, this prevents /dev/shm from going readonly with it
|
||||||
state.params.Tmpfs(fhs.AbsDev.Append("shm"), 0, 01777)
|
state.params.Tmpfs(fhs.AbsDev.Append("shm"), 0, 01777)
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"hakurei.app/container"
|
"hakurei.app/container"
|
||||||
"hakurei.app/container/bits"
|
|
||||||
"hakurei.app/container/check"
|
"hakurei.app/container/check"
|
||||||
|
"hakurei.app/container/comp"
|
||||||
"hakurei.app/container/fhs"
|
"hakurei.app/container/fhs"
|
||||||
"hakurei.app/container/seccomp"
|
"hakurei.app/container/seccomp"
|
||||||
"hakurei.app/container/stub"
|
"hakurei.app/container/stub"
|
||||||
@@ -65,11 +65,11 @@ func TestSpParamsOp(t *testing.T) {
|
|||||||
HostAbstract: true,
|
HostAbstract: true,
|
||||||
Path: config.Container.Path,
|
Path: config.Container.Path,
|
||||||
Args: []string{config.Container.Path.String()},
|
Args: []string{config.Container.Path.String()},
|
||||||
SeccompPresets: bits.PresetExt | bits.PresetDenyDevel | bits.PresetDenyNS | bits.PresetDenyTTY,
|
SeccompPresets: comp.PresetExt | comp.PresetDenyDevel | comp.PresetDenyNS | comp.PresetDenyTTY,
|
||||||
Uid: 1000,
|
Uid: 1000,
|
||||||
Gid: 100,
|
Gid: 100,
|
||||||
Ops: new(container.Ops).
|
Ops: new(container.Ops).
|
||||||
Root(m("/var/lib/hakurei/base/org.debian"), bits.BindWritable).
|
Root(m("/var/lib/hakurei/base/org.debian"), comp.BindWritable).
|
||||||
Proc(fhs.AbsProc).Tmpfs(hst.AbsPrivateTmp, 1<<12, 0755).
|
Proc(fhs.AbsProc).Tmpfs(hst.AbsPrivateTmp, 1<<12, 0755).
|
||||||
DevWritable(fhs.AbsDev, true).
|
DevWritable(fhs.AbsDev, true).
|
||||||
Tmpfs(fhs.AbsDev.Append("shm"), 0, 01777),
|
Tmpfs(fhs.AbsDev.Append("shm"), 0, 01777),
|
||||||
@@ -107,9 +107,9 @@ func TestSpParamsOp(t *testing.T) {
|
|||||||
Uid: 1000,
|
Uid: 1000,
|
||||||
Gid: 100,
|
Gid: 100,
|
||||||
Ops: new(container.Ops).
|
Ops: new(container.Ops).
|
||||||
Root(m("/var/lib/hakurei/base/org.debian"), bits.BindWritable).
|
Root(m("/var/lib/hakurei/base/org.debian"), comp.BindWritable).
|
||||||
Proc(fhs.AbsProc).Tmpfs(hst.AbsPrivateTmp, 1<<12, 0755).
|
Proc(fhs.AbsProc).Tmpfs(hst.AbsPrivateTmp, 1<<12, 0755).
|
||||||
Bind(fhs.AbsDev, fhs.AbsDev, bits.BindWritable|bits.BindDevice).
|
Bind(fhs.AbsDev, fhs.AbsDev, comp.BindWritable|comp.BindDevice).
|
||||||
Tmpfs(fhs.AbsDev.Append("shm"), 0, 01777),
|
Tmpfs(fhs.AbsDev.Append("shm"), 0, 01777),
|
||||||
}, paramsWantEnv(config, map[string]string{
|
}, paramsWantEnv(config, map[string]string{
|
||||||
"TERM": "xterm",
|
"TERM": "xterm",
|
||||||
@@ -425,8 +425,8 @@ func TestSpFilesystemOp(t *testing.T) {
|
|||||||
Bind(
|
Bind(
|
||||||
fhs.AbsVarLib.Append("hakurei/u0/org.chromium.Chromium"),
|
fhs.AbsVarLib.Append("hakurei/u0/org.chromium.Chromium"),
|
||||||
check.MustAbs("/data/data/org.chromium.Chromium"),
|
check.MustAbs("/data/data/org.chromium.Chromium"),
|
||||||
bits.BindWritable|bits.BindEnsure).
|
comp.BindWritable|comp.BindEnsure).
|
||||||
Bind(fhs.AbsDev.Append("dri"), fhs.AbsDev.Append("dri"), bits.BindDevice|bits.BindWritable|bits.BindOptional).
|
Bind(fhs.AbsDev.Append("dri"), fhs.AbsDev.Append("dri"), comp.BindDevice|comp.BindWritable|comp.BindOptional).
|
||||||
Remount(fhs.AbsRoot, syscall.MS_RDONLY),
|
Remount(fhs.AbsRoot, syscall.MS_RDONLY),
|
||||||
}, nil, nil},
|
}, nil, nil},
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ package app
|
|||||||
import (
|
import (
|
||||||
"encoding/gob"
|
"encoding/gob"
|
||||||
|
|
||||||
"hakurei.app/container/bits"
|
|
||||||
"hakurei.app/container/check"
|
"hakurei.app/container/check"
|
||||||
|
"hakurei.app/container/comp"
|
||||||
"hakurei.app/container/fhs"
|
"hakurei.app/container/fhs"
|
||||||
"hakurei.app/hst"
|
"hakurei.app/hst"
|
||||||
"hakurei.app/system"
|
"hakurei.app/system"
|
||||||
@@ -111,7 +111,7 @@ func (s *spRuntimeOp) toContainer(state *outcomeStateParams) error {
|
|||||||
state.params.Tmpfs(fhs.AbsRunUser, 1<<12, 0755)
|
state.params.Tmpfs(fhs.AbsRunUser, 1<<12, 0755)
|
||||||
if state.Container.Flags&hst.FShareRuntime != 0 {
|
if state.Container.Flags&hst.FShareRuntime != 0 {
|
||||||
_, runtimeDirInst := s.commonPaths(state.outcomeState)
|
_, runtimeDirInst := s.commonPaths(state.outcomeState)
|
||||||
state.params.Bind(runtimeDirInst, state.runtimeDir, bits.BindWritable)
|
state.params.Bind(runtimeDirInst, state.runtimeDir, comp.BindWritable)
|
||||||
} else {
|
} else {
|
||||||
state.params.Mkdir(state.runtimeDir, 0700)
|
state.params.Mkdir(state.runtimeDir, 0700)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"hakurei.app/container"
|
"hakurei.app/container"
|
||||||
"hakurei.app/container/bits"
|
"hakurei.app/container/comp"
|
||||||
"hakurei.app/container/fhs"
|
"hakurei.app/container/fhs"
|
||||||
"hakurei.app/container/stub"
|
"hakurei.app/container/stub"
|
||||||
"hakurei.app/hst"
|
"hakurei.app/hst"
|
||||||
@@ -41,7 +41,7 @@ func TestSpRuntimeOp(t *testing.T) {
|
|||||||
}, &container.Params{
|
}, &container.Params{
|
||||||
Ops: new(container.Ops).
|
Ops: new(container.Ops).
|
||||||
Tmpfs(fhs.AbsRunUser, 1<<12, 0755).
|
Tmpfs(fhs.AbsRunUser, 1<<12, 0755).
|
||||||
Bind(m("/proc/nonexistent/tmp/hakurei.0/runtime/9"), m("/run/user/1000"), bits.BindWritable),
|
Bind(m("/proc/nonexistent/tmp/hakurei.0/runtime/9"), m("/run/user/1000"), comp.BindWritable),
|
||||||
}, paramsWantEnv(config, map[string]string{
|
}, paramsWantEnv(config, map[string]string{
|
||||||
"XDG_RUNTIME_DIR": "/run/user/1000",
|
"XDG_RUNTIME_DIR": "/run/user/1000",
|
||||||
"XDG_SESSION_CLASS": "user",
|
"XDG_SESSION_CLASS": "user",
|
||||||
@@ -68,7 +68,7 @@ func TestSpRuntimeOp(t *testing.T) {
|
|||||||
}, &container.Params{
|
}, &container.Params{
|
||||||
Ops: new(container.Ops).
|
Ops: new(container.Ops).
|
||||||
Tmpfs(fhs.AbsRunUser, 1<<12, 0755).
|
Tmpfs(fhs.AbsRunUser, 1<<12, 0755).
|
||||||
Bind(m("/proc/nonexistent/tmp/hakurei.0/runtime/9"), m("/run/user/1000"), bits.BindWritable),
|
Bind(m("/proc/nonexistent/tmp/hakurei.0/runtime/9"), m("/run/user/1000"), comp.BindWritable),
|
||||||
}, paramsWantEnv(config, map[string]string{
|
}, paramsWantEnv(config, map[string]string{
|
||||||
"XDG_RUNTIME_DIR": "/run/user/1000",
|
"XDG_RUNTIME_DIR": "/run/user/1000",
|
||||||
"XDG_SESSION_CLASS": "user",
|
"XDG_SESSION_CLASS": "user",
|
||||||
@@ -95,7 +95,7 @@ func TestSpRuntimeOp(t *testing.T) {
|
|||||||
}, &container.Params{
|
}, &container.Params{
|
||||||
Ops: new(container.Ops).
|
Ops: new(container.Ops).
|
||||||
Tmpfs(fhs.AbsRunUser, 1<<12, 0755).
|
Tmpfs(fhs.AbsRunUser, 1<<12, 0755).
|
||||||
Bind(m("/proc/nonexistent/tmp/hakurei.0/runtime/9"), m("/run/user/1000"), bits.BindWritable),
|
Bind(m("/proc/nonexistent/tmp/hakurei.0/runtime/9"), m("/run/user/1000"), comp.BindWritable),
|
||||||
}, paramsWantEnv(config, map[string]string{
|
}, paramsWantEnv(config, map[string]string{
|
||||||
"XDG_RUNTIME_DIR": "/run/user/1000",
|
"XDG_RUNTIME_DIR": "/run/user/1000",
|
||||||
"XDG_SESSION_CLASS": "user",
|
"XDG_SESSION_CLASS": "user",
|
||||||
@@ -118,7 +118,7 @@ func TestSpRuntimeOp(t *testing.T) {
|
|||||||
}, &container.Params{
|
}, &container.Params{
|
||||||
Ops: new(container.Ops).
|
Ops: new(container.Ops).
|
||||||
Tmpfs(fhs.AbsRunUser, 1<<12, 0755).
|
Tmpfs(fhs.AbsRunUser, 1<<12, 0755).
|
||||||
Bind(m("/proc/nonexistent/tmp/hakurei.0/runtime/9"), m("/run/user/1000"), bits.BindWritable),
|
Bind(m("/proc/nonexistent/tmp/hakurei.0/runtime/9"), m("/run/user/1000"), comp.BindWritable),
|
||||||
}, paramsWantEnv(config, map[string]string{
|
}, paramsWantEnv(config, map[string]string{
|
||||||
"XDG_RUNTIME_DIR": "/run/user/1000",
|
"XDG_RUNTIME_DIR": "/run/user/1000",
|
||||||
"XDG_SESSION_CLASS": "user",
|
"XDG_SESSION_CLASS": "user",
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ package app
|
|||||||
import (
|
import (
|
||||||
"encoding/gob"
|
"encoding/gob"
|
||||||
|
|
||||||
"hakurei.app/container/bits"
|
|
||||||
"hakurei.app/container/check"
|
"hakurei.app/container/check"
|
||||||
|
"hakurei.app/container/comp"
|
||||||
"hakurei.app/container/fhs"
|
"hakurei.app/container/fhs"
|
||||||
"hakurei.app/hst"
|
"hakurei.app/hst"
|
||||||
"hakurei.app/system"
|
"hakurei.app/system"
|
||||||
@@ -30,7 +30,7 @@ func (s spTmpdirOp) toSystem(state *outcomeStateSys) error {
|
|||||||
func (s spTmpdirOp) toContainer(state *outcomeStateParams) error {
|
func (s spTmpdirOp) toContainer(state *outcomeStateParams) error {
|
||||||
if state.Container.Flags&hst.FShareTmpdir != 0 {
|
if state.Container.Flags&hst.FShareTmpdir != 0 {
|
||||||
_, tmpdirInst := s.commonPaths(state.outcomeState)
|
_, tmpdirInst := s.commonPaths(state.outcomeState)
|
||||||
state.params.Bind(tmpdirInst, fhs.AbsTmp, bits.BindWritable)
|
state.params.Bind(tmpdirInst, fhs.AbsTmp, comp.BindWritable)
|
||||||
} else {
|
} else {
|
||||||
state.params.Tmpfs(fhs.AbsTmp, 0, 01777)
|
state.params.Tmpfs(fhs.AbsTmp, 0, 01777)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"hakurei.app/container"
|
"hakurei.app/container"
|
||||||
"hakurei.app/container/bits"
|
"hakurei.app/container/comp"
|
||||||
"hakurei.app/container/fhs"
|
"hakurei.app/container/fhs"
|
||||||
"hakurei.app/container/stub"
|
"hakurei.app/container/stub"
|
||||||
"hakurei.app/hst"
|
"hakurei.app/hst"
|
||||||
@@ -28,7 +28,7 @@ func TestSpTmpdirOp(t *testing.T) {
|
|||||||
// this op configures the container state and does not make calls during toContainer
|
// this op configures the container state and does not make calls during toContainer
|
||||||
}, &container.Params{
|
}, &container.Params{
|
||||||
Ops: new(container.Ops).
|
Ops: new(container.Ops).
|
||||||
Bind(m("/proc/nonexistent/tmp/hakurei.0/tmpdir/9"), fhs.AbsTmp, bits.BindWritable),
|
Bind(m("/proc/nonexistent/tmp/hakurei.0/tmpdir/9"), fhs.AbsTmp, comp.BindWritable),
|
||||||
}, nil, nil},
|
}, nil, nil},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
package internal
|
|
||||||
|
|
||||||
const compPoison = "INVALIDINVALIDINVALIDINVALIDINVALID"
|
|
||||||
|
|
||||||
var (
|
|
||||||
version = compPoison
|
|
||||||
)
|
|
||||||
|
|
||||||
// checkComp validates string value set at compile time.
|
|
||||||
func checkComp(s string) (string, bool) { return s, s != compPoison && s != "" }
|
|
||||||
|
|
||||||
func Version() string {
|
|
||||||
if v, ok := checkComp(version); ok {
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
return "impure"
|
|
||||||
}
|
|
||||||
@@ -6,20 +6,20 @@ import (
|
|||||||
"hakurei.app/container/check"
|
"hakurei.app/container/check"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
// Absolute paths to the Hakurei installation.
|
||||||
hmain = compPoison
|
//
|
||||||
hsu = compPoison
|
// These are set by the linker.
|
||||||
)
|
var hakureiPath, hsuPath string
|
||||||
|
|
||||||
// MustHakureiPath returns the absolute path to hakurei, configured at compile time.
|
// MustHakureiPath returns the [check.Absolute] path to hakurei.
|
||||||
func MustHakureiPath() *check.Absolute { return mustCheckPath(log.Fatal, "hakurei", hmain) }
|
func MustHakureiPath() *check.Absolute { return mustCheckPath(log.Fatal, "hakurei", hakureiPath) }
|
||||||
|
|
||||||
// MustHsuPath returns the absolute path to hakurei, configured at compile time.
|
// MustHsuPath returns the [check.Absolute] to hsu.
|
||||||
func MustHsuPath() *check.Absolute { return mustCheckPath(log.Fatal, "hsu", hsu) }
|
func MustHsuPath() *check.Absolute { return mustCheckPath(log.Fatal, "hsu", hsuPath) }
|
||||||
|
|
||||||
// mustCheckPath checks a pathname against compPoison, then [container.NewAbs], calling fatal if either step fails.
|
// mustCheckPath checks a pathname to not be zero, then [check.NewAbs], calling fatal if either step fails.
|
||||||
func mustCheckPath(fatal func(v ...any), name, pathname string) *check.Absolute {
|
func mustCheckPath(fatal func(v ...any), name, pathname string) *check.Absolute {
|
||||||
if pathname != compPoison && pathname != "" {
|
if pathname != "" {
|
||||||
if a, err := check.NewAbs(pathname); err != nil {
|
if a, err := check.NewAbs(pathname); err != nil {
|
||||||
fatal(err.Error())
|
fatal(err.Error())
|
||||||
return nil // unreachable
|
return nil // unreachable
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ func TestMustCheckPath(t *testing.T) {
|
|||||||
pathname string
|
pathname string
|
||||||
wantFatal string
|
wantFatal string
|
||||||
}{
|
}{
|
||||||
{"poison", compPoison, "invalid test path, this program is compiled incorrectly"},
|
|
||||||
{"zero", "", "invalid test path, this program is compiled incorrectly"},
|
{"zero", "", "invalid test path, this program is compiled incorrectly"},
|
||||||
{"not absolute", "\x00", `path "\x00" is not absolute`},
|
{"not absolute", "\x00", `path "\x00" is not absolute`},
|
||||||
{"success", "/proc/nonexistent", ""},
|
{"success", "/proc/nonexistent", ""},
|
||||||
|
|||||||
19
internal/version.go
Normal file
19
internal/version.go
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
package internal
|
||||||
|
|
||||||
|
// FallbackVersion is returned when a version string was not set by the linker.
|
||||||
|
const FallbackVersion = "dirty"
|
||||||
|
|
||||||
|
// buildVersion is the Hakurei tree's version string at build time.
|
||||||
|
//
|
||||||
|
// This is set by the linker.
|
||||||
|
var buildVersion string
|
||||||
|
|
||||||
|
// Version returns the Hakurei tree's version string.
|
||||||
|
// It is either the value of the constant [FallbackVersion] or,
|
||||||
|
// when possible, a release tag like "v1.0.0".
|
||||||
|
func Version() string {
|
||||||
|
if buildVersion != "" {
|
||||||
|
return buildVersion
|
||||||
|
}
|
||||||
|
return FallbackVersion
|
||||||
|
}
|
||||||
@@ -9,8 +9,8 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"hakurei.app/container"
|
"hakurei.app/container"
|
||||||
"hakurei.app/container/bits"
|
|
||||||
"hakurei.app/container/check"
|
"hakurei.app/container/check"
|
||||||
|
"hakurei.app/container/comp"
|
||||||
"hakurei.app/container/fhs"
|
"hakurei.app/container/fhs"
|
||||||
"hakurei.app/container/seccomp"
|
"hakurei.app/container/seccomp"
|
||||||
"hakurei.app/message"
|
"hakurei.app/message"
|
||||||
@@ -40,7 +40,7 @@ func Exec(ctx context.Context, msg message.Msg, p string) ([]*Entry, error) {
|
|||||||
z := container.NewCommand(c, msg, toolPath, lddName, p)
|
z := container.NewCommand(c, msg, toolPath, lddName, p)
|
||||||
z.Hostname = "hakurei-" + lddName
|
z.Hostname = "hakurei-" + lddName
|
||||||
z.SeccompFlags |= seccomp.AllowMultiarch
|
z.SeccompFlags |= seccomp.AllowMultiarch
|
||||||
z.SeccompPresets |= bits.PresetStrict
|
z.SeccompPresets |= comp.PresetStrict
|
||||||
stdout, stderr := new(bytes.Buffer), new(bytes.Buffer)
|
stdout, stderr := new(bytes.Buffer), new(bytes.Buffer)
|
||||||
z.Stdout = stdout
|
z.Stdout = stdout
|
||||||
z.Stderr = stderr
|
z.Stderr = stderr
|
||||||
|
|||||||
@@ -75,9 +75,9 @@ buildGoModule rec {
|
|||||||
]
|
]
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
version = "v${version}";
|
buildVersion = "v${version}";
|
||||||
hmain = "${placeholder "out"}/libexec/hakurei";
|
hakureiPath = "${placeholder "out"}/libexec/hakurei";
|
||||||
hsu = "/run/wrappers/bin/hsu";
|
hsuPath = "/run/wrappers/bin/hsu";
|
||||||
};
|
};
|
||||||
|
|
||||||
# nix build environment does not allow acls
|
# nix build environment does not allow acls
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"hakurei.app/container"
|
"hakurei.app/container"
|
||||||
"hakurei.app/container/bits"
|
|
||||||
"hakurei.app/container/check"
|
"hakurei.app/container/check"
|
||||||
|
"hakurei.app/container/comp"
|
||||||
"hakurei.app/container/seccomp"
|
"hakurei.app/container/seccomp"
|
||||||
"hakurei.app/helper"
|
"hakurei.app/helper"
|
||||||
"hakurei.app/ldd"
|
"hakurei.app/ldd"
|
||||||
@@ -65,7 +65,7 @@ func (p *Proxy) Start() error {
|
|||||||
p.final, true,
|
p.final, true,
|
||||||
argF, func(z *container.Container) {
|
argF, func(z *container.Container) {
|
||||||
z.SeccompFlags |= seccomp.AllowMultiarch
|
z.SeccompFlags |= seccomp.AllowMultiarch
|
||||||
z.SeccompPresets |= bits.PresetStrict
|
z.SeccompPresets |= comp.PresetStrict
|
||||||
z.Hostname = "hakurei-dbus"
|
z.Hostname = "hakurei-dbus"
|
||||||
if p.output != nil {
|
if p.output != nil {
|
||||||
z.Stdout, z.Stderr = p.output, p.output
|
z.Stdout, z.Stderr = p.output, p.output
|
||||||
@@ -114,7 +114,7 @@ func (p *Proxy) Start() error {
|
|||||||
check.SortAbs(sockDirPaths)
|
check.SortAbs(sockDirPaths)
|
||||||
sockDirPaths = check.CompactAbs(sockDirPaths)
|
sockDirPaths = check.CompactAbs(sockDirPaths)
|
||||||
for _, name := range sockDirPaths {
|
for _, name := range sockDirPaths {
|
||||||
z.Bind(name, name, bits.BindWritable)
|
z.Bind(name, name, comp.BindWritable)
|
||||||
}
|
}
|
||||||
|
|
||||||
// xdg-dbus-proxy bin path
|
// xdg-dbus-proxy bin path
|
||||||
|
|||||||
@@ -32,6 +32,16 @@ nixosTest {
|
|||||||
environment.systemPackages = [
|
environment.systemPackages = [
|
||||||
# For go tests:
|
# For go tests:
|
||||||
(writeShellScriptBin "hakurei-test" ''
|
(writeShellScriptBin "hakurei-test" ''
|
||||||
|
# Assert hst CGO_ENABLED=0: ${
|
||||||
|
with pkgs;
|
||||||
|
runCommand "hakurei-hst-cgo" { nativeBuildInputs = [ go ]; } ''
|
||||||
|
cp -r ${options.environment.hakurei.package.default.src} "$out"
|
||||||
|
chmod -R +w "$out"
|
||||||
|
cp ${writeText "hst_cgo_test.go" ''package hakurei_test;import("testing";"hakurei.app/hst");func TestTemplate(t *testing.T){hst.Template()}''} "$out/hst_cgo_test.go"
|
||||||
|
(cd "$out" && HOME="$(mktemp -d)" CGO_ENABLED=0 go test .)
|
||||||
|
''
|
||||||
|
}
|
||||||
|
|
||||||
cd ${self.packages.${system}.hakurei.src}
|
cd ${self.packages.${system}.hakurei.src}
|
||||||
${fhs}/bin/hakurei-fhs -c \
|
${fhs}/bin/hakurei-fhs -c \
|
||||||
'go test ${if withRace then "-race" else "-count 16"} ./...' \
|
'go test ${if withRace then "-race" else "-count 16"} ./...' \
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ in
|
|||||||
{
|
{
|
||||||
name = "funcgraph-retval";
|
name = "funcgraph-retval";
|
||||||
patch = null;
|
patch = null;
|
||||||
extraStructuredConfig.FUNCTION_GRAPH_RETVAL = lib.kernel.yes;
|
structuredExtraConfig.FUNCTION_GRAPH_RETVAL = lib.kernel.yes;
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user