An account could replace ~/.claude with a link to /etc and have the node-engine chown, chmod or write through it on the next apply. Below a person's or an agent's home every component is now opened without following a link, and a link refuses the resource in words. The root judge also reads doas and polkit rules, the container runtimes' sockets with their ACLs, ACLs on the secrets, and setuid-root programs no package owns, in the C locale; Judged and NotJudged write down exactly what it covers (hq ADR 0266 review).
54 lines
1.3 KiB
Go
54 lines
1.3 KiB
Go
//go:build !linux
|
|
|
|
package apply
|
|
|
|
// Where there is no openat with O_NOFOLLOW to rely on, the check before use is all: a link below a home is
|
|
// refused, and the call is made by path. The node-engine runs on Linux; this keeps the package building.
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
)
|
|
|
|
func chmodUnder(home, path string, mode os.FileMode) error {
|
|
if err := refuseLinksUnderHome(path); err != nil {
|
|
return err
|
|
}
|
|
return os.Chmod(path, mode)
|
|
}
|
|
|
|
func chownUnder(home, path string, uid, gid int) error {
|
|
if err := refuseLinksUnderHome(path); err != nil {
|
|
return err
|
|
}
|
|
return os.Lchown(path, uid, gid)
|
|
}
|
|
|
|
func readUnder(home, path string) ([]byte, error) {
|
|
if err := refuseLinksUnderHome(path); err != nil {
|
|
return nil, err
|
|
}
|
|
return os.ReadFile(path)
|
|
}
|
|
|
|
func mkdirAllUnder(home, dir string, mode os.FileMode) ([]string, error) {
|
|
if err := refuseLinksUnderHome(dir); err != nil {
|
|
return nil, err
|
|
}
|
|
var made []string
|
|
for d := filepath.Clean(dir); d != home; d = filepath.Dir(d) {
|
|
if _, err := os.Lstat(d); err == nil {
|
|
break
|
|
}
|
|
made = append(made, d)
|
|
}
|
|
return made, os.MkdirAll(dir, mode)
|
|
}
|
|
|
|
func writeUnder(home, path string, content []byte, mode os.FileMode) error {
|
|
if err := refuseLinksUnderHome(path); err != nil {
|
|
return err
|
|
}
|
|
return writeAtomicallyByPath(path, content, mode)
|
|
}
|