| 1543 | } |
| 1544 | |
| 1545 | static int |
| 1546 | core_output(char *base, size_t len, off_t offset, struct coredump_params *p, |
| 1547 | void *tmpbuf) |
| 1548 | { |
| 1549 | vm_map_t map; |
| 1550 | struct mount *mp; |
| 1551 | size_t resid, runlen; |
| 1552 | int error; |
| 1553 | bool success; |
| 1554 | |
| 1555 | KASSERT((uintptr_t)base % PAGE_SIZE == 0, |
| 1556 | ("%s: user address %p is not page-aligned", __func__, base)); |
| 1557 | |
| 1558 | if (p->comp != NULL) |
| 1559 | return (compress_chunk(p, base, tmpbuf, len)); |
| 1560 | |
| 1561 | map = &p->td->td_proc->p_vmspace->vm_map; |
| 1562 | for (; len > 0; base += runlen, offset += runlen, len -= runlen) { |
| 1563 | /* |
| 1564 | * Attempt to page in all virtual pages in the range. If a |
| 1565 | * virtual page is not backed by the pager, it is represented as |
| 1566 | * a hole in the file. This can occur with zero-filled |
| 1567 | * anonymous memory or truncated files, for example. |
| 1568 | */ |
| 1569 | for (runlen = 0; runlen < len; runlen += PAGE_SIZE) { |
| 1570 | error = vm_fault(map, (uintptr_t)base + runlen, |
| 1571 | VM_PROT_READ, VM_FAULT_NOFILL, NULL); |
| 1572 | if (runlen == 0) |
| 1573 | success = error == KERN_SUCCESS; |
| 1574 | else if ((error == KERN_SUCCESS) != success) |
| 1575 | break; |
| 1576 | } |
| 1577 | |
| 1578 | if (success) { |
| 1579 | error = core_write(p, base, runlen, offset, |
| 1580 | UIO_USERSPACE, &resid); |
| 1581 | if (error != 0) { |
| 1582 | if (error != EFAULT) |
| 1583 | break; |
| 1584 | |
| 1585 | /* |
| 1586 | * EFAULT may be returned if the user mapping |
| 1587 | * could not be accessed, e.g., because a mapped |
| 1588 | * file has been truncated. Skip the page if no |
| 1589 | * progress was made, to protect against a |
| 1590 | * hypothetical scenario where vm_fault() was |
| 1591 | * successful but core_write() returns EFAULT |
| 1592 | * anyway. |
| 1593 | */ |
| 1594 | runlen -= resid; |
| 1595 | if (runlen == 0) { |
| 1596 | success = false; |
| 1597 | runlen = PAGE_SIZE; |
| 1598 | } |
| 1599 | } |
| 1600 | } |
| 1601 | if (!success) { |
| 1602 | error = vn_start_write(p->vp, &mp, V_WAIT); |
no test coverage detected