Skip to content

Commit d2b73ce

Browse files
hcahcaAlexander Gordeev
authored andcommitted
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 <[email protected]> Signed-off-by: Heiko Carstens <[email protected]> Signed-off-by: Alexander Gordeev <[email protected]>
1 parent b13c190 commit d2b73ce

File tree

1 file changed

+11
-10
lines changed

1 file changed

+11
-10
lines changed

arch/s390/lib/uaccess.c

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
* Gerald Schaefer ([email protected])
99
*/
1010

11+
#include <linux/kprobes.h>
1112
#include <linux/uaccess.h>
1213
#include <linux/export.h>
1314
#include <linux/mm.h>
@@ -149,8 +150,8 @@ EXPORT_SYMBOL(_copy_to_user_key);
149150

150151
#define CMPXCHG_USER_KEY_MAX_LOOPS 128
151152

152-
int __cmpxchg_user_key1(unsigned long address, unsigned char *uval,
153-
unsigned char old, unsigned char new, unsigned long key)
153+
int __kprobes __cmpxchg_user_key1(unsigned long address, unsigned char *uval,
154+
unsigned char old, unsigned char new, unsigned long key)
154155
{
155156
unsigned int prev, shift, mask, _old, _new;
156157
unsigned long count;
@@ -208,8 +209,8 @@ int __cmpxchg_user_key1(unsigned long address, unsigned char *uval,
208209
}
209210
EXPORT_SYMBOL(__cmpxchg_user_key1);
210211

211-
int __cmpxchg_user_key2(unsigned long address, unsigned short *uval,
212-
unsigned short old, unsigned short new, unsigned long key)
212+
int __kprobes __cmpxchg_user_key2(unsigned long address, unsigned short *uval,
213+
unsigned short old, unsigned short new, unsigned long key)
213214
{
214215
unsigned int prev, shift, mask, _old, _new;
215216
unsigned long count;
@@ -267,8 +268,8 @@ int __cmpxchg_user_key2(unsigned long address, unsigned short *uval,
267268
}
268269
EXPORT_SYMBOL(__cmpxchg_user_key2);
269270

270-
int __cmpxchg_user_key4(unsigned long address, unsigned int *uval,
271-
unsigned int old, unsigned int new, unsigned long key)
271+
int __kprobes __cmpxchg_user_key4(unsigned long address, unsigned int *uval,
272+
unsigned int old, unsigned int new, unsigned long key)
272273
{
273274
unsigned int prev = old;
274275
bool sacf_flag;
@@ -299,8 +300,8 @@ int __cmpxchg_user_key4(unsigned long address, unsigned int *uval,
299300
}
300301
EXPORT_SYMBOL(__cmpxchg_user_key4);
301302

302-
int __cmpxchg_user_key8(unsigned long address, unsigned long *uval,
303-
unsigned long old, unsigned long new, unsigned long key)
303+
int __kprobes __cmpxchg_user_key8(unsigned long address, unsigned long *uval,
304+
unsigned long old, unsigned long new, unsigned long key)
304305
{
305306
unsigned long prev = old;
306307
bool sacf_flag;
@@ -331,8 +332,8 @@ int __cmpxchg_user_key8(unsigned long address, unsigned long *uval,
331332
}
332333
EXPORT_SYMBOL(__cmpxchg_user_key8);
333334

334-
int __cmpxchg_user_key16(unsigned long address, __uint128_t *uval,
335-
__uint128_t old, __uint128_t new, unsigned long key)
335+
int __kprobes __cmpxchg_user_key16(unsigned long address, __uint128_t *uval,
336+
__uint128_t old, __uint128_t new, unsigned long key)
336337
{
337338
__uint128_t prev = old;
338339
bool sacf_flag;

0 commit comments

Comments
 (0)