carlos / platform Public

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

Plain git — no account needed to clone.

Download

Download this file

1package rootstate
2
3import (
4 "os"
5 "path/filepath"
6 "strings"
7
8 "github.com/carlosframework/platform/internal/safefile"
9 "golang.org/x/sys/unix"
10)
11
12func OpenAuthorityFile(path string) (*os.File, error) {
13 if !filepath.IsAbs(path) || filepath.Clean(path) != path || path == "/" {
14 return nil, os.ErrPermission
15 }
16 parent, err := os.Open("/")
17 if err != nil {
18 return nil, err
19 }
20 defer parent.Close()
21 return openAuthorityFile(parent, strings.Split(strings.TrimPrefix(path, "/"), "/"), 0)
22}
23
24func openAuthorityFile(parent *os.File, parts []string, owner uint32) (*os.File, error) {
25 if len(parts) == 0 {
26 return nil, os.ErrPermission
27 }
28 fd, err := unix.FcntlInt(parent.Fd(), unix.F_DUPFD_CLOEXEC, 0)
29 if err != nil {
30 return nil, err
31 }
32 defer func() { unix.Close(fd) }()
33 if err := trusted(fd, owner, unix.S_IFDIR); err != nil {
34 return nil, err
35 }
36 for i, name := range parts {
37 if !component(name) {
38 return nil, os.ErrPermission
39 }
40 if i == len(parts)-1 {
41 break
42 }
43 next, err := unix.Openat(fd, name, unix.O_RDONLY|unix.O_DIRECTORY|unix.O_NOFOLLOW|unix.O_CLOEXEC, 0)
44 if err != nil {
45 return nil, err
46 }
47 unix.Close(fd)
48 fd = next
49 if err := trusted(fd, owner, unix.S_IFDIR); err != nil {
50 return nil, err
51 }
52 }
53 f, err := safefile.OpenFileAt(fd, parts[len(parts)-1], os.O_RDONLY, 0)
54 if err != nil {
55 return nil, err
56 }
57 if err := trusted(int(f.Fd()), owner, unix.S_IFREG); err != nil {
58 f.Close()
59 return nil, err
60 }
61 return f, nil
62}
63