9
9
#include <linux/kasan-checks.h>
10
10
#include <linux/mm_types.h>
11
11
#include <linux/string.h>
12
+ #include <linux/mmap_lock.h>
12
13
#include <asm/asm.h>
13
14
#include <asm/page.h>
14
15
#include <asm/smap.h>
@@ -30,26 +31,44 @@ static inline bool pagefault_disabled(void);
30
31
* Magic with the 'sign' allows to untag userspace pointer without any branches
31
32
* while leaving kernel addresses intact.
32
33
*/
33
- static inline unsigned long __untagged_addr (unsigned long addr ,
34
- unsigned long mask )
34
+ static inline unsigned long __untagged_addr (unsigned long addr )
35
35
{
36
- long sign = addr >> 63 ;
36
+ long sign ;
37
+
38
+ /*
39
+ * Refer tlbstate_untag_mask directly to avoid RIP-relative relocation
40
+ * in alternative instructions. The relocation gets wrong when gets
41
+ * copied to the target place.
42
+ */
43
+ asm (ALTERNATIVE ("" ,
44
+ "sar $63, %[sign]\n\t" /* user_ptr ? 0 : -1UL */
45
+ "or %%gs:tlbstate_untag_mask, %[sign]\n\t"
46
+ "and %[sign], %[addr]\n\t" , X86_FEATURE_LAM )
47
+ : [addr ] "+r" (addr ), [sign ] "= r " (sign)
48
+ : " m " (tlbstate_untag_mask), " [sign ]" (addr));
37
49
38
- addr &= mask | sign ;
39
50
return addr ;
40
51
}
41
52
42
53
#define untagged_addr (addr ) ({ \
43
- u64 __addr = (__force u64)(addr); \
44
- __addr = __untagged_addr(__addr, current_untag_mask()); \
45
- (__force __typeof__(addr))__addr; \
54
+ unsigned long __addr = (__force unsigned long)(addr); \
55
+ (__force __typeof__(addr))__untagged_addr(__addr); \
46
56
})
47
57
58
+ static inline unsigned long __untagged_addr_remote (struct mm_struct * mm ,
59
+ unsigned long addr )
60
+ {
61
+ long sign = addr >> 63 ;
62
+
63
+ mmap_assert_locked (mm );
64
+ addr &= (mm )-> context .untag_mask | sign ;
65
+
66
+ return addr ;
67
+ }
68
+
48
69
#define untagged_addr_remote (mm , addr ) ({ \
49
- u64 __addr = (__force u64)(addr); \
50
- mmap_assert_locked(mm); \
51
- __addr = __untagged_addr(__addr, (mm)->context.untag_mask); \
52
- (__force __typeof__(addr))__addr; \
70
+ unsigned long __addr = (__force unsigned long)(addr); \
71
+ (__force __typeof__(addr))__untagged_addr_remote(mm, __addr); \
53
72
})
54
73
55
74
#else
0 commit comments