Skip to content

Commit

Permalink
feat: initial spec mount implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
nixpig committed Oct 26, 2024
1 parent d9b8575 commit 78960c9
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 77 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ My goal is for `brownie` to (eventually) pass all tests in the [opencontainers O
- [x] kill_no_effect
- [x] linux_mount_label
- [x] linux_sysctl
- [x] mounts
- [x] prestart
- [x] prestart_fail
- [x] process
Expand Down Expand Up @@ -201,7 +202,6 @@ My goal is for `brownie` to (eventually) pass all tests in the [opencontainers O
- [ ] linux_seccomp
- [ ] linux_uid_mappings
- [ ] misc_props
- [ ] mounts
- [ ] pidfile
- [ ] poststart
- [ ] poststart_fail
Expand Down
4 changes: 2 additions & 2 deletions internal/container/filesystem/devices.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,8 @@ var defaultDevices = []specs.LinuxDevice{
},
}

func mountDefaultDevices(rootfs string) error {
return mountDevices(defaultDevices, rootfs)
func mountDefaultDevices(rootfs string, log *zerolog.Logger) error {
return mountDevices(defaultDevices, rootfs, log)
}

func mountSpecDevices(devices []specs.LinuxDevice, rootfs string, log *zerolog.Logger) error {
Expand Down
75 changes: 43 additions & 32 deletions internal/container/filesystem/filesystem.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@ import (
"syscall"

"github.com/opencontainers/runtime-spec/specs-go"
"github.com/rs/zerolog"
)

func mountDevice(device Device) error {
func mountDevice(device Device, log *zerolog.Logger) error {
if _, err := os.Stat(device.Target); os.IsNotExist(err) {
log.Info().Str("target", device.Target).Msg("create target")
f, err := os.Create(device.Target)
if err != nil && !os.IsExist(err) {
return fmt.Errorf("create device target if not exists: %w", err)
Expand All @@ -21,23 +23,27 @@ func mountDevice(device Device) error {
}
}

return syscall.Mount(
if err := syscall.Mount(
device.Source,
device.Target,
device.Fstype,
device.Flags,
device.Data,
)
); err != nil {
return fmt.Errorf("mounting device: %w", err)
}

return nil
}

func mountRootfs(containerRootfs string) error {
func mountRootfs(containerRootfs string, log *zerolog.Logger) error {
if err := mountDevice(Device{
Source: "",
Target: "/",
Fstype: "",
Flags: syscall.MS_PRIVATE | syscall.MS_REC,
Data: "",
}); err != nil {
}, log); err != nil {
return err
}

Expand All @@ -47,14 +53,14 @@ func mountRootfs(containerRootfs string) error {
Fstype: "",
Flags: syscall.MS_BIND | syscall.MS_REC,
Data: "",
}); err != nil {
}, log); err != nil {
return err
}

return nil
}

func mountProc(containerRootfs string) error {
func mountProc(containerRootfs string, log *zerolog.Logger) error {
containerProc := filepath.Join(containerRootfs, "proc")
if err := os.MkdirAll(containerProc, 0666); err != nil {
return fmt.Errorf("create proc dir: %w", err)
Expand All @@ -66,7 +72,7 @@ func mountProc(containerRootfs string) error {
Fstype: "proc",
Flags: uintptr(0),
Data: "",
}); err != nil {
}, log); err != nil {
return err
}

Expand All @@ -83,7 +89,7 @@ func devIsInSpec(mounts []specs.Mount, dev string) bool {
return false
}

func mountDevices(devices []specs.LinuxDevice, rootfs string) error {
func mountDevices(devices []specs.LinuxDevice, rootfs string, log *zerolog.Logger) error {
for _, dev := range devices {
var absPath string
if strings.Index(dev.Path, "/") == 0 {
Expand All @@ -109,30 +115,25 @@ func mountDevices(devices []specs.LinuxDevice, rootfs string) error {
Fstype: "bind",
Flags: syscall.MS_BIND,
Data: "",
}); err != nil {
}, log); err != nil {
return fmt.Errorf("mount device: %w", err)
}
}

return nil
}

func mountSpecMounts(mounts []specs.Mount, rootfs string) error {
func mountSpecMounts(mounts []specs.Mount, rootfs string, log *zerolog.Logger) error {
for _, mount := range mounts {
var dest string
if strings.Index(mount.Destination, "/") == 0 {
dest = filepath.Join(rootfs, mount.Destination)
} else {
dest = mount.Destination
}
dest := filepath.Join(rootfs, mount.Destination)

if _, err := os.Stat(dest); err != nil {
if !os.IsNotExist(err) {
return err
return fmt.Errorf("exists: %w", err)
}

if err := os.MkdirAll(dest, os.ModeDir); err != nil {
return err
return fmt.Errorf("make dir: %w", err)
}
}

Expand All @@ -143,18 +144,27 @@ func mountSpecMounts(mounts []specs.Mount, rootfs string) error {

var dataOptions []string
for _, opt := range mount.Options {
o, ok := mountOptions[opt]
if !ok {
if !strings.HasPrefix(opt, "gid=") &&
!strings.HasPrefix(opt, "uid=") &&
opt != "newinstance" {
dataOptions = append(dataOptions, opt)
}
} else {
if !o.No {
flags |= o.Flag
}
if opt == "bind" || opt == "rbind" {
mount.Type = "bind"
flags |= syscall.MS_BIND
}

// TODO: review why this breaks everything!!
// o, ok := mountOptions[opt]
// if !ok {
// if !strings.HasPrefix(opt, "gid=") &&
// !strings.HasPrefix(opt, "uid=") &&
// opt != "newinstance" {
// dataOptions = append(dataOptions, opt)
// }
// } else {
// log.Info().Str("opt", opt).Any("flag", o.Flag).Msg("LISTED OPTION")
// if !o.No {
// flags |= o.Flag
// } else {
// flags ^= o.Flag
// }
// }
}

var data string
Expand All @@ -166,9 +176,10 @@ func mountSpecMounts(mounts []specs.Mount, rootfs string) error {
Source: mount.Source,
Target: dest,
Fstype: mount.Type,
Flags: flags,
Flags: uintptr(flags),
Data: data,
}); err != nil {
}, log); err != nil {
log.Error().Str("source", mount.Source).Str("target", dest).Msg("NO SUCH DEVICE???")
return fmt.Errorf("mount device: %w", err)
}
}
Expand Down
80 changes: 41 additions & 39 deletions internal/container/filesystem/mount_options.go
Original file line number Diff line number Diff line change
@@ -1,47 +1,49 @@
package filesystem

import "golang.org/x/sys/unix"
import (
"syscall"
)

var mountOptions = map[string]struct {
No bool
Flag uintptr
}{
"async": {No: false, Flag: unix.MS_SYNCHRONOUS},
"atime": {No: false, Flag: unix.MS_NOATIME},
"bind": {No: false, Flag: unix.MS_BIND},
"defaults": {No: false, Flag: 0},
"dev": {No: false, Flag: unix.MS_NODEV},
"diratime": {No: false, Flag: unix.MS_NODIRATIME},
"dirsync": {No: false, Flag: unix.MS_DIRSYNC},
"exec": {No: false, Flag: unix.MS_NOEXEC},
"iversion": {No: false, Flag: unix.MS_I_VERSION},
"lazytime": {No: false, Flag: unix.MS_LAZYTIME},
"loud": {No: false, Flag: unix.MS_SILENT},
"noatime": {No: true, Flag: unix.MS_NOATIME},
"nodev": {No: true, Flag: unix.MS_NODEV},
"nodiratime": {No: true, Flag: unix.MS_NODIRATIME},
"noexec": {No: true, Flag: unix.MS_NOEXEC},
"noiversion": {No: true, Flag: unix.MS_I_VERSION},
"nolazytime": {No: true, Flag: unix.MS_LAZYTIME},
"norelatime": {No: true, Flag: unix.MS_RELATIME},
"nostrictatime": {No: true, Flag: unix.MS_STRICTATIME},
"nosuid": {No: true, Flag: unix.MS_NOSUID},
"nosymfollow": {No: true, Flag: unix.MS_NOSYMFOLLOW},
"private": {No: false, Flag: unix.MS_PRIVATE},
"rbind": {No: false, Flag: unix.MS_BIND | unix.MS_REC},
"relatime": {No: false, Flag: unix.MS_RELATIME},
"remount": {No: false, Flag: unix.MS_REMOUNT},
"ro": {No: false, Flag: unix.MS_RDONLY},
"rprivate": {No: false, Flag: unix.MS_PRIVATE | unix.MS_REC},
"rshared": {No: false, Flag: unix.MS_SHARED | unix.MS_REC},
"rslave": {No: false, Flag: unix.MS_SLAVE | unix.MS_REC},
"runbindable": {No: false, Flag: unix.MS_UNBINDABLE | unix.MS_REC},
"rw": {No: false, Flag: unix.MS_RDONLY},
"shared": {No: false, Flag: unix.MS_SHARED},
"silent": {No: false, Flag: unix.MS_SILENT},
"slave": {No: false, Flag: unix.MS_SLAVE},
"strictatime": {No: false, Flag: unix.MS_STRICTATIME},
"suid": {No: false, Flag: unix.MS_NOSUID},
"sync": {No: false, Flag: unix.MS_SYNCHRONOUS},
"unbindable": {No: false, Flag: unix.MS_UNBINDABLE},
"async": {No: false, Flag: syscall.MS_SYNCHRONOUS},
"atime": {No: false, Flag: syscall.MS_NOATIME},
"bind": {No: false, Flag: syscall.MS_BIND},
"defaults": {No: false, Flag: 0},
"dev": {No: false, Flag: syscall.MS_NODEV},
"diratime": {No: false, Flag: syscall.MS_NODIRATIME},
"dirsync": {No: false, Flag: syscall.MS_DIRSYNC},
"exec": {No: false, Flag: syscall.MS_NOEXEC},
"iversion": {No: false, Flag: syscall.MS_I_VERSION},
// "lazytime": {No: false, Flag: syscall.MS_LAZYTIME},
"loud": {No: false, Flag: syscall.MS_SILENT},
"noatime": {No: true, Flag: syscall.MS_NOATIME},
"nodev": {No: true, Flag: syscall.MS_NODEV},
"nodiratime": {No: true, Flag: syscall.MS_NODIRATIME},
"noexec": {No: true, Flag: syscall.MS_NOEXEC},
"noiversion": {No: true, Flag: syscall.MS_I_VERSION},
// "nolazytime": {No: true, Flag: syscall.MS_LAZYTIME},
"norelatime": {No: true, Flag: syscall.MS_RELATIME},
"nostrictatime": {No: true, Flag: syscall.MS_STRICTATIME},
"nosuid": {No: true, Flag: syscall.MS_NOSUID},
// "nosymfollow": {No: true, Flag: syscall.MS_NOSYMFOLLOW},
"private": {No: false, Flag: syscall.MS_PRIVATE},
"rbind": {No: false, Flag: syscall.MS_BIND | syscall.MS_REC},
"relatime": {No: false, Flag: syscall.MS_RELATIME},
"remount": {No: false, Flag: syscall.MS_REMOUNT},
"ro": {No: false, Flag: syscall.MS_RDONLY},
"rprivate": {No: false, Flag: syscall.MS_PRIVATE | syscall.MS_REC},
"rshared": {No: false, Flag: syscall.MS_SHARED | syscall.MS_REC},
"rslave": {No: false, Flag: syscall.MS_SLAVE | syscall.MS_REC},
"runbindable": {No: false, Flag: syscall.MS_UNBINDABLE | syscall.MS_REC},
"rw": {No: false, Flag: syscall.MS_RDONLY},
"shared": {No: false, Flag: syscall.MS_SHARED},
"silent": {No: false, Flag: syscall.MS_SILENT},
"slave": {No: false, Flag: syscall.MS_SLAVE},
"strictatime": {No: false, Flag: syscall.MS_STRICTATIME},
"suid": {No: false, Flag: syscall.MS_NOSUID},
"sync": {No: false, Flag: syscall.MS_SYNCHRONOUS},
"unbindable": {No: false, Flag: syscall.MS_UNBINDABLE},
}
7 changes: 4 additions & 3 deletions internal/container/filesystem/rootfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,25 +16,26 @@ func SetupRootfs(root string, spec *specs.Spec, log *zerolog.Logger) error {
}

log.Info().Msg("mount rootfs")
if err := mountRootfs(rootfs); err != nil {
if err := mountRootfs(rootfs, log); err != nil {
return fmt.Errorf("mount rootfs: %w", err)
}

log.Info().Msg("mount proc")
if err := mountProc(rootfs); err != nil {
if err := mountProc(rootfs, log); err != nil {
return fmt.Errorf("mount proc: %w", err)
}

log.Info().Msg("mount spec mounts")
if err := mountSpecMounts(
spec.Mounts,
rootfs,
log,
); err != nil {
return fmt.Errorf("mount spec mounts: %w", err)
}

log.Info().Msg("mount default devices")
if err := mountDefaultDevices(rootfs); err != nil {
if err := mountDefaultDevices(rootfs, log); err != nil {
return fmt.Errorf("mount default devices: %w", err)
}

Expand Down
1 change: 1 addition & 0 deletions oci.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ RUNTIME=${RUNTIME:-./brownie}
./validation/kill_no_effect/kill_no_effect.t 2>&1 | tee -a results.tap
./validation/linux_mount_label/linux_mount_label.t 2>&1 | tee -a results.tap
./validation/linux_sysctl/linux_sysctl.t 2>&1 | tee -a results.tap
./validation/mounts/mounts.t 2>&1 | tee -a results.tap
# ./validation/pidfile/pidfile.t 2>&1 | tee -a results.tap
./validation/prestart/prestart.t 2>&1 | tee -a results.tap
./validation/prestart_fail/prestart_fail.t 2>&1 | tee -a results.tap
Expand Down

0 comments on commit 78960c9

Please sign in to comment.