carlos / platform Public

Clone
git clone https://amadan.net/carlos/platform

Plain git — no account needed to clone.

Download

Download this file

1//go:build linux
2
3package host
4
5import (
6 "encoding/hex"
7 "os"
8
9 "github.com/carlosframework/platform/internal/hostbox"
10 "golang.org/x/sys/unix"
11)
12
13// O_PATH pins the no-follow inode without opening a device or reading tenant
14// bytes. Compare the descriptor and name around the handle lookup.
15func servingParkPersistentArtifact(parent *os.File, expected servingParkFile) (servingParkPersistentFile, error) {
16 var zero servingParkPersistentFile
17 fd, err := unix.Openat(int(parent.Fd()), expected.Name, unix.O_PATH|unix.O_NOFOLLOW|unix.O_CLOEXEC, 0)
18 if err != nil {
19 return zero, err
20 }
21 defer unix.Close(fd)
22 var st unix.Statx_t
23 if err = unix.Statx(fd, "", unix.AT_EMPTY_PATH|unix.AT_SYMLINK_NOFOLLOW, unix.STATX_BASIC_STATS|unix.STATX_MNT_ID, &st); err != nil {
24 return zero, err
25 }
26 if !servingParkStatxMatches(expected, st) {
27 return zero, hostbox.ErrChanged
28 }
29 var fs unix.Statfs_t
30 if err = unix.Fstatfs(fd, &fs); err != nil {
31 return zero, err
32 }
33 h, mount, err := unix.NameToHandleAt(fd, "", unix.AT_EMPTY_PATH)
34 if err != nil {
35 return zero, err
36 }
37 out := servingParkPersistentFile{Filesystem: fs.Fsid.Val, Type: h.Type(), Handle: hex.EncodeToString(h.Bytes()), Owner: st.Uid, Mode: uint32(st.Mode)}
38 if !out.valid() || mount <= 0 || uint64(mount) != expected.Mount {
39 return zero, hostbox.ErrChanged
40 }
41 var again unix.Statx_t
42 if err = unix.Statx(int(parent.Fd()), expected.Name, unix.AT_SYMLINK_NOFOLLOW, unix.STATX_BASIC_STATS|unix.STATX_MNT_ID, &again); err != nil {
43 return zero, err
44 }
45 if !servingParkStatxMatches(expected, again) || again.Uid != st.Uid || again.Mode != st.Mode {
46 return zero, hostbox.ErrChanged
47 }
48 return out, nil
49}
50
51func servingParkStatxMatches(expected servingParkFile, st unix.Statx_t) bool {
52 return expected.Present && st.Mask&unix.STATX_MNT_ID != 0 && st.Mode&unix.S_IFMT == unix.S_IFREG && st.Nlink == 1 && unix.Mkdev(st.Dev_major, st.Dev_minor) == expected.Device && st.Ino == expected.Inode && st.Mnt_id == expected.Mount && st.Blocks <= ^uint64(0)/512 && st.Blocks*512 == expected.Bytes
53}
54