hst/fs: implement overlay fstype
All checks were successful
Test / Create distribution (push) Successful in 33s
Test / Sandbox (push) Successful in 2m8s
Test / Hakurei (push) Successful in 3m8s
Test / Hpkg (push) Successful in 3m59s
Test / Sandbox (race detector) (push) Successful in 4m20s
Test / Hakurei (race detector) (push) Successful in 5m1s
Test / Flake checks (push) Successful in 1m27s
All checks were successful
Test / Create distribution (push) Successful in 33s
Test / Sandbox (push) Successful in 2m8s
Test / Hakurei (push) Successful in 3m8s
Test / Hpkg (push) Successful in 3m59s
Test / Sandbox (race detector) (push) Successful in 4m20s
Test / Hakurei (race detector) (push) Successful in 5m1s
Test / Flake checks (push) Successful in 1m27s
This finally exposes overlay mounts in the high level hakurei API. Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
parent
4433c993fa
commit
9ed3ba85ea
@ -49,6 +49,7 @@ func Test_printShowInstance(t *testing.T) {
|
|||||||
|
|
||||||
Filesystem
|
Filesystem
|
||||||
w+ephemeral(-rwxr-xr-x):/tmp/
|
w+ephemeral(-rwxr-xr-x):/tmp/
|
||||||
|
w*/nix/store:/mnt-root/nix/.rw-store/upper:/mnt-root/nix/.rw-store/work:/mnt-root/nix/.ro-store
|
||||||
*/nix/store
|
*/nix/store
|
||||||
*/run/current-system
|
*/run/current-system
|
||||||
*/run/opengl-driver
|
*/run/opengl-driver
|
||||||
@ -127,6 +128,7 @@ App
|
|||||||
|
|
||||||
Filesystem
|
Filesystem
|
||||||
w+ephemeral(-rwxr-xr-x):/tmp/
|
w+ephemeral(-rwxr-xr-x):/tmp/
|
||||||
|
w*/nix/store:/mnt-root/nix/.rw-store/upper:/mnt-root/nix/.rw-store/work:/mnt-root/nix/.ro-store
|
||||||
*/nix/store
|
*/nix/store
|
||||||
*/run/current-system
|
*/run/current-system
|
||||||
*/run/opengl-driver
|
*/run/opengl-driver
|
||||||
@ -278,6 +280,15 @@ App
|
|||||||
"write": true,
|
"write": true,
|
||||||
"perm": 493
|
"perm": 493
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "overlay",
|
||||||
|
"dst": "/nix/store",
|
||||||
|
"lower": [
|
||||||
|
"/mnt-root/nix/.ro-store"
|
||||||
|
],
|
||||||
|
"upper": "/mnt-root/nix/.rw-store/upper",
|
||||||
|
"work": "/mnt-root/nix/.rw-store/work"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "bind",
|
"type": "bind",
|
||||||
"src": "/nix/store"
|
"src": "/nix/store"
|
||||||
@ -413,6 +424,15 @@ App
|
|||||||
"write": true,
|
"write": true,
|
||||||
"perm": 493
|
"perm": 493
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "overlay",
|
||||||
|
"dst": "/nix/store",
|
||||||
|
"lower": [
|
||||||
|
"/mnt-root/nix/.ro-store"
|
||||||
|
],
|
||||||
|
"upper": "/mnt-root/nix/.rw-store/upper",
|
||||||
|
"work": "/mnt-root/nix/.rw-store/work"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "bind",
|
"type": "bind",
|
||||||
"src": "/nix/store"
|
"src": "/nix/store"
|
||||||
@ -602,6 +622,15 @@ func Test_printPs(t *testing.T) {
|
|||||||
"write": true,
|
"write": true,
|
||||||
"perm": 493
|
"perm": 493
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "overlay",
|
||||||
|
"dst": "/nix/store",
|
||||||
|
"lower": [
|
||||||
|
"/mnt-root/nix/.ro-store"
|
||||||
|
],
|
||||||
|
"upper": "/mnt-root/nix/.rw-store/upper",
|
||||||
|
"work": "/mnt-root/nix/.rw-store/work"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "bind",
|
"type": "bind",
|
||||||
"src": "/nix/store"
|
"src": "/nix/store"
|
||||||
|
@ -81,6 +81,12 @@ func (f *FilesystemConfigJSON) MarshalJSON() ([]byte, error) {
|
|||||||
*FSEphemeral
|
*FSEphemeral
|
||||||
}{fsType{FilesystemEphemeral}, cv}
|
}{fsType{FilesystemEphemeral}, cv}
|
||||||
|
|
||||||
|
case *FSOverlay:
|
||||||
|
v = &struct {
|
||||||
|
fsType
|
||||||
|
*FSOverlay
|
||||||
|
}{fsType{FilesystemOverlay}, cv}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return nil, FSImplError{f.FilesystemConfig}
|
return nil, FSImplError{f.FilesystemConfig}
|
||||||
}
|
}
|
||||||
@ -103,6 +109,9 @@ func (f *FilesystemConfigJSON) UnmarshalJSON(data []byte) error {
|
|||||||
case FilesystemEphemeral:
|
case FilesystemEphemeral:
|
||||||
*f = FilesystemConfigJSON{new(FSEphemeral)}
|
*f = FilesystemConfigJSON{new(FSEphemeral)}
|
||||||
|
|
||||||
|
case FilesystemOverlay:
|
||||||
|
*f = FilesystemConfigJSON{new(FSOverlay)}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return FSTypeError(t.Type)
|
return FSTypeError(t.Type)
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,10 @@ func TestFilesystemConfigJSON(t *testing.T) {
|
|||||||
hst.FSImplError{Value: stubFS{"ephemeral"}},
|
hst.FSImplError{Value: stubFS{"ephemeral"}},
|
||||||
"\x00", "\x00"},
|
"\x00", "\x00"},
|
||||||
|
|
||||||
|
{"bad impl overlay", hst.FilesystemConfigJSON{FilesystemConfig: stubFS{"overlay"}},
|
||||||
|
hst.FSImplError{Value: stubFS{"overlay"}},
|
||||||
|
"\x00", "\x00"},
|
||||||
|
|
||||||
{"bind", hst.FilesystemConfigJSON{
|
{"bind", hst.FilesystemConfigJSON{
|
||||||
FilesystemConfig: &hst.FSBind{
|
FilesystemConfig: &hst.FSBind{
|
||||||
Dst: m("/etc"),
|
Dst: m("/etc"),
|
||||||
@ -55,6 +59,17 @@ func TestFilesystemConfigJSON(t *testing.T) {
|
|||||||
}, nil,
|
}, nil,
|
||||||
`{"type":"ephemeral","dst":"/run/user/65534","write":true,"size":1024,"perm":448}`,
|
`{"type":"ephemeral","dst":"/run/user/65534","write":true,"size":1024,"perm":448}`,
|
||||||
`{"fs":{"type":"ephemeral","dst":"/run/user/65534","write":true,"size":1024,"perm":448},"magic":3236757504}`},
|
`{"fs":{"type":"ephemeral","dst":"/run/user/65534","write":true,"size":1024,"perm":448},"magic":3236757504}`},
|
||||||
|
|
||||||
|
{"overlay", hst.FilesystemConfigJSON{
|
||||||
|
FilesystemConfig: &hst.FSOverlay{
|
||||||
|
Dst: m("/nix/store"),
|
||||||
|
Lower: ms("/mnt-root/nix/.ro-store"),
|
||||||
|
Upper: m("/mnt-root/nix/.rw-store/upper"),
|
||||||
|
Work: m("/mnt-root/nix/.rw-store/work"),
|
||||||
|
},
|
||||||
|
}, nil,
|
||||||
|
`{"type":"overlay","dst":"/nix/store","lower":["/mnt-root/nix/.ro-store"],"upper":"/mnt-root/nix/.rw-store/upper","work":"/mnt-root/nix/.rw-store/work"}`,
|
||||||
|
`{"fs":{"type":"overlay","dst":"/nix/store","lower":["/mnt-root/nix/.ro-store"],"upper":"/mnt-root/nix/.rw-store/upper","work":"/mnt-root/nix/.rw-store/work"},"magic":3236757504}`},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
|
98
hst/fsoverlay.go
Normal file
98
hst/fsoverlay.go
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
package hst
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/gob"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"hakurei.app/container"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() { gob.Register(new(FSOverlay)) }
|
||||||
|
|
||||||
|
// FilesystemOverlay is the [FilesystemConfig.Type] name of an overlay mount point.
|
||||||
|
const FilesystemOverlay = "overlay"
|
||||||
|
|
||||||
|
// FSOverlay represents an overlay mount point.
|
||||||
|
type FSOverlay struct {
|
||||||
|
// mount point in container
|
||||||
|
Dst *container.Absolute `json:"dst"`
|
||||||
|
|
||||||
|
// any filesystem, does not need to be on a writable filesystem, must not be nil
|
||||||
|
Lower []*container.Absolute `json:"lower"`
|
||||||
|
// the upperdir is normally on a writable filesystem, leave as nil to mount Lower readonly
|
||||||
|
Upper *container.Absolute `json:"upper,omitempty"`
|
||||||
|
// the workdir needs to be an empty directory on the same filesystem as Upper, must not be nil if Upper is populated
|
||||||
|
Work *container.Absolute `json:"work,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *FSOverlay) Valid() bool {
|
||||||
|
if o == nil || o.Dst == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, a := range o.Lower {
|
||||||
|
if a == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if o.Upper != nil { // rw
|
||||||
|
return o.Work != nil && len(o.Lower) > 0
|
||||||
|
} else { // ro
|
||||||
|
return len(o.Lower) >= 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *FSOverlay) Target() *container.Absolute {
|
||||||
|
if !o.Valid() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return o.Dst
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *FSOverlay) Host() []*container.Absolute {
|
||||||
|
if !o.Valid() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
p := make([]*container.Absolute, 0, 2+len(o.Lower))
|
||||||
|
if o.Upper != nil && o.Work != nil {
|
||||||
|
p = append(p, o.Upper, o.Work)
|
||||||
|
}
|
||||||
|
p = append(p, o.Lower...)
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *FSOverlay) Apply(op *container.Ops) {
|
||||||
|
if !o.Valid() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if o.Upper != nil && o.Work != nil { // rw
|
||||||
|
op.Overlay(o.Dst, o.Upper, o.Work, o.Lower...)
|
||||||
|
} else { // ro
|
||||||
|
op.OverlayReadonly(o.Dst, o.Lower...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *FSOverlay) String() string {
|
||||||
|
if !o.Valid() {
|
||||||
|
return "<invalid>"
|
||||||
|
}
|
||||||
|
|
||||||
|
lower := make([]string, len(o.Lower))
|
||||||
|
for i, a := range o.Lower {
|
||||||
|
lower[i] = container.EscapeOverlayDataSegment(a.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
if o.Upper != nil && o.Work != nil {
|
||||||
|
return "w*" + strings.Join(append([]string{
|
||||||
|
container.EscapeOverlayDataSegment(o.Dst.String()),
|
||||||
|
container.EscapeOverlayDataSegment(o.Upper.String()),
|
||||||
|
container.EscapeOverlayDataSegment(o.Work.String())},
|
||||||
|
lower...), container.SpecialOverlayPath)
|
||||||
|
} else {
|
||||||
|
return "*" + strings.Join(append([]string{
|
||||||
|
container.EscapeOverlayDataSegment(o.Dst.String())},
|
||||||
|
lower...), container.SpecialOverlayPath)
|
||||||
|
}
|
||||||
|
}
|
50
hst/fsoverlay_test.go
Normal file
50
hst/fsoverlay_test.go
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
package hst_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"hakurei.app/container"
|
||||||
|
"hakurei.app/hst"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestFSOverlay(t *testing.T) {
|
||||||
|
checkFs(t, []fsTestCase{
|
||||||
|
{"nil", (*hst.FSOverlay)(nil), false, nil, nil, nil, "<invalid>"},
|
||||||
|
{"nil lower", &hst.FSOverlay{Dst: m("/etc"), Lower: []*container.Absolute{nil}}, false, nil, nil, nil, "<invalid>"},
|
||||||
|
{"zero lower", &hst.FSOverlay{Dst: m("/etc"), Upper: m("/"), Work: m("/")}, false, nil, nil, nil, "<invalid>"},
|
||||||
|
{"zero lower ro", &hst.FSOverlay{Dst: m("/etc")}, false, nil, nil, nil, "<invalid>"},
|
||||||
|
{"short lower", &hst.FSOverlay{Dst: m("/etc"), Lower: ms("/etc")}, false, nil, nil, nil, "<invalid>"},
|
||||||
|
|
||||||
|
{"full", &hst.FSOverlay{
|
||||||
|
Dst: m("/nix/store"),
|
||||||
|
Lower: ms("/mnt-root/nix/.ro-store"),
|
||||||
|
Upper: m("/mnt-root/nix/.rw-store/upper"),
|
||||||
|
Work: m("/mnt-root/nix/.rw-store/work"),
|
||||||
|
}, true, container.Ops{&container.MountOverlayOp{
|
||||||
|
Target: m("/nix/store"),
|
||||||
|
Lower: ms("/mnt-root/nix/.ro-store"),
|
||||||
|
Upper: m("/mnt-root/nix/.rw-store/upper"),
|
||||||
|
Work: m("/mnt-root/nix/.rw-store/work"),
|
||||||
|
}}, m("/nix/store"), ms("/mnt-root/nix/.rw-store/upper", "/mnt-root/nix/.rw-store/work", "/mnt-root/nix/.ro-store"),
|
||||||
|
"w*/nix/store:/mnt-root/nix/.rw-store/upper:/mnt-root/nix/.rw-store/work:/mnt-root/nix/.ro-store"},
|
||||||
|
|
||||||
|
{"ro", &hst.FSOverlay{
|
||||||
|
Dst: m("/mnt/src"),
|
||||||
|
Lower: ms("/tmp/.src0", "/tmp/.src1"),
|
||||||
|
}, true, container.Ops{&container.MountOverlayOp{
|
||||||
|
Target: m("/mnt/src"),
|
||||||
|
Lower: ms("/tmp/.src0", "/tmp/.src1"),
|
||||||
|
}}, m("/mnt/src"), ms("/tmp/.src0", "/tmp/.src1"),
|
||||||
|
"*/mnt/src:/tmp/.src0:/tmp/.src1"},
|
||||||
|
|
||||||
|
{"ro work", &hst.FSOverlay{
|
||||||
|
Dst: m("/mnt/src"),
|
||||||
|
Lower: ms("/tmp/.src0", "/tmp/.src1"),
|
||||||
|
Work: m("/tmp"),
|
||||||
|
}, true, container.Ops{&container.MountOverlayOp{
|
||||||
|
Target: m("/mnt/src"),
|
||||||
|
Lower: ms("/tmp/.src0", "/tmp/.src1"),
|
||||||
|
}}, m("/mnt/src"), ms("/tmp/.src0", "/tmp/.src1"),
|
||||||
|
"*/mnt/src:/tmp/.src0:/tmp/.src1"},
|
||||||
|
})
|
||||||
|
}
|
@ -79,6 +79,12 @@ func Template() *Config {
|
|||||||
},
|
},
|
||||||
Filesystem: []FilesystemConfigJSON{
|
Filesystem: []FilesystemConfigJSON{
|
||||||
{&FSEphemeral{Dst: container.AbsFHSTmp, Write: true, Perm: 0755}},
|
{&FSEphemeral{Dst: container.AbsFHSTmp, Write: true, Perm: 0755}},
|
||||||
|
{&FSOverlay{
|
||||||
|
Dst: container.MustAbs("/nix/store"),
|
||||||
|
Lower: []*container.Absolute{container.MustAbs("/mnt-root/nix/.ro-store")},
|
||||||
|
Upper: container.MustAbs("/mnt-root/nix/.rw-store/upper"),
|
||||||
|
Work: container.MustAbs("/mnt-root/nix/.rw-store/work"),
|
||||||
|
}},
|
||||||
{&FSBind{Src: container.MustAbs("/nix/store")}},
|
{&FSBind{Src: container.MustAbs("/nix/store")}},
|
||||||
{&FSBind{Src: container.AbsFHSRun.Append("current-system")}},
|
{&FSBind{Src: container.AbsFHSRun.Append("current-system")}},
|
||||||
{&FSBind{Src: container.AbsFHSRun.Append("opengl-driver")}},
|
{&FSBind{Src: container.AbsFHSRun.Append("opengl-driver")}},
|
||||||
|
@ -103,6 +103,15 @@ func TestTemplate(t *testing.T) {
|
|||||||
"write": true,
|
"write": true,
|
||||||
"perm": 493
|
"perm": 493
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "overlay",
|
||||||
|
"dst": "/nix/store",
|
||||||
|
"lower": [
|
||||||
|
"/mnt-root/nix/.ro-store"
|
||||||
|
],
|
||||||
|
"upper": "/mnt-root/nix/.rw-store/upper",
|
||||||
|
"work": "/mnt-root/nix/.rw-store/work"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "bind",
|
"type": "bind",
|
||||||
"src": "/nix/store"
|
"src": "/nix/store"
|
||||||
|
@ -47,7 +47,10 @@ in
|
|||||||
];
|
];
|
||||||
|
|
||||||
fs = fs "dead" {
|
fs = fs "dead" {
|
||||||
".hakurei" = fs "800001ed" { } null;
|
".hakurei" = fs "800001ed" {
|
||||||
|
".ro-store" = fs "801001fd" null null;
|
||||||
|
store = fs "800001ff" null null;
|
||||||
|
} null;
|
||||||
bin = fs "800001ed" { sh = fs "80001ff" null null; } null;
|
bin = fs "800001ed" { sh = fs "80001ff" null null; } null;
|
||||||
dev = fs "800001ed" null null;
|
dev = fs "800001ed" null null;
|
||||||
etc = fs "800001ed" {
|
etc = fs "800001ed" {
|
||||||
@ -218,6 +221,8 @@ in
|
|||||||
(ent "/devices" "/sys/devices" "ro,nosuid,nodev,noexec,relatime" "sysfs" "sysfs" "rw")
|
(ent "/devices" "/sys/devices" "ro,nosuid,nodev,noexec,relatime" "sysfs" "sysfs" "rw")
|
||||||
(ent "/dri" "/dev/dri" "rw,nosuid" "devtmpfs" "devtmpfs" ignore)
|
(ent "/dri" "/dev/dri" "rw,nosuid" "devtmpfs" "devtmpfs" ignore)
|
||||||
(ent "/var/cache" "/var/cache" "rw,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
|
(ent "/var/cache" "/var/cache" "rw,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
|
||||||
|
(ent "/" "/.hakurei/.ro-store" "rw,relatime" "overlay" "overlay" "ro,lowerdir=/host/nix/.ro-store:/host/nix/.rw-store/upper,redirect_dir=nofollow,userxattr")
|
||||||
|
(ent "/" "/.hakurei/store" "rw,relatime" "overlay" "overlay" "rw,lowerdir=/host/nix/.ro-store:/host/nix/.rw-store/upper,upperdir=/host/tmp/.hakurei-store-rw/upper,workdir=/host/tmp/.hakurei-store-rw/work,redirect_dir=nofollow,userxattr")
|
||||||
(ent "/etc" ignore "ro,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
|
(ent "/etc" ignore "ro,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
|
||||||
(ent "/" "/run/user" "rw,nosuid,nodev,relatime" "tmpfs" "ephemeral" "rw,size=4k,mode=755,uid=1000004,gid=1000004")
|
(ent "/" "/run/user" "rw,nosuid,nodev,relatime" "tmpfs" "ephemeral" "rw,size=4k,mode=755,uid=1000004,gid=1000004")
|
||||||
(ent "/tmp/hakurei.1000/runtime/4" "/run/user/65534" "rw,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
|
(ent "/tmp/hakurei.1000/runtime/4" "/run/user/65534" "rw,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
|
||||||
|
@ -56,7 +56,10 @@ in
|
|||||||
];
|
];
|
||||||
|
|
||||||
fs = fs "dead" {
|
fs = fs "dead" {
|
||||||
".hakurei" = fs "800001ed" { } null;
|
".hakurei" = fs "800001ed" {
|
||||||
|
".ro-store" = fs "801001fd" null null;
|
||||||
|
store = fs "800001ff" null null;
|
||||||
|
} null;
|
||||||
bin = fs "800001ed" { sh = fs "80001ff" null null; } null;
|
bin = fs "800001ed" { sh = fs "80001ff" null null; } null;
|
||||||
dev = fs "800001ed" {
|
dev = fs "800001ed" {
|
||||||
core = fs "80001ff" null null;
|
core = fs "80001ff" null null;
|
||||||
@ -248,6 +251,8 @@ in
|
|||||||
(ent "/devices" "/sys/devices" "ro,nosuid,nodev,noexec,relatime" "sysfs" "sysfs" "rw")
|
(ent "/devices" "/sys/devices" "ro,nosuid,nodev,noexec,relatime" "sysfs" "sysfs" "rw")
|
||||||
(ent "/dri" "/dev/dri" "rw,nosuid" "devtmpfs" "devtmpfs" ignore)
|
(ent "/dri" "/dev/dri" "rw,nosuid" "devtmpfs" "devtmpfs" ignore)
|
||||||
(ent "/var/cache" "/var/cache" "rw,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
|
(ent "/var/cache" "/var/cache" "rw,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
|
||||||
|
(ent "/" "/.hakurei/.ro-store" "rw,relatime" "overlay" "overlay" "ro,lowerdir=/host/nix/.ro-store:/host/nix/.rw-store/upper,redirect_dir=nofollow,userxattr")
|
||||||
|
(ent "/" "/.hakurei/store" "rw,relatime" "overlay" "overlay" "rw,lowerdir=/host/nix/.ro-store:/host/nix/.rw-store/upper,upperdir=/host/tmp/.hakurei-store-rw/upper,workdir=/host/tmp/.hakurei-store-rw/work,redirect_dir=nofollow,userxattr")
|
||||||
(ent "/etc" ignore "ro,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
|
(ent "/etc" ignore "ro,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
|
||||||
(ent "/" "/run/user" "rw,nosuid,nodev,relatime" "tmpfs" "ephemeral" "rw,size=4k,mode=755,uid=1000003,gid=1000003")
|
(ent "/" "/run/user" "rw,nosuid,nodev,relatime" "tmpfs" "ephemeral" "rw,size=4k,mode=755,uid=1000003,gid=1000003")
|
||||||
(ent "/tmp/hakurei.1000/runtime/3" "/run/user/1000" "rw,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
|
(ent "/tmp/hakurei.1000/runtime/3" "/run/user/1000" "rw,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
|
||||||
|
@ -56,7 +56,10 @@ in
|
|||||||
];
|
];
|
||||||
|
|
||||||
fs = fs "dead" {
|
fs = fs "dead" {
|
||||||
".hakurei" = fs "800001ed" { } null;
|
".hakurei" = fs "800001ed" {
|
||||||
|
".ro-store" = fs "801001fd" null null;
|
||||||
|
store = fs "800001ff" null null;
|
||||||
|
} null;
|
||||||
bin = fs "800001ed" { sh = fs "80001ff" null null; } null;
|
bin = fs "800001ed" { sh = fs "80001ff" null null; } null;
|
||||||
dev = fs "800001ed" {
|
dev = fs "800001ed" {
|
||||||
console = fs "4200190" null null;
|
console = fs "4200190" null null;
|
||||||
@ -250,6 +253,8 @@ in
|
|||||||
(ent "/devices" "/sys/devices" "ro,nosuid,nodev,noexec,relatime" "sysfs" "sysfs" "rw")
|
(ent "/devices" "/sys/devices" "ro,nosuid,nodev,noexec,relatime" "sysfs" "sysfs" "rw")
|
||||||
(ent "/dri" "/dev/dri" "rw,nosuid" "devtmpfs" "devtmpfs" ignore)
|
(ent "/dri" "/dev/dri" "rw,nosuid" "devtmpfs" "devtmpfs" ignore)
|
||||||
(ent "/var/cache" "/var/cache" "rw,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
|
(ent "/var/cache" "/var/cache" "rw,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
|
||||||
|
(ent "/" "/.hakurei/.ro-store" "rw,relatime" "overlay" "overlay" "ro,lowerdir=/host/nix/.ro-store:/host/nix/.rw-store/upper,redirect_dir=nofollow,userxattr")
|
||||||
|
(ent "/" "/.hakurei/store" "rw,relatime" "overlay" "overlay" "rw,lowerdir=/host/nix/.ro-store:/host/nix/.rw-store/upper,upperdir=/host/tmp/.hakurei-store-rw/upper,workdir=/host/tmp/.hakurei-store-rw/work,redirect_dir=nofollow,uuid=on,userxattr")
|
||||||
(ent "/etc" ignore "ro,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
|
(ent "/etc" ignore "ro,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
|
||||||
(ent "/" "/run/user" "rw,nosuid,nodev,relatime" "tmpfs" "ephemeral" "rw,size=4k,mode=755,uid=1000002,gid=1000002")
|
(ent "/" "/run/user" "rw,nosuid,nodev,relatime" "tmpfs" "ephemeral" "rw,size=4k,mode=755,uid=1000002,gid=1000002")
|
||||||
(ent "/tmp/hakurei.1000/runtime/2" "/run/user/65534" "rw,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
|
(ent "/tmp/hakurei.1000/runtime/2" "/run/user/65534" "rw,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
|
||||||
|
@ -82,6 +82,24 @@ in
|
|||||||
src = "/var/cache";
|
src = "/var/cache";
|
||||||
write = true;
|
write = true;
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
type = "overlay";
|
||||||
|
dst = "/.hakurei/.ro-store";
|
||||||
|
lower = [
|
||||||
|
"/nix/.ro-store"
|
||||||
|
"/nix/.rw-store/upper"
|
||||||
|
];
|
||||||
|
}
|
||||||
|
{
|
||||||
|
type = "overlay";
|
||||||
|
dst = "/.hakurei/store";
|
||||||
|
lower = [
|
||||||
|
"/nix/.ro-store"
|
||||||
|
"/nix/.rw-store/upper"
|
||||||
|
];
|
||||||
|
upper = "/tmp/.hakurei-store-rw/upper";
|
||||||
|
work = "/tmp/.hakurei-store-rw/work";
|
||||||
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
inherit (testCases) apps;
|
inherit (testCases) apps;
|
||||||
|
@ -55,6 +55,7 @@ print(machine.fail("sudo -u alice -i hakurei run capsh --has-p=CAP_SYS_ADMIN"))
|
|||||||
print(machine.fail("sudo -u alice -i hakurei run umount -R /dev"))
|
print(machine.fail("sudo -u alice -i hakurei run umount -R /dev"))
|
||||||
|
|
||||||
# Check sandbox outcome:
|
# Check sandbox outcome:
|
||||||
|
machine.succeed("install -dm0777 /tmp/.hakurei-store-rw/{upper,work}")
|
||||||
check_offset = 0
|
check_offset = 0
|
||||||
def check_sandbox(name):
|
def check_sandbox(name):
|
||||||
global check_offset
|
global check_offset
|
||||||
|
Loading…
x
Reference in New Issue
Block a user