phoenix-rtos / phoenix-rtos/phoenix-rtos-project

readdir() returns . after rmdir() and rewinddir() [on arm targets]

Open
#1,663 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug libphoenix POSIX
Dominant language
C
Stars
66
Forks
49
Avg merge
20h 25m
Merged PRs (30d)
12

Description

Description

Calling rmdir() on an open directory successfully unlinks it (returns 0). However, after calling rewinddir() to reset the directory stream, a subsequent readdir() call returns the . entry.

POSIX specifies that rmdir() must immediately remove the . and .. entries before the function returns, even if a process still holds an open file descriptor to the directory.

Expected Behavior

  • mkdir() and opendir() successfully create and open the directory.
  • rmdir() succeeds (returns 0) while the directory is held open.
  • rewinddir() resets the directory stream to the beginning.
  • A subsequent readdir() returns NULL (indicating the . and .. entries were removed).

Actual Behavior

  • mkdir() and opendir() successfully create and open the directory.
  • rmdir() succeeds (returns 0).
  • rewinddir() resets the directory stream.
  • A subsequent readdir() returns a valid directory entry for ., indicating the standard entries were not removed upon unlinking.

POSIX Requirement

  • "If one or more processes have the directory open when the last link is removed, the dot and dot-dot entries, if present, shall be removed before rmdir() returns and no new entries may be created in the directory, but the directory shall not be removed until all references to the directory are closed." — POSIX.1-2017 (IEEE Std 1003.1), rmdir() specification.

Minimal Reproduction (confirmed on target)

#include <stdio.h>
#include <dirent.h>
#include <sys/stat.h>
#include <unistd.h>

int main(void)
{
    const char *dir_name = "ghostdir_repro";
    DIR *dp;
    struct dirent *entry;

    if (mkdir(dir_name, 0700) != 0) {
        perror("mkdir failed");
        return 1;
    }

    dp = opendir(dir_name);
    if (dp == NULL) {
        perror("opendir failed");
        rmdir(dir_name);
        return 1;
    }

    if (rmdir(dir_name) != 0) {
        perror("rmdir failed");
        closedir(dp);
        return 1;
    }

    /* Drain the stream until we hit End-Of-File */
    while (readdir(dp) != NULL) {}

    /* Rewind to the beginning of the now-deleted directory */
    rewinddir(dp);

    entry = readdir(dp);
    if (entry == NULL) {
        printf("PASS: readdir() returned NULL. Filesystem is POSIX compliant.\n");
    } else {
        printf("FAIL: FS BUG TRIGGERED! Expected NULL, but read: '%s'\n", entry->d_name);
    }

    closedir(dp);
    return 0;
}

Output on aarch64a53-zynqmp-qemu

FAIL: FS BUG TRIGGERED! Expected NULL, but read: '.'

Output on ia32-generic-qemu

PASS: readdir() returned NULL. Filesystem is POSIX compliant.

Revision

62b46f93f586ebbadf352b1d35eb3ae580543ac0

Affected targets

Reproduced on aarch64a53-zynqmp-qemu but also affects:

  • armv7a9-zynq7000-qemu,
  • armv7r5f-zynqmp-qemu,
  • armv7a7-imx6ull-evk,
  • armv7m7-imxrt106x-evk,
  • armv7m7-imxrt117x-evk,
  • armv7a9-zynq7000-zedboard,
  • armv7m4-stm32l4x6-nucleo

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by running the minimal C reproduction on an affected ARM target and compare it with ia32-generic-qemu. Then trace the filesystem implementations of rmdir(), rewinddir(), and readdir() to determine why '.' remains after unlinking an open directory. Done means the reproduction returns NULL after rewinddir() on the listed affected targets without regressing the passing target.

Written by the indexing model from the issue text.

Assessment

Tech stack
c
Domain
operating-systems
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.