skipped 329 lines 330 330 } 331 331 332 332 #ifdef CONFIG_COMPAT 333 - static void exit_on(int ret, int err_fd, char *reason) 334 - { 335 - if (ret) { 336 - syscall(__NR_write, err_fd, reason, strlen(reason)); 337 - syscall(__NR_exit, ret); 338 - } 339 - } 340 - /* 341 - * Because of restrictions of ARCH_MAP_VDSO_* API, new vDSO blob 342 - * can be mapped only if there is no vDSO blob present for a process. 343 - * This is a helper process, it unmaps 64-bit vDSO and maps 32-bit vDSO. 344 - * Then it copies vDSO blob to shared with CRIU mapping. 345 - * 346 - * The purpose is to fill compat vdso's symtable (vdso_compat_rt). 347 - * It's an optimization to fill symtable only once at CRIU restore 348 - * for all restored tasks. 349 - * 350 - * @native - 64-bit vDSO blob (for easy unmap) 351 - * @pipe_fd - to get size of compat blob from /proc/.../maps 352 - * @err_fd - to print error messages 353 - * @vdso_buf, buf_size - shared with CRIU buffer 354 - * 355 - * WARN: This helper shouldn't call pr_err() or any syscall with 356 - * Glibc's wrapper function - it may very likely blow up. 357 - */ 358 - static void compat_vdso_helper(struct vdso_symtable *native, int pipe_fd, 359 - int err_fd, void *vdso_buf, size_t buf_size) 360 - { 361 - size_t vma_size; 362 - void *vdso_addr; 363 - long vdso_size; 364 - long ret; 365 - 366 - vma_size = native->vma_end - native->vma_start; 367 - ret = syscall(__NR_munmap, native->vma_start, vma_size); 368 - exit_on(ret, err_fd, "Error: Failed to unmap native vdso\n"); 369 - 370 - vma_size = native->vvar_end - native->vvar_start; 371 - ret = syscall(__NR_munmap, native->vvar_start, vma_size); 372 - exit_on(ret, err_fd, "Error: Failed to unmap native vvar\n"); 373 - 374 - ret = syscall(__NR_arch_prctl, ARCH_MAP_VDSO_32, native->vma_start); 375 - if (ret < 0) 376 - exit_on(ret, err_fd, "Error: ARCH_MAP_VDSO failed\n"); 377 - 378 - vdso_size = ret; 379 - if (vdso_size > buf_size) 380 - exit_on(-1, err_fd, "Error: Compatible vdso's size is bigger than reserved buf\n"); 381 - 382 - /* Stop so CRIU could parse smaps to find 32-bit vdso's size */ 383 - ret = syscall(__NR_kill, syscall(__NR_getpid), SIGSTOP); 384 - exit_on(ret, err_fd, "Error: Can't stop myself with SIGSTOP (having a good time)\n"); 385 - 386 - ret = syscall(__NR_read, pipe_fd, &vdso_addr, sizeof(void *)); 387 - if (ret != sizeof(void *)) 388 - exit_on(-1, err_fd, "Error: Can't read size of mmaped vdso from pipe\n"); 389 - 390 - memcpy(vdso_buf, vdso_addr, vdso_size); 391 - 392 - syscall(__NR_exit, 0); 393 - } 394 - 395 333 static int vdso_mmap_compat(struct vdso_symtable *native, 396 334 struct vdso_symtable *compat, void *vdso_buf, size_t buf_size) 397 335 { skipped 105 lines 503 441 return ret; 504 442 } 505 443 506 - #else 444 + #else /* CONFIG_COMPAT */ 507 445 static int vdso_fill_compat_symtable(struct vdso_symtable *native, 508 446 struct vdso_symtable *compat) 509 447 { 510 448 return 0; 511 449 } 512 - #endif 450 + #endif /* CONFIG_COMPAT */ 513 451 514 452 int vdso_init(void) 515 453 { skipped 18 lines