Improve filesystem mounting

This commit is contained in:
EnumDev 2025-03-12 12:15:23 +02:00
parent 3cc35fa7ff
commit ce34b7b21a
4 changed files with 165 additions and 26 deletions

View File

@ -1,3 +1,5 @@
module enit
go 1.23.4
require golang.org/x/sys v0.31.0

View File

@ -1,4 +1,2 @@
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=

View File

@ -1,7 +1,6 @@
package main
import (
"errors"
"flag"
"fmt"
"log"
@ -75,43 +74,45 @@ func setProcessName() error {
func mountVirtualFilesystems() {
fmt.Print("Mounting virtual filesystems... ")
commonFlags := uintptr(0 | syscall.MS_NOSUID | syscall.MS_RELATIME)
commonOptions := "rw,nosuid,relatime"
// Mount /proc
if err := syscall.Mount("proc", "/proc", "proc", commonFlags|syscall.MS_NODEV|syscall.MS_NOEXEC|syscall.MS_REMOUNT, ""); err != nil {
if err := mount("proc", "/proc", "proc", commonOptions+",nodev,noexec", false); err != nil {
panic(err)
}
// Mount /sys
if err := syscall.Mount("sys", "/sys", "sysfs", commonFlags|syscall.MS_NODEV|syscall.MS_NOEXEC|syscall.MS_REMOUNT, ""); err != nil {
if err := mount("sys", "/sys", "sysfs", commonOptions+",nodev,noexec", false); err != nil {
panic(err)
}
// Mount /dev
if err := syscall.Mount("dev", "/dev", "devtmpfs", commonFlags|syscall.MS_REMOUNT, "mode=755,inode64"); err != nil {
if err := mount("dev", "/dev", "devtmpfs", commonOptions+",mode=755,inode64", false); err != nil {
panic(err)
}
// Mount /run
if err := syscall.Mount("run", "/run", "tmpfs", commonFlags|syscall.MS_NODEV|syscall.MS_REMOUNT, "mode=755,inode64"); err != nil {
if err := mount("run", "/run", "tmpfs", commonOptions+",nodev,mode=755,inode64", false); err != nil {
panic(err)
}
// Mount /dev/pts
if err := os.Mkdir("/dev/pts", 0755); err != nil && !errors.Is(err, os.ErrExist) {
panic(err)
}
if err := syscall.Mount("devpts", "/dev/pts", "devpts", commonFlags, "gid=5,mode=620,ptmxmode=000"); err != nil {
if err := mount("devpts", "/dev/pts", "devpts", commonOptions+",gid=5,mode=620,ptmxmode=000", true); err != nil {
panic(err)
}
// Mount /dev/shm
if err := os.Mkdir("/dev/shm", 0755); err != nil && !errors.Is(err, os.ErrExist) {
panic(err)
}
if err := syscall.Mount("shm", "/dev/shm", "tmpfs", commonFlags|syscall.MS_NODEV, "inode64"); err != nil {
if err := mount("shm", "/dev/shm", "tmpfs", commonOptions+",nodev,inode64", true); err != nil {
panic(err)
}
// Mount securityfs
if err := syscall.Mount("securityfs", "/sys/kernel/security", "securityfs", commonFlags, ""); err != nil {
if err := mount("securityfs", "/sys/kernel/security", "securityfs", commonOptions, false); err != nil {
panic(err)
}
// Mount cgroups v2
if err := syscall.Mount("cgroup2", "/sys/fs/cgroup", "cgroup2", commonFlags|syscall.MS_NOEXEC, ""); err != nil {
if err := mount("cgroup2", "/sys/fs/cgroup", "cgroup2", commonOptions+",noexec,nsdelegate,memory_recursiveprot", false); err != nil {
panic(err)
}
@ -119,12 +120,9 @@ func mountVirtualFilesystems() {
}
func mountFilesystems() {
fmt.Print("Mounting filesystems... ")
fmt.Print("Mounting fstab entries... ")
cmd := exec.Command("/bin/mount", "-a")
err := cmd.Run()
if err != nil {
if err := mountFstabEntries(); err != nil {
log.Println("Could not mount fstab entries!")
panic(err)
}

141
cmd/enit/mount.go Normal file
View File

@ -0,0 +1,141 @@
package main
import (
"golang.org/x/sys/unix"
"os"
"slices"
"strings"
)
var flagsEquivalence = map[string]uintptr{
"dirsync": unix.MS_DIRSYNC,
"lazytime": unix.MS_LAZYTIME,
"noatime": unix.MS_NOATIME,
"nodev": unix.MS_NODEV,
"nodiratime": unix.MS_NODIRATIME,
"noexec": unix.MS_NOEXEC,
"nosuid": unix.MS_NOSUID,
"ro": unix.MS_RDONLY,
"rw": 0,
"relatime": unix.MS_RELATIME,
"silent": unix.MS_SILENT,
"strictatime": unix.MS_STRICTATIME,
"sync": unix.MS_SYNCHRONOUS,
"defaults": 0,
}
// Split string flags to mount flags and mount data
func convertMountOptions(options string) (flags []uintptr, data string) {
for _, flag := range strings.Split(options, ",") {
if unixFlag, ok := flagsEquivalence[flag]; ok {
flags = append(flags, unixFlag)
} else {
if data == "" {
data = flag
} else {
data += "," + flag
}
}
}
return flags, data
}
// Combine a unix flag slice or array into a single uintptr
func combineUnixFlags(flagsSlice []uintptr) (flags uintptr) {
flags = 0
for _, flag := range flagsSlice {
flags |= flag
}
return flags
}
// Check whether a certain path is a mountpoint
func isMountpoint(mountpoint string) bool {
if mountpoint != "/" {
mountpoint = strings.TrimRight(mountpoint, "/")
}
if _, err := os.Stat("/proc/mounts"); err != nil {
return false
}
bytes, err := os.ReadFile("/proc/mounts")
if err != nil {
return false
}
for _, line := range strings.Split(string(bytes), "\n") {
line = strings.TrimSpace(line)
if line == "" {
continue
}
if strings.Split(line, " ")[1] == mountpoint {
return true
}
}
return false
}
func mount(source, target, fstype string, options string, mkdir bool) error {
flags, data := convertMountOptions(options)
if isMountpoint(target) && !slices.Contains(flags, unix.MS_REMOUNT) {
flags = append(flags, unix.MS_REMOUNT)
}
if mkdir {
err := os.MkdirAll(target, 0755)
if err != nil {
return err
}
}
if err := unix.Mount(source, target, fstype, combineUnixFlags(flags), data); err != nil {
return err
}
return nil
}
func mountFstabEntries() error {
if _, err := os.Stat("/etc/fstab"); err != nil {
return err
}
bytes, err := os.ReadFile("/etc/fstab")
if err != nil {
return err
}
for _, line := range strings.Split(string(bytes), "\n") {
line = strings.TrimSpace(line)
if strings.HasPrefix(line, "#") || line == "" {
continue
}
source := strings.Split(line, " ")[0]
target := strings.Split(line, " ")[1]
fstype := strings.Split(line, " ")[2]
options := strings.Split(line, " ")[3]
flags, data := convertMountOptions(options)
if slices.Contains(strings.Split(data, ","), "noauto") {
continue
}
if isMountpoint(target) && !slices.Contains(flags, unix.MS_REMOUNT) {
flags = append(flags, unix.MS_REMOUNT)
}
if err := unix.Mount(source, target, fstype, combineUnixFlags(flags), data); err != nil {
return err
}
}
return nil
}