resolve vars and globbing internally in fs package

master
brl 10 years ago
parent 539bed1768
commit 4e12488ca5

@ -68,34 +68,81 @@ func (fs *Filesystem) CreateSymlink(oldpath, newpath string) error {
return nil return nil
} }
func (fs *Filesystem) BindPath(path, target string, readonly bool) error { func (fs *Filesystem) BindPath(target string, flags int, u *user.User) error {
return fs.BindOrCreate(path, target, readonly, nil) return fs.bindResolve(target, "", flags, u)
} }
func (fs *Filesystem) BindOrCreate(p, target string, readonly bool, u *user.User) error { func (fs *Filesystem) BindTo(from string, to string, flags int, u *user.User) error {
src, err := filepath.EvalSymlinks(p) return fs.bindResolve(from, to, flags, u)
}
const (
BindReadOnly = 1 << iota
BindCanCreate
)
func (fs *Filesystem) bindResolve(from string, to string, flags int, u *user.User) error {
if (to == "") || (from == to) {
return fs.bindSame(from, flags, u)
}
if isGlobbed(to) {
return fmt.Errorf("bind target (%s) cannot have globbed path", to)
}
t, err := resolveVars(to, u)
if err != nil {
return err
}
if isGlobbed(from) {
return fmt.Errorf("bind src (%s) cannot have globbed path with separate target path (%s)", from, to)
}
f, err := resolveVars(from, u)
if err != nil { if err != nil {
return fmt.Errorf("error resolving symlinks for path (%s): %v", p, err) return err
} }
sinfo, err := readSourceInfo(src, u) return fs.bind(f, t, flags, u)
}
func (fs *Filesystem) bindSame(p string, flags int, u *user.User) error {
ps, err := resolvePath(p, u)
if err != nil {
return err
}
for _, p := range ps {
if err := fs.bind(p, p, flags, u); err != nil {
return err
}
}
return nil
}
func (fs *Filesystem) bind(from string, to string, flags int, u *user.User) error {
src, err := filepath.EvalSymlinks(from)
if err != nil {
return fmt.Errorf("error resolving symlinks for path (%s): %v", from, err)
}
cc := flags&BindCanCreate != 0
sinfo, err := readSourceInfo(src, cc, u)
if err != nil { if err != nil {
return fmt.Errorf("failed to bind path (%s): %v", src, err) return fmt.Errorf("failed to bind path (%s): %v", src, err)
} }
target = path.Join(fs.Root(), target) if to == "" {
to = from
}
to = path.Join(fs.Root(), to)
_, err = os.Stat(target) _, err = os.Stat(to)
if err == nil || !os.IsNotExist(err) { if err == nil || !os.IsNotExist(err) {
fs.log.Warning("Target (%s > %s) already exists, ignoring", src, target) fs.log.Warning("Target (%s > %s) already exists, ignoring", src, to)
return nil return nil
} }
if sinfo.IsDir() { if sinfo.IsDir() {
if err := os.MkdirAll(target, sinfo.Mode().Perm()); err != nil { if err := os.MkdirAll(to, sinfo.Mode().Perm()); err != nil {
return err return err
} }
} else { } else {
if err := createEmptyFile(target, 0750); err != nil { if err := createEmptyFile(to, 0750); err != nil {
return err return err
} }
} }
@ -103,24 +150,24 @@ func (fs *Filesystem) BindOrCreate(p, target string, readonly bool, u *user.User
if err := copyPathPermissions(fs.Root(), src); err != nil { if err := copyPathPermissions(fs.Root(), src); err != nil {
return fmt.Errorf("failed to copy path permissions for (%s): %v", src, err) return fmt.Errorf("failed to copy path permissions for (%s): %v", src, err)
} }
fs.log.Info("bind mounting %s -> %s", src, target) fs.log.Info("bind mounting %s -> %s", src, to)
flags := syscall.MS_NOSUID | syscall.MS_NODEV mntflags := syscall.MS_NOSUID | syscall.MS_NODEV
if readonly { if flags&BindReadOnly != 0 {
flags |= syscall.MS_RDONLY mntflags |= syscall.MS_RDONLY
} else { } else {
flags |= syscall.MS_NOEXEC flags |= syscall.MS_NOEXEC
} }
return bindMount(src, target, flags) return bindMount(src, to, mntflags)
} }
func readSourceInfo(src string, u *user.User) (os.FileInfo, error) { func readSourceInfo(src string, cancreate bool, u *user.User) (os.FileInfo, error) {
if fi, err := os.Stat(src); err == nil { if fi, err := os.Stat(src); err == nil {
return fi, nil return fi, nil
} else if !os.IsNotExist(err) { } else if !os.IsNotExist(err) {
return nil, err return nil, err
} }
if u == nil { if u == nil || !cancreate {
return nil, fmt.Errorf("source path (%s) does not exist", src) return nil, fmt.Errorf("source path (%s) does not exist", src)
} }
@ -145,7 +192,20 @@ func readSourceInfo(src string, u *user.User) (os.FileInfo, error) {
return os.Stat(src) return os.Stat(src)
} }
func (fs *Filesystem) BlacklistPath(target string) error { func (fs *Filesystem) BlacklistPath(target string, u *user.User) error {
ps, err := resolvePath(target, u)
if err != nil {
return err
}
for _, p := range ps {
if err := fs.blacklist(p); err != nil {
return err
}
}
return nil
}
func (fs *Filesystem) blacklist(target string) error {
t, err := filepath.EvalSymlinks(target) t, err := filepath.EvalSymlinks(target)
if err != nil { if err != nil {
return fmt.Errorf("symlink evaluation failed while blacklisting path %s: %v", target, err) return fmt.Errorf("symlink evaluation failed while blacklisting path %s: %v", target, err)

@ -9,7 +9,7 @@ import (
"strings" "strings"
) )
func ResolvePath(p string, u *user.User) ([]string, error) { func resolvePath(p string, u *user.User) ([]string, error) {
p, err := resolveVars(p, u) p, err := resolveVars(p, u)
if err != nil { if err != nil {
return nil, err return nil, err
@ -52,8 +52,12 @@ func resolveVars(p string, u *user.User) (string, error) {
return p, nil return p, nil
} }
func isGlobbed(p string) bool {
return strings.Contains(p, "*")
}
func resolveGlob(p string) ([]string, error) { func resolveGlob(p string) ([]string, error) {
if !strings.Contains(p, "*") { if !isGlobbed(p) {
return []string{p}, nil return []string{p}, nil
} }
list, err := filepath.Glob(p) list, err := filepath.Glob(p)

@ -102,7 +102,7 @@ func setupRootfs(fsys *fs.Filesystem) error {
} }
for _, p := range basicBindDirs { for _, p := range basicBindDirs {
if err := fsys.BindPath(p, p, true); err != nil { if err := fsys.BindPath(p, fs.BindReadOnly, nil); err != nil {
return fmt.Errorf("failed to bind directory '%s': %v", p, err) return fmt.Errorf("failed to bind directory '%s': %v", p, err)
} }
} }
@ -135,15 +135,9 @@ func setupRootfs(fsys *fs.Filesystem) error {
} }
for _, bl := range basicBlacklist { for _, bl := range basicBlacklist {
ps, err := fs.ResolvePath(bl, nil) if err := fsys.BlacklistPath(bl, nil); err != nil {
if err != nil {
return err return err
} }
for _, p := range ps {
if err := fsys.BlacklistPath(p); err != nil {
return err
}
}
} }
return nil return nil
} }

@ -521,7 +521,7 @@ func (st *initState) setupFilesystem(extra []oz.WhitelistItem) error {
if err != nil { if err != nil {
return err return err
} }
if err := fs.BindPath(xprapath, xprapath, false); err != nil { if err := fs.BindPath(xprapath, 0, nil); err != nil {
return err return err
} }
} }
@ -546,16 +546,14 @@ func (st *initState) bindWhitelist(fsys *fs.Filesystem, wlist []oz.WhitelistItem
return nil return nil
} }
for _, wl := range wlist { for _, wl := range wlist {
paths, err := fs.ResolvePath(wl.Path, st.user) flags := fs.BindCanCreate
if err != nil { if wl.ReadOnly {
return err flags |= fs.BindReadOnly
} }
for _, p := range paths { if err := fsys.BindPath(wl.Path, flags, st.user); err != nil {
if err := fsys.BindOrCreate(p, p, wl.ReadOnly, st.user); err != nil {
return err return err
} }
} }
}
return nil return nil
} }
@ -564,15 +562,9 @@ func (st *initState) applyBlacklist(fsys *fs.Filesystem, blist []oz.BlacklistIte
return nil return nil
} }
for _, bl := range blist { for _, bl := range blist {
paths, err := fs.ResolvePath(bl.Path, st.user) if err := fsys.BlacklistPath(bl.Path, st.user); err != nil {
if err != nil {
return err return err
} }
for _, p := range paths {
if err := fsys.BlacklistPath(p); err != nil {
return err
}
}
} }
return nil return nil
} }

Loading…
Cancel
Save