22.1 — Core Dump Files

 

22.1 — Core Dump Files
What they are, when they are created, and how Linux controls their naming

What is a Core Dump?

When a signal causes a process to crash, the Linux kernel can save a snapshot of the entire process memory to a file on disk. This file is called a core dump (or core file). A debugger like gdb can later load this file and show you exactly what the program was doing at the moment it crashed — which variables had which values, where in the code it was, what the call stack looked like.

The word core comes from old magnetic core memory technology used in early computers. The name stuck even though modern machines use RAM.

A core dump is your most powerful debugging tool when a program crashes in production where you cannot attach a debugger directly.

Which Signals Cause a Core Dump?

Not all signals create a core dump. Only specific signals do so — they are listed in Table 20-1 of TLPI. Common ones you will see in practice:

Signals That Terminate With Core Dump
Signal Default Action Typical Cause
SIGQUIT Core dump + terminate User types Ctrl+\ in terminal
SIGABRT Core dump + terminate abort() called in program
SIGSEGV Core dump + terminate Invalid memory access (null pointer, buffer overflow)
SIGBUS Core dump + terminate Bus error (misaligned memory access)
SIGFPE Core dump + terminate Floating point / integer divide-by-zero
SIGILL Core dump + terminate Illegal CPU instruction executed
Key point: If the signal disposition is changed (e.g. you install a handler), a core dump is NOT produced — the handler runs instead.

Trying It Out: Generating a Core Dump

By default, most Linux distributions set the core dump size limit to 0 (disabled). You must first enable it with ulimit.

## Step 1: Check current core dump size limit
$ ulimit -c
0                   <-- 0 means core dumps are DISABLED

## Step 2: Enable unlimited core dumps (in current shell only)
$ ulimit -c unlimited

## Step 3: Run a program and force it to crash with SIGQUIT
$ sleep 30
## Press Ctrl+\ 
Quit (core dumped)

## Step 4: Inspect the core file created
$ ls -lh core
-rw------- 1 ravi ravi 252K Jun 1 10:00 core

## Step 5: Load into gdb to analyse
$ gdb /bin/sleep core
(gdb) bt        <-- show backtrace (call stack at crash time)
Note: ulimit -c unlimited only applies to the current shell session. To make it permanent, add it to your ~/.bashrc or /etc/security/limits.conf.

Example 1: Program That Forces a Core Dump

The simplest way to force a core dump from inside your program is to call abort() or raise SIGABRT. This is useful for assertion failures or unrecoverable errors.

/* core_demo.c - Demonstrates core dump with abort() */
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

void check_value(int x) {
    if (x < 0) {
        fprintf(stderr, "Fatal: negative value %d, dumping core\n", x);
        abort();   /* sends SIGABRT, causes core dump */
    }
}

int main(void) {
    int arr[5] = {10, 20, -5, 40, 50};
    for (int i = 0; i < 5; i++) {
        printf("Checking arr[%d] = %d\n", i, arr[i]);
        check_value(arr[i]);
    }
    return 0;
}
## Build and run
$ gcc -g core_demo.c -o core_demo   # -g adds debug symbols
$ ulimit -c unlimited
$ ./core_demo
Checking arr[0] = 10
Checking arr[1] = 20
Checking arr[2] = -5
Fatal: negative value -5, dumping core
Aborted (core dumped)

## Debug the crash
$ gdb ./core_demo core
(gdb) bt
#0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
#1  __GI_abort () at abort.c:79
#2  check_value (x=-5) at core_demo.c:8
#3  main () at core_demo.c:16

GDB shows exactly which function called abort and the full call stack. This is invaluable in production debugging.

Example 2: SIGSEGV Core Dump (Null Pointer)

/* sigsegv_demo.c - Classic null pointer dereference */
#include <stdio.h>

