]>
Commit | Line | Data |
---|---|---|
98ef1803 | 1 | .\" Copyright (C) 2012, Cyrill Gorcunov <gorcunov@openvz.org> |
2e4eff1b | 2 | .\" and Copyright (C) 2012, 2016, Michael Kerrisk <mtk.manpages@gmail.com> |
98ef1803 | 3 | .\" |
5fbde956 | 4 | .\" SPDX-License-Identifier: Linux-man-pages-copyleft |
98ef1803 | 5 | .\" |
b73f9ed6 MK |
6 | .\" Kernel commit d97b46a64674a267bc41c9e16132ee2a98c3347d |
7 | .\" | |
45186a5d | 8 | .TH KCMP 2 2021-03-22 "Linux man-pages (unreleased)" |
aab0b384 | 9 | .SH NAME |
b73f9ed6 | 10 | kcmp \- compare two processes to determine if they share a kernel resource |
799cf776 AC |
11 | .SH LIBRARY |
12 | Standard C library | |
8fc3b2cf | 13 | .RI ( libc ", " \-lc ) |
aab0b384 CG |
14 | .SH SYNOPSIS |
15 | .nf | |
2f4306b0 AC |
16 | .BR "#include <linux/kcmp.h>" " /* Definition of " KCMP_* " constants */" |
17 | .BR "#include <sys/syscall.h>" " /* Definition of " SYS_* " constants */" | |
18 | .B #include <unistd.h> | |
dbfe9c70 | 19 | .PP |
2f4306b0 AC |
20 | .BI "int syscall(SYS_kcmp, pid_t " pid1 ", pid_t " pid2 ", int " type , |
21 | .BI " unsigned long " idx1 ", unsigned long " idx2 ); | |
aab0b384 | 22 | .fi |
dbfe9c70 | 23 | .PP |
b73f9ed6 | 24 | .IR Note : |
2f4306b0 AC |
25 | glibc provides no wrapper for |
26 | .BR kcmp (), | |
27 | necessitating the use of | |
28 | .BR syscall (2). | |
b73f9ed6 MK |
29 | .SH DESCRIPTION |
30 | The | |
aab0b384 | 31 | .BR kcmp () |
b73f9ed6 | 32 | system call can be used to check whether the two processes identified by |
aab0b384 CG |
33 | .I pid1 |
34 | and | |
35 | .I pid2 | |
b73f9ed6 MK |
36 | share a kernel resource such as virtual memory, file descriptors, |
37 | and so on. | |
efeece04 | 38 | .PP |
3bd3ab0f MK |
39 | Permission to employ |
40 | .BR kcmp () | |
41 | is governed by ptrace access mode | |
0647331a | 42 | .B PTRACE_MODE_READ_REALCREDS |
3bd3ab0f MK |
43 | checks against both |
44 | .I pid1 | |
45 | and | |
46 | .IR pid2 ; | |
47 | see | |
48 | .BR ptrace (2). | |
efeece04 | 49 | .PP |
b73f9ed6 | 50 | The |
aab0b384 | 51 | .I type |
b73f9ed6 MK |
52 | argument specifies which resource is to be compared in the two processes. |
53 | It has one of the following values: | |
b73f9ed6 | 54 | .TP |
1ae6b2c7 | 55 | .B KCMP_FILE |
b73f9ed6 | 56 | Check whether a file descriptor |
aab0b384 | 57 | .I idx1 |
b73f9ed6 MK |
58 | in the process |
59 | .I pid1 | |
60 | refers to the same open file description (see | |
61 | .BR open (2)) | |
62 | as file descriptor | |
aab0b384 | 63 | .I idx2 |
b73f9ed6 | 64 | in the process |
9f1b9726 | 65 | .IR pid2 . |
a579a5ab MK |
66 | The existence of two file descriptors that refer to the same |
67 | open file description can occur as a result of | |
68 | .BR dup (2) | |
69 | (and similar) | |
70 | .BR fork (2), | |
71 | or passing file descriptors via a domain socket (see | |
72 | .BR unix (7)). | |
b73f9ed6 | 73 | .TP |
1ae6b2c7 | 74 | .B KCMP_FILES |
def31770 | 75 | Check whether the processes share the same set of open file descriptors. |
b73f9ed6 MK |
76 | The arguments |
77 | .I idx1 | |
78 | and | |
79 | .I idx2 | |
80 | are ignored. | |
3c5253a5 | 81 | See the discussion of the |
1ae6b2c7 | 82 | .B CLONE_FILES |
3c5253a5 MK |
83 | flag in |
84 | .BR clone (2). | |
b73f9ed6 | 85 | .TP |
1ae6b2c7 | 86 | .B KCMP_FS |
9ee4a2b6 MK |
87 | Check whether the processes share the same filesystem information |
88 | (i.e., file mode creation mask, working directory, and filesystem root). | |
b73f9ed6 MK |
89 | The arguments |
90 | .I idx1 | |
91 | and | |
92 | .I idx2 | |
93 | are ignored. | |
3c5253a5 | 94 | See the discussion of the |
1ae6b2c7 | 95 | .B CLONE_FS |
3c5253a5 MK |
96 | flag in |
97 | .BR clone (2). | |
b73f9ed6 | 98 | .TP |
1ae6b2c7 | 99 | .B KCMP_IO |
b73f9ed6 MK |
100 | Check whether the processes share I/O context. |
101 | The arguments | |
102 | .I idx1 | |
103 | and | |
104 | .I idx2 | |
105 | are ignored. | |
3c5253a5 | 106 | See the discussion of the |
1ae6b2c7 | 107 | .B CLONE_IO |
3c5253a5 MK |
108 | flag in |
109 | .BR clone (2). | |
b73f9ed6 | 110 | .TP |
1ae6b2c7 | 111 | .B KCMP_SIGHAND |
b73f9ed6 MK |
112 | Check whether the processes share the same table of signal dispositions. |
113 | The arguments | |
114 | .I idx1 | |
115 | and | |
116 | .I idx2 | |
117 | are ignored. | |
3c5253a5 | 118 | See the discussion of the |
1ae6b2c7 | 119 | .B CLONE_SIGHAND |
3c5253a5 MK |
120 | flag in |
121 | .BR clone (2). | |
b73f9ed6 | 122 | .TP |
1ae6b2c7 | 123 | .B KCMP_SYSVSEM |
b73f9ed6 | 124 | Check whether the processes share the same |
efbfd7ec | 125 | list of System\ V semaphore undo operations. |
b73f9ed6 MK |
126 | The arguments |
127 | .I idx1 | |
128 | and | |
129 | .I idx2 | |
130 | are ignored. | |
3c5253a5 | 131 | See the discussion of the |
1ae6b2c7 | 132 | .B CLONE_SYSVSEM |
3c5253a5 MK |
133 | flag in |
134 | .BR clone (2). | |
b73f9ed6 | 135 | .TP |
1ae6b2c7 | 136 | .B KCMP_VM |
b73f9ed6 MK |
137 | Check whether the processes share the same address space. |
138 | The arguments | |
139 | .I idx1 | |
140 | and | |
141 | .I idx2 | |
142 | are ignored. | |
3c5253a5 | 143 | See the discussion of the |
1ae6b2c7 | 144 | .B CLONE_VM |
3c5253a5 MK |
145 | flag in |
146 | .BR clone (2). | |
2268af11 | 147 | .TP |
3e105e07 MK |
148 | .BR KCMP_EPOLL_TFD " (since Linux 4.13)" |
149 | .\" commit 0791e3644e5ef21646fe565b9061788d05ec71d4 | |
2268af11 CG |
150 | Check whether the file descriptor |
151 | .I idx1 | |
152 | of the process | |
153 | .I pid1 | |
3e105e07 | 154 | is present in the |
2268af11 CG |
155 | .BR epoll (7) |
156 | instance described by | |
157 | .I idx2 | |
158 | of the process | |
159 | .IR pid2 . | |
160 | The argument | |
161 | .I idx2 | |
3e105e07 MK |
162 | is a pointer to a structure where the target file is described. |
163 | This structure has the form: | |
ba39b288 | 164 | .PP |
2268af11 | 165 | .in +4n |
b8302363 | 166 | .EX |
2268af11 | 167 | struct kcmp_epoll_slot { |
3e105e07 MK |
168 | __u32 efd; |
169 | __u32 tfd; | |
170 | __u64 toff; | |
2268af11 | 171 | }; |
b8302363 | 172 | .EE |
2268af11 | 173 | .in |
ba39b288 | 174 | .PP |
3e105e07 | 175 | Within this structure, |
2268af11 | 176 | .I efd |
3e105e07 MK |
177 | is an epoll file descriptor returned from |
178 | .BR epoll_create (2), | |
2268af11 | 179 | .I tfd |
3e105e07 | 180 | is a target file descriptor number, and |
2268af11 CG |
181 | .I toff |
182 | is a target file offset counted from zero. | |
183 | Several different targets may be registered with | |
3e105e07 | 184 | the same file descriptor number and setting a specific |
2268af11 | 185 | offset helps to investigate each of them. |
b73f9ed6 | 186 | .PP |
aab0b384 CG |
187 | Note the |
188 | .BR kcmp () | |
43a9c083 MK |
189 | is not protected against false positives which may occur if |
190 | the processes are currently running. | |
191 | One should stop the processes by sending | |
1ae6b2c7 | 192 | .B SIGSTOP |
df2f284e SL |
193 | (see |
194 | .BR signal (7)) | |
6add864c | 195 | prior to inspection with this system call to obtain meaningful results. |
47297adb | 196 | .SH RETURN VALUE |
b73f9ed6 MK |
197 | The return value of a successful call to |
198 | .BR kcmp () | |
199 | is simply the result of arithmetic comparison | |
200 | of kernel pointers (when the kernel compares resources, it uses their | |
aab0b384 | 201 | memory addresses). |
efeece04 | 202 | .PP |
aab0b384 | 203 | The easiest way to explain is to consider an example. |
b73f9ed6 | 204 | Suppose that |
aab0b384 CG |
205 | .I v1 |
206 | and | |
207 | .I v2 | |
208 | are the addresses of appropriate resources, then the return value | |
b73f9ed6 | 209 | is one of the following: |
b73f9ed6 MK |
210 | .RS 4 |
211 | .IP 0 4 | |
aab0b384 CG |
212 | .I v1 |
213 | is equal to | |
b73f9ed6 MK |
214 | .IR v2 ; |
215 | in other words, the two processes share the resource. | |
b73f9ed6 | 216 | .IP 1 |
aab0b384 CG |
217 | .I v1 |
218 | is less than | |
b73f9ed6 | 219 | .IR v2 . |
b73f9ed6 | 220 | .IP 2 |
aab0b384 CG |
221 | .I v1 |
222 | is greater than | |
b73f9ed6 | 223 | .IR v2 . |
b73f9ed6 | 224 | .IP 3 |
aab0b384 CG |
225 | .I v1 |
226 | is not equal to | |
227 | .IR v2 , | |
228 | but ordering information is unavailable. | |
b73f9ed6 | 229 | .RE |
b73f9ed6 MK |
230 | .PP |
231 | On error, \-1 is returned, and | |
232 | .I errno | |
f6a4078b | 233 | is set to indicate the error. |
efeece04 | 234 | .PP |
0ae31c56 | 235 | .BR kcmp () |
b73f9ed6 MK |
236 | was designed to return values suitable for sorting. |
237 | This is particularly handy if one needs to compare | |
238 | a large number of file descriptors. | |
b73f9ed6 | 239 | .SH ERRORS |
b73f9ed6 MK |
240 | .TP |
241 | .B EBADF | |
242 | .I type | |
243 | is | |
244 | .B KCMP_FILE | |
245 | and | |
246 | .I fd1 | |
247 | or | |
248 | .I fd2 | |
249 | is not an open file descriptor. | |
250 | .TP | |
49a2a105 MK |
251 | .B EFAULT |
252 | The epoll slot addressed by | |
253 | .I idx2 | |
254 | is outside of the user's address space. | |
255 | .TP | |
b73f9ed6 MK |
256 | .B EINVAL |
257 | .I type | |
258 | is invalid. | |
259 | .TP | |
49a2a105 MK |
260 | .B ENOENT |
261 | The target file is not present in | |
262 | .BR epoll (7) | |
263 | instance. | |
264 | .TP | |
b73f9ed6 MK |
265 | .B EPERM |
266 | Insufficient permission to inspect process resources. | |
267 | The | |
268 | .B CAP_SYS_PTRACE | |
5c1932ae | 269 | capability is required to inspect processes that you do not own. |
2a7b88af | 270 | Other ptrace limitations may also apply, such as |
8ec68b89 | 271 | .BR CONFIG_SECURITY_YAMA , |
164a3a92 | 272 | which, when |
5c1932ae | 273 | .I /proc/sys/kernel/yama/ptrace_scope |
164a3a92 | 274 | is 2, limits |
5c1932ae MK |
275 | .BR kcmp () |
276 | to child processes; | |
277 | see | |
278 | .BR ptrace (2). | |
b73f9ed6 MK |
279 | .TP |
280 | .B ESRCH | |
281 | Process | |
282 | .I pid1 | |
283 | or | |
284 | .I pid2 | |
285 | does not exist. | |
b73f9ed6 MK |
286 | .SH VERSIONS |
287 | The | |
288 | .BR kcmp () | |
289 | system call first appeared in Linux 3.5. | |
3113c7f3 | 290 | .SH STANDARDS |
aab0b384 | 291 | .BR kcmp () |
76c637e1 | 292 | is Linux-specific and should not be used in programs intended to be portable. |
b73f9ed6 | 293 | .SH NOTES |
b007f233 MK |
294 | Before Linux 5.12, |
295 | this system call is available only if the kernel is configured with | |
296 | .BR CONFIG_CHECKPOINT_RESTORE , | |
b5c3fcdb | 297 | since the original purpose of the system call was for the |
b73f9ed6 | 298 | checkpoint/restore in user space (CRIU) feature. |
b007f233 | 299 | (The alternative to this system call would have been to expose suitable |
b73f9ed6 MK |
300 | process information via the |
301 | .BR proc (5) | |
b007f233 | 302 | filesystem; this was deemed to be unsuitable for security reasons.) |
79c9fe57 JH |
303 | Since Linux 5.12, |
304 | this system call is also available if the kernel is configured with | |
305 | .BR CONFIG_KCMP . | |
efeece04 | 306 | .PP |
b73f9ed6 | 307 | See |
aab0b384 | 308 | .BR clone (2) |
b73f9ed6 MK |
309 | for some background information on the shared resources |
310 | referred to on this page. | |
a14af333 | 311 | .SH EXAMPLES |
2e4eff1b MK |
312 | The program below uses |
313 | .BR kcmp () | |
314 | to test whether pairs of file descriptors refer to | |
315 | the same open file description. | |
316 | The program tests different cases for the file descriptor pairs, | |
317 | as described in the program output. | |
318 | An example run of the program is as follows: | |
efeece04 | 319 | .PP |
2e4eff1b | 320 | .in +4n |
b8302363 | 321 | .EX |
2e4eff1b MK |
322 | $ \fB./a.out\fP |
323 | Parent PID is 1144 | |
324 | Parent opened file on FD 3 | |
325 | ||
326 | PID of child of fork() is 1145 | |
327 | Compare duplicate FDs from different processes: | |
328 | kcmp(1145, 1144, KCMP_FILE, 3, 3) ==> same | |
329 | Child opened file on FD 4 | |
330 | Compare FDs from distinct open()s in same process: | |
331 | kcmp(1145, 1145, KCMP_FILE, 3, 4) ==> different | |
332 | Child duplicated FD 3 to create FD 5 | |
333 | Compare duplicated FDs in same process: | |
334 | kcmp(1145, 1145, KCMP_FILE, 3, 5) ==> same | |
b8302363 | 335 | .EE |
e646a1ba | 336 | .in |
2e4eff1b MK |
337 | .SS Program source |
338 | \& | |
33857069 | 339 | .\" SRC BEGIN (kcmp.c) |
e7d0bb47 | 340 | .EX |
2e4eff1b | 341 | #define _GNU_SOURCE |
47b94bbd AC |
342 | #include <fcntl.h> |
343 | #include <linux/kcmp.h> | |
8eb90116 | 344 | #include <stdint.h> |
2e4eff1b | 345 | #include <stdio.h> |
47b94bbd AC |
346 | #include <stdlib.h> |
347 | #include <sys/syscall.h> | |
348 | #include <sys/wait.h> | |
2e4eff1b | 349 | #include <unistd.h> |
2e4eff1b | 350 | |
d1a71985 | 351 | #define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \e |
2e4eff1b MK |
352 | } while (0) |
353 | ||
354 | static int | |
355 | kcmp(pid_t pid1, pid_t pid2, int type, | |
356 | unsigned long idx1, unsigned long idx2) | |
357 | { | |
358 | return syscall(SYS_kcmp, pid1, pid2, type, idx1, idx2); | |
359 | } | |
360 | ||
361 | static void | |
95c3d0a0 | 362 | test_kcmp(char *msg, pid_t pid1, pid_t pid2, int fd_a, int fd_b) |
2e4eff1b | 363 | { |
d1a71985 | 364 | printf("\et%s\en", msg); |
8eb90116 | 365 | printf("\et\etkcmp(%jd, %jd, KCMP_FILE, %d, %d) ==> %s\en", |
4687ab0e AC |
366 | (intmax_t) pid1, (intmax_t) pid2, fd_a, fd_b, |
367 | (kcmp(pid1, pid2, KCMP_FILE, fd_a, fd_b) == 0) ? | |
2e4eff1b MK |
368 | "same" : "different"); |
369 | } | |
370 | ||
371 | int | |
c6ae6d97 | 372 | main(void) |
2e4eff1b MK |
373 | { |
374 | int fd1, fd2, fd3; | |
375 | char pathname[] = "/tmp/kcmp.test"; | |
376 | ||
56fc210e | 377 | fd1 = open(pathname, O_CREAT | O_RDWR, 0600); |
2e4eff1b MK |
378 | if (fd1 == \-1) |
379 | errExit("open"); | |
380 | ||
8eb90116 | 381 | printf("Parent PID is %jd\en", (intmax_t) getpid()); |
d1a71985 | 382 | printf("Parent opened file on FD %d\en\en", fd1); |
2e4eff1b MK |
383 | |
384 | switch (fork()) { | |
385 | case \-1: | |
386 | errExit("fork"); | |
387 | ||
388 | case 0: | |
8eb90116 | 389 | printf("PID of child of fork() is %jd\en", (intmax_t) getpid()); |
2e4eff1b MK |
390 | |
391 | test_kcmp("Compare duplicate FDs from different processes:", | |
4687ab0e | 392 | getpid(), getppid(), fd1, fd1); |
2e4eff1b | 393 | |
56fc210e | 394 | fd2 = open(pathname, O_CREAT | O_RDWR, 0600); |
2e4eff1b MK |
395 | if (fd2 == \-1) |
396 | errExit("open"); | |
d1a71985 | 397 | printf("Child opened file on FD %d\en", fd2); |
2e4eff1b MK |
398 | |
399 | test_kcmp("Compare FDs from distinct open()s in same process:", | |
4687ab0e | 400 | getpid(), getpid(), fd1, fd2); |
2e4eff1b MK |
401 | |
402 | fd3 = dup(fd1); | |
403 | if (fd3 == \-1) | |
404 | errExit("dup"); | |
d1a71985 | 405 | printf("Child duplicated FD %d to create FD %d\en", fd1, fd3); |
2e4eff1b MK |
406 | |
407 | test_kcmp("Compare duplicated FDs in same process:", | |
4687ab0e | 408 | getpid(), getpid(), fd1, fd3); |
2e4eff1b MK |
409 | break; |
410 | ||
411 | default: | |
412 | wait(NULL); | |
413 | } | |
414 | ||
415 | exit(EXIT_SUCCESS); | |
416 | } | |
e7d0bb47 | 417 | .EE |
33857069 | 418 | .\" SRC END |
47297adb | 419 | .SH SEE ALSO |
b73f9ed6 MK |
420 | .BR clone (2), |
421 | .BR unshare (2) |