A machine with millions of files never finished the walk within fifteen minutes, so its agent account was never judged and the router refused to link. Only root can make a setuid-root file, so a complete search stays sound until root acts: it now runs at idle priority with no bound, is kept beside the engine's state, judges for rootsearch.FreshFor from its start, runs again daily and after an apply that moves accounts, packages, actions or sudo rules, and an incomplete or stale search is never free.
47 lines
1.6 KiB
Go
47 lines
1.6 KiB
Go
package apply
|
|
|
|
import (
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/novox/mesh-host/internal/declaration"
|
|
)
|
|
|
|
// rootPaths are the files and directories through which an account comes to root, or by which it is told who it
|
|
// is: the user and group databases, sudo's, doas's and polkit's rules. A file written there changes what the
|
|
// judge of an agent account reads (novox/hq ADR 0266).
|
|
var rootPaths = []string{"/etc/passwd", "/etc/shadow", "/etc/group", "/etc/gshadow", "/etc/sudoers",
|
|
"/etc/sudoers.d", "/etc/doas.conf", "/etc/doas.d", "/etc/polkit-1", "/usr/share/polkit-1"}
|
|
|
|
// MovesRoot says an apply changed something through which root's reach could have changed — an account, a
|
|
// package, an action run as root, or a file in rootPaths (novox/hq issue 361). The engine then asks for a new
|
|
// search for setuid programs: root acted, and a complete search is sound only until root acts. Outcomes that
|
|
// moved nothing (unchanged, held, waiting, held still) do not count.
|
|
func MovesRoot(outcomes []Outcome) bool {
|
|
for _, o := range outcomes {
|
|
switch o.Action {
|
|
case "unchanged", "held", "waiting", heldStill:
|
|
continue
|
|
}
|
|
switch declaration.Type(o.Type) {
|
|
case declaration.TypeUser, declaration.TypePackage, declaration.TypeAction:
|
|
return true
|
|
case declaration.TypeFile, declaration.TypeDirectory, declaration.TypeArchive:
|
|
if underRootPath(o.Target) {
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func underRootPath(target string) bool {
|
|
t := filepath.Clean(target)
|
|
for _, p := range rootPaths {
|
|
if t == p || strings.HasPrefix(t, p+"/") {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|