$RodHat_/search
Console Tips

kcmp(2): comparing kernel objects across processes

Published by · Updated

This article may contain Amazon affiliate links. I may earn a commission if you buy through them. Disclosure.

Editorial card: kcmp(2): comparing kernel objects across processes
Editorial card: RodHat
On this page · 7 sections
  1. The interface
  2. What you can compare
  3. Access requirements
  4. Why not just read /proc
  5. Practical uses
  6. What it cannot do
  7. Availability

Thirty years ago I would have told you /proc was the answer to everything. Open /proc/<pid>/fdinfo/<fd>, read the pos: field, compare inode numbers from /proc/<pid>/fd/<fd> symlinks. Done. Except it is not done, because between the read in one process and the read in another, the first process can close and reopen that fd three times. You are comparing stale data against fresh data and calling it a fact.

kcmp(2) is the non-racy answer. It went into the kernel in Linux 3.5, designed specifically for CRIU (Checkpoint/Restore In Userspace). It has been sitting there since 2012 and most people writing tools that inspect processes do not know it exists.

The interface

#include <linux/kcmp.h>

int kcmp(pid_t pid1, pid_t pid2, int type, unsigned long idx1, unsigned long idx2);

The syscall has no glibc wrapper. Use syscall(SYS_kcmp, ...) directly.

pid1 and pid2 are the processes to compare. type says what to compare. idx1 and idx2 are type-specific indices, usually file descriptor numbers.

The return value works like strcmp: negative if idx1’s object sorts before idx2’s in kernel address order, zero if they are the same object, positive if after. That ordering is not useful in isolation; you care about zero. But the ordering exists for a real reason: CRIU needs to reconstruct sharing relationships between hundreds of file descriptors across a frozen process tree. If you can sort all the fd handles by their underlying object address, identical objects cluster together and you do a single pass instead of an O(n²) equality check for each pair. A clever design from people who needed it to work on production systems.

What you can compare

The type argument controls what the indices mean:

KCMP_FILE: idx1 and idx2 are file descriptor numbers in pid1 and pid2 respectively. Returns zero if they share the same open file description, meaning the same struct file in the kernel. Two fds point to the same open file description if one was duplicated from the other with dup(2), dup2(2), or passed over a Unix socket with SCM_RIGHTS. An independent open(2) of the same path produces two distinct file descriptions even if they refer to the same inode.

/* do pid1:fd3 and pid2:fd7 share the same open file description? */
int r = syscall(SYS_kcmp, pid1, pid2, KCMP_FILE, 3, 7);
/* r == 0: yes. r != 0: no, or an error. */

KCMP_VM: idx1 and idx2 are ignored. Returns zero if pid1 and pid2 share the same virtual memory space, that is, if one is a thread of the other or if they were created with CLONE_VM without subsequent exec.

KCMP_FS: zero if they share the same filesystem context (root, cwd, umask). Threads created with CLONE_FS share this; a forked process does not.

KCMP_FILES: zero if they share the same open file descriptor table entirely, not just one fd. Threads created with CLONE_FILES share the table.

KCMP_SIGHAND: zero if they share the same signal handler table, as threads created with CLONE_SIGHAND do.

KCMP_IO: zero if they share I/O context, the per-process accounting structure used by the block layer.

KCMP_SYSVSEM: zero if they share the same list of System V semaphore undo operations.

KCMP_EPOLL_TFD: idx1 is an epoll fd in pid1, idx2 is a target fd in pid2. Returns zero if idx2 is registered with the epoll instance idx1. This one is specifically for reconstructing epoll state during checkpoint.

Access requirements

You need ptrace access to both processes. In practice that means either:

  • You are the same user as both target processes and ptrace_scope is not locked down to 0 (no ptrace).
  • You have CAP_SYS_PTRACE.

If ptrace_scope is 1 (the Yama default on most Linux systems since about 2012), you can only ptrace a process you spawned, not an arbitrary peer process. Check /proc/sys/kernel/yama/ptrace_scope. Containers and checkpoint tools typically run with the necessary privilege; a random daemon does not.

Why not just read /proc

Besides the race condition, /proc gives you inode numbers. The same inode number in two different processes could mean they opened the same path but have independent file descriptions with independent offsets, locks, and O_CLOEXEC bits. Two fds that share a file description must track each other: a write through one advances the offset seen by the other. That is a fundamentally different relationship and /proc cannot tell you which you have without racy gymnastics.

KCMP_FILE returning zero is the only reliable answer to “is this fd the same kernel object across process boundaries.”

Practical uses

Container checkpoint and restore. CRIU freezes a running process tree, dumps its state to disk, and reconstructs it from scratch either on the same host or a different one. Part of that reconstruction is getting fd sharing exactly right: a thread that shares CLONE_FILES with another thread must end up sharing the same fd table after restore, not two independent copies. kcmp makes that determination without racing against a live process.

Debuggers and introspection tools. If you are building a tool that needs to understand the fd topology of a running service, kcmp with KCMP_FILE across all visible processes lets you build a precise sharing graph. Useful for leak detectors and for verifying that SCM_RIGHTS-passed fds are actually the same objects on both ends.

Runtime verification. If your IPC protocol depends on two cooperating processes sharing a specific file description (a pipe, a memfd, a socket pair), kcmp gives you a pre-flight check in tests without modifying either process.

What it cannot do

kcmp identifies kernel objects by their in-memory addresses, shuffled through a per-boot hash to avoid leaking kernel ASLR. The ordering is not stable across reboots or across exec. Do not serialize the non-zero return values; only the zero/non-zero result has meaning outside a single kernel instance.

It also does not tell you the type of the object, what it refers to, or whether it is still valid. You still need /proc for that; you just do not use /proc to answer the identity question.

Availability

Linux 3.5+, released July 2012. No FreeBSD equivalent: the jail and ptrace infrastructure gives you other ways in, but there is no kcmp. No macOS equivalent either.

The pidfd series covers the broader fd-as-stable-identity pattern: pidfd_open for process references, pidfd_getfd for fd theft across process boundaries, and SCM_RIGHTS for explicit fd passing over Unix sockets. If you are looking at this from the namespace angle, the namespaces and containers tip covers how processes end up sharing or not sharing the resources kcmp lets you compare.

Sources

  1. kcmp(2) Linux man page (man7.org)
  2. CRIU internals: how checkpoint/restore uses kcmp (CRIU Project)