* [LTP] [PATCH v5 1/3] syscalls/modify_ldt: Add lapi/ldt.h
2025-03-31 17:43 [LTP] [PATCH v5 0/3] syscalls/modify_ldt: Refactor into new API Ricardo B. Marliere via ltp
@ 2025-03-31 17:43 ` Ricardo B. Marliere via ltp
2025-04-01 8:48 ` Petr Vorel
2025-04-01 10:29 ` Petr Vorel
2025-03-31 17:43 ` [LTP] [PATCH v5 2/3] syscalls/modify_ldt02: Refactor into new API Ricardo B. Marliere via ltp
2025-03-31 17:43 ` [LTP] [PATCH v5 3/3] syscalls/modify_ldt01: " Ricardo B. Marliere via ltp
2 siblings, 2 replies; 12+ messages in thread
From: Ricardo B. Marliere via ltp @ 2025-03-31 17:43 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 which is used in a few tests and should be
reused.
Reviewed-by: Andrea Cervesato <andrea.cervesato@suse.com>
Signed-off-by: Ricardo B. Marlière <rbm@suse.com>
---
configure.ac | 1 -
include/lapi/ldt.h | 34 ++++++++++++++++++++++++++++++
testcases/cve/cve-2015-3290.c | 37 +++++++--------------------------
testcases/cve/cve-2017-17053.c | 10 ++++-----
testcases/kernel/syscalls/fork/fork05.c | 5 ++---
5 files changed, 48 insertions(+), 39 deletions(-)
diff --git a/configure.ac b/configure.ac
index 671079f3aa48c72866f69e7c545d3428ba87f931..b22f3eacdb1ccb764eae443ab1fb70afd971a14c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -46,7 +46,6 @@ AC_CHECK_DECLS([PR_CAPBSET_DROP, PR_CAPBSET_READ],,,[#include <sys/prctl.h>])
AC_CHECK_DECLS([SEM_STAT_ANY],,,[#include <sys/sem.h>])
AC_CHECK_HEADERS_ONCE([ \
- asm/ldt.h \
asm/prctl.h \
cpuid.h \
emmintrin.h \
diff --git a/include/lapi/ldt.h b/include/lapi/ldt.h
new file mode 100644
index 0000000000000000000000000000000000000000..bab5404457b959a5b44adbf6f458602c5121dbb8
--- /dev/null
+++ b/include/lapi/ldt.h
@@ -0,0 +1,34 @@
+// 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"
+#include <asm/ldt.h>
+
+static int modify_ldt(int func, void *ptr, unsigned long bytecount)
+{
+ return tst_syscall(__NR_modify_ldt, func, ptr, bytecount);
+}
+
+static int safe_modify_ldt(const char *file, const int lineno, int func,
+ void *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);
+
+ 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..c1c513c7c652313a6778bbdc84f0140e530650dc 100644
--- a/testcases/cve/cve-2015-3290.c
+++ b/testcases/cve/cve-2015-3290.c
@@ -118,12 +118,10 @@ perhaps unsurprisingly.)
#include "tst_test.h"
#include "tst_timer.h"
-#if defined(__x86_64__) || defined(__i386__)
-
+#if defined(__i386__) || defined(__x86_64__)
#include <stdlib.h>
#include <stdio.h>
#include <inttypes.h>
-#include <asm/ldt.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <setjmp.h>
@@ -132,6 +130,7 @@ perhaps unsurprisingly.)
#include <sys/wait.h>
#include <linux/perf_event.h>
+#include "lapi/ldt.h"
#include "lapi/syscalls.h"
#include "tst_safe_pthread.h"
@@ -187,7 +186,7 @@ static int running = 1;
static void set_ldt(void)
{
/* Boring 16-bit data segment. */
- const struct user_desc data_desc = {
+ struct user_desc data_desc = {
.entry_number = 0,
.base_addr = 0,
.limit = 0xfffff,
@@ -199,27 +198,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)
@@ -528,8 +507,6 @@ static struct tst_test test = {
}
};
-#else /* defined(__x86_64__) || defined(__i386__) */
-
-TST_TEST_TCONF("not (i386 or x86_64)");
-
-#endif
+#else
+TST_TEST_TCONF("Test supported only on x86");
+#endif /* defined(__i386__) || defined(__x86_64__) */
diff --git a/testcases/cve/cve-2017-17053.c b/testcases/cve/cve-2017-17053.c
index fe7b6d694d6ffbbce863abc1672e03ae5f419df1..7ba22fa94cee57fcb0b0b60c2462d036cb4a40c5 100644
--- a/testcases/cve/cve-2017-17053.c
+++ b/testcases/cve/cve-2017-17053.c
@@ -16,8 +16,7 @@
#include "config.h"
#include "tst_test.h"
-#ifdef HAVE_ASM_LDT_H
-#include <asm/ldt.h>
+#if defined(__i386__) || defined(__x86_64__)
#include <pthread.h>
#include <signal.h>
#include <stdlib.h>
@@ -26,6 +25,7 @@
#include <unistd.h>
#include <stdio.h>
+#include "lapi/ldt.h"
#include "lapi/syscalls.h"
#define EXEC_USEC 5000000
@@ -109,7 +109,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)
@@ -164,5 +164,5 @@ static struct tst_test test = {
};
#else
-TST_TEST_TCONF("no asm/ldt.h header (only for i386 or x86_64)");
-#endif
+TST_TEST_TCONF("Test supported only on x86");
+#endif /* defined(__i386__) || defined(__x86_64__) */
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] 12+ messages in thread* Re: [LTP] [PATCH v5 1/3] syscalls/modify_ldt: Add lapi/ldt.h
2025-03-31 17:43 ` [LTP] [PATCH v5 1/3] syscalls/modify_ldt: Add lapi/ldt.h Ricardo B. Marliere via ltp
@ 2025-04-01 8:48 ` Petr Vorel
2025-04-01 8:56 ` Andrea Cervesato via ltp
2025-04-01 13:55 ` Ricardo B. Marli��re via ltp
2025-04-01 10:29 ` Petr Vorel
1 sibling, 2 replies; 12+ messages in thread
From: Petr Vorel @ 2025-04-01 8:48 UTC (permalink / raw)
To: rbm; +Cc: Linux Test Project
Hi Ricardo,
> Add a wrapper to modify_ldt which is used in a few tests and should be
> reused.
Generally LGTM. Few notes below.
> Reviewed-by: Andrea Cervesato <andrea.cervesato@suse.com>
> Signed-off-by: Ricardo B. Marlière <rbm@suse.com>
> ---
> configure.ac | 1 -
> include/lapi/ldt.h | 34 ++++++++++++++++++++++++++++++
> testcases/cve/cve-2015-3290.c | 37 +++++++--------------------------
> testcases/cve/cve-2017-17053.c | 10 ++++-----
> testcases/kernel/syscalls/fork/fork05.c | 5 ++---
> 5 files changed, 48 insertions(+), 39 deletions(-)
> diff --git a/configure.ac b/configure.ac
> index 671079f3aa48c72866f69e7c545d3428ba87f931..b22f3eacdb1ccb764eae443ab1fb70afd971a14c 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -46,7 +46,6 @@ AC_CHECK_DECLS([PR_CAPBSET_DROP, PR_CAPBSET_READ],,,[#include <sys/prctl.h>])
> AC_CHECK_DECLS([SEM_STAT_ANY],,,[#include <sys/sem.h>])
> AC_CHECK_HEADERS_ONCE([ \
> - asm/ldt.h \
I guess because <asm/ldt.h> is old enough (was here before UAPI split in kernel
v3.8-rc1 we can remove it. But it'd be nice to mention the reason in the commit
message (technically it's a separate change, ok to do that in the commit while
you're at it, but mentioning the reason helps in case of regression).
BTW it'd be nice to go over our m4/ and configure.ac and drop things old enough
to speedup configure run. AC_CHECK_HEADERS_ONCE() is probably quite quick, m4/
files probably take more time. But every speedup counts.
FYI we support quite old distros: kernel 4.4 (in SLE12-SP2):
https://linux-test-project.readthedocs.io/en/latest/users/supported_systems.html
> asm/prctl.h \
> cpuid.h \
> emmintrin.h \
> diff --git a/include/lapi/ldt.h b/include/lapi/ldt.h
> new file mode 100644
> index 0000000000000000000000000000000000000000..bab5404457b959a5b44adbf6f458602c5121dbb8
> --- /dev/null
> +++ b/include/lapi/ldt.h
> @@ -0,0 +1,34 @@
> +// 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"
> +#include <asm/ldt.h>
> +
> +static int modify_ldt(int func, void *ptr, unsigned long bytecount)
> +{
> + return tst_syscall(__NR_modify_ldt, func, ptr, bytecount);
> +}
> +
> +static int safe_modify_ldt(const char *file, const int lineno, int func,
> + void *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);
> +
> + return rval;
> +}
You dropped 'const' from struct user_desc data_desc definitions.
Using const struct user_desc *ptr as a parameter would help to keep the
function. Maybe I'm wrong but I guess if there were libc wrapper (no libc has
it) it would prefer to have pointer to struct than plain void as a parameter.
static int modify_ldt(int func, const struct user_desc *ptr, unsigned long bytecount)
{
return tst_syscall(__NR_modify_ldt, func, ptr, bytecount);
}
static 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);
return rval;
}
nit: IMHO modify_ldt() is not used anywhere outside lapi file, right?
I would also consider instead of creating modify_ldt() just put raw syscall:
rval = tst_syscall(__NR_modify_ldt, func, &ptr, bytecount);
> +
> +#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..c1c513c7c652313a6778bbdc84f0140e530650dc 100644
> --- a/testcases/cve/cve-2015-3290.c
> +++ b/testcases/cve/cve-2015-3290.c
> @@ -118,12 +118,10 @@ perhaps unsurprisingly.)
> #include "tst_test.h"
> #include "tst_timer.h"
> -#if defined(__x86_64__) || defined(__i386__)
> -
> +#if defined(__i386__) || defined(__x86_64__)
> #include <stdlib.h>
> #include <stdio.h>
> #include <inttypes.h>
> -#include <asm/ldt.h>
> #include <unistd.h>
> #include <sys/syscall.h>
We don't need <sys/syscall.h>
> #include <setjmp.h>
> @@ -132,6 +130,7 @@ perhaps unsurprisingly.)
> #include <sys/wait.h>
> #include <linux/perf_event.h>
> +#include "lapi/ldt.h"
> #include "lapi/syscalls.h"
We don't need "lapi/syscalls.h" (it's in "lapi/ldt.h").
> #include "tst_safe_pthread.h"
> @@ -187,7 +186,7 @@ static int running = 1;
> static void set_ldt(void)
> {
> /* Boring 16-bit data segment. */
> - const struct user_desc data_desc = {
> + struct user_desc data_desc = {
> .entry_number = 0,
> .base_addr = 0,
> .limit = 0xfffff,
> @@ -199,27 +198,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)
> @@ -528,8 +507,6 @@ static struct tst_test test = {
> }
> };
> -#else /* defined(__x86_64__) || defined(__i386__) */
> -
> -TST_TEST_TCONF("not (i386 or x86_64)");
> -
> -#endif
> +#else
> +TST_TEST_TCONF("Test supported only on x86");
> +#endif /* defined(__i386__) || defined(__x86_64__) */
> diff --git a/testcases/cve/cve-2017-17053.c b/testcases/cve/cve-2017-17053.c
> index fe7b6d694d6ffbbce863abc1672e03ae5f419df1..7ba22fa94cee57fcb0b0b60c2462d036cb4a40c5 100644
> --- a/testcases/cve/cve-2017-17053.c
> +++ b/testcases/cve/cve-2017-17053.c
> @@ -16,8 +16,7 @@
> #include "config.h"
> #include "tst_test.h"
> -#ifdef HAVE_ASM_LDT_H
> -#include <asm/ldt.h>
> +#if defined(__i386__) || defined(__x86_64__)
> #include <pthread.h>
> #include <signal.h>
> #include <stdlib.h>
> @@ -26,6 +25,7 @@
> #include <unistd.h>
> #include <stdio.h>
> +#include "lapi/ldt.h"
> #include "lapi/syscalls.h"
nit: We don't need "lapi/syscalls.h" since it's in "lapi/ldt.h". And we don't
need <sys/syscall.h>.
> #define EXEC_USEC 5000000
> @@ -109,7 +109,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)
> @@ -164,5 +164,5 @@ static struct tst_test test = {
> };
> #else
> -TST_TEST_TCONF("no asm/ldt.h header (only for i386 or x86_64)");
> -#endif
> +TST_TEST_TCONF("Test supported only on x86");
nit: for some people "x86" means i386 (32 bit intel).
> +#endif /* defined(__i386__) || defined(__x86_64__) */
> 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));
Interesting, no check for return value.
> + SAFE_MODIFY_LDT(1, &ldt0, sizeof(ldt0));
Kind regards,
Petr
> 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] 12+ messages in thread* Re: [LTP] [PATCH v5 1/3] syscalls/modify_ldt: Add lapi/ldt.h
2025-04-01 8:48 ` Petr Vorel
@ 2025-04-01 8:56 ` Andrea Cervesato via ltp
2025-04-01 10:21 ` Petr Vorel
2025-04-01 13:55 ` Ricardo B. Marli��re via ltp
1 sibling, 1 reply; 12+ messages in thread
From: Andrea Cervesato via ltp @ 2025-04-01 8:56 UTC (permalink / raw)
To: Petr Vorel, rbm; +Cc: Linux Test Project
Hi Petr,
On 4/1/25 10:48, Petr Vorel wrote:
> nit: IMHO modify_ldt() is not used anywhere outside lapi file, right?
> I would also consider instead of creating modify_ldt() just put raw syscall:
>
> rval = tst_syscall(__NR_modify_ldt, func, &ptr, bytecount);
Just yesterday I got a review from @Cyril asking me to add syscalls
function definition which are missing inside the lapi/.h header. The
reason is that we want to fallback libc and eventually check for
HAVE_FUNCT_* via autotools.
In general I agree with this approach.
Kind regards,
Andrea Cervesato
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [LTP] [PATCH v5 1/3] syscalls/modify_ldt: Add lapi/ldt.h
2025-04-01 8:56 ` Andrea Cervesato via ltp
@ 2025-04-01 10:21 ` Petr Vorel
0 siblings, 0 replies; 12+ messages in thread
From: Petr Vorel @ 2025-04-01 10:21 UTC (permalink / raw)
To: Andrea Cervesato; +Cc: Linux Test Project, rbm
Hi Andrea,
> Hi Petr,
> On 4/1/25 10:48, Petr Vorel wrote:
> > nit: IMHO modify_ldt() is not used anywhere outside lapi file, right?
> > I would also consider instead of creating modify_ldt() just put raw syscall:
> > rval = tst_syscall(__NR_modify_ldt, func, &ptr, bytecount);
> Just yesterday I got a review from @Cyril asking me to add syscalls function
> definition which are missing inside the lapi/.h header. The reason is that
> we want to fallback libc and eventually check for HAVE_FUNCT_* via
> autotools.
> In general I agree with this approach.
OK, no problem, thanks for info.
Kind regards,
Petr
> Kind regards,
> Andrea Cervesato
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [LTP] [PATCH v5 1/3] syscalls/modify_ldt: Add lapi/ldt.h
2025-04-01 8:48 ` Petr Vorel
2025-04-01 8:56 ` Andrea Cervesato via ltp
@ 2025-04-01 13:55 ` Ricardo B. Marli��re via ltp
1 sibling, 0 replies; 12+ messages in thread
From: Ricardo B. Marli��re via ltp @ 2025-04-01 13:55 UTC (permalink / raw)
To: Petr Vorel; +Cc: Linux Test Project
Hi Petr,
On Tue Apr 1, 2025 at 5:48 AM -03, Petr Vorel wrote:
> Hi Ricardo,
>
>> Add a wrapper to modify_ldt which is used in a few tests and should be
>> reused.
>
> Generally LGTM. Few notes below.
>
>> Reviewed-by: Andrea Cervesato <andrea.cervesato@suse.com>
>> Signed-off-by: Ricardo B. Marlière <rbm@suse.com>
>> ---
>> configure.ac | 1 -
>> include/lapi/ldt.h | 34 ++++++++++++++++++++++++++++++
>> testcases/cve/cve-2015-3290.c | 37 +++++++--------------------------
>> testcases/cve/cve-2017-17053.c | 10 ++++-----
>> testcases/kernel/syscalls/fork/fork05.c | 5 ++---
>> 5 files changed, 48 insertions(+), 39 deletions(-)
>
>> diff --git a/configure.ac b/configure.ac
>> index 671079f3aa48c72866f69e7c545d3428ba87f931..b22f3eacdb1ccb764eae443ab1fb70afd971a14c 100644
>> --- a/configure.ac
>> +++ b/configure.ac
>> @@ -46,7 +46,6 @@ AC_CHECK_DECLS([PR_CAPBSET_DROP, PR_CAPBSET_READ],,,[#include <sys/prctl.h>])
>> AC_CHECK_DECLS([SEM_STAT_ANY],,,[#include <sys/sem.h>])
>
>> AC_CHECK_HEADERS_ONCE([ \
>> - asm/ldt.h \
> I guess because <asm/ldt.h> is old enough (was here before UAPI split in kernel
> v3.8-rc1 we can remove it. But it'd be nice to mention the reason in the commit
> message (technically it's a separate change, ok to do that in the commit while
> you're at it, but mentioning the reason helps in case of regression).
>
Makes sense, I'll amend the commit log.
> BTW it'd be nice to go over our m4/ and configure.ac and drop things old enough
> to speedup configure run. AC_CHECK_HEADERS_ONCE() is probably quite quick, m4/
> files probably take more time. But every speedup counts.
I will take a look and see about that in a future series, if I find
anything useful.
>
> FYI we support quite old distros: kernel 4.4 (in SLE12-SP2):
>
> https://linux-test-project.readthedocs.io/en/latest/users/supported_systems.html
>
>> asm/prctl.h \
>> cpuid.h \
>> emmintrin.h \
>> diff --git a/include/lapi/ldt.h b/include/lapi/ldt.h
>> new file mode 100644
>> index 0000000000000000000000000000000000000000..bab5404457b959a5b44adbf6f458602c5121dbb8
>> --- /dev/null
>> +++ b/include/lapi/ldt.h
>> @@ -0,0 +1,34 @@
>> +// 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"
>> +#include <asm/ldt.h>
>> +
>> +static int modify_ldt(int func, void *ptr, unsigned long bytecount)
>> +{
>> + return tst_syscall(__NR_modify_ldt, func, ptr, bytecount);
>> +}
>> +
>> +static int safe_modify_ldt(const char *file, const int lineno, int func,
>> + void *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);
>> +
>> + return rval;
>> +}
>
> You dropped 'const' from struct user_desc data_desc definitions.
> Using const struct user_desc *ptr as a parameter would help to keep the
> function. Maybe I'm wrong but I guess if there were libc wrapper (no libc has
> it) it would prefer to have pointer to struct than plain void as a parameter.
>
> static int modify_ldt(int func, const struct user_desc *ptr, unsigned long bytecount)
> {
> return tst_syscall(__NR_modify_ldt, func, ptr, bytecount);
> }
>
> static 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);
>
> return rval;
> }
>
> nit: IMHO modify_ldt() is not used anywhere outside lapi file, right?
> I would also consider instead of creating modify_ldt() just put raw syscall:
Actually we need this in modify_ldt01.c:
TST_EXP_FAIL(modify_ldt(tc->tfunc, tc->ptr, tc->bytecount), tc->exp_errno);
and
TST_EXP_POSITIVE(modify_ldt(tc->tfunc, tc->ptr, tc->bytecount));
>
> rval = tst_syscall(__NR_modify_ldt, func, &ptr, bytecount);
>
>> +
>> +#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..c1c513c7c652313a6778bbdc84f0140e530650dc 100644
>> --- a/testcases/cve/cve-2015-3290.c
>> +++ b/testcases/cve/cve-2015-3290.c
>> @@ -118,12 +118,10 @@ perhaps unsurprisingly.)
>> #include "tst_test.h"
>> #include "tst_timer.h"
>
>> -#if defined(__x86_64__) || defined(__i386__)
>> -
>> +#if defined(__i386__) || defined(__x86_64__)
>> #include <stdlib.h>
>> #include <stdio.h>
>> #include <inttypes.h>
>> -#include <asm/ldt.h>
>> #include <unistd.h>
>> #include <sys/syscall.h>
> We don't need <sys/syscall.h>
>
>> #include <setjmp.h>
>> @@ -132,6 +130,7 @@ perhaps unsurprisingly.)
>> #include <sys/wait.h>
>> #include <linux/perf_event.h>
>
>> +#include "lapi/ldt.h"
>> #include "lapi/syscalls.h"
> We don't need "lapi/syscalls.h" (it's in "lapi/ldt.h").
Ack.
>
>> #include "tst_safe_pthread.h"
>
>> @@ -187,7 +186,7 @@ static int running = 1;
>> static void set_ldt(void)
>> {
>> /* Boring 16-bit data segment. */
>> - const struct user_desc data_desc = {
>> + struct user_desc data_desc = {
>> .entry_number = 0,
>> .base_addr = 0,
>> .limit = 0xfffff,
>> @@ -199,27 +198,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)
>> @@ -528,8 +507,6 @@ static struct tst_test test = {
>> }
>> };
>
>> -#else /* defined(__x86_64__) || defined(__i386__) */
>> -
>> -TST_TEST_TCONF("not (i386 or x86_64)");
>> -
>> -#endif
>> +#else
>> +TST_TEST_TCONF("Test supported only on x86");
>> +#endif /* defined(__i386__) || defined(__x86_64__) */
>> diff --git a/testcases/cve/cve-2017-17053.c b/testcases/cve/cve-2017-17053.c
>> index fe7b6d694d6ffbbce863abc1672e03ae5f419df1..7ba22fa94cee57fcb0b0b60c2462d036cb4a40c5 100644
>> --- a/testcases/cve/cve-2017-17053.c
>> +++ b/testcases/cve/cve-2017-17053.c
>> @@ -16,8 +16,7 @@
>> #include "config.h"
>> #include "tst_test.h"
>
>> -#ifdef HAVE_ASM_LDT_H
>> -#include <asm/ldt.h>
>> +#if defined(__i386__) || defined(__x86_64__)
>> #include <pthread.h>
>> #include <signal.h>
>> #include <stdlib.h>
>> @@ -26,6 +25,7 @@
>> #include <unistd.h>
>> #include <stdio.h>
>
>> +#include "lapi/ldt.h"
>> #include "lapi/syscalls.h"
>
> nit: We don't need "lapi/syscalls.h" since it's in "lapi/ldt.h". And we don't
> need <sys/syscall.h>.
Ack, thanks!
>
>> #define EXEC_USEC 5000000
>> @@ -109,7 +109,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)
>> @@ -164,5 +164,5 @@ static struct tst_test test = {
>> };
>
>> #else
>> -TST_TEST_TCONF("no asm/ldt.h header (only for i386 or x86_64)");
>> -#endif
>> +TST_TEST_TCONF("Test supported only on x86");
> nit: for some people "x86" means i386 (32 bit intel).
Indeed. I borrowed this from the kvm suite, I think we can keep it.
>
>> +#endif /* defined(__i386__) || defined(__x86_64__) */
>> 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));
> Interesting, no check for return value.
>
>> + SAFE_MODIFY_LDT(1, &ldt0, sizeof(ldt0));
>
> Kind regards,
> Petr
>
>> asm volatile ("movw %w0, %%fs"::"q" (7));
>> asm volatile ("movl %%fs:0, %0":"=r" (lo));
Thanks for reviewing,
- Ricardo.
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [LTP] [PATCH v5 1/3] syscalls/modify_ldt: Add lapi/ldt.h
2025-03-31 17:43 ` [LTP] [PATCH v5 1/3] syscalls/modify_ldt: Add lapi/ldt.h Ricardo B. Marliere via ltp
2025-04-01 8:48 ` Petr Vorel
@ 2025-04-01 10:29 ` Petr Vorel
2025-04-01 10:45 ` Ricardo B. Marli��re via ltp
1 sibling, 1 reply; 12+ messages in thread
From: Petr Vorel @ 2025-04-01 10:29 UTC (permalink / raw)
To: rbm; +Cc: Linux Test Project
Hi Ricardo, Andrea,
> +++ b/include/lapi/ldt.h
> @@ -0,0 +1,34 @@
> +// 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"
> +#include <asm/ldt.h>
> +
> +static int modify_ldt(int func, void *ptr, unsigned long bytecount)
FYI if this in a header it should be 'static inline'. That would be worth to fix.
We have a lot of 'static inline' in lapi headers. IMHO this is a good approach
for these feature specific syscalls, although Martin Doucha tried to get rid of
some static inline (moving them to C files in lib/) to avoid compilation problems.
But again, this is worth for some generic files long enough e.g.
lib/tst_netlink.c or lib/tst_netdevice.c.
Also static inline makes code to grow, but adding new C source to LTP libs makes
IMHO bigger code size increase (besides we don't care about LTP size anyway,
otherwise we would change linking similar to busybox - single binary providing
many functions).
> +{
> + return tst_syscall(__NR_modify_ldt, func, ptr, bytecount);
> +}
> +
> +static int safe_modify_ldt(const char *file, const int lineno, int func,
> + void *ptr, unsigned long bytecount)
> +{
And here as well.
Kind regards,
Petr
> + 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);
> +
> + return rval;
> +}
> +
> +#define SAFE_MODIFY_LDT(func, ptr, bytecount) \
> + safe_modify_ldt(__FILE__, __LINE__, (func), (ptr), (bytecount))
> +
> +#endif /* LAPI_LDT_H__ */
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 12+ messages in thread* Re: [LTP] [PATCH v5 1/3] syscalls/modify_ldt: Add lapi/ldt.h
2025-04-01 10:29 ` Petr Vorel
@ 2025-04-01 10:45 ` Ricardo B. Marli��re via ltp
0 siblings, 0 replies; 12+ messages in thread
From: Ricardo B. Marli��re via ltp @ 2025-04-01 10:45 UTC (permalink / raw)
To: Petr Vorel; +Cc: Linux Test Project
Hello Petr!
On Tue Apr 1, 2025 at 7:29 AM -03, Petr Vorel wrote:
> Hi Ricardo, Andrea,
>
>> +++ b/include/lapi/ldt.h
>> @@ -0,0 +1,34 @@
>> +// 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"
>> +#include <asm/ldt.h>
>> +
>> +static int modify_ldt(int func, void *ptr, unsigned long bytecount)
> FYI if this in a header it should be 'static inline'. That would be worth to fix.
>
> We have a lot of 'static inline' in lapi headers. IMHO this is a good approach
> for these feature specific syscalls, although Martin Doucha tried to get rid of
> some static inline (moving them to C files in lib/) to avoid compilation problems.
>
> But again, this is worth for some generic files long enough e.g.
> lib/tst_netlink.c or lib/tst_netdevice.c.
>
> Also static inline makes code to grow, but adding new C source to LTP libs makes
> IMHO bigger code size increase (besides we don't care about LTP size anyway,
> otherwise we would change linking similar to busybox - single binary providing
> many functions).
Thanks for your review, I will address your points in the next revision :)
>
>> +{
>> + return tst_syscall(__NR_modify_ldt, func, ptr, bytecount);
>> +}
>> +
>> +static int safe_modify_ldt(const char *file, const int lineno, int func,
>> + void *ptr, unsigned long bytecount)
>> +{
> And here as well.
>
> Kind regards,
> Petr
>
>> + 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);
>> +
>> + return rval;
>> +}
>> +
>> +#define SAFE_MODIFY_LDT(func, ptr, bytecount) \
>> + safe_modify_ldt(__FILE__, __LINE__, (func), (ptr), (bytecount))
>> +
>> +#endif /* LAPI_LDT_H__ */
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 12+ messages in thread
* [LTP] [PATCH v5 2/3] syscalls/modify_ldt02: Refactor into new API
2025-03-31 17:43 [LTP] [PATCH v5 0/3] syscalls/modify_ldt: Refactor into new API Ricardo B. Marliere via ltp
2025-03-31 17:43 ` [LTP] [PATCH v5 1/3] syscalls/modify_ldt: Add lapi/ldt.h Ricardo B. Marliere via ltp
@ 2025-03-31 17:43 ` Ricardo B. Marliere via ltp
2025-03-31 17:43 ` [LTP] [PATCH v5 3/3] syscalls/modify_ldt01: " Ricardo B. Marliere via ltp
2 siblings, 0 replies; 12+ messages in thread
From: Ricardo B. Marliere via ltp @ 2025-03-31 17:43 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 | 223 +++++----------------
2 files changed, 80 insertions(+), 173 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..40e33251528dc3352c39c221f26bb91733424162
--- /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"
+
+int 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,
+ };
+
+ return 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..f3dc2f6b02d6cf96354b8184cae1b738294640c0 100644
--- a/testcases/kernel/syscalls/modify_ldt/modify_ldt02.c
+++ b/testcases/kernel/syscalls/modify_ldt/modify_ldt02.c
@@ -1,199 +1,76 @@
+// 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();
+/*\
+ * Verify that after writing an invalid base address into a segment entry,
+ * a subsequent segment entry read will raise SIGSEV.
+ */
-}
+#include "tst_test.h"
-int create_segment(void *seg, size_t size)
-{
- 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;
-
- 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_child(void)
{
- tst_sig(FORK, DEF_HANDLER, cleanup);
+ int val;
- TEST_PAUSE;
+ signal(SIGSEGV, SIG_DFL);
+ val = read_segment(0);
+ exit(1);
}
-void cleanup(void)
+void run(void)
{
+ int pid, status, seg[4];
-}
-#elif HAVE_MODIFY_LDT
-int main(void)
-{
- tst_brkm(TCONF,
- NULL,
- "modify_ldt is available but not tested on the platform than __i386__");
-}
+ seg[0] = 12345;
-#else /* if defined(__i386__) */
+ create_segment(seg, sizeof(seg));
-int main(void)
-{
- tst_resm(TINFO, "modify_ldt02 test only for ix86");
- tst_exit();
+ TST_EXP_EQ_LI(read_segment(0), seg[0]);
+
+ create_segment(0, 10);
+
+ pid = SAFE_FORK();
+ if (!pid)
+ run_child();
+
+ SAFE_WAITPID(pid, &status, 0);
+ if (WEXITSTATUS(status) != 0) {
+ tst_res(TFAIL, "Did not generate SEGV, child returned "
+ "unexpected status");
+ } else {
+ if (WIFSIGNALED(status) && (WTERMSIG(status) == SIGSEGV))
+ tst_res(TPASS, "generate SEGV as expected");
+ else
+ tst_res(TFAIL, "Did not generate SEGV");
+ }
}
-#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] 12+ messages in thread* [LTP] [PATCH v5 3/3] syscalls/modify_ldt01: Refactor into new API
2025-03-31 17:43 [LTP] [PATCH v5 0/3] syscalls/modify_ldt: Refactor into new API Ricardo B. Marliere via ltp
2025-03-31 17:43 ` [LTP] [PATCH v5 1/3] syscalls/modify_ldt: Add lapi/ldt.h Ricardo B. Marliere via ltp
2025-03-31 17:43 ` [LTP] [PATCH v5 2/3] syscalls/modify_ldt02: Refactor into new API Ricardo B. Marliere via ltp
@ 2025-03-31 17:43 ` Ricardo B. Marliere via ltp
2025-03-31 17:55 ` Ricardo B. Marli��re via ltp
2 siblings, 1 reply; 12+ messages in thread
From: Ricardo B. Marliere via ltp @ 2025-03-31 17:43 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.
Signed-off-by: Ricardo B. Marlière <rbm@suse.com>
---
testcases/kernel/syscalls/modify_ldt/.gitignore | 5 +-
.../kernel/syscalls/modify_ldt/modify_ldt01.c | 261 +++++----------------
.../kernel/syscalls/modify_ldt/modify_ldt03.c | 105 ---------
3 files changed, 55 insertions(+), 316 deletions(-)
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..bf7802c31d5d1dd921289c8aeea49bf52ad667d4 100644
--- a/testcases/kernel/syscalls/modify_ldt/modify_ldt01.c
+++ b/testcases/kernel/syscalls/modify_ldt/modify_ldt01.c
@@ -1,230 +1,75 @@
+// 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)
+/*\
+ * Verify that modify_ldt() calls:
*
- * 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
- *
- * RESTRICTIONS
- * None
+ * - Fails with EINVAL, when writing (func=1) to an invalid pointer
+ * - Fails with EFAULT, when reading (func=0) from an invalid pointer
+ * - Passes when reading (func=0) from a valid pointer
*/
-#include "config.h"
-#include "test.h"
-
-TCID_DEFINE(modify_ldt01);
-int TST_TOTAL = 1;
+#include "tst_test.h"
-#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 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, &entry, sizeof(struct user_desc) - 1, EINVAL },
+ { 1, &entry, sizeof(struct user_desc), EINVAL },
+ { 0x11, &entry, sizeof(struct user_desc), EINVAL },
+};
+
+void run(unsigned int i)
{
- modify_ldt_s entry;
+ struct tcase *tc = &tcases[i];
- 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;
-
- 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)
-{
+ entry.contents = 3;
+ 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] 12+ messages in thread* Re: [LTP] [PATCH v5 3/3] syscalls/modify_ldt01: Refactor into new API
2025-03-31 17:43 ` [LTP] [PATCH v5 3/3] syscalls/modify_ldt01: " Ricardo B. Marliere via ltp
@ 2025-03-31 17:55 ` Ricardo B. Marli��re via ltp
2025-03-31 17:58 ` Ricardo B. Marli��re via ltp
0 siblings, 1 reply; 12+ messages in thread
From: Ricardo B. Marli��re via ltp @ 2025-03-31 17:55 UTC (permalink / raw)
To: rbm, Linux Test Project
On Mon Mar 31, 2025 at 2:43 PM -03, rbm wrote:
> 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.
>
> Signed-off-by: Ricardo B. Marlière <rbm@suse.com>
> ---
> testcases/kernel/syscalls/modify_ldt/.gitignore | 5 +-
> .../kernel/syscalls/modify_ldt/modify_ldt01.c | 261 +++++----------------
> .../kernel/syscalls/modify_ldt/modify_ldt03.c | 105 ---------
> 3 files changed, 55 insertions(+), 316 deletions(-)
>
> 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..bf7802c31d5d1dd921289c8aeea49bf52ad667d4 100644
> --- a/testcases/kernel/syscalls/modify_ldt/modify_ldt01.c
> +++ b/testcases/kernel/syscalls/modify_ldt/modify_ldt01.c
> @@ -1,230 +1,75 @@
> +// 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)
> +/*\
> + * Verify that modify_ldt() calls:
> *
> - * 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
> - *
> - * RESTRICTIONS
> - * None
> + * - Fails with EINVAL, when writing (func=1) to an invalid pointer
> + * - Fails with EFAULT, when reading (func=0) from an invalid pointer
> + * - Passes when reading (func=0) from a valid pointer
Ah, I forgot to update the description...
> */
>
> -#include "config.h"
> -#include "test.h"
> -
> -TCID_DEFINE(modify_ldt01);
> -int TST_TOTAL = 1;
> +#include "tst_test.h"
>
> -#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 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, &entry, sizeof(struct user_desc) - 1, EINVAL },
> + { 1, &entry, sizeof(struct user_desc), EINVAL },
> + { 0x11, &entry, sizeof(struct user_desc), EINVAL },
> +};
> +
> +void run(unsigned int i)
> {
> - modify_ldt_s entry;
> + struct tcase *tc = &tcases[i];
>
> - 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;
> -
> - 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)
> -{
> + entry.contents = 3;
> + 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__) */
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 12+ messages in thread* Re: [LTP] [PATCH v5 3/3] syscalls/modify_ldt01: Refactor into new API
2025-03-31 17:55 ` Ricardo B. Marli��re via ltp
@ 2025-03-31 17:58 ` Ricardo B. Marli��re via ltp
0 siblings, 0 replies; 12+ messages in thread
From: Ricardo B. Marli��re via ltp @ 2025-03-31 17:58 UTC (permalink / raw)
To: Ricardo B. Marlière, Linux Test Project
On Mon Mar 31, 2025 at 2:55 PM -03, Ricardo B. Marlière wrote:
> On Mon Mar 31, 2025 at 2:43 PM -03, rbm wrote:
(snip)
>> + * - Fails with EINVAL, when writing (func=1) to an invalid pointer
>> + * - Fails with EFAULT, when reading (func=0) from an invalid pointer
>> + * - Passes when reading (func=0) from a valid pointer
>
> Ah, I forgot to update the description...
>
/*\
* Verify that modify_ldt() calls:
*
* - 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
*/
Thoughts?
- Ricardo.
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 12+ messages in thread