int main(void) {
    int *ptr = NULL;

    printf("About to dereference a null pointer...\n");
    *ptr = 42;   /* This causes SIGSEGV */
    printf("This line is never reached\n");

    return 0;
}
$ gcc -g sigsegv_demo.c -o sigsegv_demo
$ ulimit -c unlimited
$ ./sigsegv_demo
About to dereference a null pointer...
Segmentation fault (core dumped)

$ gdb ./sigsegv_demo core
(gdb) bt
#0  main () at sigsegv_demo.c:7
(gdb) info locals
ptr = 0x0             <-- gdb shows ptr is NULL

Example 3: Programmatic Core Dump with prctl()

For set-user-ID programs, core dumps are suppressed by default for security reasons. The prctl() system call with PR_SET_DUMPABLE can re-enable it.

/* prctl_dumpable.c - Re-enable core dumps for set-uid process */
#include <stdio.h>
#include <stdlib.h>
#include <sys/prctl.h>

int main(void) {
    /* Check current dumpable flag */
    int dumpable = prctl(PR_GET_DUMPABLE);
    printf("Current dumpable flag: %d\n", dumpable);

    /* Set dumpable = 1 so core dump is produced even if
       this is a set-uid program running as another user */
    if (prctl(PR_SET_DUMPABLE, 1) == -1) {
        perror("prctl PR_SET_DUMPABLE");
        exit(EXIT_FAILURE);
    }

    printf("Dumpable flag set to 1\n");

    /* Now trigger a crash — core will be produced */
    raise(SIGQUIT);

    return 0;
}
$ gcc -g prctl_dumpable.c -o prctl_dumpable
$ ulimit -c unlimited
$ ./prctl_dumpable
Current dumpable flag: 1
Dumpable flag set to 1
Quit (core dumped)

When is a Core Dump NOT Produced?

Even when a crash-inducing signal is received, the kernel will skip the core dump under several conditions:

Conditions That Suppress Core Dump
Condition Reason
Process has no write permission in the directory Cannot create the file
A non-writable file named “core” already exists Cannot overwrite
RLIMIT_CORE resource limit is 0 Kernel enforces the limit
RLIMIT_FSIZE resource limit is 0 File size limit hit
Set-user-ID program run by non-owner Security: prevents password extraction from memory
Binary has no read permission Prevents indirect read of protected binary
Filesystem full or out of inodes Disk I/O failure
File has more than one hard link Would overwrite linked file

Controlling Core Dump File Naming

The file /proc/sys/kernel/core_pattern controls the name (and location) of core dump files. By default it contains the string core.

## Check current pattern
$ cat /proc/sys/kernel/core_pattern
core

## Set a richer naming pattern (needs root)
$ echo "core.%e.%p.%t" | sudo tee /proc/sys/kernel/core_pattern

## Now after a crash, the file will be named like:
## core.sleep.12345.1685000000
core_pattern Format Specifiers
Specifier Replaced With
%e Executable filename (without path)
%p Process ID (PID) of the crashed process
%t Time of crash (seconds since Epoch)
%u Real user ID of the process
%g Real group ID of the process
%s Signal number that caused the crash
%h Hostname of the machine
%c Core file size soft resource limit (bytes)
%% A literal % character
## Redirect core dumps to a specific directory
$ echo "/var/cores/core.%e.%p" | sudo tee /proc/sys/kernel/core_pattern
## Make sure the directory exists and is writable:
$ sudo mkdir -p /var/cores
$ sudo chmod 1777 /var/cores

## Pipe core dump to a program (kernel 2.6.19+)
## This sends the core to a crash handler program's stdin
$ echo "|/usr/lib/systemd/systemd-coredump %P %u %g %s %t %c %e" \
    | sudo tee /proc/sys/kernel/core_pattern
systemd-coredump: On modern Ubuntu/Fedora systems, core dumps are managed by systemd-coredump by default. Use coredumpctl list to view them and coredumpctl gdb to debug.

Controlling Which Memory Regions Are Dumped

