Commit 631426b
mm/madvise: make MADV_POPULATE_(READ|WRITE) handle VM_FAULT_RETRY properly
Darrick reports that in some cases where pread() would fail with -EIO and
mmap()+access would generate a SIGBUS signal, MADV_POPULATE_READ /
MADV_POPULATE_WRITE will keep retrying forever and not fail with -EFAULT.
While the madvise() call can be interrupted by a signal, this is not the
desired behavior. MADV_POPULATE_READ / MADV_POPULATE_WRITE should behave
like page faults in that case: fail and not retry forever.
A reproducer can be found at [1].
The reason is that __get_user_pages(), as called by
faultin_vma_page_range(), will not handle VM_FAULT_RETRY in a proper way:
it will simply return 0 when VM_FAULT_RETRY happened, making
madvise_populate()->faultin_vma_page_range() retry again and again, never
setting FOLL_TRIED->FAULT_FLAG_TRIED for __get_user_pages().
__get_user_pages_locked() does what we want, but duplicating that logic in
faultin_vma_page_range() feels wrong.
So let's use __get_user_pages_locked() instead, that will detect
VM_FAULT_RETRY and set FOLL_TRIED when retrying, making the fault handler
return VM_FAULT_SIGBUS (VM_FAULT_ERROR) at some point, propagating -EFAULT
from faultin_page() to __get_user_pages(), all the way to
madvise_populate().
But, there is an issue: __get_user_pages_locked() will end up re-taking
the MM lock and then __get_user_pages() will do another VMA lookup. In
the meantime, the VMA layout could have changed and we'd fail with
different error codes than we'd want to.
As __get_user_pages() will currently do a new VMA lookup either way, let
it do the VMA handling in a different way, controlled by a new
FOLL_MADV_POPULATE flag, effectively moving these checks from
madvise_populate() + faultin_page_range() in there.
With this change, Darricks reproducer properly fails with -EFAULT, as
documented for MADV_POPULATE_READ / MADV_POPULATE_WRITE.
[1] https://lore.kernel.org/all/20240313171936.GN1927156@frogsfrogsfrogs/
Link: https://lkml.kernel.org/r/20240314161300.382526-1-david@redhat.com
Link: https://lkml.kernel.org/r/20240314161300.382526-2-david@redhat.com
Fixes: 4ca9b38 ("mm/madvise: introduce MADV_POPULATE_(READ|WRITE) to prefault page tables")
Signed-off-by: David Hildenbrand <david@redhat.com>
Reported-by: Darrick J. Wong <djwong@kernel.org>
Closes: https://lore.kernel.org/all/20240311223815.GW1927156@frogsfrogsfrogs/
Cc: Darrick J. Wong <djwong@kernel.org>
Cc: Hugh Dickins <hughd@google.com>
Cc: Jason Gunthorpe <jgg@nvidia.com>
Cc: John Hubbard <jhubbard@nvidia.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>1 parent 0bbac3f commit 631426b
3 files changed
Lines changed: 40 additions & 41 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1206 | 1206 | | |
1207 | 1207 | | |
1208 | 1208 | | |
| 1209 | + | |
| 1210 | + | |
| 1211 | + | |
| 1212 | + | |
| 1213 | + | |
| 1214 | + | |
| 1215 | + | |
| 1216 | + | |
| 1217 | + | |
| 1218 | + | |
| 1219 | + | |
| 1220 | + | |
| 1221 | + | |
| 1222 | + | |
| 1223 | + | |
| 1224 | + | |
1209 | 1225 | | |
1210 | 1226 | | |
1211 | 1227 | | |
| |||
1685 | 1701 | | |
1686 | 1702 | | |
1687 | 1703 | | |
1688 | | - | |
1689 | | - | |
| 1704 | + | |
| 1705 | + | |
1690 | 1706 | | |
1691 | 1707 | | |
1692 | 1708 | | |
1693 | | - | |
| 1709 | + | |
1694 | 1710 | | |
1695 | 1711 | | |
1696 | 1712 | | |
1697 | 1713 | | |
1698 | 1714 | | |
1699 | | - | |
1700 | | - | |
| 1715 | + | |
| 1716 | + | |
| 1717 | + | |
| 1718 | + | |
1701 | 1719 | | |
1702 | | - | |
1703 | | - | |
| 1720 | + | |
| 1721 | + | |
| 1722 | + | |
1704 | 1723 | | |
1705 | | - | |
1706 | | - | |
| 1724 | + | |
| 1725 | + | |
1707 | 1726 | | |
1708 | | - | |
1709 | 1727 | | |
1710 | 1728 | | |
1711 | 1729 | | |
1712 | 1730 | | |
1713 | 1731 | | |
1714 | 1732 | | |
1715 | | - | |
1716 | | - | |
1717 | 1733 | | |
1718 | 1734 | | |
1719 | 1735 | | |
| |||
1725 | 1741 | | |
1726 | 1742 | | |
1727 | 1743 | | |
1728 | | - | |
| 1744 | + | |
| 1745 | + | |
1729 | 1746 | | |
1730 | 1747 | | |
1731 | 1748 | | |
1732 | | - | |
1733 | | - | |
1734 | | - | |
1735 | | - | |
1736 | | - | |
1737 | | - | |
1738 | | - | |
1739 | | - | |
1740 | | - | |
| 1749 | + | |
| 1750 | + | |
1741 | 1751 | | |
1742 | 1752 | | |
1743 | 1753 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
686 | 686 | | |
687 | 687 | | |
688 | 688 | | |
689 | | - | |
690 | | - | |
691 | | - | |
| 689 | + | |
| 690 | + | |
692 | 691 | | |
693 | 692 | | |
694 | 693 | | |
| |||
1127 | 1126 | | |
1128 | 1127 | | |
1129 | 1128 | | |
| 1129 | + | |
| 1130 | + | |
1130 | 1131 | | |
1131 | 1132 | | |
1132 | 1133 | | |
1133 | | - | |
| 1134 | + | |
| 1135 | + | |
1134 | 1136 | | |
1135 | 1137 | | |
1136 | 1138 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
908 | 908 | | |
909 | 909 | | |
910 | 910 | | |
911 | | - | |
912 | 911 | | |
913 | 912 | | |
914 | 913 | | |
915 | 914 | | |
916 | 915 | | |
917 | 916 | | |
918 | | - | |
919 | | - | |
920 | | - | |
921 | | - | |
922 | | - | |
923 | | - | |
924 | | - | |
925 | | - | |
926 | | - | |
927 | | - | |
928 | | - | |
929 | 917 | | |
930 | | - | |
931 | | - | |
| 918 | + | |
932 | 919 | | |
933 | 920 | | |
934 | 921 | | |
| |||
949 | 936 | | |
950 | 937 | | |
951 | 938 | | |
952 | | - | |
| 939 | + | |
953 | 940 | | |
954 | 941 | | |
955 | 942 | | |
| |||
0 commit comments