* [LTP] [PATCH v9 1/3] syscalls/modify_ldt: Add lapi/ldt.h
2025-04-29 10:44 [LTP] [PATCH v9 0/3] syscalls/modify_ldt: Refactor into new API Ricardo B. Marlière via ltp
@ 2025-04-29 10:44 ` Ricardo B. Marlière via ltp
2025-05-07 11:08 ` Martin Doucha
2025-05-07 11:23 ` Martin Doucha
2025-04-29 10:44 ` [LTP] [PATCH v9 2/3] syscalls/modify_ldt02: Refactor into new API Ricardo B. Marlière via ltp
` (2 subsequent siblings)
3 siblings, 2 replies; 9+ messages in thread
From: Ricardo B. Marlière via ltp @ 2025-04-29 10:44 UTC (permalink / raw)
To: Linux Test Project; +Cc: Ricardo B. Marlière
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");
- } 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));
--
2.49.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 9+ messages in thread* Re: [LTP] [PATCH v9 1/3] syscalls/modify_ldt: Add lapi/ldt.h
2025-04-29 10:44 ` [LTP] [PATCH v9 1/3] syscalls/modify_ldt: Add lapi/ldt.h Ricardo B. Marlière via ltp
@ 2025-05-07 11:08 ` Martin Doucha
2025-05-07 11:23 ` Martin Doucha
1 sibling, 0 replies; 9+ messages in thread
From: Martin Doucha @ 2025-05-07 11:08 UTC (permalink / raw)
To: Ricardo B. Marlière, Linux Test Project
Hi,
the error handling in safe_modify_ldt() is incorrect on x86_64. The
return value is intentionally cast to unsigned int in kernel which means
that glibc will interpret error codes as large positive values and
return them as is. See the workaround that this patch removed from
cve-2015-3290.c 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;
> - }
This workaround ^^^
> -
> - if (TST_RET == -1 && TST_ERR == EINVAL) {
> - tst_brk(TCONF | TTERRNO,
> - "modify_ldt: 16-bit data segments are probably disabled");
> - } 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
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: [LTP] [PATCH v9 1/3] syscalls/modify_ldt: Add lapi/ldt.h
2025-04-29 10:44 ` [LTP] [PATCH v9 1/3] syscalls/modify_ldt: Add lapi/ldt.h Ricardo B. Marlière via ltp
2025-05-07 11:08 ` Martin Doucha
@ 2025-05-07 11:23 ` Martin Doucha
2025-05-07 11:32 ` Ricardo B. Marlière via ltp
1 sibling, 1 reply; 9+ messages in thread
From: Martin Doucha @ 2025-05-07 11:23 UTC (permalink / raw)
To: Ricardo B. Marlière, Linux Test Project
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
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: [LTP] [PATCH v9 1/3] syscalls/modify_ldt: Add lapi/ldt.h
2025-05-07 11:23 ` Martin Doucha
@ 2025-05-07 11:32 ` Ricardo B. Marlière via ltp
0 siblings, 0 replies; 9+ messages in thread
From: Ricardo B. Marlière via ltp @ 2025-05-07 11:32 UTC (permalink / raw)
To: Martin Doucha, Linux Test Project
On Wed May 7, 2025 at 8:23 AM -03, Martin Doucha wrote:
> Hi,
> one more thing for cve-2015-3290 below.
>
Thanks for the reports, I'll send a fix soon!
> 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));
>>
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 9+ messages in thread
* [LTP] [PATCH v9 2/3] syscalls/modify_ldt02: Refactor into new API
2025-04-29 10:44 [LTP] [PATCH v9 0/3] syscalls/modify_ldt: Refactor into new API Ricardo B. Marlière via ltp
2025-04-29 10:44 ` [LTP] [PATCH v9 1/3] syscalls/modify_ldt: Add lapi/ldt.h Ricardo B. Marlière via ltp
@ 2025-04-29 10:44 ` Ricardo B. Marlière via ltp
2025-04-29 10:44 ` [LTP] [PATCH v9 3/3] syscalls/modify_ldt01: " Ricardo B. Marlière via ltp
2025-05-06 9:44 ` [LTP] [PATCH v9 0/3] syscalls/modify_ldt: " Cyril Hrubis
3 siblings, 0 replies; 9+ messages in thread
From: Ricardo B. Marlière via ltp @ 2025-04-29 10:44 UTC (permalink / raw)
To: Linux Test Project; +Cc: Ricardo B. Marlière
From: Ricardo B. Marlière <rbm@suse.com>
Reviewed-by: Andrea Cervesato <andrea.cervesato@suse.com>
Signed-off-by: Ricardo B. Marlière <rbm@suse.com>
---
testcases/kernel/syscalls/modify_ldt/common.h | 30 +++
.../kernel/syscalls/modify_ldt/modify_ldt02.c | 215 ++++-----------------
2 files changed, 70 insertions(+), 175 deletions(-)
diff --git a/testcases/kernel/syscalls/modify_ldt/common.h b/testcases/kernel/syscalls/modify_ldt/common.h
new file mode 100644
index 0000000000000000000000000000000000000000..3f92b677d74c5223279df028c0e1fdf1d1c28905
--- /dev/null
+++ b/testcases/kernel/syscalls/modify_ldt/common.h
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) International Business Machines Corp., 2001
+ * 07/2001 Ported by Wayne Boyer
+ * Copyright (c) 2025 SUSE LLC Ricardo B. Marlière <rbm@suse.com>
+ */
+
+#ifndef COMMON_H
+#define COMMON_H
+
+#include "tst_test.h"
+#include "lapi/ldt.h"
+
+static inline void create_segment(void *seg, size_t size)
+{
+ struct user_desc entry = {
+ .entry_number = 0,
+ .base_addr = (unsigned long)seg,
+ .limit = size,
+ .seg_32bit = 1,
+ .contents = 0,
+ .read_exec_only = 0,
+ .limit_in_pages = 0,
+ .seg_not_present = 0,
+ };
+
+ SAFE_MODIFY_LDT(1, &entry, sizeof(entry));
+}
+
+#endif
diff --git a/testcases/kernel/syscalls/modify_ldt/modify_ldt02.c b/testcases/kernel/syscalls/modify_ldt/modify_ldt02.c
index 5113b3fb4e29d241e819e98c90c297107aec93cf..4da4e162f4882face3c92e18038021b9fe2efc81 100644
--- a/testcases/kernel/syscalls/modify_ldt/modify_ldt02.c
+++ b/testcases/kernel/syscalls/modify_ldt/modify_ldt02.c
@@ -1,199 +1,64 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
- *
- * Copyright (c) International Business Machines Corp., 2001
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
- * the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-/*
- * NAME
- * modify_ldt02.c
- *
- * DESCRIPTION
- * Testcase to check the error conditions for modify_ldt(2)
- *
- * ALGORITHM
- * block1:
- * Create a segment at entry 0 and a valid base address.
- * Read the contents of the segment thru' fs register.
- * Validate the data.
- * Write an invalid base address into entry 0.
- * Read the contents of entry 0 in the child process.
- * Verify that a SIGSEGV is incurred.
- *
- * USAGE
- * modify_ldt02
- *
- * HISTORY
+ * Copyright (c) International Business Machines Corp., 2001
* 07/2001 Ported by Wayne Boyer
- *
- * RESTRICTIONS
- * None
+ * Copyright (c) 2025 SUSE LLC Ricardo B. Marlière <rbm@suse.com>
*/
-#include "config.h"
-#include "test.h"
-
-TCID_DEFINE(modify_ldt02);
-int TST_TOTAL = 1;
-
-#if defined(__i386__) && defined(HAVE_MODIFY_LDT)
-
-#ifdef HAVE_ASM_LDT_H
-#include <asm/ldt.h>
-#endif
-extern int modify_ldt(int, void *, unsigned long);
-
-#include <asm/unistd.h>
-#include <string.h>
-#include <sys/wait.h>
-#include <errno.h>
-
-/* Newer ldt.h files use user_desc, instead of modify_ldt_ldt_s */
-#ifdef HAVE_STRUCT_USER_DESC
-typedef struct user_desc modify_ldt_s;
-#elif HAVE_STRUCT_MODIFY_LDT_LDT_S
-typedef struct modify_ldt_ldt_s modify_ldt_s;
-#else
-typedef struct modify_ldt_ldt_t {
- unsigned int entry_number;
- unsigned long 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;
- unsigned int empty:25;
-} modify_ldt_s;
-#endif
-
-int create_segment(void *, size_t);
-int read_segment(unsigned int);
-void cleanup(void);
-void setup(void);
-
-int main(int ac, char **av)
-{
- int lc;
-
- int val, pid, status;
-
- int seg[4];
-
- tst_parse_opts(ac, av, NULL, NULL);
-
- setup();
-
- for (lc = 0; TEST_LOOPING(lc); lc++) {
- tst_count = 0;
-
- seg[0] = 12345;
- if (create_segment(seg, sizeof(seg)) == -1) {
- tst_brkm(TBROK, cleanup, "Creation of segment failed");
- }
-
- val = read_segment(0);
-
- if (val != seg[0]) {
- tst_resm(TFAIL, "Invalid value read %d, expected %d",
- val, seg[0]);
- } else
- tst_resm(TPASS, "value read as expected");
-
- if (create_segment(0, 10) == -1) {
- tst_brkm(TBROK, cleanup, "Creation of segment failed");
- }
-
- tst_old_flush();
- if ((pid = tst_fork()) == 0) {
- signal(SIGSEGV, SIG_DFL);
- val = read_segment(0);
- exit(1);
- }
-
- (void)waitpid(pid, &status, 0);
-
- if (WEXITSTATUS(status) != 0) {
- tst_resm(TFAIL, "Did not generate SEGV, child returned "
- "unexpected status");
- } else {
- if (WIFSIGNALED(status) && (WTERMSIG(status) == SIGSEGV))
- tst_resm(TPASS, "generate SEGV as expected");
- else
- tst_resm(TFAIL, "Did not generate SEGV");
- }
- }
- cleanup();
- tst_exit();
-
-}
-
-int create_segment(void *seg, size_t size)
-{
- modify_ldt_s entry;
+/*\
+ * Verify that after writing an invalid base address into a segment entry,
+ * a subsequent segment entry read will raise SIGSEV.
+ */
- entry.entry_number = 0;
- entry.base_addr = (unsigned long)seg;
- entry.limit = size;
- entry.seg_32bit = 1;
- entry.contents = 0;
- entry.read_exec_only = 0;
- entry.limit_in_pages = 0;
- entry.seg_not_present = 0;
+#include "tst_test.h"
- return modify_ldt(1, &entry, sizeof(entry));
-}
+#ifdef __i386__
+#include "common.h"
int read_segment(unsigned int index)
{
int res;
+
__asm__ __volatile__("\n\
push $0x0007;\n\
pop %%fs;\n\
- movl %%fs:(%1), %0":"=r"(res)
- :"r"(index * sizeof(int)));
+ movl %%fs:(%1), %0"
+ : "=r"(res)
+ : "r"(index * sizeof(int)));
+
return res;
}
-void setup(void)
+void run(void)
{
- tst_sig(FORK, DEF_HANDLER, cleanup);
+ int pid, status, seg[4];
- TEST_PAUSE;
-}
+ seg[0] = 12345;
-void cleanup(void)
-{
+ create_segment(seg, sizeof(seg));
-}
-#elif HAVE_MODIFY_LDT
-int main(void)
-{
- tst_brkm(TCONF,
- NULL,
- "modify_ldt is available but not tested on the platform than __i386__");
-}
+ TST_EXP_EQ_LI(read_segment(0), seg[0]);
-#else /* if defined(__i386__) */
+ create_segment(0, 10);
-int main(void)
-{
- tst_resm(TINFO, "modify_ldt02 test only for ix86");
- tst_exit();
+ pid = SAFE_FORK();
+ if (!pid) {
+ read_segment(0);
+ exit(1);
+ }
+
+ SAFE_WAITPID(pid, &status, 0);
+ if (WIFSIGNALED(status) && (WTERMSIG(status) == SIGSEGV))
+ tst_res(TPASS, "generate SEGV as expected");
+ else
+ tst_res(TFAIL, "child %s", tst_strstatus(status));
}
-#endif /* if defined(__i386__) */
+static struct tst_test test = {
+ .test_all = run,
+ .forks_child = 1,
+};
+
+#else
+TST_TEST_TCONF("Test supported only on i386");
+#endif /* __i386__ */
--
2.49.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 9+ messages in thread* [LTP] [PATCH v9 3/3] syscalls/modify_ldt01: Refactor into new API
2025-04-29 10:44 [LTP] [PATCH v9 0/3] syscalls/modify_ldt: Refactor into new API Ricardo B. Marlière via ltp
2025-04-29 10:44 ` [LTP] [PATCH v9 1/3] syscalls/modify_ldt: Add lapi/ldt.h Ricardo B. Marlière via ltp
2025-04-29 10:44 ` [LTP] [PATCH v9 2/3] syscalls/modify_ldt02: Refactor into new API Ricardo B. Marlière via ltp
@ 2025-04-29 10:44 ` Ricardo B. Marlière via ltp
2025-05-06 9:44 ` [LTP] [PATCH v9 0/3] syscalls/modify_ldt: " Cyril Hrubis
3 siblings, 0 replies; 9+ messages in thread
From: Ricardo B. Marlière via ltp @ 2025-04-29 10:44 UTC (permalink / raw)
To: Linux Test Project; +Cc: Ricardo B. Marlière
From: Ricardo B. Marlière <rbm@suse.com>
Now that we're using the wrapped modify_ldt() from the lapi/ldt.h which
uses tst_syscall(), it does not make sense to keep the first block of the
original test which simply checked for ENOSYS. Also, merge modify_ldt03
into modify_ldt01 and extend the test to cover all the errors from the
manual page.
Reviewed-by: Andrea Cervesato <andrea.cervesato@suse.com>
Signed-off-by: Ricardo B. Marlière <rbm@suse.com>
---
runtest/syscalls | 1 -
testcases/kernel/syscalls/modify_ldt/.gitignore | 5 +-
.../kernel/syscalls/modify_ldt/modify_ldt01.c | 264 +++++----------------
.../kernel/syscalls/modify_ldt/modify_ldt03.c | 105 --------
4 files changed, 58 insertions(+), 317 deletions(-)
diff --git a/runtest/syscalls b/runtest/syscalls
index 57338297a33b47075a3f801871753cc76b073bfa..d72f9c17f62f5d236c30170ae9ce6e159f19fa2e 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -847,7 +847,6 @@ mmap21_02 mmap21
modify_ldt01 modify_ldt01
modify_ldt02 modify_ldt02
-modify_ldt03 modify_ldt03
mount01 mount01
mount02 mount02
diff --git a/testcases/kernel/syscalls/modify_ldt/.gitignore b/testcases/kernel/syscalls/modify_ldt/.gitignore
index c0b8bbf5875af453b4880ef4b717fdb40d109ee7..c8817b2c3a811afdf40841dc1b81e4b2c034e7d8 100644
--- a/testcases/kernel/syscalls/modify_ldt/.gitignore
+++ b/testcases/kernel/syscalls/modify_ldt/.gitignore
@@ -1,3 +1,2 @@
-/modify_ldt01
-/modify_ldt02
-/modify_ldt03
+modify_ldt01
+modify_ldt02
diff --git a/testcases/kernel/syscalls/modify_ldt/modify_ldt01.c b/testcases/kernel/syscalls/modify_ldt/modify_ldt01.c
index 684e53772414ae468b4f168578596eabb27ef18b..e087b0a4e99355bbaab67c5324a6ba12bde36910 100644
--- a/testcases/kernel/syscalls/modify_ldt/modify_ldt01.c
+++ b/testcases/kernel/syscalls/modify_ldt/modify_ldt01.c
@@ -1,230 +1,78 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
- *
- * Copyright (c) International Business Machines Corp., 2001
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
- * the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ * Copyright (c) International Business Machines Corp., 2001
+ * 07/2001 Ported by Wayne Boyer
+ * Copyright (c) 2025 SUSE LLC Ricardo B. Marlière <rbm@suse.com>
*/
-/*
- * NAME
- * modify_ldt01.c
- *
- * DESCRIPTION
- * Testcase to check the error conditions for modify_ldt(2)
- *
- * CALLS
- * modify_ldt()
- *
- * ALGORITHM
- * block1:
- * Invoke modify_ldt() with a func value which is neither
- * 0 or 1. Verify that ENOSYS is set.
- * block2:
- * Invoke mprotect() with ptr == NULL. Verify that EINVAL
- * is set.
- * block3:
- * Create an LDT segment.
- * Try to read from an invalid pointer.
- * Verify that EFAULT is set.
- *
- * USAGE
- * modify_ldt01
- *
- * HISTORY
- * 07/2001 Ported by Wayne Boyer
+/*\
+ * Verify that modify_ldt() calls:
*
- * RESTRICTIONS
- * None
+ * - Fails with EFAULT, when reading (func=0) from an invalid pointer
+ * - Passes when reading (func=0) from a valid pointer
+ * - Fails with EINVAL, when writing (func=1) to an invalid pointer
+ * - Fails with EINVAL, when writing (func=1) with an invalid bytecount value
+ * - Fails with EINVAL, when writing (func=1) an entry with invalid values
+ * - Fails with EINVAL, when writing (func=0x11) an entry with invalid values
*/
-#include "config.h"
-#include "test.h"
+#include "tst_test.h"
-TCID_DEFINE(modify_ldt01);
-int TST_TOTAL = 1;
-
-#if defined(__i386__) && defined(HAVE_MODIFY_LDT)
-
-#ifdef HAVE_ASM_LDT_H
-#include <asm/ldt.h>
-#endif
-extern int modify_ldt(int, void *, unsigned long);
-
-#include <asm/unistd.h>
-#include <errno.h>
-
-/* Newer ldt.h files use user_desc, instead of modify_ldt_ldt_s */
-#ifdef HAVE_STRUCT_USER_DESC
-typedef struct user_desc modify_ldt_s;
-#elif HAVE_STRUCT_MODIFY_LDT_LDT_S
-typedef struct modify_ldt_ldt_s modify_ldt_s;
-#else
-typedef struct modify_ldt_ldt_t {
- unsigned int entry_number;
- unsigned long 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;
- unsigned int empty:25;
-} modify_ldt_s;
-#endif
-
-int create_segment(void *, size_t);
-void cleanup(void);
-void setup(void);
-
-int main(int ac, char **av)
-{
- int lc;
+#ifdef __i386__
+#include "common.h"
+static void *ptr;
+static char *buf;
+static struct user_desc invalid_entry;
+static struct tcase {
+ int tfunc;
void *ptr;
- int retval, func;
-
- int seg[4];
-
- tst_parse_opts(ac, av, NULL, NULL);
-
- setup();
-
- for (lc = 0; TEST_LOOPING(lc); lc++) {
-
- /* reset tst_count in case we are looping */
- tst_count = 0;
-
- /*
- * Check for ENOSYS.
- */
- ptr = malloc(10);
- func = 100;
- retval = modify_ldt(func, ptr, sizeof(ptr));
- if (retval < 0) {
- if (errno != ENOSYS) {
- tst_resm(TFAIL, "modify_ldt() set invalid "
- "errno, expected ENOSYS, got: %d",
- errno);
- } else {
- tst_resm(TPASS,
- "modify_ldt() set expected errno");
- }
- } else {
- tst_resm(TFAIL, "modify_ldt error: "
- "unexpected return value %d", retval);
- }
-
- free(ptr);
-
- /*
- * Check for EINVAL
- */
- ptr = 0;
-
- retval = modify_ldt(1, ptr, sizeof(ptr));
- if (retval < 0) {
- if (errno != EINVAL) {
- tst_resm(TFAIL, "modify_ldt() set invalid "
- "errno, expected EINVAL, got: %d",
- errno);
- } else {
- tst_resm(TPASS,
- "modify_ldt() set expected errno");
- }
- } else {
- tst_resm(TFAIL, "modify_ldt error: "
- "unexpected return value %d", retval);
- }
-
- /*
- * Create a new LDT segment.
- */
- if (create_segment(seg, sizeof(seg)) == -1) {
- tst_brkm(TBROK, cleanup, "Creation of segment failed");
- }
-
- /*
- * Check for EFAULT
- */
- ptr = sbrk(0);
-
- retval = modify_ldt(0, ptr + 0xFFF, sizeof(ptr));
- if (retval < 0) {
- if (errno != EFAULT) {
- tst_resm(TFAIL, "modify_ldt() set invalid "
- "errno, expected EFAULT, got: %d",
- errno);
- } else {
- tst_resm(TPASS,
- "modify_ldt() set expected errno");
- }
- } else {
- tst_resm(TFAIL, "modify_ldt error: "
- "unexpected return value %d", retval);
- }
- }
- cleanup();
- tst_exit();
-}
-
-/*
- * create_segment() -
- */
-int create_segment(void *seg, size_t size)
+ unsigned long bytecount;
+ int exp_errno;
+} tcases[] = {
+ { 0, &ptr, sizeof(ptr), EFAULT },
+ { 0, &buf, sizeof(buf), 0 },
+ { 1, (void *)0, 0, EINVAL },
+ { 1, &buf, sizeof(struct user_desc) - 1, EINVAL },
+ { 1, &invalid_entry, sizeof(struct user_desc), EINVAL },
+ { 0x11, &invalid_entry, sizeof(struct user_desc), EINVAL },
+};
+
+void run(unsigned int i)
{
- modify_ldt_s entry;
-
- entry.entry_number = 0;
- entry.base_addr = (unsigned long)seg;
- entry.limit = size;
- entry.seg_32bit = 1;
- entry.contents = 0;
- entry.read_exec_only = 0;
- entry.limit_in_pages = 0;
- entry.seg_not_present = 0;
+ struct tcase *tc = &tcases[i];
- return modify_ldt(1, &entry, sizeof(entry));
+ if (tc->exp_errno)
+ TST_EXP_FAIL(modify_ldt(tc->tfunc, tc->ptr, tc->bytecount),
+ tc->exp_errno);
+ else
+ TST_EXP_POSITIVE(modify_ldt(tc->tfunc, tc->ptr, tc->bytecount));
}
void setup(void)
{
+ int seg[4];
- tst_sig(FORK, DEF_HANDLER, cleanup);
-
- TEST_PAUSE;
-}
+ create_segment(seg, sizeof(seg));
-void cleanup(void)
-{
+ invalid_entry.contents = 3;
+ invalid_entry.seg_not_present = 0;
+ ptr = sbrk(0) + 0xFFF;
+ tcases[0].ptr = ptr;
}
-#elif HAVE_MODIFY_LDT
-int main(void)
-{
- tst_brkm(TCONF,
- NULL,
- "modify_ldt is available but not tested on the platform than __i386__");
-}
+static struct tst_test test = {
+ .test = run,
+ .tcnt = ARRAY_SIZE(tcases),
+ .setup = setup,
+ .bufs =
+ (struct tst_buffers[]){
+ { &buf, .size = sizeof(struct user_desc) },
+ {},
+ },
+};
#else
-int main(void)
-{
- tst_resm(TINFO, "modify_ldt01 test only for ix86");
- tst_exit();
-}
-
-#endif /* defined(__i386__) */
+TST_TEST_TCONF("Test supported only on i386");
+#endif /* __i386__ */
diff --git a/testcases/kernel/syscalls/modify_ldt/modify_ldt03.c b/testcases/kernel/syscalls/modify_ldt/modify_ldt03.c
deleted file mode 100644
index 01730e0e14ae98a934e7b66c9058454506bbe064..0000000000000000000000000000000000000000
--- a/testcases/kernel/syscalls/modify_ldt/modify_ldt03.c
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (c) 2014 Fujitsu Ltd.
- * Author: Zeng Linggang <zenglg.jy@cn.fujitsu.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program.
- */
-/*
- * DESCRIPTION
- * Basic test for modify_ldt(2) using func=0 argument.
- */
-
-#include "config.h"
-#include "test.h"
-
-char *TCID = "modify_ldt03";
-int TST_TOTAL = 1;
-
-#if defined(__i386__) && defined(HAVE_MODIFY_LDT)
-
-#ifdef HAVE_ASM_LDT_H
-# include <asm/ldt.h>
-#endif
-extern int modify_ldt(int, void *, unsigned long);
-
-#include <asm/unistd.h>
-#include <string.h>
-#include <sys/wait.h>
-#include <errno.h>
-#include "safe_macros.h"
-
-#ifdef HAVE_STRUCT_USER_DESC
-# define SIZE sizeof(struct user_desc)
-#else
-# define SIZE 16
-#endif
-
-static char buf[SIZE];
-static void cleanup(void);
-static void setup(void);
-
-int main(int ac, char **av)
-{
- int lc;
-
- tst_parse_opts(ac, av, NULL, NULL);
-
- setup();
-
- for (lc = 0; TEST_LOOPING(lc); lc++) {
-
- tst_count = 0;
-
- TEST(modify_ldt(0, buf, SIZE));
-
- if (TEST_RETURN < 0) {
- tst_resm(TFAIL | TTERRNO,
- "modify_ldt() failed with errno: %s",
- strerror(TEST_ERRNO));
- } else {
- tst_resm(TPASS, "modify_ldt() tested success");
- }
- }
-
- cleanup();
- tst_exit();
-}
-
-static void setup(void)
-{
- tst_sig(NOFORK, DEF_HANDLER, cleanup);
-
- TEST_PAUSE;
-}
-
-static void cleanup(void)
-{
-}
-
-#elif HAVE_MODIFY_LDT
-
-int main(void)
-{
- tst_brkm(TCONF,
- NULL, "modify_ldt is available but not tested on the platform than "
- "__i386__");
-}
-
-#else /* if defined(__i386__) */
-
-int main(void)
-{
- tst_resm(TINFO, "modify_ldt03 test only for ix86");
- tst_exit();
-}
-
-#endif /* if defined(__i386__) */
--
2.49.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 9+ messages in thread* Re: [LTP] [PATCH v9 0/3] syscalls/modify_ldt: Refactor into new API
2025-04-29 10:44 [LTP] [PATCH v9 0/3] syscalls/modify_ldt: Refactor into new API Ricardo B. Marlière via ltp
` (2 preceding siblings ...)
2025-04-29 10:44 ` [LTP] [PATCH v9 3/3] syscalls/modify_ldt01: " Ricardo B. Marlière via ltp
@ 2025-05-06 9:44 ` Cyril Hrubis
2025-05-06 10:19 ` Ricardo B. Marlière via ltp
3 siblings, 1 reply; 9+ messages in thread
From: Cyril Hrubis @ 2025-05-06 9:44 UTC (permalink / raw)
To: Ricardo B. Marlière; +Cc: Linux Test Project
Hi!
I've pushed the patchset with the change I've proposed to the tst_test
structure in order to produce a correct metadata. Thanks.
--
Cyril Hrubis
chrubis@suse.cz
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 9+ messages in thread