Shares: allow any folder, not only ZFS datasets
build / build (push) Successful in 1m7s

SMB shares and NFS exports may now point to any existing directory
(USB disks under /mnt or /media, /srv, home folders...) instead of only
ZFS dataset mountpoints. System trees (/etc, /usr, /var, /boot, /proc,
/root, ...) are refused, also after resolving symlinks. The path
suggestions list mounted data filesystems from /proc/self/mounts in
addition to ZFS mountpoints.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-02 22:48:31 +03:00
co-authored by Claude Opus 5.5
parent 78215ac100
commit b331bc736d
10 changed files with 183 additions and 37 deletions
+18 -6
View File
@@ -54,8 +54,23 @@ func ValidateComment(s string) error {
return nil
}
// ValidatePath accepts an absolute, clean path without control characters.
// Whether it lies under a pool is checked by the caller (needs live state).
// systemRoots are OS trees that must never be shared.
var systemRoots = []string{"/etc", "/proc", "/sys", "/dev", "/boot", "/run", "/usr", "/bin", "/sbin",
"/lib", "/lib32", "/lib64", "/libx32", "/var", "/root", "/snap", "/lost+found"}
// ValidateNotSystem refuses the root filesystem and system directories.
func ValidateNotSystem(p string) error {
if p == "/" {
return errors.New("refusing to share the root filesystem")
}
if UnderRoots(p, systemRoots) {
return fmt.Errorf("%s is a system directory and cannot be shared", p)
}
return nil
}
// ValidatePath accepts an absolute, clean, non-system path without control
// characters. Existence and symlinks are checked by the caller.
func ValidatePath(p string) error {
if p == "" {
return errors.New("path is required")
@@ -63,10 +78,7 @@ func ValidatePath(p string) error {
if !strings.HasPrefix(p, "/") || path.Clean(p) != p || strings.ContainsAny(p, "\"\\\r\n\t") {
return errors.New("path must be absolute and normalised (no .., trailing / or quotes)")
}
if p == "/" {
return errors.New("refusing to share the root filesystem")
}
return nil
return ValidateNotSystem(p)
}
// UnderRoots reports whether p equals or lies below one of the roots.