mirror of https://github.com/mkerrisk/man-pages
351 lines
8.2 KiB
Groff
351 lines
8.2 KiB
Groff
.\" Copyright (C) 2012, Cyrill Gorcunov <gorcunov@openvz.org>
|
|
.\" and Copyright (C) 2012, 2016, Michael Kerrisk <mtk.manpages@gmail.com>
|
|
.\"
|
|
.\" %%%LICENSE_START(VERBATIM)
|
|
.\" Permission is granted to make and distribute verbatim copies of this
|
|
.\" manual provided the copyright notice and this permission notice are
|
|
.\" preserved on all copies.
|
|
.\"
|
|
.\" Permission is granted to copy and distribute modified versions of
|
|
.\" this manual under the conditions for verbatim copying, provided that
|
|
.\" the entire resulting derived work is distributed under the terms of
|
|
.\" a permission notice identical to this one.
|
|
.\"
|
|
.\" Since the Linux kernel and libraries are constantly changing, this
|
|
.\" manual page may be incorrect or out-of-date. The author(s) assume
|
|
.\" no responsibility for errors or omissions, or for damages resulting
|
|
.\" from the use of the information contained herein. The author(s) may
|
|
.\" not have taken the same level of care in the production of this
|
|
.\" manual, which is licensed free of charge, as they might when working
|
|
.\" professionally.
|
|
.\"
|
|
.\" Formatted or processed versions of this manual, if unaccompanied by
|
|
.\" the source, must acknowledge the copyright and authors of this work.
|
|
.\" %%%LICENSE_END
|
|
.\"
|
|
.\" Kernel commit d97b46a64674a267bc41c9e16132ee2a98c3347d
|
|
.\"
|
|
.TH KCMP 2 2016-07-17 "Linux" "Linux Programmer's Manual"
|
|
.SH NAME
|
|
kcmp \- compare two processes to determine if they share a kernel resource
|
|
.SH SYNOPSIS
|
|
.nf
|
|
.B #include <linux/kcmp.h>
|
|
|
|
.BI "int kcmp(pid_t " pid1 ", pid_t " pid2 ", int " type ,
|
|
.BI " unsigned long " idx1 ", unsigned long " idx2 );
|
|
.fi
|
|
|
|
.IR Note :
|
|
There is no glibc wrapper for this system call; see NOTES.
|
|
.SH DESCRIPTION
|
|
The
|
|
.BR kcmp ()
|
|
system call can be used to check whether the two processes identified by
|
|
.I pid1
|
|
and
|
|
.I pid2
|
|
share a kernel resource such as virtual memory, file descriptors,
|
|
and so on.
|
|
|
|
Permission to employ
|
|
.BR kcmp ()
|
|
is governed by ptrace access mode
|
|
.B PTRACE_MODE_READ_REALCREDS
|
|
checks against both
|
|
.I pid1
|
|
and
|
|
.IR pid2 ;
|
|
see
|
|
.BR ptrace (2).
|
|
|
|
The
|
|
.I type
|
|
argument specifies which resource is to be compared in the two processes.
|
|
It has one of the following values:
|
|
.TP
|
|
.BR KCMP_FILE
|
|
Check whether a file descriptor
|
|
.I idx1
|
|
in the process
|
|
.I pid1
|
|
refers to the same open file description (see
|
|
.BR open (2))
|
|
as file descriptor
|
|
.I idx2
|
|
in the process
|
|
.IR pid2 .
|
|
.TP
|
|
.BR KCMP_FILES
|
|
Check whether the process share the same set of open file descriptors.
|
|
The arguments
|
|
.I idx1
|
|
and
|
|
.I idx2
|
|
are ignored.
|
|
.TP
|
|
.BR KCMP_FS
|
|
Check whether the processes share the same filesystem information
|
|
(i.e., file mode creation mask, working directory, and filesystem root).
|
|
The arguments
|
|
.I idx1
|
|
and
|
|
.I idx2
|
|
are ignored.
|
|
.TP
|
|
.BR KCMP_IO
|
|
Check whether the processes share I/O context.
|
|
The arguments
|
|
.I idx1
|
|
and
|
|
.I idx2
|
|
are ignored.
|
|
.TP
|
|
.BR KCMP_SIGHAND
|
|
Check whether the processes share the same table of signal dispositions.
|
|
The arguments
|
|
.I idx1
|
|
and
|
|
.I idx2
|
|
are ignored.
|
|
.TP
|
|
.BR KCMP_SYSVSEM
|
|
Check whether the processes share the same
|
|
list of System\ V semaphore undo operations.
|
|
The arguments
|
|
.I idx1
|
|
and
|
|
.I idx2
|
|
are ignored.
|
|
.TP
|
|
.BR KCMP_VM
|
|
Check whether the processes share the same address space.
|
|
The arguments
|
|
.I idx1
|
|
and
|
|
.I idx2
|
|
are ignored.
|
|
.PP
|
|
Note the
|
|
.BR kcmp ()
|
|
is not protected against false positives which may occur if
|
|
the processes are currently running.
|
|
One should stop the processes by sending
|
|
.BR SIGSTOP
|
|
(see
|
|
.BR signal (7))
|
|
prior to inspection with this system call to obtain meaningful results.
|
|
.SH RETURN VALUE
|
|
The return value of a successful call to
|
|
.BR kcmp ()
|
|
is simply the result of arithmetic comparison
|
|
of kernel pointers (when the kernel compares resources, it uses their
|
|
memory addresses).
|
|
|
|
The easiest way to explain is to consider an example.
|
|
Suppose that
|
|
.I v1
|
|
and
|
|
.I v2
|
|
are the addresses of appropriate resources, then the return value
|
|
is one of the following:
|
|
.RS 4
|
|
.IP 0 4
|
|
.I v1
|
|
is equal to
|
|
.IR v2 ;
|
|
in other words, the two processes share the resource.
|
|
.IP 1
|
|
.I v1
|
|
is less than
|
|
.IR v2 .
|
|
.IP 2
|
|
.I v1
|
|
is greater than
|
|
.IR v2 .
|
|
.IP 3
|
|
.I v1
|
|
is not equal to
|
|
.IR v2 ,
|
|
but ordering information is unavailable.
|
|
.RE
|
|
.PP
|
|
On error, \-1 is returned, and
|
|
.I errno
|
|
is set appropriately.
|
|
|
|
.BR kcmp ()
|
|
was designed to return values suitable for sorting.
|
|
This is particularly handy if one needs to compare
|
|
a large number of file descriptors.
|
|
.SH ERRORS
|
|
.TP
|
|
.B EBADF
|
|
.I type
|
|
is
|
|
.B KCMP_FILE
|
|
and
|
|
.I fd1
|
|
or
|
|
.I fd2
|
|
is not an open file descriptor.
|
|
.TP
|
|
.B EINVAL
|
|
.I type
|
|
is invalid.
|
|
.TP
|
|
.B EPERM
|
|
Insufficient permission to inspect process resources.
|
|
The
|
|
.B CAP_SYS_PTRACE
|
|
capability is required to inspect processes that you do not own.
|
|
Other ptrace limitations may also apply, such as
|
|
.BR CONFIG_SECURITY_YAMA ,
|
|
which, when
|
|
.I /proc/sys/kernel/yama/ptrace_scope
|
|
is 2, limits
|
|
.BR kcmp ()
|
|
to child processes;
|
|
see
|
|
.BR ptrace (2).
|
|
.TP
|
|
.B ESRCH
|
|
Process
|
|
.I pid1
|
|
or
|
|
.I pid2
|
|
does not exist.
|
|
.SH VERSIONS
|
|
The
|
|
.BR kcmp ()
|
|
system call first appeared in Linux 3.5.
|
|
.SH CONFORMING TO
|
|
.BR kcmp ()
|
|
is Linux-specific and should not be used in programs intended to be portable.
|
|
.SH NOTES
|
|
Glibc does not provide a wrapper for this system call; call it using
|
|
.BR syscall (2).
|
|
|
|
This system call is available only if the kernel was configured with
|
|
.BR CONFIG_CHECKPOINT_RESTORE .
|
|
The main use of the system call is for the
|
|
checkpoint/restore in user space (CRIU) feature.
|
|
The alternative to this system call would have been to expose suitable
|
|
process information via the
|
|
.BR proc (5)
|
|
filesystem; this was deemed to be unsuitable for security reasons.
|
|
|
|
See
|
|
.BR clone (2)
|
|
for some background information on the shared resources
|
|
referred to on this page.
|
|
.SH EXAMPLE
|
|
The program below uses
|
|
.BR kcmp ()
|
|
to test whether pairs of file descriptors refer to
|
|
the same open file description.
|
|
The program tests different cases for the file descriptor pairs,
|
|
as described in the program output.
|
|
An example run of the program is as follows:
|
|
|
|
.nf
|
|
.in +4n
|
|
$ \fB./a.out\fP
|
|
Parent PID is 1144
|
|
Parent opened file on FD 3
|
|
|
|
PID of child of fork() is 1145
|
|
Compare duplicate FDs from different processes:
|
|
kcmp(1145, 1144, KCMP_FILE, 3, 3) ==> same
|
|
Child opened file on FD 4
|
|
Compare FDs from distinct open()s in same process:
|
|
kcmp(1145, 1145, KCMP_FILE, 3, 4) ==> different
|
|
Child duplicated FD 3 to create FD 5
|
|
Compare duplicated FDs in same process:
|
|
kcmp(1145, 1145, KCMP_FILE, 3, 5) ==> same
|
|
.in
|
|
.fi
|
|
.SS Program source
|
|
\&
|
|
.nf
|
|
#define _GNU_SOURCE
|
|
#include <sys/syscall.h>
|
|
#include <sys/wait.h>
|
|
#include <sys/stat.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
#include <linux/kcmp.h>
|
|
|
|
#define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \\
|
|
} while (0)
|
|
|
|
static int
|
|
kcmp(pid_t pid1, pid_t pid2, int type,
|
|
unsigned long idx1, unsigned long idx2)
|
|
{
|
|
return syscall(SYS_kcmp, pid1, pid2, type, idx1, idx2);
|
|
}
|
|
|
|
static void
|
|
test_kcmp(char *msg, id_t pid1, pid_t pid2, int fd_a, int fd_b)
|
|
{
|
|
printf("\\t%s\\n", msg);
|
|
printf("\\t\\tkcmp(%ld, %ld, KCMP_FILE, %d, %d) ==> %s\\n",
|
|
(long) pid1, (long) pid2, fd_a, fd_b,
|
|
(kcmp(pid1, pid2, KCMP_FILE, fd_a, fd_b) == 0) ?
|
|
"same" : "different");
|
|
}
|
|
|
|
int
|
|
main(int argc, char *argv[])
|
|
{
|
|
int fd1, fd2, fd3;
|
|
char pathname[] = "/tmp/kcmp.test";
|
|
|
|
fd1 = open(pathname, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
|
|
if (fd1 == \-1)
|
|
errExit("open");
|
|
|
|
printf("Parent PID is %ld\\n", (long) getpid());
|
|
printf("Parent opened file on FD %d\\n\\n", fd1);
|
|
|
|
switch (fork()) {
|
|
case \-1:
|
|
errExit("fork");
|
|
|
|
case 0:
|
|
printf("PID of child of fork() is %ld\\n", (long) getpid());
|
|
|
|
test_kcmp("Compare duplicate FDs from different processes:",
|
|
getpid(), getppid(), fd1, fd1);
|
|
|
|
fd2 = open(pathname, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
|
|
if (fd2 == \-1)
|
|
errExit("open");
|
|
printf("Child opened file on FD %d\\n", fd2);
|
|
|
|
test_kcmp("Compare FDs from distinct open()s in same process:",
|
|
getpid(), getpid(), fd1, fd2);
|
|
|
|
fd3 = dup(fd1);
|
|
if (fd3 == \-1)
|
|
errExit("dup");
|
|
printf("Child duplicated FD %d to create FD %d\\n", fd1, fd3);
|
|
|
|
test_kcmp("Compare duplicated FDs in same process:",
|
|
getpid(), getpid(), fd1, fd3);
|
|
break;
|
|
|
|
default:
|
|
wait(NULL);
|
|
}
|
|
|
|
exit(EXIT_SUCCESS);
|
|
}
|
|
.fi
|
|
.SH SEE ALSO
|
|
.BR clone (2),
|
|
.BR unshare (2)
|