Commit ac8777c
committed
Merge patch series "eventpoll: fix ep_remove() UAF and follow-up cleanup"
Christian Brauner <[email protected]> says:
ep_remove() (via __ep_remove_file()) cleared file->f_ep under
file->f_lock but then kept using @file in the same critical section:
is_file_epoll(), hlist_del_rcu() through the head, spin_unlock. A
concurrent __fput() on the watched eventpoll caught the transient
NULL in eventpoll_release()'s lockless fast path, skipped
eventpoll_release_file() entirely, and ran to ep_eventpoll_release()
-> ep_clear_and_put() -> ep_free(). That kfree()s the struct
eventpoll whose embedded ->refs hlist_head is exactly where
epi->fllink.pprev points and the subsequent hlist_del_rcu()'s
"*pprev = next" scribbles into freed kmalloc-192 memory, which is
the slab-use-after-free KASAN caught.
struct file is SLAB_TYPESAFE_BY_RCU on top of that so the same window
also lets the slot recycle while ep_remove() is still nominally
inside file->f_lock. The upshot is an attacker-influencable
kmem_cache_free() against the wrong slab cache.
The comment on eventpoll_release()'s fast path - "False positives
simply cannot happen because the file in on the way to be removed
and nobody ( but eventpoll ) has still a reference to this file" -
was itself the wrong invariant this race exploits.
The fix pins @file via epi_fget() at the top of ep_remove() and
gates the f_ep clear / hlist_del_rcu() on the pin succeeding. With
the pin held __fput() cannot start which transitively keeps the
watched struct eventpoll alive across the critical section and also
prevents the struct file slot from recycling. Both UAFs are closed.
If the pin fails __fput() is already in flight on @file. Because we
bail before clearing f_ep that path takes eventpoll_release()'s slow
path into eventpoll_release_file() which blocks on ep->mtx until
ep_clear_and_put() drops it and then cleans up the orphaned epi. The
bailed epi's share of ep->refcount stays intact so
ep_clear_and_put()'s trailing ep_refcount_dec_and_test() cannot free
the eventpoll out from under eventpoll_release_file().
With epi_fget() now gating every ep_remove() call the epi->dying
flag becomes vestigial. epi->dying == true always coincides with
file_ref_get() == false because __fput() is reachable only once the
refcount hits zero and the refcount is monotone there. The last
patch drops the flag and leaves a single coordination mechanism
instead of two.
* patches from https://patch.msgid.link/[email protected]:
eventpoll: drop vestigial epi->dying flag
eventpoll: drop dead bool return from __ep_remove_epi()
eventpoll: refresh eventpoll_release() fast-path comment
eventpoll: move f_lock acquisition into __ep_remove_file()
eventpoll: fix ep_remove struct eventpoll / struct file UAF
eventpoll: move epi_fget() up
eventpoll: rename ep_remove_safe() back to ep_remove()
eventpoll: kill __ep_remove()
eventpoll: split __ep_remove()
eventpoll: use hlist_is_singular_node() in __ep_remove()
Link: https://patch.msgid.link/[email protected]
Signed-off-by: Christian Brauner <[email protected]>2 files changed
Lines changed: 88 additions & 86 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
148 | 148 | | |
149 | 149 | | |
150 | 150 | | |
151 | | - | |
152 | | - | |
153 | | - | |
154 | | - | |
155 | | - | |
156 | | - | |
157 | | - | |
158 | 151 | | |
159 | 152 | | |
160 | 153 | | |
| |||
220 | 213 | | |
221 | 214 | | |
222 | 215 | | |
223 | | - | |
224 | | - | |
225 | | - | |
226 | | - | |
| 216 | + | |
227 | 217 | | |
228 | 218 | | |
229 | 219 | | |
| |||
827 | 817 | | |
828 | 818 | | |
829 | 819 | | |
830 | | - | |
831 | | - | |
832 | | - | |
833 | | - | |
834 | | - | |
835 | | - | |
| 820 | + | |
| 821 | + | |
| 822 | + | |
| 823 | + | |
| 824 | + | |
| 825 | + | |
| 826 | + | |
| 827 | + | |
| 828 | + | |
| 829 | + | |
| 830 | + | |
| 831 | + | |
| 832 | + | |
| 833 | + | |
| 834 | + | |
| 835 | + | |
836 | 836 | | |
837 | | - | |
| 837 | + | |
838 | 838 | | |
839 | | - | |
840 | | - | |
841 | | - | |
| 839 | + | |
842 | 840 | | |
843 | | - | |
| 841 | + | |
| 842 | + | |
| 843 | + | |
| 844 | + | |
| 845 | + | |
844 | 846 | | |
845 | | - | |
846 | | - | |
847 | | - | |
848 | | - | |
| 847 | + | |
| 848 | + | |
| 849 | + | |
| 850 | + | |
| 851 | + | |
| 852 | + | |
| 853 | + | |
| 854 | + | |
849 | 855 | | |
850 | | - | |
851 | | - | |
852 | | - | |
853 | | - | |
854 | | - | |
855 | | - | |
| 856 | + | |
856 | 857 | | |
857 | | - | |
| 858 | + | |
858 | 859 | | |
859 | | - | |
| 860 | + | |
860 | 861 | | |
861 | 862 | | |
862 | 863 | | |
| |||
869 | 870 | | |
870 | 871 | | |
871 | 872 | | |
| 873 | + | |
| 874 | + | |
| 875 | + | |
| 876 | + | |
| 877 | + | |
872 | 878 | | |
873 | 879 | | |
874 | 880 | | |
| |||
888 | 894 | | |
889 | 895 | | |
890 | 896 | | |
891 | | - | |
892 | 897 | | |
893 | 898 | | |
894 | 899 | | |
895 | 900 | | |
896 | 901 | | |
897 | | - | |
| 902 | + | |
898 | 903 | | |
899 | | - | |
900 | | - | |
| 904 | + | |
| 905 | + | |
| 906 | + | |
| 907 | + | |
| 908 | + | |
| 909 | + | |
| 910 | + | |
| 911 | + | |
| 912 | + | |
| 913 | + | |
| 914 | + | |
| 915 | + | |
| 916 | + | |
| 917 | + | |
| 918 | + | |
| 919 | + | |
| 920 | + | |
| 921 | + | |
| 922 | + | |
901 | 923 | | |
902 | 924 | | |
903 | 925 | | |
| |||
923 | 945 | | |
924 | 946 | | |
925 | 947 | | |
926 | | - | |
| 948 | + | |
927 | 949 | | |
928 | 950 | | |
929 | 951 | | |
| |||
932 | 954 | | |
933 | 955 | | |
934 | 956 | | |
935 | | - | |
| 957 | + | |
936 | 958 | | |
937 | 959 | | |
938 | 960 | | |
| |||
1012 | 1034 | | |
1013 | 1035 | | |
1014 | 1036 | | |
1015 | | - | |
1016 | | - | |
1017 | | - | |
1018 | | - | |
1019 | | - | |
1020 | | - | |
1021 | | - | |
1022 | | - | |
1023 | | - | |
1024 | | - | |
1025 | | - | |
1026 | | - | |
1027 | | - | |
1028 | | - | |
1029 | | - | |
1030 | | - | |
1031 | | - | |
1032 | | - | |
1033 | | - | |
1034 | | - | |
1035 | | - | |
1036 | | - | |
1037 | | - | |
1038 | | - | |
1039 | | - | |
1040 | | - | |
1041 | | - | |
1042 | | - | |
1043 | 1037 | | |
1044 | 1038 | | |
1045 | 1039 | | |
| |||
1117 | 1111 | | |
1118 | 1112 | | |
1119 | 1113 | | |
1120 | | - | |
1121 | 1114 | | |
1122 | 1115 | | |
1123 | | - | |
1124 | | - | |
1125 | | - | |
| 1116 | + | |
| 1117 | + | |
| 1118 | + | |
| 1119 | + | |
1126 | 1120 | | |
1127 | 1121 | | |
1128 | 1122 | | |
1129 | 1123 | | |
1130 | 1124 | | |
1131 | | - | |
1132 | 1125 | | |
1133 | 1126 | | |
1134 | 1127 | | |
| |||
1137 | 1130 | | |
1138 | 1131 | | |
1139 | 1132 | | |
1140 | | - | |
| 1133 | + | |
| 1134 | + | |
| 1135 | + | |
| 1136 | + | |
| 1137 | + | |
| 1138 | + | |
1141 | 1139 | | |
1142 | 1140 | | |
1143 | | - | |
| 1141 | + | |
1144 | 1142 | | |
1145 | 1143 | | |
1146 | 1144 | | |
| |||
1619 | 1617 | | |
1620 | 1618 | | |
1621 | 1619 | | |
1622 | | - | |
| 1620 | + | |
1623 | 1621 | | |
1624 | 1622 | | |
1625 | 1623 | | |
1626 | 1624 | | |
1627 | 1625 | | |
1628 | 1626 | | |
1629 | | - | |
| 1627 | + | |
1630 | 1628 | | |
1631 | 1629 | | |
1632 | 1630 | | |
1633 | 1631 | | |
1634 | 1632 | | |
1635 | 1633 | | |
1636 | | - | |
| 1634 | + | |
1637 | 1635 | | |
1638 | 1636 | | |
1639 | 1637 | | |
| |||
1657 | 1655 | | |
1658 | 1656 | | |
1659 | 1657 | | |
1660 | | - | |
| 1658 | + | |
1661 | 1659 | | |
1662 | 1660 | | |
1663 | 1661 | | |
| |||
2352 | 2350 | | |
2353 | 2351 | | |
2354 | 2352 | | |
2355 | | - | |
| 2353 | + | |
2356 | 2354 | | |
2357 | 2355 | | |
2358 | 2356 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
39 | 39 | | |
40 | 40 | | |
41 | 41 | | |
42 | | - | |
43 | | - | |
44 | | - | |
45 | | - | |
46 | | - | |
47 | | - | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
48 | 52 | | |
49 | 53 | | |
50 | 54 | | |
| |||
0 commit comments