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 "errors"
7 "os"
8 "os/user"
9 "strconv"
10
11 "github.com/carlosframework/platform/internal/hostwrite"
12 "github.com/carlosframework/platform/internal/safefile"
13 "golang.org/x/sys/unix"
14)
15
16func claimStateOwner() (int, int, error) {
17 u, err := user.Lookup(serviceUser)
18 if err != nil {
19 return 0, 0, err
20 }
21 uid, err := strconv.Atoi(u.Uid)
22 if err != nil || uid <= 0 {
23 return 0, 0, hostwrite.ErrUnavailable
24 }
25 gid, err := strconv.Atoi(u.Gid)
26 return uid, gid, err
27}
28func claimPrivatePathOwner(path string, uid, gid int, directory bool) error {
29 var f *os.File
30 var err error
31 if directory {
32 f, err = safefile.OpenDir(path)
33 } else {
34 f, err = safefile.OpenFile(path, os.O_RDONLY, 0)
35 }
36 if err != nil {
37 return err
38 }
39 defer f.Close()
40 fd := int(f.Fd())
41 var stat unix.Stat_t
42 if err = unix.Fstat(fd, &stat); err != nil {
43 return err
44 }
45 kind := uint32(unix.S_IFREG)
46 mode := uint32(0600)
47 if directory {
48 kind = unix.S_IFDIR
49 mode = 0700
50 }
51 if stat.Mode&unix.S_IFMT != kind || (!directory && stat.Nlink != 1) {
52 return hostwrite.ErrUnavailable
53 }
54 if os.Geteuid() == 0 {
55 if err = unix.Fchown(fd, uid, gid); err != nil {
56 return err
57 }
58 if err = unix.Fchmod(fd, mode); err != nil {
59 return err
60 }
61 } else {
62 if int(stat.Uid) != uid {
63 return hostwrite.ErrUnavailable
64 }
65 if err = unix.Fchmod(fd, mode); err != nil {
66 return err
67 }
68 }
69 return nil
70}
71func prepareClaimStateDirectory(path string) error {
72 uid, gid, err := claimStateOwner()
73 if err != nil {
74 return err
75 }
76 if err = safefile.MkdirAll(path, 0700); err != nil {
77 return err
78 }
79 // Retirement journals are root's own and live in /var/lib/carlos-claims.
80 return claimPrivatePathOwner(path, uid, gid, true)
81}
82func claimStateDatabaseOwner(path string) error {
83 uid, gid, err := claimStateOwner()
84 if err != nil {
85 return err
86 }
87 for _, suffix := range []string{"", "-wal", "-shm"} {
88 err = claimPrivatePathOwner(path+suffix, uid, gid, false)
89 if suffix != "" && errors.Is(err, os.ErrNotExist) {
90 continue
91 }
92 if err != nil {
93 return err
94 }
95 }
96 return nil
97}
98