| 1 | package host |
| 2 | |
| 3 | import ( |
| 4 | "github.com/carlosframework/platform/internal/instancectl" |
| 5 | "github.com/carlosframework/platform/internal/rootstate" |
| 6 | "github.com/carlosframework/platform/internal/safefile" |
| 7 | "golang.org/x/sys/unix" |
| 8 | "os" |
| 9 | ) |
| 10 | |
| 11 | func openClaimUnitDropin(unit string) (*os.File, error) { |
| 12 | role, _, ordinary := instancectl.ParseUnitName(unit) |
| 13 | if !instancectl.ValidBoundClaimUnit(unit) && !(ordinary && role == instancectl.RoleRun) { |
| 14 | return nil, os.ErrPermission |
| 15 | } |
| 16 | const base = "/run/systemd/system" |
| 17 | checked, err := rootstate.Open(base, false, true) |
| 18 | if err != nil { |
| 19 | return nil, err |
| 20 | } |
| 21 | defer checked.Close() |
| 22 | parent, err := safefile.OpenDir(base) |
| 23 | if err != nil { |
| 24 | return nil, err |
| 25 | } |
| 26 | defer parent.Close() |
| 27 | fd, err := unix.Openat(int(parent.Fd()), unit+".d", unix.O_RDONLY|unix.O_DIRECTORY|unix.O_NOFOLLOW|unix.O_CLOEXEC, 0) |
| 28 | if err != nil { |
| 29 | return nil, err |
| 30 | } |
| 31 | defer unix.Close(fd) |
| 32 | var st unix.Stat_t |
| 33 | if err := unix.Fstat(fd, &st); err != nil { |
| 34 | return nil, err |
| 35 | } |
| 36 | if st.Uid != 0 || st.Mode&0022 != 0 || st.Mode&unix.S_IFMT != unix.S_IFDIR { |
| 37 | return nil, os.ErrPermission |
| 38 | } |
| 39 | f, err := safefile.OpenFileAt(fd, "60-claim-launch.conf", os.O_RDONLY, 0) |
| 40 | if err != nil { |
| 41 | return nil, err |
| 42 | } |
| 43 | if err = unix.Fstat(int(f.Fd()), &st); err != nil { |
| 44 | f.Close() |
| 45 | return nil, err |
| 46 | } |
| 47 | if st.Uid != 0 || st.Mode&0022 != 0 || st.Mode&unix.S_IFMT != unix.S_IFREG || st.Nlink != 1 { |
| 48 | f.Close() |
| 49 | return nil, os.ErrPermission |
| 50 | } |
| 51 | return f, nil |
| 52 | } |
| 53 | |