Branch data Line data Source code
1 : : #define _XOPEN_SOURCE
2 : :
3 : : #include <stdlib.h>
4 : : #include <stdio.h>
5 : : #include <stdarg.h>
6 : : #include <string.h>
7 : : #include <errno.h>
8 : : #include <unistd.h>
9 : : #include <stdbool.h>
10 : : #include <limits.h>
11 : : #include <signal.h>
12 : : #include <limits.h>
13 : : #include <unistd.h>
14 : : #include <errno.h>
15 : : #include <string.h>
16 : : #include <dirent.h>
17 : : #include <sys/sendfile.h>
18 : : #include <fcntl.h>
19 : :
20 : : #include <sys/param.h>
21 : : #include <sys/types.h>
22 : : #include <sys/ptrace.h>
23 : : #include <sys/types.h>
24 : : #include <sys/time.h>
25 : : #include <sys/resource.h>
26 : : #include <sys/stat.h>
27 : : #include <sys/mman.h>
28 : : #include <sys/vfs.h>
29 : : #include <sys/ptrace.h>
30 : : #include <sys/wait.h>
31 : : #include <sys/resource.h>
32 : : #include <sys/wait.h>
33 : :
34 : : #include "compiler.h"
35 : : #include "asm/types.h"
36 : : #include "list.h"
37 : : #include "util.h"
38 : : #include "rst-malloc.h"
39 : : #include "image.h"
40 : : #include "vma.h"
41 : : #include "mem.h"
42 : :
43 : : #include "cr_options.h"
44 : : #include "servicefd.h"
45 : : #include "cr-service.h"
46 : :
47 : : #define VMA_OPT_LEN 128
48 : :
49 : 194871 : static void vma_opt_str(const struct vma_area *v, char *opt)
50 : : {
51 : : int p = 0;
52 : :
53 : : #define opt2s(_o, _s) do { \
54 : : if (v->e->status & _o) \
55 : : p += sprintf(opt + p, _s " "); \
56 : : } while (0)
57 : :
58 : 194871 : opt[p] = '\0';
59 [ + + ]: 194871 : opt2s(VMA_AREA_REGULAR, "reg");
60 [ - + ]: 194871 : opt2s(VMA_AREA_STACK, "stk");
61 [ + + ]: 194871 : opt2s(VMA_AREA_VSYSCALL, "vsys");
62 [ + + ]: 194871 : opt2s(VMA_AREA_VDSO, "vdso");
63 [ - + ]: 194871 : opt2s(VMA_FORCE_READ, "frd");
64 [ + + ]: 194871 : opt2s(VMA_AREA_HEAP, "heap");
65 [ + + ]: 194871 : opt2s(VMA_FILE_PRIVATE, "fp");
66 [ + + ]: 194871 : opt2s(VMA_FILE_SHARED, "fs");
67 [ + + ]: 194871 : opt2s(VMA_ANON_SHARED, "as");
68 [ + + ]: 194871 : opt2s(VMA_ANON_PRIVATE, "ap");
69 [ + + ]: 194871 : opt2s(VMA_AREA_SYSVIPC, "sysv");
70 [ - + ]: 194871 : opt2s(VMA_AREA_SOCKET, "sk");
71 : :
72 : : #undef opt2s
73 : 194871 : }
74 : :
75 : 194871 : void pr_vma(unsigned int loglevel, const struct vma_area *vma_area)
76 : : {
77 : : char opt[VMA_OPT_LEN];
78 : : memset(opt, 0, VMA_OPT_LEN);
79 : :
80 [ + - ]: 194871 : if (!vma_area)
81 : 0 : return;
82 : :
83 : 194871 : vma_opt_str(vma_area, opt);
84 : 194871 : print_on_level(loglevel, "%#"PRIx64"-%#"PRIx64" (%"PRIi64"K) prot %#x flags %#x off %#"PRIx64" "
85 : : "%s shmid: %#"PRIx64"\n",
86 : : vma_area->e->start, vma_area->e->end,
87 : 194871 : KBYTES(vma_area_len(vma_area)),
88 : : vma_area->e->prot,
89 : : vma_area->e->flags,
90 : : vma_area->e->pgoff,
91 : 194871 : opt, vma_area->e->shmid);
92 : : }
93 : :
94 : 51448 : int close_safe(int *fd)
95 : : {
96 : : int ret = 0;
97 [ + + ]: 51448 : if (*fd > -1) {
98 : 47302 : ret = close(*fd);
99 [ + - ]: 47302 : if (!ret)
100 : 47302 : *fd = -1;
101 : : else
102 : 0 : pr_perror("Unable to close fd %d", *fd);
103 : : }
104 : :
105 : 51448 : return ret;
106 : : }
107 : :
108 : 5274 : int reopen_fd_as_safe(char *file, int line, int new_fd, int old_fd, bool allow_reuse_fd)
109 : : {
110 : : int tmp;
111 : :
112 [ + + ]: 5274 : if (old_fd != new_fd) {
113 : :
114 [ + + ]: 4099 : if (!allow_reuse_fd) {
115 [ + - ][ - + ]: 677 : if (fcntl(new_fd, F_GETFD) != -1 || errno != EBADF) {
116 [ # # ]: 0 : if (new_fd < 3) {
117 : : /*
118 : : * Standard descriptors.
119 : : */
120 : 0 : pr_warn("fd %d already in use (called at %s:%d)\n",
121 : : new_fd, file, line);
122 : : } else {
123 : 0 : pr_err("fd %d already in use (called at %s:%d)\n",
124 : : new_fd, file, line);
125 : 0 : return -1;
126 : : }
127 : : }
128 : : }
129 : :
130 : 4099 : tmp = dup2(old_fd, new_fd);
131 [ - + ]: 4099 : if (tmp < 0) {
132 : 0 : pr_perror("Dup %d -> %d failed (called at %s:%d)",
133 : : old_fd, new_fd, file, line);
134 : 0 : return tmp;
135 : : }
136 : :
137 : : /* Just to have error message if failed */
138 : 4099 : close_safe(&old_fd);
139 : : }
140 : :
141 : : return 0;
142 : : }
143 : :
144 : 4413 : int move_img_fd(int *img_fd, int want_fd)
145 : : {
146 [ + + ]: 4413 : if (*img_fd == want_fd) {
147 : : int tmp;
148 : :
149 : 243 : tmp = dup(*img_fd);
150 [ - + ]: 243 : if (tmp < 0) {
151 : 0 : pr_perror("Can't dup file");
152 : 0 : return -1;
153 : : }
154 : :
155 : 243 : close(*img_fd);
156 : :
157 : 243 : *img_fd = tmp;
158 : : }
159 : :
160 : : return 0;
161 : : }
162 : :
163 : : static pid_t open_proc_pid = 0;
164 : : static int open_proc_fd = -1;
165 : :
166 : 28092 : int close_pid_proc(void)
167 : : {
168 : : int ret = 0;
169 : :
170 [ + + ]: 28092 : if (open_proc_fd >= 0)
171 : 16406 : ret = close(open_proc_fd);
172 : :
173 : 28092 : open_proc_fd = -1;
174 : 28092 : open_proc_pid = 0;
175 : :
176 : 28092 : return ret;
177 : : }
178 : :
179 : 559 : void close_proc()
180 : : {
181 : 3379 : close_pid_proc();
182 : :
183 : 3379 : close_service_fd(PROC_FD_OFF);
184 : 559 : }
185 : :
186 : 564 : int set_proc_fd(int fd)
187 : : {
188 [ + - ]: 564 : if (install_service_fd(PROC_FD_OFF, fd) < 0)
189 : : return -1;
190 : 564 : return 0;
191 : : }
192 : :
193 : 2820 : static int open_proc_sfd(char *path)
194 : : {
195 : : int fd, ret;
196 : : close_proc();
197 : :
198 : : fd = open(path, O_DIRECTORY | O_RDONLY);
199 [ - + ]: 2820 : if (fd == -1) {
200 : 0 : pr_err("Can't open %s\n", path);
201 : 0 : return -1;
202 : : }
203 : :
204 : 2820 : ret = install_service_fd(PROC_FD_OFF, fd);
205 : 2820 : close(fd);
206 [ + - ]: 2820 : if (ret < 0)
207 : : return -1;
208 : :
209 : 2820 : return 0;
210 : : }
211 : :
212 : 73359 : inline int open_pid_proc(pid_t pid)
213 : : {
214 : : char path[18];
215 : : int fd;
216 : : int dfd;
217 : :
218 [ + + ]: 73359 : if (pid == open_proc_pid)
219 : 54907 : return open_proc_fd;
220 : :
221 : 18452 : close_pid_proc();
222 : :
223 : 18452 : dfd = get_service_fd(PROC_FD_OFF);
224 [ + + ]: 18452 : if (dfd < 0) {
225 [ + - ]: 2820 : if (open_proc_sfd("/proc") < 0)
226 : : return -1;
227 : :
228 : 2820 : dfd = get_service_fd(PROC_FD_OFF);
229 : : }
230 : :
231 : : snprintf(path, sizeof(path), "%d", pid);
232 : : fd = openat(dfd, path, O_RDONLY);
233 [ + + ]: 18452 : if (fd < 0)
234 : 11 : pr_perror("Can't open %s", path);
235 : : else {
236 : 18441 : open_proc_fd = fd;
237 : 18441 : open_proc_pid = pid;
238 : : }
239 : :
240 : 18452 : return fd;
241 : : }
242 : :
243 : 62984 : int do_open_proc(pid_t pid, int flags, const char *fmt, ...)
244 : : {
245 : : char path[128];
246 : : va_list args;
247 : 62984 : int dirfd = open_pid_proc(pid);
248 : :
249 [ + + ]: 62984 : if (dirfd < 0)
250 : : return -1;
251 : :
252 : 62973 : va_start(args, fmt);
253 : : vsnprintf(path, sizeof(path), fmt, args);
254 : 62973 : va_end(args);
255 : :
256 : 62973 : return openat(dirfd, path, flags);
257 : : }
258 : :
259 : : static int service_fd_rlim_cur;
260 : : static int service_fd_id = 0;
261 : :
262 : 3702 : int init_service_fd(void)
263 : : {
264 : : struct rlimit rlimit;
265 : :
266 : : /*
267 : : * Service FDs are those that most likely won't
268 : : * conflict with any 'real-life' ones
269 : : */
270 : :
271 [ - + ]: 3702 : if (getrlimit(RLIMIT_NOFILE, &rlimit)) {
272 : 0 : pr_perror("Can't get rlimit");
273 : 0 : return -1;
274 : : }
275 : :
276 : 3702 : service_fd_rlim_cur = (int)rlimit.rlim_cur;
277 [ - + ]: 3702 : BUG_ON(service_fd_rlim_cur < SERVICE_FD_MAX);
278 : :
279 : : return 0;
280 : : }
281 : :
282 : : static int __get_service_fd(enum sfd_type type, int service_fd_id)
283 : : {
284 : 4600565 : return service_fd_rlim_cur - type - SERVICE_FD_MAX * service_fd_id;
285 : : }
286 : :
287 : : static DECLARE_BITMAP(sfd_map, SERVICE_FD_MAX);
288 : :
289 : 12 : int reserve_service_fd(enum sfd_type type)
290 : : {
291 : 12 : int sfd = __get_service_fd(type, service_fd_id);
292 : :
293 [ - + ]: 12 : BUG_ON((int)type <= SERVICE_FD_MIN || (int)type >= SERVICE_FD_MAX);
294 : :
295 : 12 : set_bit(type, sfd_map);
296 : 12 : return sfd;
297 : : }
298 : :
299 : 14160 : int install_service_fd(enum sfd_type type, int fd)
300 : : {
301 : 14160 : int sfd = __get_service_fd(type, service_fd_id);
302 : :
303 [ - + ]: 14160 : BUG_ON((int)type <= SERVICE_FD_MIN || (int)type >= SERVICE_FD_MAX);
304 : :
305 [ - + ]: 14160 : if (dup3(fd, sfd, O_CLOEXEC) != sfd) {
306 : 0 : pr_perror("Dup %d -> %d failed", fd, sfd);
307 : 0 : return -1;
308 : : }
309 : :
310 : 14160 : set_bit(type, sfd_map);
311 : 14160 : return sfd;
312 : : }
313 : :
314 : 4583868 : int get_service_fd(enum sfd_type type)
315 : : {
316 [ - + ]: 4583868 : BUG_ON((int)type <= SERVICE_FD_MIN || (int)type >= SERVICE_FD_MAX);
317 : :
318 [ + + ]: 4583868 : if (!test_bit(type, sfd_map))
319 : : return -1;
320 : :
321 : 4575353 : return __get_service_fd(type, service_fd_id);
322 : : }
323 : :
324 : 6 : int criu_get_image_dir(void)
325 : : {
326 : 6 : return get_service_fd(IMG_FD_OFF);
327 : : }
328 : :
329 : 7365 : int close_service_fd(enum sfd_type type)
330 : : {
331 : : int fd;
332 : :
333 : 7365 : fd = get_service_fd(type);
334 [ + + ]: 7365 : if (fd < 0)
335 : : return 0;
336 : :
337 [ + - ]: 1810 : if (close_safe(&fd))
338 : : return -1;
339 : :
340 : 1810 : clear_bit(type, sfd_map);
341 : 1810 : return 0;
342 : : }
343 : :
344 : 688 : int clone_service_fd(int id)
345 : : {
346 : : int ret = -1, i;
347 : :
348 [ + + ]: 688 : if (service_fd_id == id)
349 : : return 0;
350 : :
351 [ + + ]: 80 : for (i = SERVICE_FD_MIN + 1; i < SERVICE_FD_MAX; i++) {
352 : 70 : int old = __get_service_fd(i, service_fd_id);
353 : : int new = __get_service_fd(i, id);
354 : :
355 : 70 : ret = dup2(old, new);
356 [ + + ]: 70 : if (ret == -1) {
357 [ + - ]: 20 : if (errno == EBADF)
358 : 20 : continue;
359 : 0 : pr_perror("Unable to clone %d->%d", old, new);
360 : : }
361 : : }
362 : :
363 : 10 : service_fd_id = id;
364 : : ret = 0;
365 : :
366 : 10 : return ret;
367 : : }
368 : :
369 : 6850 : bool is_any_service_fd(int fd)
370 : : {
371 [ + + ][ - + ]: 6850 : return fd > __get_service_fd(SERVICE_FD_MAX, service_fd_id) &&
372 : : fd < __get_service_fd(SERVICE_FD_MIN, service_fd_id);
373 : : }
374 : :
375 : 192 : bool is_service_fd(int fd, enum sfd_type type)
376 : : {
377 : 192 : return fd == get_service_fd(type);
378 : : }
379 : :
380 : 44 : int copy_file(int fd_in, int fd_out, size_t bytes)
381 : : {
382 : : ssize_t written = 0;
383 [ + + ]: 44 : size_t chunk = bytes ? bytes : 4096;
384 : :
385 : : while (1) {
386 : : ssize_t ret;
387 : :
388 : 78 : ret = sendfile(fd_out, fd_in, NULL, chunk);
389 [ - + ]: 78 : if (ret < 0) {
390 : 0 : pr_perror("Can't send data to ghost file");
391 : 0 : return -1;
392 : : }
393 : :
394 [ + + ]: 78 : if (ret == 0) {
395 [ - + ]: 44 : if (bytes && (written != bytes)) {
396 : 0 : pr_err("Ghost file size mismatch %zu/%zu\n",
397 : : written, bytes);
398 : 0 : return -1;
399 : : }
400 : : break;
401 : : }
402 : :
403 : 34 : written += ret;
404 : 34 : }
405 : :
406 : : return 0;
407 : : }
408 : :
409 : 5092 : int read_fd_link(int lfd, char *buf, size_t size)
410 : : {
411 : : char t[32];
412 : : ssize_t ret;
413 : :
414 : : snprintf(t, sizeof(t), "/proc/self/fd/%d", lfd);
415 : : ret = readlink(t, buf, size);
416 [ - + ]: 5092 : if (ret < 0) {
417 : 0 : pr_perror("Can't read link of fd %d", lfd);
418 : 0 : return -1;
419 [ - + ]: 5092 : } else if ((size_t)ret == size) {
420 : 0 : pr_err("Buffer for read link of fd %d is too small\n", lfd);
421 : 0 : return -1;
422 : : }
423 : 5092 : buf[ret] = 0;
424 : :
425 : 5092 : return ret;
426 : : }
427 : :
428 : 34158 : int is_anon_link_type(char *link, char *type)
429 : : {
430 : : char aux[32];
431 : :
432 : : snprintf(aux, sizeof(aux), "anon_inode:%s", type);
433 : 34158 : return !strcmp(link, aux);
434 : : }
435 : :
436 : 10486 : void *shmalloc(size_t bytes)
437 : : {
438 : 10486 : return rst_mem_alloc(bytes, RM_SHARED);
439 : : }
440 : :
441 : : /* Only last chunk can be released */
442 : 354 : void shfree_last(void *ptr)
443 : : {
444 : 354 : rst_mem_free_last(RM_SHARED);
445 : 354 : }
446 : :
447 : 1772 : int run_scripts(char *action)
448 : : {
449 : : struct script *script;
450 : : int ret = 0;
451 : :
452 : 1772 : pr_debug("Running %s scripts\n", action);
453 : :
454 [ - + ]: 1772 : if (setenv("CRTOOLS_SCRIPT_ACTION", action, 1)) {
455 : 0 : pr_perror("Can't set CRTOOLS_SCRIPT_ACTION=%s", action);
456 : 0 : return -1;
457 : : }
458 : :
459 [ - + ]: 1772 : list_for_each_entry(script, &opts.scripts, node) {
460 [ # # ]: 0 : if (script->path == SCRIPT_RPC_NOTIFY) {
461 : 0 : pr_debug("\tRPC\n");
462 : 0 : ret |= send_criu_rpc_script(action, script->arg);
463 : : } else {
464 : 0 : pr_debug("\t[%s]\n", script->path);
465 : 0 : ret |= system(script->path);
466 : : }
467 : : }
468 : :
469 : 1772 : unsetenv("CRTOOLS_SCRIPT_ACTION");
470 : 1772 : return ret;
471 : : }
472 : :
473 : : #define DUP_SAFE(fd, out) \
474 : : ({ \
475 : : int ret__; \
476 : : ret__ = dup(fd); \
477 : : if (ret__ == -1) { \
478 : : pr_perror("dup(%d) failed", fd); \
479 : : goto out; \
480 : : } \
481 : : ret__; \
482 : : })
483 : :
484 : : /*
485 : : * If "in" is negative, stdin will be closed.
486 : : * If "out" or "err" are negative, a log file descriptor will be used.
487 : : */
488 : 1388 : int cr_system(int in, int out, int err, char *cmd, char *const argv[])
489 : : {
490 : : sigset_t blockmask, oldmask;
491 : : int ret = -1, status;
492 : : pid_t pid;
493 : :
494 : 1388 : sigemptyset(&blockmask);
495 : 1388 : sigaddset(&blockmask, SIGCHLD);
496 [ - + ]: 1388 : if (sigprocmask(SIG_BLOCK, &blockmask, &oldmask) == -1) {
497 : 0 : pr_perror("Can not set mask of blocked signals");
498 : 0 : return -1;
499 : : }
500 : :
501 : 1388 : pid = fork();
502 [ - + ]: 2566 : if (pid == -1) {
503 : 0 : pr_perror("fork() failed");
504 : 0 : goto out;
505 [ + + ]: 2566 : } else if (pid == 0) {
506 [ + + ]: 1388 : if (out < 0)
507 : 742 : out = log_get_fd();
508 [ + - ]: 1388 : if (err < 0)
509 : 1388 : err = log_get_fd();
510 : :
511 : : /*
512 : : * out, err, in should be a separate fds,
513 : : * because reopen_fd_as() closes an old fd
514 : : */
515 [ + + ]: 1388 : if (err == out || err == in)
516 [ - + ]: 742 : err = DUP_SAFE(err, out_chld);
517 : :
518 [ - + ]: 1388 : if (out == in)
519 [ # # ]: 0 : out = DUP_SAFE(out, out_chld);
520 : :
521 [ + - + - ]: 2776 : if (move_img_fd(&out, STDIN_FILENO) ||
522 : 1388 : move_img_fd(&err, STDIN_FILENO))
523 : : goto out_chld;
524 : :
525 [ + + ]: 1388 : if (in < 0) {
526 : 742 : close(STDIN_FILENO);
527 : : } else {
528 [ + - ]: 646 : if (reopen_fd_as_nocheck(STDIN_FILENO, in))
529 : : goto out_chld;
530 : : }
531 : :
532 [ + - ]: 1388 : if (move_img_fd(&err, STDOUT_FILENO))
533 : : goto out_chld;
534 : :
535 [ + - ]: 1388 : if (reopen_fd_as_nocheck(STDOUT_FILENO, out))
536 : : goto out_chld;
537 : :
538 [ + - ]: 1388 : if (reopen_fd_as_nocheck(STDERR_FILENO, err))
539 : : goto out_chld;
540 : :
541 : 1388 : execvp(cmd, argv);
542 : :
543 : 1388 : pr_perror("exec failed");
544 : : out_chld:
545 : 0 : _exit(1);
546 : : }
547 : :
548 : : while (1) {
549 : 1178 : ret = waitpid(pid, &status, 0);
550 [ - + ]: 1178 : if (ret == -1) {
551 : 0 : pr_perror("waitpid() failed");
552 : 0 : goto out;
553 : : }
554 : :
555 [ + - ]: 1178 : if (WIFEXITED(status)) {
556 [ - + ]: 1178 : if (WEXITSTATUS(status))
557 : 0 : pr_err("exited, status=%d\n", WEXITSTATUS(status));
558 : : break;
559 [ # # ]: 0 : } else if (WIFSIGNALED(status)) {
560 : 0 : pr_err("killed by signal %d\n", WTERMSIG(status));
561 : 0 : break;
562 [ # # ]: 0 : } else if (WIFSTOPPED(status)) {
563 : 0 : pr_err("stopped by signal %d\n", WSTOPSIG(status));
564 [ # # ]: 0 : } else if (WIFCONTINUED(status)) {
565 : 0 : pr_err("continued\n");
566 : : }
567 : : }
568 : :
569 [ + - ]: 1178 : ret = status ? -1 : 0;
570 : : out:
571 [ - + ]: 1178 : if (sigprocmask(SIG_SETMASK, &oldmask, NULL) == -1) {
572 : 0 : pr_perror("Can not unset mask of blocked signals");
573 : 0 : BUG();
574 : : }
575 : :
576 : 1178 : return ret;
577 : : }
578 : :
579 : 896 : int cr_daemon(int nochdir, int noclose)
580 : : {
581 : : int pid;
582 : :
583 : 896 : pid = fork();
584 [ - + ]: 1792 : if (pid < 0) {
585 : 0 : pr_perror("Can't fork");
586 : 0 : return -1;
587 : : }
588 : :
589 [ + + ]: 1792 : if (pid > 0)
590 : : return pid;
591 : :
592 : 896 : setsid();
593 [ - + ]: 896 : if (!nochdir)
594 [ # # ]: 0 : if (chdir("/") == -1)
595 : 0 : pr_perror("Can't change directory");
596 [ + - ]: 896 : if (!noclose) {
597 : : int fd;
598 : :
599 : : fd = open("/dev/null", O_RDWR);
600 [ - + ]: 896 : if (fd < 0) {
601 : 0 : pr_perror("Can't open /dev/null");
602 : 0 : return -1;
603 : : }
604 : 896 : dup2(fd, 0);
605 : 896 : dup2(fd, 1);
606 : 896 : dup2(fd, 2);
607 : 896 : close(fd);
608 : : }
609 : :
610 : : return 0;
611 : : }
612 : :
613 : 2 : int is_root_user()
614 : : {
615 [ - + ]: 2 : if (geteuid() != 0) {
616 : 0 : pr_err("You need to be root to run this command\n");
617 : 0 : return 0;
618 : : }
619 : :
620 : : return 1;
621 : : }
622 : :
623 : 4596 : int vaddr_to_pfn(unsigned long vaddr, u64 *pfn)
624 : : {
625 : : int fd, ret = -1;
626 : : off_t off;
627 : :
628 [ - + ]: 4596 : fd = open_proc(getpid(), "pagemap");
629 [ + - ]: 4596 : if (fd < 0)
630 : : return -1;
631 : :
632 : 4596 : off = (vaddr / PAGE_SIZE) * sizeof(u64);
633 [ - + ]: 4596 : if (lseek(fd, off, SEEK_SET) != off) {
634 : 0 : pr_perror("Failed to seek address %lx\n", vaddr);
635 : 0 : goto out;
636 : : }
637 : :
638 : 4596 : ret = read(fd, pfn, sizeof(*pfn));
639 [ - + ]: 4596 : if (ret != sizeof(*pfn)) {
640 : 0 : pr_perror("Can't read pme for pid %d", getpid());
641 : : ret = -1;
642 : : } else {
643 : 4596 : *pfn &= PME_PFRAME_MASK;
644 : : ret = 0;
645 : : }
646 : : out:
647 : 4596 : close(fd);
648 : 4596 : return ret;
649 : : }
650 : :
651 : : /*
652 : : * Note since VMA_AREA_NONE = 0 we can skip assignment
653 : : * here and simply rely on xzalloc
654 : : */
655 : 230799 : struct vma_area *alloc_vma_area(void)
656 : : {
657 : : struct vma_area *p;
658 : :
659 [ - + ]: 230799 : p = xzalloc(sizeof(*p) + sizeof(VmaEntry));
660 [ + - ]: 230799 : if (p) {
661 : 230799 : p->e = (VmaEntry *)(p + 1);
662 : 230799 : vma_entry__init(p->e);
663 : 230799 : p->vm_file_fd = -1;
664 : 230799 : p->e->fd = -1;
665 : : }
666 : :
667 : 230799 : return p;
668 : : }
|