Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Segmentation fault at readdir64 on CentOS 7 #31

Open
vikman90 opened this issue Aug 23, 2021 · 0 comments
Open

Segmentation fault at readdir64 on CentOS 7 #31

vikman90 opened this issue Aug 23, 2021 · 0 comments

Comments

@vikman90
Copy link

Hi, we've found an issue that happens during a scan of /proc on CentOS 7 (kernel 3.10.0-1160.36.2.el7.x86_64): the program sometimes crashes (wazuh/wazuh#9737) and sometimes falls into an infinite loop (wazuh/wazuh#9032), when Diamorphine (commit 8988105) is installed.

We've written this program to detect this problem:

testproc.c
#include <sys/types.h>
#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <stdbool.h>
#include <unistd.h>
#include <string.h>

volatile bool keepalive = false;

// List content of a directory
static void list_dir(const char * dirname, int depth) {
    char fname[PATH_MAX];
    struct dirent * entry;
    DIR * dir = opendir(dirname);

    if (dir == NULL) {
        return;
    }

    while ((entry = readdir(dir)) != NULL) {
        if (entry->d_name[0] == '.' && (entry->d_name[1] == '\0' || (entry->d_name[1] == '.' && entry->d_name[2] == '\0'))) {
            continue;
        }

        snprintf(fname, PATH_MAX, "%s/%s", dirname, entry->d_name);
        puts(fname);

        if (depth > 0) {
            list_dir(fname, depth - 1);
        }
    }

    closedir(dir);
    keepalive = true;
}

// Monitor keepalive with 1-second timeout
static void * monitor_main() {
    int delay = 0;

    while (true) {
        sleep(1);

        if (keepalive) {
            if (delay > 0) {
                fprintf(stderr, "INFO: Program is now responding.\n");
            }
            delay = 0;
            keepalive = false;
        } else {
            fprintf(stderr, "WARNING: Program is taking %d sec. to respond.\n", ++delay);
        }
    }

    return NULL;
}

// Launch monitor thread
static void run_monitor() {
    pthread_t thread;

    int r = pthread_create(&thread, NULL, (void *(*)(void *))monitor_main, NULL);

    if (r != 0) {
        fprintf(stderr, "ERROR: Cannot run thread: %s\n", strerror(r));
        exit(EXIT_FAILURE);
    }

    r = pthread_detach(thread);

    if (r != 0) {
        fprintf(stderr, "ERROR: Cannot detach thread: %s\n", strerror(r));
    }
}

int main(int argc, char ** argv) {
    run_monitor();

    while (true) {
        if (argc > 1) {
            int i;
            for (i = 1; i < argc; i++) {
                list_dir(argv[i], 1);
            }
        } else {
            list_dir("/proc", 1);
        }
    }

    return EXIT_SUCCESS;
}

How to reproduce

We've managed to reproduce this problem by scanning /proc and launching lots of ephemeral processes (/bin/echo). I think that the issue occurs when a directory (or its content) is removed while readdir() is getting it. However, I don't know if this happens only with /proc.

insmod diamorphine.ko
for i in {1..8}; do while true; do /bin/echo Hello > /dev/null; done & done

Catching the issue

gcc -g -pthread -o testproc testproc.c
./testproc > /dev/null

(... Few seconds after running the loops above ...)

WARNING: Program is taking 1 sec. to respond.
WARNING: Program is taking 2 sec. to respond.
WARNING: Program is taking 3 sec. to respond.
WARNING: Program is taking 4 sec. to respond.
(...)

Backtrace

#0  0x00007f8f83b9b334 in __getdents64 () from /lib64/libc.so.6
#1  0x00007f8f83b9af11 in readdir64 () from /lib64/libc.so.6
#2  0x00000000004009bb in list_dir (dirname=0x7ffe3a11ff10 "/proc/31244",
    depth=0) at testproc.c:22
#3  0x00000000004009af in list_dir (dirname=0x400c91 "/proc", depth=1)
    at testproc.c:31
#4  0x0000000000400b5b in main (argc=1, argv=0x7ffe3a121038)
    at testproc.c:88

Hope this helps find the cause of the bug.

Thank you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant