erofs: fix wrong assumption on the order of on-disk directory entries

For each directory, _all_ the on-disk directory entries are _strictly_
recorded in alphabetical order. There is no special treatment of "." and
"..". Thanks to @hsiangkao for pointing out this bug.

Fixes: eca83ac68c ("Add initial support for EROFS")
Reported-by: Gao Xiang <xiang@kernel.org>
Signed-off-by: Tiwei Bie <tiwei.btw@antgroup.com>
This commit is contained in:
Tiwei Bie
2023-10-07 21:15:16 +08:00
parent addac5f248
commit 15e4366487
3 changed files with 12 additions and 6 deletions
+2 -3
View File
@@ -586,8 +586,7 @@ func (i *Inode) blocks() uint64 {
}
// IterDirents invokes cb on each entry in the directory represented by this inode.
// The first two directory entries are "." and "..". The remaining directory entries
// will be iterated in alphabetical order.
// The directory entries will be iterated in alphabetical order.
//
// https://docs.kernel.org/filesystems/erofs.html#directories
//
@@ -615,7 +614,7 @@ func (i *Inode) blocks() uint64 {
//
// [ (metadata block) inode | optional fields | dirent M+2 | dirent M+3 | name M+2 | name M+3 | optional padding ]
//
// All directory entries (except the first two: "." and "..") are _strictly_ recorded in alphabetical order.
// All directory entries are _strictly_ recorded in alphabetical order.
func (i *Inode) IterDirents(cb func(name string, typ uint8, nid uint64) error) error {
if !i.IsDir() {
return linuxerr.ENOTDIR
-3
View File
@@ -69,9 +69,6 @@ func (i *inode) lookup(name string) (uint64, error) {
return 0, err
}
// Skip "." and ".."
dirents = dirents[2:]
// The dirents are sorted in alphabetical order. We do binary search
// to find the target.
idx := sort.Search(len(dirents), func(i int) bool {
+10
View File
@@ -20,6 +20,7 @@ import (
"io"
"io/ioutil"
"math"
"math/rand"
"os"
"os/exec"
"path"
@@ -3158,6 +3159,15 @@ func TestMountEROFS(t *testing.T) {
if err := os.Mkdir(sourceDir, 0755); err != nil {
t.Fatalf("os.Mkdir() failed: %v", err)
}
// Create some files with leading non-alphanumeric characters in name. It's helpful
// to verify the on-disk directory entries order.
for _, c := range []byte("!#$%&()*+,-:;<=>?@[]^_`{|}~") {
name := fmt.Sprintf("%s/%c_file", sourceDir, c)
// Create the file with random data.
if err := ioutil.WriteFile(name, []byte(fmt.Sprintf("%v", rand.Uint64())), 0644); err != nil {
t.Fatalf("error creating %q: %v", name, err)
}
}
testApp, err := testutil.FindFile("test/cmd/test_app/test_app")
if err != nil {
t.Fatalf("error finding test_app: %v", err)