Skip to content

overlayfs v18: readdir.c loses errors and can sync the wrong directory #179

Closed

Description

@openipc-ai

Follow-up from #177. These bugs come with the out-of-tree overlayfs v18 code, so they aren't specific to S3L. #177 deliberately imported the code unchanged rather than fork one copy.

Where

fs/overlayfs/readdir.c has the same blob (4c18abfa) on these kernel branches, plus their topic branches:

  • ambarella-s3l
  • ingenic-t23
  • ingenic-t31
  • ti-dm36x
  • xiongmai-xm530

The fix should go to all five, so the copies stay identical. Other branches carry a different readdir.c and haven't been compared, so they may or may not have the same bugs.

Line numbers are from ambarella-s3l at 0e5f7083d.

Bugs

1. ovl_dir_read() always returns 0 (readdir.c:188). The error collected in err is lost after fput(). A failed read or allocation leaves a partial list that callers treat as complete. ovl_check_empty_dir could then pass on a non-empty directory, and rmdir would write a whiteout that hides a lower directory persistently.

Likely fix: return err;.

2. ovl_dir_fsync() leaves an ERR_PTR in od->realfile (readdir.c:402). If ovl_path_open() fails, the error pointer stays in the field. The next fsync skips the reopen and uses it, and ovl_dir_release() passes it to fput().

Likely fix: open into a local variable and assign it only on success.

3. ovl_fill_upper() doesn't set rdd->err on allocation failure (readdir.c:166). It returns -ENOMEM directly, while ovl_fill_lower() records the error. With rdd->err still 0 and rdd->count at 1 or more, the do/while in ovl_dir_read() can retry at the same position for as long as the allocation keeps failing. This hasn't been traced through vfs_readdir, so please confirm it before fixing.

4. ovl_dir_fsync() can sync the lower directory (readdir.c:398). The upper directory is only opened when od->realfile is NULL, but that field can still hold the lower directory from ovl_dir_open(). If the directory is copied up while the descriptor stays open, fsync targets the lower file rather than the upper directory receiving the changes.

The fix needs more care than 1–3, because it must not disturb the descriptor's iteration state.

Status

Found by code reading (a review of #177 and Qodo's review on the same PR). None of this has been reproduced on a camera, and no fix has been built. Testing should cover rmdir and readdir on a merged directory, on at least one affected board.

Fixing 1 changes behaviour: readdir and rmdir start returning errors where they used to succeed on a partial list.

Not covered here

  • Non-atomic copy-up and removal (copy_up.c:192, dir.c:378). A power cut can leave a partial upper file or bring back a deleted one. That's a v18 design limit, and fixing it means a much larger backport of the later overlayfs design.
  • remount,ro on the upper mount. Overlayfs holds mnt_want_write on it (super.c:608), which affects quiesce_overlay in firmware's sysupgrade. It's being tested separately, as asked on ambarella: s3l: add overlayfs (v18), as on the T31 kernel #177.
  • Lower-priority findings from Qodo's review on ambarella: s3l: add overlayfs (v18), as on the T31 kernel #177: whiteout failure after a rename, ovl_link ownership and failed-link cleanup, xattr handling in copy-up, and a leak on failed mount-option parsing. These haven't been verified.

Activity

  1. openipc-ai commented on Nov 7, 2026

    @openipc-ai
    Author

    The fix is up as one PR per branch, with the same commit on each:

    Branch PR Tested
    ambarella-s3l #180 QEMU before and after
    ingenic-t31 #181 QEMU before and after
    ingenic-t23 #182 QEMU before and after
    ti-dm36x #183 Compile only, with a non-board toolchain
    xiongmai-xm530 #184 QEMU before and after, -smp 2

    All four bugs reproduced before the fix on the four branches that booted, with failures forced by test-only knobs. That includes the oops from bug 2, so bug 3 is confirmed rather than only read from the code. None of this has run on a camera.

    This issue should stay open until all five are merged.

    One related bug isn't covered: fsync on a directory that is still lower-only returns EINVAL on squashfs, before and after the fix.

  2. openipc-ai commented on Nov 7, 2026

    @openipc-ai
    Author

    Fixed on all five branches: ambarella-s3l (#180), ingenic-t31 (#181), ingenic-t23 (#182), ti-dm36x (#183) and xiongmai-xm530 (#184). Their readdir.c is still identical.

    Cause: ovl_dir_read() dropped the error it collected, ovl_fill_upper() never recorded its own, and ovl_dir_fsync() used one field both for readdir's file and for the upper directory it opened itself.

    Fix: the errors now reach the caller, and fsync has its own upperfile, as in the later overlayfs on hisilicon-hi3516ev200.

    Evidence: on S3L, XM530 (-smp 2), T31 and T23 in QEMU, with failures forced by test-only knobs, all four bugs reproduced before the fix, including the oops, and none after. The output is in each PR.

    Gaps:

    • None of this has run on a camera, and ti-dm36x was only compiled, using a non-board toolchain.
    • readdir and rmdir now return errors where they used to succeed on a partial list. Anything that shows up on a camera after a kernel rebuild should be checked against this first.
    • fsync on a directory that is still lower-only returns EINVAL on squashfs, as it did before.

    Qodo's race finding on #181, not changed: a copy-up that finishes while fsync is running can leave fsync on the lower file. fsync only has to cover changes finished before it started, and the later overlayfs makes the same unlocked check.

    The items under "Not covered here" in the description are still open and aren't tracked by this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions