kup.h (4899B)
1/* SPDX-License-Identifier: GPL-2.0 */ 2#ifndef _ASM_POWERPC_KUP_H_ 3#define _ASM_POWERPC_KUP_H_ 4 5#define KUAP_READ 1 6#define KUAP_WRITE 2 7#define KUAP_READ_WRITE (KUAP_READ | KUAP_WRITE) 8 9#ifdef CONFIG_PPC_BOOK3S_64 10#include <asm/book3s/64/kup.h> 11#endif 12 13#ifdef CONFIG_PPC_8xx 14#include <asm/nohash/32/kup-8xx.h> 15#endif 16 17#ifdef CONFIG_BOOKE_OR_40x 18#include <asm/nohash/kup-booke.h> 19#endif 20 21#ifdef CONFIG_PPC_BOOK3S_32 22#include <asm/book3s/32/kup.h> 23#endif 24 25#ifdef __ASSEMBLY__ 26#ifndef CONFIG_PPC_KUAP 27.macro kuap_check_amr gpr1, gpr2 28.endm 29 30#endif 31 32#else /* !__ASSEMBLY__ */ 33 34extern bool disable_kuep; 35extern bool disable_kuap; 36 37#include <linux/pgtable.h> 38 39void setup_kup(void); 40void setup_kuep(bool disabled); 41 42#ifdef CONFIG_PPC_KUAP 43void setup_kuap(bool disabled); 44#else 45static inline void setup_kuap(bool disabled) { } 46 47static __always_inline bool kuap_is_disabled(void) { return true; } 48 49static inline bool 50__bad_kuap_fault(struct pt_regs *regs, unsigned long address, bool is_write) 51{ 52 return false; 53} 54 55static inline void __kuap_lock(void) { } 56static inline void __kuap_save_and_lock(struct pt_regs *regs) { } 57static inline void kuap_user_restore(struct pt_regs *regs) { } 58static inline void __kuap_kernel_restore(struct pt_regs *regs, unsigned long amr) { } 59 60static inline unsigned long __kuap_get_and_assert_locked(void) 61{ 62 return 0; 63} 64 65/* 66 * book3s/64/kup-radix.h defines these functions for the !KUAP case to flush 67 * the L1D cache after user accesses. Only include the empty stubs for other 68 * platforms. 69 */ 70#ifndef CONFIG_PPC_BOOK3S_64 71static inline void __allow_user_access(void __user *to, const void __user *from, 72 unsigned long size, unsigned long dir) { } 73static inline void __prevent_user_access(unsigned long dir) { } 74static inline unsigned long __prevent_user_access_return(void) { return 0UL; } 75static inline void __restore_user_access(unsigned long flags) { } 76#endif /* CONFIG_PPC_BOOK3S_64 */ 77#endif /* CONFIG_PPC_KUAP */ 78 79static __always_inline bool 80bad_kuap_fault(struct pt_regs *regs, unsigned long address, bool is_write) 81{ 82 if (kuap_is_disabled()) 83 return false; 84 85 return __bad_kuap_fault(regs, address, is_write); 86} 87 88static __always_inline void kuap_assert_locked(void) 89{ 90 if (kuap_is_disabled()) 91 return; 92 93 if (IS_ENABLED(CONFIG_PPC_KUAP_DEBUG)) 94 __kuap_get_and_assert_locked(); 95} 96 97static __always_inline void kuap_lock(void) 98{ 99 if (kuap_is_disabled()) 100 return; 101 102 __kuap_lock(); 103} 104 105static __always_inline void kuap_save_and_lock(struct pt_regs *regs) 106{ 107 if (kuap_is_disabled()) 108 return; 109 110 __kuap_save_and_lock(regs); 111} 112 113static __always_inline void kuap_kernel_restore(struct pt_regs *regs, unsigned long amr) 114{ 115 if (kuap_is_disabled()) 116 return; 117 118 __kuap_kernel_restore(regs, amr); 119} 120 121static __always_inline unsigned long kuap_get_and_assert_locked(void) 122{ 123 if (kuap_is_disabled()) 124 return 0; 125 126 return __kuap_get_and_assert_locked(); 127} 128 129#ifndef CONFIG_PPC_BOOK3S_64 130static __always_inline void allow_user_access(void __user *to, const void __user *from, 131 unsigned long size, unsigned long dir) 132{ 133 if (kuap_is_disabled()) 134 return; 135 136 __allow_user_access(to, from, size, dir); 137} 138 139static __always_inline void prevent_user_access(unsigned long dir) 140{ 141 if (kuap_is_disabled()) 142 return; 143 144 __prevent_user_access(dir); 145} 146 147static __always_inline unsigned long prevent_user_access_return(void) 148{ 149 if (kuap_is_disabled()) 150 return 0; 151 152 return __prevent_user_access_return(); 153} 154 155static __always_inline void restore_user_access(unsigned long flags) 156{ 157 if (kuap_is_disabled()) 158 return; 159 160 __restore_user_access(flags); 161} 162#endif /* CONFIG_PPC_BOOK3S_64 */ 163 164static __always_inline void allow_read_from_user(const void __user *from, unsigned long size) 165{ 166 barrier_nospec(); 167 allow_user_access(NULL, from, size, KUAP_READ); 168} 169 170static __always_inline void allow_write_to_user(void __user *to, unsigned long size) 171{ 172 allow_user_access(to, NULL, size, KUAP_WRITE); 173} 174 175static __always_inline void allow_read_write_user(void __user *to, const void __user *from, 176 unsigned long size) 177{ 178 barrier_nospec(); 179 allow_user_access(to, from, size, KUAP_READ_WRITE); 180} 181 182static __always_inline void prevent_read_from_user(const void __user *from, unsigned long size) 183{ 184 prevent_user_access(KUAP_READ); 185} 186 187static __always_inline void prevent_write_to_user(void __user *to, unsigned long size) 188{ 189 prevent_user_access(KUAP_WRITE); 190} 191 192static __always_inline void prevent_read_write_user(void __user *to, const void __user *from, 193 unsigned long size) 194{ 195 prevent_user_access(KUAP_READ_WRITE); 196} 197 198static __always_inline void prevent_current_access_user(void) 199{ 200 prevent_user_access(KUAP_READ_WRITE); 201} 202 203static __always_inline void prevent_current_read_from_user(void) 204{ 205 prevent_user_access(KUAP_READ); 206} 207 208static __always_inline void prevent_current_write_to_user(void) 209{ 210 prevent_user_access(KUAP_WRITE); 211} 212 213#endif /* !__ASSEMBLY__ */ 214 215#endif /* _ASM_POWERPC_KUAP_H_ */