Merge pull request 'mesh-files: find writes the NUL itself, so a list or search through root runs at all (issue 1409)' (#668) from fix/1409-root-list-nul into main
This commit was merged in pull request #668.
This commit is contained in:
@@ -32,6 +32,12 @@ func (r *fakeRoot) Run(bin string, args ...string) ([]byte, error) {
|
|||||||
r.mu.Lock()
|
r.mu.Lock()
|
||||||
defer r.mu.Unlock()
|
defer r.mu.Unlock()
|
||||||
r.calls = append(r.calls, bin+" "+strings.Join(args, " "))
|
r.calls = append(r.calls, bin+" "+strings.Join(args, " "))
|
||||||
|
for _, a := range append([]string{bin}, args...) {
|
||||||
|
if strings.ContainsRune(a, 0) {
|
||||||
|
// The kernel refuses a program argument holding a NUL byte, as exec does on a node.
|
||||||
|
return nil, fmt.Errorf("fork/exec /usr/bin/sudo: invalid argument")
|
||||||
|
}
|
||||||
|
}
|
||||||
if e, ok := r.fail[bin+" "+strings.Join(args, " ")]; ok {
|
if e, ok := r.fail[bin+" "+strings.Join(args, " ")]; ok {
|
||||||
return nil, e
|
return nil, e
|
||||||
}
|
}
|
||||||
@@ -672,7 +678,7 @@ func TestTheReadsFallBackToRoot(t *testing.T) {
|
|||||||
t.Errorf("readlink through root: %+v %v", rl, err)
|
t.Errorf("readlink through root: %+v %v", rl, err)
|
||||||
}
|
}
|
||||||
// list
|
// list
|
||||||
g.root.out["/usr/bin/find -H "+in+" -mindepth 1 -maxdepth 1 -printf %y\t%U\t%G\t%m\t%s\t%l\t%f\x00"] =
|
g.root.out["/usr/bin/find -H "+in+" -mindepth 1 -maxdepth 1 -printf %y\t%U\t%G\t%m\t%s\t%l\t%f\\0"] =
|
||||||
"f\t1000\t998\t640\t2\t\tf\x00d\t1000\t1000\t755\t4096\t\tsub dir\x00l\t1000\t1000\t777\t1\tf\tl\x00"
|
"f\t1000\t998\t640\t2\t\tf\x00d\t1000\t1000\t755\t4096\t\tsub dir\x00l\t1000\t1000\t777\t1\tf\tl\x00"
|
||||||
ls, err := g.List(in)
|
ls, err := g.List(in)
|
||||||
if err != nil || ls.Count != 3 {
|
if err != nil || ls.Count != 3 {
|
||||||
@@ -689,7 +695,7 @@ func TestTheReadsFallBackToRoot(t *testing.T) {
|
|||||||
t.Errorf("entries: %+v", ls.Entries)
|
t.Errorf("entries: %+v", ls.Entries)
|
||||||
}
|
}
|
||||||
// search: the files are listed by find, the secret ones skipped by name, the rest read through cat
|
// search: the files are listed by find, the secret ones skipped by name, the rest read through cat
|
||||||
g.root.out["/usr/bin/find -H "+locked+" -maxdepth 5 -xdev -type f -printf %p\x00"] =
|
g.root.out["/usr/bin/find -H "+locked+" -maxdepth 5 -xdev -type f -printf %p\\0"] =
|
||||||
in + "/f\x00" + locked + "/.ssh/id_rsa\x00"
|
in + "/f\x00" + locked + "/.ssh/id_rsa\x00"
|
||||||
g.root.cat[in+"/f"] = "one\nneedle here\n"
|
g.root.cat[in+"/f"] = "one\nneedle here\n"
|
||||||
g.root.reach(in + "/f")
|
g.root.reach(in + "/f")
|
||||||
@@ -706,7 +712,7 @@ func TestTheReadsFallBackToRoot(t *testing.T) {
|
|||||||
// a secret place is listed, as root lists it, its entries marked and never their content (ADR 0394 §7); a path
|
// a secret place is listed, as root lists it, its entries marked and never their content (ADR 0394 §7); a path
|
||||||
// that is not there under a directory the account may not enter is said missing (design 39 parts §15)
|
// that is not there under a directory the account may not enter is said missing (design 39 parts §15)
|
||||||
secretDir := locked + "/.ssh"
|
secretDir := locked + "/.ssh"
|
||||||
g.root.out["/usr/bin/find -H "+secretDir+" -mindepth 1 -maxdepth 1 -printf %y\t%U\t%G\t%m\t%s\t%l\t%f\x00"] =
|
g.root.out["/usr/bin/find -H "+secretDir+" -mindepth 1 -maxdepth 1 -printf %y\t%U\t%G\t%m\t%s\t%l\t%f\\0"] =
|
||||||
"f\t1000\t1000\t600\t9\t\tid_rsa\x00"
|
"f\t1000\t1000\t600\t9\t\tid_rsa\x00"
|
||||||
if ls, err := g.List(secretDir); err != nil || ls.Secret == "" || len(ls.Entries) != 1 || ls.Entries[0].Name != "id_rsa" {
|
if ls, err := g.List(secretDir); err != nil || ls.Secret == "" || len(ls.Entries) != 1 || ls.Entries[0].Name != "id_rsa" {
|
||||||
t.Errorf("a secret place was not listed through root: %+v %v", ls, err)
|
t.Errorf("a secret place was not listed through root: %+v %v", ls, err)
|
||||||
|
|||||||
@@ -610,7 +610,7 @@ func (r Reader) finishList(path string, all []Entry, total int, secret string) L
|
|||||||
// a name cannot confuse it: the fields end with a NUL, and the name is the last.
|
// a name cannot confuse it: the fields end with a NUL, and the name is the last.
|
||||||
func (r Reader) listAsRoot(path string, names accounts) ([]Entry, error) {
|
func (r Reader) listAsRoot(path string, names accounts) ([]Entry, error) {
|
||||||
out, err := r.Root.Run("/usr/bin/find", "-H", path, "-mindepth", "1", "-maxdepth", "1", "-printf",
|
out, err := r.Root.Run("/usr/bin/find", "-H", path, "-mindepth", "1", "-maxdepth", "1", "-printf",
|
||||||
"%y\t%U\t%G\t%m\t%s\t%l\t%f\x00")
|
"%y\t%U\t%G\t%m\t%s\t%l\t%f\\0") // find writes the NUL: an argument may not hold one
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%s cannot be listed, not even through sudo: %v", path, err)
|
return nil, fmt.Errorf("%s cannot be listed, not even through sudo: %v", path, err)
|
||||||
}
|
}
|
||||||
@@ -967,7 +967,7 @@ func (r Reader) Search(ask SearchAsk) (SearchAnswer, error) {
|
|||||||
// and searches each: the names are judged first, so no credential file is read.
|
// and searches each: the names are judged first, so no credential file is read.
|
||||||
func (r Reader) searchBelowAsRoot(p string, depth int, needle string, fold bool, bound int, deadline time.Time, a *SearchAnswer) error {
|
func (r Reader) searchBelowAsRoot(p string, depth int, needle string, fold bool, bound int, deadline time.Time, a *SearchAnswer) error {
|
||||||
out, err := r.Root.Run("/usr/bin/find", "-H", p, "-maxdepth", strconv.Itoa(depth), "-xdev", "-type", "f",
|
out, err := r.Root.Run("/usr/bin/find", "-H", p, "-maxdepth", strconv.Itoa(depth), "-xdev", "-type", "f",
|
||||||
"-printf", "%p\x00")
|
"-printf", "%p\\0") // find writes the NUL: an argument may not hold one
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.Unreadable++
|
a.Unreadable++
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
Reference in New Issue
Block a user