Since kernel 2.6.23, each process has a /proc/PID/coredump_filter file that is a bitmask controlling which memory mappings go into the core dump.

## Check the filter for a running process
$ cat /proc/$$/coredump_filter
00000033

## The bits mean:
## Bit 0 (0x01) - private anonymous mappings (stack, heap) -- usually WANT this
## Bit 1 (0x02) - private file-backed mappings
## Bit 2 (0x04) - shared anonymous mappings (shared memory)
## Bit 3 (0x08) - shared file-backed mappings (mmap'd files)
## Default 0x33 = bits 0,1,4,5 -- dumps anonymous + ELF headers

## Dump EVERYTHING (useful for full diagnosis)
$ echo 0xff > /proc/$$/coredump_filter
/* Set coredump_filter from within a C program */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int set_coredump_filter(unsigned int filter) {
    char path[64];
    FILE *f;

    snprintf(path, sizeof(path), "/proc/%d/coredump_filter", getpid());
    f = fopen(path, "w");
    if (f == NULL) return -1;

    fprintf(f, "%x", filter);
    fclose(f);
    return 0;
}

int main(void) {
    /* Include all anonymous + file-backed mappings */
    set_coredump_filter(0x3f);
    printf("Core dump filter set. PID=%d\n", getpid());
    abort();  /* trigger core dump */
    return 0;
}

Interview Questions — Core Dump Files

Q1. What is a core dump file and why is it useful?
Answer:

A core dump is a snapshot of a process’s memory (stack, heap, registers, open file info) saved to disk at the moment a fatal signal is received. It is useful because you can load it into gdb later — even after the process is gone — and inspect variables, the call stack, and the program state at the time of crash. This is essential for debugging crashes in production environments where you cannot attach a debugger live.

Q2. My program crashes but no core file is created. What do you check first?
Answer:

The first thing to check is the core dump size limit: ulimit -c. If it shows 0, core dumps are disabled. Run ulimit -c unlimited to enable. Other reasons: the working directory is not writable, the filesystem is full, the process is set-user-ID, or RLIMIT_CORE is set to 0 in /etc/security/limits.conf.

Q3. What is /proc/sys/kernel/core_pattern? Give an example of using it.
Answer:

It is a Linux-specific file that controls the filename and location of core dump files. It supports format specifiers: %e (executable name), %p (PID), %t (timestamp). Example: setting it to /var/cores/core.%e.%p.%t saves all core files to /var/cores/ with descriptive names. Since kernel 2.6.19 it can start with | to pipe core data to a program like systemd-coredump.

Q4. Why does a set-user-ID program not generate core dumps by default?
Answer:

Security. A set-user-ID program runs with elevated privileges and may have sensitive data (passwords, private keys) in memory. If a malicious user could trigger a crash and read the core file, they could extract that sensitive data. The kernel suppresses core dumps for such programs by default. The prctl(PR_SET_DUMPABLE, 1) call can override this when required for debugging.

Q5. How do you use gdb to analyse a core dump?
Answer:

Run gdb ./program_binary core_file. Once inside gdb, use bt (backtrace) to see the call stack, info locals to see local variable values, print varname to inspect specific variables, and frame N to switch between stack frames. The binary must have been compiled with -g flag for meaningful symbol information.

Q6. What does /proc/PID/coredump_filter control?
Answer:

It is a per-process bitmask (available since kernel 2.6.23) that controls which types of memory mappings are included in the core dump. Bit 0 covers private anonymous mappings (stack, heap), bit 1 covers private file-backed mappings, bits 2-3 cover shared mappings. The default value (0x33) dumps anonymous mappings which is usually sufficient. Setting it to 0xff includes everything.

Next Topic

Learn about special signal delivery rules for SIGKILL, SIGSTOP, and SIGCONT.

22.2 — Special Cases → ← Back to Index

Leave a Reply

Your email address will not be published. Required fields are marked *