[LTP] [PATCH v9 1/3] syscalls/modify_ldt: Add lapi/ldt.h
Martin Doucha
mdoucha@suse.cz
Wed May 7 13:23:53 CEST 2025
Hi,
one more thing for cve-2015-3290 below.
On 29. 04. 25 12:44, Ricardo B. Marlière via ltp wrote:
> From: Ricardo B. Marlière <rbm@suse.com>
>
> Add a wrapper to modify_ldt and a fallback definition to struct user_desc,
> which are needed in a few tests and should be reused.
>
> Reviewed-by: Cyril Hrubis <chrubis@suse.cz>
> Reviewed-by: Andrea Cervesato <andrea.cervesato@suse.com>
> Signed-off-by: Ricardo B. Marlière <rbm@suse.com>
> ---
> include/lapi/ldt.h | 59 +++++++++++++++++++++++++++++++++
> testcases/cve/cve-2015-3290.c | 26 ++-------------
> testcases/cve/cve-2017-17053.c | 6 ++--
> testcases/kernel/syscalls/fork/fork05.c | 5 ++-
> 4 files changed, 65 insertions(+), 31 deletions(-)
>
> diff --git a/include/lapi/ldt.h b/include/lapi/ldt.h
> new file mode 100644
> index 0000000000000000000000000000000000000000..6b5a2d59cb41bfc24eb5ac26c3d47d49fb8ff78f
> --- /dev/null
> +++ b/include/lapi/ldt.h
> @@ -0,0 +1,59 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + * Copyright (c) 2025 SUSE LLC Ricardo B. Marlière <rbm@suse.com>
> + */
> +
> +#ifndef LAPI_LDT_H__
> +#define LAPI_LDT_H__
> +
> +#include "config.h"
> +#include "lapi/syscalls.h"
> +
> +#ifdef HAVE_ASM_LDT_H
> +#include <asm/ldt.h>
> +#else
> +struct user_desc {
> + unsigned int entry_number;
> + unsigned int base_addr;
> + unsigned int limit;
> + unsigned int seg_32bit : 1;
> + unsigned int contents : 2;
> + unsigned int read_exec_only : 1;
> + unsigned int limit_in_pages : 1;
> + unsigned int seg_not_present : 1;
> + unsigned int useable : 1;
> +#ifdef __x86_64__
> + unsigned int lm : 1;
> +#endif /* __x86_64__ */
> +};
> +#endif /* HAVE_ASM_LDT_H */
> +
> +static inline int modify_ldt(int func, const struct user_desc *ptr,
> + unsigned long bytecount)
> +{
> + return tst_syscall(__NR_modify_ldt, func, ptr, bytecount);
> +}
> +
> +static inline int safe_modify_ldt(const char *file, const int lineno, int func,
> + const struct user_desc *ptr,
> + unsigned long bytecount)
> +{
> + int rval;
> +
> + rval = modify_ldt(func, ptr, bytecount);
> + if (rval == -1) {
> + tst_brk_(file, lineno, TBROK | TERRNO,
> + "modify_ldt(%d, %p, %lu)", func, ptr, bytecount);
> + } else if (rval) {
> + tst_brk_(file, lineno, TBROK | TERRNO,
> + "modify_ltd(%d, %p, %lu) invalid retval %i", func, ptr,
> + bytecount, rval);
> + }
> +
> + return rval;
> +}
> +
> +#define SAFE_MODIFY_LDT(func, ptr, bytecount) \
> + safe_modify_ldt(__FILE__, __LINE__, (func), (ptr), (bytecount))
> +
> +#endif /* LAPI_LDT_H__ */
> diff --git a/testcases/cve/cve-2015-3290.c b/testcases/cve/cve-2015-3290.c
> index 63e5d92c91b830cd8066a6a6c329461b72731f32..8ec1d53bbb5a9f3e7761d39855d34f593e118a28 100644
> --- a/testcases/cve/cve-2015-3290.c
> +++ b/testcases/cve/cve-2015-3290.c
> @@ -123,16 +123,14 @@ perhaps unsurprisingly.)
> #include <stdlib.h>
> #include <stdio.h>
> #include <inttypes.h>
> -#include <asm/ldt.h>
> #include <unistd.h>
> -#include <sys/syscall.h>
> #include <setjmp.h>
> #include <signal.h>
> #include <string.h>
> #include <sys/wait.h>
> #include <linux/perf_event.h>
>
> -#include "lapi/syscalls.h"
> +#include "lapi/ldt.h"
> #include "tst_safe_pthread.h"
>
> /* Abstractions for some 32-bit vs 64-bit differences. */
> @@ -199,27 +197,7 @@ static void set_ldt(void)
> .useable = 0
> };
>
> - TEST(tst_syscall(__NR_modify_ldt, 1, &data_desc, sizeof(data_desc)));
> -
> - /*
> - * The kernel intentionally casts modify_ldt() return value
> - * to unsigned int to prevent sign extension to 64 bits. This may
> - * result in syscall() returning the value as is instead of setting
> - * errno and returning -1.
> - */
> - if (TST_RET > 0 && ((int)TST_RET) < 0) {
> - tst_res(TINFO,
> - "WARNING: Libc mishandled modify_ldt() return value");
> - TST_ERR = -(int)TST_RET;
> - TST_RET = -1;
> - }
> -
> - if (TST_RET == -1 && TST_ERR == EINVAL) {
> - tst_brk(TCONF | TTERRNO,
> - "modify_ldt: 16-bit data segments are probably disabled");
There's a TCONF here if modify_ldt() returns EINVAL. SAFE_MODIFY_LDT()
will treat that as failure instead. EINVAL is expected.
> - } else if (TST_RET != 0) {
> - tst_brk(TBROK | TTERRNO, "modify_ldt");
> - }
> + SAFE_MODIFY_LDT(1, &data_desc, sizeof(data_desc));
> }
>
> static void try_corrupt_stack(unsigned short *orig_ss)
> diff --git a/testcases/cve/cve-2017-17053.c b/testcases/cve/cve-2017-17053.c
> index fe7b6d694d6ffbbce863abc1672e03ae5f419df1..ec7a534a6c0104e6688f204d763c31ed7a048201 100644
> --- a/testcases/cve/cve-2017-17053.c
> +++ b/testcases/cve/cve-2017-17053.c
> @@ -17,16 +17,14 @@
> #include "tst_test.h"
>
> #ifdef HAVE_ASM_LDT_H
> -#include <asm/ldt.h>
> #include <pthread.h>
> #include <signal.h>
> #include <stdlib.h>
> -#include <sys/syscall.h>
> #include <sys/wait.h>
> #include <unistd.h>
> #include <stdio.h>
>
> -#include "lapi/syscalls.h"
> +#include "lapi/ldt.h"
>
> #define EXEC_USEC 5000000
>
> @@ -109,7 +107,7 @@ void run_test(void)
> struct user_desc desc = { .entry_number = 8191 };
>
> install_sighandler();
> - syscall(__NR_modify_ldt, 1, &desc, sizeof(desc));
> + SAFE_MODIFY_LDT(1, &desc, sizeof(desc));
>
> for (;;) {
> if (shm->do_exit)
> diff --git a/testcases/kernel/syscalls/fork/fork05.c b/testcases/kernel/syscalls/fork/fork05.c
> index 22edefc3686978fbb9453dffabfcbccb7ea6bb12..9aa12e16201dec8f3d2a4c99df83c4e5e25ef857 100644
> --- a/testcases/kernel/syscalls/fork/fork05.c
> +++ b/testcases/kernel/syscalls/fork/fork05.c
> @@ -55,8 +55,7 @@
>
> #if defined(__i386__)
>
> -#include "lapi/syscalls.h"
> -#include <asm/ldt.h>
> +#include "lapi/ldt.h"
>
> static void run(void)
> {
> @@ -76,7 +75,7 @@ static void run(void)
> ldt0.seg_not_present = 0;
> ldt0.useable = 1;
>
> - tst_syscall(__NR_modify_ldt, 1, &ldt0, sizeof(ldt0));
> + SAFE_MODIFY_LDT(1, &ldt0, sizeof(ldt0));
>
> asm volatile ("movw %w0, %%fs"::"q" (7));
> asm volatile ("movl %%fs:0, %0":"=r" (lo));
>
--
Martin Doucha mdoucha@suse.cz
SW Quality Engineer
SUSE LINUX, s.r.o.
CORSO IIa
Krizikova 148/34
186 00 Prague 8
Czech Republic
More information about the ltp
mailing list