* [LTP] [PATCH v6 0/3] syscalls/modify_ldt: Refactor into new API
@ 2025-04-02 9:58 Ricardo B. Marlière via ltp
2025-04-02 9:58 ` [LTP] [PATCH v6 1/3] syscalls/modify_ldt: Add lapi/ldt.h Ricardo B. Marlière via ltp
` (2 more replies)
0 siblings, 3 replies; 8+ messages in thread
From: Ricardo B. Marlière via ltp @ 2025-04-02 9:58 UTC (permalink / raw)
To: Linux Test Project; +Cc: Ricardo B. Marlière
Signed-off-by: Ricardo B. Marlière <rbm@suse.com>
---
Changes in v6:
- Removed unnecessary includes
- Made modify_ldt wrappers static inline
- Used const struct user_desc *ptr instead of void *ptr in modify_ldt()
- Fixed modify_ldt01 test description
- Added explanation on removal of "asm/ldt.h" check in commit message
- Removed run_child() in modify_ldt02 - instead, removed unused "int val"
- Renamed "entry" to "invalid_entry" in modify_ldt01
- Link to v5: https://lore.kernel.org/r/20250331-conversions-modify_ldt-v5-0-fd6ea1491956@suse.com
Changes in v5:
- Removed unnecessary #error
- Removed const specifier in cve-2015-3290.c
- Improved modify_ldt02 test description
- Added run_child() in modify_ldt02
- Removed unnecessary #include "lapi/ldt.h" in files that include common.h
- Extended coverage in modify_ldt01
- Link to v4: https://lore.kernel.org/r/20250328-conversions-modify_ldt-v4-0-a5ee7b8d82aa@suse.com
Changes in v4:
- Re-added the asm/ldt.h include directive
- Link to v3: https://lore.kernel.org/r/20250328-conversions-modify_ldt-v3-0-f6b6ee1c9144@suse.com
Changes in v3:
- Dropped the set_thread_area01 patch for a later series
- Squashed modify_ldt03 commit into modify_ldt01
- Renamed struct tst_case to tcase
- Removed fallback definition of struct user_desc
- Link to v2: https://lore.kernel.org/r/20250327-conversions-modify_ldt-v2-0-2907d4d3f6c0@suse.com
Changes in v2:
- Also refactored set_thread_area01
- Merged simple tests (including the existing modify_ldt03) into
modify_ldt01 instead of splitting it
- Added SAFE_MODIFY_LDT() macro
- Removed check to asm/ldt.h in configure.ac
- Used tst_syscall() instead of syscall() in modify_ldt() @ lapi/ldt.h
- Link to v1: https://lore.kernel.org/r/20250324-conversions-modify_ldt-v1-0-8d6d82f10768@suse.com
---
Ricardo B. Marlière (3):
syscalls/modify_ldt: Add lapi/ldt.h
syscalls/modify_ldt02: Refactor into new API
syscalls/modify_ldt01: Refactor into new API
configure.ac | 1 -
include/lapi/ldt.h | 36 +++
testcases/cve/cve-2015-3290.c | 37 +--
testcases/cve/cve-2017-17053.c | 12 +-
testcases/kernel/syscalls/fork/fork05.c | 5 +-
testcases/kernel/syscalls/modify_ldt/.gitignore | 5 +-
testcases/kernel/syscalls/modify_ldt/common.h | 30 +++
.../kernel/syscalls/modify_ldt/modify_ldt01.c | 264 +++++----------------
.../kernel/syscalls/modify_ldt/modify_ldt02.c | 221 ++++-------------
.../kernel/syscalls/modify_ldt/modify_ldt03.c | 105 --------
10 files changed, 183 insertions(+), 533 deletions(-)
---
base-commit: 0a0a77c444b56483bdde5046feeb518c96f5e4a2
change-id: 20250324-conversions-modify_ldt-816329223f6e
Best regards,
--
Ricardo B. Marlière <rbm@suse.com>
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 8+ messages in thread
* [LTP] [PATCH v6 1/3] syscalls/modify_ldt: Add lapi/ldt.h
2025-04-02 9:58 [LTP] [PATCH v6 0/3] syscalls/modify_ldt: Refactor into new API Ricardo B. Marlière via ltp
@ 2025-04-02 9:58 ` Ricardo B. Marlière via ltp
2025-04-07 12:09 ` Cyril Hrubis
2025-04-02 9:58 ` [LTP] [PATCH v6 2/3] syscalls/modify_ldt02: Refactor into new API Ricardo B. Marlière via ltp
2025-04-02 9:58 ` [LTP] [PATCH v6 3/3] syscalls/modify_ldt01: " Ricardo B. Marlière via ltp
2 siblings, 1 reply; 8+ messages in thread
From: Ricardo B. Marlière via ltp @ 2025-04-02 9:58 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. Currently, LTP supports Linux v4.4+, which always have "asm/ldt.h",
therefore remove the check for it in configure.ac.
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 | 36 ++++++++++++++++++++++++++++++++
testcases/cve/cve-2015-3290.c | 37 ++++++---------------------------
testcases/cve/cve-2017-17053.c | 12 +++++------
testcases/kernel/syscalls/fork/fork05.c | 5 ++---
5 files changed, 49 insertions(+), 42 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..068a577cf113ba47a45d29920c6adb6851f4fc52
--- /dev/null
+++ b/include/lapi/ldt.h
@@ -0,0 +1,36 @@
+// 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 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);
+
+ 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..603a4ba19f713dc7b7d4134324114ba8ffe245cb 100644
--- a/testcases/cve/cve-2015-3290.c
+++ b/testcases/cve/cve-2015-3290.c
@@ -118,21 +118,18 @@ 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>
#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 +196,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 +505,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..8ebf97380b7d7f71ec3f9f6a79e627f9c2a4b09a 100644
--- a/testcases/cve/cve-2017-17053.c
+++ b/testcases/cve/cve-2017-17053.c
@@ -16,17 +16,15 @@
#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>
-#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)
@@ -164,5 +162,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] 8+ messages in thread
* [LTP] [PATCH v6 2/3] syscalls/modify_ldt02: Refactor into new API
2025-04-02 9:58 [LTP] [PATCH v6 0/3] syscalls/modify_ldt: Refactor into new API Ricardo B. Marlière via ltp
2025-04-02 9:58 ` [LTP] [PATCH v6 1/3] syscalls/modify_ldt: Add lapi/ldt.h Ricardo B. Marlière via ltp
@ 2025-04-02 9:58 ` Ricardo B. Marlière via ltp
2025-04-07 12:24 ` Cyril Hrubis
2025-04-02 9:58 ` [LTP] [PATCH v6 3/3] syscalls/modify_ldt01: " Ricardo B. Marlière via ltp
2 siblings, 1 reply; 8+ messages in thread
From: Ricardo B. Marlière via ltp @ 2025-04-02 9:58 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 | 221 +++++----------------
2 files changed, 76 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..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..e301622052a4d20047c622a0d65a9188a427ad86 100644
--- a/testcases/kernel/syscalls/modify_ldt/modify_ldt02.c
+++ b/testcases/kernel/syscalls/modify_ldt/modify_ldt02.c
@@ -1,199 +1,70 @@
+// 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) {
+ signal(SIGSEGV, SIG_DFL);
+ read_segment(0);
+ exit(1);
+ }
+
+ 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] 8+ messages in thread
* [LTP] [PATCH v6 3/3] syscalls/modify_ldt01: Refactor into new API
2025-04-02 9:58 [LTP] [PATCH v6 0/3] syscalls/modify_ldt: Refactor into new API Ricardo B. Marlière via ltp
2025-04-02 9:58 ` [LTP] [PATCH v6 1/3] syscalls/modify_ldt: Add lapi/ldt.h Ricardo B. Marlière via ltp
2025-04-02 9:58 ` [LTP] [PATCH v6 2/3] syscalls/modify_ldt02: Refactor into new API Ricardo B. Marlière via ltp
@ 2025-04-02 9:58 ` Ricardo B. Marlière via ltp
2025-04-07 12:41 ` Cyril Hrubis
2 siblings, 1 reply; 8+ messages in thread
From: Ricardo B. Marlière via ltp @ 2025-04-02 9:58 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 | 264 +++++----------------
.../kernel/syscalls/modify_ldt/modify_ldt03.c | 105 --------
3 files changed, 58 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..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] 8+ messages in thread
* Re: [LTP] [PATCH v6 1/3] syscalls/modify_ldt: Add lapi/ldt.h
2025-04-02 9:58 ` [LTP] [PATCH v6 1/3] syscalls/modify_ldt: Add lapi/ldt.h Ricardo B. Marlière via ltp
@ 2025-04-07 12:09 ` Cyril Hrubis
2025-04-07 12:18 ` Ricardo B. Marli��re via ltp
0 siblings, 1 reply; 8+ messages in thread
From: Cyril Hrubis @ 2025-04-07 12:09 UTC (permalink / raw)
To: Ricardo B. Marlière; +Cc: Linux Test Project
Hi!
> +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);
We should make sure that we only accept the success value here (as we do
in the rest of the safe macros) so that we catch the cases when kernel
returns an invalid value.
This should be:
if (rval == -1) {
tst_brk_(...);
} else if (rval) {
tst_brk_("modify_ltd(...) invalid retval %i", ...);
}
With that fixed:
Reviewed-by: Cyril Hrubis <chrubis@suse.cz>
--
Cyril Hrubis
chrubis@suse.cz
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [LTP] [PATCH v6 1/3] syscalls/modify_ldt: Add lapi/ldt.h
2025-04-07 12:09 ` Cyril Hrubis
@ 2025-04-07 12:18 ` Ricardo B. Marli��re via ltp
0 siblings, 0 replies; 8+ messages in thread
From: Ricardo B. Marli��re via ltp @ 2025-04-07 12:18 UTC (permalink / raw)
To: Cyril Hrubis; +Cc: Linux Test Project
On Mon Apr 7, 2025 at 9:09 AM -03, Cyril Hrubis wrote:
> Hi!
>> +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);
>
> We should make sure that we only accept the success value here (as we do
> in the rest of the safe macros) so that we catch the cases when kernel
> returns an invalid value.
>
> This should be:
>
> if (rval == -1) {
> tst_brk_(...);
> } else if (rval) {
> tst_brk_("modify_ltd(...) invalid retval %i", ...);
> }
Makes sense! Unfortunately I just sent a v7, will wait some more before
sending the next one :)
>
>
> With that fixed:
>
> Reviewed-by: Cyril Hrubis <chrubis@suse.cz>
Thanks for reviewing,
- Ricardo.
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [LTP] [PATCH v6 2/3] syscalls/modify_ldt02: Refactor into new API
2025-04-02 9:58 ` [LTP] [PATCH v6 2/3] syscalls/modify_ldt02: Refactor into new API Ricardo B. Marlière via ltp
@ 2025-04-07 12:24 ` Cyril Hrubis
0 siblings, 0 replies; 8+ messages in thread
From: Cyril Hrubis @ 2025-04-07 12:24 UTC (permalink / raw)
To: Ricardo B. Marlière; +Cc: Linux Test Project
Hi!
> --- /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)
This should be void now, since we are not checking the return value
anyways.
> +{
> + 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));
> +}
...
> + if (!pid) {
> + signal(SIGSEGV, SIG_DFL);
We do not mess with signal handlers in the new test library, so this
shouldn't be needed.
> + read_segment(0);
> + exit(1);
> + }
> +
> + 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");
> + }
This should be just:
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
--
Cyril Hrubis
chrubis@suse.cz
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [LTP] [PATCH v6 3/3] syscalls/modify_ldt01: Refactor into new API
2025-04-02 9:58 ` [LTP] [PATCH v6 3/3] syscalls/modify_ldt01: " Ricardo B. Marlière via ltp
@ 2025-04-07 12:41 ` Cyril Hrubis
0 siblings, 0 replies; 8+ messages in thread
From: Cyril Hrubis @ 2025-04-07 12:41 UTC (permalink / raw)
To: Ricardo B. Marlière; +Cc: Linux Test Project
Hi!
> 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 | 264 +++++----------------
> .../kernel/syscalls/modify_ldt/modify_ldt03.c | 105 --------
You should remove modify_ldt03 from the syscalls runtest file as well.
--
Cyril Hrubis
chrubis@suse.cz
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2025-04-07 12:41 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-04-02 9:58 [LTP] [PATCH v6 0/3] syscalls/modify_ldt: Refactor into new API Ricardo B. Marlière via ltp
2025-04-02 9:58 ` [LTP] [PATCH v6 1/3] syscalls/modify_ldt: Add lapi/ldt.h Ricardo B. Marlière via ltp
2025-04-07 12:09 ` Cyril Hrubis
2025-04-07 12:18 ` Ricardo B. Marli��re via ltp
2025-04-02 9:58 ` [LTP] [PATCH v6 2/3] syscalls/modify_ldt02: Refactor into new API Ricardo B. Marlière via ltp
2025-04-07 12:24 ` Cyril Hrubis
2025-04-02 9:58 ` [LTP] [PATCH v6 3/3] syscalls/modify_ldt01: " Ricardo B. Marlière via ltp
2025-04-07 12:41 ` Cyril Hrubis
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox