aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/lib
diff options
context:
space:
mode:
authorHeiko Carstens <hca@linux.ibm.com>2025-06-16 17:00:32 +0200
committerAlexander Gordeev <agordeev@linux.ibm.com>2025-06-29 13:12:02 +0200
commitd2b73ce90a7141d5aa34a52de82d69fbb68efc30 (patch)
tree1f2f759500a1d4f59a94907375deb19e7933c3ef /arch/s390/lib
parents390/uaccess: Initialize code pages executed with non-default access key (diff)
downloadlinux-d2b73ce90a7141d5aa34a52de82d69fbb68efc30.tar.gz
linux-d2b73ce90a7141d5aa34a52de82d69fbb68efc30.zip
s390/uaccess: Prevent kprobes on cmpxchg_user_key() functions
Code regions within cmpxchg_user_key() functions may be executed with a non-default access key, which may lead to a protection exception if the corresponding page has the fetch-protection bit enabled. There is code in place which initializes the storage keys of such pages when needed. However there is also the possibility of out-of-line execution of such code in case a kprobe is set within such a region. To avoid this problem prevent that any kprobe can be set within the cmpxchg_user_key() functions. Reviewed-by: Claudio Imbrenda <imbrenda@linux.ibm.com> Signed-off-by: Heiko Carstens <hca@linux.ibm.com> Signed-off-by: Alexander Gordeev <agordeev@linux.ibm.com>
Diffstat (limited to 'arch/s390/lib')
-rw-r--r--arch/s390/lib/uaccess.c21
1 files changed, 11 insertions, 10 deletions
diff --git a/arch/s390/lib/uaccess.c b/arch/s390/lib/uaccess.c
index 02359c03b809..750360cce02c 100644
--- a/arch/s390/lib/uaccess.c
+++ b/arch/s390/lib/uaccess.c
@@ -8,6 +8,7 @@
* Gerald Schaefer (gerald.schaefer@de.ibm.com)
*/
+#include <linux/kprobes.h>
#include <linux/uaccess.h>
#include <linux/export.h>
#include <linux/mm.h>
@@ -149,8 +150,8 @@ EXPORT_SYMBOL(_copy_to_user_key);
#define CMPXCHG_USER_KEY_MAX_LOOPS 128
-int __cmpxchg_user_key1(unsigned long address, unsigned char *uval,
- unsigned char old, unsigned char new, unsigned long key)
+int __kprobes __cmpxchg_user_key1(unsigned long address, unsigned char *uval,
+ unsigned char old, unsigned char new, unsigned long key)
{
unsigned int prev, shift, mask, _old, _new;
unsigned long count;
@@ -208,8 +209,8 @@ int __cmpxchg_user_key1(unsigned long address, unsigned char *uval,
}
EXPORT_SYMBOL(__cmpxchg_user_key1);
-int __cmpxchg_user_key2(unsigned long address, unsigned short *uval,
- unsigned short old, unsigned short new, unsigned long key)
+int __kprobes __cmpxchg_user_key2(unsigned long address, unsigned short *uval,
+ unsigned short old, unsigned short new, unsigned long key)
{
unsigned int prev, shift, mask, _old, _new;
unsigned long count;
@@ -267,8 +268,8 @@ int __cmpxchg_user_key2(unsigned long address, unsigned short *uval,
}
EXPORT_SYMBOL(__cmpxchg_user_key2);
-int __cmpxchg_user_key4(unsigned long address, unsigned int *uval,
- unsigned int old, unsigned int new, unsigned long key)
+int __kprobes __cmpxchg_user_key4(unsigned long address, unsigned int *uval,
+ unsigned int old, unsigned int new, unsigned long key)
{
unsigned int prev = old;
bool sacf_flag;
@@ -299,8 +300,8 @@ int __cmpxchg_user_key4(unsigned long address, unsigned int *uval,
}
EXPORT_SYMBOL(__cmpxchg_user_key4);
-int __cmpxchg_user_key8(unsigned long address, unsigned long *uval,
- unsigned long old, unsigned long new, unsigned long key)
+int __kprobes __cmpxchg_user_key8(unsigned long address, unsigned long *uval,
+ unsigned long old, unsigned long new, unsigned long key)
{
unsigned long prev = old;
bool sacf_flag;
@@ -331,8 +332,8 @@ int __cmpxchg_user_key8(unsigned long address, unsigned long *uval,
}
EXPORT_SYMBOL(__cmpxchg_user_key8);
-int __cmpxchg_user_key16(unsigned long address, __uint128_t *uval,
- __uint128_t old, __uint128_t new, unsigned long key)
+int __kprobes __cmpxchg_user_key16(unsigned long address, __uint128_t *uval,
+ __uint128_t old, __uint128_t new, unsigned long key)
{
__uint128_t prev = old;
bool sacf_flag;