aboutsummaryrefslogtreecommitdiff
path: root/testcases/kernel/syscalls
diff options
context:
space:
mode:
Diffstat (limited to 'testcases/kernel/syscalls')
-rw-r--r--testcases/kernel/syscalls/access/access01.c9
-rw-r--r--testcases/kernel/syscalls/access/access02.c22
-rw-r--r--testcases/kernel/syscalls/access/access03.c5
-rw-r--r--testcases/kernel/syscalls/access/access04.c71
-rw-r--r--testcases/kernel/syscalls/acct/acct01.c84
-rw-r--r--testcases/kernel/syscalls/adjtimex/adjtimex02.c13
-rw-r--r--testcases/kernel/syscalls/adjtimex/adjtimex03.c13
-rw-r--r--testcases/kernel/syscalls/alarm/alarm02.c1
-rw-r--r--testcases/kernel/syscalls/bind/bind03.c6
-rw-r--r--testcases/kernel/syscalls/bpf/bpf_common.h1
-rw-r--r--testcases/kernel/syscalls/bpf/bpf_prog01.c2
-rw-r--r--testcases/kernel/syscalls/bpf/bpf_prog02.c4
-rw-r--r--testcases/kernel/syscalls/bpf/bpf_prog04.c1
-rw-r--r--testcases/kernel/syscalls/bpf/bpf_prog05.c2
-rw-r--r--testcases/kernel/syscalls/bpf/bpf_prog06.c2
-rw-r--r--testcases/kernel/syscalls/bpf/bpf_prog07.c2
-rw-r--r--testcases/kernel/syscalls/capset/capset01.c18
-rw-r--r--testcases/kernel/syscalls/capset/capset02.c20
-rw-r--r--testcases/kernel/syscalls/capset/capset03.c10
-rw-r--r--testcases/kernel/syscalls/capset/capset04.c8
-rw-r--r--testcases/kernel/syscalls/chdir/chdir01.c55
-rw-r--r--testcases/kernel/syscalls/chmod/chmod01.c28
-rw-r--r--testcases/kernel/syscalls/chown/chown02.c1
-rw-r--r--testcases/kernel/syscalls/chroot/chroot03.c46
-rw-r--r--testcases/kernel/syscalls/clone/clone04.c5
-rw-r--r--testcases/kernel/syscalls/clone3/.gitignore1
-rw-r--r--testcases/kernel/syscalls/clone3/clone302.c5
-rw-r--r--testcases/kernel/syscalls/clone3/clone303.c94
-rw-r--r--testcases/kernel/syscalls/delete_module/delete_module01.c28
-rw-r--r--testcases/kernel/syscalls/delete_module/delete_module03.c3
-rw-r--r--testcases/kernel/syscalls/dup/dup01.c25
-rw-r--r--testcases/kernel/syscalls/dup/dup02.c34
-rw-r--r--testcases/kernel/syscalls/dup/dup03.c34
-rw-r--r--testcases/kernel/syscalls/dup/dup04.c44
-rw-r--r--testcases/kernel/syscalls/dup/dup05.c46
-rw-r--r--testcases/kernel/syscalls/epoll_ctl/epoll_ctl02.c4
-rw-r--r--testcases/kernel/syscalls/epoll_ctl/epoll_ctl03.c2
-rw-r--r--testcases/kernel/syscalls/epoll_ctl/epoll_ctl04.c4
-rw-r--r--testcases/kernel/syscalls/epoll_ctl/epoll_ctl05.c6
-rw-r--r--testcases/kernel/syscalls/epoll_pwait/epoll_pwait01.c2
-rw-r--r--testcases/kernel/syscalls/epoll_pwait/epoll_pwait02.c2
-rw-r--r--testcases/kernel/syscalls/epoll_pwait/epoll_pwait03.c2
-rw-r--r--testcases/kernel/syscalls/epoll_pwait/epoll_pwait04.c2
-rw-r--r--testcases/kernel/syscalls/epoll_pwait/epoll_pwait05.c2
-rw-r--r--testcases/kernel/syscalls/epoll_wait/.gitignore3
-rw-r--r--testcases/kernel/syscalls/epoll_wait/epoll_wait02.c2
-rw-r--r--testcases/kernel/syscalls/epoll_wait/epoll_wait03.c2
-rw-r--r--testcases/kernel/syscalls/epoll_wait/epoll_wait04.c2
-rw-r--r--testcases/kernel/syscalls/epoll_wait/epoll_wait05.c126
-rw-r--r--testcases/kernel/syscalls/epoll_wait/epoll_wait06.c107
-rw-r--r--testcases/kernel/syscalls/epoll_wait/epoll_wait07.c73
-rw-r--r--testcases/kernel/syscalls/eventfd/.gitignore5
-rw-r--r--testcases/kernel/syscalls/eventfd/eventfd01.c749
-rw-r--r--testcases/kernel/syscalls/eventfd/eventfd02.c53
-rw-r--r--testcases/kernel/syscalls/eventfd/eventfd03.c57
-rw-r--r--testcases/kernel/syscalls/eventfd/eventfd04.c60
-rw-r--r--testcases/kernel/syscalls/eventfd/eventfd05.c47
-rw-r--r--testcases/kernel/syscalls/eventfd/eventfd06.c174
-rw-r--r--testcases/kernel/syscalls/eventfd2/eventfd2.h18
-rw-r--r--testcases/kernel/syscalls/eventfd2/eventfd2_01.c148
-rw-r--r--testcases/kernel/syscalls/eventfd2/eventfd2_02.c147
-rw-r--r--testcases/kernel/syscalls/eventfd2/eventfd2_03.c128
-rw-r--r--testcases/kernel/syscalls/execve/execve01.c2
-rw-r--r--testcases/kernel/syscalls/execve/execve06.c2
-rw-r--r--testcases/kernel/syscalls/faccessat/.gitignore1
-rw-r--r--testcases/kernel/syscalls/faccessat/faccessat01.c203
-rw-r--r--testcases/kernel/syscalls/faccessat/faccessat02.c67
-rw-r--r--testcases/kernel/syscalls/faccessat2/.gitignore2
-rw-r--r--testcases/kernel/syscalls/faccessat2/Makefile9
-rw-r--r--testcases/kernel/syscalls/faccessat2/faccessat201.c88
-rw-r--r--testcases/kernel/syscalls/faccessat2/faccessat202.c102
-rw-r--r--testcases/kernel/syscalls/fanotify/fanotify.h21
-rw-r--r--testcases/kernel/syscalls/fanotify/fanotify13.c63
-rw-r--r--testcases/kernel/syscalls/fanotify/fanotify14.c198
-rw-r--r--testcases/kernel/syscalls/fanotify/fanotify22.c33
-rw-r--r--testcases/kernel/syscalls/fanotify/fanotify23.c8
-rw-r--r--testcases/kernel/syscalls/fchmod/fchmod02.c20
-rw-r--r--testcases/kernel/syscalls/fchmod/fchmod03.c9
-rw-r--r--testcases/kernel/syscalls/fchmod/fchmod04.c9
-rw-r--r--testcases/kernel/syscalls/fchown/fchown02.c1
-rw-r--r--testcases/kernel/syscalls/fcntl/.gitignore2
-rw-r--r--testcases/kernel/syscalls/fcntl/fcntl06.c165
-rw-r--r--testcases/kernel/syscalls/fcntl/fcntl11.c6
-rw-r--r--testcases/kernel/syscalls/fcntl/fcntl19.c6
-rw-r--r--testcases/kernel/syscalls/fcntl/fcntl20.c6
-rw-r--r--testcases/kernel/syscalls/fcntl/fcntl21.c6
-rw-r--r--testcases/kernel/syscalls/fcntl/fcntl30.c111
-rw-r--r--testcases/kernel/syscalls/fcntl/fcntl33.c2
-rw-r--r--testcases/kernel/syscalls/finit_module/finit_module01.c3
-rw-r--r--testcases/kernel/syscalls/finit_module/finit_module02.c10
-rw-r--r--testcases/kernel/syscalls/flistxattr/flistxattr01.c2
-rw-r--r--testcases/kernel/syscalls/fork/fork03.c144
-rw-r--r--testcases/kernel/syscalls/fsconfig/.gitignore1
-rw-r--r--testcases/kernel/syscalls/fsconfig/fsconfig03.c97
-rw-r--r--testcases/kernel/syscalls/futex/Makefile3
-rw-r--r--testcases/kernel/syscalls/futex/futex_wake04.c1
-rw-r--r--testcases/kernel/syscalls/getcpu/getcpu01.c5
-rw-r--r--testcases/kernel/syscalls/geteuid/geteuid01.c91
-rw-r--r--testcases/kernel/syscalls/geteuid/geteuid02.c89
-rw-r--r--testcases/kernel/syscalls/getgroups/getgroups01.c2
-rw-r--r--testcases/kernel/syscalls/gethostname/gethostname01.c166
-rw-r--r--testcases/kernel/syscalls/getpgid/getpgid01.c160
-rw-r--r--testcases/kernel/syscalls/getpgid/getpgid02.c143
-rw-r--r--testcases/kernel/syscalls/getpgrp/getpgrp01.c166
-rw-r--r--testcases/kernel/syscalls/getpid/getpid02.c1
-rw-r--r--testcases/kernel/syscalls/getrusage/getrusage04.c11
-rw-r--r--testcases/kernel/syscalls/init_module/init_module01.c3
-rw-r--r--testcases/kernel/syscalls/init_module/init_module02.c9
-rw-r--r--testcases/kernel/syscalls/io_uring/io_uring01.c5
-rw-r--r--testcases/kernel/syscalls/io_uring/io_uring02.c5
-rw-r--r--testcases/kernel/syscalls/ioctl/Makefile2
-rw-r--r--testcases/kernel/syscalls/ioctl/ioctl01.c84
-rwxr-xr-xtestcases/kernel/syscalls/ioctl/test_ioctl23
-rw-r--r--testcases/kernel/syscalls/ioprio/ioprio.h31
-rw-r--r--testcases/kernel/syscalls/ioprio/ioprio_get01.c9
-rw-r--r--testcases/kernel/syscalls/ioprio/ioprio_set01.c9
-rw-r--r--testcases/kernel/syscalls/ioprio/ioprio_set02.c9
-rw-r--r--testcases/kernel/syscalls/ioprio/ioprio_set03.c11
-rw-r--r--testcases/kernel/syscalls/ipc/msgctl/msgctl01.c2
-rw-r--r--testcases/kernel/syscalls/ipc/msgget/msgget02.c6
-rw-r--r--testcases/kernel/syscalls/ipc/msgstress/msgstress03.c7
-rw-r--r--testcases/kernel/syscalls/ipc/semget/.gitignore2
-rw-r--r--testcases/kernel/syscalls/ipc/semget/Makefile4
-rw-r--r--testcases/kernel/syscalls/ipc/semget/semget01.c187
-rw-r--r--testcases/kernel/syscalls/ipc/semget/semget02.c221
-rw-r--r--testcases/kernel/syscalls/ipc/semget/semget03.c133
-rw-r--r--testcases/kernel/syscalls/ipc/semget/semget05.c189
-rw-r--r--testcases/kernel/syscalls/ipc/semget/semget06.c143
-rw-r--r--testcases/kernel/syscalls/ipc/semop/.gitignore2
-rw-r--r--testcases/kernel/syscalls/ipc/semop/Makefile5
-rw-r--r--testcases/kernel/syscalls/ipc/semop/semop04.c93
-rw-r--r--testcases/kernel/syscalls/ipc/semop/semop05.c157
-rw-r--r--testcases/kernel/syscalls/ipc/shmget/shmget02.c28
-rw-r--r--testcases/kernel/syscalls/keyctl/keyctl02.c1
-rw-r--r--testcases/kernel/syscalls/keyctl/keyctl07.c2
-rw-r--r--testcases/kernel/syscalls/madvise/.gitignore1
-rw-r--r--testcases/kernel/syscalls/madvise/Makefile2
-rw-r--r--testcases/kernel/syscalls/madvise/madvise01.c1
-rw-r--r--testcases/kernel/syscalls/madvise/madvise02.c1
-rw-r--r--testcases/kernel/syscalls/madvise/madvise06.c10
-rw-r--r--testcases/kernel/syscalls/madvise/madvise11.c442
-rw-r--r--testcases/kernel/syscalls/memfd_create/memfd_create02.c4
-rw-r--r--testcases/kernel/syscalls/memfd_create/memfd_create04.c27
-rw-r--r--testcases/kernel/syscalls/mknod/mknod01.c137
-rw-r--r--testcases/kernel/syscalls/mknod/mknod02.c316
-rw-r--r--testcases/kernel/syscalls/mlock/mlock01.c159
-rw-r--r--testcases/kernel/syscalls/mlock/mlock02.c190
-rw-r--r--testcases/kernel/syscalls/mlock/mlock03.c131
-rw-r--r--testcases/kernel/syscalls/mlock/mlock04.c110
-rw-r--r--testcases/kernel/syscalls/mmap/.gitignore2
-rw-r--r--testcases/kernel/syscalls/mmap/mmap02.c204
-rw-r--r--testcases/kernel/syscalls/mmap/mmap05.c220
-rw-r--r--testcases/kernel/syscalls/mmap/mmap06.c176
-rw-r--r--testcases/kernel/syscalls/mmap/mmap07.c146
-rw-r--r--testcases/kernel/syscalls/mmap/mmap08.c155
-rw-r--r--testcases/kernel/syscalls/mmap/mmap17.c1
-rw-r--r--testcases/kernel/syscalls/mmap/mmap20.c64
-rw-r--r--testcases/kernel/syscalls/mount/.gitignore1
-rw-r--r--testcases/kernel/syscalls/mount/mount03.c2
-rw-r--r--testcases/kernel/syscalls/mount/mount07.c177
-rw-r--r--testcases/kernel/syscalls/mount_setattr/mount_setattr01.c1
-rw-r--r--testcases/kernel/syscalls/mprotect/.gitignore1
-rw-r--r--testcases/kernel/syscalls/mprotect/mprotect05.c69
-rw-r--r--testcases/kernel/syscalls/mq_notify/.gitignore1
-rw-r--r--testcases/kernel/syscalls/mq_notify/mq_notify02.c93
-rw-r--r--testcases/kernel/syscalls/mq_notify/mq_notify03.c99
-rw-r--r--testcases/kernel/syscalls/mremap/.gitignore1
-rw-r--r--testcases/kernel/syscalls/mremap/mremap06.c134
-rw-r--r--testcases/kernel/syscalls/msync/msync01.c2
-rw-r--r--testcases/kernel/syscalls/munlock/munlock01.c181
-rw-r--r--testcases/kernel/syscalls/munlock/munlock02.c212
-rw-r--r--testcases/kernel/syscalls/munmap/munmap01.c2
-rw-r--r--testcases/kernel/syscalls/munmap/munmap02.c2
-rw-r--r--testcases/kernel/syscalls/name_to_handle_at/name_to_handle_at01.c2
-rw-r--r--testcases/kernel/syscalls/open_by_handle_at/open_by_handle_at01.c2
-rw-r--r--testcases/kernel/syscalls/personality/personality01.c93
-rw-r--r--testcases/kernel/syscalls/personality/personality02.c64
-rw-r--r--testcases/kernel/syscalls/pipe/.gitignore1
-rw-r--r--testcases/kernel/syscalls/pipe/pipe03.c51
-rw-r--r--testcases/kernel/syscalls/pipe/pipe06.c138
-rw-r--r--testcases/kernel/syscalls/pipe/pipe07.c203
-rw-r--r--testcases/kernel/syscalls/pipe/pipe08.c152
-rw-r--r--testcases/kernel/syscalls/pipe/pipe10.c178
-rw-r--r--testcases/kernel/syscalls/pipe/pipe14.c46
-rw-r--r--testcases/kernel/syscalls/prctl/prctl04.c1
-rw-r--r--testcases/kernel/syscalls/preadv2/preadv203.c2
-rw-r--r--testcases/kernel/syscalls/process_madvise/.gitignore1
-rw-r--r--testcases/kernel/syscalls/process_madvise/Makefile (renamed from testcases/kernel/syscalls/paging/Makefile)3
-rw-r--r--testcases/kernel/syscalls/process_madvise/process_madvise.h101
-rw-r--r--testcases/kernel/syscalls/process_madvise/process_madvise01.c131
-rw-r--r--testcases/kernel/syscalls/quotactl/quotactl08.c1
-rw-r--r--testcases/kernel/syscalls/readahead/readahead02.c15
-rw-r--r--testcases/kernel/syscalls/readlinkat/readlinkat01.c182
-rw-r--r--testcases/kernel/syscalls/readlinkat/readlinkat02.c127
-rw-r--r--testcases/kernel/syscalls/recvmsg/recvmsg01.c718
-rw-r--r--testcases/kernel/syscalls/sbrk/sbrk01.c121
-rw-r--r--testcases/kernel/syscalls/sbrk/sbrk02.c101
-rw-r--r--testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval01.c3
-rw-r--r--testcases/kernel/syscalls/sendfile/sendfile04.c1
-rw-r--r--testcases/kernel/syscalls/setgroups/.gitignore2
-rw-r--r--testcases/kernel/syscalls/setgroups/setgroups01.c211
-rw-r--r--testcases/kernel/syscalls/setgroups/setgroups02.c191
-rw-r--r--testcases/kernel/syscalls/setgroups/setgroups03.c245
-rw-r--r--testcases/kernel/syscalls/setgroups/setgroups04.c163
-rw-r--r--testcases/kernel/syscalls/setpgid/setpgid02.c14
-rw-r--r--testcases/kernel/syscalls/setpgid/setpgid03.c6
-rw-r--r--testcases/kernel/syscalls/setreuid/setreuid04.c150
-rw-r--r--testcases/kernel/syscalls/setreuid/setreuid07.c196
-rw-r--r--testcases/kernel/syscalls/setsockopt/setsockopt02.c4
-rw-r--r--testcases/kernel/syscalls/setsockopt/setsockopt08.c80
-rw-r--r--testcases/kernel/syscalls/sockioctl/sockioctl01.c4
-rw-r--r--testcases/kernel/syscalls/stat/stat01.c6
-rw-r--r--testcases/kernel/syscalls/statvfs/statvfs02.c1
-rw-r--r--testcases/kernel/syscalls/statx/.gitignore3
-rw-r--r--testcases/kernel/syscalls/statx/statx01.c1
-rw-r--r--testcases/kernel/syscalls/statx/statx02.c1
-rw-r--r--testcases/kernel/syscalls/statx/statx03.c1
-rw-r--r--testcases/kernel/syscalls/statx/statx04.c3
-rw-r--r--testcases/kernel/syscalls/statx/statx05.c1
-rw-r--r--testcases/kernel/syscalls/statx/statx06.c4
-rw-r--r--testcases/kernel/syscalls/statx/statx07.c14
-rw-r--r--testcases/kernel/syscalls/statx/statx08.c1
-rw-r--r--testcases/kernel/syscalls/statx/statx09.c15
-rw-r--r--testcases/kernel/syscalls/statx/statx10.c93
-rw-r--r--testcases/kernel/syscalls/statx/statx11.c89
-rw-r--r--testcases/kernel/syscalls/statx/statx12.c95
-rw-r--r--testcases/kernel/syscalls/switch/endian_switch01.c27
-rw-r--r--testcases/kernel/syscalls/symlink/symlink01.c8
-rw-r--r--testcases/kernel/syscalls/timerfd/timerfd_create01.c99
-rw-r--r--testcases/kernel/syscalls/uname/uname04.c4
-rw-r--r--testcases/kernel/syscalls/utils/compat_uid.h2
-rw-r--r--testcases/kernel/syscalls/utils/ioprio.h46
-rw-r--r--testcases/kernel/syscalls/utime/utime02.c1
-rw-r--r--testcases/kernel/syscalls/utime/utime04.c7
-rw-r--r--testcases/kernel/syscalls/utime/utime05.c1
-rw-r--r--testcases/kernel/syscalls/utime/utime06.c9
-rw-r--r--testcases/kernel/syscalls/utimensat/utimensat01.c2
-rw-r--r--testcases/kernel/syscalls/write/write02.c17
-rw-r--r--testcases/kernel/syscalls/write/write04.c2
-rw-r--r--testcases/kernel/syscalls/write/write05.c39
240 files changed, 5985 insertions, 8077 deletions
diff --git a/testcases/kernel/syscalls/access/access01.c b/testcases/kernel/syscalls/access/access01.c
index c9a076dfe..391c8d44b 100644
--- a/testcases/kernel/syscalls/access/access01.c
+++ b/testcases/kernel/syscalls/access/access01.c
@@ -1,11 +1,16 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
- * AUTHOR : William Roske
+ * Copyright (c) Linux Test Project, 2003-2023
+ * Author: William Roske
*/
-/*
+
+/*\
+ * [Description]
+ *
* Basic test for access(2) using F_OK, R_OK, W_OK and X_OK
*/
+
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
diff --git a/testcases/kernel/syscalls/access/access02.c b/testcases/kernel/syscalls/access/access02.c
index bf636f9f4..c8fe0d0dc 100644
--- a/testcases/kernel/syscalls/access/access02.c
+++ b/testcases/kernel/syscalls/access/access02.c
@@ -1,21 +1,19 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
- * Copyright (c) International Business Machines Corp., 2001
+ * Copyright (c) International Business Machines Corp., 2001
+ * Copyright (c) Guangwen Feng <fenggw-fnst@cn.fujitsu.com>, 2016
+ * Copyright (c) Linux Test Project, 2002-2023
+ * Ported to LTP: Wayne Boyer
*/
-/*
- * Test Description:
- * Verify that access() succeeds to check the existence or read/write/execute
- * permissions on a file if the mode argument passed was F_OK/R_OK/W_OK/X_OK.
+/*\
+ * [Description]
*
- * Also verify that, access() succeeds to test the accessibility of the file
- * referred to by symbolic link if the pathname points to a symbolic link.
+ * Test access(2) syscall
*
- * As well as verify that, these test files can be
- * stat/read/written/executed indeed as root and nobody respectively.
- *
- * Ported to LTP: Wayne Boyer
- * 06/2016 Modified by Guangwen Feng <fenggw-fnst@cn.fujitsu.com>
+ * - check the existence or read/write/execute permissions on a file (mode argument: F_OK/R_OK/W_OK/X_OK)
+ * - test the accessibility of the file referred to by symbolic link if the pathname points to a symbolic link
+ * - file can be stat/read/written/executed as root and nobody
*/
#include <sys/types.h>
diff --git a/testcases/kernel/syscalls/access/access03.c b/testcases/kernel/syscalls/access/access03.c
index ae3f676b1..7cae1ec2e 100644
--- a/testcases/kernel/syscalls/access/access03.c
+++ b/testcases/kernel/syscalls/access/access03.c
@@ -1,9 +1,12 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) Linux Test Project, 2003-2023
*/
-/*
+/*\
+ * [Description]
+ *
* access(2) test for errno(s) EFAULT as root and nobody respectively.
*/
diff --git a/testcases/kernel/syscalls/access/access04.c b/testcases/kernel/syscalls/access/access04.c
index 2d6dd70e8..b5764a5dd 100644
--- a/testcases/kernel/syscalls/access/access04.c
+++ b/testcases/kernel/syscalls/access/access04.c
@@ -2,26 +2,27 @@
/*
* Copyright (c) International Business Machines Corp., 2001
* Copyright (c) 2013 Fujitsu Ltd.
+ * Copyright (c) Linux Test Project, 2003-2023
+ * Ported to LTP: Wayne Boyer
+ * 11/2013 Ported by Xiaoguang Wang <wangxg.fnst@cn.fujitsu.com>
+ * 11/2016 Modified by Guangwen Feng <fenggw-fnst@cn.fujitsu.com>
*/
-/*
- * Verify that,
- * 1) access() fails with -1 return value and sets errno to EINVAL
- * if the specified access mode argument is invalid.
- * 2) access() fails with -1 return value and sets errno to ENOENT
- * if the specified file doesn't exist (or pathname is NULL).
- * 3) access() fails with -1 return value and sets errno to ENAMETOOLONG
- * if the pathname size is > PATH_MAX characters.
- * 4) access() fails with -1 return value and sets errno to ENOTDIR
- * if a component used as a directory in pathname is not a directory.
- * 5) access() fails with -1 return value and sets errno to ELOOP
- * if too many symbolic links were encountered in resolving pathname.
- * 6) access() fails with -1 return value and sets errno to EROFS
- * if write permission was requested for files on a read-only file system.
+/*\
+ * [Description]
*
- * Ported to LTP: Wayne Boyer
- * 11/2013 Ported by Xiaoguang Wang <wangxg.fnst@cn.fujitsu.com>
- * 11/2016 Modified by Guangwen Feng <fenggw-fnst@cn.fujitsu.com>
+ * - access() fails with -1 return value and sets errno to EINVAL
+ * if the specified access mode argument is invalid.
+ * - access() fails with -1 return value and sets errno to ENOENT
+ * if the specified file doesn't exist (or pathname is NULL).
+ * - access() fails with -1 return value and sets errno to ENAMETOOLONG
+ * if the pathname size is > PATH_MAX characters.
+ * - access() fails with -1 return value and sets errno to ENOTDIR
+ * if a component used as a directory in pathname is not a directory.
+ * - access() fails with -1 return value and sets errno to ELOOP
+ * if too many symbolic links were encountered in resolving pathname.
+ * - access() fails with -1 return value and sets errno to EROFS
+ * if write permission was requested for files on a read-only file system.
*/
#include <errno.h>
@@ -39,26 +40,32 @@
#define SNAME1 "symlink1"
#define SNAME2 "symlink2"
#define MNT_POINT "mntpoint"
+#define LONGPATHSIZE (PATH_MAX + 2)
static uid_t uid;
-static char longpathname[PATH_MAX + 2];
+static char *longpathname;
+static char *fname1;
+static char *fname2;
+static char *sname1;
+static char *empty_fname;
+static char *mnt_point;
static struct tcase {
- const char *pathname;
+ char **pathname;
int mode;
int exp_errno;
} tcases[] = {
- {FNAME1, -1, EINVAL},
- {"", W_OK, ENOENT},
- {longpathname, R_OK, ENAMETOOLONG},
- {FNAME2, R_OK, ENOTDIR},
- {SNAME1, R_OK, ELOOP},
- {MNT_POINT, W_OK, EROFS}
+ {&fname1, -1, EINVAL},
+ {&empty_fname, W_OK, ENOENT},
+ {&longpathname, R_OK, ENAMETOOLONG},
+ {&fname2, R_OK, ENOTDIR},
+ {&sname1, R_OK, ELOOP},
+ {&mnt_point, W_OK, EROFS}
};
static void access_test(struct tcase *tc, const char *user)
{
- TST_EXP_FAIL(access(tc->pathname, tc->mode), tc->exp_errno,
+ TST_EXP_FAIL(access(*tc->pathname, tc->mode), tc->exp_errno,
"access as %s", user);
}
@@ -86,7 +93,8 @@ static void setup(void)
uid = pw->pw_uid;
- memset(longpathname, 'a', sizeof(longpathname) - 1);
+ memset(longpathname, 'a', LONGPATHSIZE - 1);
+ longpathname[LONGPATHSIZE-1] = 0;
SAFE_TOUCH(FNAME1, 0333, NULL);
SAFE_TOUCH(DNAME, 0644, NULL);
@@ -103,4 +111,13 @@ static struct tst_test test = {
.mntpoint = MNT_POINT,
.setup = setup,
.test = verify_access,
+ .bufs = (struct tst_buffers []) {
+ {&fname1, .str = FNAME1},
+ {&fname2, .str = FNAME2},
+ {&sname1, .str = SNAME1},
+ {&empty_fname, .str = ""},
+ {&longpathname, .size = LONGPATHSIZE},
+ {&mnt_point, .str = MNT_POINT},
+ {}
+ }
};
diff --git a/testcases/kernel/syscalls/acct/acct01.c b/testcases/kernel/syscalls/acct/acct01.c
index 254d7b503..52c4d41da 100644
--- a/testcases/kernel/syscalls/acct/acct01.c
+++ b/testcases/kernel/syscalls/acct/acct01.c
@@ -27,17 +27,25 @@
#define DIR_MODE (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP| \
S_IXGRP|S_IROTH|S_IXOTH)
#define FILE_EISDIR "."
-#define FILE_EACCES "/dev/null"
+#define FILE_EACCESS "/dev/null"
#define FILE_ENOENT "/tmp/does/not/exist"
#define FILE_ENOTDIR "./tmpfile/"
-#define TEST_TMPFILE "./tmpfile"
-#define TEST_ELOOP "test_file_eloop1"
-#define TEST_ENAMETOOLONG nametoolong
-#define TEST_EROFS "mntpoint/file"
+#define FILE_TMPFILE "./tmpfile"
+#define FILE_ELOOP "test_file_eloop1"
+#define FILE_EROFS "ro_mntpoint/file"
-static char nametoolong[PATH_MAX+2];
static struct passwd *ltpuser;
+static char *file_eisdir;
+static char *file_eaccess;
+static char *file_enoent;
+static char *file_enotdir;
+static char *file_tmpfile;
+static char *file_eloop;
+static char *file_enametoolong;
+static char *file_erofs;
+static char *file_null;
+
static void setup_euid(void)
{
SAFE_SETEUID(ltpuser->pw_uid);
@@ -49,21 +57,21 @@ static void cleanup_euid(void)
}
static struct test_case {
- char *filename;
- char *exp_errval;
+ char **filename;
+ char *desc;
int exp_errno;
void (*setupfunc) ();
void (*cleanfunc) ();
} tcases[] = {
- {FILE_EISDIR, "EISDIR", EISDIR, NULL, NULL},
- {FILE_EACCES, "EACCES", EACCES, NULL, NULL},
- {FILE_ENOENT, "ENOENT", ENOENT, NULL, NULL},
- {FILE_ENOTDIR, "ENOTDIR", ENOTDIR, NULL, NULL},
- {TEST_TMPFILE, "EPERM", EPERM, setup_euid, cleanup_euid},
- {NULL, "EPERM", EPERM, setup_euid, cleanup_euid},
- {TEST_ELOOP, "ELOOP", ELOOP, NULL, NULL},
- {TEST_ENAMETOOLONG, "ENAMETOOLONG", ENAMETOOLONG, NULL, NULL},
- {TEST_EROFS, "EROFS", EROFS, NULL, NULL},
+ {&file_eisdir, FILE_EISDIR, EISDIR, NULL, NULL},
+ {&file_eaccess, FILE_EACCESS, EACCES, NULL, NULL},
+ {&file_enoent, FILE_ENOENT, ENOENT, NULL, NULL},
+ {&file_enotdir, FILE_ENOTDIR, ENOTDIR, NULL, NULL},
+ {&file_tmpfile, FILE_TMPFILE, EPERM, setup_euid, cleanup_euid},
+ {&file_null, "NULL", EPERM, setup_euid, cleanup_euid},
+ {&file_eloop, FILE_ELOOP, ELOOP, NULL, NULL},
+ {&file_enametoolong, "aaaa...", ENAMETOOLONG, NULL, NULL},
+ {&file_erofs, FILE_EROFS, EROFS, NULL, NULL},
};
static void setup(void)
@@ -76,10 +84,10 @@ static void setup(void)
ltpuser = SAFE_GETPWNAM("nobody");
- fd = SAFE_CREAT(TEST_TMPFILE, 0777);
+ fd = SAFE_CREAT(FILE_TMPFILE, 0777);
SAFE_CLOSE(fd);
- TEST(acct(TEST_TMPFILE));
+ TEST(acct(FILE_TMPFILE));
if (TST_RET == -1)
tst_brk(TBROK | TTERRNO, "acct failed unexpectedly");
@@ -89,11 +97,11 @@ static void setup(void)
tst_brk(TBROK | TTERRNO, "acct(NULL) failed");
/* ELOOP SETTING */
- SAFE_SYMLINK(TEST_ELOOP, "test_file_eloop2");
- SAFE_SYMLINK("test_file_eloop2", TEST_ELOOP);
+ SAFE_SYMLINK(FILE_ELOOP, "test_file_eloop2");
+ SAFE_SYMLINK("test_file_eloop2", FILE_ELOOP);
- /* ENAMETOOLONG SETTING */
- memset(nametoolong, 'a', PATH_MAX+1);
+ memset(file_enametoolong, 'a', PATH_MAX+1);
+ file_enametoolong[PATH_MAX+1] = 0;
}
static void verify_acct(unsigned int nr)
@@ -103,31 +111,29 @@ static void verify_acct(unsigned int nr)
if (tcase->setupfunc)
tcase->setupfunc();
- TEST(acct(tcase->filename));
+ TST_EXP_FAIL(acct(*tcase->filename), tcase->exp_errno,
+ "acct(%s)", tcase->desc);
if (tcase->cleanfunc)
tcase->cleanfunc();
-
- if (TST_RET != -1) {
- tst_res(TFAIL, "acct(%s) succeeded unexpectedly",
- tcase->filename);
- return;
- }
-
- if (TST_ERR == tcase->exp_errno) {
- tst_res(TPASS | TTERRNO, "acct() failed as expected");
- } else {
- tst_res(TFAIL | TTERRNO,
- "acct() failed, expected: %s",
- tst_strerrno(tcase->exp_errno));
- }
}
static struct tst_test test = {
.needs_root = 1,
- .mntpoint = "mntpoint",
+ .mntpoint = "ro_mntpoint",
.needs_rofs = 1,
.tcnt = ARRAY_SIZE(tcases),
.setup = setup,
.test = verify_acct,
+ .bufs = (struct tst_buffers []) {
+ {&file_eisdir, .str = FILE_EISDIR},
+ {&file_eaccess, .str = FILE_EACCESS},
+ {&file_enoent, .str = FILE_ENOENT},
+ {&file_enotdir, .str = FILE_ENOTDIR},
+ {&file_tmpfile, .str = FILE_TMPFILE},
+ {&file_eloop, .str = FILE_ELOOP},
+ {&file_enametoolong, .size = PATH_MAX+2},
+ {&file_erofs, .str = FILE_EROFS},
+ {}
+ }
};
diff --git a/testcases/kernel/syscalls/adjtimex/adjtimex02.c b/testcases/kernel/syscalls/adjtimex/adjtimex02.c
index dab640ff3..e66ba2a5c 100644
--- a/testcases/kernel/syscalls/adjtimex/adjtimex02.c
+++ b/testcases/kernel/syscalls/adjtimex/adjtimex02.c
@@ -14,11 +14,6 @@
* - EFAULT with SET_MODE and invalid timex pointer
* - EINVAL with ADJ_TICK greater than max tick
* - EINVAL with ADJ_TICK smaller than min tick
- *
- * On kernels older than 2.6.26:
- *
- * - EINVAL with AJD_OFFSET smaller than min offset
- * - EINVAL with AJD_OFFSET greater than max offset
*/
#include <errno.h>
@@ -57,8 +52,6 @@ static struct test_case {
{.modes = SET_MODE, .exp_err = EFAULT},
{.modes = ADJ_TICK, .lowlimit = 900000, .delta = 1, .exp_err = EINVAL},
{.modes = ADJ_TICK, .highlimit = 1100000, .delta = 1, .exp_err = EINVAL},
- {.modes = ADJ_OFFSET, .highlimit = 512000L, .delta = 1, .exp_err = EINVAL},
- {.modes = ADJ_OFFSET, .lowlimit = -512000L, .delta = -1, .exp_err = EINVAL},
};
static struct test_variants
@@ -93,12 +86,6 @@ static void verify_adjtimex(unsigned int i)
if (tc[i].highlimit)
buf->tick = tc[i].highlimit + tc[i].delta;
}
- if (tc[i].modes == ADJ_OFFSET) {
- if (tc[i].lowlimit || tc[i].highlimit) {
- tst_res(TCONF, "Newer kernels normalize offset value outside range");
- return;
- }
- }
}
if (tc[i].exp_err == EFAULT) {
diff --git a/testcases/kernel/syscalls/adjtimex/adjtimex03.c b/testcases/kernel/syscalls/adjtimex/adjtimex03.c
index 333cabf11..7056973cc 100644
--- a/testcases/kernel/syscalls/adjtimex/adjtimex03.c
+++ b/testcases/kernel/syscalls/adjtimex/adjtimex03.c
@@ -1,14 +1,16 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
- * Copyright (c) Zilogic Systems Pvt. Ltd, 2020. All Rights Reserved.
- * Email: <code@zilogic.com>
+ * Copyright (c) Zilogic Systems Pvt. Ltd <code@zilogic.com>, 2020
+ * Copyright (c) Linux Test Project, 2021-2023
*
* Based on testcases/kernel/syscalls/adjtimex/adjtimex01.c
* Copyright (c) Wipro Technologies Ltd, 2002.
+ */
+
+/*\
+ * [Description]
*
- * CVE-2018-11508
- *
- * Test 4-byte kernel data leak via adjtimex
+ * CVE-2018-11508: Test 4-byte kernel data leak via adjtimex.
*
* On calling the adjtimex() function call with invalid mode (let's say
* 0x8000), ideally all the parameters should return with null data. But,
@@ -64,6 +66,7 @@ void verify_adjtimex(void)
break;
}
}
+
if (data_leak != 0)
tst_res(TFAIL, "Data leak observed");
else
diff --git a/testcases/kernel/syscalls/alarm/alarm02.c b/testcases/kernel/syscalls/alarm/alarm02.c
index b2fde03c8..fcf70c5f3 100644
--- a/testcases/kernel/syscalls/alarm/alarm02.c
+++ b/testcases/kernel/syscalls/alarm/alarm02.c
@@ -9,6 +9,7 @@
* [Description]
*
* Verify that alarm() returns:
+ *
* - zero when there was no previously scheduled alarm
* - number of seconds remaining until any previously scheduled alarm
*/
diff --git a/testcases/kernel/syscalls/bind/bind03.c b/testcases/kernel/syscalls/bind/bind03.c
index 37a040b29..8c95cd799 100644
--- a/testcases/kernel/syscalls/bind/bind03.c
+++ b/testcases/kernel/syscalls/bind/bind03.c
@@ -43,8 +43,12 @@ static void run(void)
* locks the socket and does all the checks and the node is not removed
* in the error path. For now we will unlink the node here so that the
* test works fine when the run() function is executed in a loop.
+ * From v5.14-rc1 the kernel has fix above issue.
*/
- unlink(SNAME_B);
+ if (tst_kvercmp(5, 14, 0) >= 0)
+ TST_EXP_FAIL(unlink(SNAME_B), ENOENT, "check exist of SNAME_B");
+ else
+ unlink(SNAME_B);
}
static void setup(void)
diff --git a/testcases/kernel/syscalls/bpf/bpf_common.h b/testcases/kernel/syscalls/bpf/bpf_common.h
index 39764ba1f..a0800d19b 100644
--- a/testcases/kernel/syscalls/bpf/bpf_common.h
+++ b/testcases/kernel/syscalls/bpf/bpf_common.h
@@ -13,6 +13,7 @@
#include "lapi/socket.h"
#define BPF_MEMLOCK_ADD (2*1024*1024)
+#define BUFSIZE 8192
/* map[array_indx] = reg_to_save
*
diff --git a/testcases/kernel/syscalls/bpf/bpf_prog01.c b/testcases/kernel/syscalls/bpf/bpf_prog01.c
index e2fc80a9f..de4f68cef 100644
--- a/testcases/kernel/syscalls/bpf/bpf_prog01.c
+++ b/testcases/kernel/syscalls/bpf/bpf_prog01.c
@@ -63,7 +63,7 @@ int load_prog(int fd)
BPF_EXIT_INSN(), /* return r0 */
};
- bpf_init_prog_attr(attr, PROG, sizeof(PROG), log, BUFSIZ);
+ bpf_init_prog_attr(attr, PROG, sizeof(PROG), log, BUFSIZE);
return bpf_load_prog(attr, log);
}
diff --git a/testcases/kernel/syscalls/bpf/bpf_prog02.c b/testcases/kernel/syscalls/bpf/bpf_prog02.c
index b40ea0f1d..fd3e535c1 100644
--- a/testcases/kernel/syscalls/bpf/bpf_prog02.c
+++ b/testcases/kernel/syscalls/bpf/bpf_prog02.c
@@ -64,7 +64,7 @@ static int load_prog(int fd)
BPF_EXIT_INSN(), /* 26: return r0 */
};
- bpf_init_prog_attr(attr, insn, sizeof(insn), log, BUFSIZ);
+ bpf_init_prog_attr(attr, insn, sizeof(insn), log, BUFSIZE);
return bpf_load_prog(attr, log);
}
@@ -117,7 +117,7 @@ static struct tst_test test = {
.bufs = (struct tst_buffers []) {
{&key, .size = sizeof(*key)},
{&val, .size = sizeof(*val)},
- {&log, .size = BUFSIZ},
+ {&log, .size = BUFSIZE},
{&attr, .size = sizeof(*attr)},
{&msg, .size = sizeof(MSG)},
{},
diff --git a/testcases/kernel/syscalls/bpf/bpf_prog04.c b/testcases/kernel/syscalls/bpf/bpf_prog04.c
index ebee26cbc..cf3bb1254 100644
--- a/testcases/kernel/syscalls/bpf/bpf_prog04.c
+++ b/testcases/kernel/syscalls/bpf/bpf_prog04.c
@@ -28,7 +28,6 @@
#include "tst_capability.h"
#include "bpf_common.h"
-#define BUFSIZE 8192
#define CHECK_BPF_RET(x) ((x) >= 0 || ((x) == -1 && errno != EACCES))
static const char MSG[] = "Ahoj!";
diff --git a/testcases/kernel/syscalls/bpf/bpf_prog05.c b/testcases/kernel/syscalls/bpf/bpf_prog05.c
index 2be5a2cc9..742beab0b 100644
--- a/testcases/kernel/syscalls/bpf/bpf_prog05.c
+++ b/testcases/kernel/syscalls/bpf/bpf_prog05.c
@@ -52,8 +52,6 @@
#include "tst_capability.h"
#include "bpf_common.h"
-#define BUFSIZE 8192
-
static const char MSG[] = "Ahoj!";
static char *msg;
diff --git a/testcases/kernel/syscalls/bpf/bpf_prog06.c b/testcases/kernel/syscalls/bpf/bpf_prog06.c
index c38dd8239..cee9616cf 100644
--- a/testcases/kernel/syscalls/bpf/bpf_prog06.c
+++ b/testcases/kernel/syscalls/bpf/bpf_prog06.c
@@ -46,8 +46,6 @@
#include "lapi/bpf.h"
#include "bpf_common.h"
-#define BUFSIZE 8192
-
static const char MSG[] = "Ahoj!";
static char *msg;
diff --git a/testcases/kernel/syscalls/bpf/bpf_prog07.c b/testcases/kernel/syscalls/bpf/bpf_prog07.c
index 50ff6eed0..dab5bb8ad 100644
--- a/testcases/kernel/syscalls/bpf/bpf_prog07.c
+++ b/testcases/kernel/syscalls/bpf/bpf_prog07.c
@@ -46,8 +46,6 @@
#include "lapi/bpf.h"
#include "bpf_common.h"
-#define BUFSIZE 8192
-
static const char MSG[] = "Ahoj!";
static char *msg;
diff --git a/testcases/kernel/syscalls/capset/capset01.c b/testcases/kernel/syscalls/capset/capset01.c
index a323fc5be..25db8112c 100644
--- a/testcases/kernel/syscalls/capset/capset01.c
+++ b/testcases/kernel/syscalls/capset/capset01.c
@@ -1,12 +1,20 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) Wipro Technologies Ltd, 2002. All Rights Reserved.
- * AUTHOR : Saji Kumar.V.R <saji.kumar@wipro.com>
+ * Author: Saji Kumar.V.R <saji.kumar@wipro.com>
*
- * CHANGES:
- * 2005/01/01: add an hint to a possible solution when test fails
- * - Ricky Ng-Adam <rngadam@yahoo.com>
+ * 2005/01/01: add an hint to a possible solution when test fails
+ * Ricky Ng-Adam <rngadam@yahoo.com>
+ *
+ * Copyright (c) Linux Test Project, 2003-2023
*/
+
+/*\
+ * [Description]
+ *
+ * Test capset() with with LINUX_CAPABILITY_VERSION_{1,2,3}.
+ */
+
#include <sys/types.h>
#include <unistd.h>
#include "tst_test.h"
diff --git a/testcases/kernel/syscalls/capset/capset02.c b/testcases/kernel/syscalls/capset/capset02.c
index 5173be09b..989f3e4ce 100644
--- a/testcases/kernel/syscalls/capset/capset02.c
+++ b/testcases/kernel/syscalls/capset/capset02.c
@@ -2,21 +2,27 @@
/*
* Copyright (c) Wipro Technologies Ltd, 2002. All Rights Reserved.
* Author: Saji Kumar.V.R <saji.kumar@wipro.com>
- *
+ * Copyright (c) Linux Test Project, 2003-2023
+ */
+
+/*\
+ * [Description]
* Tests basic error handling of the capset syscall.
- * 1) capset() fails with errno set to EFAULT if an invalid address
+ *
+ * 1. capset() fails with errno set to EFAULT if an invalid address
* is given for header.
- * 2) capset() fails with errno set to EFAULT if an invalid address
+ * 2. capset() fails with errno set to EFAULT if an invalid address
* is given for data.
- * 3) capset() fails with errno set to EINVAL if an invalid value
+ * 3. capset() fails with errno set to EINVAL if an invalid value
* is given for header->version.
- * 4) capset() fails with errno set to EPERM if the new_Effective is
+ * 4. capset() fails with errno set to EPERM if the new_Effective is
* not a subset of the new_Permitted.
- * 5) capset() fails with errno set to EPERM if the new_Permitted is
+ * 5. capset() fails with errno set to EPERM if the new_Permitted is
* not a subset of the old_Permitted.
- * 6) capset() fails with errno set ot EPERM if the new_Inheritable is
+ * 6. capset() fails with errno set ot EPERM if the new_Inheritable is
* not a subset of the old_Inheritable and bounding set.
*/
+
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
diff --git a/testcases/kernel/syscalls/capset/capset03.c b/testcases/kernel/syscalls/capset/capset03.c
index 074ab1f50..2b83e6ce9 100644
--- a/testcases/kernel/syscalls/capset/capset03.c
+++ b/testcases/kernel/syscalls/capset/capset03.c
@@ -1,11 +1,17 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
- * Copyright (c) 2019 FUJITSU LIMITED. All rights reserved.
- * Author: Yang Xu <xuyang2018.jy@cn.fujitsu.com
+ * Copyright (c) 2020 FUJITSU LIMITED. All rights reserved.
+ * Copyright (c) Linux Test Project, 2020-2023
+ * Author: Yang Xu <xuyang2018.jy@cn.fujitsu.com>
+ */
+
+/*\
+ * [Description]
*
* capset() fails with errno set or EPERM if the new_Inheritable is
* not a subset of old_Inheritable and old_Permitted without CAP_SETPCAP.
*/
+
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
diff --git a/testcases/kernel/syscalls/capset/capset04.c b/testcases/kernel/syscalls/capset/capset04.c
index f929be555..13477a4a9 100644
--- a/testcases/kernel/syscalls/capset/capset04.c
+++ b/testcases/kernel/syscalls/capset/capset04.c
@@ -1,12 +1,18 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) Wipro Technologies Ltd, 2002. All Rights Reserved.
+ * Copyright (c) Linux Test Project, 2020-2023
* Author: Saji Kumar.V.R <saji.kumar@wipro.com>
+ */
+
+/*\
+ * [Description]
*
- * Tests whether we can use capset() to modify the capabilities of a thread
+ * Test whether capset() can be used to modify the capabilities of a thread
* other than itself. Now, most linux distributions with kernel supporting
* VFS capabilities, this should be never permitted.
*/
+
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
diff --git a/testcases/kernel/syscalls/chdir/chdir01.c b/testcases/kernel/syscalls/chdir/chdir01.c
index e4080e3f4..d50a8f50c 100644
--- a/testcases/kernel/syscalls/chdir/chdir01.c
+++ b/testcases/kernel/syscalls/chdir/chdir01.c
@@ -31,18 +31,27 @@ static char *workdir;
static int skip_symlinks, skip_blocked;
static struct passwd *ltpuser;
+static char *file_name;
+static char *blocked_name;
+static char *dir_name;
+static char *cwd_name;
+static char *parent_name;
+static char *root_name;
+static char *missing_name;
+static char *link_name;
+
static struct test_case {
- const char *name;
+ char **name;
int root_ret, root_err, nobody_ret, nobody_err;
} testcase_list[] = {
- {FILE_NAME, -1, ENOTDIR, -1, ENOTDIR},
- {BLOCKED_NAME, 0, 0, -1, EACCES},
- {DIR_NAME, 0, 0, 0, 0},
- {".", 0, 0, 0, 0},
- {"..", 0, 0, 0, 0},
- {"/", 0, 0, 0, 0},
- {"missing", -1, ENOENT, -1, ENOENT},
- {LINK_NAME1, -1, ELOOP, -1, ELOOP},
+ {&file_name, -1, ENOTDIR, -1, ENOTDIR},
+ {&blocked_name, 0, 0, -1, EACCES},
+ {&dir_name, 0, 0, 0, 0},
+ {&cwd_name, 0, 0, 0, 0},
+ {&parent_name, 0, 0, 0, 0},
+ {&root_name, 0, 0, 0, 0},
+ {&missing_name, -1, ENOENT, -1, ENOENT},
+ {&link_name, -1, ELOOP, -1, ELOOP},
};
static void setup(void)
@@ -53,8 +62,6 @@ static void setup(void)
umask(0);
- SAFE_MOUNT(tst_device->dev, MNTPOINT, tst_device->fs_type, 0, NULL);
-
cwd = SAFE_GETCWD(NULL, 0);
workdir = SAFE_MALLOC(strlen(cwd) + strlen(MNTPOINT) + 2);
sprintf(workdir, "%s/%s", cwd, MNTPOINT);
@@ -109,7 +116,7 @@ static void run(unsigned int n)
{
struct test_case *tc = testcase_list + n;
- tst_res(TINFO, "Testing '%s'", tc->name);
+ tst_res(TINFO, "Testing '%s'", *tc->name);
if (tc->root_err == ELOOP && skip_symlinks) {
tst_res(TCONF, "Skipping symlink loop test, not supported");
@@ -119,8 +126,8 @@ static void run(unsigned int n)
/* Reset current directory to mountpoint */
SAFE_CHDIR(workdir);
- TEST(chdir(tc->name));
- check_result("root", tc->name, tc->root_ret, tc->root_err);
+ TEST(chdir(*tc->name));
+ check_result("root", *tc->name, tc->root_ret, tc->root_err);
if (tc->nobody_err == EACCES && skip_blocked) {
tst_res(TCONF, "Skipping unprivileged permission test, "
@@ -130,25 +137,35 @@ static void run(unsigned int n)
SAFE_CHDIR(workdir);
SAFE_SETEUID(ltpuser->pw_uid);
- TEST(chdir(tc->name));
+ TEST(chdir(*tc->name));
SAFE_SETEUID(0);
- check_result(TESTUSER, tc->name, tc->nobody_ret, tc->nobody_err);
+ check_result(TESTUSER, *tc->name, tc->nobody_ret, tc->nobody_err);
}
static void cleanup(void)
{
SAFE_CHDIR("..");
- tst_umount(workdir);
free(workdir);
}
static struct tst_test test = {
.needs_root = 1,
- .format_device = 1,
+ .mount_device = 1,
.mntpoint = MNTPOINT,
.all_filesystems = 1,
.test = run,
.tcnt = ARRAY_SIZE(testcase_list),
.setup = setup,
- .cleanup = cleanup
+ .cleanup = cleanup,
+ .bufs = (struct tst_buffers []) {
+ {&file_name, .str = FILE_NAME},
+ {&blocked_name, .str = BLOCKED_NAME},
+ {&dir_name, .str = DIR_NAME},
+ {&cwd_name, .str = "."},
+ {&parent_name, .str = ".."},
+ {&root_name, .str = "/"},
+ {&missing_name, .str = "does_not_exist"},
+ {&link_name, .str = LINK_NAME1},
+ {}
+ }
};
diff --git a/testcases/kernel/syscalls/chmod/chmod01.c b/testcases/kernel/syscalls/chmod/chmod01.c
index 9f5ec4c67..b3b828ac3 100644
--- a/testcases/kernel/syscalls/chmod/chmod01.c
+++ b/testcases/kernel/syscalls/chmod/chmod01.c
@@ -19,13 +19,16 @@
static int modes[] = {0, 07, 070, 0700, 0777, 02777, 04777, 06777};
+static char *test_dir;
+static char *test_file;
+
static struct variant {
- char *name;
+ char **name;
unsigned int mode_mask;
char *desc;
} variants[] = {
- {TESTFILE, S_IFREG, "verify permissions of file"},
- {TESTDIR, S_IFDIR, "verify permissions of directory"},
+ {&test_file, S_IFREG, "verify permissions of file"},
+ {&test_dir, S_IFDIR, "verify permissions of directory"},
};
static void verify_chmod(unsigned int n)
@@ -34,21 +37,21 @@ static void verify_chmod(unsigned int n)
int mode = modes[n];
struct variant *tc = &variants[tst_variant];
- TST_EXP_PASS(chmod(tc->name, mode), "chmod(%s, %04o)",
- tc->name, mode);
+ TST_EXP_PASS(chmod(*tc->name, mode), "chmod(%s, %04o)",
+ *tc->name, mode);
if (!TST_PASS)
return;
- SAFE_STAT(tc->name, &stat_buf);
+ SAFE_STAT(*tc->name, &stat_buf);
stat_buf.st_mode &= ~tc->mode_mask;
if (stat_buf.st_mode == (unsigned int)mode) {
tst_res(TPASS, "stat(%s) mode=%04o",
- tc->name, stat_buf.st_mode);
+ *tc->name, stat_buf.st_mode);
} else {
tst_res(TFAIL, "stat(%s) mode=%04o",
- tc->name, stat_buf.st_mode);
+ *tc->name, stat_buf.st_mode);
}
}
@@ -57,9 +60,9 @@ static void setup(void)
tst_res(TINFO, "Testing variant: %s", variants[tst_variant].desc);
if (tst_variant)
- SAFE_MKDIR(variants[tst_variant].name, MODE);
+ SAFE_MKDIR(*variants[tst_variant].name, MODE);
else
- SAFE_TOUCH(variants[tst_variant].name, MODE, NULL);
+ SAFE_TOUCH(*variants[tst_variant].name, MODE, NULL);
}
static struct tst_test test = {
@@ -68,4 +71,9 @@ static struct tst_test test = {
.tcnt = ARRAY_SIZE(modes),
.test = verify_chmod,
.needs_tmpdir = 1,
+ .bufs = (struct tst_buffers []) {
+ {&test_file, .str = TESTFILE},
+ {&test_dir, .str = TESTDIR},
+ {}
+ }
};
diff --git a/testcases/kernel/syscalls/chown/chown02.c b/testcases/kernel/syscalls/chown/chown02.c
index 7c96832a4..467185831 100644
--- a/testcases/kernel/syscalls/chown/chown02.c
+++ b/testcases/kernel/syscalls/chown/chown02.c
@@ -9,6 +9,7 @@
* [Description]
*
* Verify that chown(2) invoked by super-user:
+ *
* - clears setuid and setgid bits set on an executable file
* - preserves setgid bit set on a non-group-executable file
*/
diff --git a/testcases/kernel/syscalls/chroot/chroot03.c b/testcases/kernel/syscalls/chroot/chroot03.c
index ba8c1e9ac..87faec316 100644
--- a/testcases/kernel/syscalls/chroot/chroot03.c
+++ b/testcases/kernel/syscalls/chroot/chroot03.c
@@ -25,41 +25,42 @@
#include <stdio.h>
#include "tst_test.h"
-static char fname[255];
-static char nonexistent_dir[100] = "testdir";
-static char bad_dir[] = "abcdefghijklmnopqrstmnopqrstuvwxyzabcdefghijklmnopqrstmnopqrstuvwxyzabcdefghijklmnopqrstmnopqrstuvwxyzabcdefghijklmnopqrstmnopqrstuvwxyzabcdefghijklmnopqrstmnopqrstuvwxyzabcdefghijklmnopqrstmnopqrstuvwxyzabcdefghijklmnopqrstmnopqrstuvwxyzabcdefghijklmnopqrstmnopqrstuvwxyz";
-static char symbolic_dir[] = "sym_dir1";
+#define FILE_NAME "test_file"
+#define LOOP_DIR "sym_dir1"
+#define NONEXISTENT_DIR "does_not_exist"
+
+static char *longname_dir;
+static char *file_name;
+static char *nonexistent_dir;
+static char *bad_ptr;
+static char *loop_dir;
static struct tcase {
- char *dir;
+ char **dir;
int error;
char *desc;
} tcases[] = {
- {bad_dir, ENAMETOOLONG, "chroot(longer than VFS_MAXNAMELEN)"},
- {fname, ENOTDIR, "chroot(not a directory)"},
- {nonexistent_dir, ENOENT, "chroot(does not exists)"},
- {(char *)-1, EFAULT, "chroot(an invalid address)"},
- {symbolic_dir, ELOOP, "chroot(symlink loop)"}
+ {&longname_dir, ENAMETOOLONG, "chroot(longer than VFS_MAXNAMELEN)"},
+ {&file_name, ENOTDIR, "chroot(not a directory)"},
+ {&nonexistent_dir, ENOENT, "chroot(does not exists)"},
+ {&bad_ptr, EFAULT, "chroot(an invalid address)"},
+ {&loop_dir, ELOOP, "chroot(symlink loop)"}
};
static void verify_chroot(unsigned int n)
{
struct tcase *tc = &tcases[n];
- TST_EXP_FAIL(chroot(tc->dir), tc->error, "%s", tc->desc);
+ TST_EXP_FAIL(chroot(*tc->dir), tc->error, "%s", tc->desc);
}
static void setup(void)
{
- unsigned int i;
-
- (void)sprintf(fname, "tfile_%d", getpid());
- SAFE_TOUCH(fname, 0666, NULL);
+ SAFE_TOUCH(FILE_NAME, 0666, NULL);
+ bad_ptr = tst_get_bad_addr(NULL);
- for (i = 0; i < ARRAY_SIZE(tcases); i++) {
- if (tcases[i].error == EFAULT)
- tcases[3].dir = tst_get_bad_addr(NULL);
- }
+ memset(longname_dir, 'a', PATH_MAX + 1);
+ longname_dir[PATH_MAX+1] = 0;
SAFE_SYMLINK("sym_dir1/", "sym_dir2");
SAFE_SYMLINK("sym_dir2/", "sym_dir1");
@@ -70,4 +71,11 @@ static struct tst_test test = {
.tcnt = ARRAY_SIZE(tcases),
.test = verify_chroot,
.needs_tmpdir = 1,
+ .bufs = (struct tst_buffers []) {
+ {&file_name, .str = FILE_NAME},
+ {&nonexistent_dir, .str = NONEXISTENT_DIR},
+ {&loop_dir, .str = LOOP_DIR},
+ {&longname_dir, .size = PATH_MAX+2},
+ {}
+ }
};
diff --git a/testcases/kernel/syscalls/clone/clone04.c b/testcases/kernel/syscalls/clone/clone04.c
index 7af4fedd3..74347e2b4 100644
--- a/testcases/kernel/syscalls/clone/clone04.c
+++ b/testcases/kernel/syscalls/clone/clone04.c
@@ -2,6 +2,7 @@
/*
* Copyright (c) Wipro Technologies Ltd, 2002. All Rights Reserved.
* Copyright (c) 2012 Wanlong Gao <gaowanlong@cn.fujitsu.com>
+ * Copyright (c) Linux Test Project, 2003-2023
*/
/*\
@@ -44,4 +45,8 @@ static void verify_clone(unsigned int nr)
static struct tst_test test = {
.tcnt = ARRAY_SIZE(tcases),
.test = verify_clone,
+ .tags = (const struct tst_tag[]) {
+ {"musl-git", "fa4a8abd06a4"},
+ {}
+ },
};
diff --git a/testcases/kernel/syscalls/clone3/.gitignore b/testcases/kernel/syscalls/clone3/.gitignore
index 604cb903e..10369954b 100644
--- a/testcases/kernel/syscalls/clone3/.gitignore
+++ b/testcases/kernel/syscalls/clone3/.gitignore
@@ -1,2 +1,3 @@
clone301
clone302
+clone303
diff --git a/testcases/kernel/syscalls/clone3/clone302.c b/testcases/kernel/syscalls/clone3/clone302.c
index b1b4ccebb..48b831554 100644
--- a/testcases/kernel/syscalls/clone3/clone302.c
+++ b/testcases/kernel/syscalls/clone3/clone302.c
@@ -12,6 +12,7 @@
#define _GNU_SOURCE
#include <stdlib.h>
+#include <assert.h>
#include "tst_test.h"
#include "lapi/sched.h"
@@ -34,7 +35,7 @@ static struct tcase {
} tcases[] = {
{"invalid args", &invalid_args, sizeof(*valid_args), 0, NULL, SIGCHLD, 0, 0, 0, EFAULT},
{"zero size", &valid_args, 0, 0, NULL, SIGCHLD, 0, 0, 0, EINVAL},
- {"short size", &valid_args, sizeof(*valid_args) - 1, 0, NULL, SIGCHLD, 0, 0, 0, EINVAL},
+ {"short size", &valid_args, sizeof(struct clone_args_minimal) - 1, 0, NULL, SIGCHLD, 0, 0, 0, EINVAL},
{"extra size", &valid_args, sizeof(*valid_args) + 1, 0, NULL, SIGCHLD, 0, 0, 0, EFAULT},
{"sighand-no-VM", &valid_args, sizeof(*valid_args), CLONE_SIGHAND, NULL, SIGCHLD, 0, 0, 0, EINVAL},
{"thread-no-sighand", &valid_args, sizeof(*valid_args), CLONE_THREAD, NULL, SIGCHLD, 0, 0, 0, EINVAL},
@@ -59,6 +60,8 @@ static void setup(void)
{
clone3_supported_by_kernel();
+ TST_EXP_EQ_SZ(sizeof(struct clone_args_minimal), 64);
+
void *p = tst_get_bad_addr(NULL);
invalid_args = p;
diff --git a/testcases/kernel/syscalls/clone3/clone303.c b/testcases/kernel/syscalls/clone3/clone303.c
new file mode 100644
index 000000000..04c41942a
--- /dev/null
+++ b/testcases/kernel/syscalls/clone3/clone303.c
@@ -0,0 +1,94 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2023 SUSE LLC <wegao@suse.com>
+ */
+
+/*\
+ * [Description]
+ *
+ * This test case check clone3 CLONE_INTO_CGROUP flag
+ *
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/wait.h>
+
+#include "tst_test.h"
+#include "lapi/sched.h"
+#include "lapi/pidfd.h"
+
+#define BUF_LEN 20
+
+static struct tst_cg_group *cg_child_test_simple;
+static int fd;
+static struct tst_clone_args *args;
+
+static pid_t clone_into_cgroup(int cgroup_fd)
+{
+
+ args->flags = CLONE_INTO_CGROUP;
+ args->exit_signal = SIGCHLD;
+ args->cgroup = cgroup_fd;
+
+ return tst_clone(args);
+}
+
+static void run(void)
+{
+ pid_t pid;
+
+ pid = clone_into_cgroup(fd);
+
+ if (!pid) {
+ TST_CHECKPOINT_WAIT(0);
+ return;
+ }
+
+ char buf[BUF_LEN];
+
+ SAFE_CG_READ(cg_child_test_simple, "cgroup.procs", buf, BUF_LEN);
+
+ if (atoi(buf) == pid)
+ tst_res(TPASS, "clone3 case pass!");
+ else
+ tst_brk(TFAIL | TTERRNO, "clone3() failed !");
+
+ TST_CHECKPOINT_WAKE(0);
+
+ SAFE_WAITPID(pid, NULL, 0);
+
+}
+
+static void setup(void)
+{
+ clone3_supported_by_kernel();
+
+ cg_child_test_simple = tst_cg_group_mk(tst_cg, "cg_test_simple");
+
+ fd = tst_cg_group_unified_dir_fd(cg_child_test_simple);
+
+ if (fd < 0)
+ tst_brk(TBROK, "get dir fd failed!");
+}
+
+static void cleanup(void)
+{
+ cg_child_test_simple = tst_cg_group_rm(cg_child_test_simple);
+}
+
+static struct tst_test test = {
+ .test_all = run,
+ .setup = setup,
+ .cleanup = cleanup,
+ .forks_child = 1,
+ .needs_cgroup_ctrls = (const char *const []){ "base", NULL },
+ .needs_cgroup_ver = TST_CG_V2,
+ .needs_checkpoints = 1,
+ .min_kver = "5.7",
+ .bufs = (struct tst_buffers []) {
+ {&args, .size = sizeof(*args)},
+ {},
+ }
+};
diff --git a/testcases/kernel/syscalls/delete_module/delete_module01.c b/testcases/kernel/syscalls/delete_module/delete_module01.c
index 476551233..90d8b5289 100644
--- a/testcases/kernel/syscalls/delete_module/delete_module01.c
+++ b/testcases/kernel/syscalls/delete_module/delete_module01.c
@@ -2,38 +2,39 @@
/*
* Copyright (c) Wipro Technologies Ltd, 2002. All Rights Reserved.
* Copyright (c) 2018 Xiao Yang <yangx.jy@cn.fujitsu.com>
+ * Copyright (c) Linux Test Project, 2002-2023
+ * Author: Madhu T L <madhu.tarikere@wipro.com>
*/
-/*
- * AUTHOR: Madhu T L <madhu.tarikere@wipro.com>
+/*\
+ * [Description]
+ *
+ * Basic test for delete_module(2).
*
- * DESCRIPTION:
- * Basic tests for delete_module(2)
- * 1) insmod dummy_del_mod.ko
- * 2) call delete_module(2) to remove dummy_del_mod.ko
+ * Install dummy_del_mod.ko and delete it with delete_module(2).
*/
-#include <errno.h>
#include "tst_test.h"
#include "tst_module.h"
#include "lapi/syscalls.h"
#define MODULE_NAME "dummy_del_mod"
-#define MODULE_NAME_KO "dummy_del_mod.ko"
+#define MODULE_NAME_KO MODULE_NAME ".ko"
static int module_loaded;
static void do_delete_module(void)
{
- if (module_loaded == 0) {
+ if (!module_loaded) {
tst_module_load(MODULE_NAME_KO, NULL);
module_loaded = 1;
}
TEST(tst_syscall(__NR_delete_module, MODULE_NAME, 0));
if (TST_RET == -1) {
- tst_res(TFAIL | TTERRNO, "delete_module() failed to "
- "remove module entry for %s ", MODULE_NAME);
+ tst_res(TFAIL | TTERRNO,
+ "delete_module() failed to remove module entry for %s",
+ MODULE_NAME);
return;
}
@@ -43,14 +44,15 @@ static void do_delete_module(void)
static void cleanup(void)
{
- if (module_loaded == 1)
+ if (module_loaded)
tst_module_unload(MODULE_NAME_KO);
}
static struct tst_test test = {
.needs_root = 1,
- /* lockdown requires signed modules */
+ /* lockdown and SecureBoot requires signed modules */
.skip_in_lockdown = 1,
+ .skip_in_secureboot = 1,
.cleanup = cleanup,
.test_all = do_delete_module,
};
diff --git a/testcases/kernel/syscalls/delete_module/delete_module03.c b/testcases/kernel/syscalls/delete_module/delete_module03.c
index 863d36188..7e92fc2af 100644
--- a/testcases/kernel/syscalls/delete_module/delete_module03.c
+++ b/testcases/kernel/syscalls/delete_module/delete_module03.c
@@ -72,8 +72,9 @@ static void cleanup(void)
static struct tst_test test = {
.needs_root = 1,
- /* lockdown requires signed modules */
+ /* lockdown and SecureBoot requires signed modules */
.skip_in_lockdown = 1,
+ .skip_in_secureboot = 1,
.setup = setup,
.cleanup = cleanup,
.test_all = do_delete_module,
diff --git a/testcases/kernel/syscalls/dup/dup01.c b/testcases/kernel/syscalls/dup/dup01.c
index 74e24cc02..f5cd058e8 100644
--- a/testcases/kernel/syscalls/dup/dup01.c
+++ b/testcases/kernel/syscalls/dup/dup01.c
@@ -7,27 +7,32 @@
*
*/
+/*\
+ * [Description]
+ *
+ * Verify that dup(2) syscall executes successfully and allocates
+ * a new file descriptor which refers to the same open file as oldfd.
+ */
+
#include "tst_test.h"
static int fd;
+static struct stat buf1, buf2;
static void verify_dup(void)
{
- TEST(dup(fd));
-
- if (TST_RET < -1) {
- tst_res(TFAIL, "Invalid dup() return value %ld", TST_RET);
- } else if (TST_RET == -1) {
- tst_res(TFAIL | TTERRNO, "dup(%d) Failed", fd);
- } else {
- tst_res(TPASS, "dup(%d) returned %ld", fd, TST_RET);
- SAFE_CLOSE(TST_RET);
- }
+ TST_EXP_FD(dup(fd));
+
+ SAFE_FSTAT(TST_RET, &buf2);
+ TST_EXP_EQ_LU(buf1.st_ino, buf2.st_ino);
+
+ SAFE_CLOSE(TST_RET);
}
static void setup(void)
{
fd = SAFE_OPEN("dupfile", O_RDWR | O_CREAT, 0700);
+ SAFE_FSTAT(fd, &buf1);
}
static void cleanup(void)
diff --git a/testcases/kernel/syscalls/dup/dup02.c b/testcases/kernel/syscalls/dup/dup02.c
index 528bcdbc1..5391738a4 100644
--- a/testcases/kernel/syscalls/dup/dup02.c
+++ b/testcases/kernel/syscalls/dup/dup02.c
@@ -2,24 +2,21 @@
/*
* Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
* Copyright (c) 2020 SUSE LLC
- *
* 03/30/1992 AUTHOR: Richard Logan CO-PILOT: William Roske
- *
*/
+
/*\
* [Description]
- * Negative test for dup(2) with bad fds.
*
- * [Algorithm]
- * Call dup(2) with invalid argument and make sure it returns -1 with errno set
- * to EBADF.
+ * Verify that dup(2) syscall fails with errno EBADF when called with
+ * invalid value for oldfd argument.
*/
#include "tst_test.h"
static struct tcase {
int fd;
- int expected_errno;
+ int exp_err;
} tcases[] = {
{-1, EBADF},
{1500, EBADF},
@@ -29,27 +26,10 @@ static void run(unsigned int n)
{
struct tcase *tc = &tcases[n];
- TEST(dup(tc->fd));
-
- if (TST_RET < -1) {
- tst_res(TFAIL | TTERRNO, "Invalid dup() return value %ld",
- TST_RET);
- return;
- }
-
- if (TST_RET == -1) {
- if (tc->expected_errno == TST_ERR) {
- tst_res(TPASS | TTERRNO, "dup(%d) failed as expected",
- tc->fd);
- } else {
- tst_res(TFAIL | TTERRNO, "dup(%d) failed unexpectedly",
- tc->fd);
- }
- return;
- }
+ TST_EXP_FAIL2(dup(tc->fd), tc->exp_err, "dup(%d)", tc->fd);
- tst_res(TFAIL, "dup(%d) succeeded unexpectedly", tc->fd);
- SAFE_CLOSE(TST_RET);
+ if (TST_RET != -1)
+ SAFE_CLOSE(TST_RET);
}
static struct tst_test test = {
diff --git a/testcases/kernel/syscalls/dup/dup03.c b/testcases/kernel/syscalls/dup/dup03.c
index 0e99813f4..d59e61f2b 100644
--- a/testcases/kernel/syscalls/dup/dup03.c
+++ b/testcases/kernel/syscalls/dup/dup03.c
@@ -6,48 +6,30 @@
*/
/*\
* [Description]
- * Negative test for dup(2) (too many fds).
*
- * [Algorithm]
- * Open the maximum allowed number of file descriptors and then try to call
- * dup() once more and verify it fails with EMFILE.
+ * Verify that dup(2) syscall fails with errno EMFILE when the per-process
+ * limit on the number of open file descriptors has been reached.
*/
#include <stdlib.h>
#include "tst_test.h"
-int *fd;
-int nfds;
+static int *fd;
+static int nfds;
static void run(void)
{
- TEST(dup(fd[0]));
+ TST_EXP_FAIL2(dup(fd[0]), EMFILE, "dup(%d)", fd[0]);
- if (TST_RET < -1) {
- tst_res(TFAIL, "Invalid dup() return value %ld", TST_RET);
- return;
- }
-
- if (TST_RET == -1) {
- if (TST_ERR == EMFILE)
- tst_res(TPASS | TTERRNO, "dup() failed as expected");
- else
- tst_res(TFAIL | TTERRNO, "dup() failed unexpectedly");
- return;
- }
-
- tst_res(TFAIL, "dup() succeeded unexpectedly");
- SAFE_CLOSE(TST_RET);
+ if (TST_RET != -1)
+ SAFE_CLOSE(TST_RET);
}
static void setup(void)
{
long maxfds;
- maxfds = sysconf(_SC_OPEN_MAX);
- if (maxfds == -1)
- tst_brk(TBROK, "sysconf(_SC_OPEN_MAX) failed");
-
+ maxfds = SAFE_SYSCONF(_SC_OPEN_MAX);
fd = SAFE_MALLOC(maxfds * sizeof(int));
fd[0] = SAFE_OPEN("dupfile", O_RDWR | O_CREAT, 0700);
diff --git a/testcases/kernel/syscalls/dup/dup04.c b/testcases/kernel/syscalls/dup/dup04.c
index 8d45f7a9c..053fb40c2 100644
--- a/testcases/kernel/syscalls/dup/dup04.c
+++ b/testcases/kernel/syscalls/dup/dup04.c
@@ -1,12 +1,12 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
- *
* 06/1994 AUTHOR: Richard Logan CO-PILOT: William Roske
+ * Copyright (c) 2023 SUSE LLC
*/
/*\
- * [DESCRIPTION]
+ * [Description]
*
* Basic test for dup(2) of a system pipe descriptor.
*/
@@ -17,38 +17,18 @@
#include "tst_test.h"
-int fd[2];
+static int fd[2];
static void run(void)
{
- TEST(dup(fd[0]));
-
- if (TST_RET == -1)
- tst_res(TFAIL | TTERRNO,
- "dup of read side of pipe failed");
- else {
- tst_res(TPASS,
- "dup(%d) read side of syspipe returned %ld",
- fd[0], TST_RET);
-
- SAFE_CLOSE(TST_RET);
- }
-
- TEST(dup(fd[1]));
-
- if (TST_RET == -1) {
- tst_res(TFAIL | TTERRNO,
- "dup of write side of pipe failed");
- } else {
- tst_res(TPASS,
- "dup(%d) write side of syspipe returned %ld",
- fd[1], TST_RET);
-
- SAFE_CLOSE(TST_RET);
- }
+ TST_EXP_FD(dup(fd[0]), "dup(%d) read end of the pipe", fd[0]);
+ SAFE_CLOSE(TST_RET);
+
+ TST_EXP_FD(dup(fd[1]), "dup(%d) write end of the pipe", fd[1]);
+ SAFE_CLOSE(TST_RET);
}
-void setup(void)
+static void setup(void)
{
fd[0] = -1;
@@ -56,7 +36,7 @@ void setup(void)
}
static struct tst_test test = {
- .test_all = run,
- .setup = setup,
- .needs_tmpdir = 1,
+ .test_all = run,
+ .setup = setup,
+ .needs_tmpdir = 1,
};
diff --git a/testcases/kernel/syscalls/dup/dup05.c b/testcases/kernel/syscalls/dup/dup05.c
index 362f3e170..619b4861e 100644
--- a/testcases/kernel/syscalls/dup/dup05.c
+++ b/testcases/kernel/syscalls/dup/dup05.c
@@ -1,55 +1,43 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
- *
* 06/1994 AUTHOR: Richard Logan CO-PILOT: William Roske
+ * Copyright (c) 2012-2023 SUSE LLC
*/
/*\
- * [DESCRIPTION]
+ * [Description]
*
- * Basic test for dup(2) of a named pipe descriptor
+ * Basic test for dup(2) of a named pipe descriptor.
*/
-#include <stdio.h>
+
#include "tst_test.h"
-char Fname[255];
-int fd;
+#define FNAME "dupfile"
+
+static int fd = -1;
static void run(void)
{
- TEST(dup(fd));
-
- if (TST_RET == -1) {
- tst_res(TFAIL | TTERRNO, "dup failed");
- } else {
- tst_res(TPASS, "dup returned %ld",
- TST_RET);
-
- SAFE_CLOSE(TST_RET);
- }
+ TST_EXP_FD(dup(fd), "dup(%d)", fd);
+ SAFE_CLOSE(TST_RET);
}
-void setup(void)
+static void setup(void)
{
- fd = -1;
-
- sprintf(Fname, "dupfile");
- SAFE_MKFIFO(Fname, 0777);
- if ((fd = open(Fname, O_RDWR, 0700)) == -1)
- tst_brk(TBROK, "open failed");
+ SAFE_MKFIFO(FNAME, 0777);
+ fd = SAFE_OPEN(FNAME, O_RDWR, 0700);
}
-void cleanup(void)
+static void cleanup(void)
{
if (fd != -1)
- if (close(fd) == -1)
- tst_res(TWARN | TERRNO, "close failed");
+ SAFE_CLOSE(fd);
}
static struct tst_test test = {
- .test_all = run,
- .setup = setup,
- .cleanup = cleanup,
+ .test_all = run,
+ .setup = setup,
+ .cleanup = cleanup,
.needs_tmpdir = 1,
};
diff --git a/testcases/kernel/syscalls/epoll_ctl/epoll_ctl02.c b/testcases/kernel/syscalls/epoll_ctl/epoll_ctl02.c
index fe16ad1cb..dcf74bf77 100644
--- a/testcases/kernel/syscalls/epoll_ctl/epoll_ctl02.c
+++ b/testcases/kernel/syscalls/epoll_ctl/epoll_ctl02.c
@@ -67,7 +67,7 @@ static void setup(void)
events[1].data.fd = fd[1];
if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd[0], &events[0]))
- tst_brk(TBROK | TERRNO, "epoll_clt(..., EPOLL_CTL_ADD, ...)");
+ tst_brk(TBROK | TERRNO, "epoll_ctl(..., EPOLL_CTL_ADD, ...)");
}
static void cleanup(void)
@@ -85,7 +85,7 @@ static void cleanup(void)
static void verify_epoll_ctl(unsigned int n)
{
TST_EXP_FAIL(epoll_ctl(*tc[n].epfd, tc[n].opt, *tc[n].fd, tc[n].event),
- tc[n].exp_err, "epoll_clt(...) if %s", tc[n].desc);
+ tc[n].exp_err, "epoll_ctl(...) if %s", tc[n].desc);
}
static struct tst_test test = {
diff --git a/testcases/kernel/syscalls/epoll_ctl/epoll_ctl03.c b/testcases/kernel/syscalls/epoll_ctl/epoll_ctl03.c
index c92b0b62e..f617295cc 100644
--- a/testcases/kernel/syscalls/epoll_ctl/epoll_ctl03.c
+++ b/testcases/kernel/syscalls/epoll_ctl/epoll_ctl03.c
@@ -55,7 +55,7 @@ static void setup(void)
events.data.fd = fds[0];
if (epoll_ctl(epfd, EPOLL_CTL_ADD, fds[0], &events))
- tst_brk(TBROK | TERRNO, "epoll_clt(..., EPOLL_CTL_ADD, ...)");
+ tst_brk(TBROK | TERRNO, "epoll_ctl(..., EPOLL_CTL_ADD, ...)");
}
static void cleanup(void)
diff --git a/testcases/kernel/syscalls/epoll_ctl/epoll_ctl04.c b/testcases/kernel/syscalls/epoll_ctl/epoll_ctl04.c
index 5173755f7..bc015c01b 100644
--- a/testcases/kernel/syscalls/epoll_ctl/epoll_ctl04.c
+++ b/testcases/kernel/syscalls/epoll_ctl/epoll_ctl04.c
@@ -36,7 +36,7 @@ static void setup(void)
events.data.fd = epfd;
if (epoll_ctl(new_epfd, EPOLL_CTL_ADD, epfd, &events))
- tst_brk(TBROK | TERRNO, "epoll_clt(..., EPOLL_CTL_ADD, ...)");
+ tst_brk(TBROK | TERRNO, "epoll_ctl(..., EPOLL_CTL_ADD, ...)");
epfd = new_epfd;
}
@@ -59,7 +59,7 @@ static void verify_epoll_ctl(void)
events.data.fd = epfd;
TST_EXP_FAIL(epoll_ctl(new_epfd, EPOLL_CTL_ADD, epfd, &events), EINVAL,
- "epoll_clt(..., EPOLL_CTL_ADD, ...) with number of nesting is 5");
+ "epoll_ctl(..., EPOLL_CTL_ADD, ...) with number of nesting is 5");
SAFE_CLOSE(new_epfd);
}
diff --git a/testcases/kernel/syscalls/epoll_ctl/epoll_ctl05.c b/testcases/kernel/syscalls/epoll_ctl/epoll_ctl05.c
index d03009cf3..71e300daa 100644
--- a/testcases/kernel/syscalls/epoll_ctl/epoll_ctl05.c
+++ b/testcases/kernel/syscalls/epoll_ctl/epoll_ctl05.c
@@ -40,12 +40,12 @@ static void setup(void)
events.data.fd = epfd;
if (epoll_ctl(new_epfd, EPOLL_CTL_ADD, epfd, &events))
- tst_brk(TBROK | TERRNO, "epoll_clt(..., EPOLL_CTL_ADD, ...)");
+ tst_brk(TBROK | TERRNO, "epoll_ctl(..., EPOLL_CTL_ADD, ...)");
}
events.data.fd = fd[0];
if (epoll_ctl(origin_epfd, EPOLL_CTL_DEL, fd[0], &events))
- tst_brk(TBROK | TERRNO, "epoll_clt(..., EPOLL_CTL_DEL, ...)");
+ tst_brk(TBROK | TERRNO, "epoll_ctl(..., EPOLL_CTL_DEL, ...)");
}
static void cleanup(void)
@@ -61,7 +61,7 @@ static void verify_epoll_ctl(void)
{
events.data.fd = epfd;
TST_EXP_FAIL(epoll_ctl(origin_epfd, EPOLL_CTL_ADD, epfd, &events),
- ELOOP, "epoll_clt(..., EPOLL_CTL_ADD, ...)");
+ ELOOP, "epoll_ctl(..., EPOLL_CTL_ADD, ...)");
}
static struct tst_test test = {
diff --git a/testcases/kernel/syscalls/epoll_pwait/epoll_pwait01.c b/testcases/kernel/syscalls/epoll_pwait/epoll_pwait01.c
index f4a55e008..928d57803 100644
--- a/testcases/kernel/syscalls/epoll_pwait/epoll_pwait01.c
+++ b/testcases/kernel/syscalls/epoll_pwait/epoll_pwait01.c
@@ -102,7 +102,7 @@ static void setup(void)
e.events = EPOLLIN;
if (epoll_ctl(efd, EPOLL_CTL_ADD, sfd[0], &e))
- tst_brk(TBROK | TERRNO, "epoll_clt(..., EPOLL_CTL_ADD, ...)");
+ tst_brk(TBROK | TERRNO, "epoll_ctl(..., EPOLL_CTL_ADD, ...)");
}
static void cleanup(void)
diff --git a/testcases/kernel/syscalls/epoll_pwait/epoll_pwait02.c b/testcases/kernel/syscalls/epoll_pwait/epoll_pwait02.c
index 7914f1c50..2ae32519f 100644
--- a/testcases/kernel/syscalls/epoll_pwait/epoll_pwait02.c
+++ b/testcases/kernel/syscalls/epoll_pwait/epoll_pwait02.c
@@ -42,7 +42,7 @@ static void setup(void)
e.events = EPOLLIN;
if (epoll_ctl(efd, EPOLL_CTL_ADD, sfd[0], &e))
- tst_brk(TBROK | TERRNO, "epoll_clt(..., EPOLL_CTL_ADD, ...)");
+ tst_brk(TBROK | TERRNO, "epoll_ctl(..., EPOLL_CTL_ADD, ...)");
SAFE_WRITE(SAFE_WRITE_ALL, sfd[1], "w", 1);
}
diff --git a/testcases/kernel/syscalls/epoll_pwait/epoll_pwait03.c b/testcases/kernel/syscalls/epoll_pwait/epoll_pwait03.c
index 2ad1a6abc..aa08daa1b 100644
--- a/testcases/kernel/syscalls/epoll_pwait/epoll_pwait03.c
+++ b/testcases/kernel/syscalls/epoll_pwait/epoll_pwait03.c
@@ -50,7 +50,7 @@ static void setup(void)
e.events = EPOLLIN;
if (epoll_ctl(efd, EPOLL_CTL_ADD, sfd[0], &e))
- tst_brk(TBROK | TERRNO, "epoll_clt(..., EPOLL_CTL_ADD, ...)");
+ tst_brk(TBROK | TERRNO, "epoll_ctl(..., EPOLL_CTL_ADD, ...)");
}
static void cleanup(void)
diff --git a/testcases/kernel/syscalls/epoll_pwait/epoll_pwait04.c b/testcases/kernel/syscalls/epoll_pwait/epoll_pwait04.c
index 54b9be975..4be33488d 100644
--- a/testcases/kernel/syscalls/epoll_pwait/epoll_pwait04.c
+++ b/testcases/kernel/syscalls/epoll_pwait/epoll_pwait04.c
@@ -38,7 +38,7 @@ static void setup(void)
e.events = EPOLLIN;
if (epoll_ctl(efd, EPOLL_CTL_ADD, sfd[0], &e))
- tst_brk(TBROK | TERRNO, "epoll_clt(..., EPOLL_CTL_ADD, ...)");
+ tst_brk(TBROK | TERRNO, "epoll_ctl(..., EPOLL_CTL_ADD, ...)");
SAFE_WRITE(SAFE_WRITE_ALL, sfd[1], "w", 1);
bad_addr = tst_get_bad_addr(NULL);
diff --git a/testcases/kernel/syscalls/epoll_pwait/epoll_pwait05.c b/testcases/kernel/syscalls/epoll_pwait/epoll_pwait05.c
index 4c4aeb77d..ed8f3e4f8 100644
--- a/testcases/kernel/syscalls/epoll_pwait/epoll_pwait05.c
+++ b/testcases/kernel/syscalls/epoll_pwait/epoll_pwait05.c
@@ -46,7 +46,7 @@ static void setup(void)
e.events = EPOLLIN;
if (epoll_ctl(efd, EPOLL_CTL_ADD, sfd[0], &e))
- tst_brk(TBROK | TERRNO, "epoll_clt(..., EPOLL_CTL_ADD, ...)");
+ tst_brk(TBROK | TERRNO, "epoll_ctl(..., EPOLL_CTL_ADD, ...)");
SAFE_WRITE(SAFE_WRITE_ALL, sfd[1], "w", 1);
}
diff --git a/testcases/kernel/syscalls/epoll_wait/.gitignore b/testcases/kernel/syscalls/epoll_wait/.gitignore
index 222955dd2..66ac18ae2 100644
--- a/testcases/kernel/syscalls/epoll_wait/.gitignore
+++ b/testcases/kernel/syscalls/epoll_wait/.gitignore
@@ -2,3 +2,6 @@ epoll_wait01
epoll_wait02
epoll_wait03
epoll_wait04
+epoll_wait05
+epoll_wait06
+epoll_wait07
diff --git a/testcases/kernel/syscalls/epoll_wait/epoll_wait02.c b/testcases/kernel/syscalls/epoll_wait/epoll_wait02.c
index d2c0b6ef4..93ada1cf3 100644
--- a/testcases/kernel/syscalls/epoll_wait/epoll_wait02.c
+++ b/testcases/kernel/syscalls/epoll_wait/epoll_wait02.c
@@ -50,7 +50,7 @@ static void setup(void)
epevs[0].data.fd = fds[0];
if (epoll_ctl(epfd, EPOLL_CTL_ADD, fds[0], &epevs[0]))
- tst_brk(TBROK | TERRNO, "epoll_clt(..., EPOLL_CTL_ADD, ...)");
+ tst_brk(TBROK | TERRNO, "epoll_ctl(..., EPOLL_CTL_ADD, ...)");
}
static void cleanup(void)
diff --git a/testcases/kernel/syscalls/epoll_wait/epoll_wait03.c b/testcases/kernel/syscalls/epoll_wait/epoll_wait03.c
index 4b21aba4c..d31e49864 100644
--- a/testcases/kernel/syscalls/epoll_wait/epoll_wait03.c
+++ b/testcases/kernel/syscalls/epoll_wait/epoll_wait03.c
@@ -57,7 +57,7 @@ static void setup(void)
epevs[0].data.fd = fds[1];
if (epoll_ctl(epfd, EPOLL_CTL_ADD, fds[1], &epevs[0]))
- tst_brk(TBROK | TERRNO, "epoll_clt(..., EPOLL_CTL_ADD, ...)");
+ tst_brk(TBROK | TERRNO, "epoll_ctl(..., EPOLL_CTL_ADD, ...)");
}
static void verify_epoll_wait(unsigned int n)
diff --git a/testcases/kernel/syscalls/epoll_wait/epoll_wait04.c b/testcases/kernel/syscalls/epoll_wait/epoll_wait04.c
index dc62e9202..bd8baca22 100644
--- a/testcases/kernel/syscalls/epoll_wait/epoll_wait04.c
+++ b/testcases/kernel/syscalls/epoll_wait/epoll_wait04.c
@@ -49,7 +49,7 @@ static void setup(void)
epevs[0].data.fd = fds[0];
if (epoll_ctl(epfd, EPOLL_CTL_ADD, fds[0], &epevs[0]))
- tst_brk(TBROK | TERRNO, "epoll_clt(..., EPOLL_CTL_ADD, ...)");
+ tst_brk(TBROK | TERRNO, "epoll_ctl(..., EPOLL_CTL_ADD, ...)");
}
static void cleanup(void)
diff --git a/testcases/kernel/syscalls/epoll_wait/epoll_wait05.c b/testcases/kernel/syscalls/epoll_wait/epoll_wait05.c
new file mode 100644
index 000000000..d06a024ff
--- /dev/null
+++ b/testcases/kernel/syscalls/epoll_wait/epoll_wait05.c
@@ -0,0 +1,126 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * [Description]
+ *
+ * Verify that epoll receives EPOLLRDHUP event when we hang a reading
+ * half-socket we are polling on.
+ */
+
+#include "tst_test.h"
+#include "tst_net.h"
+#include "tst_epoll.h"
+
+static int epfd;
+static int sockfd_client;
+static int sockfd_server;
+static in_port_t *sock_port;
+
+static void create_server(void)
+{
+ int sockfd_server;
+ socklen_t len;
+ struct sockaddr_in serv_addr;
+ struct sockaddr_in sin;
+
+ tst_init_sockaddr_inet_bin(&serv_addr, INADDR_ANY, 0);
+
+ sockfd_server = SAFE_SOCKET(AF_INET, SOCK_STREAM, 0);
+ SAFE_BIND(sockfd_server, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
+ SAFE_LISTEN(sockfd_server, 10);
+
+ len = sizeof(sin);
+ memset(&sin, 0, sizeof(struct sockaddr_in));
+ SAFE_GETSOCKNAME(sockfd_server, (struct sockaddr *)&sin, &len);
+
+ *sock_port = ntohs(sin.sin_port);
+
+ tst_res(TINFO, "Listening on port %d", *sock_port);
+
+ TST_CHECKPOINT_WAKE_AND_WAIT(0);
+
+ SAFE_CLOSE(sockfd_server);
+}
+
+static void run(void)
+{
+ struct sockaddr_in client_addr;
+ struct epoll_event evt_req;
+ struct epoll_event evt_rec;
+ int ret;
+
+ if (!SAFE_FORK()) {
+ create_server();
+ return;
+ }
+
+ TST_CHECKPOINT_WAIT(0);
+
+ tst_res(TINFO, "Connecting to port %d", *sock_port);
+
+ sockfd_client = SAFE_SOCKET(AF_INET, SOCK_STREAM, 0);
+
+ tst_init_sockaddr_inet(&client_addr, "127.0.0.1", *sock_port);
+
+ SAFE_CONNECT(sockfd_client,
+ (struct sockaddr *)&client_addr,
+ sizeof(client_addr));
+
+ tst_res(TINFO, "Polling on socket");
+
+ epfd = SAFE_EPOLL_CREATE1(0);
+ evt_req.events = EPOLLRDHUP;
+ SAFE_EPOLL_CTL(epfd, EPOLL_CTL_ADD, sockfd_client, &evt_req);
+
+ tst_res(TINFO, "Hang socket");
+
+ TST_EXP_PASS_SILENT(shutdown(sockfd_client, SHUT_RD));
+ ret = SAFE_EPOLL_WAIT(epfd, &evt_rec, 1, 2000);
+ if (ret != 1) {
+ tst_res(TFAIL, "Wrong number of events reported %i", ret);
+ goto exit;
+ }
+
+ if (evt_rec.events & EPOLLRDHUP)
+ tst_res(TPASS, "Received EPOLLRDHUP");
+ else
+ tst_res(TFAIL, "EPOLLRDHUP has not been received");
+
+exit:
+ SAFE_CLOSE(epfd);
+ SAFE_CLOSE(sockfd_client);
+
+ TST_CHECKPOINT_WAKE(0);
+}
+
+static void setup(void)
+{
+ sock_port = SAFE_MMAP(NULL, sizeof(in_port_t), PROT_READ | PROT_WRITE,
+ MAP_SHARED | MAP_ANONYMOUS, -1, 0);
+}
+
+static void cleanup(void)
+{
+ if (sock_port)
+ SAFE_MUNMAP(sock_port, sizeof(in_port_t));
+
+ if (fcntl(sockfd_client, F_GETFD) > 0)
+ SAFE_CLOSE(sockfd_client);
+
+ if (fcntl(sockfd_server, F_GETFD) > 0)
+ SAFE_CLOSE(sockfd_server);
+
+ if (fcntl(epfd, F_GETFD) > 0)
+ SAFE_CLOSE(epfd);
+}
+
+static struct tst_test test = {
+ .setup = setup,
+ .cleanup = cleanup,
+ .test_all = run,
+ .forks_child = 1,
+ .needs_checkpoints = 1,
+};
diff --git a/testcases/kernel/syscalls/epoll_wait/epoll_wait06.c b/testcases/kernel/syscalls/epoll_wait/epoll_wait06.c
new file mode 100644
index 000000000..f35e0423a
--- /dev/null
+++ b/testcases/kernel/syscalls/epoll_wait/epoll_wait06.c
@@ -0,0 +1,107 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * [Description]
+ *
+ * Verify that edge triggering is correctly handled by epoll, for both EPOLLIN
+ * and EPOLLOUT.
+ *
+ * [Algorithm]
+ *
+ * - The file descriptors for non-blocking pipe are registered on an epoll
+ * instance.
+ * - A pipe writer writes data on the write side of the pipe.
+ * - A call to epoll_wait() is done that will return a EPOLLIN event.
+ * - The pipe reader reads half of data from rfd.
+ * - A call to epoll_wait() should hang because there's data left to read.
+ * - The pipe reader reads remaining data from rfd.
+ * - A call to epoll_wait() should return a EPOLLOUT event.
+ */
+
+#define _GNU_SOURCE
+
+#include <fcntl.h>
+#include "tst_test.h"
+#include "tst_epoll.h"
+
+static size_t write_size;
+static size_t read_size;
+static int fds[2];
+static int epfd;
+
+static void setup(void)
+{
+ write_size = getpagesize();
+ read_size = write_size / 2;
+
+ SAFE_PIPE2(fds, O_NONBLOCK);
+
+ /* EPOLLOUT will be raised when buffer became empty after becoming full */
+ SAFE_FCNTL(fds[1], F_SETPIPE_SZ, write_size);
+}
+
+static void cleanup(void)
+{
+ if (epfd > 0)
+ SAFE_CLOSE(epfd);
+
+ if (fds[0] > 0)
+ SAFE_CLOSE(fds[0]);
+
+ if (fds[1] > 0)
+ SAFE_CLOSE(fds[1]);
+}
+
+static void run(void)
+{
+ char buff[write_size];
+ struct epoll_event evt_receive;
+
+ tst_res(TINFO, "Polling on channel with EPOLLET");
+
+ epfd = SAFE_EPOLL_CREATE1(0);
+
+ SAFE_EPOLL_CTL(epfd, EPOLL_CTL_ADD, fds[0], &((struct epoll_event) {
+ .events = EPOLLIN | EPOLLET,
+ .data.fd = fds[0],
+ }));
+ SAFE_EPOLL_CTL(epfd, EPOLL_CTL_ADD, fds[1], &((struct epoll_event) {
+ .events = EPOLLOUT | EPOLLET,
+ .data.fd = fds[1],
+ }));
+
+ tst_res(TINFO, "Write bytes on channel: %zu bytes", write_size);
+
+ memset(buff, 'a', write_size);
+ SAFE_WRITE(SAFE_WRITE_ANY, fds[1], buff, write_size);
+ TST_EXP_FAIL(write(fds[1], buff, write_size), EAGAIN, "write() failed");
+
+ TST_EXP_EQ_LI(SAFE_EPOLL_WAIT(epfd, &evt_receive, 1, 0), 1);
+ TST_EXP_EQ_LI(evt_receive.data.fd, fds[0]);
+ TST_EXP_EQ_LI(evt_receive.events & EPOLLIN, EPOLLIN);
+
+ tst_res(TINFO, "Read half bytes from channel: %zu bytes", read_size);
+
+ memset(buff, 0, write_size);
+ SAFE_READ(1, fds[0], buff, read_size);
+
+ TST_EXP_EQ_LI(SAFE_EPOLL_WAIT(epfd, &evt_receive, 1, 0), 0);
+
+ tst_res(TINFO, "Read remaining bytes from channel: %zu bytes", read_size);
+
+ SAFE_READ(1, fds[0], buff + read_size, read_size);
+ TST_EXP_FAIL(read(fds[0], buff, read_size), EAGAIN, "read() failed");
+
+ TST_EXP_EQ_LI(SAFE_EPOLL_WAIT(epfd, &evt_receive, 1, 0), 1);
+ TST_EXP_EQ_LI(evt_receive.data.fd, fds[1]);
+ TST_EXP_EQ_LI(evt_receive.events & EPOLLOUT, EPOLLOUT);
+}
+
+static struct tst_test test = {
+ .setup = setup,
+ .cleanup = cleanup,
+ .test_all = run,
+};
diff --git a/testcases/kernel/syscalls/epoll_wait/epoll_wait07.c b/testcases/kernel/syscalls/epoll_wait/epoll_wait07.c
new file mode 100644
index 000000000..dfabd0d87
--- /dev/null
+++ b/testcases/kernel/syscalls/epoll_wait/epoll_wait07.c
@@ -0,0 +1,73 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * [Description]
+ *
+ * Verify that EPOLLONESHOT is correctly handled by epoll_wait.
+ * We open a channel, write in it two times and verify that EPOLLIN has been
+ * received only once.
+ */
+
+#include <poll.h>
+#include <sys/epoll.h>
+#include "tst_test.h"
+#include "tst_epoll.h"
+
+static int fds[2];
+static int epfd;
+
+static void cleanup(void)
+{
+ if (epfd > 0)
+ SAFE_CLOSE(epfd);
+
+ if (fds[0] > 0)
+ SAFE_CLOSE(fds[0]);
+
+ if (fds[1] > 0)
+ SAFE_CLOSE(fds[1]);
+}
+
+static void run(void)
+{
+ struct epoll_event evt_receive;
+ char buff = 'a';
+
+ SAFE_PIPE(fds);
+
+ tst_res(TINFO, "Polling on channel with EPOLLONESHOT");
+
+ epfd = SAFE_EPOLL_CREATE1(0);
+
+ SAFE_EPOLL_CTL(epfd, EPOLL_CTL_ADD, fds[0], &((struct epoll_event) {
+ .events = EPOLLIN | EPOLLONESHOT,
+ .data.fd = fds[0],
+ }));
+
+ tst_res(TINFO, "Write channel for the 1st time. EPOLLIN expected");
+
+ SAFE_WRITE(0, fds[1], &buff, 1);
+ TST_EXP_EQ_LI(SAFE_EPOLL_WAIT(epfd, &evt_receive, 10, 0), 1);
+ TST_EXP_EQ_LI(evt_receive.events & EPOLLIN, EPOLLIN);
+ TST_EXP_EQ_LI(evt_receive.data.fd, fds[0]);
+
+ SAFE_READ(1, fds[0], &buff, 1);
+ TST_EXP_EQ_LI(SAFE_EPOLL_WAIT(epfd, &evt_receive, 10, 0), 0);
+
+ tst_res(TINFO, "Write channel for the 2nd time. No events expected");
+
+ SAFE_WRITE(0, fds[1], &buff, 1);
+ TST_EXP_EQ_LI(SAFE_EPOLL_WAIT(epfd, &evt_receive, 10, 0), 0);
+
+ SAFE_CLOSE(epfd);
+ SAFE_CLOSE(fds[0]);
+ SAFE_CLOSE(fds[1]);
+}
+
+static struct tst_test test = {
+ .cleanup = cleanup,
+ .test_all = run,
+};
diff --git a/testcases/kernel/syscalls/eventfd/.gitignore b/testcases/kernel/syscalls/eventfd/.gitignore
index db45c67cf..4f577370c 100644
--- a/testcases/kernel/syscalls/eventfd/.gitignore
+++ b/testcases/kernel/syscalls/eventfd/.gitignore
@@ -1 +1,6 @@
/eventfd01
+/eventfd02
+/eventfd03
+/eventfd04
+/eventfd05
+/eventfd06
diff --git a/testcases/kernel/syscalls/eventfd/eventfd01.c b/testcases/kernel/syscalls/eventfd/eventfd01.c
index 9b60434a2..b66d6a55c 100644
--- a/testcases/kernel/syscalls/eventfd/eventfd01.c
+++ b/testcases/kernel/syscalls/eventfd/eventfd01.c
@@ -1,738 +1,47 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
- * Copyright (c) 2008 Vijay Kumar B. <vijaykumar@bravegnu.org>
- * Copyright (c) Linux Test Project, 2008-2022
- *
- * Based on testcases/kernel/syscalls/waitpid/waitpid01.c
- * Original copyright message:
- *
- * 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
+ * Copyright (c) 2008 Vijay Kumar B. <vijaykumar@bravegnu.org>
+ * Copyright (c) Linux Test Project, 2008-2022
+ * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
*/
-/*
- * NAME
- * eventfd01.c
- *
- * DESCRIPTION
- * Test cases for eventfd syscall.
+/*\
+ * [Description]
*
- * USAGE: <for command-line>
- * eventfd01 [-c n] [-i n] [-I x] [-P x] [-t]
- * where, -c n : Run n copies concurrently.
- * -i n : Execute test n times.
- * -I x : Execute test for x seconds.
- * -P x : Pause for x seconds between iterations.
- *
- * History
- * 07/2008 Vijay Kumar
- * Initial Version.
- *
- * Restrictions
- * None
- */
-
-#include "config.h"
-
-#include <sys/types.h>
-#include <sys/select.h>
-#include <sys/wait.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <poll.h>
-#include <signal.h>
-#include <stdint.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "test.h"
-#define CLEANUP cleanup
-#include "lapi/syscalls.h"
-
-TCID_DEFINE(eventfd01);
-int TST_TOTAL = 15;
-
-#ifdef HAVE_LIBAIO
-#include <libaio.h>
-
-static void setup(void);
-
-static int myeventfd(unsigned int initval, int flags)
-{
- /* eventfd2 uses FLAGS but eventfd doesn't take FLAGS. */
- return tst_syscall(__NR_eventfd, initval);
-}
-
-/*
- * clear_counter() - clears the counter by performing a dummy read
- * @fd: the eventfd
+ * Verify read operation for eventfd fail with:
*
- * RETURNS:
- * 0 on success, and -1 on failure
- */
-static int clear_counter(int fd)
-{
- uint64_t dummy;
- int ret;
-
- ret = read(fd, &dummy, sizeof(dummy));
- if (ret == -1) {
- if (errno != EAGAIN) {
- tst_resm(TINFO | TERRNO, "error clearing counter");
- return -1;
- }
- }
-
- return 0;
-}
-
-/*
- * set_counter() - sets the count to specified value
- * @fd: the eventfd
- * @val: the value to be set
- *
- * Clears the counter and sets the counter to @val.
- *
- * RETURNS:
- * 0 on success, -1 on failure
- */
-static int set_counter(int fd, uint64_t val)
-{
- int ret;
-
- ret = clear_counter(fd);
- if (ret == -1)
- return -1;
-
- ret = write(fd, &val, sizeof(val));
- if (ret == -1) {
- tst_resm(TINFO | TERRNO, "error setting counter value");
- return -1;
- }
-
- return 0;
-}
-
-/*
- * Test whether the current value of the counter matches @required.
- */
-static void read_test(int fd, uint64_t required)
-{
- int ret;
- uint64_t val;
-
- ret = read(fd, &val, sizeof(val));
- if (ret == -1) {
- tst_resm(TBROK | TERRNO, "error reading eventfd");
- return;
- }
-
- if (val == required)
- tst_resm(TPASS, "counter value matches required");
- else
- tst_resm(TFAIL, "counter value mismatch: "
- "required: %" PRIu64 ", got: %" PRIu64, required, val);
-}
-
-/*
- * Test whether read returns with error EAGAIN when counter is at 0.
- */
-static void read_eagain_test(int fd)
-{
- int ret;
- uint64_t val;
-
- ret = clear_counter(fd);
- if (ret == -1) {
- tst_resm(TBROK, "error clearing counter");
- return;
- }
-
- ret = read(fd, &val, sizeof(val));
- if (ret == -1) {
- if (errno == EAGAIN)
- tst_resm(TPASS, "read failed with EAGAIN as expected");
- else
- tst_resm(TFAIL | TERRNO, "read failed (wanted EAGAIN)");
- } else
- tst_resm(TFAIL, "read returned with %d", ret);
-}
-
-/*
- * Test whether writing to counter works.
+ * - EAGAIN when counter is zero on non blocking fd
+ * - EINVAL when buffer size is less than 8 bytes
*/
-static void write_test(int fd)
-{
- int ret;
- uint64_t val;
-
- val = 12;
- ret = set_counter(fd, val);
- if (ret == -1) {
- tst_resm(TBROK, "error setting counter value to %" PRIu64, val);
- return;
- }
+#include <stdlib.h>
+#include <sys/eventfd.h>
+#include "tst_test.h"
- read_test(fd, val);
-}
+#define EVENT_COUNT 10
-/*
- * Test whether write returns with error EAGAIN when counter is at
- * (UINT64_MAX - 1).
- */
-static void write_eagain_test(int fd)
+static void run(void)
{
- int ret;
+ int fd;
uint64_t val;
-
- ret = set_counter(fd, UINT64_MAX - 1);
- if (ret == -1) {
- tst_resm(TBROK, "error setting counter value to UINT64_MAX-1");
- return;
- }
-
- val = 1;
- ret = write(fd, &val, sizeof(val));
- if (ret == -1) {
- if (errno == EAGAIN)
- tst_resm(TPASS, "write failed with EAGAIN as expected");
- else
- tst_resm(TFAIL, "write failed (wanted EAGAIN)");
- } else
- tst_resm(TFAIL, "write returned with %d", ret);
-}
-
-/*
- * Test whether read returns with error EINVAL, if buffer size is less
- * than 8 bytes.
- */
-static void read_einval_test(int fd)
-{
uint32_t invalid;
- int ret;
- ret = read(fd, &invalid, sizeof(invalid));
- if (ret == -1) {
- if (errno == EINVAL)
- tst_resm(TPASS, "read failed with EINVAL as expected");
- else
- tst_resm(TFAIL | TERRNO, "read failed (wanted EINVAL)");
- } else
- tst_resm(TFAIL, "read returned with %d", ret);
-}
+ fd = TST_EXP_FD(eventfd(EVENT_COUNT, EFD_NONBLOCK));
-/*
- * Test whether write returns with error EINVAL, if buffer size is
- * less than 8 bytes.
- */
-static void write_einval_test(int fd)
-{
- uint32_t invalid;
- int ret;
+ SAFE_READ(0, fd, &val, sizeof(val));
+ TST_EXP_EQ_LI(val, EVENT_COUNT);
- ret = write(fd, &invalid, sizeof(invalid));
- if (ret == -1) {
- if (errno == EINVAL)
- tst_resm(TPASS, "write failed with EINVAL as expected");
- else
- tst_resm(TFAIL | TERRNO,
- "write failed (wanted EINVAL)");
- } else
- tst_resm(TFAIL, "write returned with %d", ret);
-}
+ TST_EXP_FAIL(read(fd, &val, sizeof(val)), EAGAIN);
+ TST_EXP_FAIL(read(fd, &invalid, sizeof(invalid)), EINVAL);
-/*
- * Test wheter write returns with error EINVAL, when the written value
- * is 0xFFFFFFFFFFFFFFFF.
- */
-static void write_einval2_test(int fd)
-{
- int ret;
- uint64_t val;
-
- ret = clear_counter(fd);
- if (ret == -1) {
- tst_resm(TBROK, "error clearing counter");
- return;
- }
-
- val = 0xffffffffffffffffLL;
- ret = write(fd, &val, sizeof(val));
- if (ret == -1) {
- if (errno == EINVAL)
- tst_resm(TPASS, "write failed with EINVAL as expected");
- else
- tst_resm(TFAIL | TERRNO,
- "write failed (wanted EINVAL)");
- } else {
- tst_resm(TFAIL, "write returned with %d", ret);
- }
+ SAFE_CLOSE(fd);
}
-/*
- * Test whether readfd is set by select when counter value is
- * non-zero.
- */
-static void readfd_set_test(int fd)
-{
- int ret;
- fd_set readfds;
- struct timeval timeout = { 0, 0 };
- uint64_t non_zero = 10;
-
- FD_ZERO(&readfds);
- FD_SET(fd, &readfds);
-
- ret = set_counter(fd, non_zero);
- if (ret == -1) {
- tst_resm(TBROK, "error setting counter value to %" PRIu64,
- non_zero);
- return;
- }
-
- ret = select(fd + 1, &readfds, NULL, NULL, &timeout);
- if (ret == -1) {
- /* EINTR cannot occur, since we don't block. */
- tst_resm(TBROK | TERRNO, "select() failed");
- return;
- }
-
- if (FD_ISSET(fd, &readfds))
- tst_resm(TPASS, "fd is set in readfds");
- else
- tst_resm(TFAIL, "fd is not set in readfds");
-}
-
-/*
- * Test whether readfd is not set by select when counter value is
- * zero.
- */
-static void readfd_not_set_test(int fd)
-{
- int ret;
- fd_set readfds;
- struct timeval timeout = { 0, 0 };
-
- FD_ZERO(&readfds);
- FD_SET(fd, &readfds);
-
- ret = clear_counter(fd);
- if (ret == -1) {
- tst_resm(TBROK, "error clearing counter");
- return;
- }
-
- ret = select(fd + 1, &readfds, NULL, NULL, &timeout);
- if (ret == -1) {
- /* EINTR cannot occur, since we don't block. */
- tst_resm(TBROK | TERRNO, "select() failed");
- return;
- }
-
- if (!FD_ISSET(fd, &readfds))
- tst_resm(TPASS, "fd is not set in readfds");
- else
- tst_resm(TFAIL, "fd is set in readfds");
-}
-
-/*
- * Test whether writefd is set by select when counter value is not the
- * maximum counter value.
- */
-static void writefd_set_test(int fd)
-{
- int ret;
- fd_set writefds;
- struct timeval timeout = { 0, 0 };
- uint64_t non_max = 10;
-
- FD_ZERO(&writefds);
- FD_SET(fd, &writefds);
-
- ret = set_counter(fd, non_max);
- if (ret == -1) {
- tst_resm(TBROK, "error setting counter value to %" PRIu64,
- non_max);
- return;
- }
-
- ret = select(fd + 1, NULL, &writefds, NULL, &timeout);
- if (ret == -1) {
- /* EINTR cannot occur, since we don't block. */
- tst_resm(TBROK | TERRNO, "select: error getting fd status");
- return;
- }
-
- if (FD_ISSET(fd, &writefds))
- tst_resm(TPASS, "fd is set in writefds");
- else
- tst_resm(TFAIL, "fd is not set in writefds");
-}
-
-/*
- * Test whether writefd is not set by select when counter value is at
- * (UINT64_MAX - 1).
- */
-static void writefd_not_set_test(int fd)
-{
- int ret;
- fd_set writefds;
- struct timeval timeout = { 0, 0 };
-
- FD_ZERO(&writefds);
- FD_SET(fd, &writefds);
-
- ret = set_counter(fd, UINT64_MAX - 1);
- if (ret == -1) {
- tst_resm(TBROK, "error setting counter value to UINT64_MAX-1");
- return;
- }
-
- ret = select(fd + 1, NULL, &writefds, NULL, &timeout);
- if (ret == -1) {
- /* EINTR cannot occur, since we don't block. */
- tst_resm(TBROK | TERRNO, "select: error getting fd status");
- return;
- }
-
- if (!FD_ISSET(fd, &writefds))
- tst_resm(TPASS, "fd is not set in writefds");
- else
- tst_resm(TFAIL, "fd is set in writefds");
-}
-
-/*
- * Test whether counter update in child is reflected in the parent.
- */
-static void child_inherit_test(int fd)
-{
- uint64_t val;
- pid_t cpid;
- int ret;
- int status;
- uint64_t to_parent = 0xdeadbeef;
- uint64_t dummy;
-
- cpid = fork();
- if (cpid == -1)
- tst_resm(TBROK | TERRNO, "fork failed");
- else if (cpid != 0) {
- ret = wait(&status);
- if (ret == -1) {
- tst_resm(TBROK, "error getting child exit status");
- return;
- }
-
- if (WEXITSTATUS(status) == 1) {
- tst_resm(TBROK, "counter value write not "
- "successful in child");
- return;
- }
-
- ret = read(fd, &val, sizeof(val));
- if (ret == -1) {
- tst_resm(TBROK | TERRNO, "error reading eventfd");
- return;
- }
-
- if (val == to_parent)
- tst_resm(TPASS, "counter value write from "
- "child successful");
- else
- tst_resm(TFAIL, "counter value write in child "
- "failed");
- } else {
- /* Child */
- ret = read(fd, &dummy, sizeof(dummy));
- if (ret == -1 && errno != EAGAIN) {
- tst_resm(TWARN | TERRNO, "error clearing counter");
- exit(1);
- }
-
- ret = write(fd, &to_parent, sizeof(to_parent));
- if (ret == -1) {
- tst_resm(TWARN | TERRNO, "error writing eventfd");
- exit(1);
- }
-
- exit(0);
- }
-}
-
-#ifdef HAVE_IO_SET_EVENTFD
-/*
- * Test whether counter overflow is detected and handled correctly.
- *
- * It is not possible to directly overflow the counter using the
- * write() syscall. Overflows occur when the counter is incremented
- * from kernel space, in an irq context, when it is not possible to
- * block the calling thread of execution.
- *
- * The AIO subsystem internally uses eventfd mechanism for
- * notification of completion of read or write requests. In this test
- * we trigger a counter overflow, by setting the counter value to the
- * max possible value initially. When the AIO subsystem notifies
- * through the eventfd counter, the counter overflows.
- *
- * NOTE: If the the counter starts from an initial value of 0, it will
- * take decades for an overflow to occur. But since we set the initial
- * value to the max possible counter value, we are able to cause it to
- * overflow with a single increment.
- *
- * When the counter overflows, the following are tested
- * 1. Check whether POLLERR event occurs in poll() for the eventfd.
- * 2. Check whether readfd_set/writefd_set is set in select() for the
- eventfd.
- * 3. The counter value is UINT64_MAX.
- */
-static int trigger_eventfd_overflow(int evfd, int *fd, io_context_t * ctx)
-{
- int ret;
- struct iocb iocb;
- struct iocb *iocbap[1];
- struct io_event ioev;
- static char buf[4 * 1024];
-
- *ctx = 0;
- ret = io_setup(16, ctx);
- if (ret < 0) {
- errno = -ret;
- if (errno == ENOSYS) {
- tst_brkm(TCONF | TERRNO, cleanup,
- "io_setup(): AIO not supported by kernel");
- }
-
- tst_resm(TINFO | TERRNO, "io_setup error");
- return -1;
- }
-
- *fd = open("testfile", O_RDWR | O_CREAT, 0644);
- if (*fd == -1) {
- tst_resm(TINFO | TERRNO, "open(testfile) failed");
- goto err_io_destroy;
- }
-
- ret = set_counter(evfd, UINT64_MAX - 1);
- if (ret == -1) {
- tst_resm(TINFO, "error setting counter to UINT64_MAX-1");
- goto err_close_file;
- }
-
- io_prep_pwrite(&iocb, *fd, buf, sizeof(buf), 0);
- io_set_eventfd(&iocb, evfd);
-
- iocbap[0] = &iocb;
- ret = io_submit(*ctx, 1, iocbap);
- if (ret < 0) {
- errno = -ret;
- tst_resm(TINFO | TERRNO, "error submitting iocb");
- goto err_close_file;
- }
-
- ret = io_getevents(*ctx, 1, 1, &ioev, NULL);
- if (ret < 0) {
- errno = -ret;
- tst_resm(TINFO | TERRNO, "error waiting for event");
- goto err_close_file;
- }
-
- return 0;
-
-err_close_file:
- close(*fd);
-
-err_io_destroy:
- io_destroy(*ctx);
-
- return -1;
-}
-
-static void cleanup_overflow(int fd, io_context_t ctx)
-{
- close(fd);
- io_destroy(ctx);
-}
-
-static void overflow_select_test(int evfd)
-{
- struct timeval timeout = { 10, 0 };
- fd_set readfds;
- int fd;
- io_context_t ctx;
- int ret;
-
- ret = trigger_eventfd_overflow(evfd, &fd, &ctx);
- if (ret == -1) {
- tst_resm(TBROK, "error triggering eventfd overflow");
- return;
- }
-
- FD_ZERO(&readfds);
- FD_SET(evfd, &readfds);
- ret = select(evfd + 1, &readfds, NULL, NULL, &timeout);
- if (ret == -1)
- tst_resm(TBROK | TERRNO,
- "error getting evfd status with select");
- else {
- if (FD_ISSET(evfd, &readfds))
- tst_resm(TPASS, "read fd set as expected");
- else
- tst_resm(TFAIL, "read fd not set");
- }
- cleanup_overflow(fd, ctx);
-}
-
-static void overflow_poll_test(int evfd)
-{
- struct pollfd pollfd;
- int fd;
- io_context_t ctx;
- int ret;
-
- ret = trigger_eventfd_overflow(evfd, &fd, &ctx);
- if (ret == -1) {
- tst_resm(TBROK, "error triggering eventfd overflow");
- return;
- }
-
- pollfd.fd = evfd;
- pollfd.events = POLLIN;
- pollfd.revents = 0;
- ret = poll(&pollfd, 1, 10000);
- if (ret == -1)
- tst_resm(TBROK | TERRNO, "error getting evfd status with poll");
- else {
- if (pollfd.revents & POLLERR)
- tst_resm(TPASS, "POLLERR occurred as expected");
- else
- tst_resm(TFAIL, "POLLERR did not occur");
- }
- cleanup_overflow(fd, ctx);
-}
-
-static void overflow_read_test(int evfd)
-{
- uint64_t count;
- io_context_t ctx;
- int fd;
- int ret;
-
- ret = trigger_eventfd_overflow(evfd, &fd, &ctx);
- if (ret == -1) {
- tst_resm(TBROK, "error triggering eventfd overflow");
- return;
- }
-
- ret = read(evfd, &count, sizeof(count));
- if (ret == -1)
- tst_resm(TBROK | TERRNO, "error reading eventfd");
- else {
-
- if (count == UINT64_MAX)
- tst_resm(TPASS, "overflow occurred as expected");
- else
- tst_resm(TFAIL, "overflow did not occur");
- }
- cleanup_overflow(fd, ctx);
-}
-#else
-static void overflow_select_test(int evfd)
-{
- tst_resm(TCONF, "eventfd support is not available in AIO subsystem");
-}
-
-static void overflow_poll_test(int evfd)
-{
- tst_resm(TCONF, "eventfd support is not available in AIO subsystem");
-}
-
-static void overflow_read_test(int evfd)
-{
- tst_resm(TCONF, "eventfd support is not available in AIO subsystem");
-}
-#endif
-
-int main(int argc, char **argv)
-{
- int lc;
- int fd;
-
- tst_parse_opts(argc, argv, NULL, NULL);
-
- setup();
-
- for (lc = 0; TEST_LOOPING(lc); lc++) {
- int ret;
- uint64_t einit = 10;
-
- tst_count = 0;
-
- fd = myeventfd(einit, 0);
- if (fd == -1)
- tst_brkm(TBROK | TERRNO, CLEANUP,
- "error creating eventfd");
-
- ret = fcntl(fd, F_SETFL, O_NONBLOCK);
- if (ret == -1)
- tst_brkm(TBROK | TERRNO, CLEANUP,
- "error setting non-block mode");
-
- read_test(fd, einit);
- read_eagain_test(fd);
- write_test(fd);
- write_eagain_test(fd);
- read_einval_test(fd);
- write_einval_test(fd);
- write_einval2_test(fd);
- readfd_set_test(fd);
- readfd_not_set_test(fd);
- writefd_set_test(fd);
- writefd_not_set_test(fd);
- child_inherit_test(fd);
- overflow_select_test(fd);
- overflow_poll_test(fd);
- overflow_read_test(fd);
-
- close(fd);
- }
-
- cleanup();
-
- tst_exit();
-}
-
-static void setup(void)
-{
-
- tst_sig(FORK, DEF_HANDLER, cleanup);
-
- tst_tmpdir();
-
- TEST_PAUSE;
-}
-
-static void cleanup(void)
-{
- tst_rmdir();
-}
-
-#else
-int main(void)
-{
- tst_brkm(TCONF, NULL, "test requires libaio and it's development packages");
-}
-#endif
+static struct tst_test test = {
+ .test_all = run,
+ .needs_kconfigs = (const char *[]) {
+ "CONFIG_EVENTFD",
+ NULL
+ },
+};
diff --git a/testcases/kernel/syscalls/eventfd/eventfd02.c b/testcases/kernel/syscalls/eventfd/eventfd02.c
new file mode 100644
index 000000000..f028961c7
--- /dev/null
+++ b/testcases/kernel/syscalls/eventfd/eventfd02.c
@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) International Business Machines Corp., 2001
+ * Copyright (c) 2008 Vijay Kumar B. <vijaykumar@bravegnu.org>
+ * Copyright (c) Linux Test Project, 2008-2022
+ * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * [Description]
+ *
+ * Verify write operation for eventfd fail with:
+ *
+ * - EAGAIN when counter is zero on non blocking fd
+ * - EINVAL when buffer size is less than 8 bytes, or if an attempt is made to
+ * write the value 0xffffffffffffffff
+ */
+
+#include <stdlib.h>
+#include <sys/eventfd.h>
+#include "tst_test.h"
+
+static void run(void)
+{
+ int fd;
+ uint64_t val = 12;
+ uint64_t buf;
+ uint32_t invalid;
+
+ fd = TST_EXP_FD(eventfd(0, EFD_NONBLOCK));
+
+ SAFE_WRITE(0, fd, &val, sizeof(val));
+ SAFE_READ(0, fd, &buf, sizeof(buf));
+ TST_EXP_EQ_LI(buf, val);
+
+ val = UINT64_MAX - 1;
+ SAFE_WRITE(0, fd, &val, sizeof(val));
+ TST_EXP_FAIL(write(fd, &val, sizeof(val)), EAGAIN);
+ TST_EXP_FAIL(write(fd, &invalid, sizeof(invalid)), EINVAL);
+
+ val = 0xffffffffffffffffLL;
+ TST_EXP_FAIL(write(fd, &val, sizeof(val)), EINVAL);
+
+ SAFE_CLOSE(fd);
+}
+
+static struct tst_test test = {
+ .test_all = run,
+ .needs_kconfigs = (const char *[]) {
+ "CONFIG_EVENTFD",
+ NULL
+ },
+};
diff --git a/testcases/kernel/syscalls/eventfd/eventfd03.c b/testcases/kernel/syscalls/eventfd/eventfd03.c
new file mode 100644
index 000000000..452264cad
--- /dev/null
+++ b/testcases/kernel/syscalls/eventfd/eventfd03.c
@@ -0,0 +1,57 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) International Business Machines Corp., 2001
+ * Copyright (c) 2008 Vijay Kumar B. <vijaykumar@bravegnu.org>
+ * Copyright (c) Linux Test Project, 2008-2022
+ * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * [Description]
+ *
+ * Test whether readfd is set by select() when eventfd() counter value is
+ * non-zero, then check if readfd is not set when eventfd() counter value is
+ * zero.
+ */
+
+#include <stdlib.h>
+#include <sys/eventfd.h>
+#include "tst_test.h"
+
+static void run(void)
+{
+ int fd;
+ uint64_t val;
+ fd_set readfds;
+ uint64_t non_zero = 10;
+ struct timeval timeout = { 0, 0 };
+
+ fd = TST_EXP_FD(eventfd(0, EFD_NONBLOCK));
+
+ FD_ZERO(&readfds);
+ FD_SET(fd, &readfds);
+
+ SAFE_WRITE(0, fd, &non_zero, sizeof(non_zero));
+ TEST(select(fd + 1, &readfds, NULL, NULL, &timeout));
+ if (TST_RET == -1)
+ tst_brk(TBROK | TERRNO, "select");
+
+ TST_EXP_EQ_LI(FD_ISSET(fd, &readfds), 1);
+
+ SAFE_READ(0, fd, &val, sizeof(val));
+ TEST(select(fd + 1, &readfds, NULL, NULL, &timeout));
+ if (TST_RET == -1)
+ tst_brk(TBROK | TERRNO, "select");
+
+ TST_EXP_EQ_LI(FD_ISSET(fd, &readfds), 0);
+
+ SAFE_CLOSE(fd);
+}
+
+static struct tst_test test = {
+ .test_all = run,
+ .needs_kconfigs = (const char *[]) {
+ "CONFIG_EVENTFD",
+ NULL
+ },
+};
diff --git a/testcases/kernel/syscalls/eventfd/eventfd04.c b/testcases/kernel/syscalls/eventfd/eventfd04.c
new file mode 100644
index 000000000..c7186ae64
--- /dev/null
+++ b/testcases/kernel/syscalls/eventfd/eventfd04.c
@@ -0,0 +1,60 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) International Business Machines Corp., 2001
+ * Copyright (c) 2008 Vijay Kumar B. <vijaykumar@bravegnu.org>
+ * Copyright (c) Linux Test Project, 2008-2022
+ * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * [Description]
+ *
+ * Test whether writefd is set by select() when eventfd() counter value is
+ * not the maximum value, then check if writefd is not set when eventfd()
+ * counter value is maximum value.
+ */
+
+#include <stdlib.h>
+#include <sys/eventfd.h>
+#include "tst_test.h"
+
+static void run(void)
+{
+ int fd;
+ fd_set writefds;
+ uint64_t val;
+ uint64_t non_max = 10;
+ uint64_t max = UINT64_MAX - 1;
+ struct timeval timeout = { 0, 0 };
+
+ fd = TST_EXP_FD(eventfd(0, EFD_NONBLOCK));
+
+ FD_ZERO(&writefds);
+ FD_SET(fd, &writefds);
+
+ SAFE_WRITE(0, fd, &non_max, sizeof(non_max));
+ TEST(select(fd + 1, NULL, &writefds, NULL, &timeout));
+ if (TST_RET == -1)
+ tst_brk(TBROK | TERRNO, "select");
+
+ TST_EXP_EQ_LI(FD_ISSET(fd, &writefds), 1);
+
+ SAFE_READ(0, fd, &val, sizeof(val));
+ SAFE_WRITE(0, fd, &max, sizeof(max));
+
+ TEST(select(fd + 1, NULL, &writefds, NULL, &timeout));
+ if (TST_RET == -1)
+ tst_brk(TBROK | TERRNO, "select");
+
+ TST_EXP_EQ_LI(FD_ISSET(fd, &writefds), 0);
+
+ SAFE_CLOSE(fd);
+}
+
+static struct tst_test test = {
+ .test_all = run,
+ .needs_kconfigs = (const char *[]) {
+ "CONFIG_EVENTFD",
+ NULL
+ },
+};
diff --git a/testcases/kernel/syscalls/eventfd/eventfd05.c b/testcases/kernel/syscalls/eventfd/eventfd05.c
new file mode 100644
index 000000000..6ea2c4138
--- /dev/null
+++ b/testcases/kernel/syscalls/eventfd/eventfd05.c
@@ -0,0 +1,47 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) International Business Machines Corp., 2001
+ * Copyright (c) 2008 Vijay Kumar B. <vijaykumar@bravegnu.org>
+ * Copyright (c) Linux Test Project, 2008-2022
+ * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * [Description]
+ *
+ * Test whether eventfd() counter update in child is reflected in the parent.
+ */
+
+#include <stdlib.h>
+#include <sys/eventfd.h>
+#include "tst_test.h"
+
+static void run(void)
+{
+ int fd;
+ uint64_t val;
+ uint64_t to_parent = 0xdeadbeef;
+
+ fd = TST_EXP_FD(eventfd(0, EFD_NONBLOCK));
+
+ if (!SAFE_FORK()) {
+ SAFE_WRITE(0, fd, &to_parent, sizeof(to_parent));
+ exit(0);
+ }
+
+ tst_reap_children();
+
+ SAFE_READ(0, fd, &val, sizeof(val));
+ TST_EXP_EQ_LI(val, to_parent);
+
+ SAFE_CLOSE(fd);
+}
+
+static struct tst_test test = {
+ .test_all = run,
+ .forks_child = 1,
+ .needs_kconfigs = (const char *[]) {
+ "CONFIG_EVENTFD",
+ NULL
+ },
+};
diff --git a/testcases/kernel/syscalls/eventfd/eventfd06.c b/testcases/kernel/syscalls/eventfd/eventfd06.c
new file mode 100644
index 000000000..7339dd471
--- /dev/null
+++ b/testcases/kernel/syscalls/eventfd/eventfd06.c
@@ -0,0 +1,174 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) International Business Machines Corp., 2001
+ * Copyright (c) 2008 Vijay Kumar B. <vijaykumar@bravegnu.org>
+ * Copyright (c) Linux Test Project, 2008-2022
+ * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * [Description]
+ *
+ * Test whether counter overflow is detected and handled correctly.
+ *
+ * It is not possible to directly overflow the counter using the
+ * write() syscall. Overflows occur when the counter is incremented
+ * from kernel space, in an IRQ context, when it is not possible to
+ * block the calling thread of execution.
+ *
+ * The AIO subsystem internally uses eventfd mechanism for
+ * notification of completion of read or write requests. In this test
+ * we trigger a counter overflow, by setting the counter value to the
+ * max possible value initially. When the AIO subsystem notifies
+ * through the eventfd counter, the counter overflows.
+ *
+ * If the counter starts from an initial value of 0, it will
+ * take decades for an overflow to occur. But since we set the initial
+ * value to the max possible counter value, we are able to cause it to
+ * overflow with a single increment.
+ *
+ * When the counter overflows, the following is tested:
+ *
+ * - POLLERR event occurs in poll() for the eventfd
+ * - readfd_set/writefd_set is set in select() for the eventfd
+ * - the counter value is UINT64_MAX
+ */
+
+#include "tst_test.h"
+
+#ifdef HAVE_LIBAIO
+#ifdef HAVE_IO_SET_EVENTFD
+
+#include <poll.h>
+#include <libaio.h>
+#include <stdlib.h>
+#include <sys/eventfd.h>
+
+#define MAXEVENTS 16
+#define BUFSIZE 1024
+
+static int fd;
+static int evfd;
+static io_context_t ctx;
+
+static void async_write(void)
+{
+ struct iocb iocb;
+ struct iocb *iocbap[1];
+ struct io_event ioev;
+ static char buf[BUFSIZE];
+
+ memset(buf, 1, BUFSIZE);
+
+ io_prep_pwrite(&iocb, fd, buf, sizeof(buf), 0);
+ io_set_eventfd(&iocb, evfd);
+
+ iocbap[0] = &iocb;
+ TEST(io_submit(ctx, 1, iocbap));
+ if (TST_RET < 0)
+ tst_brk(TBROK, "io_submit() failed: %s", tst_strerrno(-TST_RET));
+
+ TEST(io_getevents(ctx, 1, 1, &ioev, NULL));
+ if (TST_RET < 0)
+ tst_brk(TBROK, "io_getevents() failed: %s", tst_strerrno(-TST_RET));
+}
+
+static void clear_counter(void)
+{
+ uint64_t val;
+ uint64_t max = UINT64_MAX - 1;
+
+ TEST(read(evfd, &val, sizeof(val)));
+ if (TST_RET == -1 && TST_ERR != EAGAIN)
+ tst_brk(TBROK | TERRNO, "read");
+
+ SAFE_WRITE(0, evfd, &max, sizeof(max));
+}
+
+static void test_select(void)
+{
+ fd_set readfds;
+ uint64_t count;
+ struct timeval timeout = { 10, 0 };
+
+ clear_counter();
+ async_write();
+
+ FD_ZERO(&readfds);
+ FD_SET(fd, &readfds);
+
+ tst_res(TINFO, "Checking if select() detects counter overflow");
+
+ TEST(select(fd + 1, NULL, &readfds, NULL, &timeout));
+ if (TST_RET == -1)
+ tst_brk(TBROK | TERRNO, "select");
+
+ TST_EXP_EQ_LI(FD_ISSET(fd, &readfds), 1);
+
+ SAFE_READ(0, evfd, &count, sizeof(count));
+ TST_EXP_EQ_LI(count, UINT64_MAX);
+}
+
+static void test_poll(void)
+{
+ uint64_t count;
+ struct pollfd pollfd;
+
+ clear_counter();
+ async_write();
+
+ pollfd.fd = evfd;
+ pollfd.events = POLLIN;
+ pollfd.revents = 0;
+
+ tst_res(TINFO, "Checking if poll() detects counter overflow");
+
+ TEST(poll(&pollfd, 1, 10000));
+ if (TST_RET == -1)
+ tst_brk(TBROK | TERRNO, "poll");
+
+ TST_EXP_EQ_LI(pollfd.revents & POLLERR, POLLERR);
+
+ SAFE_READ(0, evfd, &count, sizeof(count));
+ TST_EXP_EQ_LI(count, UINT64_MAX);
+}
+
+static void setup(void)
+{
+ TEST(io_setup(MAXEVENTS, &ctx));
+ if (TST_RET < 0)
+ tst_brk(TBROK, "io_setup() failed: %s", tst_strerrno(-TST_RET));
+
+ fd = SAFE_OPEN("testfile", O_RDWR | O_CREAT, 0644);
+ evfd = TST_EXP_FD(eventfd(0, EFD_NONBLOCK));
+}
+
+static void cleanup(void)
+{
+ SAFE_CLOSE(evfd);
+ io_destroy(ctx);
+}
+
+static void run(void)
+{
+ test_select();
+ test_poll();
+}
+
+static struct tst_test test = {
+ .test_all = run,
+ .setup = setup,
+ .cleanup = cleanup,
+ .needs_tmpdir = 1,
+ .needs_kconfigs = (const char *[]) {
+ "CONFIG_EVENTFD",
+ NULL
+ },
+};
+
+#else /* HAVE_IO_SET_EVENTFD */
+TST_TEST_TCONF("eventfd support is not available in AIO subsystem");
+#endif
+#else /* HAVE_LIBAIO */
+TST_TEST_TCONF("libaio is not available");
+#endif
diff --git a/testcases/kernel/syscalls/eventfd2/eventfd2.h b/testcases/kernel/syscalls/eventfd2/eventfd2.h
new file mode 100644
index 000000000..5350820b8
--- /dev/null
+++ b/testcases/kernel/syscalls/eventfd2/eventfd2.h
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+#include "tst_test.h"
+#include "lapi/syscalls.h"
+
+static inline int eventfd2(unsigned int count, unsigned int flags)
+{
+ int ret;
+
+ ret = tst_syscall(__NR_eventfd2, count, flags);
+ if (ret == -1)
+ tst_brk(TBROK | TERRNO, "eventfd2");
+
+ return ret;
+}
diff --git a/testcases/kernel/syscalls/eventfd2/eventfd2_01.c b/testcases/kernel/syscalls/eventfd2/eventfd2_01.c
index 85ad86d42..3a80379a3 100644
--- a/testcases/kernel/syscalls/eventfd2/eventfd2_01.c
+++ b/testcases/kernel/syscalls/eventfd2/eventfd2_01.c
@@ -1,119 +1,37 @@
-/******************************************************************************/
-/* */
-/* Copyright (c) Ulrich Drepper <drepper@redhat.com> */
-/* Copyright (c) International Business Machines Corp., 2009 */
-/* */
-/* 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 */
-/* */
-/******************************************************************************/
-/******************************************************************************/
-/* */
-/* File: eventfd2_01.c */
-/* */
-/* Description: This Program tests the new system call introduced in 2.6.27. */
-/* Ulrich´s comment as in: */
-/* http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=b087498eb5605673b0f260a7620d91818cd72304 */
-/* says: */
-/* This patch adds the new eventfd2 syscall. It extends the old eventfd */
-/* syscall by one parameter which is meant to hold a flag value. In this */
-/* patch the only flag support is EFD_CLOEXEC which causes the close-on-exec */
-/* flag for the returned file descriptor to be set. A new name EFD_CLOEXEC is */
-/* introduced which in this implementation must have the same value as */
-/* O_CLOEXEC. The following test must be adjusted for architectures other than*/
-/* x86 and x86-64 and in case the syscall numbers changed. */
-/* */
-/* Usage: <for command-line> */
-/* eventfd2_01 [-c n] [-e][-i n] [-I x] [-p x] [-t] */
-/* where, -c n : Run n copies concurrently. */
-/* -e : Turn on errno logging. */
-/* -i n : Execute test n times. */
-/* -I x : Execute test for x seconds. */
-/* -P x : Pause for x seconds between iterations. */
-/* -t : Turn on syscall timing. */
-/* */
-/* Total Tests: 1 */
-/* */
-/* Test Name: eventfd2_01 */
-/* */
-/* Author: Ulrich Drepper <drepper@redhat.com> */
-/* */
-/* History: Created - Jan 08 2009 - Ulrich Drepper <drepper@redhat.com> */
-/* Ported to LTP */
-/* - Jan 08 2009 - Subrata <subrata@linux.vnet.ibm.com> */
-/******************************************************************************/
-#include <stdio.h>
-#include <unistd.h>
-#include <sys/syscall.h>
-#include <errno.h>
-
-#include "test.h"
-#include "lapi/fcntl.h"
-#include "lapi/syscalls.h"
-
-#define EFD_CLOEXEC O_CLOEXEC
-
-char *TCID = "eventfd2_01";
-int testno;
-int TST_TOTAL = 1;
-
-void cleanup(void)
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) Ulrich Drepper <drepper@redhat.com>
+ * Copyright (c) International Business Machines Corp., 2009
+ * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * [Description]
+ *
+ * This test verifies that eventfd2 correctly set FD_CLOEXEC flag on file when
+ * EFD_CLOEXEC flag is used.
+ */
+
+#include <fcntl.h>
+#include <sys/eventfd.h>
+#include "tst_test.h"
+#include "eventfd2.h"
+
+static void run(void)
{
- tst_rmdir();
-}
+ int fd, flags;
-void setup(void)
-{
- TEST_PAUSE;
- tst_tmpdir();
-}
+ fd = eventfd2(1, 0);
+ flags = SAFE_FCNTL(fd, F_GETFD);
+ TST_EXP_EXPR(!(flags & FD_CLOEXEC), "FD_CLOEXEC is not set");
+ SAFE_CLOSE(fd);
-int main(int argc, char *argv[])
-{
- int fd, coe;
-
- tst_parse_opts(argc, argv, NULL, NULL);
-
- setup();
-
- fd = tst_syscall(__NR_eventfd2, 1, 0);
- if (fd == -1) {
- tst_brkm(TFAIL, cleanup, "eventfd2(0) failed");
- }
- coe = fcntl(fd, F_GETFD);
- if (coe == -1) {
- tst_brkm(TBROK, cleanup, "fcntl failed");
- }
- if (coe & FD_CLOEXEC) {
- tst_brkm(TFAIL, cleanup, "eventfd2(0) set close-on-exec flag");
- }
- close(fd);
-
- fd = tst_syscall(__NR_eventfd2, 1, EFD_CLOEXEC);
- if (fd == -1) {
- tst_brkm(TFAIL, cleanup, "eventfd2(EFD_CLOEXEC) failed");
- }
- coe = fcntl(fd, F_GETFD);
- if (coe == -1) {
- tst_brkm(TBROK, cleanup, "fcntl failed");
- }
- if ((coe & FD_CLOEXEC) == 0) {
- tst_brkm(TFAIL, cleanup,
- "eventfd2(EFD_CLOEXEC) does not set close-on-exec flag");
- }
- close(fd);
- tst_resm(TPASS, "eventfd2(EFD_CLOEXEC) Passed");
- cleanup();
- tst_exit();
+ fd = eventfd2(1, EFD_CLOEXEC);
+ flags = SAFE_FCNTL(fd, F_GETFD);
+ TST_EXP_EXPR((flags & FD_CLOEXEC), "FD_CLOEXEC is set");
+ SAFE_CLOSE(fd);
}
+
+static struct tst_test test = {
+ .test_all = run,
+};
diff --git a/testcases/kernel/syscalls/eventfd2/eventfd2_02.c b/testcases/kernel/syscalls/eventfd2/eventfd2_02.c
index 5f3b6ee67..430cdb33c 100644
--- a/testcases/kernel/syscalls/eventfd2/eventfd2_02.c
+++ b/testcases/kernel/syscalls/eventfd2/eventfd2_02.c
@@ -1,118 +1,37 @@
-/******************************************************************************/
-/* */
-/* Copyright (c) Ulrich Drepper <drepper@redhat.com> */
-/* Copyright (c) International Business Machines Corp., 2009 */
-/* */
-/* 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 */
-/* */
-/******************************************************************************/
-/******************************************************************************/
-/* */
-/* File: eventfd2_02.c */
-/* */
-/* Description: This Program tests the new system call introduced in 2.6.27. */
-/* Ulrich´s comment as in: */
-/* http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=e7d476dfdf0bcfed478a207aecfdc84f81efecaf */
-/* which says: */
-/* This patch adds support for the EFD_NONBLOCK flag to eventfd2. The */
-/* additional changes needed are minimal. The following test must be adjusted */
-/* or architectures other than x86 and x86-64 and in case the syscall numbers */
-/* changed. */
-/* */
-/* Usage: <for command-line> */
-/* eventfd2_02 [-c n] [-e][-i n] [-I x] [-p x] [-t] */
-/* where, -c n : Run n copies concurrently. */
-/* -e : Turn on errno logging. */
-/* -i n : Execute test n times. */
-/* -I x : Execute test for x seconds. */
-/* -P x : Pause for x seconds between iterations. */
-/* -t : Turn on syscall timing. */
-/* */
-/* Total Tests: 1 */
-/* */
-/* Test Name: eventfd2_02 */
-/* */
-/* Author: Ulrich Drepper <drepper@redhat.com> */
-/* */
-/* History: Created - Jan 13 2009 - Ulrich Drepper <drepper@redhat.com> */
-/* Ported to LTP */
-/* - Jan 13 2009 - Subrata <subrata@linux.vnet.ibm.com> */
-/******************************************************************************/
-#include <stdio.h>
-#include <unistd.h>
-#include <sys/syscall.h>
-#include <errno.h>
-
-#include "test.h"
-#include "lapi/fcntl.h"
-#include "lapi/syscalls.h"
-
-#define EFD_NONBLOCK O_NONBLOCK
-
-char *TCID = "eventfd2_02";
-int testno;
-int TST_TOTAL = 1;
-
-void cleanup(void)
-{
- tst_rmdir();
-}
-
-void setup(void)
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) Ulrich Drepper <drepper@redhat.com>
+ * Copyright (c) International Business Machines Corp., 2009
+ * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * [Description]
+ *
+ * This test verifies that eventfd2 correctly set O_NONBLOCK flag on file when
+ * EFD_NONBLOCK flag is used.
+ */
+
+#include <fcntl.h>
+#include <sys/eventfd.h>
+#include "tst_test.h"
+#include "eventfd2.h"
+
+static void run(void)
{
- TEST_PAUSE;
- tst_tmpdir();
-}
-
-int main(int argc, char *argv[])
-{
- int fd, fl;
-
- tst_parse_opts(argc, argv, NULL, NULL);
+ int fd, flags;
- setup();
+ fd = eventfd2(1, 0);
+ flags = SAFE_FCNTL(fd, F_GETFL);
+ TST_EXP_EXPR(!(flags & O_NONBLOCK), "O_NONBLOCK is not set");
+ SAFE_CLOSE(fd);
- tst_count = 0;
- fd = tst_syscall(__NR_eventfd2, 1, 0);
- if (fd == -1) {
- tst_brkm(TFAIL, cleanup, "eventfd2(0) failed");
- }
- fl = fcntl(fd, F_GETFL);
- if (fl == -1) {
- tst_brkm(TBROK, cleanup, "fcntl failed");
- }
- if (fl & O_NONBLOCK) {
- tst_brkm(TFAIL, cleanup, "eventfd2(0) sets non-blocking mode");
- }
- close(fd);
-
- fd = tst_syscall(__NR_eventfd2, 1, EFD_NONBLOCK);
- if (fd == -1) {
- tst_brkm(TFAIL, cleanup, "eventfd2(EFD_NONBLOCK) failed");
- }
- fl = fcntl(fd, F_GETFL);
- if (fl == -1) {
- tst_brkm(TBROK, cleanup, "fcntl failed");
- }
- if ((fl & O_NONBLOCK) == 0) {
- tst_brkm(TFAIL, cleanup,
- "eventfd2(EFD_NONBLOCK) didn't set non-blocking mode");
- }
- close(fd);
- tst_resm(TPASS, "eventfd2(EFD_NONBLOCK) PASSED");
-
- cleanup();
- tst_exit();
+ fd = eventfd2(1, EFD_NONBLOCK);
+ flags = SAFE_FCNTL(fd, F_GETFL);
+ TST_EXP_EXPR((flags & O_NONBLOCK), "O_NONBLOCK is set");
+ SAFE_CLOSE(fd);
}
+
+static struct tst_test test = {
+ .test_all = run,
+};
diff --git a/testcases/kernel/syscalls/eventfd2/eventfd2_03.c b/testcases/kernel/syscalls/eventfd2/eventfd2_03.c
index 909004edb..e1949fd32 100644
--- a/testcases/kernel/syscalls/eventfd2/eventfd2_03.c
+++ b/testcases/kernel/syscalls/eventfd2/eventfd2_03.c
@@ -1,139 +1,81 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
- * eventfd-sem by Davide Libenzi (Simple test for eventfd sempahore)
- * Copyright (C) 2009 Davide Libenzi
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Davide Libenzi <davidel@xmailserver.org>
- * Reference: http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=bcd0b235bf3808dec5115c381cd55568f63b85f0
- * Reference: http://www.xmailserver.org/eventfd-sem.c
- * eventfd: testing improved support for semaphore-like behavior in linux-2.6.30
+ * Copyright (c) Ulrich Drepper <drepper@redhat.com>
+ * Copyright (c) International Business Machines Corp., 2009
+ * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * [Description]
*
+ * This test verifies that eventfd2 semaphore-like support is properly working.
*/
-#include <sys/types.h>
-#include <sys/syscall.h>
-#include <sys/stat.h>
-#include <sys/wait.h>
#include <fcntl.h>
#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-#include <inttypes.h>
-
-#include "test.h"
-#include "lapi/syscalls.h"
-
-char *TCID = "eventfd2_03";
-int TST_TOTAL = 1;
-
-#ifndef EFD_SEMLIKE
-#define EFD_SEMLIKE (1 << 0)
-#endif
-
-/* Dummy function as syscall from linux_syscall_numbers.h uses cleanup(). */
-void cleanup(void)
-{
-}
-
-static int eventfd2(int count, int flags)
-{
- return tst_syscall(__NR_eventfd2, count, flags);
-}
+#include <sys/eventfd.h>
+#include "tst_test.h"
+#include "eventfd2.h"
static void xsem_wait(int fd)
{
u_int64_t cntr;
- if (read(fd, &cntr, sizeof(cntr)) != sizeof(cntr)) {
- perror("reading eventfd");
- exit(1);
- }
- fprintf(stdout, "[%u] wait completed on %d: count=%" PRIu64 "\n",
- getpid(), fd, cntr);
+ SAFE_READ(0, fd, &cntr, sizeof(cntr));
}
static void xsem_post(int fd, int count)
{
u_int64_t cntr = count;
- if (write(fd, &cntr, sizeof(cntr)) != sizeof(cntr)) {
- perror("writing eventfd");
- exit(1);
- }
+ SAFE_WRITE(0, fd, &cntr, sizeof(cntr));
}
static void sem_player(int fd1, int fd2)
{
- fprintf(stdout, "[%u] posting 1 on %d\n", getpid(), fd1);
- xsem_post(fd1, 1);
+ pid_t pid = getpid();
- fprintf(stdout, "[%u] waiting on %d\n", getpid(), fd2);
- xsem_wait(fd2);
-
- fprintf(stdout, "[%u] posting 1 on %d\n", getpid(), fd1);
+ tst_res(TINFO, "[%u] posting 1 on fd=%d", pid, fd1);
xsem_post(fd1, 1);
- fprintf(stdout, "[%u] waiting on %d\n", getpid(), fd2);
+ tst_res(TINFO, "[%u] waiting on fd=%d", pid, fd2);
xsem_wait(fd2);
- fprintf(stdout, "[%u] posting 5 on %d\n", getpid(), fd1);
+ tst_res(TINFO, "[%u] posting 5 on fd=%d", pid, fd1);
xsem_post(fd1, 5);
- fprintf(stdout, "[%u] waiting 5 times on %d\n", getpid(), fd2);
+ tst_res(TINFO, "[%u] waiting 5 times on fd=%d", pid, fd2);
xsem_wait(fd2);
xsem_wait(fd2);
xsem_wait(fd2);
xsem_wait(fd2);
xsem_wait(fd2);
-}
-static void usage(char const *prg)
-{
- fprintf(stderr, "use: %s [-h]\n", prg);
+ tst_res(TPASS, "[%u] received all events", pid);
}
-int main(int argc, char **argv)
+static void run(void)
{
- int c, fd1, fd2, status;
pid_t cpid_poster, cpid_waiter;
+ int fd1, fd2;
- while ((c = getopt(argc, argv, "h")) != -1) {
- switch (c) {
- default:
- usage(argv[0]);
- return 1;
- }
- }
- if ((fd1 = eventfd2(0, EFD_SEMLIKE)) == -1 ||
- (fd2 = eventfd2(0, EFD_SEMLIKE)) == -1) {
- perror("eventfd2");
- return 1;
- }
- if ((cpid_poster = fork()) == 0) {
+ fd1 = eventfd2(0, EFD_SEMAPHORE);
+ fd2 = eventfd2(0, EFD_SEMAPHORE);
+
+ cpid_poster = SAFE_FORK();
+ if (!cpid_poster) {
sem_player(fd1, fd2);
exit(0);
}
- if ((cpid_waiter = fork()) == 0) {
+
+ cpid_waiter = SAFE_FORK();
+ if (!cpid_waiter) {
sem_player(fd2, fd1);
exit(0);
}
- waitpid(cpid_poster, &status, 0);
- waitpid(cpid_waiter, &status, 0);
-
- tst_exit();
}
+
+static struct tst_test test = {
+ .test_all = run,
+ .forks_child = 1,
+};
diff --git a/testcases/kernel/syscalls/execve/execve01.c b/testcases/kernel/syscalls/execve/execve01.c
index 2b12c7666..53f0475e3 100644
--- a/testcases/kernel/syscalls/execve/execve01.c
+++ b/testcases/kernel/syscalls/execve/execve01.c
@@ -34,7 +34,7 @@ static void verify_execve(void)
pid = SAFE_FORK();
if (pid == 0) {
execve(path, args, envp);
- tst_brk(TFAIL | TERRNO, "Failed to execute execl01_child");
+ tst_brk(TFAIL | TERRNO, "Failed to execute execve01_child");
}
}
diff --git a/testcases/kernel/syscalls/execve/execve06.c b/testcases/kernel/syscalls/execve/execve06.c
index afbfcfa9e..a00089265 100644
--- a/testcases/kernel/syscalls/execve/execve06.c
+++ b/testcases/kernel/syscalls/execve/execve06.c
@@ -35,7 +35,7 @@ static void verify_execve(void)
pid = SAFE_FORK();
if (pid == 0) {
execve(path, argv, envp);
- tst_brk(TFAIL | TERRNO, "Failed to execute execl01_child");
+ tst_brk(TFAIL | TERRNO, "Failed to execute execve06_child");
}
}
diff --git a/testcases/kernel/syscalls/faccessat/.gitignore b/testcases/kernel/syscalls/faccessat/.gitignore
index 9551ab97e..276caca45 100644
--- a/testcases/kernel/syscalls/faccessat/.gitignore
+++ b/testcases/kernel/syscalls/faccessat/.gitignore
@@ -1 +1,2 @@
/faccessat01
+/faccessat02
diff --git a/testcases/kernel/syscalls/faccessat/faccessat01.c b/testcases/kernel/syscalls/faccessat/faccessat01.c
index d11e8cf12..557d7eb4c 100644
--- a/testcases/kernel/syscalls/faccessat/faccessat01.c
+++ b/testcases/kernel/syscalls/faccessat/faccessat01.c
@@ -1,151 +1,88 @@
-/******************************************************************************
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) International Business Machines Corp., 2006
+ * Copyright (c) Linux Test Project, 2003-2023
+ * Author: Yi Yang <yyangcdl@cn.ibm.com>
+ */
+
+/*\
+ * [Description]
*
- * Copyright (c) International Business Machines Corp., 2006
+ * Check the basic functionality of the faccessat() system call.
*
- * 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.
+ * - faccessat() passes if dir_fd is file descriptor to the directory
+ * where the file is located and pathname is relative path of the file.
*
- * 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.
+ * - faccessat() passes if dir_fd is a bad file descriptor and pathname is
+ * absolute path of the file.
*
- * 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
- * faccessat01.c
- *
- * DESCRIPTION
- * This test case will verify basic function of faccessat
- * added by kernel 2.6.16 or up.
- *
- * Author
- * Yi Yang <yyangcdl@cn.ibm.com>
- *
- * History
- * 08/28/2006 Created first by Yi Yang <yyangcdl@cn.ibm.com>
- *
- *****************************************************************************/
-
-#define _GNU_SOURCE
+ * - faccessat() passes if dir_fd is AT_FDCWD and pathname is interpreted
+ * relative to the current working directory of the calling process.
+ */
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
#include <stdlib.h>
-#include <errno.h>
-#include <string.h>
-#include <signal.h>
-#include "test.h"
-#include "safe_macros.h"
-#include "lapi/syscalls.h"
-
-#define TEST_CASES 6
-#ifndef AT_FDCWD
-#define AT_FDCWD -100
-#endif
-void setup();
-void cleanup();
-
-char *TCID = "faccessat01";
-int TST_TOTAL = TEST_CASES;
-static char pathname[256];
-static char testfile[256];
-static char testfile2[256];
-static char testfile3[256];
-static int fds[TEST_CASES];
-static char *filenames[TEST_CASES];
-static int expected_errno[TEST_CASES] = { 0, 0, ENOTDIR, EBADF, 0, 0 };
-
-int myfaccessat(int dirfd, const char *filename, int mode)
+#include <stdio.h>
+#include "tst_test.h"
+
+#define TESTDIR "faccessatdir"
+#define TESTFILE "faccessatfile"
+#define FILEPATH "faccessatdir/faccessatfile"
+
+static int dir_fd, file_fd;
+static int atcwd_fd = AT_FDCWD;
+static char *abs_path;
+static char *test_file;
+static char *file_path;
+
+static struct tcase {
+ int *fd;
+ char **filename;
+ int exp_errno;
+} tcases[] = {
+ {&dir_fd, &test_file, 0},
+ {&dir_fd, &abs_path, 0},
+ {&atcwd_fd, &file_path, 0},
+};
+
+static void verify_faccessat(unsigned int i)
{
- return tst_syscall(__NR_faccessat, dirfd, filename, mode);
-}
-
-int main(int ac, char **av)
-{
- int lc;
- int i;
-
- tst_parse_opts(ac, av, NULL, NULL);
-
- setup();
+ struct tcase *tc = &tcases[i];
- for (lc = 0; TEST_LOOPING(lc); lc++) {
- tst_count = 0;
-
- /*
- * Call faccessat
- */
- for (i = 0; i < TST_TOTAL; i++) {
- TEST(myfaccessat(fds[i], filenames[i], R_OK));
-
- /* check return code */
- if (TEST_ERRNO == expected_errno[i]) {
- tst_resm(TPASS,
- "faccessat() returned the expected errno %d: %s",
- TEST_ERRNO,
- strerror(TEST_ERRNO));
- } else {
- tst_resm(TFAIL,
- "faccessdat() Failed, errno=%d : %s",
- TEST_ERRNO, strerror(TEST_ERRNO));
- }
- }
- }
-
- cleanup();
- tst_exit();
+ TST_EXP_PASS(faccessat(*tc->fd, *tc->filename, R_OK, 0),
+ "faccessat(%d, %s, R_OK, 0)",
+ *tc->fd, *tc->filename);
}
-void setup(void)
+static void setup(void)
{
- tst_sig(NOFORK, DEF_HANDLER, cleanup);
-
- tst_tmpdir();
-
- char *abs_path = tst_get_tmpdir();
- int p = getpid();
-
- /* Initialize test dir and file names */
- sprintf(pathname, "faccessattestdir%d", p);
- sprintf(testfile, "faccessattestfile%d.txt", p);
- sprintf(testfile2, "%s/faccessattestfile%d.txt", abs_path, p);
- sprintf(testfile3, "faccessattestdir%d/faccessattestfile%d.txt", p, p);
-
- free(abs_path);
+ char *tmpdir_path = tst_get_tmpdir();
- SAFE_MKDIR(cleanup, pathname, 0700);
+ abs_path = tst_aprintf("%s/%s", tmpdir_path, FILEPATH);
+ free(tmpdir_path);
- fds[0] = SAFE_OPEN(cleanup, pathname, O_DIRECTORY);
- fds[1] = fds[4] = fds[0];
-
- SAFE_FILE_PRINTF(cleanup, testfile, "%s", testfile);
- SAFE_FILE_PRINTF(cleanup, testfile2, "%s", testfile2);
-
- fds[2] = SAFE_OPEN(cleanup, testfile3, O_CREAT | O_RDWR, 0600);
-
- fds[3] = 100;
- fds[5] = AT_FDCWD;
-
- filenames[0] = filenames[2] = filenames[3] = filenames[4] = testfile;
- filenames[1] = testfile2;
- filenames[5] = testfile3;
-
- TEST_PAUSE;
+ SAFE_MKDIR(TESTDIR, 0700);
+ dir_fd = SAFE_OPEN(TESTDIR, O_DIRECTORY);
+ file_fd = SAFE_OPEN(FILEPATH, O_CREAT | O_RDWR, 0600);
}
-void cleanup(void)
+static void cleanup(void)
{
- if (fds[0] > 0)
- close(fds[0]);
- if (fds[2] > 0)
- close(fds[2]);
+ if (dir_fd > -1)
+ SAFE_CLOSE(dir_fd);
- tst_rmdir();
+ if (file_fd > -1)
+ SAFE_CLOSE(file_fd);
}
+
+static struct tst_test test = {
+ .test = verify_faccessat,
+ .tcnt = ARRAY_SIZE(tcases),
+ .setup = setup,
+ .cleanup = cleanup,
+ .bufs = (struct tst_buffers []) {
+ {&test_file, .str = TESTFILE},
+ {&file_path, .str = FILEPATH},
+ {},
+ },
+ .needs_tmpdir = 1,
+};
diff --git a/testcases/kernel/syscalls/faccessat/faccessat02.c b/testcases/kernel/syscalls/faccessat/faccessat02.c
new file mode 100644
index 000000000..1add695c1
--- /dev/null
+++ b/testcases/kernel/syscalls/faccessat/faccessat02.c
@@ -0,0 +1,67 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) International Business Machines Corp., 2006
+ * Copyright (c) Linux Test Project, 2003-2023
+ * Author: Yi Yang <yyangcdl@cn.ibm.com>
+ */
+
+/*\
+ * [Description]
+ *
+ * - faccessat() fails with ENOTDIR if dir_fd is file descriptor to the file
+ * and pathname is relative path of the file.
+ *
+ * - faccessat() fails with EBADF if dir_fd is invalid.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "tst_test.h"
+
+#define TESTDIR "faccessatdir"
+#define TESTFILE "faccessatfile"
+#define FILEPATH "faccessatdir/faccessatfile"
+
+static int dir_fd, file_fd;
+static int bad_fd = -1;
+
+static struct tcase {
+ int *fd;
+ int exp_errno;
+} tcases[] = {
+ {&file_fd, ENOTDIR},
+ {&bad_fd, EBADF},
+};
+
+static void verify_faccessat(unsigned int i)
+{
+ struct tcase *tc = &tcases[i];
+
+ TST_EXP_FAIL(faccessat(*tc->fd, TESTFILE, R_OK, 0),
+ tc->exp_errno, "faccessat(%d, TESTFILE, R_OK, 0)",
+ *tc->fd);
+}
+
+static void setup(void)
+{
+ SAFE_MKDIR(TESTDIR, 0700);
+ dir_fd = SAFE_OPEN(TESTDIR, O_DIRECTORY);
+ file_fd = SAFE_OPEN(FILEPATH, O_CREAT | O_RDWR, 0600);
+}
+
+static void cleanup(void)
+{
+ if (dir_fd > -1)
+ SAFE_CLOSE(dir_fd);
+
+ if (file_fd > -1)
+ SAFE_CLOSE(file_fd);
+}
+
+static struct tst_test test = {
+ .test = verify_faccessat,
+ .tcnt = ARRAY_SIZE(tcases),
+ .setup = setup,
+ .cleanup = cleanup,
+ .needs_tmpdir = 1,
+};
diff --git a/testcases/kernel/syscalls/faccessat2/.gitignore b/testcases/kernel/syscalls/faccessat2/.gitignore
new file mode 100644
index 000000000..f58f045f4
--- /dev/null
+++ b/testcases/kernel/syscalls/faccessat2/.gitignore
@@ -0,0 +1,2 @@
+/faccessat201
+/faccessat202
diff --git a/testcases/kernel/syscalls/faccessat2/Makefile b/testcases/kernel/syscalls/faccessat2/Makefile
new file mode 100644
index 000000000..aaac6b703
--- /dev/null
+++ b/testcases/kernel/syscalls/faccessat2/Makefile
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+# Copyright (c) 2023 FUJITSU LIMITED. All rights reserved.
+# Author: Yang Xu <xuyang2018.jy@fujitsu.com>
+
+top_srcdir ?= ../../../..
+
+include $(top_srcdir)/include/mk/testcases.mk
+
+include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/syscalls/faccessat2/faccessat201.c b/testcases/kernel/syscalls/faccessat2/faccessat201.c
new file mode 100644
index 000000000..012091752
--- /dev/null
+++ b/testcases/kernel/syscalls/faccessat2/faccessat201.c
@@ -0,0 +1,88 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2023 FUJITSU LIMITED. All rights reserved.
+ * Copyright (c) Linux Test Project, 2003-2023
+ * Author: Yang Xu <xuyang2018.jy@fujitsu.com>
+ */
+
+/*\
+ * [Description]
+ *
+ * Check the basic functionality of faccessat2().
+ *
+ * Minimum Linux version required is v5.8.
+ */
+
+#include <stdlib.h>
+
+#include "tst_test.h"
+#include "lapi/syscalls.h"
+#include "lapi/faccessat.h"
+
+#define TESTDIR "faccessat2dir"
+#define TESTFILE "faccessat2file"
+#define RELPATH "faccessat2dir/faccessat2file"
+#define TESTSYMLINK "faccessat2symlink"
+
+static int dir_fd, bad_fd = -1;
+static int atcwd_fd = AT_FDCWD;
+static char *testfile;
+static char *abs_path;
+static char *rel_path;
+static char *sym_path;
+
+static struct tcase {
+ int *fd;
+ char **filename;
+ int flags;
+} tcases[] = {
+ {&dir_fd, &testfile, 0},
+ {&bad_fd, &abs_path, 0},
+ {&atcwd_fd, &rel_path, 0},
+ {&dir_fd, &testfile, AT_EACCESS},
+ {&bad_fd, &abs_path, AT_EACCESS},
+ {&atcwd_fd, &rel_path, AT_EACCESS},
+ {&atcwd_fd, &sym_path, AT_SYMLINK_NOFOLLOW},
+};
+
+static void verify_faccessat2(unsigned int i)
+{
+ struct tcase *tc = &tcases[i];
+
+ TST_EXP_PASS(faccessat2(*tc->fd, *tc->filename, R_OK, tc->flags),
+ "faccessat2(%d, %s, R_OK, %d)",
+ *tc->fd, *tc->filename, tc->flags);
+}
+
+static void setup(void)
+{
+ char *tmpdir_path = tst_get_tmpdir();
+
+ abs_path = tst_aprintf("%s/%s", tmpdir_path, RELPATH);
+ free(tmpdir_path);
+
+ SAFE_MKDIR(TESTDIR, 0777);
+ dir_fd = SAFE_OPEN(TESTDIR, O_DIRECTORY);
+ SAFE_TOUCH(abs_path, 0444, NULL);
+ SAFE_SYMLINK(abs_path, TESTSYMLINK);
+}
+
+static void cleanup(void)
+{
+ if (dir_fd > -1)
+ SAFE_CLOSE(dir_fd);
+}
+
+static struct tst_test test = {
+ .test = verify_faccessat2,
+ .tcnt = ARRAY_SIZE(tcases),
+ .setup = setup,
+ .cleanup = cleanup,
+ .bufs = (struct tst_buffers []) {
+ {&testfile, .str = TESTFILE},
+ {&rel_path, .str = RELPATH},
+ {&sym_path, .str = TESTSYMLINK},
+ {},
+ },
+ .needs_tmpdir = 1,
+};
diff --git a/testcases/kernel/syscalls/faccessat2/faccessat202.c b/testcases/kernel/syscalls/faccessat2/faccessat202.c
new file mode 100644
index 000000000..a60db2bf8
--- /dev/null
+++ b/testcases/kernel/syscalls/faccessat2/faccessat202.c
@@ -0,0 +1,102 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2023 FUJITSU LIMITED. All rights reserved.
+ * Copyright (c) Linux Test Project, 2003-2023
+ * Author: Yang Xu <xuyang2018.jy@fujitsu.com>
+ */
+
+/*\
+ * [Description]
+ *
+ * Test basic error handling of faccessat2 syscall:
+ *
+ * - faccessat2() fails with EFAULT if pathname is a bad pathname point.
+ * - faccessat2() fails with EINVAL if flags is -1.
+ * - faccessat2() fails with EINVAL if mode is -1.
+ * - faccessat2() fails with EBADF if dirfd is -1.
+ * - faccessat2() fails with ENOTDIR if pathname is relative path to a
+ * file and dir_fd is file descriptor for this file.
+ * - faccessat2() fails with EACCES if flags is AT_EACCESS and not using
+ * the effective user and group IDs.
+ *
+ * Minimum Linux version required is v5.8.
+ */
+
+#include <pwd.h>
+
+#include "tst_test.h"
+#include "lapi/syscalls.h"
+#include "lapi/faccessat.h"
+
+#define TESTUSER "nobody"
+#define TESTDIR "faccessat2dir"
+#define RELPATH "faccessat2dir/faccessat2file"
+
+static int fd;
+static int bad_fd = -1;
+static int atcwd_fd = AT_FDCWD;
+static char *bad_path;
+static char *rel_path;
+
+static struct passwd *ltpuser;
+
+static struct tcase {
+ int *fd;
+ char **filename;
+ int mode;
+ int flags;
+ int exp_errno;
+ const char *desc;
+} tcases[] = {
+ {&atcwd_fd, &bad_path, R_OK, 0, EFAULT, "invalid address"},
+ {&atcwd_fd, &rel_path, R_OK, -1, EINVAL, "invalid flags"},
+ {&atcwd_fd, &rel_path, -1, 0, EINVAL, "invalid mode"},
+ {&bad_fd, &rel_path, R_OK, 0, EBADF, "invalid fd"},
+ {&fd, &rel_path, R_OK, 0, ENOTDIR, "fd pointing to file"},
+ {&atcwd_fd, &rel_path, R_OK, AT_EACCESS, EACCES,
+ "AT_EACCESS and unprivileged EUID"},
+};
+
+static void verify_faccessat2(unsigned int i)
+{
+ struct tcase *tc = &tcases[i];
+
+ if (tc->exp_errno == EACCES)
+ SAFE_SETEUID(ltpuser->pw_uid);
+
+ TST_EXP_FAIL(faccessat2(*tc->fd, *tc->filename, tc->mode, tc->flags),
+ tc->exp_errno, "faccessat2() with %s", tc->desc);
+
+ if (tc->exp_errno == EACCES)
+ SAFE_SETEUID(0);
+}
+
+static void setup(void)
+{
+ SAFE_MKDIR(TESTDIR, 0666);
+ SAFE_TOUCH(RELPATH, 0444, NULL);
+
+ fd = SAFE_OPEN(RELPATH, O_RDONLY);
+ bad_path = tst_get_bad_addr(NULL);
+
+ ltpuser = SAFE_GETPWNAM(TESTUSER);
+}
+
+static void cleanup(void)
+{
+ if (fd > -1)
+ SAFE_CLOSE(fd);
+}
+
+static struct tst_test test = {
+ .test = verify_faccessat2,
+ .tcnt = ARRAY_SIZE(tcases),
+ .setup = setup,
+ .cleanup = cleanup,
+ .bufs = (struct tst_buffers []) {
+ {&rel_path, .str = RELPATH},
+ {},
+ },
+ .needs_tmpdir = 1,
+ .needs_root = 1,
+};
diff --git a/testcases/kernel/syscalls/fanotify/fanotify.h b/testcases/kernel/syscalls/fanotify/fanotify.h
index 51078103e..75a081dc9 100644
--- a/testcases/kernel/syscalls/fanotify/fanotify.h
+++ b/testcases/kernel/syscalls/fanotify/fanotify.h
@@ -72,6 +72,10 @@ static inline int safe_fanotify_mark(const char *file, const int lineno,
#define MAX_HANDLE_SZ 128
#endif
+#ifndef AT_HANDLE_FID
+#define AT_HANDLE_FID 0x200
+#endif
+
/*
* Helper function used to obtain fsid and file_handle for a given path.
* Used by test files correlated to FAN_REPORT_FID functionality.
@@ -260,10 +264,27 @@ static inline int fanotify_mark_supported_by_kernel(uint64_t flag)
return rval;
}
+static inline int fanotify_handle_supported_by_kernel(int flag)
+{
+ /*
+ * On Kernel that does not support AT_HANDLE_FID this will result
+ * with EINVAL. On older kernels, this will result in EBADF.
+ */
+ if (name_to_handle_at(-1, "", NULL, NULL, AT_EMPTY_PATH | flag)) {
+ if (errno == EINVAL)
+ return -1;
+ }
+ return 0;
+}
+
#define REQUIRE_MARK_TYPE_SUPPORTED_BY_KERNEL(mark_type) \
fanotify_init_flags_err_msg(#mark_type, __FILE__, __LINE__, tst_brk_, \
fanotify_mark_supported_by_kernel(mark_type))
+#define REQUIRE_HANDLE_TYPE_SUPPORTED_BY_KERNEL(handle_type) \
+ fanotify_init_flags_err_msg(#handle_type, __FILE__, __LINE__, tst_brk_, \
+ fanotify_handle_supported_by_kernel(handle_type))
+
#define REQUIRE_FANOTIFY_EVENTS_SUPPORTED_ON_FS(init_flags, mark_type, mask, fname) do { \
if (mark_type) \
REQUIRE_MARK_TYPE_SUPPORTED_BY_KERNEL(mark_type); \
diff --git a/testcases/kernel/syscalls/fanotify/fanotify13.c b/testcases/kernel/syscalls/fanotify/fanotify13.c
index c3daaf3a2..a25a360fd 100644
--- a/testcases/kernel/syscalls/fanotify/fanotify13.c
+++ b/testcases/kernel/syscalls/fanotify/fanotify13.c
@@ -25,6 +25,7 @@
#include <sys/statfs.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/mount.h>
#include <errno.h>
#include <unistd.h>
#include "tst_test.h"
@@ -37,7 +38,7 @@
#define DIR_ONE "dir_one"
#define FILE_ONE "file_one"
#define FILE_TWO "file_two"
-#define MOUNT_PATH "mntpoint"
+#define MOUNT_PATH "tstmnt"
#define EVENT_MAX ARRAY_SIZE(objects)
#define DIR_PATH_ONE MOUNT_PATH"/"DIR_ONE
#define FILE_PATH_ONE MOUNT_PATH"/"FILE_ONE
@@ -88,6 +89,8 @@ static struct test_case_t {
}
};
+static int ovl_mounted;
+static int bind_mounted;
static int nofid_fd;
static int fanotify_fd;
static int filesystem_mark_unsupported;
@@ -143,8 +146,13 @@ static void do_test(unsigned int number)
struct fanotify_mark_type *mark = &tc->mark;
tst_res(TINFO,
- "Test #%d: FAN_REPORT_FID with mark flag: %s",
- number, mark->name);
+ "Test #%d.%d: FAN_REPORT_FID with mark flag: %s",
+ number, tst_variant, mark->name);
+
+ if (tst_variant && !ovl_mounted) {
+ tst_res(TCONF, "overlayfs not supported on %s", tst_device->fs_type);
+ return;
+ }
if (filesystem_mark_unsupported && mark->flag & FAN_MARK_FILESYSTEM) {
tst_res(TCONF, "FAN_MARK_FILESYSTEM not supported in kernel?");
@@ -160,6 +168,15 @@ static void do_test(unsigned int number)
if (setup_marks(fanotify_fd, tc) != 0)
goto out;
+ /* Variant #1: watching upper fs - open files on overlayfs */
+ if (tst_variant == 1) {
+ if (mark->flag & FAN_MARK_MOUNT) {
+ tst_res(TCONF, "overlayfs upper fs cannot be watched with mount mark");
+ goto out;
+ }
+ SAFE_MOUNT(OVL_MNT, MOUNT_PATH, "none", MS_BIND, NULL);
+ }
+
/* Generate sequence of FAN_OPEN events on objects */
for (i = 0; i < ARRAY_SIZE(objects); i++)
fds[i] = SAFE_OPEN(objects[i].path, O_RDONLY);
@@ -174,6 +191,9 @@ static void do_test(unsigned int number)
SAFE_CLOSE(fds[i]);
}
+ if (tst_variant == 1)
+ SAFE_UMOUNT(MOUNT_PATH);
+
/* Read events from event queue */
len = SAFE_READ(0, fanotify_fd, events_buf, BUF_SIZE);
@@ -261,7 +281,32 @@ out:
static void do_setup(void)
{
- REQUIRE_FANOTIFY_INIT_FLAGS_SUPPORTED_ON_FS(FAN_REPORT_FID, MOUNT_PATH);
+ const char *mnt;
+
+ /*
+ * Bind mount to either base fs or to overlayfs over base fs:
+ * Variant #0: watch base fs - open files on base fs
+ * Variant #1: watch upper fs - open files on overlayfs
+ *
+ * Variant #1 tests a bug whose fix bc2473c90fca ("ovl: enable fsnotify
+ * events on underlying real files") in kernel 6.5 is not likely to be
+ * backported to older kernels.
+ * To avoid waiting for events that won't arrive when testing old kernels,
+ * require that kernel supports encoding fid with new flag AT_HADNLE_FID,
+ * also merged to 6.5 and not likely to be backported to older kernels.
+ */
+ if (tst_variant) {
+ REQUIRE_HANDLE_TYPE_SUPPORTED_BY_KERNEL(AT_HANDLE_FID);
+ ovl_mounted = TST_MOUNT_OVERLAY();
+ mnt = OVL_UPPER;
+ } else {
+ mnt = OVL_BASE_MNTPOINT;
+
+ }
+ REQUIRE_FANOTIFY_INIT_FLAGS_SUPPORTED_ON_FS(FAN_REPORT_FID, mnt);
+ SAFE_MKDIR(MOUNT_PATH, 0755);
+ SAFE_MOUNT(mnt, MOUNT_PATH, "none", MS_BIND, NULL);
+ bind_mounted = 1;
filesystem_mark_unsupported = fanotify_mark_supported_by_kernel(FAN_MARK_FILESYSTEM);
@@ -287,19 +332,27 @@ static void do_cleanup(void)
SAFE_CLOSE(nofid_fd);
if (fanotify_fd > 0)
SAFE_CLOSE(fanotify_fd);
+ if (bind_mounted) {
+ SAFE_UMOUNT(MOUNT_PATH);
+ SAFE_RMDIR(MOUNT_PATH);
+ }
+ if (ovl_mounted)
+ SAFE_UMOUNT(OVL_MNT);
}
static struct tst_test test = {
.test = do_test,
.tcnt = ARRAY_SIZE(test_cases),
+ .test_variants = 2,
.setup = do_setup,
.cleanup = do_cleanup,
.needs_root = 1,
.mount_device = 1,
- .mntpoint = MOUNT_PATH,
+ .mntpoint = OVL_BASE_MNTPOINT,
.all_filesystems = 1,
.tags = (const struct tst_tag[]) {
{"linux-git", "c285a2f01d69"},
+ {"linux-git", "bc2473c90fca"},
{}
}
};
diff --git a/testcases/kernel/syscalls/fanotify/fanotify14.c b/testcases/kernel/syscalls/fanotify/fanotify14.c
index bfa0349fe..4596511f0 100644
--- a/testcases/kernel/syscalls/fanotify/fanotify14.c
+++ b/testcases/kernel/syscalls/fanotify/fanotify14.c
@@ -19,6 +19,9 @@
*
* ceaf69f8eadc fanotify: do not allow setting dirent events in mask of non-dir
* 8698e3bab4dd fanotify: refine the validation checks on non-dir inode mask
+ *
+ * The pipes test cases are regression tests for commit:
+ * 69562eb0bd3e fanotify: disallow mount/sb marks on kernel internal pseudo fs
*/
#define _GNU_SOURCE
@@ -40,6 +43,7 @@
#define FLAGS_DESC(flags) {(flags), (#flags)}
+static int pipes[2] = {-1, -1};
static int fanotify_fd;
static int fan_report_target_fid_unsupported;
static int ignore_mark_unsupported;
@@ -60,94 +64,179 @@ static struct test_case_t {
/* when mask.flags == 0, fanotify_init() is expected to fail */
struct test_case_flags_t mask;
int expected_errno;
+ int *pfd;
} test_cases[] = {
/* FAN_REPORT_FID without class FAN_CLASS_NOTIF is not valid */
- {FLAGS_DESC(FAN_CLASS_CONTENT | FAN_REPORT_FID), {}, {}, EINVAL},
+ {
+ .init = FLAGS_DESC(FAN_CLASS_CONTENT | FAN_REPORT_FID),
+ .expected_errno = EINVAL,
+ },
/* FAN_REPORT_FID without class FAN_CLASS_NOTIF is not valid */
- {FLAGS_DESC(FAN_CLASS_PRE_CONTENT | FAN_REPORT_FID), {}, {}, EINVAL},
+ {
+ .init = FLAGS_DESC(FAN_CLASS_PRE_CONTENT | FAN_REPORT_FID),
+ .expected_errno = EINVAL,
+ },
/* INODE_EVENTS in mask without class FAN_REPORT_FID are not valid */
- {FLAGS_DESC(FAN_CLASS_NOTIF), FLAGS_DESC(0), FLAGS_DESC(INODE_EVENTS),
- EINVAL},
+ {
+ .init = FLAGS_DESC(FAN_CLASS_NOTIF),
+ .mark = FLAGS_DESC(FAN_MARK_INODE),
+ .mask = FLAGS_DESC(INODE_EVENTS),
+ .expected_errno = EINVAL,
+ },
/* INODE_EVENTS in mask with FAN_MARK_MOUNT are not valid */
- {FLAGS_DESC(FAN_CLASS_NOTIF | FAN_REPORT_FID),
- FLAGS_DESC(FAN_MARK_MOUNT), FLAGS_DESC(INODE_EVENTS), EINVAL},
+ {
+ .init = FLAGS_DESC(FAN_CLASS_NOTIF | FAN_REPORT_FID),
+ .mark = FLAGS_DESC(FAN_MARK_MOUNT),
+ .mask = FLAGS_DESC(INODE_EVENTS),
+ .expected_errno = EINVAL,
+ },
/* FAN_REPORT_NAME without FAN_REPORT_DIR_FID is not valid */
- {FLAGS_DESC(FAN_CLASS_NOTIF | FAN_REPORT_NAME), {}, {}, EINVAL},
+ {
+ .init = FLAGS_DESC(FAN_CLASS_NOTIF | FAN_REPORT_NAME),
+ .expected_errno = EINVAL,
+ },
/* FAN_REPORT_NAME without FAN_REPORT_DIR_FID is not valid */
- {FLAGS_DESC(FAN_CLASS_NOTIF | FAN_REPORT_FID | FAN_REPORT_NAME), {},
- {}, EINVAL},
+ {
+ .init = FLAGS_DESC(FAN_CLASS_NOTIF | FAN_REPORT_FID | FAN_REPORT_NAME),
+ .expected_errno = EINVAL,
+ },
/* FAN_REPORT_TARGET_FID without FAN_REPORT_FID is not valid */
- {FLAGS_DESC(FAN_CLASS_NOTIF | FAN_REPORT_TARGET_FID | FAN_REPORT_DFID_NAME),
- {}, {}, EINVAL},
+ {
+ .init = FLAGS_DESC(FAN_CLASS_NOTIF | FAN_REPORT_TARGET_FID | FAN_REPORT_DFID_NAME),
+ .expected_errno = EINVAL,
+ },
/* FAN_REPORT_TARGET_FID without FAN_REPORT_NAME is not valid */
- {FLAGS_DESC(FAN_CLASS_NOTIF | FAN_REPORT_TARGET_FID | FAN_REPORT_DFID_FID),
- {}, {}, EINVAL},
+ {
+ .init = FLAGS_DESC(FAN_CLASS_NOTIF | FAN_REPORT_TARGET_FID | FAN_REPORT_DFID_FID),
+ .expected_errno = EINVAL,
+ },
/* FAN_RENAME without FAN_REPORT_NAME is not valid */
- {FLAGS_DESC(FAN_CLASS_NOTIF | FAN_REPORT_DFID_FID), FLAGS_DESC(0),
- FLAGS_DESC(FAN_RENAME), EINVAL},
+ {
+ .init = FLAGS_DESC(FAN_CLASS_NOTIF | FAN_REPORT_DFID_FID),
+ .mark = FLAGS_DESC(FAN_MARK_INODE),
+ .mask = FLAGS_DESC(FAN_RENAME),
+ .expected_errno = EINVAL,
+ },
/* With FAN_MARK_ONLYDIR on non-dir is not valid */
- {FLAGS_DESC(FAN_CLASS_NOTIF), FLAGS_DESC(FAN_MARK_ONLYDIR),
- FLAGS_DESC(FAN_OPEN), ENOTDIR},
+ {
+ .init = FLAGS_DESC(FAN_CLASS_NOTIF),
+ .mark = FLAGS_DESC(FAN_MARK_ONLYDIR),
+ .mask = FLAGS_DESC(FAN_OPEN),
+ .expected_errno = ENOTDIR,
+ },
/* With FAN_REPORT_TARGET_FID, FAN_DELETE on non-dir is not valid */
- {FLAGS_DESC(FAN_CLASS_NOTIF | FAN_REPORT_DFID_NAME_TARGET),
- FLAGS_DESC(0), FLAGS_DESC(FAN_DELETE), ENOTDIR},
+ {
+ .init = FLAGS_DESC(FAN_CLASS_NOTIF | FAN_REPORT_DFID_NAME_TARGET),
+ .mark = FLAGS_DESC(FAN_MARK_INODE),
+ .mask = FLAGS_DESC(FAN_DELETE),
+ .expected_errno = ENOTDIR,
+ },
/* With FAN_REPORT_TARGET_FID, FAN_RENAME on non-dir is not valid */
- {FLAGS_DESC(FAN_CLASS_NOTIF | FAN_REPORT_DFID_NAME_TARGET),
- FLAGS_DESC(0), FLAGS_DESC(FAN_RENAME), ENOTDIR},
+ {
+ .init = FLAGS_DESC(FAN_CLASS_NOTIF | FAN_REPORT_DFID_NAME_TARGET),
+ .mark = FLAGS_DESC(FAN_MARK_INODE),
+ .mask = FLAGS_DESC(FAN_RENAME),
+ .expected_errno = ENOTDIR,
+ },
/* With FAN_REPORT_TARGET_FID, FAN_ONDIR on non-dir is not valid */
- {FLAGS_DESC(FAN_CLASS_NOTIF | FAN_REPORT_DFID_NAME_TARGET),
- FLAGS_DESC(0), FLAGS_DESC(FAN_OPEN | FAN_ONDIR), ENOTDIR},
+ {
+ .init = FLAGS_DESC(FAN_CLASS_NOTIF | FAN_REPORT_DFID_NAME_TARGET),
+ .mark = FLAGS_DESC(FAN_MARK_INODE),
+ .mask = FLAGS_DESC(FAN_OPEN | FAN_ONDIR),
+ .expected_errno = ENOTDIR,
+ },
/* With FAN_REPORT_TARGET_FID, FAN_EVENT_ON_CHILD on non-dir is not valid */
- {FLAGS_DESC(FAN_CLASS_NOTIF | FAN_REPORT_DFID_NAME_TARGET),
- FLAGS_DESC(0), FLAGS_DESC(FAN_OPEN | FAN_EVENT_ON_CHILD),
- ENOTDIR},
+ {
+ .init = FLAGS_DESC(FAN_CLASS_NOTIF | FAN_REPORT_DFID_NAME_TARGET),
+ .mark = FLAGS_DESC(FAN_MARK_INODE),
+ .mask = FLAGS_DESC(FAN_OPEN | FAN_EVENT_ON_CHILD),
+ .expected_errno = ENOTDIR,
+ },
/* FAN_MARK_IGNORE_SURV with FAN_DELETE on non-dir is not valid */
- {FLAGS_DESC(FAN_CLASS_NOTIF | FAN_REPORT_DFID_NAME),
- FLAGS_DESC(FAN_MARK_IGNORE_SURV), FLAGS_DESC(FAN_DELETE),
- ENOTDIR},
+ {
+ .init = FLAGS_DESC(FAN_CLASS_NOTIF | FAN_REPORT_DFID_NAME),
+ .mark = FLAGS_DESC(FAN_MARK_IGNORE_SURV),
+ .mask = FLAGS_DESC(FAN_DELETE),
+ .expected_errno = ENOTDIR,
+ },
/* FAN_MARK_IGNORE_SURV with FAN_RENAME on non-dir is not valid */
- {FLAGS_DESC(FAN_CLASS_NOTIF | FAN_REPORT_DFID_NAME),
- FLAGS_DESC(FAN_MARK_IGNORE_SURV), FLAGS_DESC(FAN_RENAME),
- ENOTDIR},
+ {
+ .init = FLAGS_DESC(FAN_CLASS_NOTIF | FAN_REPORT_DFID_NAME),
+ .mark = FLAGS_DESC(FAN_MARK_IGNORE_SURV),
+ .mask = FLAGS_DESC(FAN_RENAME),
+ .expected_errno = ENOTDIR,
+ },
/* FAN_MARK_IGNORE_SURV with FAN_ONDIR on non-dir is not valid */
- {FLAGS_DESC(FAN_CLASS_NOTIF | FAN_REPORT_DFID_NAME),
- FLAGS_DESC(FAN_MARK_IGNORE_SURV),
- FLAGS_DESC(FAN_OPEN | FAN_ONDIR), ENOTDIR},
+ {
+ .init = FLAGS_DESC(FAN_CLASS_NOTIF | FAN_REPORT_DFID_NAME),
+ .mark = FLAGS_DESC(FAN_MARK_IGNORE_SURV),
+ .mask = FLAGS_DESC(FAN_OPEN | FAN_ONDIR),
+ .expected_errno = ENOTDIR,
+ },
/* FAN_MARK_IGNORE_SURV with FAN_EVENT_ON_CHILD on non-dir is not valid */
- {FLAGS_DESC(FAN_CLASS_NOTIF | FAN_REPORT_DFID_NAME),
- FLAGS_DESC(FAN_MARK_IGNORE_SURV),
- FLAGS_DESC(FAN_OPEN | FAN_EVENT_ON_CHILD), ENOTDIR},
+ {
+ .init = FLAGS_DESC(FAN_CLASS_NOTIF | FAN_REPORT_DFID_NAME),
+ .mark = FLAGS_DESC(FAN_MARK_IGNORE_SURV),
+ .mask = FLAGS_DESC(FAN_OPEN | FAN_EVENT_ON_CHILD),
+ .expected_errno = ENOTDIR,
+ },
/* FAN_MARK_IGNORE without FAN_MARK_IGNORED_SURV_MODIFY on directory is not valid */
- {FLAGS_DESC(FAN_CLASS_NOTIF), FLAGS_DESC(FAN_MARK_IGNORE),
- FLAGS_DESC(FAN_OPEN), EISDIR},
+ {
+ .init = FLAGS_DESC(FAN_CLASS_NOTIF),
+ .mark = FLAGS_DESC(FAN_MARK_IGNORE),
+ .mask = FLAGS_DESC(FAN_OPEN),
+ .expected_errno = EISDIR,
+ },
/* FAN_MARK_IGNORE without FAN_MARK_IGNORED_SURV_MODIFY on mount mark is not valid */
- {FLAGS_DESC(FAN_CLASS_NOTIF),
- FLAGS_DESC(FAN_MARK_MOUNT | FAN_MARK_IGNORE),
- FLAGS_DESC(FAN_OPEN), EINVAL},
+ {
+ .init = FLAGS_DESC(FAN_CLASS_NOTIF),
+ .mark = FLAGS_DESC(FAN_MARK_MOUNT | FAN_MARK_IGNORE),
+ .mask = FLAGS_DESC(FAN_OPEN),
+ .expected_errno = EINVAL,
+ },
/* FAN_MARK_IGNORE without FAN_MARK_IGNORED_SURV_MODIFY on filesystem mark is not valid */
- {FLAGS_DESC(FAN_CLASS_NOTIF),
- FLAGS_DESC(FAN_MARK_FILESYSTEM | FAN_MARK_IGNORE),
- FLAGS_DESC(FAN_OPEN), EINVAL},
+ {
+ .init = FLAGS_DESC(FAN_CLASS_NOTIF),
+ .mark = FLAGS_DESC(FAN_MARK_FILESYSTEM | FAN_MARK_IGNORE),
+ .mask = FLAGS_DESC(FAN_OPEN),
+ .expected_errno = EINVAL,
+ },
+ /* mount mark on anonymous pipe is not valid */
+ {
+ .init = FLAGS_DESC(FAN_CLASS_NOTIF),
+ .mark = FLAGS_DESC(FAN_MARK_MOUNT),
+ .mask = { FAN_ACCESS, "anonymous pipe"},
+ .pfd = pipes,
+ .expected_errno = EINVAL,
+ },
+ /* filesystem mark on anonymous pipe is not valid */
+ {
+ .init = FLAGS_DESC(FAN_CLASS_NOTIF),
+ .mark = FLAGS_DESC(FAN_MARK_FILESYSTEM),
+ .mask = { FAN_ACCESS, "anonymous pipe"},
+ .pfd = pipes,
+ .expected_errno = EINVAL,
+ },
};
static void do_test(unsigned int number)
@@ -185,11 +274,17 @@ static void do_test(unsigned int number)
/* Set mark on non-dir only when expecting error ENOTDIR */
const char *path = tc->expected_errno == ENOTDIR ? FILE1 : MNTPOINT;
+ int dirfd = AT_FDCWD;
+
+ if (tc->pfd) {
+ dirfd = tc->pfd[0];
+ path = NULL;
+ }
- tst_res(TINFO, "Testing fanotify_mark(FAN_MARK_ADD | %s, %s)",
+ tst_res(TINFO, "Testing %s with %s",
tc->mark.desc, tc->mask.desc);
TST_EXP_FD_OR_FAIL(fanotify_mark(fanotify_fd, FAN_MARK_ADD | tc->mark.flags,
- tc->mask.flags, AT_FDCWD, path),
+ tc->mask.flags, dirfd, path),
tc->expected_errno);
/*
@@ -231,12 +326,18 @@ static void do_setup(void)
/* Create temporary test file to place marks on */
SAFE_FILE_PRINTF(FILE1, "0");
+ /* Create anonymous pipes to place marks on */
+ SAFE_PIPE2(pipes, O_CLOEXEC);
}
static void do_cleanup(void)
{
if (fanotify_fd > 0)
SAFE_CLOSE(fanotify_fd);
+ if (pipes[0] != -1)
+ SAFE_CLOSE(pipes[0]);
+ if (pipes[1] != -1)
+ SAFE_CLOSE(pipes[1]);
}
static struct tst_test test = {
@@ -251,6 +352,7 @@ static struct tst_test test = {
.tags = (const struct tst_tag[]) {
{"linux-git", "ceaf69f8eadc"},
{"linux-git", "8698e3bab4dd"},
+ {"linux-git", "69562eb0bd3e"},
{}
}
};
diff --git a/testcases/kernel/syscalls/fanotify/fanotify22.c b/testcases/kernel/syscalls/fanotify/fanotify22.c
index 6596a69c9..a654e8912 100644
--- a/testcases/kernel/syscalls/fanotify/fanotify22.c
+++ b/testcases/kernel/syscalls/fanotify/fanotify22.c
@@ -41,6 +41,7 @@
#define MOUNT_PATH "test_mnt"
#define BASE_DIR "internal_dir"
#define BAD_DIR BASE_DIR"/bad_dir"
+#define BAD_LINK BASE_DIR"/bad_link"
#ifdef HAVE_NAME_TO_HANDLE_AT
@@ -50,6 +51,7 @@ static int fd_notify;
/* These expected FIDs are common to multiple tests */
static struct fanotify_fid_t null_fid;
static struct fanotify_fid_t bad_file_fid;
+static struct fanotify_fid_t bad_link_fid;
static void trigger_fs_abort(void)
{
@@ -64,7 +66,7 @@ static void do_debugfs_request(const char *dev, char *request)
SAFE_CMD(cmd, NULL, NULL);
}
-static void tcase2_trigger_lookup(void)
+static void trigger_bad_file_lookup(void)
{
int ret;
@@ -75,15 +77,27 @@ static void tcase2_trigger_lookup(void)
ret, BAD_DIR, errno, EUCLEAN);
}
+static void trigger_bad_link_lookup(void)
+{
+ int ret;
+
+ /* SAFE_OPEN cannot be used here because we expect it to fail. */
+ ret = open(MOUNT_PATH"/"BAD_LINK, O_RDONLY, 0);
+ if (ret != -1 && errno != EUCLEAN)
+ tst_res(TFAIL, "Unexpected open result(%d) of %s (%d!=%d)",
+ ret, BAD_LINK, errno, EUCLEAN);
+}
+
+
static void tcase3_trigger(void)
{
- trigger_fs_abort();
- tcase2_trigger_lookup();
+ trigger_bad_link_lookup();
+ trigger_bad_file_lookup();
}
static void tcase4_trigger(void)
{
- tcase2_trigger_lookup();
+ trigger_bad_file_lookup();
trigger_fs_abort();
}
@@ -103,7 +117,7 @@ static struct test_case {
},
{
.name = "Lookup of inode with invalid mode",
- .trigger_error = &tcase2_trigger_lookup,
+ .trigger_error = &trigger_bad_file_lookup,
.error_count = 1,
.error = EFSCORRUPTED,
.fid = &bad_file_fid,
@@ -112,8 +126,8 @@ static struct test_case {
.name = "Multiple error submission",
.trigger_error = &tcase3_trigger,
.error_count = 2,
- .error = ESHUTDOWN,
- .fid = &null_fid,
+ .error = EFSCORRUPTED,
+ .fid = &bad_link_fid,
},
{
.name = "Multiple error submission 2",
@@ -247,6 +261,9 @@ static void do_test(unsigned int i)
FAN_FS_ERROR, AT_FDCWD, MOUNT_PATH);
check_event(event_buf, read_len, tcase);
+ /* Unmount and mount the filesystem to get it out of the error state */
+ SAFE_UMOUNT(MOUNT_PATH);
+ SAFE_MOUNT(tst_device->dev, MOUNT_PATH, tst_device->fs_type, 0, NULL);
}
static void pre_corrupt_fs(void)
@@ -255,9 +272,11 @@ static void pre_corrupt_fs(void)
SAFE_MKDIR(MOUNT_PATH"/"BAD_DIR, 0777);
fanotify_save_fid(MOUNT_PATH"/"BAD_DIR, &bad_file_fid);
+ fanotify_save_fid(MOUNT_PATH"/"BASE_DIR, &bad_link_fid);
SAFE_UMOUNT(MOUNT_PATH);
do_debugfs_request(tst_device->dev, "sif " BAD_DIR " mode 0xff");
+ do_debugfs_request(tst_device->dev, "ln <1> " BAD_LINK);
SAFE_MOUNT(tst_device->dev, MOUNT_PATH, tst_device->fs_type, 0, NULL);
}
diff --git a/testcases/kernel/syscalls/fanotify/fanotify23.c b/testcases/kernel/syscalls/fanotify/fanotify23.c
index 89fd4f36a..fb812c51e 100644
--- a/testcases/kernel/syscalls/fanotify/fanotify23.c
+++ b/testcases/kernel/syscalls/fanotify/fanotify23.c
@@ -160,10 +160,16 @@ static void test_fanotify(void)
}
/*
- * drop_caches should evict inode from cache and remove evictable mark
+ * drop_caches should evict inode from cache and remove evictable mark.
+ * We call drop_caches twice as once the dentries will just cycle
+ * through the LRU without being reclaimed and if there are no other
+ * objects to reclaim, the slab reclaim will just stop instead of
+ * retrying. Note that this relies on how reclaim of fs objects work
+ * for the filesystem but this test is restricted to ext2...
*/
fsync_file(TEST_FILE);
SAFE_FILE_PRINTF(DROP_CACHES_FILE, "3");
+ SAFE_FILE_PRINTF(DROP_CACHES_FILE, "3");
verify_mark_removed(TEST_FILE, "after drop_caches");
diff --git a/testcases/kernel/syscalls/fchmod/fchmod02.c b/testcases/kernel/syscalls/fchmod/fchmod02.c
index e60cb33a6..d6abeffce 100644
--- a/testcases/kernel/syscalls/fchmod/fchmod02.c
+++ b/testcases/kernel/syscalls/fchmod/fchmod02.c
@@ -1,18 +1,18 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) International Business Machines Corp., 2001
+ */
+
+/*\
+ * [Description]
*
- * Test Description:
- * Verify that, fchmod() will succeed to change the mode of a file/directory
- * set the sticky bit on it if invoked by root (uid = 0) process with
- * the following constraints,
- * - the process is not the owner of the file/directory.
- * - the effective group ID or one of the supplementary group ID's of the
- * process is equal to the group ID of the file/directory.
+ * Verify that, fchmod(2) will succeed to change the mode of a file/directory
+ * set the sticky bit on it if invoked by root (uid = 0) process with
+ * the following constraints:
*
- * Expected Result:
- * fchmod() should return value 0 on success and succeeds to set sticky bit
- * on the specified file.
+ * - the process is not the owner of the file/directory
+ * - the effective group ID or one of the supplementary group ID's of the
+ * process is equal to the group ID of the file/directory
*/
#include <pwd.h>
diff --git a/testcases/kernel/syscalls/fchmod/fchmod03.c b/testcases/kernel/syscalls/fchmod/fchmod03.c
index 12a6f5a93..bdd720c37 100644
--- a/testcases/kernel/syscalls/fchmod/fchmod03.c
+++ b/testcases/kernel/syscalls/fchmod/fchmod03.c
@@ -8,10 +8,11 @@
*
* Verify that, fchmod(2) will succeed to change the mode of a file
* and set the sticky bit on it if invoked by non-root (uid != 0)
- * process with the following constraints,
- * - the process is the owner of the file.
- * - the effective group ID or one of the supplementary group ID's of the
- * process is equal to the group ID of the file.
+ * process with the following constraints:
+ *
+ * - the process is the owner of the file
+ * - the effective group ID or one of the supplementary group ID's of the
+ * process is equal to the group ID of the file
*/
#include <pwd.h>
diff --git a/testcases/kernel/syscalls/fchmod/fchmod04.c b/testcases/kernel/syscalls/fchmod/fchmod04.c
index d60cb39b2..4fa69e227 100644
--- a/testcases/kernel/syscalls/fchmod/fchmod04.c
+++ b/testcases/kernel/syscalls/fchmod/fchmod04.c
@@ -8,10 +8,11 @@
*
* Verify that, fchmod(2) will succeed to change the mode of a directory
* and set the sticky bit on it if invoked by non-root (uid != 0) process
- * with the following constraints,
- * - the process is the owner of the directory.
- * - the effective group ID or one of the supplementary group ID's of the
- * process is equal to the group ID of the directory.
+ * with the following constraints:
+ *
+ * - the process is the owner of the directory
+ * - the effective group ID or one of the supplementary group ID's of the
+ * process is equal to the group ID of the directory
*/
#include <pwd.h>
diff --git a/testcases/kernel/syscalls/fchown/fchown02.c b/testcases/kernel/syscalls/fchown/fchown02.c
index d02f5bc92..bd1baf3bb 100644
--- a/testcases/kernel/syscalls/fchown/fchown02.c
+++ b/testcases/kernel/syscalls/fchown/fchown02.c
@@ -10,6 +10,7 @@
* [Description]
*
* Verify that fchown(2) invoked by super-user:
+ *
* - clears setuid and setgid bits set on an executable file
* - preserves setgid bit set on a non-group-executable file
*/
diff --git a/testcases/kernel/syscalls/fcntl/.gitignore b/testcases/kernel/syscalls/fcntl/.gitignore
index 48b36ec34..10cb0995f 100644
--- a/testcases/kernel/syscalls/fcntl/.gitignore
+++ b/testcases/kernel/syscalls/fcntl/.gitignore
@@ -8,8 +8,6 @@
/fcntl04_64
/fcntl05
/fcntl05_64
-/fcntl06
-/fcntl06_64
/fcntl07
/fcntl07_64
/fcntl08
diff --git a/testcases/kernel/syscalls/fcntl/fcntl06.c b/testcases/kernel/syscalls/fcntl/fcntl06.c
deleted file mode 100644
index 8dcc04866..000000000
--- a/testcases/kernel/syscalls/fcntl/fcntl06.c
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- *
- * 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
- * fcntl06.c
- *
- * DESCRIPTION
- * Error checking conditions for remote locking of regions of a file.
- *
- * CALLS
- * open(2), write(2), fcntl(2)
- *
- * ALGORITHM
- * Test unlocking sections around a write lock using remote Lock/Unlock
- * call which should all fail.
- *
- * USAGE
- * fcntl06
- *
- * HISTORY
- * 07/2001 Ported by Wayne Boyer
- *
- * RESTRICTIONS
- * Currently Linux kernel doesn't implement R_GETLK/R_SETLK facility,
- * but this facility seems to be present in other standard flavours of
- * Unix. Currently this program has all the testing done under
- * "#ifdef LINUX_FILE_REGION_LOCK", when Linux implements the regions
- * locking then, this testcase should be recompiled accordingly with the
- * "ifdef" removed.
- */
-
-#include <fcntl.h>
-#include <errno.h>
-#include <signal.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include "test.h"
-
-#define F_RGETLK 10 /* kludge code */
-#define F_RSETLK 11 /* kludge code */
-
-char *TCID = "fcntl06";
-int TST_TOTAL = 1;
-
-void setup();
-void cleanup();
-
-#define STRINGSIZE 27
-#define STRING "abcdefghijklmnopqrstuvwxyz\n"
-
-int fd;
-void unlock_file();
-int do_lock(int, short, short, int, int);
-
-int main(int ac, char **av)
-{
- int fail = 0;
-
- tst_parse_opts(ac, av, NULL, NULL);
-
- setup(); /* global setup */
-
- fail = 0;
-
-#ifdef LINUX_FILE_REGION_LOCK
- if (fcntl(fd, F_RGETLK, &tl) == -1) {
- if (errno == EINVAL)
- tst_brkm(TCONF, cleanup,
- "fcntl remote locking feature not implemented in "
- "the kernel");
- else {
- /*
- * FIXME (garrcoop): having it always pass on
- * non-EINVAL is a bad test.
- */
- tst_resm(TPASS, "fcntl on file failed");
- }
- }
-
- /*
- * Add a write lock to the middle of the file and unlock a section
- * just before the lock
- */
- if (do_lock(F_RSETLK, F_WRLCK, 0, 10, 5) == -1)
- tst_resm(TFAIL, "F_RSETLK WRLCK failed");
-
- if (do_lock(F_RSETLK, F_UNLCK, 0, 5, 5) == -1)
- tst_resm(TFAIL | TERRNO, "F_RSETLK UNLOCK failed");
-
- unlock_file();
-#else
- tst_resm(TCONF, "system doesn't have LINUX_LOCK_FILE_REGION support");
-#endif
-
- cleanup();
- tst_exit();
-}
-
-void setup(void)
-{
- char *buf = STRING;
- char template[PATH_MAX];
-
- tst_sig(FORK, DEF_HANDLER, cleanup);
-
- umask(0);
-
- TEST_PAUSE;
-
- tst_tmpdir();
-
- snprintf(template, PATH_MAX, "fcntl06XXXXXX");
-
- if ((fd = mkstemp(template)) == -1)
- tst_resm(TBROK | TERRNO, "mkstemp failed");
-
- if (write(fd, buf, STRINGSIZE) == -1)
- tst_resm(TBROK | TERRNO, "write failed");
-}
-
-int do_lock(int cmd, short type, short whence, int start, int len)
-{
- struct flock fl;
-
- fl.l_type = type;
- fl.l_whence = whence;
- fl.l_start = start;
- fl.l_len = len;
- return (fcntl(fd, cmd, &fl));
-}
-
-void unlock_file(void)
-{
- if (do_lock(F_RSETLK, (short)F_UNLCK, (short)0, 0, 0) == -1) {
- /* Same as FIXME comment above. */
- tst_resm(TPASS | TERRNO, "fcntl on file failed");
- }
-}
-
-void cleanup(void)
-{
-
- if (close(fd) == -1)
- tst_resm(TWARN | TERRNO, "close failed");
-
- tst_rmdir();
-
-}
diff --git a/testcases/kernel/syscalls/fcntl/fcntl11.c b/testcases/kernel/syscalls/fcntl/fcntl11.c
index b66fa8421..d042c6b9b 100644
--- a/testcases/kernel/syscalls/fcntl/fcntl11.c
+++ b/testcases/kernel/syscalls/fcntl/fcntl11.c
@@ -189,11 +189,11 @@ char *str_type(int type)
static char buf[20];
switch (type) {
- case 0:
+ case F_RDLCK:
return ("F_RDLCK");
- case 1:
+ case F_WRLCK:
return ("F_WRLCK");
- case 2:
+ case F_UNLCK:
return ("F_UNLCK");
default:
sprintf(buf, "BAD VALUE: %d", type);
diff --git a/testcases/kernel/syscalls/fcntl/fcntl19.c b/testcases/kernel/syscalls/fcntl/fcntl19.c
index 88c91d6ea..f929aff99 100644
--- a/testcases/kernel/syscalls/fcntl/fcntl19.c
+++ b/testcases/kernel/syscalls/fcntl/fcntl19.c
@@ -215,11 +215,11 @@ char *str_type(int type)
static char buf[20];
switch (type) {
- case 1:
+ case F_RDLCK:
return ("F_RDLCK");
- case 2:
+ case F_WRLCK:
return ("F_WRLCK");
- case 3:
+ case F_UNLCK:
return ("F_UNLCK");
default:
sprintf(buf, "BAD VALUE: %d", type);
diff --git a/testcases/kernel/syscalls/fcntl/fcntl20.c b/testcases/kernel/syscalls/fcntl/fcntl20.c
index b671af8a9..4aa773451 100644
--- a/testcases/kernel/syscalls/fcntl/fcntl20.c
+++ b/testcases/kernel/syscalls/fcntl/fcntl20.c
@@ -214,11 +214,11 @@ char *str_type(int type)
static char buf[20];
switch (type) {
- case 1:
+ case F_RDLCK:
return ("F_RDLCK");
- case 2:
+ case F_WRLCK:
return ("F_WRLCK");
- case 3:
+ case F_UNLCK:
return ("F_UNLCK");
default:
sprintf(buf, "BAD VALUE: %d", type);
diff --git a/testcases/kernel/syscalls/fcntl/fcntl21.c b/testcases/kernel/syscalls/fcntl/fcntl21.c
index 8f1a67cf6..824b8c059 100644
--- a/testcases/kernel/syscalls/fcntl/fcntl21.c
+++ b/testcases/kernel/syscalls/fcntl/fcntl21.c
@@ -222,11 +222,11 @@ char *str_type(int type)
static char buf[20];
switch (type) {
- case 1:
+ case F_RDLCK:
return ("F_RDLCK");
- case 2:
+ case F_WRLCK:
return ("F_WRLCK");
- case 3:
+ case F_UNLCK:
return ("F_UNLCK");
default:
sprintf(buf, "BAD VALUE: %d", type);
diff --git a/testcases/kernel/syscalls/fcntl/fcntl30.c b/testcases/kernel/syscalls/fcntl/fcntl30.c
index c4c3f81f1..64bbb9e3a 100644
--- a/testcases/kernel/syscalls/fcntl/fcntl30.c
+++ b/testcases/kernel/syscalls/fcntl/fcntl30.c
@@ -1,103 +1,54 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2014 Fujitsu Ltd.
* Author: Xiaoguang Wang <wangxg.fnst@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; if not, write the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ * Copyright (c) 2023 SUSE LLC Avinesh Kumar <avinesh.kumar@suse.com>
*/
-/*
- * Description:
- * Verify that,
- * Basic test for fcntl(2) using F_SETPIPE_SZ, F_GETPIPE_SZ argument.
+/*\
+ * [Description]
+ *
+ * Verify that, fetching and changing the capacity of a pipe works as
+ * expected with fcntl(2) syscall using F_GETPIPE_SZ, F_SETPIPE_SZ arguments.
*/
-
-#include <stdio.h>
-#include <errno.h>
-#include <unistd.h>
-#include <string.h>
-#include <signal.h>
-#include <sys/types.h>
-#include <pwd.h>
-
-#include "test.h"
-#include "safe_macros.h"
+#include "tst_test.h"
#include "lapi/fcntl.h"
-char *TCID = "fcntl30";
-int TST_TOTAL = 1;
-
-static void setup(void);
-static void cleanup(void);
+static int fds[2];
+static int max_size_unpriv;
-int main(int ac, char **av)
+static void run(void)
{
- int lc;
- int pipe_fds[2], test_fd;
- int orig_pipe_size, new_pipe_size;
+ SAFE_PIPE(fds);
+ TST_EXP_POSITIVE(fcntl(fds[1], F_GETPIPE_SZ));
- tst_parse_opts(ac, av, NULL, NULL);
+ TST_EXP_POSITIVE(fcntl(fds[1], F_SETPIPE_SZ, max_size_unpriv));
+ TST_EXP_POSITIVE(fcntl(fds[1], F_GETPIPE_SZ));
+ TST_EXP_EXPR(TST_RET >= max_size_unpriv,
+ "new pipe size (%ld) >= requested size (%d)",
+ TST_RET, max_size_unpriv);
- setup();
-
- for (lc = 0; TEST_LOOPING(lc); lc++) {
- tst_count = 0;
-
- SAFE_PIPE(cleanup, pipe_fds);
- test_fd = pipe_fds[1];
-
- TEST(fcntl(test_fd, F_GETPIPE_SZ));
- if (TEST_RETURN < 0) {
- tst_brkm(TFAIL | TTERRNO, cleanup,
- "fcntl get pipe size failed");
- }
-
- orig_pipe_size = TEST_RETURN;
- new_pipe_size = orig_pipe_size * 2;
- TEST(fcntl(test_fd, F_SETPIPE_SZ, new_pipe_size));
- if (TEST_RETURN < 0) {
- tst_brkm(TFAIL | TTERRNO, cleanup,
- "fcntl test F_SETPIPE_SZ failed");
- }
-
- TEST(fcntl(test_fd, F_GETPIPE_SZ));
- if (TEST_RETURN < 0) {
- tst_brkm(TFAIL | TTERRNO, cleanup,
- "fcntl test F_GETPIPE_SZ failed");
- }
- tst_resm(TINFO, "orig_pipe_size: %d new_pipe_size: %d",
- orig_pipe_size, new_pipe_size);
- if (TEST_RETURN >= new_pipe_size) {
- tst_resm(TPASS, "fcntl test F_GETPIPE_SZ and F_SETPIPE_SZ passed");
- } else {
- tst_resm(TFAIL, "fcntl test F_GETPIPE_SZ and F_SETPIPE_SZ failed");
- }
- SAFE_CLOSE(cleanup, pipe_fds[0]);
- SAFE_CLOSE(cleanup, pipe_fds[1]);
- }
-
- cleanup();
- tst_exit();
+ SAFE_CLOSE(fds[0]);
+ SAFE_CLOSE(fds[1]);
}
static void setup(void)
{
- tst_sig(NOFORK, DEF_HANDLER, cleanup);
-
- TEST_PAUSE;
+ SAFE_FILE_SCANF("/proc/sys/fs/pipe-max-size", "%d", &max_size_unpriv);
}
static void cleanup(void)
{
+ if (fds[0] > 0)
+ SAFE_CLOSE(fds[0]);
+ if (fds[1] > 0)
+ SAFE_CLOSE(fds[1]);
}
+
+static struct tst_test test = {
+ .test_all = run,
+ .setup = setup,
+ .cleanup = cleanup
+};
diff --git a/testcases/kernel/syscalls/fcntl/fcntl33.c b/testcases/kernel/syscalls/fcntl/fcntl33.c
index 8d0d1a5a1..3c6a38b81 100644
--- a/testcases/kernel/syscalls/fcntl/fcntl33.c
+++ b/testcases/kernel/syscalls/fcntl/fcntl33.c
@@ -209,7 +209,7 @@ static void cleanup(void)
SAFE_CLOSE(fd);
/* Restore the lease-break-time. */
- FILE_PRINTF(PATH_LS_BRK_T, "%d", ls_brk_t);
+ SAFE_FILE_PRINTF(PATH_LS_BRK_T, "%d", ls_brk_t);
}
static struct tst_test test = {
diff --git a/testcases/kernel/syscalls/finit_module/finit_module01.c b/testcases/kernel/syscalls/finit_module/finit_module01.c
index f960b2e40..1929c30fa 100644
--- a/testcases/kernel/syscalls/finit_module/finit_module01.c
+++ b/testcases/kernel/syscalls/finit_module/finit_module01.c
@@ -49,6 +49,7 @@ static struct tst_test test = {
.setup = setup,
.cleanup = cleanup,
.needs_root = 1,
- /* lockdown requires signed modules */
+ /* lockdown and SecureBoot requires signed modules */
.skip_in_lockdown = 1,
+ .skip_in_secureboot = 1,
};
diff --git a/testcases/kernel/syscalls/finit_module/finit_module02.c b/testcases/kernel/syscalls/finit_module/finit_module02.c
index a7434de7d..223d9b388 100644
--- a/testcases/kernel/syscalls/finit_module/finit_module02.c
+++ b/testcases/kernel/syscalls/finit_module/finit_module02.c
@@ -25,7 +25,7 @@
static char *mod_path;
static int fd, fd_zero, fd_invalid = -1, fd_dir;
-static int kernel_lockdown;
+static int kernel_lockdown, secure_boot;
static struct tst_cap cap_req = TST_CAP(TST_CAP_REQ, CAP_SYS_MODULE);
static struct tst_cap cap_drop = TST_CAP(TST_CAP_DROP, CAP_SYS_MODULE);
@@ -83,7 +83,9 @@ static void setup(void)
tst_module_exists(MODULE_NAME, &mod_path);
- kernel_lockdown = tst_lockdown_enabled();
+ kernel_lockdown = tst_lockdown_enabled() > 0;
+ secure_boot = tst_secureboot_enabled() > 0;
+
SAFE_MKDIR(TEST_DIR, 0700);
fd_dir = SAFE_OPEN(TEST_DIR, O_DIRECTORY);
@@ -102,8 +104,8 @@ static void run(unsigned int n)
{
struct tcase *tc = &tcases[n];
- if (tc->skip_in_lockdown && kernel_lockdown) {
- tst_res(TCONF, "Kernel is locked down, skipping %s", tc->name);
+ if (tc->skip_in_lockdown && (kernel_lockdown || secure_boot)) {
+ tst_res(TCONF, "Cannot load unsigned modules, skipping %s", tc->name);
return;
}
diff --git a/testcases/kernel/syscalls/flistxattr/flistxattr01.c b/testcases/kernel/syscalls/flistxattr/flistxattr01.c
index 98a6fa254..68c3948b7 100644
--- a/testcases/kernel/syscalls/flistxattr/flistxattr01.c
+++ b/testcases/kernel/syscalls/flistxattr/flistxattr01.c
@@ -47,7 +47,7 @@ static int has_attribute(const char *list, int llen, const char *attr)
static void verify_flistxattr(void)
{
- char buf[64];
+ char buf[128];
TEST(flistxattr(fd, buf, sizeof(buf)));
if (TST_RET == -1) {
diff --git a/testcases/kernel/syscalls/fork/fork03.c b/testcases/kernel/syscalls/fork/fork03.c
index 25b36c897..c6381dd67 100644
--- a/testcases/kernel/syscalls/fork/fork03.c
+++ b/testcases/kernel/syscalls/fork/fork03.c
@@ -1,119 +1,59 @@
+// 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
+ * Copyright (c) Linux Test Project, 2003-2023
+ * Author: 2001 Ported by Wayne Boyer
*/
-/*
- * NAME
- * fork03.c
- *
- * DESCRIPTION
- * Check that child can use a large text space and do a large
- * number of operations.
- *
- * ALGORITHM
- * Fork one process, check for pid == 0 in child.
- * Check for pid > 0 in parent after wait.
+/*\
+ *[Description]
*
- * USAGE
- * fork03
- *
- * HISTORY
- * 07/2001 Ported by Wayne Boyer
- *
- * RESTRICTIONS
- * None
+ * Check that child process can use a large text space and do a large number
+ * of operations. In this situation, check for pid == 0 in child and check
+ * for pid > 0 in parent after wait.
*/
-#include <sys/types.h>
+#include <unistd.h>
#include <sys/wait.h>
-#include <stdio.h>
-#include "test.h"
-
-char *TCID = "fork03";
-int TST_TOTAL = 1;
+#include <stdlib.h>
+#include "tst_test.h"
-static void setup(void);
-static void cleanup(void);
-
-int main(int ac, char **av)
+static void verify_fork(void)
{
float fl1, fl2;
- int i;
- int pid1, pid2, status;
-
- int lc;
-
- tst_parse_opts(ac, av, NULL, NULL);
-
- setup();
-
- for (lc = 0; TEST_LOOPING(lc); lc++) {
- tst_count = 0;
- pid1 = fork();
- if (pid1 == -1)
- tst_brkm(TBROK, cleanup, "fork() failed");
-
- if (pid1 == 0) {
- /* child uses some cpu cycles */
- for (i = 1; i < 32767; i++) {
- fl1 = 0.000001;
- fl1 = fl2 = 0.000001;
- fl1 = fl1 * 10.0;
- fl2 = fl1 / 1.232323;
- fl1 = fl2 - fl2;
- fl1 = fl2;
- }
-
- /* Pid must always be zero in child */
- if (pid1 != 0)
- exit(1);
- else
- exit(0);
- } else {
- tst_resm(TINFO, "process id in parent of child from "
- "fork : %d", pid1);
- pid2 = wait(&status); /* wait for child */
-
- if (pid1 != pid2) {
- tst_resm(TFAIL, "pids don't match : %d vs %d",
- pid1, pid2);
- continue;
- }
+ int pid1, pid2, status, i;
+
+ pid1 = SAFE_FORK();
+ if (!pid1) {
+ /* child uses some cpu time slices */
+ for (i = 1; i < 32767; i++) {
+ fl1 = 0.000001;
+ fl1 = fl2 = 0.000001;
+ fl1 = fl1 * 10.0;
+ fl2 = fl1 / 1.232323;
+ fl1 = fl2 - fl2;
+ fl1 = fl2;
+ }
+ exit(!!pid1);
+ }
- if ((status >> 8) != 0) {
- tst_resm(TFAIL, "child exited with failure");
- continue;
- }
+ tst_res(TINFO, "process id in parent of child from fork: %d", pid1);
+ pid2 = SAFE_WAIT(&status);
- tst_resm(TPASS, "test 1 PASSED");
- }
+ if (pid1 != pid2) {
+ tst_res(TFAIL, "pids don't match: %d vs %d", pid1, pid2);
+ return;
}
- cleanup();
- tst_exit();
-}
+ if ((status >> 8) != 0) {
+ tst_res(TFAIL, "child exited with failure");
+ return;
+ }
-static void setup(void)
-{
- tst_sig(FORK, DEF_HANDLER, cleanup);
- TEST_PAUSE;
+ tst_res(TPASS, "test PASSED");
}
-static void cleanup(void)
-{
-}
+static struct tst_test test = {
+ .test_all = verify_fork,
+ .forks_child = 1,
+};
diff --git a/testcases/kernel/syscalls/fsconfig/.gitignore b/testcases/kernel/syscalls/fsconfig/.gitignore
index 2bc54b827..cfedae5f7 100644
--- a/testcases/kernel/syscalls/fsconfig/.gitignore
+++ b/testcases/kernel/syscalls/fsconfig/.gitignore
@@ -1,2 +1,3 @@
/fsconfig01
/fsconfig02
+/fsconfig03
diff --git a/testcases/kernel/syscalls/fsconfig/fsconfig03.c b/testcases/kernel/syscalls/fsconfig/fsconfig03.c
new file mode 100644
index 000000000..0ba5355d3
--- /dev/null
+++ b/testcases/kernel/syscalls/fsconfig/fsconfig03.c
@@ -0,0 +1,97 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2022 Alejandro Guerrero <aguerrero@qualys.com>
+ * Copyright (c) 2023 Wei Gao <wegao@suse.com>
+ */
+
+/*\
+ * [Description]
+ *
+ * Test for CVE-2022-0185.
+ *
+ * References links:
+ *
+ * - https://www.openwall.com/lists/oss-security/2022/01/25/14
+ * - https://github.com/Crusaders-of-Rust/CVE-2022-0185
+ *
+ */
+
+#include "tst_test.h"
+#include "lapi/fsmount.h"
+
+#define MNTPOINT "mntpoint"
+
+static int fd = -1;
+
+static void setup(void)
+{
+ fsopen_supported_by_kernel();
+}
+
+static void run(void)
+{
+ char *val = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
+ long pagesize;
+
+ TEST(fd = fsopen(tst_device->fs_type, 0));
+ if (fd == -1)
+ tst_brk(TBROK | TTERRNO, "fsopen() failed");
+
+ pagesize = sysconf(_SC_PAGESIZE);
+ if (pagesize == -1)
+ tst_brk(TBROK, "sysconf(_SC_PAGESIZE) failed");
+
+ for (size_t i = 0; i < 5000; i++) {
+ /* use same logic in kernel legacy_parse_param function */
+ const size_t len = i * (strlen(val) + 2) + (strlen(val) + 1) + 2;
+
+ TEST(fsconfig(fd, FSCONFIG_SET_STRING, "\x00", val, 0));
+
+ /* Legacy fsconfig() just copies arguments to buffer */
+ if (!TST_RET && len <= (size_t)pagesize)
+ continue;
+
+ if (!TST_RET) {
+ tst_res(TFAIL, "fsconfig() passed unexpectedly");
+ } else if (TST_RET != -1) {
+ tst_brk(TBROK | TTERRNO,
+ "Invalid fsconfig() return value %ld", TST_RET);
+ } else if (TST_ERR != EINVAL) {
+ tst_res(TFAIL | TTERRNO,
+ "fsconfig() failed with unexpected error");
+ }
+ }
+
+ if (fd != -1)
+ SAFE_CLOSE(fd);
+
+ if (tst_taint_check())
+ tst_res(TFAIL, "kernel has issues on %s",
+ tst_device->fs_type);
+ else
+ tst_res(TPASS, "kernel seems to be fine on %s",
+ tst_device->fs_type);
+}
+
+static void cleanup(void)
+{
+ if (fd >= 0)
+ SAFE_CLOSE(fd);
+}
+
+static struct tst_test test = {
+ .test_all = run,
+ .setup = setup,
+ .cleanup = cleanup,
+ .needs_root = 1,
+ .format_device = 1,
+ .mntpoint = MNTPOINT,
+ .all_filesystems = 1,
+ .taint_check = TST_TAINT_W | TST_TAINT_D,
+ .skip_filesystems = (const char *const []){"fuse", NULL},
+ .tags = (const struct tst_tag[]) {
+ {"linux-git", "722d94847de29"},
+ {"CVE", "2022-0185"},
+ {}
+ }
+};
diff --git a/testcases/kernel/syscalls/futex/Makefile b/testcases/kernel/syscalls/futex/Makefile
index 7228496bc..1d05cf115 100644
--- a/testcases/kernel/syscalls/futex/Makefile
+++ b/testcases/kernel/syscalls/futex/Makefile
@@ -9,6 +9,9 @@ futex_wait02: LDLIBS+=-lrt
futex_wake03: LDLIBS+=-lrt
futex_wait05: LDLIBS+=-lrt
futex_wait_bitset01: LDLIBS+=-lrt
+futex_waitv01: LDLIBS+=-lrt
+futex_waitv02: LDLIBS+=-lrt
+futex_waitv03: LDLIBS+=-lrt
futex_wait03: CFLAGS+=-pthread
futex_wake02: CFLAGS+=-pthread
diff --git a/testcases/kernel/syscalls/futex/futex_wake04.c b/testcases/kernel/syscalls/futex/futex_wake04.c
index 176dd4aeb..03d90591b 100644
--- a/testcases/kernel/syscalls/futex/futex_wake04.c
+++ b/testcases/kernel/syscalls/futex/futex_wake04.c
@@ -21,7 +21,6 @@
*/
#include <stdio.h>
-#include <sys/mman.h>
#include <fcntl.h>
#include <sys/time.h>
#include <string.h>
diff --git a/testcases/kernel/syscalls/getcpu/getcpu01.c b/testcases/kernel/syscalls/getcpu/getcpu01.c
index f6fcc4fc1..9842c8999 100644
--- a/testcases/kernel/syscalls/getcpu/getcpu01.c
+++ b/testcases/kernel/syscalls/getcpu/getcpu01.c
@@ -69,6 +69,7 @@ static unsigned int get_nodeid(unsigned int cpu_id)
DIR *directory_parent, *directory_node;
struct dirent *de, *dn;
char directory_path[PATH_MAX];
+ char *invalid_number;
unsigned int cpu;
int node_id = 0;
@@ -91,7 +92,9 @@ static unsigned int get_nodeid(unsigned int cpu_id)
while ((dn = readdir(directory_node)) != NULL) {
if (strncmp(dn->d_name, "cpu", 3))
continue;
- cpu = strtoul(dn->d_name + 3, NULL, 0);
+ cpu = strtoul(dn->d_name + 3, &invalid_number, 0);
+ if (strcmp(invalid_number, "\0"))
+ continue;
if (cpu == cpu_id) {
node_id =
strtoul(de->d_name + 4, NULL, 0);
diff --git a/testcases/kernel/syscalls/geteuid/geteuid01.c b/testcases/kernel/syscalls/geteuid/geteuid01.c
index d02fb0a8d..66fb8936c 100644
--- a/testcases/kernel/syscalls/geteuid/geteuid01.c
+++ b/testcases/kernel/syscalls/geteuid/geteuid01.c
@@ -1,87 +1,26 @@
+//SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) Linux Test Project, 2003-2023
*
- * 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.
- *
- * Further, this software is distributed without any warranty that it is
- * free of the rightful claim of any third person regarding infringement
- * or the like. Any license provided herein, whether implied or
- * otherwise, applies only to this software file. Patent licenses, if
- * any, provided herein do not apply to combinations of this program with
- * other software, or any other product whatsoever.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
- * Mountain View, CA 94043, or:
- *
- * http://www.sgi.com
- *
- * For further information regarding this notice, see:
- *
- * http://oss.sgi.com/projects/GenInfo/NoticeExplan/
- *
+ * Author: William Roske
+ * CO-PILOT: Dave Fenner
*/
-/*
- * AUTHOR : William Roske
- * CO-PILOT : Dave Fenner
+/*\
+ *[Description]
+ *
+ * Check the basic functionality of the geteuid() system call.
*/
-#include <sys/types.h>
-#include <errno.h>
-#include <string.h>
-#include <signal.h>
-
-#include "test.h"
-#include "compat_16.h"
-
-static void setup(void);
-static void cleanup(void);
-
-TCID_DEFINE(geteuid01);
-int TST_TOTAL = 1;
+#include "tst_test.h"
+#include "compat_tst_16.h"
-int main(int ac, char **av)
+static void verify_geteuid(void)
{
- int lc;
-
- tst_parse_opts(ac, av, NULL, NULL);
-
- setup();
-
- for (lc = 0; TEST_LOOPING(lc); lc++) {
-
- tst_count = 0;
-
- TEST(GETEUID(cleanup));
-
- if (TEST_RETURN < 0) {
- tst_resm(TFAIL | TTERRNO, "geteuid failed");
- continue; /* next loop for MTKERNEL */
- }
-
- tst_resm(TPASS, "geteuid returned %ld", TEST_RETURN);
- }
-
- cleanup();
- tst_exit();
-}
-
-static void setup(void)
-{
- tst_sig(NOFORK, DEF_HANDLER, cleanup);
- TEST_PAUSE;
+ TST_EXP_POSITIVE(GETEUID(), "geteuid()");
}
-static void cleanup(void)
-{
-}
+static struct tst_test test = {
+ .test_all = verify_geteuid,
+};
diff --git a/testcases/kernel/syscalls/geteuid/geteuid02.c b/testcases/kernel/syscalls/geteuid/geteuid02.c
index e00f81296..eb2272bff 100644
--- a/testcases/kernel/syscalls/geteuid/geteuid02.c
+++ b/testcases/kernel/syscalls/geteuid/geteuid02.c
@@ -1,79 +1,36 @@
+//SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) International Business Machines Corp., 2001
- * Ported by Wayne Boyer
- *
- * 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) Linux Test Project, 2003-2023
+ * Ported by Wayne Boyer
*/
-#include <pwd.h>
-#include <errno.h>
-
-#include "test.h"
-#include "compat_16.h"
-
-TCID_DEFINE(geteuid02);
-int TST_TOTAL = 1;
+/*\
+ *[Description]
+ *
+ * Check that geteuid() return value matches value from /proc/self/status.
+ */
-static void setup(void);
-static void cleanup(void);
+#include "tst_test.h"
+#include "compat_tst_16.h"
-int main(int ac, char **av)
+static void verify_geteuid(void)
{
- struct passwd *pwent;
- int lc;
- uid_t uid;
-
- tst_parse_opts(ac, av, NULL, NULL);
-
- setup();
+ long uid[4];
- for (lc = 0; TEST_LOOPING(lc); lc++) {
- tst_count = 0;
+ TST_EXP_POSITIVE(GETEUID(), "geteuid()");
- TEST(GETEUID(cleanup));
+ if (!TST_PASS)
+ return;
- if (TEST_RETURN == -1)
- tst_brkm(TBROK | TTERRNO, cleanup, "geteuid* failed");
+ SAFE_FILE_LINES_SCANF("/proc/self/status", "Uid: %ld %ld %ld %ld",
+ &uid[0], &uid[1], &uid[2], &uid[3]);
- uid = geteuid();
- pwent = getpwuid(uid);
-
- if (pwent == NULL)
- tst_resm(TFAIL | TERRNO, "getpwuid failed");
-
- UID16_CHECK(pwent->pw_uid, geteuid, cleanup);
- if (pwent->pw_uid != TEST_RETURN)
- tst_resm(TFAIL, "getpwuid value, %d, "
- "does not match geteuid "
- "value, %ld", pwent->pw_uid,
- TEST_RETURN);
- else
- tst_resm(TPASS, "values from geteuid "
- "and getpwuid match");
- }
-
- cleanup();
- tst_exit();
-}
-
-static void setup(void)
-{
- tst_sig(NOFORK, DEF_HANDLER, cleanup);
- TEST_PAUSE;
+ TST_EXP_EXPR(TST_RET == uid[1],
+ "geteuid() ret %ld == /proc/self/status EUID: %ld",
+ TST_RET, uid[1]);
}
-static void cleanup(void)
-{
-}
+static struct tst_test test = {
+ .test_all = verify_geteuid,
+};
diff --git a/testcases/kernel/syscalls/getgroups/getgroups01.c b/testcases/kernel/syscalls/getgroups/getgroups01.c
index dc3074b75..cfddeb408 100644
--- a/testcases/kernel/syscalls/getgroups/getgroups01.c
+++ b/testcases/kernel/syscalls/getgroups/getgroups01.c
@@ -95,7 +95,7 @@ int main(int ac, char **av)
/*
* Check that if ngrps is zero that the number of groups is
- * return and the the gidset array is not modified.
+ * return and the gidset array is not modified.
* This is a POSIX special case.
*/
memset(gidset, 052, NGROUPS * sizeof(GID_T));
diff --git a/testcases/kernel/syscalls/gethostname/gethostname01.c b/testcases/kernel/syscalls/gethostname/gethostname01.c
index a7cb5417f..f2276a38c 100644
--- a/testcases/kernel/syscalls/gethostname/gethostname01.c
+++ b/testcases/kernel/syscalls/gethostname/gethostname01.c
@@ -1,161 +1,25 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
- *
- * 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.
- *
- * Further, this software is distributed without any warranty that it is
- * free of the rightful claim of any third person regarding infringement
- * or the like. Any license provided herein, whether implied or
- * otherwise, applies only to this software file. Patent licenses, if
- * any, provided herein do not apply to combinations of this program with
- * other software, or any other product whatsoever.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
- * Mountain View, CA 94043, or:
- *
- * http://www.sgi.com
- *
- * For further information regarding this notice, see:
- *
- * http://oss.sgi.com/projects/GenInfo/NoticeExplan/
- *
+ * Copyright (c) 2023 SUSE LLC Ioannis Bonatakis <ybonatakis@suse.com>
*/
-/* $Id: gethostname01.c,v 1.6 2009/10/26 14:55:47 subrata_modak Exp $ */
-/**********************************************************
- *
- * OS Test - Silicon Graphics, Inc.
- *
- * TEST IDENTIFIER : gethostname01
- *
- * EXECUTED BY : anyone
- *
- * TEST TITLE : Basic test for gethostname(2)
- *
- * PARENT DOCUMENT : usctpl01
- *
- * TEST CASE TOTAL : 1
- *
- * WALL CLOCK TIME : 1
- *
- * CPU TYPES : ALL
- *
- * AUTHOR : William Roske
- *
- * CO-PILOT : Dave Fenner
- *
- * DATE STARTED : 03/30/92
- *
- * INITIAL RELEASE : UNICOS 7.0
- *
- * TEST CASES
- *
- * 1.) gethostname(2) returns...(See Description)
- *
- * INPUT SPECIFICATIONS
- * The standard options for system call tests are accepted.
- * (See the parse_opts(3) man page).
- *
- * DURATION
- * Terminates - with frequency and infinite modes.
- *
- * SIGNALS
- * Uses SIGUSR1 to pause before test if option set.
- * (See the parse_opts(3) man page).
- *
- * RESOURCES
- * None
- *
- * ENVIRONMENTAL NEEDS
- * No run-time environmental needs.
- *
- * SPECIAL PROCEDURAL REQUIREMENTS
- * None
- *
- * INTERCASE DEPENDENCIES
- * None
- *
- * DETAILED DESCRIPTION
- * This is a Phase I test for the gethostname(2) system call. It is intended
- * to provide a limited exposure of the system call, for now. It
- * should/will be extended when full functional tests are written for
- * gethostname(2).
- *
- * Setup:
- * Setup signal handling.
- * Pause for SIGUSR1 if option specified.
- *
- * Test:
- * Loop if the proper options are given.
- * Execute system call
- * Check return code, if system call failed (return=-1)
- * Log the errno and Issue a FAIL message.
- * Otherwise, Issue a PASS message.
- *
- * Cleanup:
- * Print errno log and/or timing stats if options given
- *
- *
- *#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#**/
-
-#include <errno.h>
-#include <signal.h>
-#include <string.h>
-
-#include "test.h"
-
-void setup();
-void cleanup();
-
-char *TCID = "gethostname01";
-int TST_TOTAL = 1;
-
-int main(int ac, char **av)
-{
- int lc;
- char hname[100]; /* host name */
-
- tst_parse_opts(ac, av, NULL, NULL);
-
- setup();
-
- for (lc = 0; TEST_LOOPING(lc); lc++) {
-
- tst_count = 0;
-
- TEST(gethostname(hname, sizeof(hname)));
-
- if (TEST_RETURN == -1) {
- tst_resm(TFAIL | TTERRNO, "gethostname failed");
- continue; /* next loop for MTKERNEL */
- }
-
- tst_resm(TPASS, "gethostname returned %ld",
- TEST_RETURN);
- }
+/*\
+ * [Description]
+ *
+ * Test is checking that gethostname() succeeds.
+ */
- cleanup();
- tst_exit();
-}
+#include "tst_test.h"
+#include <stdlib.h>
-void setup(void)
+static void run(void)
{
+ char hname[100];
- tst_sig(NOFORK, DEF_HANDLER, cleanup);
-
- TEST_PAUSE;
+ TST_EXP_PASS(gethostname(hname, sizeof(hname)));
}
-void cleanup(void)
-{
-}
+static struct tst_test test = {
+ .test_all = run
+};
diff --git a/testcases/kernel/syscalls/getpgid/getpgid01.c b/testcases/kernel/syscalls/getpgid/getpgid01.c
index 060486e7e..4c614e0b9 100644
--- a/testcases/kernel/syscalls/getpgid/getpgid01.c
+++ b/testcases/kernel/syscalls/getpgid/getpgid01.c
@@ -1,145 +1,57 @@
+// 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) 2023 SUSE LLC Avinesh Kumar <avinesh.kumar@suse.com>
*/
-/*
- * NAME
- * getpgid01.c
- *
- * DESCRIPTION
- * Testcase to check the basic functionality of getpgid().
- *
- * ALGORITHM
- * block1: Does getpgid(0), and checks for error.
- * block2: Does getpgid(getpid()) and checks for error.
- * block3: Does getpgid(getppid()) and checks for error.
- * block4: Verifies that getpgid(getpgid(0)) == getpgid(0).
- * block5: Does getpgid(1) and checks for error.
+/*\
+ * [Description]
*
- * USAGE
- * getpgid01
- *
- * HISTORY
- * 07/2001 Ported by Wayne Boyer
- *
- * RESTRICTIONS
- * Expects that there are no EPERM limitations on getting the
- * process group ID from proc 1 (init).
+ * Verify the basic functionality of getpgid(2) syscall.
*/
-#define _GNU_SOURCE 1
-
-#include <errno.h>
-#include <unistd.h>
-#include <stdarg.h>
-#include <sys/wait.h>
-#include <sys/types.h>
-#include "test.h"
-void setup(void);
-void cleanup(void);
+#include "tst_test.h"
-char *TCID = "getpgid01";
-int TST_TOTAL = 1;
-
-int main(int ac, char **av)
+static int get_init_pgid(void)
{
- int lc;
-
- register int pgid_0, pgid_1;
- register int my_pid, my_ppid;
- int ex_stat;
-
- tst_parse_opts(ac, av, NULL, NULL);
+ int pgid;
- setup();
-
- for (lc = 0; TEST_LOOPING(lc); lc++) {
- tst_count = 0;
-
- if ((pgid_0 = FORK_OR_VFORK()) == -1)
- tst_brkm(TBROK, cleanup, "fork failed");
- if (pgid_0 > 0) {
- while ((pgid_0 = wait(&ex_stat)) != -1) ;
-
- if (WEXITSTATUS(ex_stat) == 0)
- tst_resm(TPASS, "%s PASSED", TCID);
- else
- tst_resm(TFAIL, "%s FAILED", TCID);
-
- exit(0);
- }
+ SAFE_FILE_SCANF("/proc/1/stat", "%*d %*s %*c %*d %d", &pgid);
+ return pgid;
+}
- if ((pgid_0 = getpgid(0)) == -1)
- tst_resm(TFAIL | TERRNO, "getpgid(0) failed");
- else
- tst_resm(TPASS, "getpgid(0) PASSED");
+static void run(void)
+{
+ pid_t pid_1, child_pid, pgid;
-//block2:
- my_pid = getpid();
- if ((pgid_1 = getpgid(my_pid)) == -1)
- tst_resm(TFAIL | TERRNO, "getpgid(%d) failed", my_pid);
+ pgid = getpgid(0);
+ tst_res(TINFO, "getpgid(0) in parent = %d", pgid);
- if (pgid_0 != pgid_1) {
- tst_resm(TFAIL, "getpgid(my_pid=%d) != getpgid(0) "
- "[%d != %d]", my_pid, pgid_1, pgid_0);
- } else
- tst_resm(TPASS, "getpgid(getpid()) PASSED");
+ pid_1 = SAFE_FORK();
+ if (!pid_1) {
+ child_pid = getpid();
-//block3:
- my_ppid = getppid();
- if ((pgid_1 = getpgid(my_ppid)) == -1)
- tst_resm(TFAIL | TERRNO, "getpgid(%d) failed", my_ppid);
+ tst_res(TINFO, "getpid() in child = %d", child_pid);
+ tst_res(TINFO, "Running getpgid() in child");
- if (pgid_0 != pgid_1) {
- tst_resm(TFAIL, "getpgid(%d) != getpgid(0) [%d != %d]",
- my_ppid, pgid_1, pgid_0);
- } else
- tst_resm(TPASS, "getpgid(getppid()) PASSED");
+ TST_EXP_PID(getpgid(0));
+ TST_EXP_EQ_LI(TST_RET, pgid);
-//block4:
- if ((pgid_1 = getpgid(pgid_0)) < 0)
- tst_resm(TFAIL | TERRNO, "getpgid(%d) failed", pgid_0);
+ TST_EXP_PID(getpgid(child_pid), "getpgid(%d)", child_pid);
+ TST_EXP_EQ_LI(TST_RET, pgid);
- if (pgid_0 != pgid_1) {
- tst_resm(TFAIL, "getpgid(%d) != getpgid(0) [%d != %d]",
- pgid_0, pgid_1, pgid_0);
- } else
- tst_resm(TPASS, "getpgid(%d) PASSED", pgid_0);
+ TST_EXP_PID(getpgid(pgid), "getpgid(%d)", pgid);
+ TST_EXP_EQ_LI(TST_RET, pgid);
-//block5:
- if (getpgid(1) < 0)
- tst_resm(TFAIL | TERRNO, "getpgid(1) failed");
- else
- tst_resm(TPASS, "getpgid(1) PASSED");
+ TST_EXP_PID(getpgid(1));
+ TST_EXP_EQ_LI(TST_RET, get_init_pgid());
}
- cleanup();
- tst_exit();
+ tst_reap_children();
}
-void setup(void)
-{
-
- tst_sig(FORK, DEF_HANDLER, cleanup);
-
- TEST_PAUSE;
-}
-
-void cleanup(void)
-{
-}
+static struct tst_test test = {
+ .test_all = run,
+ .forks_child = 1
+};
diff --git a/testcases/kernel/syscalls/getpgid/getpgid02.c b/testcases/kernel/syscalls/getpgid/getpgid02.c
index 92482e3ae..30d0129bc 100644
--- a/testcases/kernel/syscalls/getpgid/getpgid02.c
+++ b/testcases/kernel/syscalls/getpgid/getpgid02.c
@@ -1,137 +1,34 @@
+// 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) 2023 SUSE LLC Avinesh Kumar <avinesh.kumar@suse.com>
*/
-/*
- * NAME
- * getpgid02.c
- *
- * DESCRIPTION
- * Testcase to check the basic functionality of getpgid().
- *
- * ALGORITHM
- * test 1: Does getpgid(-99) and expects ESRCH.
- * test 2: Searches an unused pid and expects ESRCH.
- *
- * USAGE: <for command-line>
- * getpgid02 [-c n] [-e] [-i n] [-I x] [-P x] [-t]
- * where, -c n : Run n copies concurrently.
- * -e : Turn on errno logging.
- * -i n : Execute test n times.
- * -I x : Execute test for x seconds.
- * -P x : Pause for x seconds between iterations.
- * -t : Turn on syscall timing.
- *
- * HISTORY
- * 07/2001 Ported by Wayne Boyer
+/*\
+ * [Description]
*
- * RESTRICTIONS
- * none
+ * Verify that getpgid(2) fails with errno ESRCH when
+ * pid does not match any process.
*/
-#define _GNU_SOURCE 1
-#include <errno.h>
-#include <unistd.h>
-#include <stdarg.h>
-#include <sys/wait.h>
-#include <sys/types.h>
-#include "test.h"
+#include "tst_test.h"
-void setup(void);
-void cleanup(void);
+static pid_t unused_pid;
+static pid_t neg_pid = -99;
-char *TCID = "getpgid02";
-int TST_TOTAL = 2;
-
-int pgid_0, pgid_1;
-#define BADPID -99
-
-struct test_case_t {
- int *id;
- int error;
-} TC[] = {
- /* The pid value is negative */
- {
- &pgid_0, ESRCH},
- /* The pid value does not match any process */
- {
- &pgid_1, ESRCH}
-};
-
-int main(int ac, char **av)
+static void setup(void)
{
- int lc;
- int i;
-
- 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;
-
- /* loop through the test cases */
- for (i = 0; i < TST_TOTAL; i++) {
-
- TEST(getpgid(*TC[i].id));
-
- if (TEST_RETURN != -1) {
- tst_resm(TFAIL, "call succeeded unexpectedly");
- continue;
- }
-
- if (TEST_ERRNO == TC[i].error) {
- tst_resm(TPASS, "expected failure - "
- "errno = %d : %s", TEST_ERRNO,
- strerror(TEST_ERRNO));
- } else {
- tst_resm(TFAIL, "unexpected error - %d : %s - "
- "expected %d", TEST_ERRNO,
- strerror(TEST_ERRNO), TC[i].error);
- }
- }
- }
- cleanup();
-
- tst_exit();
+ unused_pid = tst_get_unused_pid();
}
-/*
- * setup() - performs all ONE TIME setup for this test.
- */
-void setup(void)
+static void run(void)
{
-
- tst_sig(NOFORK, DEF_HANDLER, cleanup);
-
- TEST_PAUSE;
-
- pgid_0 = BADPID;
-
- pgid_1 = tst_get_unused_pid(cleanup);
+ TST_EXP_FAIL2(getpgid(neg_pid), ESRCH, "getpgid(%d)", neg_pid);
+ TST_EXP_FAIL2(getpgid(unused_pid), ESRCH, "getpgid(%d)", unused_pid);
}
-/*
- * cleanup() - performs all ONE TIME cleanup for this test at
- * completion or premature exit.
- */
-void cleanup(void)
-{
-
-}
+static struct tst_test test = {
+ .setup = setup,
+ .test_all = run
+};
diff --git a/testcases/kernel/syscalls/getpgrp/getpgrp01.c b/testcases/kernel/syscalls/getpgrp/getpgrp01.c
index 61feba8d1..a94736661 100644
--- a/testcases/kernel/syscalls/getpgrp/getpgrp01.c
+++ b/testcases/kernel/syscalls/getpgrp/getpgrp01.c
@@ -1,160 +1,24 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
- *
- * 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.
- *
- * Further, this software is distributed without any warranty that it is
- * free of the rightful claim of any third person regarding infringement
- * or the like. Any license provided herein, whether implied or
- * otherwise, applies only to this software file. Patent licenses, if
- * any, provided herein do not apply to combinations of this program with
- * other software, or any other product whatsoever.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
- * Mountain View, CA 94043, or:
- *
- * http://www.sgi.com
- *
- * For further information regarding this notice, see:
- *
- * http://oss.sgi.com/projects/GenInfo/NoticeExplan/
- *
+ * AUTHOR: William Roske, CO-PILOT: Dave Fenner
+ * Copyright (c) 2023 SUSE LLC Avinesh Kumar <avinesh.kumar@suse.com>
*/
-/* $Id: getpgrp01.c,v 1.6 2009/10/26 14:55:47 subrata_modak Exp $ */
-/**********************************************************
- *
- * OS Test - Silicon Graphics, Inc.
- *
- * TEST IDENTIFIER : getpgrp01
- *
- * EXECUTED BY : anyone
- *
- * TEST TITLE : Basic test for getpgrp(2)
- *
- * PARENT DOCUMENT : usctpl01
- *
- * TEST CASE TOTAL : 1
- *
- * WALL CLOCK TIME : 1
- *
- * CPU TYPES : ALL
- *
- * AUTHOR : William Roske
- *
- * CO-PILOT : Dave Fenner
- *
- * DATE STARTED : 03/30/92
- *
- * INITIAL RELEASE : UNICOS 7.0
- *
- * TEST CASES
- *
- * 1.) getpgrp(2) returns...(See Description)
- *
- * INPUT SPECIFICATIONS
- * The standard options for system call tests are accepted.
- * (See the parse_opts(3) man page).
- *
- * OUTPUT SPECIFICATIONS
- *$
- * DURATION
- * Terminates - with frequency and infinite modes.
- *
- * SIGNALS
- * Uses SIGUSR1 to pause before test if option set.
- * (See the parse_opts(3) man page).
- *
- * RESOURCES
- * None
- *
- * ENVIRONMENTAL NEEDS
- * No run-time environmental needs.
- *
- * SPECIAL PROCEDURAL REQUIREMENTS
- * None
- *
- * INTERCASE DEPENDENCIES
- * None
- *
- * DETAILED DESCRIPTION
- * This is a Phase I test for the getpgrp(2) system call. It is intended
- * to provide a limited exposure of the system call, for now. It
- * should/will be extended when full functional tests are written for
- * getpgrp(2).
- *
- * Setup:
- * Setup signal handling.
- * Pause for SIGUSR1 if option specified.
- *
- * Test:
- * Loop if the proper options are given.
- * Execute system call
- * Check return code, if system call failed (return=-1)
- * Log the errno and Issue a FAIL message.
- * Otherwise, Issue a PASS message.
- *
- * Cleanup:
- * Print errno log and/or timing stats if options given
- *
- *
- *#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#**/
-
-#include <sys/types.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <signal.h>
-#include <string.h>
-#include "test.h"
-
-void setup();
-void cleanup();
-
-char *TCID = "getpgrp01";
-int TST_TOTAL = 1;
-
-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(getpgrp());
-
- if (TEST_RETURN == -1)
- tst_resm(TFAIL | TTERRNO, "getpgrp failed");
- else
- tst_resm(TPASS, "getpgrp returned %ld", TEST_RETURN);
-
- }
+/*\
+ * [Description]
+ *
+ * Verify that getpgrp(2) syscall executes successfully.
+ */
- cleanup();
- tst_exit();
-}
+#include "tst_test.h"
-void setup(void)
+static void run(void)
{
-
- tst_sig(NOFORK, DEF_HANDLER, cleanup);
-
- TEST_PAUSE;
+ TST_EXP_PID(getpgrp());
+ TST_EXP_EQ_LI(TST_RET, SAFE_GETPGID(0));
}
-void cleanup(void)
-{
-}
+static struct tst_test test = {
+ .test_all = run
+};
diff --git a/testcases/kernel/syscalls/getpid/getpid02.c b/testcases/kernel/syscalls/getpid/getpid02.c
index d826724f4..86ad5a29f 100644
--- a/testcases/kernel/syscalls/getpid/getpid02.c
+++ b/testcases/kernel/syscalls/getpid/getpid02.c
@@ -7,6 +7,7 @@
* [Description]
*
* Check that:
+ *
* - fork() in parent returns the same pid as getpid() in child
* - getppid() in child returns the same pid as getpid() in parent
*/
diff --git a/testcases/kernel/syscalls/getrusage/getrusage04.c b/testcases/kernel/syscalls/getrusage/getrusage04.c
index 06b576d79..b03bc549b 100644
--- a/testcases/kernel/syscalls/getrusage/getrusage04.c
+++ b/testcases/kernel/syscalls/getrusage/getrusage04.c
@@ -104,8 +104,9 @@ int main(int argc, char *argv[])
tst_count = 0;
i = 0;
SAFE_GETRUSAGE(cleanup, RUSAGE_THREAD, &usage);
- tst_resm(TINFO, "utime:%12luus; stime:%12luus",
- usage.ru_utime.tv_usec, usage.ru_stime.tv_usec);
+ tst_resm(TINFO, "utime:%12lldus; stime:%12lldus",
+ (long long)usage.ru_utime.tv_usec,
+ (long long)usage.ru_stime.tv_usec);
ulast = usage.ru_utime.tv_usec;
slast = usage.ru_stime.tv_usec;
@@ -115,9 +116,9 @@ int main(int argc, char *argv[])
sdelta = usage.ru_stime.tv_usec - slast;
if (udelta > 0 || sdelta > 0) {
i++;
- tst_resm(TINFO, "utime:%12luus; stime:%12luus",
- usage.ru_utime.tv_usec,
- usage.ru_stime.tv_usec);
+ tst_resm(TINFO, "utime:%12lldus; stime:%12lldus",
+ (long long)usage.ru_utime.tv_usec,
+ (long long)usage.ru_stime.tv_usec);
if ((long)udelta > 1000 + (BIAS_MAX * factor_nr)) {
sprintf(msg_string,
"utime increased > %ldus:",
diff --git a/testcases/kernel/syscalls/init_module/init_module01.c b/testcases/kernel/syscalls/init_module/init_module01.c
index 79e567cd6..26ff0b93b 100644
--- a/testcases/kernel/syscalls/init_module/init_module01.c
+++ b/testcases/kernel/syscalls/init_module/init_module01.c
@@ -53,6 +53,7 @@ static struct tst_test test = {
.setup = setup,
.cleanup = cleanup,
.needs_root = 1,
- /* lockdown requires signed modules */
+ /* lockdown and SecureBoot requires signed modules */
.skip_in_lockdown = 1,
+ .skip_in_secureboot = 1,
};
diff --git a/testcases/kernel/syscalls/init_module/init_module02.c b/testcases/kernel/syscalls/init_module/init_module02.c
index ad6569a06..e6730e21c 100644
--- a/testcases/kernel/syscalls/init_module/init_module02.c
+++ b/testcases/kernel/syscalls/init_module/init_module02.c
@@ -22,7 +22,7 @@
#define MODULE_NAME "init_module.ko"
static unsigned long size, zero_size;
-static int kernel_lockdown;
+static int kernel_lockdown, secure_boot;
static void *buf, *faulty_buf, *null_buf;
static struct tst_cap cap_req = TST_CAP(TST_CAP_REQ, CAP_SYS_MODULE);
@@ -53,7 +53,8 @@ static void setup(void)
tst_module_exists(MODULE_NAME, NULL);
- kernel_lockdown = tst_lockdown_enabled();
+ kernel_lockdown = tst_lockdown_enabled() > 0;
+ secure_boot = tst_secureboot_enabled() > 0;
fd = SAFE_OPEN(MODULE_NAME, O_RDONLY|O_CLOEXEC);
SAFE_FSTAT(fd, &sb);
size = sb.st_size;
@@ -67,8 +68,8 @@ static void run(unsigned int n)
{
struct tcase *tc = &tcases[n];
- if (tc->skip_in_lockdown && kernel_lockdown) {
- tst_res(TCONF, "Kernel is locked down, skipping %s", tc->name);
+ if (tc->skip_in_lockdown && (kernel_lockdown || secure_boot)) {
+ tst_res(TCONF, "Cannot load unsigned modules, skipping %s", tc->name);
return;
}
diff --git a/testcases/kernel/syscalls/io_uring/io_uring01.c b/testcases/kernel/syscalls/io_uring/io_uring01.c
index 70151bb85..ab1ec00d6 100644
--- a/testcases/kernel/syscalls/io_uring/io_uring01.c
+++ b/testcases/kernel/syscalls/io_uring/io_uring01.c
@@ -264,5 +264,10 @@ static struct tst_test test = {
.bufs = (struct tst_buffers []) {
{&iov, .iov_sizes = (int[]){BLOCK_SZ, -1}},
{}
+ },
+ .save_restore = (const struct tst_path_val[]) {
+ {"/proc/sys/kernel/io_uring_disabled", "0",
+ TST_SR_SKIP_MISSING | TST_SR_TCONF_RO},
+ {}
}
};
diff --git a/testcases/kernel/syscalls/io_uring/io_uring02.c b/testcases/kernel/syscalls/io_uring/io_uring02.c
index c5c770074..c9d4bbcb1 100644
--- a/testcases/kernel/syscalls/io_uring/io_uring02.c
+++ b/testcases/kernel/syscalls/io_uring/io_uring02.c
@@ -255,6 +255,11 @@ static struct tst_test test = {
TST_CAP(TST_CAP_REQ, CAP_SYS_CHROOT),
{}
},
+ .save_restore = (const struct tst_path_val[]) {
+ {"/proc/sys/kernel/io_uring_disabled", "0",
+ TST_SR_SKIP_MISSING | TST_SR_TCONF_RO},
+ {}
+ },
.tags = (const struct tst_tag[]) {
{"linux-git", "9392a27d88b9"},
{"linux-git", "ff002b30181d"},
diff --git a/testcases/kernel/syscalls/ioctl/Makefile b/testcases/kernel/syscalls/ioctl/Makefile
index c2ff6c8e7..1d40f5e0b 100644
--- a/testcases/kernel/syscalls/ioctl/Makefile
+++ b/testcases/kernel/syscalls/ioctl/Makefile
@@ -7,6 +7,8 @@ include $(top_srcdir)/include/mk/testcases.mk
INSTALL_TARGETS += test_ioctl
+ioctl01: LDLIBS+=-lutil
+
ifeq ($(ANDROID),1)
FILTER_OUT_MAKE_TARGETS += ioctl02
endif
diff --git a/testcases/kernel/syscalls/ioctl/ioctl01.c b/testcases/kernel/syscalls/ioctl/ioctl01.c
index 2989c0e9b..c84a72b9a 100644
--- a/testcases/kernel/syscalls/ioctl/ioctl01.c
+++ b/testcases/kernel/syscalls/ioctl/ioctl01.c
@@ -2,104 +2,90 @@
/*
* Copyright (c) International Business Machines Corp., 2001
* Copyright (c) 2020 Petr Vorel <petr.vorel@gmail.com>
+ * Copyright (c) Linux Test Project, 2002-2023
* 07/2001 Ported by Wayne Boyer
* 04/2002 Fixes by wjhuie
+ */
+
+/*\
+ * [Description]
*
- * Testcase to check the errnos set by the ioctl(2) system call.
+ * Testcase to check the errnos set by the ioctl(2) system call.
*
- * ALGORITHM
- * 1. EBADF: Pass an invalid fd to ioctl(fd, ..) and expect EBADF.
- * 2. EFAULT: Pass an invalid address of arg in ioctl(fd, .., arg)
- * 3. EINVAL: Pass invalid cmd in ioctl(fd, cmd, arg)
- * 4. ENOTTY: Pass an non-streams fd in ioctl(fd, cmd, arg)
- * 5. EFAULT: Pass a NULL address for termio
+ * - EBADF: Pass an invalid fd to ioctl(fd, ...) and expect EBADF
+ * - EFAULT: Pass an invalid address of arg in ioctl(fd, ..., arg)
+ * - EINVAL: Pass invalid cmd in ioctl(fd, cmd, arg)
+ * - ENOTTY: Pass an non-streams fd in ioctl(fd, cmd, arg)
+ * - EFAULT: Pass a NULL address for termio
*/
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <termios.h>
+#include <pty.h>
#include "tst_test.h"
#include "lapi/ioctl.h"
#define INVAL_IOCTL 9999999
+static int amaster, aslave;
static int fd, fd_file;
static int bfd = -1;
static struct termio termio;
+static struct termios termios;
static struct tcase {
+ const char *desc;
int *fd;
int request;
- struct termio *s_tio;
+ void *s_tio;
int error;
} tcases[] = {
- /* file descriptor is invalid */
- {&bfd, TCGETA, &termio, EBADF},
- /* termio address is invalid */
- {&fd, TCGETA, (struct termio *)-1, EFAULT},
- /* command is invalid */
+ {"File descriptor is invalid (termio)", &bfd, TCGETA, &termio, EBADF},
+ {"File descriptor is invalid (termios)", &bfd, TCGETS, &termios, EBADF},
+ {"Termio address is invalid", &fd, TCGETA, (struct termio *)-1, EFAULT},
+ {"Termios address is invalid", &fd, TCGETS, (struct termios *)-1, EFAULT},
/* This errno value was changed from EINVAL to ENOTTY
* by kernel commit 07d106d0 and bbb63c51
*/
- {&fd, INVAL_IOCTL, &termio, ENOTTY},
- /* file descriptor is for a regular file */
- {&fd_file, TCGETA, &termio, ENOTTY},
- /* termio is NULL */
- {&fd, TCGETA, NULL, EFAULT}
+ {"Command is invalid", &fd, INVAL_IOCTL, &termio, ENOTTY},
+ {"File descriptor is for a regular file (termio)", &fd_file, TCGETA, &termio, ENOTTY},
+ {"File descriptor is for a regular file (termios)", &fd_file, TCGETS, &termios, ENOTTY},
+ {"Termio is NULL", &fd, TCGETA, NULL, EFAULT},
+ {"Termios is NULL", &fd, TCGETS, NULL, EFAULT}
};
-static char *device;
-
static void verify_ioctl(unsigned int i)
{
- TEST(ioctl(*(tcases[i].fd), tcases[i].request, tcases[i].s_tio));
-
- if (TST_RET != -1) {
- tst_res(TFAIL, "call succeeded unexpectedly");
- return;
- }
-
- if (TST_ERR != tcases[i].error) {
- tst_res(TFAIL | TTERRNO,
- "failed unexpectedly; expected %s",
- tst_strerrno(tcases[i].error));
- return;
- }
-
- tst_res(TPASS | TTERRNO, "failed as expected");
+ TST_EXP_FAIL(ioctl(*(tcases[i].fd), tcases[i].request, tcases[i].s_tio),
+ tcases[i].error, "%s", tcases[i].desc);
}
static void setup(void)
{
- unsigned int i;
+ if (openpty(&amaster, &aslave, NULL, NULL, NULL) < 0)
+ tst_brk(TBROK | TERRNO, "unable to open pty");
- if (!device)
- tst_brk(TBROK, "You must specify a tty device with -D option");
-
- fd = SAFE_OPEN(device, O_RDWR, 0777);
+ fd = amaster;
fd_file = SAFE_OPEN("x", O_CREAT, 0777);
}
static void cleanup(void)
{
- if (fd > 0)
- SAFE_CLOSE(fd);
-
+ if (amaster > 0)
+ SAFE_CLOSE(amaster);
+ if (aslave > 0)
+ SAFE_CLOSE(aslave);
if (fd_file > 0)
SAFE_CLOSE(fd_file);
}
static struct tst_test test = {
- .needs_root = 1,
.needs_tmpdir = 1,
.setup = setup,
.cleanup = cleanup,
.test = verify_ioctl,
- .tcnt = ARRAY_SIZE(tcases),
- .options = (struct tst_option[]) {
- {"D:", &device, "Tty device. For example, /dev/tty[0-9]"},
- {}
- }
+ .tcnt = ARRAY_SIZE(tcases)
};
diff --git a/testcases/kernel/syscalls/ioctl/test_ioctl b/testcases/kernel/syscalls/ioctl/test_ioctl
index 923275433..43836a229 100755
--- a/testcases/kernel/syscalls/ioctl/test_ioctl
+++ b/testcases/kernel/syscalls/ioctl/test_ioctl
@@ -41,29 +41,6 @@ case "$device_no" in
[0-9]|[0-9][0-9])
has_tty $tttype
if [ $? -eq 0 ]; then
- tst_resm TINFO "Skipping ioctl01 with $tttype"
- continue
- fi
- tst_resm TINFO "Testing ioctl01 with $tttype"
- ioctl01 -D $tttype
- RC=$?
- if [ $RC -eq 0 ]
- then
- tst_resm TPASS "ioctl01 Passed with $tttype"
- else
- tst_resm TFAIL "ioctl01 Failed with $tttype"
- fi
-echo;;
-esac
-done
-
-for tttype in `ls /dev/tty*`
-do
-device_no=${tttype#/dev/tty}
-case "$device_no" in
-[0-9]|[0-9][0-9])
- has_tty $tttype
- if [ $? -eq 0 ]; then
tst_resm TINFO "Skipping ioctl02 with $tttype"
continue
fi
diff --git a/testcases/kernel/syscalls/ioprio/ioprio.h b/testcases/kernel/syscalls/ioprio/ioprio.h
index c74380475..dbe27c15f 100644
--- a/testcases/kernel/syscalls/ioprio/ioprio.h
+++ b/testcases/kernel/syscalls/ioprio/ioprio.h
@@ -1,33 +1,14 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Copyright (c) 2019 Linus Walleij <linus.walleij@linaro.org>
+ * Copyright (c) 2023 Linux Test Project
*/
#ifndef LTP_IOPRIO_H
#define LTP_IOPRIO_H
-enum {
- IOPRIO_CLASS_NONE = 0,
- IOPRIO_CLASS_RT,
- IOPRIO_CLASS_BE,
- IOPRIO_CLASS_IDLE,
-};
-
-enum {
- IOPRIO_WHO_PROCESS = 1,
- IOPRIO_WHO_PGRP,
- IOPRIO_WHO_USER,
-};
-
-/* The I/O scheduler classes have 8 priorities 0..7 except for the IDLE class */
-#define IOPRIO_PRIO_NUM 8
-
-#define IOPRIO_CLASS_SHIFT (13)
-#define IOPRIO_PRIO_MASK ((1UL << IOPRIO_CLASS_SHIFT) - 1)
-
-#define IOPRIO_PRIO_CLASS(data) ((data) >> IOPRIO_CLASS_SHIFT)
-#define IOPRIO_PRIO_LEVEL(data) ((data) & IOPRIO_PRIO_MASK)
-#define IOPRIO_PRIO_VALUE(class, data) (((class) << IOPRIO_CLASS_SHIFT) | data)
+#include "lapi/ioprio.h"
+#include "lapi/syscalls.h"
static const char * const to_class_str[] = {
[IOPRIO_CLASS_NONE] = "NONE",
@@ -46,10 +27,10 @@ static inline int sys_ioprio_set(int which, int who, int ioprio)
return tst_syscall(__NR_ioprio_set, which, who, ioprio);
}
-/* Priority range from 0 (highest) to 7 (lowest) */
+/* Priority range from 0 (highest) to IOPRIO_PRIO_NUM (lowest) */
static inline int prio_in_range(int prio)
{
- if ((prio < 0) || (prio > 7))
+ if ((prio < 0) || (prio >= IOPRIO_PRIO_NUM))
return 0;
return 1;
}
@@ -91,4 +72,4 @@ static inline void ioprio_check_setting(int class, int prio, int report)
newprio);
}
-#endif
+#endif /* LTP_IOPRIO_H */
diff --git a/testcases/kernel/syscalls/ioprio/ioprio_get01.c b/testcases/kernel/syscalls/ioprio/ioprio_get01.c
index 6e822434e..f1325be31 100644
--- a/testcases/kernel/syscalls/ioprio/ioprio_get01.c
+++ b/testcases/kernel/syscalls/ioprio/ioprio_get01.c
@@ -1,16 +1,17 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2019 Linus Walleij <linus.walleij@linaro.org>
+ * Copyright (c) 2023 Linux Test Project
+ */
+
+/*\
+ * [Description]
*
- * Description:
* Basic ioprio_get() test. Gets the current process I/O priority and
* checks that the values are sane.
*/
-#include <sys/types.h>
-#include <sys/syscall.h>
#include "tst_test.h"
-#include "lapi/syscalls.h"
#include "ioprio.h"
static void run(void)
diff --git a/testcases/kernel/syscalls/ioprio/ioprio_set01.c b/testcases/kernel/syscalls/ioprio/ioprio_set01.c
index 19953ba36..0868cea7c 100644
--- a/testcases/kernel/syscalls/ioprio/ioprio_set01.c
+++ b/testcases/kernel/syscalls/ioprio/ioprio_set01.c
@@ -1,17 +1,18 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2019 Linus Walleij <linus.walleij@linaro.org>
+ * Copyright (c) 2019-2023 Linux Test Project
+ */
+
+/*\
+ * [Description]
*
- * Description:
* Basic ioprio_set() test. Gets the current process I/O priority and
* bumps it up one notch, then down two notches and checks that the
* new priority is reported back correctly.
*/
-#include <sys/types.h>
-#include <sys/syscall.h>
#include "tst_test.h"
-#include "lapi/syscalls.h"
#include "ioprio.h"
static int orig_class;
diff --git a/testcases/kernel/syscalls/ioprio/ioprio_set02.c b/testcases/kernel/syscalls/ioprio/ioprio_set02.c
index 328a130cb..37db7bf42 100644
--- a/testcases/kernel/syscalls/ioprio/ioprio_set02.c
+++ b/testcases/kernel/syscalls/ioprio/ioprio_set02.c
@@ -1,17 +1,18 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2019 Linus Walleij <linus.walleij@linaro.org>
+ * Copyright (c) 2023 Linux Test Project
+ */
+
+/*\
+ * [Description]
*
- * Description:
* Extended ioprio_set() test.
* Tests to set all 8 priority levels for best effort priority, then
* switches to test all 8 priority levels for idle priority.
*/
-#include <sys/types.h>
-#include <sys/syscall.h>
#include "tst_test.h"
-#include "lapi/syscalls.h"
#include "ioprio.h"
static void run(void)
diff --git a/testcases/kernel/syscalls/ioprio/ioprio_set03.c b/testcases/kernel/syscalls/ioprio/ioprio_set03.c
index b2c962a6f..6efcacc1c 100644
--- a/testcases/kernel/syscalls/ioprio/ioprio_set03.c
+++ b/testcases/kernel/syscalls/ioprio/ioprio_set03.c
@@ -1,16 +1,17 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2019 Linus Walleij <linus.walleij@linaro.org>
+ * Copyright (c) 2023 Linux Test Project
+ */
+
+/*\
+ * [Description]
*
- * Description:
* Negative ioprio_set() test. Test some non-working priorities to make
* sure they don't work.
*/
-#include <sys/types.h>
-#include <sys/syscall.h>
#include "tst_test.h"
-#include "lapi/syscalls.h"
#include "ioprio.h"
static void run(void)
@@ -27,7 +28,7 @@ static void run(void)
sys_ioprio_set(IOPRIO_WHO_PROCESS, 0,
IOPRIO_PRIO_VALUE(class, 4));
TEST(sys_ioprio_set(IOPRIO_WHO_PROCESS, 0,
- IOPRIO_PRIO_VALUE(class, 8)));
+ IOPRIO_PRIO_VALUE(class, IOPRIO_PRIO_NUM)));
if (TST_RET == -1) {
ioprio_check_setting(class, 4, 1);
if (errno == EINVAL)
diff --git a/testcases/kernel/syscalls/ipc/msgctl/msgctl01.c b/testcases/kernel/syscalls/ipc/msgctl/msgctl01.c
index 75adcb229..56d1505fd 100644
--- a/testcases/kernel/syscalls/ipc/msgctl/msgctl01.c
+++ b/testcases/kernel/syscalls/ipc/msgctl/msgctl01.c
@@ -6,7 +6,7 @@
*/
/*
- * Test that IPC_STAT command succeeds and the the buffer is filled with
+ * Test that IPC_STAT command succeeds and the buffer is filled with
* correct data.
*/
#include <errno.h>
diff --git a/testcases/kernel/syscalls/ipc/msgget/msgget02.c b/testcases/kernel/syscalls/ipc/msgget/msgget02.c
index ce59a8fb5..1885599d1 100644
--- a/testcases/kernel/syscalls/ipc/msgget/msgget02.c
+++ b/testcases/kernel/syscalls/ipc/msgget/msgget02.c
@@ -8,11 +8,11 @@
*
* Test for EEXIST, ENOENT, EACCES errors.
*
- * 1) msgget(2) fails if a message queue exists for key and msgflg
+ * - msgget(2) fails if a message queue exists for key and msgflg
* specified both IPC_CREAT and IPC_EXCL.
- * 2) msgget(2) fails if no message queue exists for key and msgflg
+ * - msgget(2) fails if no message queue exists for key and msgflg
* did not specify IPC_CREAT.
- * 3) msgget(2) fails if a message queue exists for key, but the
+ * - msgget(2) fails if a message queue exists for key, but the
* calling process does not have permission to access the queue,
* and does not have the CAP_IPC_OWNER capability.
*
diff --git a/testcases/kernel/syscalls/ipc/msgstress/msgstress03.c b/testcases/kernel/syscalls/ipc/msgstress/msgstress03.c
index 3cb70ab18..aa37d9058 100644
--- a/testcases/kernel/syscalls/ipc/msgstress/msgstress03.c
+++ b/testcases/kernel/syscalls/ipc/msgstress/msgstress03.c
@@ -110,11 +110,12 @@ int main(int argc, char **argv)
}
free_pids = tst_get_free_pids(cleanup);
- if (nprocs >= free_pids) {
+ /* Each forked child forks once, take it into account here. */
+ if (nprocs * 2 >= free_pids) {
tst_resm(TINFO,
"Requested number of processes higher than limit (%d > %d), "
- "setting to %d", nprocs, free_pids, free_pids);
- nprocs = free_pids;
+ "setting to %d", nprocs * 2, free_pids, free_pids);
+ nprocs = free_pids / 2;
}
srand(getpid());
diff --git a/testcases/kernel/syscalls/ipc/semget/.gitignore b/testcases/kernel/syscalls/ipc/semget/.gitignore
index ce26c93b0..4519b30d2 100644
--- a/testcases/kernel/syscalls/ipc/semget/.gitignore
+++ b/testcases/kernel/syscalls/ipc/semget/.gitignore
@@ -1,5 +1,3 @@
/semget01
/semget02
-/semget03
/semget05
-/semget06
diff --git a/testcases/kernel/syscalls/ipc/semget/Makefile b/testcases/kernel/syscalls/ipc/semget/Makefile
index 26b9f264d..b1201281d 100644
--- a/testcases/kernel/syscalls/ipc/semget/Makefile
+++ b/testcases/kernel/syscalls/ipc/semget/Makefile
@@ -3,10 +3,10 @@
top_srcdir ?= ../../../../..
-LTPLIBS = ltpipc
+LTPLIBS = ltpnewipc
include $(top_srcdir)/include/mk/testcases.mk
-LTPLDLIBS = -lltpipc
+LTPLDLIBS = -lltpnewipc
include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/syscalls/ipc/semget/semget01.c b/testcases/kernel/syscalls/ipc/semget/semget01.c
index 217163b3a..872acabd3 100644
--- a/testcases/kernel/syscalls/ipc/semget/semget01.c
+++ b/testcases/kernel/syscalls/ipc/semget/semget01.c
@@ -1,172 +1,65 @@
+// 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
*/
-/*
- * NAME
- * semget01.c
- *
- * DESCRIPTION
- * semget01 - test that semget() correclty creates a semaphore set
+/*\
+ * [Description]
*
- * ALGORITHM
- * loop if that option was specified
- * call semget() to create the semaphore set
- * check the return code
- * if failure, issue a FAIL message.
- * otherwise,
- * if doing functionality testing
- * stat the semaphore set
- * if the number of primitive semaphores is correct and
- * the semaphore uid == the process uid
- * then,
- * issue a PASS message
- * otherwise
- * issue a FAIL message
- * call cleanup
- *
- * USAGE: <for command-line>
- * semget01 [-c n] [-f] [-i n] [-I x] [-P x] [-t]
- * where, -c n : Run n copies concurrently.
- * -f : Turn off functionality Testing.
- * -i n : Execute test n times.
- * -I x : Execute test for x seconds.
- * -P x : Pause for x seconds between iterations.
- * -t : Turn on syscall timing.
- *
- * HISTORY
- * 03/2001 - Written by Wayne Boyer
- *
- * RESTRICTIONS
- * none
+ * This case checks that semget() correclty creates a semaphore set.
*/
-#include "ipcsem.h"
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include "lapi/sem.h"
+#include "tst_test.h"
+#include "libnewipc.h"
+#include "tst_safe_sysv_ipc.h"
-char *TCID = "semget01";
-int TST_TOTAL = 1;
+static int sem_id = -1, sem_key = -1;
-int sem_id_1 = -1;
-
-int main(int ac, char **av)
+static void check_functionality(void)
{
- int lc;
- void check_functionality(void);
-
- tst_parse_opts(ac, av, NULL, NULL);
-
- setup(); /* global setup */
-
- /* The following loop checks looping state if -i option given */
-
- for (lc = 0; TEST_LOOPING(lc); lc++) {
- /* reset tst_count in case we are looping */
- tst_count = 0;
-
- /*
- * Use TEST macro to make the call
- */
-
- TEST(semget(semkey, PSEMS, IPC_CREAT | IPC_EXCL | SEM_RA));
-
- if (TEST_RETURN == -1) {
- tst_resm(TFAIL, "%s call failed - errno = %d : %s",
- TCID, TEST_ERRNO, strerror(TEST_ERRNO));
- } else {
- /* get the semaphore ID */
- sem_id_1 = TEST_RETURN;
-
- check_functionality();
- }
-
- /*
- * remove the semaphore that was created and mark the ID
- * as invalid.
- */
- if (sem_id_1 != -1) {
- rm_sema(sem_id_1);
- sem_id_1 = -1;
- }
- }
+ struct semid_ds semary;
+ union semun un_arg;
- cleanup();
+ un_arg.buf = &semary;
+ SAFE_SEMCTL(sem_id, 0, IPC_STAT, un_arg);
+ TST_EXP_EQ_LI(un_arg.buf->sem_nsems, PSEMS);
+ TST_EXP_EQ_LI(un_arg.buf->sem_perm.cuid, geteuid());
- tst_exit();
+ tst_res(TPASS, "basic semaphore values are okay");
}
-/*
- * check_functionality() - check the functionality of the tested system call.
- */
-void check_functionality(void)
+static void verify_semget(void)
{
- struct semid_ds semary;
- union semun un_arg; /* union defined in ipcsem.h */
-
- /* STAT the semaphore */
- un_arg.buf = &semary;
- if (semctl(sem_id_1, 0, IPC_STAT, un_arg) == -1) {
- tst_brkm(TBROK, cleanup, "Could not stat the semaphore");
+ TEST(semget(sem_key, PSEMS, IPC_CREAT | IPC_EXCL | SEM_RA));
+ if (TST_RET == -1) {
+ tst_res(TFAIL | TTERRNO, "semget() failed");
return;
}
- if (un_arg.buf->sem_nsems != PSEMS) {
- tst_resm(TFAIL, "# of semaphores in set != # given to create");
- return;
- }
+ sem_id = TST_RET;
+ check_functionality();
- if (un_arg.buf->sem_perm.cuid != geteuid()) {
- tst_resm(TFAIL, "semaphore uid != process uid");
- return;
- }
-
- tst_resm(TPASS, "basic semaphore values are okay");
+ SAFE_SEMCTL(sem_id, PSEMS, IPC_RMID);
}
-/*
- * setup() - performs all the ONE TIME setup for this test.
- */
-void setup(void)
+static void setup(void)
{
-
- tst_sig(NOFORK, DEF_HANDLER, cleanup);
-
- TEST_PAUSE;
-
- /*
- * Create a temporary directory and cd into it.
- * This helps to ensure that a unique msgkey is created.
- * See libs/libltpipc/libipc.c for more information.
- */
- tst_tmpdir();
-
- /* get an IPC resource key */
- semkey = getipckey();
+ sem_key = GETIPCKEY();
}
-/*
- * cleanup() - performs all the ONE TIME cleanup for this test at completion
- * or premature exit.
- */
-void cleanup(void)
+static void cleanup(void)
{
- /* if it exists, remove the semaphore resouce */
- rm_sema(sem_id_1);
-
- tst_rmdir();
-
+ if (sem_id != -1)
+ SAFE_SEMCTL(sem_id, PSEMS, IPC_RMID);
}
+
+static struct tst_test test = {
+ .needs_tmpdir = 1,
+ .setup = setup,
+ .cleanup = cleanup,
+ .test_all = verify_semget,
+};
diff --git a/testcases/kernel/syscalls/ipc/semget/semget02.c b/testcases/kernel/syscalls/ipc/semget/semget02.c
index 4124514c2..4273c84c7 100644
--- a/testcases/kernel/syscalls/ipc/semget/semget02.c
+++ b/testcases/kernel/syscalls/ipc/semget/semget02.c
@@ -1,165 +1,102 @@
+// 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
*/
-/*
- * NAME
- * semget02.c
+/*\
+ * [Description]
*
- * DESCRIPTION
- * semget02 - test for EACCES and EEXIST errors
+ * This basic error handing of the semget syscall.
*
- * ALGORITHM
- * create a semaphore set without read or alter permissions
- * loop if that option was specified
- * call semget() using two different invalid cases
- * check the errno value
- * issue a PASS message if we get EACCES or EEXIST
- * otherwise, the tests fails
- * issue a FAIL message
- * call cleanup
- *
- * USAGE: <for command-line>
- * semget02 [-c n] [-e] [-i n] [-I x] [-P x] [-t]
- * where, -c n : Run n copies concurrently.
- * -e : Turn on errno logging.
- * -i n : Execute test n times.
- * -I x : Execute test for x seconds.
- * -P x : Pause for x seconds between iterations.
- * -t : Turn on syscall timing.
- *
- * HISTORY
- * 03/2001 - Written by Wayne Boyer
- *
- * RESTRICTIONS
- * none
+ * - EACCES - a semaphore set exists for key, but the calling process does not
+ * have permission to access the set
+ * - EEXIST - a semaphore set already exists for key and IPC_CREAT | IPC_EXCL
+ * is given
+ * - ENOENT - No semaphore set exists for key and semflg did not specify
+ * IPC_CREAT
+ * - EINVAL - nsems is less than 0 or greater than the limit on the number of
+ * semaphores per semaphore set(SEMMSL)
+ * - EINVAL - a semaphore set corresponding to key already exists, but nsems is
+ * larger than the number of semaphores in that set
*/
-#include <pwd.h>
-
-#include "ipcsem.h"
-char *TCID = "semget02";
-int TST_TOTAL = 2;
-
-char nobody_uid[] = "nobody";
-struct passwd *ltpuser;
-
-int sem_id_1 = -1;
-
-struct test_case_t {
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include "tst_test.h"
+#include "tst_safe_sysv_ipc.h"
+#include "libnewipc.h"
+#include "lapi/sem.h"
+
+static int sem_id = -1;
+static key_t semkey, semkey1;
+static struct passwd *pw;
+static struct tcase {
+ int *key;
+ int nsems;
int flags;
- int error;
-} TC[] = {
- /* EACCES - the semaphore has no read or alter permissions */
- {
- SEM_RA, EACCES},
- /* EEXIST - the semaphore id exists and semget() was called with */
- /* IPC_CREAT and IPC_EXCL */
- {
- IPC_CREAT | IPC_EXCL, EEXIST}
+ int exp_err;
+ /*1: nobody expected, 0: root expected */
+ int exp_user;
+} tcases[] = {
+ {&semkey, PSEMS, SEM_RA, EACCES, 1},
+ {&semkey, PSEMS, IPC_CREAT | IPC_EXCL, EEXIST, 0},
+ {&semkey1, PSEMS, SEM_RA, ENOENT, 0},
+ {&semkey1, -1, IPC_CREAT | IPC_EXCL, EINVAL, 0},
+ {&semkey1, SEMMSL + 1, IPC_CREAT | IPC_EXCL, EINVAL, 0},
+ {&semkey, PSEMS + 1, SEM_RA, EINVAL, 0},
};
-int main(int ac, char **av)
+static void verify_semget(struct tcase *tc)
{
- int lc;
- int i;
-
- tst_parse_opts(ac, av, NULL, NULL);
-
- setup(); /* global setup */
-
- /* The following loop checks looping state if -i option given */
-
- for (lc = 0; TEST_LOOPING(lc); lc++) {
- /* reset tst_count in case we are looping */
- tst_count = 0;
-
- for (i = 0; i < TST_TOTAL; i++) {
- /* use the TEST macro to make the call */
-
- TEST(semget(semkey, PSEMS, TC[i].flags));
-
- if (TEST_RETURN != -1) {
- sem_id_1 = TEST_RETURN;
- tst_resm(TFAIL, "call succeeded");
- continue;
- }
+ TST_EXP_FAIL2(semget(*tc->key, tc->nsems, tc->flags), tc->exp_err,
+ "semget(%i, %i, %i)", *tc->key, tc->nsems, tc->flags);
+}
- if (TEST_ERRNO == TC[i].error) {
- tst_resm(TPASS, "expected failure - errno "
- "= %d : %s", TEST_ERRNO,
- strerror(TEST_ERRNO));
- } else {
- tst_resm(TFAIL, "unexpected error - %d : %s",
- TEST_ERRNO, strerror(TEST_ERRNO));
- }
+static void do_test(unsigned int n)
+{
+ pid_t pid;
+ struct tcase *tc = &tcases[n];
+
+ if (tc->exp_user == 0) {
+ verify_semget(tc);
+ } else {
+ pid = SAFE_FORK();
+ if (pid) {
+ tst_reap_children();
+ } else {
+ SAFE_SETUID(pw->pw_uid);
+ verify_semget(tc);
+ exit(0);
}
}
-
- cleanup();
-
- tst_exit();
}
-/*
- * setup() - performs all the ONE TIME setup for this test.
- */
-void setup(void)
+static void setup(void)
{
- tst_require_root();
-
- /* Switch to nobody user for correct error code collection */
- ltpuser = getpwnam(nobody_uid);
- if (seteuid(ltpuser->pw_uid) == -1) {
- tst_resm(TINFO, "setreuid failed to "
- "to set the effective uid to %d", ltpuser->pw_uid);
- perror("setreuid");
- }
-
- tst_sig(NOFORK, DEF_HANDLER, cleanup);
+ semkey = GETIPCKEY();
+ semkey1 = GETIPCKEY();
- TEST_PAUSE;
+ sem_id = SAFE_SEMGET(semkey, PSEMS, IPC_CREAT | IPC_EXCL);
- /*
- * Create a temporary directory and cd into it.
- * This helps to ensure that a unique msgkey is created.
- * See libs/libltpipc/libipc.c for more information.
- */
- tst_tmpdir();
-
- /* get an IPC resource key */
- semkey = getipckey();
-
- /* create a semaphore set without read or alter permissions */
- if ((sem_id_1 = semget(semkey, PSEMS, IPC_CREAT | IPC_EXCL)) == -1) {
- tst_brkm(TBROK, cleanup, "couldn't create semaphore in setup");
- }
+ pw = SAFE_GETPWNAM("nobody");
}
-/*
- * cleanup() - performs all the ONE TIME cleanup for this test at completion
- * or premature exit.
- */
-void cleanup(void)
+static void cleanup(void)
{
- /* if it exists, remove the semaphore resource */
- rm_sema(sem_id_1);
-
- tst_rmdir();
-
+ if (sem_id != -1)
+ SAFE_SEMCTL(sem_id, PSEMS, IPC_RMID);
}
+
+static struct tst_test test = {
+ .needs_tmpdir = 1,
+ .needs_root = 1,
+ .forks_child = 1,
+ .tcnt = ARRAY_SIZE(tcases),
+ .setup = setup,
+ .cleanup = cleanup,
+ .test = do_test,
+};
diff --git a/testcases/kernel/syscalls/ipc/semget/semget03.c b/testcases/kernel/syscalls/ipc/semget/semget03.c
deleted file mode 100644
index 995b4bd3a..000000000
--- a/testcases/kernel/syscalls/ipc/semget/semget03.c
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- *
- * 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
- * semget03.c
- *
- * DESCRIPTION
- * semget03 - test for ENOENT error
- *
- * ALGORITHM
- * loop if that option was specified
- * call semget() with a valid key but with no associated semaphore set
- * and IPC_CREAT is not asserted
- * check the errno value
- * issue a PASS message if we get ENOENT
- * otherwise, the tests fails
- * issue a FAIL message
- * call cleanup
- *
- * USAGE: <for command-line>
- * semget03 [-c n] [-e] [-i n] [-I x] [-P x] [-t]
- * where, -c n : Run n copies concurrently.
- * -e : Turn on errno logging.
- * -i n : Execute test n times.
- * -I x : Execute test for x seconds.
- * -P x : Pause for x seconds between iterations.
- * -t : Turn on syscall timing.
- *
- * HISTORY
- * 03/2001 - Written by Wayne Boyer
- *
- * RESTRICTIONS
- * none
- */
-
-#include "ipcsem.h"
-
-char *TCID = "semget03";
-int TST_TOTAL = 1;
-
-int sem_id_1 = -1;
-
-int main(int ac, char **av)
-{
- int lc;
-
- tst_parse_opts(ac, av, NULL, NULL);
-
- setup(); /* global setup */
-
- /* The following loop checks looping state if -i option given */
-
- for (lc = 0; TEST_LOOPING(lc); lc++) {
- /* reset tst_count in case we are looping */
- tst_count = 0;
-
- /* use the TEST macro to make the call */
-
- TEST(semget(semkey, PSEMS, SEM_RA));
-
- if (TEST_RETURN != -1) {
- sem_id_1 = TEST_RETURN;
- tst_resm(TFAIL, "call succeeded when error expected");
- continue;
- }
-
- switch (TEST_ERRNO) {
- case ENOENT:
- tst_resm(TPASS, "expected failure - errno "
- "= %d : %s", TEST_ERRNO, strerror(TEST_ERRNO));
- break;
- default:
- tst_resm(TFAIL, "unexpected error - %d : %s",
- TEST_ERRNO, strerror(TEST_ERRNO));
- break;
- }
- }
-
- cleanup();
-
- tst_exit();
-}
-
-/*
- * setup() - performs all the ONE TIME setup for this test.
- */
-void setup(void)
-{
-
- tst_sig(NOFORK, DEF_HANDLER, cleanup);
-
- TEST_PAUSE;
-
- /*
- * Create a temporary directory and cd into it.
- * This helps to ensure that a unique msgkey is created.
- * See libs/libltpipc/libipc.c for more information.
- */
- tst_tmpdir();
-
- /* get an IPC resource key */
- semkey = getipckey();
-}
-
-/*
- * cleanup() - performs all the ONE TIME cleanup for this test at completion
- * or premature exit.
- */
-void cleanup(void)
-{
- /* if it exists, remove the semaphore resource */
- rm_sema(sem_id_1);
-
- tst_rmdir();
-
-}
diff --git a/testcases/kernel/syscalls/ipc/semget/semget05.c b/testcases/kernel/syscalls/ipc/semget/semget05.c
index f801cb8ed..dd9a6285d 100644
--- a/testcases/kernel/syscalls/ipc/semget/semget05.c
+++ b/testcases/kernel/syscalls/ipc/semget/semget05.c
@@ -1,152 +1,83 @@
+// 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
*/
-/*
- * NAME
- * semget05.c
- *
- * DESCRIPTION
- * semget05 - test for ENOSPC error
+/*\
+ * [Description]
*
- * ALGORITHM
- * create semaphore sets in a loop until the system limit is reached
- * loop if that option was specified
- * attempt to create yet another semaphore set
- * check the errno value
- * issue a PASS message if we get ENOSPC
- * otherwise, the tests fails
- * issue a FAIL message
- * call cleanup
+ * Test for ENOSPC error.
*
- * USAGE: <for command-line>
- * HISTORY
- * 03/2001 - Written by Wayne Boyer
- * 07/2006 - Changes By Michael Reed
- * - Changed the value of MAXIDS for the specific machine by reading
- * the system limit for SEMMNI - The maximum number of sempahore sets
- * 03/2008 - Matthieu Fertré (mfertre@irisa.fr)
- * - Fix concurrency issue. Create private semaphores to
- * avoid conflict with concurrent processes.
- *
- * RESTRICTIONS
- * none
- */
-
-#include "ipcsem.h"
-
-char *TCID = "semget05";
-int TST_TOTAL = 1;
-
-/*
- * The MAXIDS value is somewhat arbitrary and may need to be increased
- * depending on the system being tested.
+ * ENOSPC - a semaphore set exceed the maximum number of semaphore sets(SEMMNI)
*/
-int MAXIDS = 2048;
-
-int *sem_id_arr = NULL;
-int num_sems = 0; /* count the semaphores created */
-
-int main(int ac, char **av)
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include "lapi/sem.h"
+#include "tst_test.h"
+#include "libnewipc.h"
+#include "tst_safe_sysv_ipc.h"
+
+static int *sem_id_arr;
+static int maxsems, array_cnt, used_cnt;
+static key_t semkey;
+
+static void verify_semget(void)
{
- int lc;
- FILE *fp;
-
- tst_parse_opts(ac, av, NULL, NULL);
-
- /* Set the MAXIDS for the specific machine by reading the system limit
- * for SEMMNI - The maximum number of sempahore sets
- */
- fp = fopen("/proc/sys/kernel/sem", "r");
- if (fp != NULL) {
- int getmaxid;
- if (fscanf(fp, "%*d %*d %*d %d", &getmaxid) == 1)
- MAXIDS = getmaxid + 1;
- fclose(fp);
- }
-
- sem_id_arr = malloc(sizeof(int) * MAXIDS);
- if (sem_id_arr == NULL)
- tst_brkm(TBROK, cleanup, "malloc failed");
-
- setup();
-
- for (lc = 0; TEST_LOOPING(lc); lc++) {
- tst_count = 0;
-
-
- TEST(semget(IPC_PRIVATE, PSEMS, IPC_CREAT | IPC_EXCL | SEM_RA));
- if (TEST_RETURN != -1) {
- tst_resm(TFAIL, "call succeeded when error expected");
- continue;
- }
-
- switch (TEST_ERRNO) {
- case ENOSPC:
- tst_resm(TPASS, "expected failure - errno "
- "= %d : %s", TEST_ERRNO, strerror(TEST_ERRNO));
- break;
- default:
- tst_resm(TFAIL, "unexpected error - %d : %s",
- TEST_ERRNO, strerror(TEST_ERRNO));
- break;
- }
- }
-
- cleanup();
-
- tst_exit();
+ TST_EXP_FAIL2(semget(semkey + maxsems, PSEMS, IPC_CREAT | IPC_EXCL | SEM_RA),
+ ENOSPC, "semget(%i, %i, %i)", semkey + maxsems, PSEMS,
+ IPC_CREAT | IPC_EXCL | SEM_RA);
}
-void setup(void)
+static void setup(void)
{
- int sem_q;
+ int res, num;
- tst_sig(NOFORK, DEF_HANDLER, cleanup);
+ semkey = GETIPCKEY();
+ used_cnt = GET_USED_ARRAYS();
+ tst_res(TINFO, "Current environment %d semaphore arrays are already in use",
+ used_cnt);
+ SAFE_FILE_SCANF("/proc/sys/kernel/sem", "%*d %*d %*d %d", &maxsems);
- TEST_PAUSE;
+ /* Prevent timeout due to high semaphore array limit */
+ tst_set_max_runtime(maxsems / 200);
- tst_tmpdir();
-
- while ((sem_q = semget(IPC_PRIVATE, PSEMS, IPC_CREAT | IPC_EXCL)) != -1) {
- sem_id_arr[num_sems++] = sem_q;
- if (num_sems == MAXIDS) {
- tst_brkm(TBROK, cleanup, "The maximum number of "
- "semaphore ID's has been\n\t reached. Please "
- "increase the MAXIDS value in the test.");
- }
- }
+ sem_id_arr = SAFE_MALLOC((maxsems - used_cnt) * sizeof(int));
+ for (num = 0; num < maxsems - used_cnt; num++) {
+ res = semget(semkey + num, PSEMS, IPC_CREAT | IPC_EXCL | SEM_RA);
+ if (res == -1)
+ tst_brk(TBROK | TERRNO, "semget failed unexpectedly");
- if (errno != ENOSPC) {
- tst_brkm(TBROK, cleanup, "Didn't get ENOSPC in test setup"
- " - errno = %d : %s", errno, strerror(errno));
+ sem_id_arr[array_cnt++] = res;
}
+ tst_res(TINFO, "The maximum number of semaphore arrays (%d) has been reached",
+ maxsems);
}
-void cleanup(void)
+static void cleanup(void)
{
- int i;
+ int num;
- for (i = 0; i < num_sems; i++) {
- rm_sema(sem_id_arr[i]);
- }
+ if (!sem_id_arr)
+ return;
+
+ for (num = 0; num < array_cnt; num++)
+ SAFE_SEMCTL(sem_id_arr[num], PSEMS, IPC_RMID);
free(sem_id_arr);
- tst_rmdir();
}
+
+static struct tst_test test = {
+ .needs_tmpdir = 1,
+ .setup = setup,
+ .cleanup = cleanup,
+ .test_all = verify_semget,
+ .save_restore = (const struct tst_path_val[]){
+ {"/proc/sys/kernel/sem", NULL,
+ TST_SR_TCONF_MISSING | TST_SR_SKIP_RO},
+ {}
+ }
+};
diff --git a/testcases/kernel/syscalls/ipc/semget/semget06.c b/testcases/kernel/syscalls/ipc/semget/semget06.c
deleted file mode 100644
index 52297c010..000000000
--- a/testcases/kernel/syscalls/ipc/semget/semget06.c
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- *
- * 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
- * semget06.c
- *
- * DESCRIPTION
- * semget06 - test for EINVAL error
- *
- * ALGORITHM
- * loop if that option was specified
- * call semget() using two different invalid cases - too many and too
- * few primitive semaphores
- * check the errno value
- * issue a PASS message if we get EINVAL
- * otherwise, the tests fails
- * issue a FAIL message
- * call cleanup
- *
- * USAGE: <for command-line>
- * semget06 [-c n] [-e] [-i n] [-I x] [-P x] [-t]
- * where, -c n : Run n copies concurrently.
- * -e : Turn on errno logging.
- * -i n : Execute test n times.
- * -I x : Execute test for x seconds.
- * -P x : Pause for x seconds between iterations.
- * -t : Turn on syscall timing.
- *
- * HISTORY
- * 03/2001 - Written by Wayne Boyer
- *
- * RESTRICTIONS
- * none
- */
-
-#include "ipcsem.h"
-
-char *TCID = "semget06";
-int TST_TOTAL = 2;
-
-#define LARGENUM 1024 * 32
-#define SMALLNUM -1
-
-int sem_id_1 = -1;
-
-int num_sems[] = { LARGENUM, SMALLNUM };
-
-int main(int ac, char **av)
-{
- int lc;
- int i;
-
- tst_parse_opts(ac, av, NULL, NULL);
-
- setup(); /* global setup */
-
- /* The following loop checks looping state if -i option given */
-
- for (lc = 0; TEST_LOOPING(lc); lc++) {
- /* reset tst_count in case we are looping */
- tst_count = 0;
-
- /* loop through the test cases */
-
- for (i = 0; i < TST_TOTAL; i++) {
- TEST(semget(semkey, num_sems[i],
- IPC_CREAT | IPC_EXCL | SEM_RA));
-
- if (TEST_RETURN != -1) {
- sem_id_1 = TEST_RETURN;
- tst_resm(TFAIL, "call succeeded");
- continue;
- }
-
- switch (TEST_ERRNO) {
- case EINVAL:
- tst_resm(TPASS, "expected failure - errno "
- "= %d : %s", TEST_ERRNO,
- strerror(TEST_ERRNO));
- break;
- default:
- tst_resm(TFAIL, "unexpected error - %d : %s",
- TEST_ERRNO, strerror(TEST_ERRNO));
- break;
- }
- }
- }
-
- cleanup();
-
- tst_exit();
-}
-
-/*
- * setup() - performs all the ONE TIME setup for this test.
- */
-void setup(void)
-{
-
- tst_sig(NOFORK, DEF_HANDLER, cleanup);
-
- TEST_PAUSE;
-
- /*
- * Create a temporary directory and cd into it.
- * This helps to ensure that a unique msgkey is created.
- * See libs/libltpipc/libipc.c for more information.
- */
- tst_tmpdir();
-
- /* get an IPC resource key */
- semkey = getipckey();
-}
-
-/*
- * cleanup() - performs all the ONE TIME cleanup for this test at completion
- * or premature exit.
- */
-void cleanup(void)
-{
- /* if it exists, remove the semaphore resource */
- rm_sema(sem_id_1);
-
- tst_rmdir();
-
-}
diff --git a/testcases/kernel/syscalls/ipc/semop/.gitignore b/testcases/kernel/syscalls/ipc/semop/.gitignore
index bb57f08af..cc67b1862 100644
--- a/testcases/kernel/syscalls/ipc/semop/.gitignore
+++ b/testcases/kernel/syscalls/ipc/semop/.gitignore
@@ -1,3 +1,5 @@
/semop01
/semop02
/semop03
+/semop04
+/semop05
diff --git a/testcases/kernel/syscalls/ipc/semop/Makefile b/testcases/kernel/syscalls/ipc/semop/Makefile
index 6b2b26d05..43afffb3f 100644
--- a/testcases/kernel/syscalls/ipc/semop/Makefile
+++ b/testcases/kernel/syscalls/ipc/semop/Makefile
@@ -7,6 +7,9 @@ LTPLIBS = ltpnewipc
include $(top_srcdir)/include/mk/testcases.mk
-LTPLDLIBS = -lltpnewipc
+semop01: LTPLDLIBS = -lltpnewipc
+semop02: LTPLDLIBS = -lltpnewipc
+semop03: LTPLDLIBS = -lltpnewipc
+semop05: LDLIBS += -lpthread
include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/syscalls/ipc/semop/semop04.c b/testcases/kernel/syscalls/ipc/semop/semop04.c
new file mode 100644
index 000000000..1f49e7740
--- /dev/null
+++ b/testcases/kernel/syscalls/ipc/semop/semop04.c
@@ -0,0 +1,93 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) International Business Machines Corp., 2001
+ * Copyright (C) 2003-2023 Linux Test Project, Inc.
+ * Author: 2001 Paul Larson <plars@us.ibm.com>
+ * Modified: 2001 Manoj Iyer <manjo@ausin.ibm.com>
+ */
+
+/*\
+ * [Description]
+ *
+ * Creates a semaphore and two processes. The processes
+ * each go through a loop where they semdown, delay for a
+ * random amount of time, and semup, so they will almost
+ * always be fighting for control of the semaphore.
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include "lapi/sem.h"
+#include "tst_test.h"
+#include "tst_safe_sysv_ipc.h"
+
+#define LOOPS 1000
+#define SEED 123
+
+static void semup(int semid)
+{
+ struct sembuf semops;
+
+ semops.sem_num = 0;
+ semops.sem_op = 1;
+ semops.sem_flg = SEM_UNDO;
+
+ SAFE_SEMOP(semid, &semops, 1);
+}
+
+static void semdown(int semid)
+{
+ struct sembuf semops;
+
+ semops.sem_num = 0;
+ semops.sem_op = -1;
+ semops.sem_flg = SEM_UNDO;
+
+ SAFE_SEMOP(semid, &semops, 1);
+}
+
+static void mainloop(int semid)
+{
+ int i;
+
+ for (i = 0; i < LOOPS; i++) {
+ semdown(semid);
+ usleep(1 + ((100.0 * rand()) / RAND_MAX));
+ semup(semid);
+ }
+}
+
+static void run(void)
+{
+ int semid;
+ union semun semunion;
+ pid_t pid;
+
+ /* set up the semaphore */
+ semid = SAFE_SEMGET((key_t) 9142, 1, 0666 | IPC_CREAT);
+
+ semunion.val = 1;
+
+ SAFE_SEMCTL(semid, 0, SETVAL, semunion);
+
+ tst_res(TINFO, "srand seed is %d", SEED);
+ srand(SEED);
+
+ pid = SAFE_FORK();
+
+ if (pid) {
+ mainloop(semid);
+ tst_reap_children();
+ TST_EXP_POSITIVE(semctl(semid, 0, IPC_RMID, semunion));
+ } else {
+ mainloop(semid);
+ }
+}
+
+static struct tst_test test = {
+ .test_all = run,
+ .forks_child = 1,
+};
diff --git a/testcases/kernel/syscalls/ipc/semop/semop05.c b/testcases/kernel/syscalls/ipc/semop/semop05.c
new file mode 100644
index 000000000..34b714bf0
--- /dev/null
+++ b/testcases/kernel/syscalls/ipc/semop/semop05.c
@@ -0,0 +1,157 @@
+/*
+ *
+ * Copyright (c) International Business Machines Corp., 2002
+ *
+ * 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
+ */
+
+/*
+ * FILE : sem02.c
+ *
+ * DESCRIPTION : The application creates several threads using pthread_create().
+ * One thread performs a semop() with the SEM_UNDO flag set. The change in
+ * sempaphore value performed by that semop should be "undone" only when the
+ * last pthread exits.
+ *
+ * EXPECTED OUTPUT:
+ * Waiter, pid = <pid#>
+ * Poster, pid = <pid#>, posting
+ * Poster posted
+ * Poster exiting
+ * Waiter waiting, pid = <pid#>
+ * Waiter done waiting
+ *
+ * HISTORY:
+ * written by Dave Olien (oliend@us.ibm.com)
+ * 03/06/2002 Robbie Williamson (robbiew@us.ibm.com)
+ * -ported
+ * 07/04/2003 Paul Larson (plars@linuxtestproject.org)
+ * -ported to LTP
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <pthread.h>
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include "lapi/sem.h"
+#include "test.h"
+
+#define KEY IPC_PRIVATE
+
+#define NUMTHREADS 2
+
+void *retval[NUMTHREADS];
+void *waiter(void *);
+void *poster(void *);
+void cleanup(void);
+
+char *TCID = "sem02";
+int TST_TOTAL = 1;
+
+struct sembuf Psembuf = { 0, -1, SEM_UNDO };
+struct sembuf Vsembuf = { 0, 1, SEM_UNDO };
+
+int sem_id;
+int err_ret; /* This is used to determine PASS/FAIL status */
+int main(int argc, char **argv)
+{
+ int i, rc;
+ union semun semunion;
+
+ pthread_t pt[NUMTHREADS];
+ pthread_attr_t attr;
+
+ tst_parse_opts(argc, argv, NULL, NULL);
+ /* Create the semaphore set */
+ sem_id = semget(KEY, 1, 0666 | IPC_CREAT);
+ if (sem_id < 0) {
+ printf("semget failed, errno = %d\n", errno);
+ exit(1);
+ }
+ /* initialize data structure associated to the semaphore */
+ semunion.val = 1;
+ semctl(sem_id, 0, SETVAL, semunion);
+
+ /* setup the attributes of the thread */
+ /* set the scope to be system to make sure the threads compete on a */
+ /* global scale for cpu */
+ pthread_attr_init(&attr);
+ pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
+
+ err_ret = 1; /* Set initial error value to 1 */
+ /* Create the threads */
+ for (i = 0; i < NUMTHREADS; i++) {
+ if (i == 0)
+ rc = pthread_create(&pt[i], &attr, waiter, retval[i]);
+ else
+ rc = pthread_create(&pt[i], &attr, poster, retval[i]);
+ }
+
+ /* Sleep long enough to see that the other threads do what they are supposed to do */
+ sleep(20);
+ semunion.val = 1;
+ semctl(sem_id, 0, IPC_RMID, semunion);
+ if (err_ret == 1)
+ tst_resm(TFAIL, "failed");
+ else
+ tst_resm(TPASS, "passed");
+ cleanup();
+
+ tst_exit();
+}
+
+/* This thread sleeps 10 seconds then waits on the semaphore. As long
+ as someone has posted on the semaphore, and no undo has taken
+ place, the semop should complete and we'll print "Waiter done
+ waiting." */
+void *waiter(void *foo)
+{
+ int pid;
+ pid = getpid();
+
+ tst_resm(TINFO, "Waiter, pid = %d", pid);
+ sleep(10);
+
+ tst_resm(TINFO, "Waiter waiting, pid = %d", pid);
+ semop(sem_id, &Psembuf, 1);
+ tst_resm(TINFO, "Waiter done waiting");
+ err_ret = 0; /* If the message above is displayed, the test is a PASS */
+ pthread_exit(0);
+}
+
+/* This thread immediately posts on the semaphore and then immediately
+ exits. If the *thread* exits, the undo should not happen, and the
+ waiter thread which will start waiting on it in 10 seconds, should
+ still get it. */
+void *poster(void *foo)
+{
+ int pid;
+
+ pid = getpid();
+ tst_resm(TINFO, "Poster, pid = %d, posting", pid);
+ semop(sem_id, &Vsembuf, 1);
+ tst_resm(TINFO, "Poster posted");
+ tst_resm(TINFO, "Poster exiting");
+
+ pthread_exit(0);
+}
+
+void cleanup(void)
+{
+}
diff --git a/testcases/kernel/syscalls/ipc/shmget/shmget02.c b/testcases/kernel/syscalls/ipc/shmget/shmget02.c
index 3788e711f..8168803a5 100644
--- a/testcases/kernel/syscalls/ipc/shmget/shmget02.c
+++ b/testcases/kernel/syscalls/ipc/shmget/shmget02.c
@@ -11,17 +11,17 @@
*
* Test for ENOENT, EEXIST, EINVAL, EACCES, EPERM errors.
*
- * ENOENT - No segment exists for the given key and IPC_CREAT was not specified.
- * EEXIST - the segment exists and IPC_CREAT | IPC_EXCL is given.
- * EINVAL - A new segment was to be created and size is less than SHMMIN or
- * greater than SHMMAX. Or a segment for the given key exists, but size is
- * gran eater than the size of that segment.
- * EACCES - The user does not have permission to access the shared memory segment.
- * EPERM - The SHM_HUGETLB flag was specified, but the caller was not privileged
- * (did not have the CAP_IPC_LOCK capability) and is not a member of the
- * sysctl_hugetlb_shm_group group.
- * ENOMEM - The SHM_HUGETLB flag was specified, the caller was privileged but not
- * have enough hugepage memory space.
+ * - ENOENT - No segment exists for the given key and IPC_CREAT was not specified.
+ * - EEXIST - the segment exists and IPC_CREAT | IPC_EXCL is given.
+ * - EINVAL - A new segment was to be created and size is less than SHMMIN or
+ * greater than SHMMAX. Or a segment for the given key exists, but size is
+ * gran eater than the size of that segment.
+ * - EACCES - The user does not have permission to access the shared memory segment.
+ * - EPERM - The SHM_HUGETLB flag was specified, but the caller was not
+ * privileged (did not have the CAP_IPC_LOCK capability) and is not a member
+ * of the sysctl_hugetlb_shm_group group.
+ * - ENOMEM - The SHM_HUGETLB flag was specified, the caller was privileged but
+ * not have enough hugepage memory space.
*/
#include <errno.h>
@@ -56,7 +56,7 @@ static struct tcase {
{&shmkey1, SHM_SIZE, IPC_EXCL, 0, 0, ENOENT},
{&shmkey, SHM_SIZE, IPC_CREAT | IPC_EXCL, 0, 0, EEXIST},
{&shmkey1, SHMMIN - 1, IPC_CREAT | IPC_EXCL, 0, 0, EINVAL},
- {&shmkey1, SHMMAX + 1, IPC_CREAT | IPC_EXCL, 0, 0, EINVAL},
+ {&shmkey1, 8192 + 1, IPC_CREAT | IPC_EXCL, 0, 0, EINVAL},
{&shmkey, SHM_SIZE * 2, IPC_EXCL, 0, 0, EINVAL},
{&shmkey, SHM_SIZE, SHM_RD, 1, 0, EACCES},
{&shmkey1, SHM_SIZE, IPC_CREAT | SHM_HUGETLB, 0, 1, EPERM},
@@ -149,4 +149,8 @@ static struct tst_test test = {
.test = do_test,
.tcnt = ARRAY_SIZE(tcases),
.hugepages = {TST_NO_HUGEPAGES},
+ .save_restore = (const struct tst_path_val[]) {
+ {"/proc/sys/kernel/shmmax", "8192", TST_SR_TCONF_MISSING | TST_SR_TBROK_RO},
+ {}
+ },
};
diff --git a/testcases/kernel/syscalls/keyctl/keyctl02.c b/testcases/kernel/syscalls/keyctl/keyctl02.c
index 572f34b16..35cc2838d 100644
--- a/testcases/kernel/syscalls/keyctl/keyctl02.c
+++ b/testcases/kernel/syscalls/keyctl/keyctl02.c
@@ -144,6 +144,7 @@ static struct tst_test test = {
.test_all = do_test,
.tags = (const struct tst_tag[]) {
{"linux-git", "b4a1b4f5047e"},
+ {"CVE", "2015-7550"},
{}
}
};
diff --git a/testcases/kernel/syscalls/keyctl/keyctl07.c b/testcases/kernel/syscalls/keyctl/keyctl07.c
index 875ef0bb8..d9e20db5f 100644
--- a/testcases/kernel/syscalls/keyctl/keyctl07.c
+++ b/testcases/kernel/syscalls/keyctl/keyctl07.c
@@ -104,7 +104,7 @@ static struct tst_test test = {
.test_all = do_test,
.forks_child = 1,
.tags = (const struct tst_tag[]) {
- {"CVE", "2017-12912"},
+ {"CVE", "2017-12192"},
{"linux-git", "37863c43b2c6"},
{}
}
diff --git a/testcases/kernel/syscalls/madvise/.gitignore b/testcases/kernel/syscalls/madvise/.gitignore
index f4bfdfefe..722ac3c34 100644
--- a/testcases/kernel/syscalls/madvise/.gitignore
+++ b/testcases/kernel/syscalls/madvise/.gitignore
@@ -7,3 +7,4 @@
/madvise08
/madvise09
/madvise10
+/madvise11
diff --git a/testcases/kernel/syscalls/madvise/Makefile b/testcases/kernel/syscalls/madvise/Makefile
index 044619fb8..78613df11 100644
--- a/testcases/kernel/syscalls/madvise/Makefile
+++ b/testcases/kernel/syscalls/madvise/Makefile
@@ -6,3 +6,5 @@ top_srcdir ?= ../../../..
include $(top_srcdir)/include/mk/testcases.mk
include $(top_srcdir)/include/mk/generic_leaf_target.mk
+
+madvise11: CFLAGS += -pthread
diff --git a/testcases/kernel/syscalls/madvise/madvise01.c b/testcases/kernel/syscalls/madvise/madvise01.c
index 2262bf12d..884c59b0b 100644
--- a/testcases/kernel/syscalls/madvise/madvise01.c
+++ b/testcases/kernel/syscalls/madvise/madvise01.c
@@ -11,7 +11,6 @@
*/
#include <sys/types.h>
-#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/mount.h>
#include <errno.h>
diff --git a/testcases/kernel/syscalls/madvise/madvise02.c b/testcases/kernel/syscalls/madvise/madvise02.c
index 858d67ae2..90c0431c5 100644
--- a/testcases/kernel/syscalls/madvise/madvise02.c
+++ b/testcases/kernel/syscalls/madvise/madvise02.c
@@ -30,7 +30,6 @@
*/
#include <sys/types.h>
-#include <sys/mman.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/time.h>
diff --git a/testcases/kernel/syscalls/madvise/madvise06.c b/testcases/kernel/syscalls/madvise/madvise06.c
index c7967ae6f..be22318ea 100644
--- a/testcases/kernel/syscalls/madvise/madvise06.c
+++ b/testcases/kernel/syscalls/madvise/madvise06.c
@@ -198,7 +198,7 @@ static void test_advice_willneed(void)
meminfo_diag("After madvise");
res = swapcached > swapcached_start + PASS_THRESHOLD_KB;
- tst_res(res ? TPASS : TFAIL,
+ tst_res(res ? TPASS : TINFO,
"%s than %ld Kb were moved to the swap cache",
res ? "more" : "less", PASS_THRESHOLD_KB);
@@ -226,10 +226,15 @@ static void test_advice_willneed(void)
meminfo_diag("After page access");
res = page_fault_num_2 - page_fault_num_1;
- tst_res(res == 0 ? TPASS : TFAIL,
+ tst_res(res == 0 ? TPASS : TINFO,
"%d pages were faulted out of 3 max", res);
SAFE_MUNMAP(target, CHUNK_SZ);
+
+ if (tst_taint_check())
+ tst_res(TFAIL, "Kernel tainted");
+ else
+ tst_res(TPASS, "No kernel taints");
}
static struct tst_test test = {
@@ -237,6 +242,7 @@ static struct tst_test test = {
.setup = setup,
.needs_tmpdir = 1,
.needs_root = 1,
+ .taint_check = TST_TAINT_W | TST_TAINT_D,
.save_restore = (const struct tst_path_val[]) {
{"/proc/sys/vm/swappiness", NULL,
TST_SR_SKIP_MISSING | TST_SR_TCONF_RO},
diff --git a/testcases/kernel/syscalls/madvise/madvise11.c b/testcases/kernel/syscalls/madvise/madvise11.c
new file mode 100644
index 000000000..7a12abf20
--- /dev/null
+++ b/testcases/kernel/syscalls/madvise/madvise11.c
@@ -0,0 +1,442 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2023 Oracle and/or its affiliates.
+ */
+
+/*\
+ * [Description]
+ *
+ * Stress a possible race condition between memory pages allocation
+ * and soft-offline of unrelated pages as explained in the commit:
+ * d4ae9916ea29 (mm: soft-offline: close the race against page allocation)
+ *
+ * Control that soft-offlined pages get correctly replaced: with the
+ * same content and without SIGBUS generation when accessed.
+ */
+
+#include <errno.h>
+#include <mntent.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/klog.h>
+
+#include "tst_test.h"
+#include "tst_safe_pthread.h"
+#include "tst_safe_stdio.h"
+#include "lapi/mmap.h"
+
+#define NUM_LOOPS 5
+#define NUM_PAGES 32
+#define NUM_PAGES_OFFSET 5
+
+/* Needed module to online back memory pages */
+#define HW_MODULE "hwpoison_inject"
+
+static pthread_t *thread_ids;
+static int number_threads;
+static int run_iterations;
+static int maximum_pfns;
+
+static volatile int sigbus_received;
+static pthread_cond_t sigbus_received_cv;
+static pthread_mutex_t sigbus_received_mtx = PTHREAD_MUTEX_INITIALIZER;
+
+static long pagesize;
+static char beginning_tag[BUFSIZ];
+static int hwpoison_probe;
+
+static void my_yield(void)
+{
+ static const struct timespec t0 = { 0, 0 };
+
+ nanosleep(&t0, NULL);
+}
+
+/* a SIGBUS received is a confirmation of test failure */
+static void sigbus_handler(int signum LTP_ATTRIBUTE_UNUSED)
+{
+ pthread_mutex_lock(&sigbus_received_mtx);
+ sigbus_received++;
+ pthread_cond_signal(&sigbus_received_cv);
+ pthread_mutex_unlock(&sigbus_received_mtx);
+ pause();
+}
+
+static void *sigbus_monitor(void *arg LTP_ATTRIBUTE_UNUSED)
+{
+ pthread_mutex_lock(&sigbus_received_mtx);
+ while (!sigbus_received)
+ pthread_cond_wait(&sigbus_received_cv, &sigbus_received_mtx);
+ pthread_mutex_unlock(&sigbus_received_mtx);
+ tst_res(TFAIL, "SIGBUS Received");
+ exit(1);
+}
+
+/*
+ * Allocate a page and write a sentinel value into it.
+ */
+static void *allocate_write(int sentinel)
+{
+ void *p;
+ int *s;
+
+ p = SAFE_MMAP(NULL, pagesize, PROT_READ|PROT_WRITE,
+ MAP_SHARED|MAP_ANONYMOUS, -1, 0);
+ s = (int *)p;
+ *s = sentinel;
+ return p;
+}
+
+/*
+ * Verify and unmap the given page.
+ */
+static int verif_unmap(void *page, int sentinel)
+{
+ int *s = (int *)page;
+
+ if (*s != sentinel) {
+ tst_res(TFAIL, "pid[%d]: fail: bad sentinel value seen: %d expected: %d\n", getpid(), *s, sentinel);
+ return 1;
+ }
+
+ return SAFE_MUNMAP(page, pagesize);
+}
+
+/*
+ * allocate_offline() - Allocate and offline test called per-thread
+ *
+ * This function does the allocation and offline by mmapping an
+ * anonymous page and offlining it.
+ */
+static int allocate_offline(int tnum)
+{
+ int loop;
+
+ for (loop = 0; loop < NUM_LOOPS; loop++) {
+ long *ptrs[NUM_PAGES];
+ int num_alloc;
+ int i;
+
+ for (num_alloc = 0; num_alloc < NUM_PAGES; num_alloc++) {
+
+ ptrs[num_alloc] = allocate_write((tnum << NUM_PAGES_OFFSET) | num_alloc);
+ if (ptrs[num_alloc] == NULL)
+ return -1;
+
+ if (madvise(ptrs[num_alloc], pagesize, MADV_SOFT_OFFLINE) == -1) {
+ if (errno != EINVAL)
+ tst_res(TFAIL | TERRNO, "madvise failed");
+ if (errno == EINVAL)
+ tst_res(TCONF, "madvise() didn't support MADV_SOFT_OFFLINE");
+ return errno;
+ }
+ }
+
+ for (i = 0; i < num_alloc; i++) {
+ if (verif_unmap(ptrs[i], (tnum << NUM_PAGES_OFFSET) | i) != 0)
+ return 1;
+ }
+
+ my_yield();
+ if (!tst_remaining_runtime()) {
+ tst_res(TINFO, "Thread [%d]: Test runtime is over, exiting", tnum);
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static void *alloc_mem(void *threadnum)
+{
+ int err;
+ int tnum = (int)(uintptr_t)threadnum;
+
+ /* waiting for other threads starting */
+ TST_CHECKPOINT_WAIT(0);
+
+ err = allocate_offline(tnum);
+ tst_res(TINFO,
+ "Thread [%d] returned %d, %s.", tnum, err, (err ? "failed" : "succeeded"));
+ return (void *)(uintptr_t) (err ? -1 : 0);
+}
+
+static void stress_alloc_offl(void)
+{
+ int thread_index;
+ int thread_failure = 0;
+ pthread_t sigbus_monitor_t;
+
+ run_iterations++;
+
+ SAFE_PTHREAD_CREATE(&sigbus_monitor_t, NULL, sigbus_monitor, NULL);
+ pthread_detach(sigbus_monitor_t);
+
+ for (thread_index = 0; thread_index < number_threads; thread_index++) {
+ SAFE_PTHREAD_CREATE(&thread_ids[thread_index], NULL, alloc_mem,
+ (void *)(uintptr_t)thread_index);
+ }
+
+ TST_CHECKPOINT_WAKE2(0, number_threads);
+
+ for (thread_index = 0; thread_index < number_threads; thread_index++) {
+ void *status;
+
+ SAFE_PTHREAD_JOIN(thread_ids[thread_index], &status);
+ if ((intptr_t)status != 0) {
+ tst_res(TFAIL, "thread [%d] - exited with errors",
+ thread_index);
+ thread_failure++;
+ }
+ }
+
+ if (thread_failure == 0)
+ tst_res(TPASS, "soft-offline / mmap race still clean");
+}
+
+/*
+ * ------------
+ * Cleanup code:
+ * The idea is to retrieve all the pfn numbers that have been soft-offined
+ * (generating a "Soft offlining pfn 0x..." message in the kernel ring buffer)
+ * by the current test (since a "beginning_tag" message we write when starting).
+ * And to put these pages back online by writing the pfn number to the
+ * <debugfs>/hwpoison/unpoison-pfn special file.
+ * ------------
+ */
+#define OFFLINE_PATTERN "Soft offlining pfn 0x"
+#define OFFLINE_PATTERN_LEN sizeof(OFFLINE_PATTERN)
+
+/* return the pfn if the kmsg msg is a soft-offline indication*/
+static unsigned long parse_kmsg_soft_offlined_pfn(char *line, ssize_t len)
+{
+ char *pos;
+ unsigned long addr = 0UL;
+
+ pos = strstr(line, OFFLINE_PATTERN);
+ if (pos == NULL)
+ return 0UL;
+
+ pos += OFFLINE_PATTERN_LEN-1;
+ if (pos > (line + len))
+ return 0UL;
+
+ addr = strtoul(pos, NULL, 16);
+ if ((addr == ULONG_MAX) && (errno == ERANGE))
+ return 0UL;
+
+ return addr;
+}
+
+/* return the pfns seen in kernel message log */
+static int populate_from_klog(char *begin_tag, unsigned long *pfns, int max)
+{
+ int found = 0, fd, beginning_tag_found = 0;
+ ssize_t sz;
+ unsigned long pfn;
+ char buf[BUFSIZ];
+
+ fd = SAFE_OPEN("/dev/kmsg", O_RDONLY|O_NONBLOCK);
+
+ while (found < max) {
+ sz = read(fd, buf, sizeof(buf));
+ /* kmsg returns EPIPE if record was modified while reading */
+ if (sz < 0 && errno == EPIPE)
+ continue;
+ if (sz <= 0)
+ break;
+ if (!beginning_tag_found) {
+ if (strstr(buf, begin_tag))
+ beginning_tag_found = 1;
+ continue;
+ }
+ pfn = parse_kmsg_soft_offlined_pfn(buf, sz);
+ if (pfn)
+ pfns[found++] = pfn;
+ }
+ SAFE_CLOSE(fd);
+ return found;
+}
+
+/*
+ * Read the given file to search for the key.
+ * Return 1 if the key is found.
+ */
+static int find_in_file(char *path, char *key)
+{
+ char line[4096];
+ int found = 0;
+ FILE *file = SAFE_FOPEN(path, "r");
+
+ while (fgets(line, sizeof(line), file)) {
+ if (strstr(line, key)) {
+ found = 1;
+ break;
+ }
+ }
+ SAFE_FCLOSE(file);
+ return found;
+}
+
+static void unpoison_this_pfn(unsigned long pfn, int fd)
+{
+ char pfn_str[19];
+
+ snprintf(pfn_str, sizeof(pfn_str), "0x%lx", pfn);
+ SAFE_WRITE(0, fd, pfn_str, strlen(pfn_str));
+}
+
+/* Find and open the <debugfs>/hwpoison/unpoison-pfn special file */
+static int open_unpoison_pfn(void)
+{
+ char *added_file_path = "/hwpoison/unpoison-pfn";
+ const char *const cmd_modprobe[] = {"modprobe", HW_MODULE, NULL};
+ char debugfs_fp[4096];
+ struct mntent *mnt;
+ FILE *mntf;
+
+ if (!find_in_file("/proc/modules", HW_MODULE) && tst_check_builtin_driver(HW_MODULE))
+ hwpoison_probe = 1;
+
+ /* probe hwpoison only if it isn't already there */
+ if (hwpoison_probe)
+ SAFE_CMD(cmd_modprobe, NULL, NULL);
+
+ /* debugfs mount point */
+ mntf = setmntent("/proc/mounts", "r");
+ if (!mntf) {
+ tst_brk(TBROK | TERRNO, "Can't open /proc/mounts");
+ return -1;
+ }
+ while ((mnt = getmntent(mntf)) != NULL) {
+ if (strcmp(mnt->mnt_type, "debugfs") == 0) {
+ strcpy(debugfs_fp, mnt->mnt_dir);
+ strcat(debugfs_fp, added_file_path);
+ break;
+ }
+ }
+ endmntent(mntf);
+ if (!mnt)
+ return -1;
+
+ TEST(open(debugfs_fp, O_WRONLY));
+
+ if (TST_RET == -1 && TST_ERR == EPERM && tst_lockdown_enabled() > 0) {
+ tst_res(TINFO,
+ "Cannot restore soft-offlined memory due to lockdown");
+ return TST_RET;
+ }
+
+ if (TST_RET == -1) {
+ tst_brk(TBROK | TTERRNO, "open(%s) failed", debugfs_fp);
+ } else if (TST_RET < 0) {
+ tst_brk(TBROK | TTERRNO, "Invalid open() return value %ld",
+ TST_RET);
+ }
+
+ return TST_RET;
+}
+
+/*
+ * Get all the Offlined PFNs indicated in the dmesg output
+ * starting after the given beginning tag, and request a debugfs
+ * hwpoison/unpoison-pfn for each of them.
+ */
+static void unpoison_pfn(char *begin_tag)
+{
+ unsigned long *pfns;
+ const char *const cmd_rmmod[] = {"rmmod", HW_MODULE, NULL};
+ int found_pfns, fd;
+
+ pfns = SAFE_MALLOC(sizeof(pfns) * maximum_pfns * run_iterations);
+
+ fd = open_unpoison_pfn();
+ if (fd >= 0) {
+ found_pfns = populate_from_klog(begin_tag, pfns, maximum_pfns * run_iterations);
+
+ tst_res(TINFO, "Restore %d Soft-offlined pages", found_pfns);
+ /* unpoison in reverse order */
+ while (found_pfns-- > 0)
+ unpoison_this_pfn(pfns[found_pfns], fd);
+
+ SAFE_CLOSE(fd);
+ }
+ /* remove hwpoison only if we probed it */
+ if (hwpoison_probe)
+ SAFE_CMD(cmd_rmmod, NULL, NULL);
+}
+
+/*
+ * Create and write a beginning tag to the kernel buffer to be used on cleanup
+ * when trying to restore the soft-offlined pages of our test run.
+ */
+static void write_beginning_tag_to_kmsg(void)
+{
+ int fd;
+
+ fd = SAFE_OPEN("/dev/kmsg", O_WRONLY);
+ snprintf(beginning_tag, sizeof(beginning_tag),
+ "Soft-offlining pages test starting (pid: %ld)",
+ (long)getpid());
+ SAFE_WRITE(1, fd, beginning_tag, strlen(beginning_tag));
+ SAFE_CLOSE(fd);
+}
+
+static void setup(void)
+{
+ struct sigaction my_sigaction;
+
+ number_threads = (int)sysconf(_SC_NPROCESSORS_ONLN) * 2;
+ if (number_threads <= 1)
+ number_threads = 2;
+ else if (number_threads > 5)
+ number_threads = 5;
+
+ maximum_pfns = number_threads * NUM_LOOPS * NUM_PAGES;
+ thread_ids = SAFE_MALLOC(sizeof(pthread_t) * number_threads);
+ pagesize = sysconf(_SC_PAGESIZE);
+
+ /* SIGBUS is the main failure criteria */
+ my_sigaction.sa_handler = sigbus_handler;
+ if (sigaction(SIGBUS, &my_sigaction, NULL) == -1)
+ tst_res(TFAIL | TERRNO, "Signal handler attach failed");
+
+ write_beginning_tag_to_kmsg();
+ tst_res(TINFO, "Spawning %d threads, with a total of %d memory pages",
+ number_threads, maximum_pfns);
+}
+
+static void cleanup(void)
+{
+ unpoison_pfn(beginning_tag);
+}
+
+static struct tst_test test = {
+ .needs_root = 1,
+ .needs_drivers = (const char *const []) {
+ HW_MODULE,
+ NULL
+ },
+ .needs_cmds = (const char *[]) {
+ "modprobe",
+ "rmmod",
+ NULL
+ },
+ .needs_kconfigs = (const char *[]) {
+ "CONFIG_MEMORY_FAILURE=y",
+ NULL
+ },
+ .max_runtime = 30,
+ .needs_checkpoints = 1,
+ .setup = setup,
+ .cleanup = cleanup,
+ .test_all = stress_alloc_offl,
+ .tags = (const struct tst_tag[]) {
+ {"linux-git", "d4ae9916ea29"},
+ {}
+ }
+};
diff --git a/testcases/kernel/syscalls/memfd_create/memfd_create02.c b/testcases/kernel/syscalls/memfd_create/memfd_create02.c
index f547e1424..b9ddc0825 100644
--- a/testcases/kernel/syscalls/memfd_create/memfd_create02.c
+++ b/testcases/kernel/syscalls/memfd_create/memfd_create02.c
@@ -13,10 +13,8 @@
#define _GNU_SOURCE
#include <errno.h>
-
-#include <tst_test.h>
-
#include "memfd_create_common.h"
+#include "tst_test.h"
static char buf[2048];
static char term_buf[2048];
diff --git a/testcases/kernel/syscalls/memfd_create/memfd_create04.c b/testcases/kernel/syscalls/memfd_create/memfd_create04.c
index 7b699b218..585f17e16 100644
--- a/testcases/kernel/syscalls/memfd_create/memfd_create04.c
+++ b/testcases/kernel/syscalls/memfd_create/memfd_create04.c
@@ -1,20 +1,23 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
- * Copyright (c) Zilogic Systems Pvt. Ltd., 2018
- * Email: code@zilogic.com
+ * Copyright (c) Zilogic Systems Pvt. Ltd. <code@zilogic.com>, 2018
+ * Copyright (c) Linux Test Project, 2019-2023
*/
-/*
- * Test: Validating memfd_create() with MFD_HUGETLB and MFD_HUGE_x flags.
+/*\
+ * [Description]
+ *
+ * Validating memfd_create() with MFD_HUGETLB and MFD_HUGE_x flags.
*
- * Test cases: Attempt to create files in the hugetlbfs filesystem using
- * different huge page sizes.
+ * Attempt to create files in the hugetlbfs filesystem using different huge page
+ * sizes.
*
- * Test logic: memfd_create() should return non-negative value (fd)
- * if the system supports that particular huge page size.
- * On success, fd is returned.
- * On failure, -1 is returned with ENODEV error.
+ * [Algorithm]
+ *
+ * memfd_create() should return non-negative value (fd) if the system supports
+ * that particular huge page size.
+ * On success, fd is returned. On failure, -1 is returned with ENODEV error.
*/
#define _GNU_SOURCE
@@ -25,8 +28,6 @@
#include <errno.h>
#include <stdio.h>
-#define PATH_HUGEPAGES "/sys/kernel/mm/hugepages"
-
static struct test_flag {
int flag;
char *h_size;
@@ -48,7 +49,7 @@ static void check_hugepage_support(struct test_flag *test_flags)
char pattern[64];
sprintf(pattern, PATH_HUGEPAGES);
- strcat(pattern, "/hugepages-");
+ strcat(pattern, "hugepages-");
strcat(pattern, test_flags->h_size);
if (access(pattern, F_OK))
diff --git a/testcases/kernel/syscalls/mknod/mknod01.c b/testcases/kernel/syscalls/mknod/mknod01.c
index f79e5fa42..7a4d5b43f 100644
--- a/testcases/kernel/syscalls/mknod/mknod01.c
+++ b/testcases/kernel/syscalls/mknod/mknod01.c
@@ -1,123 +1,50 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
- * AUTHOR : William Roske
- * CO-PILOT : Dave Fenner
- *
- * 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.
- *
- * Further, this software is distributed without any warranty that it is
- * free of the rightful claim of any third person regarding infringement
- * or the like. Any license provided herein, whether implied or
- * otherwise, applies only to this software file. Patent licenses, if
- * any, provided herein do not apply to combinations of this program with
- * other software, or any other product whatsoever.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
- * Mountain View, CA 94043, or:
- *
- * http://www.sgi.com
- *
- * For further information regarding this notice, see:
- *
- * http://oss.sgi.com/projects/GenInfo/NoticeExplan/
+ * AUTHOR: William Roske, CO-PILOT: Dave Fenner
+ * Copyright (c) 2023 SUSE LLC Avinesh Kumar <avinesh.kumar@suse.com>
+ */
+
+/*\
+ * [Description]
*
+ * Verify that mknod(2) successfully creates a filesystem node with
+ * various modes.
*/
-#include <unistd.h>
-#include <errno.h>
-#include <string.h>
-#include <signal.h>
-#include <sys/types.h>
-#include <sys/stat.h>
#include <sys/sysmacros.h>
-
-#include "test.h"
-#include "safe_macros.h"
-
-static void setup(void);
-static void cleanup(void);
-
-char *TCID = "mknod01";
+#include "tst_test.h"
#define PATH "test_node"
-int tcases[] = { /* modes to give nodes created (1 per text case) */
- S_IFREG | 0777, /* ordinary file with mode 0777 */
- S_IFIFO | 0777, /* fifo special with mode 0777 */
- S_IFCHR | 0777, /* character special with mode 0777 */
- S_IFBLK | 0777, /* block special with mode 0777 */
+static int tcases[] = {
+ S_IFREG | 0777,
+ S_IFIFO | 0777,
+ S_IFCHR | 0777,
+ S_IFBLK | 0777,
- S_IFREG | 04700, /* ordinary file with mode 04700 (suid) */
- S_IFREG | 02700, /* ordinary file with mode 02700 (sgid) */
- S_IFREG | 06700, /* ordinary file with mode 06700 (sgid & suid) */
+ S_IFREG | 04700,
+ S_IFREG | 02700,
+ S_IFREG | 06700,
};
-int TST_TOTAL = ARRAY_SIZE(tcases);
-int main(int ac, char **av)
+static void run(unsigned int i)
{
- int lc, i;
- dev_t dev;
-
- tst_parse_opts(ac, av, NULL, NULL);
+ dev_t dev = 0;
- setup();
+ if (S_ISCHR(tcases[i]) || S_ISBLK(tcases[i]))
+ dev = makedev(1, 3);
- for (lc = 0; TEST_LOOPING(lc); lc++) {
- tst_count = 0;
-
- for (i = 0; i < TST_TOTAL; i++) {
- /*
- * overlayfs doesn't support mknod char device with
- * major 0 and minor 0, which is known as whiteout_dev
- */
- if (S_ISCHR(tcases[i]))
- dev = makedev(1, 3);
- else
- dev = 0;
- TEST(mknod(PATH, tcases[i], dev));
-
- if (TEST_RETURN == -1) {
- tst_resm(TFAIL,
- "mknod(%s, %#o, %lu) failed, errno=%d : %s",
- PATH, tcases[i], dev, TEST_ERRNO,
- strerror(TEST_ERRNO));
- } else {
- tst_resm(TPASS,
- "mknod(%s, %#o, %lu) returned %ld",
- PATH, tcases[i], dev, TEST_RETURN);
- }
-
- SAFE_UNLINK(cleanup, PATH);
- }
-
- }
-
- cleanup();
- tst_exit();
+ TST_EXP_PASS(mknod(PATH, tcases[i], dev),
+ "mknod(PATH, %o, %ld)",
+ tcases[i], dev);
+ SAFE_UNLINK(PATH);
}
-void setup(void)
-{
- tst_require_root();
- tst_sig(NOFORK, DEF_HANDLER, cleanup);
-
- TEST_PAUSE;
-
- tst_tmpdir();
-}
-
-void cleanup(void)
-{
- tst_rmdir();
-}
+static struct tst_test test = {
+ .test = run,
+ .tcnt = ARRAY_SIZE(tcases),
+ .needs_root = 1,
+ .needs_tmpdir = 1
+};
diff --git a/testcases/kernel/syscalls/mknod/mknod02.c b/testcases/kernel/syscalls/mknod/mknod02.c
index 594473e24..b1885fed1 100644
--- a/testcases/kernel/syscalls/mknod/mknod02.c
+++ b/testcases/kernel/syscalls/mknod/mknod02.c
@@ -1,301 +1,57 @@
+// 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
+ * 07/2001 Ported by Wayne Boyer
+ * Copyright (c) 2023 SUSE LLC Avinesh Kumar <avinesh.kumar@suse.com>
*/
-/*
- * Test Name: mknod02
- *
- * Test Description:
- * Verify that mknod(2) succeeds when used to create a filesystem
- * node with set group-ID bit set on a directory without set group-ID bit set.
- * The node created should have set group-ID bit set and its gid should be
- * equal to that of its parent directory.
- *
- * Expected Result:
- * mknod() should return value 0 on success and node created should have
- * set group-ID bit set, its gid should be equal to that of its parent
- * directory.
- *
- * Algorithm:
- * Setup:
- * Setup signal handling.
- * Create temporary directory.
- * Pause for SIGUSR1 if option specified.
- *
- * Test:
- * Loop if the proper options are given.
- * Execute system call
- * Check return code, if system call failed (return=-1)
- * Log the errno and Issue a FAIL message.
- * Otherwise,
- * Verify the Functionality of system call
- * if successful,
- * Issue Functionality-Pass message.
- * Otherwise,
- * Issue Functionality-Fail message.
- * Cleanup:
- * Print errno log and/or timing stats if options given
- * Delete the temporary directory created.
- *
- * Usage: <for command-line>
- * mknod02 [-c n] [-f] [-i n] [-I x] [-P x] [-t]
- * where, -c n : Run n copies concurrently.
- * -f : Turn off functionality Testing.
- * -i n : Execute test n times.
- * -I x : Execute test for x seconds.
- * -P x : Pause for x seconds between iterations.
- * -t : Turn on syscall timing.
- *
- * HISTORY
- * 07/2001 Ported by Wayne Boyer
- *
- * RESTRICTIONS:
- * This test should be run by 'super-user' (root) only.
+/*\
+ * [Description]
*
+ * Verify that if mknod(2) creates a filesystem node in a directory which
+ * does not have the set-group-ID bit set, new node will not inherit the
+ * group ownership from its parent directory and its group ID will be the
+ * effective group ID of the process.
*/
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <errno.h>
-#include <string.h>
-#include <signal.h>
#include <pwd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include "test.h"
-#include "safe_macros.h"
+#include "tst_test.h"
-#define LTPUSER "nobody"
-#define MODE_RWX S_IFIFO | S_IRWXU | S_IRWXG | S_IRWXO
-#define MODE_SGID S_IFIFO | S_ISGID | S_IRWXU | S_IRWXG | S_IRWXO
-#define DIR_TEMP "testdir_2"
-#define TNODE "tnode_%d"
+#define MODE_DIR 0777
+#define MODE1 0010777
+#define MODE_SGID 02000
-struct stat buf; /* struct. to hold stat(2) o/p contents */
-struct passwd *user1; /* struct. to hold getpwnam(3) o/p contents */
+#define TEMP_DIR "testdir"
+#define TEMP_NODE "testnode"
-char *TCID = "mknod02";
-int TST_TOTAL = 1;
-char node_name[PATH_MAX]; /* buffer to hold node name created */
+static struct stat buf;
+static struct passwd *user_nobody;
+static gid_t gid_nobody;
-gid_t group1_gid, group2_gid, mygid; /* user and process group id's */
-uid_t save_myuid, user1_uid; /* user and process user id's */
-pid_t mypid; /* process id */
-
-void setup(); /* setup function for the test */
-void cleanup(); /* cleanup function for the test */
-
-int main(int ac, char **av)
+static void setup(void)
{
- int lc;
- int fflag;
-
- tst_parse_opts(ac, av, NULL, NULL);
-
- setup();
-
- for (lc = 0; TEST_LOOPING(lc); lc++) {
-
- tst_count = 0;
-
- /*
- * Attempt to create a filesystem node with group-id bit set
- * on a directory without group id bit set such that,
- * the node created by mknod(2) should have group-id (sgid)
- * bit set and node's gid should be equal to that of its
- * parent directory.
- */
- TEST(mknod(node_name, MODE_SGID, 0));
-
- /* Check return code from mknod(2) */
- if (TEST_RETURN == -1) {
- tst_resm(TFAIL,
- "mknod(%s, %#o, 0) failed, errno=%d : %s",
- node_name, MODE_SGID, TEST_ERRNO,
- strerror(TEST_ERRNO));
- continue;
- }
- /* Set the functionality flag */
- fflag = 1;
-
- /* Check for node's creation */
- if (stat(node_name, &buf) < 0) {
- tst_resm(TFAIL, "stat() of %s failed, errno:%d",
- node_name, TEST_ERRNO);
-
- /* unset functionality flag */
- fflag = 0;
- }
-
- /* Verify mode permissions of node */
- if (!(buf.st_mode & S_ISGID)) {
- tst_resm(TFAIL, "%s: Incorrect modes, setgid "
- "bit not set", node_name);
- /* unset flag as functionality fails */
- fflag = 0;
- }
-
- /* Verify group ID of node */
- if (buf.st_gid != mygid) {
- tst_resm(TFAIL, "%s: Incorrect group",
- node_name);
- /* unset flag as functionality fails */
- fflag = 0;
- }
- if (fflag) {
- tst_resm(TPASS, "Functionality of mknod(%s, "
- "%#o, 0) successful",
- node_name, MODE_SGID);
- }
-
- /* Remove the node for the next go `round */
- if (unlink(node_name) == -1) {
- tst_resm(TWARN, "unlink(%s) failed, errno:%d %s",
- node_name, errno, strerror(errno));
- }
- }
+ user_nobody = SAFE_GETPWNAM("nobody");
+ gid_nobody = user_nobody->pw_gid;
- /* Change the directory back to temporary directory */
- SAFE_CHDIR(cleanup, "..");
-
- /*
- * Invoke cleanup() to delete the test directories created
- * in the setup() and exit main().
- */
- cleanup();
-
- tst_exit();
+ SAFE_MKDIR(TEMP_DIR, MODE_DIR);
+ SAFE_CHOWN(TEMP_DIR, -1, gid_nobody);
}
-/*
- * setup(void) - performs all ONE TIME setup for this test.
- * Exit the test program on receipt of unexpected signals.
- * Create a temporary directory used to hold test directories created
- * and change the directory to it.
- * Verify that pid of process executing the test is root.
- * Create a test directory on temporary directory and set the ownership
- * of test directory to ltp user and process.
- * Set the effective uid/gid of the process to that of ltp user.
- */
-void setup(void)
+static void run(void)
{
- tst_require_root();
-
- /* Capture unexpected signals */
- tst_sig(NOFORK, DEF_HANDLER, cleanup);
-
- TEST_PAUSE;
-
- /* Make a temp dir and cd to it */
- tst_tmpdir();
-
- /* fix permissions on the tmpdir */
- if (chmod(".", 0711) != 0) {
- tst_brkm(TBROK, cleanup, "chmod() failed");
- }
-
- /* Save the real user id of the current test process */
- save_myuid = getuid();
-
- /* Save the process id of the current test process */
- mypid = getpid();
-
- /* Get the node name to be created in the test */
- sprintf(node_name, TNODE, mypid);
-
- /* Get the uid/gid of ltpuser */
- if ((user1 = getpwnam(LTPUSER)) == NULL) {
- tst_brkm(TBROK | TERRNO, cleanup,
- "Couldn't determine if %s was in /etc/passwd",
- LTPUSER);
- }
- user1_uid = user1->pw_uid;
- group1_gid = user1->pw_gid;
-
- /* Get the effective group id of the test process */
- group2_gid = getegid();
+ SAFE_CHDIR(TEMP_DIR);
+ TST_EXP_PASS(mknod(TEMP_NODE, MODE1, 0), "mknod(%s, %o, 0)", TEMP_NODE, MODE1);
- /*
- * Create a test directory under temporary directory with the
- * specified mode permissions, with uid/gid set to that of guest
- * user and the test process.
- */
- SAFE_MKDIR(cleanup, DIR_TEMP, MODE_RWX);
- SAFE_CHOWN(cleanup, DIR_TEMP, user1_uid, group2_gid);
+ SAFE_STAT(TEMP_NODE, &buf);
+ TST_EXP_EQ_LI(buf.st_gid, 0);
- /*
- * Verify that test directory created with expected permission modes
- * and ownerships.
- */
- SAFE_STAT(cleanup, DIR_TEMP, &buf);
-
- /* Verify modes of test directory */
- if (buf.st_mode & S_ISGID) {
- tst_brkm(TBROK, cleanup,
- "%s: Incorrect modes, setgid bit set", DIR_TEMP);
- }
-
- /* Verify group ID of test directory */
- if (buf.st_gid != group2_gid) {
- tst_brkm(TBROK, cleanup, "%s: Incorrect group", DIR_TEMP);
- }
-
- /*
- * Set the effective group id and user id of the test process
- * to that of guest user.
- */
- SAFE_SETGID(cleanup, group1_gid);
- if (setreuid(-1, user1_uid) < 0) {
- tst_brkm(TBROK, cleanup,
- "Unable to set process uid to that of ltp user");
- }
-
- /* Save the real group ID of the current process */
- mygid = getgid();
-
- /* Change directory to DIR_TEMP */
- SAFE_CHDIR(cleanup, DIR_TEMP);
+ SAFE_UNLINK(TEMP_NODE);
+ SAFE_CHDIR("..");
}
-/*
- * cleanup() - Performs all ONE TIME cleanup for this test at
- * completion or premature exit.
- * Print test timing stats and errno log if test executed with options.
- * Restore the real/effective user id of the process changed during
- * setup().
- * Remove temporary directory and sub-directories/files under it
- * created during setup().
- * Exit the test program with normal exit code.
- */
-void cleanup(void)
-{
-
- /*
- * Restore the effective uid of the process changed in the
- * setup().
- */
- if (setreuid(-1, save_myuid) < 0) {
- tst_brkm(TBROK, NULL,
- "resetting process real/effective uid failed");
- }
-
- tst_rmdir();
-
-}
+static struct tst_test test = {
+ .setup = setup,
+ .test_all = run,
+ .needs_root = 1,
+ .needs_tmpdir = 1
+};
diff --git a/testcases/kernel/syscalls/mlock/mlock01.c b/testcases/kernel/syscalls/mlock/mlock01.c
index 2338d4d56..0b079f8be 100644
--- a/testcases/kernel/syscalls/mlock/mlock01.c
+++ b/testcases/kernel/syscalls/mlock/mlock01.c
@@ -1,145 +1,52 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
- *
- * Copyright (c) International Business Machines Corp., 2002
- *
- * 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
- * mlock01.c
- *
- * DESCRIPTION
- * Test to see that mlock works
- *$
- * ALGORITHM
- * test 1:
- * Call mlock with various valid addresses and lengths. No
- * error should be returned
- *
- * USAGE: <for command-line>
- * -c n Run n copies concurrently
- * -e Turn on errno logging
- * -f Turn off functional testing
- * -h Show this help screen
- * -i n Execute test n times
- * -I x Execute test for x seconds
- * -p Pause for SIGUSR1 before starting
- * -P x Pause for x seconds between iterations
- * -t Turn on syscall timing
+ * Copyright (c) International Business Machines Corp., 2002
*
* HISTORY
* 06/2002 Written by Paul Larson
- *
- * RESTRICTIONS
- * None
*/
-#include <errno.h>
-#include <unistd.h>
-#include <sys/mman.h>
-#include "test.h"
-void setup();
-void setup1(int);
-void cleanup();
+/*\
+ * [Description]
+ *
+ * Test mlock with various valid addresses and lengths.
+ */
-char *TCID = "mlock01";
-int TST_TOTAL = 4;
+#include <stdlib.h>
+#include "tst_test.h"
-void *addr1;
+static void *addr;
-struct test_case_t {
- void **addr;
+static struct tcase {
+ char *msg;
int len;
- void (*setupfunc) ();
-} TC[] = {
- /* mlock should return ENOMEM when some or all of the address
- * range pointed to by addr and len are not valid mapped pages
- * in the address space of the process
- */
- {
- &addr1, 1, setup1}, {
- &addr1, 1024, setup1}, {
- &addr1, 1024 * 1024, setup1}, {
- &addr1, 1024 * 1024 * 10, setup1}
+} tcases[] = {
+ {"mlock 1 byte", 1},
+ {"mlock 1024 bytes", 1024},
+ {"mlock 1024 * 1024 bytes", 1024 * 1024},
+ {"mlock 1024 * 1024 * 10 bytes", 1024 * 1024 * 10}
};
-#if !defined(UCLINUX)
-
-int main(int ac, char **av)
-{
- int lc, i;
-
- tst_parse_opts(ac, av, NULL, NULL);
-
- setup();
-
- /*
- * FIXME (garrcoop): this should really test out whether or not the
- * process's mappable address space is indeed accessible by the
- * current user, instead of needing to be run by root all the time.
- */
- tst_require_root();
-
- for (lc = 0; TEST_LOOPING(lc); lc++) {
-
- tst_count = 0;
-
- for (i = 0; i < TST_TOTAL; i++) {
-
- if (TC[i].setupfunc != NULL)
- TC[i].setupfunc(TC[i].len);
-
- TEST(mlock(*(TC[i].addr), TC[i].len));
-
- /* I'm confused -- given the description above this
- * should fail as designed, but this application
- * */
- if (TEST_RETURN == -1)
- tst_resm(TFAIL | TTERRNO, "mlock failed");
- else
- tst_resm(TPASS, "mlock passed");
- }
- }
-
- cleanup();
-
- tst_exit();
-}
-
-#else
-
-int main(void)
+static void do_mlock(unsigned int i)
{
- tst_brkm(TCONF, NULL, "test is not available on uClinux");
-}
-
-#endif /* if !defined(UCLINUX) */
+ struct tcase *tc = &tcases[i];
-void setup(void)
-{
- TEST_PAUSE;
+ tst_res(TINFO, "%s", tc->msg);
+ addr = SAFE_MALLOC(tc->len);
+ TST_EXP_PASS(mlock(addr, tc->len), "mlock(%p, %d)", addr, tc->len);
+ free(addr);
+ addr = NULL;
}
-void setup1(int len)
+static void cleanup(void)
{
- addr1 = malloc(len);
- if (addr1 == NULL)
- tst_brkm(TFAIL, cleanup, "malloc failed");
+ if (addr)
+ free(addr);
}
-void cleanup(void)
-{
-}
+static struct tst_test test = {
+ .needs_root = 1,
+ .test = do_mlock,
+ .tcnt = ARRAY_SIZE(tcases),
+ .cleanup = cleanup,
+};
diff --git a/testcases/kernel/syscalls/mlock/mlock02.c b/testcases/kernel/syscalls/mlock/mlock02.c
index 50ee31d1c..921ddeeae 100644
--- a/testcases/kernel/syscalls/mlock/mlock02.c
+++ b/testcases/kernel/syscalls/mlock/mlock02.c
@@ -1,109 +1,46 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
- * Copyright (c) International Business Machines Corp., 2002
- * 06/2002 Written by Paul Larson
+ * Copyright (c) International Business Machines Corp., 2002
*
- * 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
+ * 06/2002 Written by Paul Larson
*/
-/*
- * Test Description:
- * Verify that,
- * 1. mlock() fails with -1 return value and sets errno to ENOMEM,
- * if some of the specified address range does not correspond to
- * mapped pages in the address space of the process.
- * 2. mlock() fails with -1 return value and sets errno to ENOMEM,
- * if (Linux 2.6.9 and later) the caller had a non-zero RLIMIT_MEMLOCK
- * soft resource limit, but tried to lock more memory than the limit
- * permitted. This limit is not enforced if the process is privileged
- * (CAP_IPC_LOCK).
- * 3. mlock() fails with -1 return value and sets errno to EPERM,
- * if (Linux 2.6.9 and later) the caller was not privileged (CAP_IPC_LOCK)
- * and its RLIMIT_MEMLOCK soft resource limit was 0.
+/*\
+ * [Description]
+ *
+ * Test for ENOMEM, EPERM errors.
+ *
+ * 1) mlock(2) fails with ENOMEM if some of the specified address range
+ * does not correspond to mapped pages in the address space of
+ * the process.
+ *
+ * 2) mlock(2) fails with ENOMEM if the caller had a non-zero RLIMIT_MEMLOCK
+ * soft resource limit, but tried to lock more memory than the limit
+ * permitted. This limit is not enforced if the process is
+ * privileged (CAP_IPC_LOCK).
+ *
+ * 3) mlock(2) fails with EPERM if the caller was not privileged (CAP_IPC_LOCK)
+ * and its RLIMIT_MEMLOCK soft resource limit was 0.
*/
-#include <errno.h>
#include <unistd.h>
#include <sys/mman.h>
+#include <sys/types.h>
#include <pwd.h>
-
-#include "test.h"
-#include "safe_macros.h"
-
-char *TCID = "mlock02";
-
-#if !defined(UCLINUX)
-
-static void setup(void);
-static void cleanup(void);
-static void test_enomem1(void);
-static void test_enomem2(void);
-static void test_eperm(void);
-static void mlock_verify(const void *, const size_t, const int);
+#include "tst_test.h"
static size_t len;
static struct rlimit original;
static struct passwd *ltpuser;
-static void (*test_func[])(void) = { test_enomem1, test_enomem2, test_eperm };
-
-int TST_TOTAL = ARRAY_SIZE(test_func);
-
-int main(int ac, char **av)
-{
- int lc, i;
-
- tst_parse_opts(ac, av, NULL, NULL);
-
- setup();
-
- for (lc = 0; TEST_LOOPING(lc); lc++) {
- tst_count = 0;
- for (i = 0; i < TST_TOTAL; i++)
- (*test_func[i])();
- }
-
- cleanup();
- tst_exit();
-}
-
-static void setup(void)
-{
- tst_require_root();
-
- tst_sig(NOFORK, DEF_HANDLER, cleanup);
-
- TEST_PAUSE;
-
- ltpuser = SAFE_GETPWNAM(cleanup, "nobody");
-
- len = getpagesize();
-
- SAFE_GETRLIMIT(cleanup, RLIMIT_MEMLOCK, &original);
-}
-
static void test_enomem1(void)
{
void *addr;
- struct rlimit rl;
- addr = SAFE_MMAP(cleanup, NULL, len, PROT_READ,
+ addr = SAFE_MMAP(NULL, len, PROT_READ,
MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
-
- SAFE_MUNMAP(cleanup, addr, len);
-
- mlock_verify(addr, len, ENOMEM);
+ SAFE_MUNMAP(addr, len);
+ TST_EXP_FAIL(mlock(addr, len), ENOMEM, "mlock(%p, %lu)", addr, len);
}
static void test_enomem2(void)
@@ -113,20 +50,14 @@ static void test_enomem2(void)
rl.rlim_max = len - 1;
rl.rlim_cur = len - 1;
- SAFE_SETRLIMIT(cleanup, RLIMIT_MEMLOCK, &rl);
-
- addr = SAFE_MMAP(cleanup, NULL, len, PROT_READ,
+ SAFE_SETRLIMIT(RLIMIT_MEMLOCK, &rl);
+ addr = SAFE_MMAP(NULL, len, PROT_READ,
MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
-
- SAFE_SETEUID(cleanup, ltpuser->pw_uid);
-
- mlock_verify(addr, len, ENOMEM);
-
- SAFE_SETEUID(cleanup, 0);
-
- SAFE_MUNMAP(cleanup, addr, len);
-
- SAFE_SETRLIMIT(cleanup, RLIMIT_MEMLOCK, &original);
+ SAFE_SETEUID(ltpuser->pw_uid);
+ TST_EXP_FAIL(mlock(addr, len), ENOMEM, "mlock(%p, %lu)", addr, len);
+ SAFE_SETEUID(0);
+ SAFE_MUNMAP(addr, len);
+ SAFE_SETRLIMIT(RLIMIT_MEMLOCK, &original);
}
static void test_eperm(void)
@@ -136,51 +67,32 @@ static void test_eperm(void)
rl.rlim_max = 0;
rl.rlim_cur = 0;
- SAFE_SETRLIMIT(cleanup, RLIMIT_MEMLOCK, &rl);
-
- addr = SAFE_MMAP(cleanup, NULL, len, PROT_READ,
+ SAFE_SETRLIMIT(RLIMIT_MEMLOCK, &rl);
+ addr = SAFE_MMAP(NULL, len, PROT_READ,
MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
-
- SAFE_SETEUID(cleanup, ltpuser->pw_uid);
-
- mlock_verify(addr, len, EPERM);
-
- SAFE_SETEUID(cleanup, 0);
-
- SAFE_MUNMAP(cleanup, addr, len);
-
- SAFE_SETRLIMIT(cleanup, RLIMIT_MEMLOCK, &original);
+ SAFE_SETEUID(ltpuser->pw_uid);
+ TST_EXP_FAIL(mlock(addr, len), EPERM, "mlock(%p, %lu)", addr, len);
+ SAFE_SETEUID(0);
+ SAFE_MUNMAP(addr, len);
+ SAFE_SETRLIMIT(RLIMIT_MEMLOCK, &original);
}
-static void mlock_verify(const void *addr, const size_t len, const int error)
+static void run(void)
{
- TEST(mlock(addr, len));
-
- if (TEST_RETURN != -1) {
- tst_resm(TFAIL, "mlock succeeded unexpectedly");
- return;
- }
-
- if (TEST_ERRNO != error) {
- tst_resm(TFAIL | TTERRNO,
- "mlock didn't fail as expected; expected - %d : %s",
- error, strerror(error));
- } else {
- tst_resm(TPASS | TTERRNO, "mlock failed as expected");
- }
+ test_enomem1();
+ test_enomem2();
+ test_eperm();
}
-static void cleanup(void)
-{
-}
-
-#else
-
-int TST_TOTAL = 1;
-
-int main(void)
+static void setup(void)
{
- tst_brkm(TCONF, NULL, "test is not available on uClinux");
+ ltpuser = SAFE_GETPWNAM("nobody");
+ len = getpagesize();
+ SAFE_GETRLIMIT(RLIMIT_MEMLOCK, &original);
}
-#endif /* if !defined(UCLINUX) */
+static struct tst_test test = {
+ .needs_root = 1,
+ .setup = setup,
+ .test_all = run,
+};
diff --git a/testcases/kernel/syscalls/mlock/mlock03.c b/testcases/kernel/syscalls/mlock/mlock03.c
index 8bc65701c..3700b64b0 100644
--- a/testcases/kernel/syscalls/mlock/mlock03.c
+++ b/testcases/kernel/syscalls/mlock/mlock03.c
@@ -1,5 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0
/*
+ * Copyright (C) 2010 Red Hat, Inc.
+ */
+
+/*\
+ * [Description]
+ *
+ * This case is a regression test on old RHEL5.
+ *
* Stack size mapping is decreased through mlock/munlock call.
+ * See the following url:
+ * https://bugzilla.redhat.com/show_bug.cgi?id=643426
*
* This is to test kernel if it has a problem with shortening [stack]
* mapping through several loops of mlock/munlock of /proc/self/maps.
@@ -11,109 +22,61 @@
* munlock 44KiB bfefa000-bff05000 rw-p 00000000 00:00 0 [stack]
*
* with more iterations - could drop to 0KiB.
- *
- * Copyright (C) 2010 Red Hat, Inc.
- * 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.
- *
- * Further, this software is distributed without any warranty that it
- * is free of the rightful claim of any third person regarding
- * infringement or the like. Any license provided herein, whether
- * implied or otherwise, applies only to this software file. Patent
- * licenses, if any, provided herein do not apply to combinations of
- * this program with other software, or any other product whatsoever.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
*/
+
#include <sys/mman.h>
#include <stdio.h>
#include <string.h>
-#include "test.h"
+#include <pwd.h>
+#include "tst_test.h"
+#include "tst_safe_stdio.h"
#define KB 1024
-char *TCID = "mlock03";
-int TST_TOTAL = 1;
-
-static void setup(void);
-static void cleanup(void);
-
-int main(int argc, char *argv[])
+static void verify_mlock(void)
{
- int lc;
long from, to;
long first = -1, last = -1;
char b[KB];
FILE *fp;
- tst_parse_opts(argc, argv, NULL, NULL);
-
- setup();
+ fp = SAFE_FOPEN("/proc/self/maps", "r");
+ while (!feof(fp)) {
+ if (!fgets(b, KB - 1, fp))
+ break;
+ b[strlen(b) - 1] = '\0';
+ if (sscanf(b, "%lx-%lx", &from, &to) != 2) {
+ tst_brk(TBROK, "parse %s start and end address failed",
+ b);
+ continue;
+ }
- for (lc = 0; TEST_LOOPING(lc); lc++) {
- fp = fopen("/proc/self/maps", "r");
- if (fp == NULL)
- tst_brkm(TBROK | TERRNO, cleanup, "fopen");
- while (!feof(fp)) {
- if (!fgets(b, KB - 1, fp))
- break;
- b[strlen(b) - 1] = '\0';
- sscanf(b, "%lx-%lx", &from, &to);
+ /* Record the initial stack size. */
+ if (strstr(b, "[stack]") != NULL)
+ first = (to - from) / KB;
- /* Record the initial stack size. */
- if (lc == 0 && strstr(b, "[stack]") != NULL)
- first = (to - from) / KB;
+ tst_res(TINFO, "mlock [%lx,%lx]", from, to);
+ if (mlock((const void *)from, to - from) == -1)
+ tst_res(TINFO | TERRNO, "mlock failed");
- switch (lc & 1) {
- case 0:
- if (mlock((const void *)from, to - from) == -1)
- tst_resm(TINFO | TERRNO,
- "mlock failed");
- break;
- case 1:
- if (munlock((void *)from, to - from) == -1)
- tst_resm(TINFO | TERRNO,
- "munlock failed");
- break;
- default:
- break;
- }
- tst_resm(TINFO, "%s from %lx to %0lx",
- (lc & 1) ? "munlock" : "mlock", from, to);
+ tst_res(TINFO, "munlock [%lx,%lx]", from, to);
+ if (munlock((void *)from, to - from) == -1)
+ tst_res(TINFO | TERRNO, "munlock failed");
- /* Record the final stack size. */
- if (strstr(b, "[stack]") != NULL)
- last = (to - from) / KB;
- }
- fclose(fp);
+ /* Record the final stack size. */
+ if (strstr(b, "[stack]") != NULL)
+ last = (to - from) / KB;
}
- tst_resm(TINFO, "starting stack size is %ld", first);
- tst_resm(TINFO, "final stack size is %ld", last);
+ SAFE_FCLOSE(fp);
+
+ tst_res(TINFO, "starting stack size is %ld", first);
+ tst_res(TINFO, "final stack size is %ld", last);
if (last < first)
- tst_resm(TFAIL, "stack size is decreased.");
+ tst_res(TFAIL, "stack size is decreased.");
else
- tst_resm(TPASS, "stack size is not decreased.");
-
- cleanup();
- tst_exit();
+ tst_res(TPASS, "stack size is not decreased.");
}
-void setup(void)
-{
- tst_require_root();
-
- tst_sig(FORK, DEF_HANDLER, cleanup);
- TEST_PAUSE;
-}
-
-void cleanup(void)
-{
-}
+static struct tst_test test = {
+ .test_all = verify_mlock,
+};
diff --git a/testcases/kernel/syscalls/mlock/mlock04.c b/testcases/kernel/syscalls/mlock/mlock04.c
index 8ac884583..f25460ba1 100644
--- a/testcases/kernel/syscalls/mlock/mlock04.c
+++ b/testcases/kernel/syscalls/mlock/mlock04.c
@@ -1,102 +1,68 @@
+// SPDX-License-Identifier: GPL-2.0
/*
- * This is a reproducer copied from one of LKML patch submission,
+ * Copyright (C) 2010 Red Hat, Inc.
+ */
+
+/*\
+ * [Description]
+ *
+ * This is a reproducer copied from one of LKML patch submission
* which subject is
*
* [PATCH] mlock: revert the optimization for dirtying pages and triggering writeback.
+ * url see https://www.spinics.net/lists/kernel/msg1141090.html
*
* "In 5ecfda0, we do some optimization in mlock, but it causes
* a very basic test case(attached below) of mlock to fail. So
* this patch revert it with some tiny modification so that it
* apply successfully with the lastest 38-rc2 kernel."
*
- * Copyright (C) 2010 Red Hat, Inc.
- * 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.
- *
- * Further, this software is distributed without any warranty that it
- * is free of the rightful claim of any third person regarding
- * infringement or the like. Any license provided herein, whether
- * implied or otherwise, applies only to this software file. Patent
- * licenses, if any, provided herein do not apply to combinations of
- * this program with other software, or any other product whatsoever.
+ * This bug was fixed by kernel
+ * commit fdf4c587a7 ("mlock: operate on any regions with protection != PROT_NONE")
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
+ * As this case does, mmaps a file with PROT_WRITE permissions but without
+ * PROT_READ, so attempt to not unnecessarity break COW during mlock ended up
+ * causing mlock to fail with a permission problem on unfixed kernel.
*/
-#include "test.h"
-#include "safe_macros.h"
-#include "config.h"
-
-char *TCID = "mlock04";
-int TST_TOTAL = 1;
#include <sys/mman.h>
#include <stdio.h>
#include <sys/types.h>
-#include <sys/stat.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <sys/types.h>
-
-int fd, file_len = 40960;
-char *testfile = "test_mlock";
+#include "tst_test.h"
+#include "tst_safe_macros.h"
-static void setup(void);
-static void cleanup(void);
+static int fd = -1, file_len = 40960;
+static char *testfile = "test_mlock";
-int main(void)
+static void verify_mlock(void)
{
char *buf;
- int lc;
-
- setup();
-
- for (lc = 0; TEST_LOOPING(lc); lc++) {
- buf = mmap(NULL, file_len, PROT_WRITE, MAP_SHARED, fd, 0);
-
- if (buf == MAP_FAILED)
- tst_brkm(TBROK | TERRNO, cleanup, "mmap");
- if (mlock(buf, file_len) == -1)
- tst_brkm(TBROK | TERRNO, cleanup, "mlock");
-
- tst_resm(TINFO, "locked %d bytes from %p", file_len, buf);
-
- if (munlock(buf, file_len) == -1)
- tst_brkm(TBROK | TERRNO, cleanup, "munlock");
-
- SAFE_MUNMAP(cleanup, buf, file_len);
- }
-
- tst_resm(TPASS, "test succeeded.");
-
- cleanup();
-
- tst_exit();
+ buf = SAFE_MMAP(NULL, file_len, PROT_WRITE, MAP_SHARED, fd, 0);
+ TST_EXP_PASS(mlock(buf, file_len), "mlock(%p, %d)", buf, file_len);
+ SAFE_MUNLOCK(buf, file_len);
+ SAFE_MUNMAP(buf, file_len);
}
static void setup(void)
{
- tst_tmpdir();
-
- fd = SAFE_OPEN(cleanup, testfile, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
-
- SAFE_FTRUNCATE(cleanup, fd, file_len);
-
- TEST_PAUSE;
+ fd = SAFE_OPEN(testfile, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
+ SAFE_FTRUNCATE(fd, file_len);
}
static void cleanup(void)
{
- close(fd);
-
- tst_rmdir();
+ if (fd > -1)
+ SAFE_CLOSE(fd);
}
+
+static struct tst_test test = {
+ .needs_tmpdir = 1,
+ .setup = setup,
+ .cleanup = cleanup,
+ .test_all = verify_mlock,
+ .tags = (const struct tst_tag[]) {
+ {"linux-git", "fdf4c587a793"},
+ {}
+ }
+};
diff --git a/testcases/kernel/syscalls/mmap/.gitignore b/testcases/kernel/syscalls/mmap/.gitignore
index 8811226be..4591fdbb9 100644
--- a/testcases/kernel/syscalls/mmap/.gitignore
+++ b/testcases/kernel/syscalls/mmap/.gitignore
@@ -5,7 +5,6 @@
/mmap04
/mmap05
/mmap06
-/mmap07
/mmap08
/mmap09
/mmap10
@@ -18,3 +17,4 @@
/mmap17
/mmap18
/mmap19
+/mmap20
diff --git a/testcases/kernel/syscalls/mmap/mmap02.c b/testcases/kernel/syscalls/mmap/mmap02.c
index 566cc323a..7ffe61fa3 100644
--- a/testcases/kernel/syscalls/mmap/mmap02.c
+++ b/testcases/kernel/syscalls/mmap/mmap02.c
@@ -1,186 +1,64 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) International Business Machines Corp., 2001
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
- * the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ * 07/2001 Ported by Wayne Boyer
+ * Copyright (c) 2023 SUSE LLC Avinesh Kumar <avinesh.kumar@suse.com>
*/
-/*
- * Test Description:
- * Call mmap() with prot parameter set to PROT_READ and with the file
- * descriptor being open for read, to map a file creating mapped memory
- * with read access. The minimum file permissions should be 0444.
- *
- * The call should succeed to create the mapped region with required
- * attributes.
+/*\
+ * [Description]
*
- * Expected Result:
- * mmap() should succeed returning the address of the mapped region,
- * the mapped region should contain the contents of the mapped file.
- *
- * HISTORY
- * 07/2001 Ported by Wayne Boyer
+ * Verify that, mmap() call with PROT_READ and a file descriptor which is
+ * open for read only, succeeds to map a file creating mapped memory with
+ * read access.
*/
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <errno.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <string.h>
-#include <signal.h>
-#include <sys/stat.h>
-#include <sys/mman.h>
-
-#include "test.h"
-#define TEMPFILE "mmapfile"
-
-char *TCID = "mmap02";
-int TST_TOTAL = 1;
+#include <stdlib.h>
+#include "tst_test.h"
+#define TEMPFILE "mmapfile"
+static ssize_t page_sz;
+static int fd;
static char *addr;
-static char *dummy;
-static size_t page_sz;
-static int fildes;
-
-static void setup(void);
-static void cleanup(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;
-
- /*
- * Call mmap to map the temporary file 'TEMPFILE'
- * with read access.
- */
- errno = 0;
- addr = mmap(0, page_sz, PROT_READ,
- MAP_FILE | MAP_SHARED, fildes, 0);
-
- /* Check for the return value of mmap() */
- if (addr == MAP_FAILED) {
- tst_resm(TFAIL | TERRNO, "mmap of %s failed", TEMPFILE);
- continue;
- }
-
- /*
- * Read the file contents into the dummy
- * string.
- */
- if (read(fildes, dummy, page_sz) < 0) {
- tst_brkm(TFAIL | TERRNO, cleanup,
- "reading %s failed", TEMPFILE);
- }
-
- /*
- * Check whether mapped memory region has
- * the file contents.
- */
- if (memcmp(dummy, addr, page_sz)) {
- tst_resm(TFAIL, "mapped memory area contains "
- "invalid data");
- } else {
- tst_resm(TPASS,
- "Functionality of mmap() successful");
- }
-
- /* Clean up things in case we are looping */
- /* Unmap the mapped memory */
- if (munmap(addr, page_sz) != 0) {
- tst_brkm(TFAIL | TERRNO, cleanup, "munmapping failed");
- }
- }
-
- cleanup();
- tst_exit();
-}
+static char *buf;
static void setup(void)
{
- char *tst_buff;
-
- tst_sig(FORK, DEF_HANDLER, cleanup);
-
- TEST_PAUSE;
-
page_sz = getpagesize();
+ buf = SAFE_MALLOC(page_sz);
+ memset(buf, 'A', page_sz);
- /* Allocate space for the test buffer */
- if ((tst_buff = calloc(page_sz, sizeof(char))) == NULL) {
- tst_brkm(TFAIL, NULL, "calloc failed (tst_buff)");
- }
-
- /* Fill the test buffer with the known data */
- memset(tst_buff, 'A', page_sz);
+ fd = SAFE_OPEN(TEMPFILE, O_RDWR | O_CREAT, 0666);
+ SAFE_WRITE(SAFE_WRITE_ALL, fd, buf, page_sz);
- tst_tmpdir();
-
- /* Creat a temporary file used for mapping */
- if ((fildes = open(TEMPFILE, O_RDWR | O_CREAT, 0666)) < 0) {
- free(tst_buff);
- tst_brkm(TFAIL | TERRNO, cleanup, "opening %s failed",
- TEMPFILE);
- }
-
- /* Write test buffer contents into temporary file */
- if (write(fildes, tst_buff, page_sz) < (int)page_sz) {
- free(tst_buff);
- tst_brkm(TFAIL | TERRNO, cleanup,
- "writing to %s failed", TEMPFILE);
- }
-
- /* Free the memory allocated for test buffer */
- free(tst_buff);
-
- /* Change Mode permissions on Temporary file */
- if (fchmod(fildes, 0444) < 0) {
- tst_brkm(TFAIL | TERRNO, cleanup, "fchmod(%s, 0444) failed",
- TEMPFILE);
- }
-
- /* Close the temporary file */
- if (close(fildes) < 0) {
- tst_brkm(TFAIL | TERRNO, cleanup, "closing %s failed",
- TEMPFILE);
- }
+ SAFE_FCHMOD(fd, 0444);
+ SAFE_CLOSE(fd);
+ fd = SAFE_OPEN(TEMPFILE, O_RDONLY);
+}
- /* Open the temporary file again, - Readonly mode */
- if ((fildes = open(TEMPFILE, O_RDONLY)) < 0) {
- tst_brkm(TFAIL, cleanup, "reopening %s readonly failed",
- TEMPFILE);
- }
+static void run(void)
+{
+ addr = SAFE_MMAP(NULL, page_sz, PROT_READ, MAP_FILE | MAP_SHARED, fd, 0);
- /* Allocate and initialize dummy string of system page size bytes */
- if ((dummy = calloc(page_sz, sizeof(char))) == NULL) {
- tst_brkm(TFAIL, cleanup, "calloc failed (dummy)");
- }
+ if (memcmp(buf, addr, page_sz) == 0)
+ tst_res(TPASS, "mmap() functionality successful");
+ else
+ tst_res(TFAIL, "mapped memory area contains invalid data");
+ SAFE_MUNMAP(addr, page_sz);
}
static void cleanup(void)
{
- close(fildes);
- free(dummy);
- tst_rmdir();
+ if (fd > 0)
+ SAFE_CLOSE(fd);
+
+ free(buf);
}
+
+static struct tst_test test = {
+ .setup = setup,
+ .cleanup = cleanup,
+ .test_all = run,
+ .needs_tmpdir = 1
+};
diff --git a/testcases/kernel/syscalls/mmap/mmap05.c b/testcases/kernel/syscalls/mmap/mmap05.c
index 82f122543..7abddaa9e 100644
--- a/testcases/kernel/syscalls/mmap/mmap05.c
+++ b/testcases/kernel/syscalls/mmap/mmap05.c
@@ -1,205 +1,83 @@
+// 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
+ * 07/2001 Ported by Wayne Boyer
+ * Copyright (c) 2023 SUSE LLC Avinesh Kumar <avinesh.kumar@suse.com>
*/
-/*
- * Test Description:
- * Call mmap() to map a file creating mapped memory with no access under
- * the following conditions -
- * - The prot parameter is set to PROT_NONE
- * - The file descriptor is open for read(any mode other than write)
- * - The minimum file permissions should be 0444.
- *
- * The call should succeed to map the file creating mapped memory with the
- * required attributes.
- *
- * Expected Result:
- * mmap() should succeed returning the address of the mapped region,
- * and an attempt to access the contents of the mapped region should give
- * rise to the signal SIGSEGV.
+/*\
+ * [Description]
*
- * HISTORY
- * 07/2001 Ported by Wayne Boyer
+ * Verify that, mmap() call with 'PROT_NONE' and a file descriptor which is
+ * open for read and write, succeeds to map the file creating mapped memory,
+ * but any attempt to access the contents of the mapped region causes the
+ * SIGSEGV signal.
*/
-#include <stdio.h>
+
#include <stdlib.h>
-#include <sys/types.h>
-#include <errno.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <string.h>
-#include <signal.h>
-#include <sys/stat.h>
-#include <sys/mman.h>
#include <setjmp.h>
+#include "tst_test.h"
-#include "test.h"
-
-#define TEMPFILE "mmapfile"
-
-char *TCID = "mmap05";
-int TST_TOTAL = 1;
-
+#define TEMPFILE "mmapfile"
static size_t page_sz;
static volatile char *addr;
-static int fildes;
-static volatile int pass = 0;
+static int fd;
+static volatile int sig_flag;
static sigjmp_buf env;
-static void setup(void);
-static void cleanup(void);
-static void sig_handler(int sig);
-
-int main(int ac, char **av)
+static void sig_handler(int sig)
{
- int lc;
- char file_content;
-
- tst_parse_opts(ac, av, NULL, NULL);
-
- setup();
-
- for (lc = 0; TEST_LOOPING(lc); lc++) {
-
- tst_count = 0;
-
- /*
- * Call mmap to map the temporary file 'TEMPFILE'
- * with no access.
- */
- errno = 0;
- addr = mmap(0, page_sz, PROT_NONE,
- MAP_FILE | MAP_SHARED, fildes, 0);
- TEST_ERRNO = errno;
-
- /* Check for the return value of mmap() */
- if (addr == MAP_FAILED) {
- tst_resm(TFAIL | TERRNO, "mmap() failed on %s",
- TEMPFILE);
- continue;
- }
-
- /*
- * Try to access the mapped region. This should
- * generate a SIGSEGV which will be caught below.
- *
- * This is wrapped by the sigsetjmp() call that will
- * take care of restoring the program's context in an
- * elegant way in conjunction with the call to
- * siglongjmp() in the signal handler.
- */
- if (sigsetjmp(env, 1) == 0) {
- file_content = addr[0];
- }
-
- if (pass) {
- tst_resm(TPASS, "Got SIGSEGV as expected");
- } else {
- tst_resm(TFAIL, "Mapped memory region with NO "
- "access is accessible");
- }
-
- /* Unmap mapped memory and reset pass in case we are looping */
- if (munmap((void *)addr, page_sz) != 0) {
- tst_brkm(TFAIL | TERRNO, cleanup, "munmap failed");
- }
- pass = 0;
-
+ if (sig == SIGSEGV) {
+ sig_flag = 1;
+ siglongjmp(env, 1);
}
-
- cleanup();
- tst_exit();
}
static void setup(void)
{
- char *tst_buff;
-
- tst_sig(NOFORK, sig_handler, cleanup);
+ char *buf;
- TEST_PAUSE;
+ SAFE_SIGNAL(SIGSEGV, sig_handler);
page_sz = getpagesize();
+ buf = SAFE_MALLOC(page_sz);
+ memset(buf, 'A', page_sz);
- /* Allocate space for the test buffer */
- if ((tst_buff = calloc(page_sz, sizeof(char))) == NULL) {
- tst_brkm(TFAIL, NULL, "calloc failed (tst_buff)");
- }
-
- /* Fill the test buffer with the known data */
- memset(tst_buff, 'A', page_sz);
-
- tst_tmpdir();
-
- /* Creat a temporary file used for mapping */
- if ((fildes = open(TEMPFILE, O_WRONLY | O_CREAT, 0666)) < 0) {
- free(tst_buff);
- tst_brkm(TFAIL | TERRNO, cleanup, "opening %s failed",
- TEMPFILE);
- }
+ fd = SAFE_OPEN(TEMPFILE, O_RDWR | O_CREAT, 0666);
+ SAFE_WRITE(SAFE_WRITE_ALL, fd, buf, page_sz);
+ free(buf);
+}
- /* Write test buffer contents into temporary file */
- if (write(fildes, tst_buff, page_sz) != (int)page_sz) {
- free(tst_buff);
- tst_brkm(TFAIL, cleanup, "writing to %s failed", TEMPFILE);
+static void run(void)
+{
+ addr = mmap(NULL, page_sz, PROT_NONE, MAP_FILE | MAP_SHARED, fd, 0);
+ if (addr == MAP_FAILED) {
+ tst_res(TFAIL | TERRNO, "mmap() of %s failed", TEMPFILE);
+ return;
}
- /* Free the memory allocated for test buffer */
- free(tst_buff);
+ if (sigsetjmp(env, 1) == 0)
+ tst_res(TINFO, "Trying to access mapped region: %c", addr[0]);
- /* Make sure proper permissions set on file */
- if (fchmod(fildes, 0444) < 0) {
- tst_brkm(TFAIL | TERRNO, cleanup, "fchmod of %s failed",
- TEMPFILE);
- }
+ if (sig_flag)
+ tst_res(TPASS, "Received SIGSEGV signal as expected");
+ else
+ tst_res(TFAIL, "SIGSEGV signal not received");
- /* Close the temporary file opened for write */
- if (close(fildes) < 0) {
- tst_brkm(TFAIL | TERRNO, cleanup, "closing %s failed",
- TEMPFILE);
- }
+ SAFE_MUNMAP((char *)addr, page_sz);
- /* Open the temporary file again for reading */
- if ((fildes = open(TEMPFILE, O_RDONLY)) < 0) {
- tst_brkm(TFAIL | TERRNO, cleanup, "opening %s readonly failed",
- TEMPFILE);
- }
-}
-
-/*
- * sig_handler() - Signal Catching function.
- * This function gets executed when the test process receives
- * the signal SIGSEGV while trying to access the contents of memory which
- * is not accessible.
- */
-static void sig_handler(int sig)
-{
- if (sig == SIGSEGV) {
- /* set the global variable and jump back */
- pass = 1;
- siglongjmp(env, 1);
- } else {
- tst_brkm(TBROK, cleanup, "received an unexpected signal: %d",
- sig);
- }
+ sig_flag = 0;
}
static void cleanup(void)
{
- close(fildes);
- tst_rmdir();
+ if (fd > 0)
+ SAFE_CLOSE(fd);
}
+
+static struct tst_test test = {
+ .setup = setup,
+ .cleanup = cleanup,
+ .test_all = run,
+ .needs_tmpdir = 1
+};
diff --git a/testcases/kernel/syscalls/mmap/mmap06.c b/testcases/kernel/syscalls/mmap/mmap06.c
index fb7c49257..615743fa7 100644
--- a/testcases/kernel/syscalls/mmap/mmap06.c
+++ b/testcases/kernel/syscalls/mmap/mmap06.c
@@ -1,143 +1,83 @@
+// 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
+ * 07/2001 Ported by Wayne Boyer
+ * Copyright (c) 2023 SUSE LLC Avinesh Kumar <avinesh.kumar@suse.com>
*/
-/*
- * Test Description:
- * Call mmap() to map a file creating a mapped region with read access
- * under the following conditions -
- * - The prot parameter is set to PROT_READ
- * - The file descriptor is open for writing.
+/*\
+ * [Description]
*
- * The call should fail to map the file.
+ * Verify that, mmap() call fails with errno:
*
- * Expected Result:
- * mmap() should fail returning -1 and errno should get set to EACCES.
- *
- * HISTORY
- * 07/2001 Ported by Wayne Boyer
+ * - EACCES, when a file mapping is requested but the file descriptor is not open for reading.
+ * - EINVAL, when length argument is 0.
+ * - EINVAL, when flags contains none of MAP_PRIVATE, MAP_SHARED, or MAP_SHARED_VALIDATE.
*/
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <errno.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <string.h>
-#include <signal.h>
-#include <sys/stat.h>
-#include <sys/mman.h>
-
-#include "test.h"
-
-#define TEMPFILE "mmapfile"
-char *TCID = "mmap06";
-int TST_TOTAL = 1;
+#include <stdlib.h>
+#include "tst_test.h"
+#define MMAPSIZE 1024
+#define TEMPFILE "mmapfile"
static size_t page_sz;
-static char *addr;
-static int fildes;
-
-static void setup(void);
-static void cleanup(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;
-
- /*
- * Call mmap to map the temporary file 'TEMPFILE'
- * with read access.
- */
- errno = 0;
- addr = mmap(0, page_sz, PROT_READ,
- MAP_FILE | MAP_SHARED, fildes, 0);
- TEST_ERRNO = errno;
-
- /* Check for the return value of mmap() */
- if (addr != MAP_FAILED) {
- tst_resm(TFAIL | TERRNO,
- "mmap() returned invalid value, expected: %p",
- MAP_FAILED);
- /* Unmap the mapped memory */
- if (munmap(addr, page_sz) != 0) {
- tst_resm(TBROK, "munmap() failed");
- cleanup();
- }
- continue;
- }
- if (TEST_ERRNO == EACCES) {
- tst_resm(TPASS, "mmap failed with EACCES");
- } else {
- tst_resm(TFAIL | TERRNO,
- "mmap failed with unexpected errno");
- }
- }
- cleanup();
- tst_exit();
-
-}
+static int fd;
+
+static struct tcase {
+ size_t length;
+ int prot;
+ int flags;
+ int exp_errno;
+} tcases[] = {
+ {MMAPSIZE, PROT_WRITE, MAP_FILE | MAP_PRIVATE, EACCES},
+ {MMAPSIZE, PROT_WRITE, MAP_FILE | MAP_SHARED, EACCES},
+ {MMAPSIZE, PROT_READ, MAP_FILE | MAP_PRIVATE, EACCES},
+ {MMAPSIZE, PROT_READ, MAP_FILE | MAP_SHARED, EACCES},
+ {MMAPSIZE, PROT_READ | PROT_WRITE, MAP_FILE | MAP_PRIVATE, EACCES},
+ {MMAPSIZE, PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, EACCES},
+ {0, PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, EINVAL},
+ {MMAPSIZE, PROT_READ | PROT_WRITE, MAP_FILE, EINVAL}
+};
static void setup(void)
{
- char *tst_buff;
-
- tst_sig(NOFORK, DEF_HANDLER, cleanup);
-
- TEST_PAUSE;
+ char *buf;
page_sz = getpagesize();
+ buf = SAFE_MALLOC(page_sz);
+ memset(buf, 'A', page_sz);
- /* Allocate space for the test buffer */
- if ((tst_buff = calloc(page_sz, sizeof(char))) == NULL) {
- tst_brkm(TFAIL, NULL, "calloc() failed (tst_buff)");
- }
+ fd = SAFE_OPEN(TEMPFILE, O_WRONLY | O_CREAT, 0666);
+ SAFE_WRITE(SAFE_WRITE_ALL, fd, buf, page_sz);
+ free(buf);
+}
- /* Fill the test buffer with the known data */
- memset(tst_buff, 'A', page_sz);
+static void run(unsigned int i)
+{
+ struct tcase *tc = &tcases[i];
- tst_tmpdir();
+ TESTPTR(mmap(NULL, tc->length, tc->prot, tc->flags, fd, 0));
- /* Creat a temporary file used for mapping */
- if ((fildes = open(TEMPFILE, O_WRONLY | O_CREAT, 0666)) < 0) {
- free(tst_buff);
- tst_brkm(TFAIL, cleanup, "opening %s failed", TEMPFILE);
+ if (TST_RET_PTR != MAP_FAILED) {
+ tst_res(TFAIL, "mmap() was successful unexpectedly");
+ SAFE_MUNMAP(TST_RET_PTR, MMAPSIZE);
+ } else if (TST_ERR == tc->exp_errno) {
+ tst_res(TPASS | TERRNO, "mmap() failed with");
+ } else {
+ tst_res(TFAIL | TERRNO, "mmap() failed unexpectedly");
}
-
- /* Write test buffer contents into temporary file */
- if (write(fildes, tst_buff, page_sz) < (ssize_t)page_sz) {
- free(tst_buff);
- tst_brkm(TFAIL, cleanup, "writing to %s failed", TEMPFILE);
- }
-
- free(tst_buff);
}
static void cleanup(void)
{
- close(fildes);
- tst_rmdir();
+ if (fd > 0)
+ SAFE_CLOSE(fd);
}
+
+static struct tst_test test = {
+ .setup = setup,
+ .cleanup = cleanup,
+ .test = run,
+ .tcnt = ARRAY_SIZE(tcases),
+ .needs_tmpdir = 1
+};
diff --git a/testcases/kernel/syscalls/mmap/mmap07.c b/testcases/kernel/syscalls/mmap/mmap07.c
deleted file mode 100644
index 682e527aa..000000000
--- a/testcases/kernel/syscalls/mmap/mmap07.c
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * 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
- */
-
-/*
- * Test Description:
- * Call mmap() to map a file creating a mapped region with read access
- * under the following conditions -
- * - The prot parameter is set to PROT_WRITE
- * - The file descriptor is open for writing.
- * - The flags parameter has MAP_PRIVATE set.
- *
- * The call should fail to map the file.
- *
- * Expected Result:
- * mmap() should fail returning -1 and errno should get set to EACCES.
- *
- * HISTORY
- * 07/2001 Ported by Wayne Boyer
- */
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <errno.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <string.h>
-#include <signal.h>
-#include <sys/stat.h>
-#include <sys/mman.h>
-
-#include "test.h"
-
-#define TEMPFILE "mmapfile"
-
-char *TCID = "mmap07";
-int TST_TOTAL = 1;
-
-static size_t page_sz;
-static char *addr;
-static int fildes;
-
-static void setup(void);
-static void cleanup(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;
-
- /*
- * Call mmap to map the temporary file 'TEMPFILE'
- * with write access.
- */
- errno = 0;
- addr = mmap(0, page_sz, PROT_WRITE,
- MAP_FILE | MAP_PRIVATE, fildes, 0);
- TEST_ERRNO = errno;
-
- /* Check for the return value of mmap() */
- if (addr != MAP_FAILED) {
- tst_resm(TFAIL | TERRNO,
- "mmap() returned invalid value, expected: %p",
- MAP_FAILED);
- /* Unmap the mapped memory */
- if (munmap(addr, page_sz) != 0) {
- tst_resm(TBROK, "munmap() failed");
- cleanup();
- }
- continue;
- }
- if (TEST_ERRNO == EACCES) {
- tst_resm(TPASS, "mmap failed with EACCES");
- } else {
- tst_resm(TFAIL | TERRNO,
- "mmap failed with unexpected errno");
- }
-
- }
- cleanup();
- tst_exit();
-
-}
-
-static void setup(void)
-{
- char *tst_buff;
-
- tst_sig(NOFORK, DEF_HANDLER, cleanup);
-
- TEST_PAUSE;
-
- page_sz = getpagesize();
-
- /* Allocate space for the test buffer */
- if ((tst_buff = calloc(page_sz, sizeof(char))) == NULL) {
- tst_brkm(TFAIL, NULL,
- "calloc() failed to allocate space for tst_buff");
- }
-
- /* Fill the test buffer with the known data */
- memset(tst_buff, 'A', page_sz);
-
- tst_tmpdir();
-
- /* Creat a temporary file used for mapping */
- if ((fildes = open(TEMPFILE, O_WRONLY | O_CREAT, 0666)) < 0) {
- free(tst_buff);
- tst_brkm(TFAIL, cleanup, "open() on %s failed", TEMPFILE);
- }
-
- /* Write test buffer contents into temporary file */
- if (write(fildes, tst_buff, page_sz) < (int)page_sz) {
- free(tst_buff);
- tst_brkm(TFAIL, cleanup, "writing to %s failed", TEMPFILE);
- }
-
- free(tst_buff);
-}
-
-static void cleanup(void)
-{
- close(fildes);
- tst_rmdir();
-}
diff --git a/testcases/kernel/syscalls/mmap/mmap08.c b/testcases/kernel/syscalls/mmap/mmap08.c
index f2daf45a3..5c9fd782c 100644
--- a/testcases/kernel/syscalls/mmap/mmap08.c
+++ b/testcases/kernel/syscalls/mmap/mmap08.c
@@ -1,142 +1,53 @@
+// 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
+ * 07/2001 Ported by Wayne Boyer
+ * Copyright (c) 2023 SUSE LLC Avinesh Kumar <avinesh.kumar@suse.com>
*/
-/*
- * Test Description:
- * Verify that mmap() fails to map a file creating a mapped region
- * when the file specified by file descriptor is not valid.
- *
- * Expected Result:
- * mmap() should fail returning -1 and errno should get set to EBADF.
+/*\
+ * [Description]
*
- * HISTORY
- * 07/2001 Ported by Wayne Boyer
+ * verify that, mmap() calls fails with errno EBADF when a file mapping
+ * is requested but the fd is not a valid file descriptor.
*/
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <errno.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <string.h>
-#include <signal.h>
-#include <sys/stat.h>
-#include <sys/mman.h>
-
-#include "test.h"
-#define TEMPFILE "mmapfile"
-
-char *TCID = "mmap08";
-int TST_TOTAL = 1;
+#include <stdlib.h>
+#include "tst_test.h"
+#define TEMPFILE "mmapfile"
static size_t page_sz;
-static char *addr;
-static int fildes;
+static int fd;
-static void setup(void);
-static void cleanup(void);
-
-int main(int ac, char **av)
+static void setup(void)
{
- int lc;
-
- tst_parse_opts(ac, av, NULL, NULL);
-
- setup();
-
- for (lc = 0; TEST_LOOPING(lc); lc++) {
-
- tst_count = 0;
-
- /*
- * Call mmap to map the temporary file 'TEMPFILE'
- * which is already closed. so, fildes is not valid.
- */
- errno = 0;
- addr = mmap(0, page_sz, PROT_WRITE,
- MAP_FILE | MAP_SHARED, fildes, 0);
- TEST_ERRNO = errno;
-
- /* Check for the return value of mmap() */
- if (addr != MAP_FAILED) {
- tst_resm(TFAIL, "mmap() didn't fail (%p != %p)",
- addr, MAP_FAILED);
- /* Unmap the mapped memory */
- if (munmap(addr, page_sz) != 0) {
- tst_brkm(TBROK, cleanup, "munmap() failed");
- }
- continue;
- }
- if (TEST_ERRNO == EBADF) {
- tst_resm(TPASS, "mmap failed with EBADF");
- } else {
- tst_resm(TFAIL | TERRNO,
- "mmap failed with an invalid errno");
- }
- }
-
- cleanup();
- tst_exit();
+ fd = SAFE_OPEN(TEMPFILE, O_RDWR | O_CREAT, 0666);
+ SAFE_CLOSE(fd);
}
-static void setup(void)
+static void run(void)
{
- char *tst_buff;
-
- tst_sig(NOFORK, DEF_HANDLER, cleanup);
-
- TEST_PAUSE;
-
- page_sz = getpagesize();
-
- if ((tst_buff = calloc(page_sz, sizeof(char))) == NULL) {
- tst_brkm(TFAIL, NULL,
- "calloc() failed to allocate space for tst_buff");
- }
-
- /* Fill the test buffer with the known data */
- memset(tst_buff, 'A', page_sz);
-
- tst_tmpdir();
-
- /* Creat a temporary file used for mapping */
- if ((fildes = open(TEMPFILE, O_WRONLY | O_CREAT, 0666)) < 0) {
- free(tst_buff);
- tst_brkm(TFAIL, cleanup, "opening %s failed", TEMPFILE);
- }
-
- /* Write test buffer contents into temporary file */
- if (write(fildes, tst_buff, page_sz) != (int)page_sz) {
- free(tst_buff);
- tst_brkm(TFAIL, cleanup, "writing to %s failed", TEMPFILE);
- }
-
- /* Free the memory allocated for test buffer */
- free(tst_buff);
-
- /* Close the temporary file opened for writing */
- if (close(fildes) < 0) {
- tst_brkm(TFAIL, cleanup, "closing %s failed", TEMPFILE);
+ TESTPTR(mmap(NULL, page_sz, PROT_WRITE, MAP_FILE | MAP_SHARED, fd, 0));
+
+ if (TST_RET_PTR != MAP_FAILED) {
+ tst_res(TFAIL, "mmap() passed unexpectedly");
+ SAFE_MUNMAP(TST_RET_PTR, page_sz);
+ } else if (TST_ERR == EBADF) {
+ tst_res(TPASS, "mmap() failed with EBADF");
+ } else {
+ tst_res(TFAIL | TERRNO, "mmap() failed with an invalid errno");
}
}
static void cleanup(void)
{
- tst_rmdir();
+ if (fd > 0)
+ SAFE_CLOSE(fd);
}
+
+static struct tst_test test = {
+ .setup = setup,
+ .cleanup = cleanup,
+ .test_all = run,
+ .needs_tmpdir = 1
+};
diff --git a/testcases/kernel/syscalls/mmap/mmap17.c b/testcases/kernel/syscalls/mmap/mmap17.c
index a8136a0b2..39703fbd3 100644
--- a/testcases/kernel/syscalls/mmap/mmap17.c
+++ b/testcases/kernel/syscalls/mmap/mmap17.c
@@ -17,7 +17,6 @@
#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
-#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
diff --git a/testcases/kernel/syscalls/mmap/mmap20.c b/testcases/kernel/syscalls/mmap/mmap20.c
new file mode 100644
index 000000000..02d150e45
--- /dev/null
+++ b/testcases/kernel/syscalls/mmap/mmap20.c
@@ -0,0 +1,64 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2023 Paulson Raja L <paulson@zilogic.com>
+ */
+
+/*\
+ * [Description]
+ *
+ * Test mmap(2) with MAP_SHARED_VALIDATE flag.
+ *
+ * Test expected EOPNOTSUPP errno when testing mmap(2) with MAP_SHARED_VALIDATE
+ * flag and invalid flag.
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include "tst_test.h"
+#include "lapi/mmap.h"
+
+#define TEST_FILE "file_to_mmap"
+#define TEST_FILE_SIZE 1024
+#define INVALID_FLAG (1 << 10)
+
+static int fd = -1;
+static void *addr;
+
+static void setup(void)
+{
+ fd = SAFE_OPEN(TEST_FILE, O_CREAT | O_RDWR, 0600);
+
+ if (tst_fill_file(TEST_FILE, 'a', TEST_FILE_SIZE, 1))
+ tst_brk(TBROK, "Could not fill the testfile");
+}
+
+static void cleanup(void)
+{
+ if (fd > -1)
+ SAFE_CLOSE(fd);
+
+ if (addr && addr != MAP_FAILED)
+ SAFE_MUNMAP(addr, TEST_FILE_SIZE);
+}
+
+static void test_mmap(void)
+{
+ addr = mmap(NULL, TEST_FILE_SIZE, PROT_READ | PROT_WRITE,
+ INVALID_FLAG | MAP_SHARED_VALIDATE, fd, 0);
+
+ if (addr != MAP_FAILED)
+ tst_res(TFAIL | TERRNO, "mmap() is successful, but it should have failed");
+ else if (errno == EOPNOTSUPP)
+ tst_res(TPASS, "mmap() failed with errno set to EOPNOTSUPP");
+ else
+ tst_res(TFAIL | TERRNO, "mmap() failed with unexpected error");
+}
+
+static struct tst_test test = {
+ .min_kver = "4.15",
+ .setup = setup,
+ .cleanup = cleanup,
+ .test_all = test_mmap,
+ .needs_tmpdir = 1,
+};
diff --git a/testcases/kernel/syscalls/mount/.gitignore b/testcases/kernel/syscalls/mount/.gitignore
index f92600d36..80885dbf0 100644
--- a/testcases/kernel/syscalls/mount/.gitignore
+++ b/testcases/kernel/syscalls/mount/.gitignore
@@ -5,3 +5,4 @@
/mount04
/mount05
/mount06
+/mount07
diff --git a/testcases/kernel/syscalls/mount/mount03.c b/testcases/kernel/syscalls/mount/mount03.c
index 60f9963da..98d5933b7 100644
--- a/testcases/kernel/syscalls/mount/mount03.c
+++ b/testcases/kernel/syscalls/mount/mount03.c
@@ -122,7 +122,7 @@ static void test_file_dir_noatime(int update_fatime, int update_datime)
SAFE_CLOSEDIR(test_dir);
dir_atime = dir_st.st_atime;
- sleep(1);
+ usleep(1001000);
SAFE_READ(0, otfd, readbuf, sizeof(readbuf));
SAFE_FSTAT(otfd, &st);
diff --git a/testcases/kernel/syscalls/mount/mount07.c b/testcases/kernel/syscalls/mount/mount07.c
new file mode 100644
index 000000000..eb3fb55a0
--- /dev/null
+++ b/testcases/kernel/syscalls/mount/mount07.c
@@ -0,0 +1,177 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2023 FUJITSU LIMITED. All rights reserved.
+ * Author: Yang Xu <xuyang2018.jy@cn.fujitsu.com>
+ */
+
+/*\
+ * [Description]
+ *
+ * It is a basic test for MS_NOSYMFOLLOW mount option and is copied
+ * from kernel selftests nosymfollow-test.c.
+ *
+ * It tests to make sure that symlink traversal fails with ELOOP when
+ * 'nosymfollow' is set, but symbolic links can still be created, and
+ * readlink(2) and realpath(3) still work properly. It also verifies
+ * that statfs(2) correctly returns ST_NOSYMFOLLOW.
+ */
+
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/mount.h>
+#include <stdbool.h>
+#include "tst_test.h"
+#include "lapi/mount.h"
+
+#ifndef ST_NOSYMFOLLOW
+# define ST_NOSYMFOLLOW 0x2000
+#endif
+
+#define MNTPOINT "mntpoint"
+
+static char test_file[PATH_MAX];
+static char link_file[PATH_MAX];
+static char temp_link_file[PATH_MAX];
+static int flag;
+
+static void setup_symlink(void)
+{
+ int fd;
+
+ fd = SAFE_CREAT(test_file, O_RDWR);
+ SAFE_SYMLINK(test_file, link_file);
+ SAFE_CLOSE(fd);
+ flag = 1;
+}
+
+static void test_link_traversal(bool nosymfollow)
+{
+ if (nosymfollow) {
+ TST_EXP_FAIL2(open(link_file, 0, O_RDWR), ELOOP,
+ "open(%s, 0, O_RDWR)", link_file);
+ } else {
+ TST_EXP_FD(open(link_file, 0, O_RDWR));
+ }
+
+ if (TST_RET > 0)
+ SAFE_CLOSE(TST_RET);
+}
+
+static void test_readlink(void)
+{
+ char buf[4096];
+
+ memset(buf, 0, 4096);
+ TST_EXP_POSITIVE(readlink(link_file, buf, sizeof(buf)),
+ "readlink(%s, buf, %ld)", link_file, sizeof(buf));
+ if (strcmp(buf, test_file) != 0) {
+ tst_res(TFAIL, "readlink strcmp failed, %s, %s",
+ buf, test_file);
+ } else {
+ tst_res(TPASS, "readlink strcmp succeeded");
+ }
+}
+
+static void test_realpath(void)
+{
+ TESTPTR(realpath(link_file, NULL));
+
+ if (!TST_RET_PTR) {
+ tst_res(TFAIL | TERRNO, "realpath failed");
+ return;
+ }
+
+ if (strcmp(TST_RET_PTR, test_file) != 0) {
+ tst_res(TFAIL, "realpath strcmp failed, %s, %s",
+ (char *)TST_RET_PTR, test_file);
+ } else {
+ tst_res(TPASS, "realpath strcmp succeeded");
+ }
+}
+
+static void test_cycle_link(void)
+{
+ TST_EXP_PASS(symlink(test_file, temp_link_file), "symlink(%s, %s)",
+ test_file, temp_link_file);
+ TST_EXP_PASS(unlink(temp_link_file));
+}
+
+static void test_statfs(bool nosymfollow)
+{
+ struct statfs buf;
+
+ SAFE_STATFS(MNTPOINT, &buf);
+ if (buf.f_flags & ST_NOSYMFOLLOW) {
+ tst_res(nosymfollow ? TPASS : TFAIL, "ST_NOSYMFOLLOW set on %s",
+ MNTPOINT);
+ } else {
+ tst_res(nosymfollow ? TFAIL : TPASS, "ST_NOSYMFOLLOW not set on %s",
+ MNTPOINT);
+ }
+}
+
+static void setup(void)
+{
+ char *tmpdir = tst_get_tmpdir();
+
+ snprintf(test_file, PATH_MAX, "%s/%s/test_file", tst_get_tmpdir(),
+ MNTPOINT);
+ snprintf(link_file, PATH_MAX, "%s/%s/link_file", tst_get_tmpdir(),
+ MNTPOINT);
+ snprintf(temp_link_file, PATH_MAX, "%s/%s/temp_link_file",
+ tst_get_tmpdir(), MNTPOINT);
+ free(tmpdir);
+}
+
+static void cleanup(void)
+{
+ if (tst_is_mounted(MNTPOINT))
+ SAFE_UMOUNT(MNTPOINT);
+}
+
+static void run_tests(bool nosymfollow)
+{
+ test_link_traversal(nosymfollow);
+ test_readlink();
+ test_realpath();
+ test_cycle_link();
+ test_statfs(nosymfollow);
+}
+
+static void run(void)
+{
+ tst_res(TINFO, "Testing behaviour when not setting MS_NOSYMFOLLOW");
+
+ TST_EXP_PASS_SILENT(mount(tst_device->dev, MNTPOINT, tst_device->fs_type,
+ 0, NULL));
+ if (!flag || !strcmp(tst_device->fs_type, "tmpfs"))
+ setup_symlink();
+ run_tests(false);
+
+ tst_res(TINFO, "Testing behaviour when setting MS_NOSYMFOLLOW");
+ TST_EXP_PASS_SILENT(mount(tst_device->dev, MNTPOINT, tst_device->fs_type,
+ MS_REMOUNT | MS_NOSYMFOLLOW, NULL));
+ run_tests(true);
+
+ SAFE_UMOUNT(MNTPOINT);
+}
+
+static struct tst_test test = {
+ .test_all = run,
+ .setup = setup,
+ .cleanup = cleanup,
+ .forks_child = 1,
+ .needs_root = 1,
+ .min_kver = "5.10",
+ .format_device = 1,
+ .mntpoint = MNTPOINT,
+ .all_filesystems = 1,
+ .skip_filesystems = (const char *const []){
+ "exfat",
+ "vfat",
+ "ntfs",
+ NULL
+ },
+};
diff --git a/testcases/kernel/syscalls/mount_setattr/mount_setattr01.c b/testcases/kernel/syscalls/mount_setattr/mount_setattr01.c
index 83746b878..e500df28e 100644
--- a/testcases/kernel/syscalls/mount_setattr/mount_setattr01.c
+++ b/testcases/kernel/syscalls/mount_setattr/mount_setattr01.c
@@ -32,7 +32,6 @@
#include <sys/statvfs.h>
#include "tst_test.h"
#include "lapi/fsmount.h"
-#include "lapi/stat.h"
#define MNTPOINT "mntpoint"
#define OT_MNTPOINT "ot_mntpoint"
diff --git a/testcases/kernel/syscalls/mprotect/.gitignore b/testcases/kernel/syscalls/mprotect/.gitignore
index 9571ffd43..929c3b3a2 100644
--- a/testcases/kernel/syscalls/mprotect/.gitignore
+++ b/testcases/kernel/syscalls/mprotect/.gitignore
@@ -2,3 +2,4 @@
/mprotect02
/mprotect03
/mprotect04
+/mprotect05
diff --git a/testcases/kernel/syscalls/mprotect/mprotect05.c b/testcases/kernel/syscalls/mprotect/mprotect05.c
new file mode 100644
index 000000000..2b15f5beb
--- /dev/null
+++ b/testcases/kernel/syscalls/mprotect/mprotect05.c
@@ -0,0 +1,69 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2023 Oracle and/or its affiliates. All Rights Reserved.
+ * Author: Liam R. Howlett <liam.howlett@oracle.com>
+ */
+
+/*\
+ * [Description]
+ *
+ * Testcase to check the mprotect(2) system call split and merge.
+ *
+ * https://bugzilla.kernel.org/show_bug.cgi?id=217061
+ *
+ */
+
+#include "tst_test.h"
+
+#define TEST_FILE "mprotect05-testfile"
+
+static int fd;
+static char *addr = MAP_FAILED;
+static unsigned long pagesize;
+static unsigned long fullsize;
+
+static void setup(void)
+{
+ pagesize = getpagesize();
+ fullsize = 5 * pagesize;
+}
+
+static void run(void)
+{
+ fd = SAFE_OPEN(TEST_FILE, O_RDWR | O_CREAT, 0777);
+ addr = SAFE_MMAP(0, fullsize, PROT_READ, MAP_SHARED, fd, 0);
+
+ if (mprotect(addr + pagesize, pagesize, PROT_EXEC))
+ tst_res(TFAIL | TERRNO, "mprotect failed to exec");
+
+ if (mprotect(addr + 3 * pagesize, pagesize, PROT_WRITE))
+ tst_res(TFAIL | TERRNO, "mprotect failed to write");
+
+ if (mprotect(addr + pagesize, pagesize * 4, PROT_READ))
+ tst_res(TFAIL | TERRNO, "mprotect failed to read");
+
+ SAFE_MUNMAP(addr, fullsize);
+ SAFE_CLOSE(fd);
+ addr = MAP_FAILED;
+ SAFE_UNLINK(TEST_FILE);
+ tst_res(TPASS, "test passed");
+}
+
+static void cleanup(void)
+{
+ if (addr != MAP_FAILED) {
+ SAFE_MUNMAP(addr, fullsize);
+ SAFE_CLOSE(fd);
+ }
+}
+
+static struct tst_test test = {
+ .test_all = run,
+ .setup = setup,
+ .cleanup = cleanup,
+ .needs_tmpdir = 1,
+ .tags = (const struct tst_tag[]) {
+ {"linux-git", "2fcd07b7ccd5"},
+ {}
+ },
+};
diff --git a/testcases/kernel/syscalls/mq_notify/.gitignore b/testcases/kernel/syscalls/mq_notify/.gitignore
index cca05a7fa..3f9403c05 100644
--- a/testcases/kernel/syscalls/mq_notify/.gitignore
+++ b/testcases/kernel/syscalls/mq_notify/.gitignore
@@ -1,2 +1,3 @@
/mq_notify01
/mq_notify02
+/mq_notify03
diff --git a/testcases/kernel/syscalls/mq_notify/mq_notify02.c b/testcases/kernel/syscalls/mq_notify/mq_notify02.c
index 3109fe345..d979a4e9d 100644
--- a/testcases/kernel/syscalls/mq_notify/mq_notify02.c
+++ b/testcases/kernel/syscalls/mq_notify/mq_notify02.c
@@ -1,91 +1,36 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* 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.
+ * Author: Zeng Linggang <zenglg.jy@cn.fujitsu.com>
+ * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
*/
-/*
- * ALGORITHM
- * test 1:
- * sevp->sigev_notify = -1, EINVAL should be returned.
- * test 2:
- * sevp->sigev_notify = SIGEV_SIGNAL and sevp->sigev_signo > _NSG,
- * EINVAL should be returned.
+
+/*\
+ * [Description]
+ *
+ * This test verifies that mq_notify() fails with EINVAL when invalid input
+ * arguments are given.
*/
-#include <errno.h>
#include <mqueue.h>
-#include "test.h"
-
-char *TCID = "mq_notify02";
-static void setup(void);
-static void cleanup(void);
+#include "tst_test.h"
static struct test_case_t {
struct sigevent sevp;
int exp_errno;
-} test_cases[] = {
+} tcase[] = {
{{.sigev_notify = -1}, EINVAL},
- {{.sigev_notify = SIGEV_SIGNAL, .sigev_signo = _NSIG+1}, EINVAL},
+ {{.sigev_notify = SIGEV_SIGNAL, .sigev_signo = _NSIG + 1}, EINVAL},
};
-int TST_TOTAL = ARRAY_SIZE(test_cases);
-static void mq_notify_verify(struct test_case_t *);
-
-int main(int argc, char **argv)
-{
- int lc;
- int i;
-
- tst_parse_opts(argc, argv, NULL, NULL);
-
- setup();
-
- for (lc = 0; TEST_LOOPING(lc); lc++) {
- tst_count = 0;
- for (i = 0; i < TST_TOTAL; i++)
- mq_notify_verify(&test_cases[i]);
- }
- cleanup();
- tst_exit();
-}
-
-static void setup(void)
+static void run(unsigned int i)
{
- tst_sig(NOFORK, DEF_HANDLER, cleanup);
+ struct test_case_t *test = &tcase[i];
- TEST_PAUSE;
+ TST_EXP_FAIL(mq_notify(0, &(test->sevp)), test->exp_errno);
}
-static void mq_notify_verify(struct test_case_t *test)
-{
- TEST(mq_notify(0, &(test->sevp)));
-
- if (TEST_RETURN != -1) {
- tst_resm(TFAIL, "mq_notify() succeeded unexpectedly");
- return;
- }
-
- if (TEST_ERRNO == test->exp_errno) {
- tst_resm(TPASS | TTERRNO, "mq_notify failed as expected");
- } else if (TEST_ERRNO == ENOSYS) {
- tst_resm(TCONF | TTERRNO, "mq_notify not available");
- } else {
- tst_resm(TFAIL | TTERRNO,
- "mq_notify failed unexpectedly; expected: %d - %s",
- test->exp_errno, strerror(test->exp_errno));
- }
-}
-
-static void cleanup(void)
-{
-}
+static struct tst_test test = {
+ .tcnt = ARRAY_SIZE(tcase),
+ .test = run,
+};
diff --git a/testcases/kernel/syscalls/mq_notify/mq_notify03.c b/testcases/kernel/syscalls/mq_notify/mq_notify03.c
new file mode 100644
index 000000000..bf6898cd8
--- /dev/null
+++ b/testcases/kernel/syscalls/mq_notify/mq_notify03.c
@@ -0,0 +1,99 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) The GNU Toolchain Authors.
+ * Copyright (c) 2023 Wei Gao <wegao@suse.com>
+ *
+ */
+
+/*\
+ * [Description]
+ *
+ * Test for NULL pointer dereference in mq_notify(CVE-2021-38604)
+ *
+ * References links:
+ * - https://sourceware.org/bugzilla/show_bug.cgi?id=28213
+ */
+
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <mqueue.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include "tst_test.h"
+#include "tst_safe_posix_ipc.h"
+
+static mqd_t m = -1;
+static const char msg[] = "hello";
+
+static void try_null_dereference_cb(union sigval sv)
+{
+ char buf[sizeof(msg)];
+
+ (void)sv;
+
+ TST_EXP_VAL((size_t) mq_receive(m, buf, sizeof(buf), NULL),
+ sizeof(buf));
+ TST_EXP_PASS(memcmp(buf, msg, sizeof(buf)));
+
+ exit(0);
+}
+
+static void try_null_dereference(void)
+{
+ struct sigevent sev;
+
+ memset(&sev, '\0', sizeof(sev));
+ sev.sigev_notify = SIGEV_THREAD;
+ sev.sigev_notify_function = try_null_dereference_cb;
+
+ /* Step 1: Register & unregister notifier.
+ * Helper thread should receive NOTIFY_REMOVED notification.
+ * In a vulnerable version of glibc, NULL pointer dereference follows.
+ */
+ TST_EXP_PASS(mq_notify(m, &sev));
+ TST_EXP_PASS(mq_notify(m, NULL));
+
+ /* Step 2: Once again, register notification.
+ * Try to send one message.
+ * Test is considered successful, if the callback does exit (0).
+ */
+ TST_EXP_PASS(mq_notify(m, &sev));
+ TST_EXP_PASS(mq_send(m, msg, sizeof(msg), 1));
+
+ /* Wait... */
+ pause();
+}
+
+static void do_test(void)
+{
+ static const char m_name[] = "/ltp_mq_notify03";
+ struct mq_attr m_attr;
+
+ memset(&m_attr, '\0', sizeof(m_attr));
+ m_attr.mq_maxmsg = 1;
+ m_attr.mq_msgsize = sizeof(msg);
+
+ m = SAFE_MQ_OPEN(m_name,
+ O_RDWR | O_CREAT | O_EXCL,
+ 0600,
+ &m_attr);
+
+ TST_EXP_PASS(mq_unlink(m_name));
+
+ try_null_dereference();
+}
+
+
+static struct tst_test test = {
+ .test_all = do_test,
+ .tags = (const struct tst_tag[]) {
+ {"glibc-git", "b805aebd42"},
+ {"CVE", "2021-38604"},
+ {}
+ },
+ .needs_root = 1,
+};
diff --git a/testcases/kernel/syscalls/mremap/.gitignore b/testcases/kernel/syscalls/mremap/.gitignore
index 833e1b883..ec15a19cd 100644
--- a/testcases/kernel/syscalls/mremap/.gitignore
+++ b/testcases/kernel/syscalls/mremap/.gitignore
@@ -3,3 +3,4 @@
/mremap03
/mremap04
/mremap05
+/mremap06
diff --git a/testcases/kernel/syscalls/mremap/mremap06.c b/testcases/kernel/syscalls/mremap/mremap06.c
new file mode 100644
index 000000000..a19262750
--- /dev/null
+++ b/testcases/kernel/syscalls/mremap/mremap06.c
@@ -0,0 +1,134 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2023 SUSE LLC
+ * Author: Vlastimil Babka <vbabka@suse.cz>
+ * https://bugzilla.suse.com/attachment.cgi?id=867254
+ * LTP port: Petr Vorel <pvorel@suse.cz>
+ */
+
+/*\
+ * [Description]
+ *
+ * Bug reproducer for 7e7757876f25 ("mm/mremap: fix vm_pgoff in vma_merge() case 3")
+ */
+
+#define _GNU_SOURCE
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+
+#include "tst_test.h"
+#include "tst_safe_macros.h"
+
+#define NUM_PAGES 3
+
+static int fd;
+static char *buf, *buf2;
+static int page_size, mmap_size, mremap_size;
+
+static struct tcase {
+ size_t incompatible;
+ const char *desc;
+} tcases[] = {
+ {
+ .desc = "all pages with compatible mapping",
+ },
+ {
+ .incompatible = 3,
+ .desc = "third page's mapping incompatible",
+ },
+ {
+ .incompatible = 1,
+ .desc = "first page's mapping incompatible",
+ },
+};
+
+static int check_pages(void)
+{
+ int fail = 0, i;
+ char val;
+
+ for (i = 0; i < (int)ARRAY_SIZE(tcases); i++) {
+ val = buf[i * page_size];
+ if (val != 0x30 + i) {
+ tst_res(TFAIL, "page %d wrong value %d (0x%x)", i, val - 0x30, val);
+ fail = 1;
+ }
+ }
+
+ return fail;
+}
+
+static void do_test(unsigned int n)
+{
+ struct tcase *tc = &tcases[n];
+ int ret;
+
+ tst_res(TINFO, "%s", tc->desc);
+
+ buf = SAFE_MMAP(0, mmap_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+
+ buf2 = mremap(buf + page_size, page_size, page_size,
+ MREMAP_MAYMOVE|MREMAP_FIXED, buf + mremap_size);
+ if (buf2 == MAP_FAILED)
+ tst_brk(TBROK, "mremap() failed");
+
+ if (tc->incompatible) {
+ ret = mprotect(buf + (tc->incompatible-1)*page_size, page_size, PROT_READ);
+ if (ret == -1)
+ tst_brk(TBROK, "mprotect() failed");
+ }
+
+ buf2 = mremap(buf + mremap_size, page_size, page_size,
+ MREMAP_MAYMOVE|MREMAP_FIXED, buf + page_size);
+ if (buf2 == MAP_FAILED)
+ tst_brk(TBROK, "mremap() failed");
+
+ if (!check_pages())
+ tst_res(TPASS, "mmap/mremap work properly");
+
+ SAFE_MUNMAP(buf, mremap_size);
+}
+
+static void setup(void)
+{
+ int ret, i;
+
+ page_size = getpagesize();
+ mmap_size = (NUM_PAGES+1) * page_size;
+ mremap_size = NUM_PAGES * page_size;
+
+ fd = SAFE_OPEN("testfile", O_CREAT | O_RDWR | O_TRUNC, 0600);
+
+ ret = fallocate(fd, 0, 0, mmap_size);
+ if (ret == -1)
+ tst_brk(TBROK, "fallocate() failed");
+
+ buf = SAFE_MMAP(0, mmap_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+
+ for (i = 0; i < (int)ARRAY_SIZE(tcases)+1; i++)
+ buf[i*page_size] = 0x30 + i;
+
+ /* clear the page tables */
+ SAFE_MUNMAP(buf, mmap_size);
+}
+
+static void cleanup(void)
+{
+ if (fd > 0)
+ SAFE_CLOSE(fd);
+}
+
+static struct tst_test test = {
+ .setup = setup,
+ .cleanup = cleanup,
+ .test = do_test,
+ .needs_tmpdir = 1,
+ .tcnt = ARRAY_SIZE(tcases),
+ .tags = (struct tst_tag[]) {
+ {"linux-git", "7e7757876f25"},
+ {}
+ },
+};
diff --git a/testcases/kernel/syscalls/msync/msync01.c b/testcases/kernel/syscalls/msync/msync01.c
index 3a5a48ee5..3c57ebb99 100644
--- a/testcases/kernel/syscalls/msync/msync01.c
+++ b/testcases/kernel/syscalls/msync/msync01.c
@@ -25,7 +25,7 @@
* of, or all of a mapped region.
*
* Expected Result:
- * msync() should succeed with a return value of 0, and succesfully
+ * msync() should succeed with a return value of 0, and successfully
* synchronize the memory region. Data read from mapped region should be
* the same as the initialized data.
*
diff --git a/testcases/kernel/syscalls/munlock/munlock01.c b/testcases/kernel/syscalls/munlock/munlock01.c
index 8a52f032d..31d749e66 100644
--- a/testcases/kernel/syscalls/munlock/munlock01.c
+++ b/testcases/kernel/syscalls/munlock/munlock01.c
@@ -1,162 +1,51 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) Wipro Technologies Ltd, 2002. All Rights Reserved.
- *
- * 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; if not, write the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ * AUTHOR: Nirmala Devi Dhanasekar <nirmala.devi@wipro.com>
*/
-/**************************************************************************
- *
- * TEST IDENTIFIER : munlock01
- *
- * EXECUTED BY : root / superuser
- *
- * TEST TITLE : Basic test for munlock(2)
- *
- * TEST CASE TOTAL : 4
- *
- * AUTHOR : Nirmala Devi Dhanasekar <nirmala.devi@wipro.com>
- *
- * SIGNALS
- * Uses SIGUSR1 to pause before test if option set.
- * (See the parse_opts(3) man page).
- *
- * DESCRIPTION
- * This is a Phase I test for the munlock(2) system call.
- * It is intended to provide a limited exposure of the system call.
- *
- * Setup:
- * Setup signal handling.
- * Pause for SIGUSR1 if option specified.
- *
- * Test:
- * Loop if the proper options are given.
- * Execute system call
- * Check return code, if system call failed (return=-1)
- * Log the errno and Issue a FAIL message.
- * Otherwise, Issue a PASS message.
- *
- * Cleanup:
- * Print errno log and/or timing stats if options given
- *
- * USAGE: <for command-line>
- * munlock01 [-c n] [-e] [-i n] [-I x] [-p x] [-t]
- * where, -c n : Run n copies concurrently
- * -e : Turn on errno logging.
- * -h : Show this help screen
- * -i n : Execute test n times.
- * -I x : Execute test for x seconds.
- * -p : Pause for SIGUSR1 before starting
- * -P x : Pause for x seconds between iterations.
- * -t : Turn on syscall timing.
- *
- * RESTRICTIONS
- * Must be root/superuser to run it.
- *****************************************************************************/
-
-#include <errno.h>
-#include <unistd.h>
-#include <sys/mman.h>
-#include "test.h"
-void setup();
-void setup1(int);
-void cleanup();
+/*\
+ * [Description]
+ *
+ * Test munlock with various valid addresses and lengths.
+ */
-char *TCID = "munlock01";
-int TST_TOTAL = 4;
+#include <stdlib.h>
+#include "tst_test.h"
-void *addr1;
+static void *addr;
-struct test_case_t {
- void **addr;
+static struct tcase {
+ char *msg;
int len;
- void (*setupfunc) ();
-} TC[] = {
- {
- &addr1, 1, setup1}, {
- &addr1, 1024, setup1}, {
- &addr1, 1024 * 1024, setup1}, {
- &addr1, 1024 * 1024 * 10, setup1}
+} tcases[] = {
+ {"munlock 1 byte", 1},
+ {"munlock 1024 bytes", 1024},
+ {"munlock 1024 * 1024 bytes", 1024 * 1024},
+ {"munlock 1024 * 1024 * 10 bytes", 1024 * 1024 * 10}
};
-int main(int ac, char **av)
-{
- int lc, i;
-
- tst_parse_opts(ac, av, NULL, NULL);
-
- setup();
-
- /* check looping state */
- for (lc = 0; TEST_LOOPING(lc); lc++) {
-
- tst_count = 0;
-
- for (i = 0; i < TST_TOTAL; i++) {
-
- if (TC[i].setupfunc != NULL)
- TC[i].setupfunc(i);
-
- TEST(munlock(*(TC[i].addr), TC[i].len));
-
- /* check return code */
- if (TEST_RETURN == -1) {
- tst_resm(TFAIL | TTERRNO,
- "mlock(%p, %d) Failed with "
- "return=%ld", TC[i].addr, TC[i].len,
- TEST_RETURN);
- } else {
- tst_resm(TPASS, "test %d passed length = %d",
- i, TC[i].len);
- }
- }
- }
-
- /* cleanup and exit */
- cleanup();
-
- tst_exit();
-}
-
-void setup1(int i)
+static void verify_munlock(unsigned int i)
{
- addr1 = malloc(TC[i].len);
- if (addr1 == NULL)
- tst_brkm(TFAIL, cleanup, "malloc failed");
- TEST(mlock(*(TC[i].addr), TC[i].len));
-
- /* check return code */
- if (TEST_RETURN == -1) {
- tst_brkm(TFAIL | TTERRNO, cleanup,
- "mlock(%p, %d) Failed with return=%ld", TC[i].addr,
- TC[i].len, TEST_RETURN);
- }
+ struct tcase *tc = &tcases[i];
+
+ tst_res(TINFO, "%s", tc->msg);
+ addr = SAFE_MALLOC(tc->len);
+ SAFE_MLOCK(addr, tc->len);
+ TST_EXP_PASS(munlock(addr, tc->len), "munlock(%p, %d)", addr, tc->len);
+ free(addr);
+ addr = NULL;
}
-/* setup() - performs all ONE TIME setup for this test. */
-void setup(void)
+static void cleanup(void)
{
- tst_require_root();
-
- tst_sig(NOFORK, DEF_HANDLER, cleanup);
-
- TEST_PAUSE;
+ if (addr)
+ free(addr);
}
-/*
- * cleanup() - performs all ONE TIME cleanup for this test at
- * completion or premature exit.
- */
-void cleanup(void)
-{
-}
+static struct tst_test test = {
+ .needs_root = 1,
+ .test = verify_munlock,
+ .tcnt = ARRAY_SIZE(tcases),
+ .cleanup = cleanup,
+};
diff --git a/testcases/kernel/syscalls/munlock/munlock02.c b/testcases/kernel/syscalls/munlock/munlock02.c
index 75906a1df..f51c3d21f 100644
--- a/testcases/kernel/syscalls/munlock/munlock02.c
+++ b/testcases/kernel/syscalls/munlock/munlock02.c
@@ -1,198 +1,48 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) Wipro Technologies Ltd, 2002. All Rights Reserved.
- *
- * 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; if not, write the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ * AUTHOR: Nirmala Devi Dhanasekar <nirmala.devi@wipro.com>
*/
-/**************************************************************************
- *
- * TEST IDENTIFIER : munlock02
- *
- * EXECUTED BY : root / superuser
- *
- * TEST TITLE : Test for checking basic error conditions for
- * munlock(2)
- *
- * TEST CASE TOTAL : 2
- *
- * AUTHOR : Nirmala Devi Dhanasekar <nirmala.devi@wipro.com>
- *
- * SIGNALS
- * Uses SIGUSR1 to pause before test if option set.
- * (See the parse_opts(3) man page).
- *
- * DESCRIPTION
- * Check for basic errors returned by munlock(2) system call.
- *
- * Verify that munlock(2) returns -1 and sets errno to
- *
- * 1) ENOMEM - Some of the specified address range does not correspond to
- * mapped pages in the address space of the process.
- *
- * Setup:
- * Setup signal handling.
- * Pause for SIGUSR1 if option specified.
- *
- * Test:
- * Loop if the proper options are given.
- * Do necessary setup for each test.
- * Execute system call
- * Check return code, if system call failed (return=-1)
- * Log the errno and Issue a FAIL message.
- * Otherwise, Issue a PASS message.
- *
- * Cleanup:
- * Print errno log and/or timing stats if options given
+
+/*\
+ * [Description]
*
- * USAGE: <for command-line>
- * munlock02 [-c n] [-e] [-i n] [-I x] [-p x] [-t]
- * where, -c n : Run n copies concurrently
- * -e : Turn on errno logging.
- * -h : Show this help screen
- * -i n : Execute test n times.
- * -I x : Execute test for x seconds.
- * -p : Pause for SIGUSR1 before starting
- * -P x : Pause for x seconds between iterations.
- * -t : Turn on syscall timing.
+ * Test for ENOMEM error.
*
- * RESTRICTIONS
- * Test must run as root.
- *****************************************************************************/
-#include <errno.h>
-#include <unistd.h>
-#include <sys/mman.h>
-#include <pwd.h>
-#include "test.h"
-
-void setup();
-void cleanup();
-
-char *TCID = "munlock02";
-int TST_TOTAL = 1;
-
-#define LEN 1024
-
-void *addr1;
+ * munlock(2) fails with ENOMEM if some of the specified address range
+ * does not correspond to mapped pages in the address space of the
+ * process.
+ */
-struct test_case_t {
- void *addr;
- int len;
- int error;
- char *edesc;
-} TC[] = {
- {
-NULL, 0, ENOMEM, "address range out of address space"},};
+#include <sys/mman.h>
+#include "tst_test.h"
-#if !defined(UCLINUX)
+static size_t len, pg_size;
+static void *addr;
-int main(int ac, char **av)
+static void run(void)
{
- int lc, i;
-
- tst_parse_opts(ac, av, NULL, NULL);
-
- setup();
-
- /* check looping state */
- for (lc = 0; TEST_LOOPING(lc); lc++) {
-
- tst_count = 0;
- for (i = 0; i < TST_TOTAL; i++) {
-#ifdef __ia64__
- TC[0].len = 8 * getpagesize();
-#endif
- TEST(munlock(TC[i].addr, TC[i].len));
-
- /* check return code */
- if (TEST_RETURN == -1) {
- if (TEST_ERRNO != TC[i].error)
- tst_brkm(TFAIL, cleanup,
- "munlock() Failed with wrong "
- "errno, expected errno=%s, "
- "got errno=%d : %s",
- TC[i].edesc, TEST_ERRNO,
- strerror(TEST_ERRNO));
- else
- tst_resm(TPASS,
- "expected failure - errno "
- "= %d : %s",
- TEST_ERRNO,
- strerror(TEST_ERRNO));
- } else {
- tst_brkm(TFAIL, cleanup,
- "munlock() Failed, expected "
- "return value=-1, got %ld",
- TEST_RETURN);
- }
- }
- }
-
- /* cleanup and exit */
- cleanup();
-
- tst_exit();
+ TST_EXP_FAIL(munlock(addr, len), ENOMEM, "munlock(%p, %lu)",
+ addr, len);
}
-/* setup() - performs all ONE TIME setup for this test. */
-
-void setup(void)
+static void setup(void)
{
-
- char *address;
-
- tst_sig(FORK, DEF_HANDLER, cleanup);
-
- TC[0].len = 8 * getpagesize();
- address = mmap(0, TC[0].len, PROT_READ | PROT_WRITE,
- MAP_PRIVATE_EXCEPT_UCLINUX | MAP_ANONYMOUS, 0, 0);
- if (address == MAP_FAILED)
- tst_brkm(TFAIL, cleanup, "mmap_failed");
- memset(address, 0x20, TC[0].len);
- TEST(mlock(address, TC[0].len));
-
- /* check return code */
- if (TEST_RETURN == -1) {
- tst_brkm(TFAIL | TTERRNO, cleanup,
- "mlock(%p, %d) Failed with return=%ld", address,
- TC[0].len, TEST_RETURN);
- }
- TC[0].addr = address;
+ pg_size = getpagesize();
+ len = 8 * pg_size;
+ addr = SAFE_MMAP(NULL, len, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
+ memset(addr, 0x20, len);
+ SAFE_MLOCK(addr, len);
/*
* unmap part of the area, to create the condition for ENOMEM
*/
- address += 2 * getpagesize();
- munmap(address, 4 * getpagesize());
-
- TEST_PAUSE;
-
- return;
-}
-
-#else
-
-int main(void)
-{
- tst_resm(TINFO, "test is not available on uClinux");
- tst_exit();
+ addr += 2 * pg_size;
+ SAFE_MUNMAP(addr, 4 * pg_size);
}
-#endif /* if !defined(UCLINUX) */
-
-/*
- * cleanup() - performs all ONE TIME cleanup for this test at
- * completion or premature exit.
- */
-void cleanup(void)
-{
- return;
-}
+static struct tst_test test = {
+ .needs_root = 1,
+ .setup = setup,
+ .test_all = run,
+};
diff --git a/testcases/kernel/syscalls/munmap/munmap01.c b/testcases/kernel/syscalls/munmap/munmap01.c
index 2a5cfc90d..7d10c0eac 100644
--- a/testcases/kernel/syscalls/munmap/munmap01.c
+++ b/testcases/kernel/syscalls/munmap/munmap01.c
@@ -193,7 +193,7 @@ void setup(void)
/*
* map the open file 'TEMPFILE' from its beginning up to the maplength
* into the calling process's address space at the system choosen
- * with read/write permissions to the the mapped region.
+ * with read/write permissions to the mapped region.
*/
#ifdef UCLINUX
/* MAP_SHARED is not implemented on uClinux */
diff --git a/testcases/kernel/syscalls/munmap/munmap02.c b/testcases/kernel/syscalls/munmap/munmap02.c
index b43250512..cd85d9436 100644
--- a/testcases/kernel/syscalls/munmap/munmap02.c
+++ b/testcases/kernel/syscalls/munmap/munmap02.c
@@ -197,7 +197,7 @@ void setup(void)
/*
* map the open file 'TEMPFILE' from its beginning up to the maplength
* into the calling process's address space at the system choosen
- * with read/write permissions to the the mapped region.
+ * with read/write permissions to the mapped region.
*/
#ifdef UCLINUX
/* mmap() doesn't support MAP_SHARED on uClinux */
diff --git a/testcases/kernel/syscalls/name_to_handle_at/name_to_handle_at01.c b/testcases/kernel/syscalls/name_to_handle_at/name_to_handle_at01.c
index 9677b0671..6535fdf5c 100644
--- a/testcases/kernel/syscalls/name_to_handle_at/name_to_handle_at01.c
+++ b/testcases/kernel/syscalls/name_to_handle_at/name_to_handle_at01.c
@@ -72,7 +72,7 @@ static void setup(void)
dir_fd = SAFE_OPEN(TEST_DIR, O_DIRECTORY);
SAFE_CHDIR(TEST_DIR);
SAFE_TOUCH(TEST_FILE, 0600, NULL);
- file_fd = SAFE_OPEN("foo_file", O_RDWR | O_CREAT);
+ file_fd = SAFE_OPEN("foo_file", O_RDWR | O_CREAT, 0600);
fhp = allocate_file_handle(AT_FDCWD, TEST_FILE);
}
diff --git a/testcases/kernel/syscalls/open_by_handle_at/open_by_handle_at01.c b/testcases/kernel/syscalls/open_by_handle_at/open_by_handle_at01.c
index 76be720ca..6171229f0 100644
--- a/testcases/kernel/syscalls/open_by_handle_at/open_by_handle_at01.c
+++ b/testcases/kernel/syscalls/open_by_handle_at/open_by_handle_at01.c
@@ -55,7 +55,7 @@ static void setup(void)
dir_fd = SAFE_OPEN(TEST_DIR, O_DIRECTORY);
SAFE_CHDIR(TEST_DIR);
SAFE_TOUCH(TEST_FILE, 0600, NULL);
- file_fd = SAFE_OPEN("foo_file", O_RDWR | O_CREAT);
+ file_fd = SAFE_OPEN("foo_file", O_RDWR | O_CREAT, 0600);
f_fhp = allocate_file_handle(AT_FDCWD, TEST_FILE);
d_fhp = allocate_file_handle(AT_FDCWD, TEST_FILE);
diff --git a/testcases/kernel/syscalls/personality/personality01.c b/testcases/kernel/syscalls/personality/personality01.c
index b646e2a9b..47fb66256 100644
--- a/testcases/kernel/syscalls/personality/personality01.c
+++ b/testcases/kernel/syscalls/personality/personality01.c
@@ -1,24 +1,15 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
+ * Copyright (c) 2016 Linux Test Project
* Copyright (c) International Business Machines Corp., 2001
* 03/2001 - Written by Wayne Boyer
* Copyright (c) 2016 Cyril Hrubis <chrubis@suse.cz>
- *
- * 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) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
*/
-/*
+/*\
+ * [Description]
+ *
* Tries to set different personalities.
*
* We set the personality in a child process since it's not guaranteed that we
@@ -26,19 +17,17 @@
* bit archs.
*/
-#include "test.h"
-#include <sys/personality.h>
-
-char *TCID = "personality01";
+#include "tst_test.h"
+#include "lapi/personality.h"
#define PAIR(id) {id, #id}
struct personalities {
- unsigned long int pers;
+ unsigned long pers;
const char *name;
};
-struct personalities pers[] = {
+static struct personalities pers[] = {
PAIR(PER_LINUX),
PAIR(PER_LINUX_32BIT),
PAIR(PER_SVR4),
@@ -62,60 +51,24 @@ struct personalities pers[] = {
PAIR(PER_HPUX),
};
-int TST_TOTAL = ARRAY_SIZE(pers);
-
-static void do_child(unsigned int i)
+static void run(unsigned int i)
{
- int ret;
+ pid_t pid;
- ret = personality(pers[i].pers);
- if (ret < 0) {
- tst_resm(TFAIL | TERRNO, "personality(%s) failed", pers[i].name);
- return;
- }
+ pid = SAFE_FORK();
+ if (!pid) {
+ SAFE_PERSONALITY(pers[i].pers);
- ret = personality(0xffffffff);
+ TST_EXP_EXPR((unsigned long)SAFE_PERSONALITY(0xffffffff) == pers[i].pers,
+ "%s personality is set",
+ pers[i].name);
- if ((unsigned long)ret != pers[i].pers) {
- tst_resm(TFAIL,
- "%s: wrong personality read back %d expected %lu",
- pers[i].name, ret, pers[i].pers);
return;
}
-
- tst_resm(TPASS, "personality(%s)", pers[i].name);
-}
-
-static void verify_personality(unsigned int i)
-{
- pid_t pid;
-
- pid = tst_fork();
- switch (pid) {
- case 0:
- do_child(i);
- tst_exit();
- break;
- case -1:
- tst_brkm(TBROK | TERRNO, NULL, "fork() failed");
- break;
- default:
- tst_record_childstatus(NULL, pid);
- break;
- }
}
-int main(int ac, char **av)
-{
- int i, lc;
-
- tst_parse_opts(ac, av, NULL, NULL);
-
- for (lc = 0; TEST_LOOPING(lc); lc++) {
- for (i = 0; i < TST_TOTAL; i++) {
- verify_personality(i);
- }
- }
-
- tst_exit();
-}
+static struct tst_test test = {
+ .test = run,
+ .tcnt = ARRAY_SIZE(pers),
+ .forks_child = 1,
+};
diff --git a/testcases/kernel/syscalls/personality/personality02.c b/testcases/kernel/syscalls/personality/personality02.c
index eb18c9951..e080284f4 100644
--- a/testcases/kernel/syscalls/personality/personality02.c
+++ b/testcases/kernel/syscalls/personality/personality02.c
@@ -1,62 +1,42 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
+ * Copyright (c) 2016 Linux Test Project
* Copyright (c) 2016 Cyril Hrubis <chrubis@suse.cz>
- *
- * 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, see <http://www.gnu.org/licenses/>.
+ * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
*/
-/*
- * If personality with STICKY_TIMEOUTS is used select() timeout is not updated.
+/*\
+ * [Description]
+ *
+ * This test checks if select() timeout is not updated when personality with
+ * STICKY_TIMEOUTS is used.
*/
-#include "test.h"
-#include <sys/personality.h>
+#include "tst_test.h"
+#include "lapi/personality.h"
#include <sys/select.h>
-char *TCID = "personality02";
-int TST_TOTAL = 1;
-
#define USEC 10
-static void verify_personality(void)
+static void run(void)
{
- struct timeval tv = {.tv_sec = 0, .tv_usec = USEC};
- int ret;
+ struct timeval tv = { .tv_sec = 0, .tv_usec = USEC };
fd_set rfds;
FD_ZERO(&rfds);
FD_SET(1, &rfds);
- personality(PER_LINUX | STICKY_TIMEOUTS);
- ret = select(2, &rfds, NULL, NULL, &tv);
- personality(PER_LINUX);
- if (ret < 0)
- tst_resm(TBROK | TERRNO, "select()");
+ SAFE_PERSONALITY(PER_LINUX | STICKY_TIMEOUTS);
- if (tv.tv_usec != USEC)
- tst_resm(TFAIL, "Timeout was modified");
- else
- tst_resm(TPASS, "Timeout wasn't modified");
-}
-
-int main(int ac, char **av)
-{
- int lc;
+ TEST(select(2, &rfds, NULL, NULL, &tv));
+ if (TST_RET == -1)
+ tst_brk(TBROK | TERRNO, "select() error");
- tst_parse_opts(ac, av, NULL, NULL);
+ SAFE_PERSONALITY(PER_LINUX);
- for (lc = 0; TEST_LOOPING(lc); lc++)
- verify_personality();
-
- tst_exit();
+ TST_EXP_EQ_LI(tv.tv_usec, USEC);
}
+
+static struct tst_test test = {
+ .test_all = run,
+};
diff --git a/testcases/kernel/syscalls/pipe/.gitignore b/testcases/kernel/syscalls/pipe/.gitignore
index 23e7186a6..774d73205 100644
--- a/testcases/kernel/syscalls/pipe/.gitignore
+++ b/testcases/kernel/syscalls/pipe/.gitignore
@@ -11,3 +11,4 @@
/pipe11
/pipe12
/pipe13
+/pipe14
diff --git a/testcases/kernel/syscalls/pipe/pipe03.c b/testcases/kernel/syscalls/pipe/pipe03.c
index 89c0911c1..d20867b2b 100644
--- a/testcases/kernel/syscalls/pipe/pipe03.c
+++ b/testcases/kernel/syscalls/pipe/pipe03.c
@@ -1,51 +1,42 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) International Business Machines Corp., 2002
+ * Copyright (c) 2003-2023 Linux Test Project
*/
-/*
- * Make sure that writing to the read end of a pipe and reading from
- * the write end of a pipe both fail.
+/*\
+ * [Description]
+ *
+ * Verify that, an attempt to write to the read end of a pipe fails with EBADF
+ * and an attempt to read from the write end of a pipe also fails with EBADF.
*/
-#include <unistd.h>
-#include <errno.h>
#include "tst_test.h"
static int fd[2];
static void verify_pipe(void)
{
- char buf[2];
-
- TEST(pipe(fd));
- if (TST_RET == -1) {
- tst_res(TFAIL | TTERRNO, "pipe() failed unexpectedly");
- return;
- }
-
- TEST(write(fd[0], "A", 1));
- if (TST_RET == -1 && errno == EBADF) {
- tst_res(TPASS | TTERRNO, "expected failure writing "
- "to read end of pipe");
- } else {
- tst_res(TFAIL | TTERRNO, "unexpected failure writing "
- "to read end of pipe");
- }
-
- TEST(read(fd[1], buf, 1));
- if (TST_RET == -1 && errno == EBADF) {
- tst_res(TPASS | TTERRNO, "expected failure reading "
- "from write end of pipe");
- } else {
- tst_res(TFAIL | TTERRNO, "unexpected failure reading "
- "from write end of pipe");
- }
+ char buf[] = "abcdef";
+
+ SAFE_PIPE(fd);
+
+ TST_EXP_FAIL2(write(fd[0], "A", 1), EBADF);
+ TST_EXP_FAIL2(read(fd[1], buf, 1), EBADF);
SAFE_CLOSE(fd[0]);
SAFE_CLOSE(fd[1]);
}
+static void cleanup(void)
+{
+ if (fd[0] > 0)
+ SAFE_CLOSE(fd[0]);
+ if (fd[1] > 0)
+ SAFE_CLOSE(fd[1]);
+}
+
static struct tst_test test = {
.test_all = verify_pipe,
+ .cleanup = cleanup
};
diff --git a/testcases/kernel/syscalls/pipe/pipe06.c b/testcases/kernel/syscalls/pipe/pipe06.c
index d83765632..0c6bc03bd 100644
--- a/testcases/kernel/syscalls/pipe/pipe06.c
+++ b/testcases/kernel/syscalls/pipe/pipe06.c
@@ -1,119 +1,57 @@
+// 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) Linux Test Project, 2002-2015
+ * Copyright (c) 2023 SUSE LLC Avinesh Kumar <avinesh.kumar@suse.com>
*/
-/*
- * NAME
- * pipe06.c
- *
- * DESCRIPTION
- * Check what happens when the system runs out of pipes.
- *
- * ALGORITHM
- * Issue enough pipe calls to run the system out of pipes.
- * Check that we get EMFILE.
+/*\
+ * [Description]
*
- * USAGE: <for command-line>
- * pipe06 [-c n] [-e] [-i n] [-I x] [-P x] [-t]
- * where, -c n : Run n copies concurrently.
- * -e : Turn on errno logging.
- * -i n : Execute test n times.
- * -I x : Execute test for x seconds.
- * -P x : Pause for x seconds between iterations.
- * -t : Turn on syscall timing.
- *
- * HISTORY
- * 07/2001 Ported by Wayne Boyer
- *
- * RESTRICTIONS
- * None
+ * Verify that, pipe(2) syscall fails with errno EMFILE when
+ * limit on the number of open file descriptors has been reached.
*/
-#include <fcntl.h>
-#include <errno.h>
-#include "test.h"
-char *TCID = "pipe06";
-int TST_TOTAL = 1;
+#include "tst_test.h"
+#include <stdlib.h>
-int pipe_ret, pipes[2];
-void setup(void);
-void cleanup(void);
+static int fds[2];
+static int *opened_fds, num_opened_fds;
-int main(int ac, char **av)
+static void setup(void)
{
- int lc;
-
- 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;
+ int max_fds;
- TEST(pipe(pipes));
+ max_fds = getdtablesize();
+ tst_res(TINFO, "getdtablesize() = %d", max_fds);
+ opened_fds = SAFE_MALLOC(max_fds * sizeof(int));
- if (TEST_RETURN != -1) {
- tst_resm(TFAIL, "call succeeded unexpectedly");
- }
-
- if (TEST_ERRNO != EMFILE) {
- tst_resm(TFAIL | TTERRNO, "pipe failed unexpectedly");
- } else {
- tst_resm(TPASS, "failed with EMFILE");
- }
-
- }
- cleanup();
- tst_exit();
+ do {
+ SAFE_PIPE(fds);
+ opened_fds[num_opened_fds++] = fds[0];
+ opened_fds[num_opened_fds++] = fds[1];
+ } while (fds[1] < max_fds - 2);
+ tst_res(TINFO, "Number of fds opened by pipe calls: %d", num_opened_fds);
}
-/*
- * setup() - performs all ONE TIME setup for this test.
- */
-void setup(void)
+static void run(void)
{
- int i, numb_fds;
-
- tst_sig(NOFORK, DEF_HANDLER, cleanup);
-
- TEST_PAUSE;
-
- numb_fds = getdtablesize();
-
- for (i = 0; i < numb_fds; i++) {
- pipe_ret = pipe(pipes);
- if (pipe_ret < 0) {
- if (errno != EMFILE) {
- tst_brkm(TBROK | TTERRNO, cleanup,
- "didn't get EMFILE");
- }
- break;
- }
- }
+ TST_EXP_FAIL(pipe(fds), EMFILE);
}
-/*
- * cleanup() - performs all ONE TIME cleanup for this test at
- * completion or premature exit.
- */
-void cleanup(void)
+static void cleanup(void)
{
+ for (int i = 0; i < num_opened_fds; i++)
+ SAFE_CLOSE(opened_fds[i]);
+
+ if (opened_fds)
+ free(opened_fds);
}
+
+static struct tst_test test = {
+ .setup = setup,
+ .cleanup = cleanup,
+ .test_all = run
+};
diff --git a/testcases/kernel/syscalls/pipe/pipe07.c b/testcases/kernel/syscalls/pipe/pipe07.c
index 55bb9f419..8098007c2 100644
--- a/testcases/kernel/syscalls/pipe/pipe07.c
+++ b/testcases/kernel/syscalls/pipe/pipe07.c
@@ -1,176 +1,103 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) International Business Machines Corp., 2002
- * Ported by Paul Larson
+ * Ported by Paul Larson
* Copyright (c) 2013 Cyril Hrubis <chrubis@suse.cz>
- *
- * 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) 2023 SUSE LLC Avinesh Kumar <avinesh.kumar@suse.com>
*/
-/*
- * Test the ability of pipe to open the maximum even number of file
- * descriptors permitted (or (maxfds - 3)/2 pipes)
+/*\
+ * [Description]
*
- * ALGORITHM
- * 1. record file descriptors open prior to test run
- * 2. open pipes until EMFILE is returned
- * 3. check to see that the number of pipes opened is (maxfds - 3) / 2
- * 4. close all fds in range 0, maximal fd that were not open prior to
- * the test execution
+ * Verify that, pipe(2) syscall can open the maximum number of
+ * file descriptors permitted.
*/
-#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <dirent.h>
-#include "test.h"
-#include "safe_macros.h"
-
-char *TCID = "pipe07";
-int TST_TOTAL = 1;
-
-/* used to record file descriptors open at the test start */
-static int rec_fds[128];
-static int rec_fds_max;
-static void record_open_fds(void);
-static void close_test_fds(int max_fd);
+#include "tst_test.h"
+#include <stdlib.h>
-static void setup(void);
-static void cleanup(void);
+static int *opened_fds, *pipe_fds;
+static int num_pipe_fds, exp_num_pipes;
-int main(int ac, char **av)
+static int record_open_fds(void)
{
- int lc;
- int min, ret;
- int npipes;
- int pipes[2], max_fd = 0;
-
- tst_parse_opts(ac, av, NULL, NULL);
+ DIR *dir;
+ struct dirent *ent;
+ int fd;
+ int num_opened_fds = 0;
+ int arr_size = 0;
- setup();
+ dir = SAFE_OPENDIR("/proc/self/fd");
- min = getdtablesize() - rec_fds_max;
-
- for (lc = 0; TEST_LOOPING(lc); lc++) {
- tst_count = 0;
+ while ((ent = SAFE_READDIR(dir))) {
+ if (!strcmp(ent->d_name, ".") ||
+ !strcmp(ent->d_name, ".."))
+ continue;
+ fd = atoi(ent->d_name);
- for (npipes = 0;; npipes++) {
- ret = pipe(pipes);
- if (ret < 0) {
- if (errno != EMFILE) {
- tst_brkm(TFAIL, cleanup,
- "got unexpected error - %d",
- errno);
- }
- break;
- }
+ if (fd == dirfd(dir))
+ continue;
- max_fd = MAX(pipes[0], max_fd);
- max_fd = MAX(pipes[1], max_fd);
+ if (num_opened_fds >= arr_size) {
+ arr_size = MAX(1, arr_size * 2);
+ opened_fds = SAFE_REALLOC(opened_fds, arr_size * sizeof(int));
}
-
- if (npipes == (min / 2))
- tst_resm(TPASS, "Opened %d pipes", npipes);
- else
- tst_resm(TFAIL, "Unable to open maxfds/2 pipes");
-
- close_test_fds(max_fd);
- max_fd = 0;
+ opened_fds[num_opened_fds++] = fd;
}
- cleanup();
- tst_exit();
+ SAFE_CLOSEDIR(dir);
+
+ return num_opened_fds;
}
static void setup(void)
{
- tst_sig(FORK, DEF_HANDLER, cleanup);
- TEST_PAUSE;
+ int max_fds;
+
+ max_fds = getdtablesize();
+ tst_res(TINFO, "getdtablesize() = %d", max_fds);
+ pipe_fds = SAFE_MALLOC(max_fds * sizeof(int));
- record_open_fds();
+ exp_num_pipes = (max_fds - record_open_fds()) / 2 * 2;
+ tst_res(TINFO, "expected max fds to be opened by pipe(): %d", exp_num_pipes);
}
-static void record_open_fds(void)
+static void run(void)
{
- DIR *dir = opendir("/proc/self/fd");
- int dir_fd, fd;
- struct dirent *file;
-
- if (dir == NULL)
- tst_brkm(TBROK | TERRNO, cleanup, "opendir()");
-
- dir_fd = dirfd(dir);
+ int fds[2];
- if (dir_fd == -1)
- tst_brkm(TBROK | TERRNO, cleanup, "dirfd()");
-
- errno = 0;
-
- while ((file = readdir(dir))) {
- if (!strcmp(file->d_name, ".") || !strcmp(file->d_name, ".."))
- continue;
-
- fd = atoi(file->d_name);
-
- if (fd == dir_fd)
- continue;
-
- if (rec_fds_max >= (int)ARRAY_SIZE(rec_fds)) {
- tst_brkm(TBROK, cleanup,
- "Too much file descriptors open");
+ do {
+ TEST(pipe(fds));
+ if (!TST_RET) {
+ pipe_fds[num_pipe_fds++] = fds[0];
+ pipe_fds[num_pipe_fds++] = fds[1];
}
+ } while (!TST_RET);
- rec_fds[rec_fds_max++] = fd;
- }
-
- if (errno)
- tst_brkm(TBROK | TERRNO, cleanup, "readdir()");
+ TST_EXP_EQ_LI(errno, EMFILE);
+ TST_EXP_EQ_LI(exp_num_pipes, num_pipe_fds);
- closedir(dir);
+ for (int i = 0; i < num_pipe_fds; i++)
+ SAFE_CLOSE(pipe_fds[i]);
- tst_resm(TINFO, "Found %u files open", rec_fds_max);
+ num_pipe_fds = 0;
}
-static int not_recorded(int fd)
+static void cleanup(void)
{
- int i;
+ for (int i = 0; i < num_pipe_fds; i++)
+ if (pipe_fds[i] > 0)
+ SAFE_CLOSE(pipe_fds[i]);
- for (i = 0; i < rec_fds_max; i++)
- if (fd == rec_fds[i])
- return 0;
+ if (pipe_fds)
+ free(pipe_fds);
- return 1;
+ if (opened_fds)
+ free(opened_fds);
}
-static void close_test_fds(int max_fd)
-{
- int i;
-
- for (i = 0; i <= max_fd; i++) {
- if (not_recorded(i)) {
- if (close(i)) {
- if (errno == EBADF)
- continue;
- tst_resm(TWARN | TERRNO, "close(%i)", i);
- }
- }
- }
-}
-
-static void cleanup(void)
-{
-}
+static struct tst_test test = {
+ .setup = setup,
+ .cleanup = cleanup,
+ .test_all = run
+};
diff --git a/testcases/kernel/syscalls/pipe/pipe08.c b/testcases/kernel/syscalls/pipe/pipe08.c
index 173ec788a..28088cf61 100644
--- a/testcases/kernel/syscalls/pipe/pipe08.c
+++ b/testcases/kernel/syscalls/pipe/pipe08.c
@@ -1,137 +1,59 @@
+// 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) 2023 SUSE LLC Avinesh Kumar <avinesh.kumar@suse.com>
*/
-/*
- * NAME
- * pipe08.c
- *
- * DESCRIPTION
- * Check that a SIGPIPE signal is generated when a write is
- * attempted on an empty pipe.
- *
- * ALGORITHM
- * 1. Write to a pipe after closing the read side.
- * 2. Check for the signal SIGPIPE to be received.
+/*\
+ * [Description]
*
- * USAGE: <for command-line>
- * pipe08 [-c n] [-f] [-i n] [-I x] [-P x] [-t]
- * where, -c n : Run n copies concurrently.
- * -f : Turn off functionality Testing.
- * -i n : Execute test n times.
- * -I x : Execute test for x seconds.
- * -P x : Pause for x seconds between iterations.
- * -t : Turn on syscall timing.
- *
- * USAGE
- * pipe08
- *
- * HISTORY
- * 07/2001 Ported by Wayne Boyer
- *
- * RESTRICTIONS
- * None
+ * Verify that, on any attempt to write to a pipe which is closed for
+ * reading will generate a SIGPIPE signal and write will fail with
+ * EPIPE errno.
*/
-#include <errno.h>
-#include <unistd.h>
-#include <signal.h>
-#include <string.h>
-#include "test.h"
-char *TCID = "pipe08";
-int TST_TOTAL = 1;
+#include "tst_test.h"
-void setup(void);
-void cleanup(void);
-void sighandler(int);
+static int pipefd[2];
+static volatile int sigpipe_cnt;
-int main(int ac, char **av)
+static void sighandler(int sig)
{
- int lc;
-
- int pipefd[2]; /* fds for pipe read/write */
- char wrbuf[BUFSIZ];
- int written, length;
- int close_stat; /* exit status of close(read fd) */
-
- 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;
-
- TEST(pipe(pipefd));
+ if (sig == SIGPIPE)
+ sigpipe_cnt++;
+}
- if (TEST_RETURN != 0) {
- tst_resm(TFAIL, "call failed unexpectedly");
- continue;
- }
+static void run(void)
+{
+ char wrbuf[] = "abcdefghijklmnopqrstuvwxyz";
- if ((close_stat = close(pipefd[0])) == -1) {
- tst_brkm(TBROK, cleanup, "close of read side failed");
- }
+ sigpipe_cnt = 0;
- strcpy(wrbuf, "abcdefghijklmnopqrstuvwxyz\0");
- length = strlen(wrbuf);
+ SAFE_PIPE(pipefd);
+ SAFE_CLOSE(pipefd[0]);
- /*
- * the SIGPIPE signal will be caught here or else
- * the program will dump core when the signal is
- * sent
- */
- written = write(pipefd[1], wrbuf, length);
- if (written > 0)
- tst_brkm(TBROK, cleanup, "write succeeded unexpectedly");
- }
- cleanup();
- tst_exit();
+ TST_EXP_FAIL2_SILENT(write(pipefd[1], wrbuf, sizeof(wrbuf)), EPIPE);
+ TST_EXP_EQ_LI(sigpipe_cnt, 1);
+ SAFE_CLOSE(pipefd[1]);
}
-/*
- * sighandler - catch signals and look for SIGPIPE
- */
-void sighandler(int sig)
+static void setup(void)
{
- if (sig != SIGPIPE)
- tst_resm(TFAIL, "expected SIGPIPE, got %d", sig);
- else
- tst_resm(TPASS, "got expected SIGPIPE signal");
+ SAFE_SIGNAL(SIGPIPE, sighandler);
}
-/*
- * setup() - performs all ONE TIME setup for this test.
- */
-void setup(void)
+static void cleanup(void)
{
-
- tst_sig(NOFORK, sighandler, cleanup);
-
- TEST_PAUSE;
+ if (pipefd[0] > 0)
+ SAFE_CLOSE(pipefd[0]);
+ if (pipefd[1] > 0)
+ SAFE_CLOSE(pipefd[1]);
}
-/*
- * cleanup() - performs all ONE TIME cleanup for this test at
- * completion or premature exit.
- */
-void cleanup(void)
-{
-}
+static struct tst_test test = {
+ .setup = setup,
+ .test_all = run,
+ .cleanup = cleanup
+};
diff --git a/testcases/kernel/syscalls/pipe/pipe10.c b/testcases/kernel/syscalls/pipe/pipe10.c
index 48f722e3e..018e653da 100644
--- a/testcases/kernel/syscalls/pipe/pipe10.c
+++ b/testcases/kernel/syscalls/pipe/pipe10.c
@@ -1,164 +1,52 @@
+// 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) 2023 SUSE LLC Avinesh Kumar <avinesh.kumar@suse.com>
*/
-/*
- * NAME
- * pipe10.c
- *
- * DESCRIPTION
- * Check that parent can open a pipe and have a child read from it
- *
- * ALGORITHM
- * Parent opens pipe, child reads. Passes if child can read all the
- * characters written by the parent.
- *
- * USAGE: <for command-line>
- * pipe10 [-c n] [-f] [-i n] [-I x] [-P x] [-t]
- * where, -c n : Run n copies concurrently.
- * -f : Turn off functionality Testing.
- * -i n : Execute test n times.
- * -I x : Execute test for x seconds.
- * -P x : Pause for x seconds between iterations.
- * -t : Turn on syscall timing.
- *
- * HISTORY
- * 07/2001 Ported by Wayne Boyer
+/*\
+ * [Description]
*
- * RESTRICTIONS
- * None
+ * Verify that, when a parent process opens a pipe, a child process can
+ * read from it.
*/
-#include <errno.h>
-#include <unistd.h>
-#include <sys/wait.h>
-#include <string.h>
-#include "test.h"
-char *TCID = "pipe10";
-int TST_TOTAL = 1;
+#include <stdio.h>
+#include "tst_test.h"
-void setup(void);
-void cleanup(void);
+static int fds[2];
-ssize_t do_read(int fd, void *buf, size_t count)
+static void run(void)
{
- ssize_t n;
-
- do {
- n = read(fd, buf, count);
- } while (n < 0 && errno == EINTR);
-
- return n;
-}
-
-int main(int ac, char **av)
-{
- int lc;
-
- int fd[2]; /* fds for pipe read/write */
- char wrbuf[BUFSIZ], rebuf[BUFSIZ];
- int red, written; /* no of chars read and */
- /* written to pipe */
- int length, greater, forkstat;
- int retval = 0, status, e_code;
-
- tst_parse_opts(ac, av, NULL, NULL);
-
- setup();
-
- for (lc = 0; TEST_LOOPING(lc); lc++) {
+ int wr_cnt, rd_cnt;
+ char wrbuf[] = "abcdefghijklmnopqrstuvwxyz";
+ char rdbuf[BUFSIZ];
- /* reset tst_count in case we are looping */
- tst_count = 0;
+ SAFE_PIPE(fds);
+ wr_cnt = SAFE_WRITE(SAFE_WRITE_ALL, fds[1], wrbuf, sizeof(wrbuf));
- TEST(pipe(fd));
-
- if (TEST_RETURN == -1) {
- retval = 1;
- tst_resm(TFAIL, "pipe creation failed");
- continue;
- }
-
- strcpy(wrbuf, "abcdefghijklmnopqrstuvwxyz");
- length = strlen(wrbuf) + 1;
-
- written = write(fd[1], wrbuf, length);
-
- /* did write write at least some chars */
- if ((written < 0) || (written > length)) {
- tst_brkm(TBROK, cleanup, "write to pipe failed");
- }
-
- forkstat = FORK_OR_VFORK();
-
- if (forkstat == -1) {
- tst_brkm(TBROK, cleanup, "fork() failed");
- }
-
- if (forkstat == 0) { /* child */
- red = do_read(fd[0], rebuf, written);
-
- /* did read , get at least some chars */
- if ((red < 0) || (red > written)) {
- tst_brkm(TBROK, cleanup, "read pipe failed");
- }
-
- greater = strcmp(rebuf, wrbuf);
-
- /* are the strings written and read equal */
- if (greater == 0) {
- tst_resm(TPASS, "functionality is correct");
- } else {
- retval = 1;
- tst_resm(TFAIL, "read & write strings do "
- "not match");
- }
- exit(retval);
- } else { /* parent */
- /* wait for the child to finish */
- wait(&status);
- /* make sure the child returned a good exit status */
- e_code = status >> 8;
- if (e_code != 0) {
- tst_resm(TFAIL, "Failures reported above");
- }
- }
+ if (!SAFE_FORK()) {
+ rd_cnt = SAFE_READ(1, fds[0], rdbuf, wr_cnt);
+ TST_EXP_EQ_LU(wr_cnt, rd_cnt);
}
- cleanup();
- tst_exit();
+ tst_reap_children();
+ SAFE_CLOSE(fds[0]);
+ SAFE_CLOSE(fds[1]);
}
-/*
- * setup() - performs all ONE TIME setup for this test.
- */
-void setup(void)
+static void cleanup(void)
{
+ if (fds[0] > 0)
+ SAFE_CLOSE(fds[0]);
- tst_sig(FORK, DEF_HANDLER, cleanup);
-
- TEST_PAUSE;
+ if (fds[1] > 0)
+ SAFE_CLOSE(fds[1]);
}
-/*
- * cleanup() - performs all ONE TIME cleanup for this test at
- * completion or premature exit.
- */
-void cleanup(void)
-{
-}
+static struct tst_test test = {
+ .test_all = run,
+ .forks_child = 1,
+ .cleanup = cleanup
+};
diff --git a/testcases/kernel/syscalls/pipe/pipe14.c b/testcases/kernel/syscalls/pipe/pipe14.c
new file mode 100644
index 000000000..2d2969d82
--- /dev/null
+++ b/testcases/kernel/syscalls/pipe/pipe14.c
@@ -0,0 +1,46 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2023 SUSE LLC Avinesh Kumar <avinesh.kumar@suse.com>
+ */
+
+/*\
+ * [Description]
+ *
+ * Verify that, if the write end of a pipe is closed, then a process reading
+ * from the pipe will see end-of-file (i.e., read() returns 0) once it has
+ * read all remaining data in the pipe.
+ */
+
+#include "tst_test.h"
+
+static int fds[2];
+
+static void run(void)
+{
+ char wrbuf[] = "abcdefghijklmnopqrstuvwxyz";
+ char rdbuf[30];
+
+ memset(rdbuf, 0, sizeof(rdbuf));
+ SAFE_PIPE(fds);
+
+ SAFE_WRITE(SAFE_WRITE_ALL, fds[1], wrbuf, sizeof(wrbuf));
+ SAFE_CLOSE(fds[1]);
+
+ SAFE_READ(0, fds[0], rdbuf, sizeof(wrbuf));
+
+ TST_EXP_VAL(SAFE_READ(0, fds[0], rdbuf, 1), 0);
+ SAFE_CLOSE(fds[0]);
+}
+
+static void cleanup(void)
+{
+ if (fds[0] > 0)
+ SAFE_CLOSE(fds[0]);
+ if (fds[1] > 0)
+ SAFE_CLOSE(fds[1]);
+}
+
+static struct tst_test test = {
+ .test_all = run,
+ .cleanup = cleanup
+};
diff --git a/testcases/kernel/syscalls/prctl/prctl04.c b/testcases/kernel/syscalls/prctl/prctl04.c
index f6e1f0fea..8b135d611 100644
--- a/testcases/kernel/syscalls/prctl/prctl04.c
+++ b/testcases/kernel/syscalls/prctl/prctl04.c
@@ -45,6 +45,7 @@
static const struct sock_filter strict_filter[] = {
BPF_STMT(BPF_LD | BPF_W | BPF_ABS, (offsetof(struct seccomp_data, nr))),
+ BPF_JUMP(BPF_JMP | BPF_JEQ, __NR_waitid, 7, 0),
BPF_JUMP(BPF_JMP | BPF_JEQ, __NR_rt_sigprocmask, 6, 0),
BPF_JUMP(BPF_JMP | BPF_JEQ, __NR_close, 5, 0),
BPF_JUMP(BPF_JMP | BPF_JEQ, __NR_exit, 4, 0),
diff --git a/testcases/kernel/syscalls/preadv2/preadv203.c b/testcases/kernel/syscalls/preadv2/preadv203.c
index 25c6e1c2e..c87deb674 100644
--- a/testcases/kernel/syscalls/preadv2/preadv203.c
+++ b/testcases/kernel/syscalls/preadv2/preadv203.c
@@ -159,7 +159,7 @@ static void *writer_thread(void *unused)
while (!stop) {
int fd = fds[random() % FILES];
- for (j = 0; j < CHUNKS; j++) {
+ for (j = 0; j < CHUNKS && !stop; j++) {
memset(buf, '0' + j, sizeof(buf));
off_t off = CHUNK_SZ * j;
diff --git a/testcases/kernel/syscalls/process_madvise/.gitignore b/testcases/kernel/syscalls/process_madvise/.gitignore
new file mode 100644
index 000000000..93d2640f7
--- /dev/null
+++ b/testcases/kernel/syscalls/process_madvise/.gitignore
@@ -0,0 +1 @@
+/process_madvise01
diff --git a/testcases/kernel/syscalls/paging/Makefile b/testcases/kernel/syscalls/process_madvise/Makefile
index 044619fb8..ad5b66061 100644
--- a/testcases/kernel/syscalls/paging/Makefile
+++ b/testcases/kernel/syscalls/process_madvise/Makefile
@@ -1,8 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-or-later
-# Copyright (c) International Business Machines Corp., 2001
+# Copyright (C) 2023 Linux Test Project, Inc.
top_srcdir ?= ../../../..
include $(top_srcdir)/include/mk/testcases.mk
-
include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/syscalls/process_madvise/process_madvise.h b/testcases/kernel/syscalls/process_madvise/process_madvise.h
new file mode 100644
index 000000000..5b227ada0
--- /dev/null
+++ b/testcases/kernel/syscalls/process_madvise/process_madvise.h
@@ -0,0 +1,101 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+#ifndef PROCESS_MADVISE_H__
+#define PROCESS_MADVISE_H__
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "tst_safe_stdio.h"
+
+struct addr_mapping {
+ int size;
+ int rss;
+ int pss;
+ int shared_clean;
+ int shared_dirty;
+ int private_clean;
+ int private_dirty;
+ int referenced;
+ int anonymous;
+ int anon_huge_pages;
+ int shmem_huge_pages;
+ int shmem_pmd_mapped;
+ int swap;
+ int kernel_page_size;
+ int mmu_page_size;
+ int locked;
+ int protection_key;
+};
+
+static inline void read_address_mapping(unsigned long address, struct addr_mapping *mapping)
+{
+ FILE *f;
+ int found = 0;
+ char label[BUFSIZ];
+ char line[BUFSIZ];
+ char smaps[BUFSIZ];
+ char ptr_str[BUFSIZ];
+ int value;
+
+ snprintf(smaps, BUFSIZ, "/proc/%i/smaps", getpid());
+ snprintf(ptr_str, BUFSIZ, "%lx", address);
+
+ f = SAFE_FOPEN(smaps, "r");
+
+ while (fgets(line, BUFSIZ, f) != NULL) {
+ if (strncmp(ptr_str, line, strlen(ptr_str)) == 0)
+ found = 1;
+
+ if (!found)
+ continue;
+
+ if (found && strncmp(line, "VmFlags", 7) == 0)
+ break;
+
+ if (sscanf(line, "%31[^:]: %d", label, &value) > 0) {
+ if (strcmp(label, "Size") == 0)
+ mapping->size = value;
+ else if (strcmp(label, "Rss") == 0)
+ mapping->rss = value;
+ else if (strcmp(label, "Pss") == 0)
+ mapping->pss = value;
+ else if (strcmp(label, "Shared_Clean") == 0)
+ mapping->shared_clean = value;
+ else if (strcmp(label, "Shared_Dirty") == 0)
+ mapping->shared_dirty = value;
+ else if (strcmp(label, "Private_Clean") == 0)
+ mapping->private_clean = value;
+ else if (strcmp(label, "Private_Dirty") == 0)
+ mapping->private_dirty = value;
+ else if (strcmp(label, "Referenced") == 0)
+ mapping->referenced = value;
+ else if (strcmp(label, "Anonymous") == 0)
+ mapping->anonymous = value;
+ else if (strcmp(label, "AnonHugePages") == 0)
+ mapping->anon_huge_pages = value;
+ else if (strcmp(label, "ShmemHugePages") == 0)
+ mapping->shmem_huge_pages = value;
+ else if (strcmp(label, "ShmemPmdMapped") == 0)
+ mapping->shmem_pmd_mapped = value;
+ else if (strcmp(label, "Swap") == 0)
+ mapping->swap = value;
+ else if (strcmp(label, "KernelPageSize") == 0)
+ mapping->kernel_page_size = value;
+ else if (strcmp(label, "MMUPageSize") == 0)
+ mapping->mmu_page_size = value;
+ else if (strcmp(label, "Locked") == 0)
+ mapping->locked = value;
+ else if (strcmp(label, "ProtectionKey") == 0)
+ mapping->protection_key = value;
+ }
+ }
+
+ SAFE_FCLOSE(f);
+}
+
+#endif
diff --git a/testcases/kernel/syscalls/process_madvise/process_madvise01.c b/testcases/kernel/syscalls/process_madvise/process_madvise01.c
new file mode 100644
index 000000000..0fd3c1ef4
--- /dev/null
+++ b/testcases/kernel/syscalls/process_madvise/process_madvise01.c
@@ -0,0 +1,131 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * [Description]
+ *
+ * Allocate anonymous memory pages inside child and reclaim it with
+ * MADV_PAGEOUT. Then check if memory pages have been swapped out by looking
+ * at smaps information.
+ *
+ * The advice might be ignored for some pages in the range when it is
+ * not applicable, so test passes if swap memory increases after
+ * reclaiming memory with MADV_PAGEOUT.
+ */
+
+#define _GNU_SOURCE
+
+#include <sys/mman.h>
+#include "tst_test.h"
+#include "lapi/mmap.h"
+#include "lapi/syscalls.h"
+#include "process_madvise.h"
+
+#define MEM_CHILD (1 * TST_MB)
+
+static void **data_ptr;
+
+static void child_alloc(void)
+{
+ char data[MEM_CHILD];
+ struct addr_mapping map_before;
+ struct addr_mapping map_after;
+
+ memset(data, 'a', MEM_CHILD);
+
+ tst_res(TINFO, "Allocate memory: %d bytes", MEM_CHILD);
+
+ *data_ptr = SAFE_MMAP(NULL, MEM_CHILD,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED | MAP_ANONYMOUS, -1, 0);
+
+ memset(*data_ptr, 'a', MEM_CHILD);
+
+ memset(&map_before, 0, sizeof(struct addr_mapping));
+ read_address_mapping((unsigned long)*data_ptr, &map_before);
+
+ TST_CHECKPOINT_WAKE_AND_WAIT(0);
+
+ memset(&map_after, 0, sizeof(struct addr_mapping));
+ read_address_mapping((unsigned long)*data_ptr, &map_after);
+
+ if (memcmp(*data_ptr, data, MEM_CHILD) != 0) {
+ tst_res(TFAIL, "Dirty memory after reclaiming it");
+ return;
+ }
+
+ SAFE_MUNMAP(*data_ptr, MEM_CHILD);
+ *data_ptr = NULL;
+
+ TST_EXP_EXPR(map_before.swap < map_after.swap,
+ "Most of the memory has been swapped out: %dkB out of %dkB",
+ map_after.swap - map_before.swap,
+ MEM_CHILD / TST_KB);
+}
+
+static void setup(void)
+{
+ data_ptr = SAFE_MMAP(NULL, sizeof(void *),
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED | MAP_ANONYMOUS, -1, 0);
+}
+
+static void cleanup(void)
+{
+ if (*data_ptr)
+ SAFE_MUNMAP(*data_ptr, MEM_CHILD);
+
+ if (data_ptr)
+ SAFE_MUNMAP(data_ptr, sizeof(void *));
+}
+
+static void run(void)
+{
+ int ret;
+ int pidfd;
+ pid_t pid_alloc;
+ struct iovec vec;
+
+ pid_alloc = SAFE_FORK();
+ if (!pid_alloc) {
+ child_alloc();
+ return;
+ }
+
+ TST_CHECKPOINT_WAIT(0);
+
+ tst_res(TINFO, "Reclaim memory using MADV_PAGEOUT");
+
+ pidfd = SAFE_PIDFD_OPEN(pid_alloc, 0);
+
+ vec.iov_base = *data_ptr;
+ vec.iov_len = MEM_CHILD;
+
+ ret = tst_syscall(__NR_process_madvise, pidfd, &vec, 1UL,
+ MADV_PAGEOUT, 0UL);
+
+ if (ret == -1)
+ tst_brk(TBROK | TERRNO, "process_madvise failed");
+
+ if (ret != MEM_CHILD)
+ tst_brk(TBROK, "process_madvise reclaimed only %d bytes", ret);
+
+ TST_CHECKPOINT_WAKE(0);
+}
+
+static struct tst_test test = {
+ .setup = setup,
+ .cleanup = cleanup,
+ .test_all = run,
+ .forks_child = 1,
+ .min_kver = "5.10",
+ .needs_checkpoints = 1,
+ .needs_root = 1,
+ .min_swap_avail = MEM_CHILD / TST_MB,
+ .needs_kconfigs = (const char *[]) {
+ "CONFIG_SWAP=y",
+ NULL
+ },
+};
diff --git a/testcases/kernel/syscalls/quotactl/quotactl08.c b/testcases/kernel/syscalls/quotactl/quotactl08.c
index da1d62a32..0fabb51a5 100644
--- a/testcases/kernel/syscalls/quotactl/quotactl08.c
+++ b/testcases/kernel/syscalls/quotactl/quotactl08.c
@@ -28,6 +28,7 @@
* - turn off quota with Q_QUOTAOFF flag for group
*
* It is similar to quotactl01.c, only two difference
+ *
* - use new quotactl_fd syscalls if supports
* - quota file hidden in filesystem
*
diff --git a/testcases/kernel/syscalls/readahead/readahead02.c b/testcases/kernel/syscalls/readahead/readahead02.c
index 7acf4bb18..dc03c5931 100644
--- a/testcases/kernel/syscalls/readahead/readahead02.c
+++ b/testcases/kernel/syscalls/readahead/readahead02.c
@@ -318,6 +318,19 @@ static void test_readahead(unsigned int n)
tst_res(TCONF, "Page cache on your system is too small "
"to hold whole testfile.");
}
+
+ /*
+ * The time consuming of readahead quite depending on the platform IO
+ * speed, sometime test timeout when the default max_runtime is used up.
+ *
+ * readahead02.c:221: TINFO: Test #2: POSIX_FADV_WILLNEED on file
+ * readahead02.c:285: TINFO: read_testfile(0) took: 26317623 usec
+ * readahead02.c:286: TINFO: read_testfile(1) took: 26101484 usec
+ *
+ * Here raise the maximum runtime dynamically.
+ */
+ if ((tc+1)->readahead)
+ tst_set_max_runtime(test.max_runtime + (usec + usec_ra) / 1000000);
}
@@ -352,7 +365,7 @@ static void setup_readahead_length(void)
/* raise bdi limit as much as kernel allows */
ra_new_limit = testfile_size / 1024;
while (ra_new_limit > pagesize / 1024) {
- FILE_PRINTF(sys_bdi_ra_path, "%d", ra_new_limit);
+ SAFE_FILE_PRINTF(sys_bdi_ra_path, "%d", ra_new_limit);
SAFE_FILE_SCANF(sys_bdi_ra_path, "%d", &ra_limit);
if (ra_limit == ra_new_limit) {
diff --git a/testcases/kernel/syscalls/readlinkat/readlinkat01.c b/testcases/kernel/syscalls/readlinkat/readlinkat01.c
index 985890ebe..b1214c3ae 100644
--- a/testcases/kernel/syscalls/readlinkat/readlinkat01.c
+++ b/testcases/kernel/syscalls/readlinkat/readlinkat01.c
@@ -1,143 +1,103 @@
-/******************************************************************************
- *
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
* Copyright (c) International Business Machines Corp., 2006
- * Author: Yi Yang <yyangcdl@cn.ibm.com>
* Copyright (c) Cyril Hrubis 2014 <chrubis@suse.cz>
+ * Copyright (c) Linux Test Project, 2003-2023
+ * Author: Yi Yang <yyangcdl@cn.ibm.com>
+ */
+
+/*\
+ * [Description]
*
- * 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
- *
- * This test case will verify basic function of readlinkat
- * added by kernel 2.6.16 or up.
+ * Check the basic functionality of the readlinkat() system call.
*
- *****************************************************************************/
+ * - readlinkat() passes if dirfd is directory file descriptor
+ * and the pathname is relative.
+ * - readlinkat() passes if the pathname is abspath, then dirfd
+ * is ignored.
+ * - readlinkat() passes if dirfd is the special value AT_FDCWD
+ * and the pathname is relative.
+ * - readlinkat() passes if pathname is an empty string, in which
+ * case the call operates on the symbolic link referred to by dirfd.
+ */
-#define _GNU_SOURCE
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <fcntl.h>
#include <stdlib.h>
-#include <errno.h>
-#include <string.h>
-#include <signal.h>
-#include "test.h"
-#include "safe_macros.h"
-#include "lapi/readlinkat.h"
-
-static void setup(void);
-static void cleanup(void);
+#include <stdio.h>
+#include "tst_test.h"
+#include "lapi/fcntl.h"
-char *TCID = "readlinkat01";
+#define TEST_FILE "readlink_file"
+#define TEST_SYMLINK "readlink_symlink"
-static int dir_fd, fd;
-static int fd_invalid = 100;
+static int file_fd, dir_fd, dir_fd2;
static int fd_atcwd = AT_FDCWD;
-
-#define TEST_SYMLINK "readlink_symlink"
-#define TEST_FILE "readlink_file"
-
-static char abspath[1024];
-
-static struct test_case {
- int *dir_fd;
- const char *path;
- const char *exp_buf;
- int exp_ret;
- int exp_errno;
-} test_cases[] = {
- {&dir_fd, TEST_SYMLINK, TEST_FILE, sizeof(TEST_FILE)-1, 0},
- {&dir_fd, abspath, TEST_FILE, sizeof(TEST_FILE)-1, 0},
- {&fd, TEST_SYMLINK, NULL, -1, ENOTDIR},
- {&fd_invalid, TEST_SYMLINK, NULL, -1, EBADF},
- {&fd_atcwd, TEST_SYMLINK, TEST_FILE, sizeof(TEST_FILE)-1, 0},
+static const char *abspath;
+static const char *testsymlink;
+static const char *emptypath;
+
+static struct tcase {
+ int *fd;
+ const char **path;
+} tcases[] = {
+ {&dir_fd, &testsymlink},
+ {&dir_fd, &abspath},
+ {&file_fd, &abspath},
+ {&fd_atcwd, &abspath},
+ {&fd_atcwd, &testsymlink},
+ {&dir_fd2, &emptypath},
};
-int TST_TOTAL = ARRAY_SIZE(test_cases);
-
-static void verify_readlinkat(struct test_case *test)
+static void verify_readlinkat(unsigned int i)
{
char buf[1024];
+ struct tcase *tc = &tcases[i];
memset(buf, 0, sizeof(buf));
- TEST(readlinkat(*test->dir_fd, test->path, buf, sizeof(buf)));
-
- if (TEST_RETURN != test->exp_ret) {
- tst_resm(TFAIL | TTERRNO,
- "readlinkat() returned %ld, expected %d",
- TEST_RETURN, test->exp_ret);
- return;
- }
-
- if (TEST_ERRNO != test->exp_errno) {
- tst_resm(TFAIL | TTERRNO,
- "readlinkat() returned %ld, expected %d",
- TEST_RETURN, test->exp_ret);
- return;
- }
-
- if (test->exp_ret > 0 && strcmp(test->exp_buf, buf)) {
- tst_resm(TFAIL, "Unexpected buffer have '%s', expected '%s'",
- buf, test->exp_buf);
- return;
- }
-
- tst_resm(TPASS | TTERRNO, "readlinkat() returned %ld", TEST_RETURN);
-}
-
-int main(int ac, char **av)
-{
- int lc;
- int i;
-
- tst_parse_opts(ac, av, NULL, NULL);
-
- setup();
+ TST_EXP_POSITIVE(readlinkat(*tc->fd, *tc->path, buf, sizeof(buf)),
+ "readlinkat(%d, %s, %s, %ld)",
+ *tc->fd, *tc->path, buf, sizeof(buf));
- for (lc = 0; TEST_LOOPING(lc); lc++) {
- for (i = 0; i < TST_TOTAL; i++)
- verify_readlinkat(&test_cases[i]);
- }
-
- cleanup();
- tst_exit();
+ if (strcmp(buf, TEST_FILE) == 0)
+ tst_res(TPASS, "The filename in buffer is correct");
+ else
+ tst_res(TFAIL, "Wrong filename in buffer '%s'", buf);
}
static void setup(void)
{
- tst_tmpdir();
char *tmpdir = tst_get_tmpdir();
- snprintf(abspath, sizeof(abspath), "%s/" TEST_SYMLINK, tmpdir);
+ abspath = tst_aprintf("%s/" TEST_SYMLINK, tmpdir);
free(tmpdir);
- fd = SAFE_OPEN(cleanup, TEST_FILE, O_CREAT, 0600);
- SAFE_SYMLINK(cleanup, TEST_FILE, TEST_SYMLINK);
- dir_fd = SAFE_OPEN(cleanup, ".", O_DIRECTORY);
-
- TEST_PAUSE;
+ file_fd = SAFE_OPEN(TEST_FILE, O_CREAT, 0600);
+ SAFE_SYMLINK(TEST_FILE, TEST_SYMLINK);
+ dir_fd = SAFE_OPEN(".", O_DIRECTORY);
+ dir_fd2 = SAFE_OPEN(TEST_SYMLINK, O_PATH | O_NOFOLLOW);
}
static void cleanup(void)
{
- if (fd > 0 && close(fd))
- tst_resm(TWARN | TERRNO, "Failed to close fd");
+ if (file_fd > -1)
+ SAFE_CLOSE(file_fd);
- if (dir_fd > 0 && close(dir_fd))
- tst_resm(TWARN | TERRNO, "Failed to close dir_fd");
+ if (dir_fd > -1)
+ SAFE_CLOSE(dir_fd);
- tst_rmdir();
+ if (dir_fd2 > -1)
+ SAFE_CLOSE(dir_fd2);
}
+
+static struct tst_test test = {
+ .test = verify_readlinkat,
+ .needs_tmpdir = 1,
+ .setup = setup,
+ .cleanup = cleanup,
+ .bufs = (struct tst_buffers []) {
+ {&testsymlink, .str = TEST_SYMLINK},
+ {&emptypath, .str = ""},
+ {},
+ },
+ .tcnt = ARRAY_SIZE(tcases),
+};
diff --git a/testcases/kernel/syscalls/readlinkat/readlinkat02.c b/testcases/kernel/syscalls/readlinkat/readlinkat02.c
index d30c1917a..64afb898f 100644
--- a/testcases/kernel/syscalls/readlinkat/readlinkat02.c
+++ b/testcases/kernel/syscalls/readlinkat/readlinkat02.c
@@ -1,122 +1,85 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2014 Fujitsu Ltd.
+ * Copyright (c) Linux Test Project, 2003-2023
* Author: Zeng Linggang <zenglg.jy@cn.fujitsu.com>
+ */
+
+/*\
+ * [Description]
*
- * 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.
+ * - readlinkat() fails with EINVAL if the bufsiz is 0.
*
- * 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 Library General Public License for more details.
+ * - readlinkat() fails with EINVAL if the named file is not a symbolic link.
*
- * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * - readlinkat() fails with ENOTDIR if the component of the path prefix is
+ * not a directory.
*
- */
-/*
- * Test Description:
- * Verify that,
- * 1. bufsiz is 0, EINVAL should be returned.
- * 2. The named file is not a symbolic link, EINVAL should be returned.
- * 3. The component of the path prefix is not a directory, ENOTDIR should be
- * returned.
- * 4. pathname is relative and dirfd is a file descriptor referring to a file
- * other than a directory, ENOTDIR should be returned.
+ * - readlinkat() fails with ENOTDIR if the pathname is relative and
+ * dirfd is a file descriptor referring to a file other than a directory.
+ *
+ * - readlinkat() fails with EBADF if the file descriptor is invalid.
+ *
+ * - readlinkat() fails with ENOENT when the pathname does not exists.
*/
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-
-#include "test.h"
-#include "safe_macros.h"
-#include "lapi/readlinkat.h"
-#include "lapi/syscalls.h"
+#include "tst_test.h"
#define TEST_FILE "test_file"
#define SYMLINK_FILE "symlink_file"
#define BUFF_SIZE 256
static int file_fd, dir_fd;
+static int fd_invalid = -1;
-static struct test_case_t {
- int *dirfd;
+static struct tcase {
+ int *fd;
const char *pathname;
size_t bufsiz;
int exp_errno;
-} test_cases[] = {
+} tcases[] = {
{&dir_fd, SYMLINK_FILE, 0, EINVAL},
{&dir_fd, TEST_FILE, BUFF_SIZE, EINVAL},
{&file_fd, SYMLINK_FILE, BUFF_SIZE, ENOTDIR},
{&dir_fd, "test_file/test_file", BUFF_SIZE, ENOTDIR},
+ {&fd_invalid, SYMLINK_FILE, BUFF_SIZE, EBADF},
+ {&dir_fd, "does_not_exists", BUFF_SIZE, ENOENT},
};
-char *TCID = "readlinkat02";
-int TST_TOTAL = ARRAY_SIZE(test_cases);
-static void setup(void);
-static void cleanup(void);
-static void readlinkat_verify(const struct test_case_t *);
-
-int main(int argc, char **argv)
+static void verify_readlinkat(unsigned int i)
{
- int i, lc;
-
- tst_parse_opts(argc, argv, NULL, NULL);
-
- setup();
+ char buf[BUFF_SIZE];
+ struct tcase *tc = &tcases[i];
- for (lc = 0; TEST_LOOPING(lc); lc++) {
- tst_count = 0;
- for (i = 0; i < TST_TOTAL; i++)
- readlinkat_verify(&test_cases[i]);
- }
+ memset(buf, 0, sizeof(buf));
- cleanup();
- tst_exit();
+ TST_EXP_FAIL(readlinkat(*tc->fd, tc->pathname, buf, tc->bufsiz),
+ tc->exp_errno, "readlinkat(%d, %s, NULL, %ld)",
+ *tc->fd, tc->pathname, tc->bufsiz);
}
static void setup(void)
{
- tst_sig(NOFORK, DEF_HANDLER, cleanup);
+ dir_fd = SAFE_OPEN(".", O_RDONLY);
- TEST_PAUSE;
+ file_fd = SAFE_OPEN(TEST_FILE, O_RDWR | O_CREAT, 0644);
- tst_tmpdir();
-
- dir_fd = SAFE_OPEN(cleanup, "./", O_RDONLY);
-
- file_fd = SAFE_OPEN(cleanup, TEST_FILE, O_RDWR | O_CREAT, 0644);
-
- SAFE_SYMLINK(cleanup, TEST_FILE, SYMLINK_FILE);
-}
-
-static void readlinkat_verify(const struct test_case_t *test)
-{
- char buf[BUFF_SIZE];
- TEST(readlinkat(*test->dirfd, test->pathname, buf, test->bufsiz));
-
- if (TEST_RETURN != -1) {
- tst_resm(TFAIL, "readlinkat succeeded unexpectedly");
- return;
- }
-
- if (TEST_ERRNO == test->exp_errno) {
- tst_resm(TPASS | TTERRNO, "readlinkat failed as expected");
- } else {
- tst_resm(TFAIL | TTERRNO,
- "readlinkat failed unexpectedly; expected: %d - %s",
- test->exp_errno, strerror(test->exp_errno));
- }
+ SAFE_SYMLINK(TEST_FILE, SYMLINK_FILE);
}
static void cleanup(void)
{
- close(dir_fd);
- close(file_fd);
+ if (file_fd > -1)
+ SAFE_CLOSE(file_fd);
- tst_rmdir();
+ if (dir_fd > -1)
+ SAFE_CLOSE(dir_fd);
}
+
+static struct tst_test test = {
+ .test = verify_readlinkat,
+ .needs_tmpdir = 1,
+ .setup = setup,
+ .cleanup = cleanup,
+ .tcnt = ARRAY_SIZE(tcases),
+};
diff --git a/testcases/kernel/syscalls/recvmsg/recvmsg01.c b/testcases/kernel/syscalls/recvmsg/recvmsg01.c
index 3ce7ab027..80c1b3aa9 100644
--- a/testcases/kernel/syscalls/recvmsg/recvmsg01.c
+++ b/testcases/kernel/syscalls/recvmsg/recvmsg01.c
@@ -1,364 +1,356 @@
+// 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) 2001 Wayne Boyer International Business Machines
+ * Copyright (c) Linux Test Project, 2002-2022
+ * Copyright (c) 2023 Wei Gao <wegao@suse.com>
*/
-/*
- * Test Name: recvmsg01
- *
- * Test Description:
- * Verify that recvmsg() returns the proper errno for various failure cases
- *
- * Usage: <for command-line>
- * recvmsg01 [-c n] [-e] [-i n] [-I x] [-P x] [-t]
- * where, -c n : Run n copies concurrently.
- * -e : Turn on errno logging.
- * -i n : Execute test n times.
- * -I x : Execute test for x seconds.
- * -P x : Pause for x seconds between iterations.
- * -t : Turn on syscall timing.
- *
- * HISTORY
- * 07/2001 Ported by Wayne Boyer
- *
- * RESTRICTIONS:
- * None.
+/*\
+ * [Description]
*
+ * Verify that recvmsg() returns the proper errno for various failure cases.
*/
#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include <fcntl.h>
-
+#include <stdlib.h>
#include <sys/wait.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/signal.h>
-#include <sys/uio.h>
-#include <sys/un.h>
-#include <sys/file.h>
-
-#include <netinet/in.h>
-
-#include "test.h"
-#include "safe_macros.h"
-
-char *TCID = "recvmsg01";
-int testno;
-
-char buf[1024], cbuf[1024];
-int s; /* socket descriptor */
-int passed_fd = -1; /* rights-passing test descriptor */
-struct sockaddr_in sin1, from;
-struct sockaddr_un sun1;
-struct msghdr msgdat;
-struct cmsghdr *control = 0;
-int controllen = 0;
-struct iovec iov[1];
+#include "tst_test.h"
+
+#define MSG "from recvmsg01 server"
+#define BUF_SIZE 1024
+#define CONTROL_LEN (128 * 1024)
+
+static char recv_buf[BUF_SIZE], cbuf[BUF_SIZE];
+static int sock;
+static struct sockaddr_in sin1, from;
+static struct sockaddr_un sun1;
+static struct msghdr msgdat;
+static struct cmsghdr *control;
+static int controllen;
+static struct iovec iov[1];
static int sfd; /* shared between do_child and start_server */
static int ufd; /* shared between do_child and start_server */
-
-void setup(void);
-void setup0(void);
-void setup1(void);
-void setup2(void);
-void setup3(void);
-void setup4(void);
-void cleanup(void);
-void cleanup0(void);
-void cleanup1(void);
-void cleanup2(void);
-void do_child(void);
-
-void sender(int);
-pid_t start_server(struct sockaddr_in *, struct sockaddr_un *);
-
-struct test_case_t { /* test case structure */
- int domain; /* PF_INET, PF_UNIX, ... */
- int type; /* SOCK_STREAM, SOCK_DGRAM ... */
- int proto; /* protocol number (usually 0 = default) */
+static pid_t pid;
+static char tmpsunpath[BUF_SIZE];
+
+static void setup_all(void);
+static void setup_invalid_sock(int);
+static void setup_valid_sock(int);
+static void setup_valid_msg_control(int);
+static void setup_large_msg_control(int);
+static void cleanup_all(void);
+static void cleanup_invalid_sock(int);
+static void cleanup_close_sock(int);
+static void cleanup_reset_all(int);
+static void do_child(void);
+static pid_t start_server(struct sockaddr_in *, struct sockaddr_un *);
+
+static struct tcase {
+ int domain;
+ int type;
+ int protocol;
struct iovec *iov;
int iovcnt;
- void *buf; /* recv data buffer */
- int buflen; /* recv buffer length */
+ void *recv_buf;
+ int buflen;
struct msghdr *msg;
- unsigned flags;
- struct sockaddr *from; /* from address */
- int fromlen; /* from address value/result buffer length */
- int retval; /* syscall return value */
- int experrno; /* expected errno */
- void (*setup) (void);
- void (*cleanup) (void);
+ unsigned int flags;
+ struct sockaddr *from;
+ int fromlen;
+ int exp_errno;
+ void (*setup)(int n);
+ void (*cleanup)(int n);
char *desc;
-} tdat[] = {
-/* 1 */
- {
- PF_INET, SOCK_STREAM, 0, iov, 1, buf, sizeof(buf), &msgdat, 0,
- (struct sockaddr *)&from, sizeof(from),
- -1, EBADF, setup0, cleanup0, "bad file descriptor"}
- ,
-/* 2 */
+} tcases[] = {
{
- 0, 0, 0, iov, 1, (void *)buf, sizeof(buf), &msgdat, 0,
- (struct sockaddr *)&from, sizeof(from),
- -1, ENOTSOCK, setup0, cleanup0, "invalid socket"}
- ,
-/* 3 */
+ .domain = PF_INET,
+ .type = SOCK_STREAM,
+ .iov = iov,
+ .iovcnt = 1,
+ .recv_buf = recv_buf,
+ .buflen = sizeof(recv_buf),
+ .msg = &msgdat,
+ .from = (struct sockaddr *)&from,
+ .fromlen = sizeof(from),
+ .exp_errno = EBADF,
+ .setup = setup_invalid_sock,
+ .cleanup = cleanup_invalid_sock,
+ .desc = "bad file descriptor",
+ },
{
- PF_INET, SOCK_STREAM, 0, iov, 1, (void *)buf, sizeof(buf),
- &msgdat, 0, (struct sockaddr *)-1, sizeof(from), 0,
- ENOTSOCK, setup1, cleanup1, "invalid socket buffer"}
- ,
-/* 4 */
+ .domain = PF_INET,
+ .type = SOCK_STREAM,
+ .iov = iov,
+ .iovcnt = 1,
+ .recv_buf = (void *)recv_buf,
+ .buflen = sizeof(recv_buf),
+ .msg = &msgdat,
+ .from = (struct sockaddr *)&from,
+ .fromlen = sizeof(from),
+ .exp_errno = ENOTSOCK,
+ .setup = setup_invalid_sock,
+ .cleanup = cleanup_invalid_sock,
+ .desc = "invalid socket",
+ },
{
- PF_INET, SOCK_STREAM, 0, iov, 1, (void *)buf, sizeof(buf),
- &msgdat, -1, (struct sockaddr *)&from, -1, -1,
- EINVAL, setup1, cleanup1, "invalid socket length"},
-/* 5 */
+ .domain = PF_INET,
+ .type = SOCK_STREAM,
+ .iov = iov,
+ .iovcnt = 1,
+ .recv_buf = (void *)recv_buf,
+ .buflen = sizeof(recv_buf),
+ .msg = &msgdat,
+ .flags = -1,
+ .from = (struct sockaddr *)&from,
+ .fromlen = -1,
+ .exp_errno = EINVAL,
+ .setup = setup_valid_sock,
+ .cleanup = cleanup_close_sock,
+ .desc = "invalid socket length",
+ },
{
- PF_INET, SOCK_STREAM, 0, iov, 1, (void *)-1, sizeof(buf),
- &msgdat, 0, (struct sockaddr *)&from, sizeof(from),
- -1, EFAULT, setup1, cleanup1, "invalid recv buffer"}
- ,
-/* 6 */
+ .domain = PF_INET,
+ .type = SOCK_STREAM,
+ .iov = iov,
+ .iovcnt = 1,
+ .recv_buf = (void *)-1,
+ .buflen = sizeof(recv_buf),
+ .msg = &msgdat,
+ .from = (struct sockaddr *)&from,
+ .fromlen = sizeof(from),
+ .exp_errno = EFAULT,
+ .setup = setup_valid_sock,
+ .cleanup = cleanup_close_sock,
+ .desc = "invalid recv buffer",
+ },
{
- PF_INET, SOCK_STREAM, 0, 0, 1, (void *)buf, sizeof(buf),
- &msgdat, 0, (struct sockaddr *)&from, sizeof(from),
- -1, EFAULT, setup1, cleanup1, "invalid iovec buffer"}
- ,
-/* 7 */
+ .domain = PF_INET,
+ .type = SOCK_STREAM,
+ .iovcnt = 1,
+ .recv_buf = recv_buf,
+ .buflen = sizeof(recv_buf),
+ .msg = &msgdat,
+ .from = (struct sockaddr *)&from,
+ .fromlen = sizeof(from),
+ .exp_errno = EFAULT,
+ .setup = setup_valid_sock,
+ .cleanup = cleanup_close_sock,
+ .desc = "invalid iovec buffer",
+ },
{
- PF_INET, SOCK_STREAM, 0, iov, -1, (void *)buf, sizeof(buf),
- &msgdat, 0, (struct sockaddr *)&from, sizeof(from),
- -1, EMSGSIZE, setup1, cleanup1, "invalid iovec count"}
- ,
-/* 8 */
+ .domain = PF_INET,
+ .type = SOCK_STREAM,
+ .iov = iov,
+ .iovcnt = -1,
+ .recv_buf = recv_buf,
+ .buflen = sizeof(recv_buf),
+ .msg = &msgdat,
+ .from = (struct sockaddr *)&from,
+ .fromlen = sizeof(from),
+ .exp_errno = EMSGSIZE,
+ .setup = setup_valid_sock,
+ .cleanup = cleanup_close_sock,
+ .desc = "invalid iovec count",
+ },
{
- PF_UNIX, SOCK_STREAM, 0, iov, 1, (void *)buf, sizeof(buf),
- &msgdat, 0, (struct sockaddr *)&from, sizeof(from),
- 0, 0, setup2, cleanup2, "rights reception"}
- ,
-/* 9 */
+ .domain = PF_INET,
+ .type = SOCK_STREAM,
+ .iov = iov,
+ .iovcnt = 1,
+ .recv_buf = recv_buf,
+ .buflen = sizeof(recv_buf),
+ .msg = &msgdat,
+ .from = (struct sockaddr *)&from,
+ .fromlen = sizeof(from),
+ .setup = setup_valid_msg_control,
+ .cleanup = cleanup_reset_all,
+ .desc = "permission reception",
+ },
{
- PF_INET, SOCK_STREAM, 0, iov, 1, (void *)buf, sizeof(buf),
- &msgdat, MSG_OOB, (struct sockaddr *)&from,
- sizeof(from), -1, EINVAL, setup1, cleanup1,
- "invalid MSG_OOB flag set"}
- ,
-/* 10 */
+ .domain = PF_INET,
+ .type = SOCK_STREAM,
+ .iov = iov,
+ .iovcnt = 1,
+ .recv_buf = recv_buf,
+ .buflen = sizeof(recv_buf),
+ .msg = &msgdat,
+ .flags = MSG_OOB,
+ .from = (struct sockaddr *)&from,
+ .fromlen = sizeof(from),
+ .exp_errno = EINVAL,
+ .setup = setup_valid_sock,
+ .cleanup = cleanup_close_sock,
+ .desc = "invalid MSG_OOB flag set",
+ },
{
- PF_INET, SOCK_STREAM, 0, iov, 1, (void *)buf, sizeof(buf),
- &msgdat, MSG_ERRQUEUE, (struct sockaddr *)&from,
- sizeof(from), -1, EAGAIN, setup1, cleanup1,
- "invalid MSG_ERRQUEUE flag set"}
- ,
-/* 11 */
+ .domain = PF_INET,
+ .type = SOCK_STREAM,
+ .iov = iov,
+ .iovcnt = 1,
+ .recv_buf = recv_buf,
+ .buflen = sizeof(recv_buf),
+ .msg = &msgdat,
+ .flags = MSG_ERRQUEUE,
+ .from = (struct sockaddr *)&from,
+ .fromlen = sizeof(from),
+ .exp_errno = EAGAIN,
+ .setup = setup_valid_sock,
+ .cleanup = cleanup_close_sock,
+ .desc = "invalid MSG_ERRQUEUE flag set",
+ },
{
- PF_UNIX, SOCK_STREAM, 0, iov, 1, (void *)buf, sizeof(buf),
- &msgdat, 0, (struct sockaddr *)&from, sizeof(from),
- 0, EINVAL, setup3, cleanup2, "invalid cmsg length"}
- ,
-/* 12 */
- {
- PF_UNIX, SOCK_STREAM, 0, iov, 1, (void *)buf, sizeof(buf),
- &msgdat, 0, (struct sockaddr *)&from, sizeof(from),
- 0, 0, setup4, cleanup2, "large cmesg length"}
-,};
-
-int TST_TOTAL = sizeof(tdat) / sizeof(tdat[0]);
-
-#ifdef UCLINUX
-static char *argv0;
-#endif
-
-int main(int argc, char *argv[])
+ .domain = PF_INET,
+ .type = SOCK_STREAM,
+ .iov = iov,
+ .iovcnt = 1,
+ .recv_buf = recv_buf,
+ .buflen = sizeof(recv_buf),
+ .msg = &msgdat,
+ .from = (struct sockaddr *)&from,
+ .fromlen = sizeof(from),
+ .setup = setup_large_msg_control,
+ .cleanup = cleanup_reset_all,
+ .desc = "large cmesg length",
+ },
+
+};
+
+static void run(unsigned int n)
{
- int lc;
-
- tst_parse_opts(argc, argv, NULL, NULL);
-#ifdef UCLINUX
- argv0 = argv[0];
- maybe_run_child(&do_child, "dd", &sfd, &ufd);
-#endif
-
- setup();
-
- for (lc = 0; TEST_LOOPING(lc); ++lc) {
- tst_count = 0;
- for (testno = 0; testno < TST_TOTAL; ++testno) {
- if ((tst_kvercmp(3, 17, 0) < 0)
- && (tdat[testno].flags & MSG_ERRQUEUE)
- && (tdat[testno].type & SOCK_STREAM)) {
- tst_resm(TCONF, "skip MSG_ERRQUEUE test, "
- "it's supported from 3.17");
- continue;
- }
+ struct tcase *tc = &tcases[n];
+ int ret = tc->exp_errno ? -1 : 0;
- tdat[testno].setup();
-
- /* setup common to all tests */
- iov[0].iov_base = tdat[testno].buf;
- iov[0].iov_len = tdat[testno].buflen;
- msgdat.msg_name = tdat[testno].from;
- msgdat.msg_namelen = tdat[testno].fromlen;
- msgdat.msg_iov = tdat[testno].iov;
- msgdat.msg_iovlen = tdat[testno].iovcnt;
- msgdat.msg_control = control;
- msgdat.msg_controllen = controllen;
- msgdat.msg_flags = 0;
-
- TEST(recvmsg(s, tdat[testno].msg, tdat[testno].flags));
- if (TEST_RETURN >= 0)
- TEST_RETURN = 0; /* all nonzero equal here */
- if (TEST_RETURN != tdat[testno].retval ||
- (TEST_RETURN < 0 &&
- TEST_ERRNO != tdat[testno].experrno)) {
- tst_resm(TFAIL, "%s ; returned"
- " %ld (expected %d), errno %d (expected"
- " %d)", tdat[testno].desc,
- TEST_RETURN, tdat[testno].retval,
- TEST_ERRNO, tdat[testno].experrno);
- } else {
- tst_resm(TPASS, "%s successful",
- tdat[testno].desc);
- }
- tdat[testno].cleanup();
- }
+ if ((tst_kvercmp(3, 17, 0) < 0)
+ && (tc->flags & MSG_ERRQUEUE)
+ && (tc->type & SOCK_STREAM)) {
+ tst_res(TCONF, "MSG_ERRQUEUE requires kernel >= 3.17");
+ return;
+ }
+
+ setup_all();
+ tc->setup(n);
+
+ iov[0].iov_base = tc->recv_buf;
+ iov[0].iov_len = tc->buflen;
+ msgdat.msg_name = tc->from;
+ msgdat.msg_namelen = tc->fromlen;
+ msgdat.msg_iov = tc->iov;
+ msgdat.msg_iovlen = tc->iovcnt;
+ msgdat.msg_control = control;
+ msgdat.msg_controllen = controllen;
+ msgdat.msg_flags = 0;
+
+ TEST(recvmsg(sock, tc->msg, tc->flags));
+ if (TST_RET >= 0)
+ TST_RET = 0;
+
+ if (TST_RET != ret) {
+ tst_res(TFAIL | TTERRNO, "%s: expected %d, returned %ld",
+ tc->desc, ret, TST_RET);
+ } else if (TST_ERR != tc->exp_errno) {
+ tst_res(TFAIL | TTERRNO,
+ "%s: expected %s",
+ tc->desc, tst_strerrno(tc->exp_errno));
+ } else {
+ tst_res(TPASS, "%s passed", tc->desc);
}
- cleanup();
- tst_exit();
+ tc->cleanup(n);
+ cleanup_all();
}
-pid_t pid;
-char tmpsunpath[1024];
-void setup(void)
+static void setup_all(void)
{
int tfd;
- TEST_PAUSE;
- tst_tmpdir();
+ sun1.sun_family = AF_UNIX;
+
(void)strcpy(tmpsunpath, "udsockXXXXXX");
tfd = mkstemp(tmpsunpath);
- close(tfd);
- unlink(tmpsunpath);
- sun1.sun_family = AF_UNIX;
+ SAFE_CLOSE(tfd);
+ SAFE_UNLINK(tmpsunpath);
(void)strcpy(sun1.sun_path, tmpsunpath);
-
- signal(SIGPIPE, SIG_IGN);
-
+ SAFE_SIGNAL(SIGPIPE, SIG_IGN);
pid = start_server(&sin1, &sun1);
}
-void cleanup(void)
+static void cleanup_all(void)
{
if (pid > 0) {
(void)kill(pid, SIGKILL); /* kill server */
wait(NULL);
}
- if (tmpsunpath[0] != '\0')
- (void)unlink(tmpsunpath);
- tst_rmdir();
+ if (tmpsunpath[0] != '\0')
+ (void)SAFE_UNLINK(tmpsunpath);
}
-void setup0(void)
+static void setup_invalid_sock(int n)
{
- if (tdat[testno].experrno == EBADF)
- s = 400; /* anything not an open file */
- else if ((s = open("/dev/null", O_WRONLY)) == -1)
- tst_brkm(TBROK | TERRNO, cleanup, "open(/dev/null) failed");
+ if (tcases[n].exp_errno == EBADF)
+ sock = 400; /* anything not an open file */
+ else
+ sock = SAFE_OPEN("/dev/null", O_WRONLY);
}
-void cleanup0(void)
+static void cleanup_invalid_sock(int n)
{
- s = -1;
+ if (tcases[n].exp_errno == EBADF)
+ sock = -1;
+ else
+ SAFE_CLOSE(sock);
}
-void setup1(void)
+static void setup_valid_sock(int n)
{
fd_set rdfds;
struct timeval timeout;
- int n;
-
- s = SAFE_SOCKET(cleanup, tdat[testno].domain, tdat[testno].type,
- tdat[testno].proto);
- if (tdat[testno].type == SOCK_STREAM) {
- if (tdat[testno].domain == PF_INET) {
- SAFE_CONNECT(cleanup, s, (struct sockaddr *)&sin1,
- sizeof(sin1));
+
+ sock = SAFE_SOCKET(tcases[n].domain, tcases[n].type, tcases[n].protocol);
+
+ if (tcases[n].type == SOCK_STREAM) {
+ if (tcases[n].domain == PF_INET) {
+ SAFE_CONNECT(sock, (struct sockaddr *)&sin1, sizeof(sin1));
/* Wait for something to be readable, else we won't detect EFAULT on recv */
FD_ZERO(&rdfds);
- FD_SET(s, &rdfds);
+ FD_SET(sock, &rdfds);
timeout.tv_sec = 2;
timeout.tv_usec = 0;
- n = select(s + 1, &rdfds, 0, 0, &timeout);
- if (n != 1 || !FD_ISSET(s, &rdfds))
- tst_brkm(TBROK, cleanup,
- "client setup1 failed - no message ready in 2 sec");
- } else if (tdat[testno].domain == PF_UNIX) {
- SAFE_CONNECT(cleanup, s, (struct sockaddr *)&sun1,
- sizeof(sun1));
+ n = select(sock + 1, &rdfds, 0, 0, &timeout);
+
+ if (n != 1 || !FD_ISSET(sock, &rdfds))
+ tst_brk(TBROK, "no message ready in %d sec", (int)timeout.tv_sec);
+
+ } else if (tcases[n].domain == PF_UNIX) {
+ SAFE_CONNECT(sock, (struct sockaddr *)&sun1, sizeof(sun1));
}
}
}
-void setup2(void)
+static void setup_valid_msg_control(int n)
{
- setup1();
- if (write(s, "R", 1) < 0)
- tst_brkm(TBROK | TERRNO, cleanup, "test setup failed: write:");
+ setup_valid_sock(n);
+ SAFE_SEND(1, sock, "R", 1, 0);
control = (struct cmsghdr *)cbuf;
controllen = control->cmsg_len = sizeof(cbuf);
}
-void setup3(void)
+static void setup_large_msg_control(int n)
{
- setup2();
- controllen = sizeof(struct cmsghdr) - 1;
+ setup_valid_msg_control(n);
+ controllen = CONTROL_LEN;
}
-void setup4(void)
+static void cleanup_close_sock(int n LTP_ATTRIBUTE_UNUSED)
{
- setup2();
- controllen = 128 * 1024;
+ SAFE_CLOSE(sock);
}
-void cleanup1(void)
+static void cleanup_reset_all(int n LTP_ATTRIBUTE_UNUSED)
{
- (void)close(s);
- close(ufd);
- close(sfd);
- s = -1;
-}
+ SAFE_CLOSE(sock);
-void cleanup2(void)
-{
- close(ufd);
- close(sfd);
- (void)close(s);
- s = -1;
-
- if (passed_fd >= 0)
- (void)close(passed_fd);
- passed_fd = -1;
control = 0;
controllen = 0;
}
@@ -373,63 +365,70 @@ pid_t start_server(struct sockaddr_in *ssin, struct sockaddr_un *ssun)
ssin->sin_addr.s_addr = INADDR_ANY;
/* set up inet socket */
- sfd = socket(PF_INET, SOCK_STREAM, 0);
- if (sfd < 0) {
- tst_brkm(TBROK | TERRNO, cleanup, "server socket failed");
- return -1;
- }
- if (bind(sfd, (struct sockaddr *)ssin, sizeof(*ssin)) < 0) {
- tst_brkm(TBROK | TERRNO, cleanup, "server bind failed");
- return -1;
- }
- if (listen(sfd, 10) < 0) {
- tst_brkm(TBROK | TERRNO, cleanup, "server listen failed");
- return -1;
- }
- SAFE_GETSOCKNAME(cleanup, sfd, (struct sockaddr *)ssin, &slen);
+ sfd = SAFE_SOCKET(PF_INET, SOCK_STREAM, 0);
+ SAFE_BIND(sfd, (struct sockaddr *)ssin, sizeof(*ssin));
+ SAFE_LISTEN(sfd, 10);
+ SAFE_GETSOCKNAME(sfd, (struct sockaddr *)ssin, &slen);
/* set up UNIX-domain socket */
- ufd = socket(PF_UNIX, SOCK_STREAM, 0);
- if (ufd < 0) {
- tst_brkm(TBROK | TERRNO, cleanup, "server UD socket failed");
- return -1;
- }
- if (bind(ufd, (struct sockaddr *)ssun, sizeof(*ssun))) {
- tst_brkm(TBROK | TERRNO, cleanup, "server UD bind failed");
- return -1;
- }
- if (listen(ufd, 10) < 0) {
- tst_brkm(TBROK | TERRNO, cleanup, "server UD listen failed");
- return -1;
- }
+ ufd = SAFE_SOCKET(PF_UNIX, SOCK_STREAM, 0);
+ SAFE_BIND(ufd, (struct sockaddr *)ssun, sizeof(*ssun));
+ SAFE_LISTEN(ufd, 10);
- switch ((pid = FORK_OR_VFORK())) {
- case 0: /* child */
-#ifdef UCLINUX
- if (self_exec(argv0, "dd", sfd, ufd) < 0)
- tst_brkm(TBROK | TERRNO, cleanup,
- "server self_exec failed");
-#else
+ pid = SAFE_FORK();
+ if (!pid) {
do_child();
-#endif
- break;
- case -1:
- tst_brkm(TBROK | TERRNO, cleanup, "server fork failed");
- /* fall through */
- default: /* parent */
- (void)close(sfd);
- (void)close(ufd);
- return pid;
+ exit(1);
}
- exit(1);
+
+ SAFE_CLOSE(sfd);
+ SAFE_CLOSE(ufd);
+
+ return pid;
+}
+
+/* for permission test */
+static void sender(int fd)
+{
+ struct msghdr mh = {};
+ struct cmsghdr *control;
+ char tmpfn[BUF_SIZE] = "";
+ char snd_cbuf[BUF_SIZE] = "";
+ int tfd;
+
+ (void)strcpy(tmpfn, "smtXXXXXX");
+ tfd = mkstemp(tmpfn);
+ if (tfd < 0)
+ return;
+
+ /* set up cmsghdr */
+ control = (struct cmsghdr *)snd_cbuf;
+ control->cmsg_len = sizeof(struct cmsghdr) + 4;
+ control->cmsg_level = SOL_SOCKET;
+ control->cmsg_type = SCM_RIGHTS;
+ *(int *)CMSG_DATA(control) = tfd;
+
+ /* set up msghdr */
+ iov[0].iov_base = MSG;
+ iov[0].iov_len = sizeof(MSG);
+ mh.msg_iov = iov;
+ mh.msg_iovlen = 1;
+ mh.msg_flags = 0;
+ mh.msg_control = control;
+ mh.msg_controllen = control->cmsg_len;
+
+ /* do it */
+ SAFE_SENDMSG(sizeof(MSG), fd, &mh, 0);
+ SAFE_CLOSE(tfd);
+ (void)SAFE_UNLINK(tmpfn);
}
-void do_child(void)
+static void do_child(void)
{
struct sockaddr_in fsin;
struct sockaddr_un fsun;
fd_set afds, rfds;
- int nfds, cc, fd;
+ int nfds, fd;
FD_ZERO(&afds);
FD_SET(sfd, &afds);
@@ -455,19 +454,19 @@ void do_child(void)
int newfd;
fromlen = sizeof(fsin);
- newfd = accept(sfd, (struct sockaddr *)&fsin, &fromlen);
+ newfd = SAFE_ACCEPT(sfd, (struct sockaddr *)&fsin, &fromlen);
if (newfd >= 0) {
FD_SET(newfd, &afds);
nfds = MAX(nfds, newfd + 1);
/* send something back */
- (void)write(newfd, "hoser\n", 6);
+ SAFE_SEND(1, newfd, "hi", 2, 0);
}
}
if (FD_ISSET(ufd, &rfds)) {
int newfd;
fromlen = sizeof(fsun);
- newfd = accept(ufd, (struct sockaddr *)&fsun, &fromlen);
+ newfd = SAFE_ACCEPT(ufd, (struct sockaddr *)&fsun, &fromlen);
if (newfd >= 0) {
FD_SET(newfd, &afds);
nfds = MAX(nfds, newfd + 1);
@@ -475,55 +474,22 @@ void do_child(void)
}
for (fd = 0; fd < nfds; ++fd)
if (fd != sfd && fd != ufd && FD_ISSET(fd, &rfds)) {
- char rbuf[1024];
+ char rbuf[BUF_SIZE];
- cc = read(fd, rbuf, sizeof(rbuf));
- if (cc && rbuf[0] == 'R')
+ TEST(read(fd, rbuf, sizeof(rbuf)));
+ if (TST_RET > 0 && rbuf[0] == 'R')
sender(fd);
- if (cc == 0 || (cc < 0 && errno != EINTR)) {
- (void)close(fd);
+ if (TST_RET == 0 || (TST_RET < 0 && TST_ERR != EINTR)) {
+ close(fd);
FD_CLR(fd, &afds);
}
}
}
}
-#define TM "from recvmsg01 server"
-
-/* special for rights-passing test */
-void sender(int fd)
-{
- struct msghdr mh;
- struct cmsghdr *control;
- char tmpfn[1024], snd_cbuf[1024];
- int tfd;
-
- (void)strcpy(tmpfn, "smtXXXXXX");
- tfd = mkstemp(tmpfn);
- if (tfd < 0)
- return;
-
- memset(&mh, 0x00, sizeof(mh));
-
- /* set up cmsghdr */
- control = (struct cmsghdr *)snd_cbuf;
- memset(control, 0x00, sizeof(struct cmsghdr));
- control->cmsg_len = sizeof(struct cmsghdr) + 4;
- control->cmsg_level = SOL_SOCKET;
- control->cmsg_type = SCM_RIGHTS;
- *(int *)CMSG_DATA(control) = tfd;
-
- /* set up msghdr */
- iov[0].iov_base = TM;
- iov[0].iov_len = sizeof(TM);
- mh.msg_iov = iov;
- mh.msg_iovlen = 1;
- mh.msg_flags = 0;
- mh.msg_control = control;
- mh.msg_controllen = control->cmsg_len;
-
- /* do it */
- (void)sendmsg(fd, &mh, 0);
- (void)close(tfd);
- (void)unlink(tmpfn);
-}
+static struct tst_test test = {
+ .test = run,
+ .tcnt = ARRAY_SIZE(tcases),
+ .forks_child = 1,
+ .needs_tmpdir = 1,
+};
diff --git a/testcases/kernel/syscalls/sbrk/sbrk01.c b/testcases/kernel/syscalls/sbrk/sbrk01.c
index ce26b1503..c99fb0106 100644
--- a/testcases/kernel/syscalls/sbrk/sbrk01.c
+++ b/testcases/kernel/syscalls/sbrk/sbrk01.c
@@ -1,111 +1,40 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
- * AUTHOR : William Roske
- * CO-PILOT : Dave Fenner
- *
- * 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.
- *
- * Further, this software is distributed without any warranty that it is
- * free of the rightful claim of any third person regarding infringement
- * or the like. Any license provided herein, whether implied or
- * otherwise, applies only to this software file. Patent licenses, if
- * any, provided herein do not apply to combinations of this program with
- * other software, or any other product whatsoever.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
- * Mountain View, CA 94043, or:
- *
- * http://www.sgi.com
- *
- * For further information regarding this notice, see:
- *
- * http://oss.sgi.com/projects/GenInfo/NoticeExplan/
- *
- */
-/*
- * DESCRIPTION
- * 1.) test sbrk(8192) should return successfully.
- * 2.) test sbrk(-8192) should return successfully.
+ * AUTHOR : William Roske, CO-PILOT : Dave Fenner
+ * Copyright (c) 2023 SUSE LLC Avinesh Kumar <avinesh.kumar@suse.com>
*/
-#include <unistd.h>
-#include <errno.h>
-#include <string.h>
-#include <signal.h>
-#include <sys/types.h>
-
-#include "test.h"
+/*\
+ * [Description]
+ *
+ * Verify that sbrk() successfully increments or decrements the program's
+ * data break.
+ */
-char *TCID = "sbrk01";
+#include "tst_test.h"
-static struct test_case_t {
+static struct tcase {
long increment;
-} test_cases[] = {
+} tcases[] = {
+ {0},
{8192},
- {-8192},
+ {-8192}
};
-static void setup(void);
-static void sbrk_verify(const struct test_case_t *);
-static void cleanup(void);
-
-int TST_TOTAL = ARRAY_SIZE(test_cases);
-
-int main(int ac, char **av)
+static void run(unsigned int i)
{
- int lc;
- int i;
-
- tst_parse_opts(ac, av, NULL, NULL);
+ struct tcase *tc = &tcases[i];
- setup();
+ TESTPTR(sbrk(tc->increment));
- for (lc = 0; TEST_LOOPING(lc); lc++) {
-
- tst_count = 0;
-
- for (i = 0; i < TST_TOTAL; i++)
- sbrk_verify(&test_cases[i]);
- }
-
- cleanup();
- tst_exit();
-
-}
-
-static void setup(void)
-{
- tst_sig(NOFORK, DEF_HANDLER, cleanup);
-
- TEST_PAUSE;
+ if (TST_RET_PTR == (void *) -1)
+ tst_res(TFAIL | TTERRNO, "sbrk(%ld) failed", tc->increment);
+ else
+ tst_res(TPASS, "sbrk(%ld) returned %p", tc->increment, TST_RET_PTR);
}
-static void sbrk_verify(const struct test_case_t *test)
-{
- void *tret;
-
- tret = sbrk(test->increment);
- TEST_ERRNO = errno;
-
- if (tret == (void *)-1) {
- tst_resm(TFAIL | TTERRNO, "sbrk - Increase by %ld bytes failed",
- test->increment);
- } else {
- tst_resm(TPASS, "sbrk - Increase by %ld bytes returned %p",
- test->increment, tret);
- }
-}
-
-static void cleanup(void)
-{
-}
+static struct tst_test test = {
+ .test = run,
+ .tcnt = ARRAY_SIZE(tcases)
+};
diff --git a/testcases/kernel/syscalls/sbrk/sbrk02.c b/testcases/kernel/syscalls/sbrk/sbrk02.c
index 84744ef90..7fccc4d3a 100644
--- a/testcases/kernel/syscalls/sbrk/sbrk02.c
+++ b/testcases/kernel/syscalls/sbrk/sbrk02.c
@@ -1,101 +1,52 @@
+// SPDX-License-Identifier: GPL-2.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; if not, write the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ * Copyright (c) 2023 SUSE LLC Avinesh Kumar <avinesh.kumar@suse.com>
*/
-/*
- * DESCRIPTION
- * Check sbrk() with error condition that should produce ENOMEM.
- */
-
-#include <errno.h>
-#include <unistd.h>
-#include "test.h"
-#define INC 16*1024*1024
+/*\
+ * [Description]
+ *
+ * Verify that sbrk() on failure sets errno to ENOMEM.
+ */
-char *TCID = "sbrk02";
-int TST_TOTAL = 1;
-static void setup(void);
-static void sbrk_verify(void);
-static void cleanup(void);
+#include "tst_test.h"
+#define INC (16*1024*1024)
static long increment = INC;
-int main(int argc, char *argv[])
+static void run(void)
{
- int lc;
- int i;
-
- tst_parse_opts(argc, argv, NULL, NULL);
-
- setup();
+ TESTPTR(sbrk(increment));
- for (lc = 0; TEST_LOOPING(lc); lc++) {
- tst_count = 0;
- for (i = 0; i < TST_TOTAL; i++)
- sbrk_verify();
+ if (TST_RET_PTR != (void *)-1) {
+ tst_res(TFAIL, "sbrk(%ld) unexpectedly passed and returned %p, "
+ "expected (void *)-1 with errno=%d",
+ increment, TST_RET_PTR, ENOMEM);
+ return;
}
- cleanup();
- tst_exit();
+ if (TST_ERR == ENOMEM)
+ tst_res(TPASS | TTERRNO, "sbrk(%ld) failed as expected", increment);
+ else
+ tst_res(TFAIL | TTERRNO, "sbrk(%ld) failed but unexpected errno, "
+ "expected errno=%d - %s",
+ increment, ENOMEM, strerror(ENOMEM));
}
static void setup(void)
{
void *ret = NULL;
- tst_sig(NOFORK, DEF_HANDLER, cleanup);
-
- TEST_PAUSE;
-
- /* call sbrk until it fails or increment overflows */
while (ret != (void *)-1 && increment > 0) {
ret = sbrk(increment);
increment += INC;
}
- tst_resm(TINFO | TERRNO, "setup() bailing inc: %ld, ret: %p, sbrk: %p",
- increment, ret, sbrk(0));
-
- errno = 0;
-}
-
-static void sbrk_verify(void)
-{
- void *tret;
-
- tret = sbrk(increment);
- TEST_ERRNO = errno;
-
- if (tret != (void *)-1) {
- tst_resm(TFAIL,
- "sbrk(%ld) returned %p, expected (void *)-1, errno=%d",
- increment, tret, ENOMEM);
- return;
- }
-
- if (TEST_ERRNO == ENOMEM) {
- tst_resm(TPASS | TTERRNO, "sbrk(%ld) failed as expected",
- increment);
- } else {
- tst_resm(TFAIL | TTERRNO,
- "sbrk(%ld) failed unexpectedly; expected: %d - %s",
- increment, ENOMEM, strerror(ENOMEM));
- }
}
-static void cleanup(void)
-{
-}
+static struct tst_test test = {
+ .test_all = run,
+ .setup = setup
+};
diff --git a/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval01.c b/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval01.c
index 447242159..597de4665 100644
--- a/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval01.c
+++ b/testcases/kernel/syscalls/sched_rr_get_interval/sched_rr_get_interval01.c
@@ -69,7 +69,7 @@ static void run(void)
}
if (proc_flag)
- TST_ASSERT_INT("/proc/sys/kernel/sched_rr_timeslice_ms", tst_ts_to_ms(tp));
+ TST_ASSERT_INT(PROC_SCHED_RR_TIMESLICE_MS, tst_ts_to_ms(tp));
}
static struct tst_test test = {
@@ -79,6 +79,7 @@ static struct tst_test test = {
.needs_root = 1,
.tags = (const struct tst_tag[]) {
{"linux-git", "975e155ed873"},
+ {"linux-git", "c7fcb99877f9"},
{}
}
};
diff --git a/testcases/kernel/syscalls/sendfile/sendfile04.c b/testcases/kernel/syscalls/sendfile/sendfile04.c
index 9a8ec08b9..4fa748137 100644
--- a/testcases/kernel/syscalls/sendfile/sendfile04.c
+++ b/testcases/kernel/syscalls/sendfile/sendfile04.c
@@ -14,6 +14,7 @@
* [Algorithm]
*
* Given wrong address or protected buffer as OFFSET argument to sendfile:
+ *
* - a wrong address is created by munmap a buffer allocated by mmap
* - a protected buffer is created by mmap with specifying protection
*/
diff --git a/testcases/kernel/syscalls/setgroups/.gitignore b/testcases/kernel/syscalls/setgroups/.gitignore
index 0649a3425..9de928241 100644
--- a/testcases/kernel/syscalls/setgroups/.gitignore
+++ b/testcases/kernel/syscalls/setgroups/.gitignore
@@ -4,5 +4,3 @@
/setgroups02_16
/setgroups03
/setgroups03_16
-/setgroups04
-/setgroups04_16
diff --git a/testcases/kernel/syscalls/setgroups/setgroups01.c b/testcases/kernel/syscalls/setgroups/setgroups01.c
index fed7f8e5a..9a5b77e93 100644
--- a/testcases/kernel/syscalls/setgroups/setgroups01.c
+++ b/testcases/kernel/syscalls/setgroups/setgroups01.c
@@ -1,202 +1,39 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) Linux Test Project, 2003-2023
*
- * 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.
- *
- * Further, this software is distributed without any warranty that it is
- * free of the rightful claim of any third person regarding infringement
- * or the like. Any license provided herein, whether implied or
- * otherwise, applies only to this software file. Patent licenses, if
- * any, provided herein do not apply to combinations of this program with
- * other software, or any other product whatsoever.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
- * Mountain View, CA 94043, or:
- *
- * http://www.sgi.com
- *
- * For further information regarding this notice, see:
- *
- * http://oss.sgi.com/projects/GenInfo/NoticeExplan/
- *
+ * Author: William Roske
+ * CO-PILOT: Dave Fenner
*/
-/* $Id: setgroups01.c,v 1.7 2009/11/02 13:57:18 subrata_modak Exp $ */
-/**********************************************************
- *
- * OS Test - Silicon Graphics, Inc.
- *
- * TEST IDENTIFIER : setgroups01
- *
- * EXECUTED BY : root
- *
- * TEST TITLE : Basic test for setgroups(2)
- *
- * PARENT DOCUMENT : usctpl01
- *
- * TEST CASE TOTAL : 1
- *
- * WALL CLOCK TIME : 1
- *
- * CPU TYPES : ALL
- *
- * AUTHOR : William Roske
- *
- * CO-PILOT : Dave Fenner
- *
- * DATE STARTED : 03/30/92
- *
- * INITIAL RELEASE : UNICOS 7.0
- *
- * TEST CASES
- *
- * 1.) setgroups(2) returns...(See Description)
- *
- * INPUT SPECIFICATIONS
- * The standard options for system call tests are accepted.
- * (See the parse_opts(3) man page).
- *
- * OUTPUT SPECIFICATIONS
- *$
- * DURATION
- * Terminates - with frequency and infinite modes.
- *
- * SIGNALS
- * Uses SIGUSR1 to pause before test if option set.
- * (See the parse_opts(3) man page).
- *
- * RESOURCES
- * None
- *
- * ENVIRONMENTAL NEEDS
- * No run-time environmental needs.
- *
- * SPECIAL PROCEDURAL REQUIREMENTS
- * None
- *
- * INTERCASE DEPENDENCIES
- * None
- *
- * DETAILED DESCRIPTION
- * This is a Phase I test for the setgroups(2) system call. It is intended
- * to provide a limited exposure of the system call, for now. It
- * should/will be extended when full functional tests are written for
- * setgroups(2).
- *
- * Setup:
- * Setup signal handling.
- * Pause for SIGUSR1 if option specified.
- *
- * Test:
- * Loop if the proper options are given.
- * Execute system call
- * Check return code, if system call failed (return=-1)
- * Log the errno and Issue a FAIL message.
- * Otherwise, Issue a PASS message.
- *
- * Cleanup:
- * Print errno log and/or timing stats if options given
- *
- *
- *#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#**/
-
-#include <errno.h>
-#include <string.h>
-#include <signal.h>
-#include <sys/param.h>
-#include <unistd.h>
-#include <grp.h>
-#include "test.h"
-
-#include "compat_16.h"
+/*\
+ * [Description]
+ *
+ * Check the basic functionality of the setgroups() system call.
+ */
-void setup();
-void cleanup();
+#include "tst_test.h"
+#include "compat_tst_16.h"
-TCID_DEFINE(setgroups01);
-int TST_TOTAL = 1;
+static int len = NGROUPS;
-int len = NGROUPS, ngrps = 0;
-GID_T list[NGROUPS];
+static GID_T list[NGROUPS];
-int main(int ac, char **av)
+static void verify_setgroups(void)
{
- int lc;
-
- /***************************************************************
- * parse standard options
- ***************************************************************/
- tst_parse_opts(ac, av, NULL, NULL);
-
- /***************************************************************
- * perform global setup for test
- ***************************************************************/
- setup();
-
- /***************************************************************
- * check looping state if -c option given
- ***************************************************************/
- for (lc = 0; TEST_LOOPING(lc); lc++) {
-
- tst_count = 0;
-
- /*
- * Call setgroups(2)
- */
- TEST(SETGROUPS(cleanup, ngrps, list));
-
- /* check return code */
- if (TEST_RETURN == -1) {
- tst_resm(TFAIL,
- "setgroups(%d, list) Failed, errno=%d : %s",
- len, TEST_ERRNO, strerror(TEST_ERRNO));
- } else {
- tst_resm(TPASS,
- "setgroups(%d, list) returned %ld",
- len, TEST_RETURN);
- }
-
- }
-
- cleanup();
- tst_exit();
+ TST_EXP_POSITIVE(SETGROUPS(1, list), "setgroups()");
}
-/***************************************************************
- * setup() - performs all ONE TIME setup for this test.
- ***************************************************************/
-void setup(void)
+static void setup(void)
{
-
- tst_require_root();
-
- tst_sig(NOFORK, DEF_HANDLER, cleanup);
-
- TEST_PAUSE;
-
- ngrps = GETGROUPS(cleanup, len, list);
- if (ngrps == -1) {
- tst_brkm(TBROK, cleanup,
- "getgroups(%d, list) Failure. errno=%d : %s",
- len, errno, strerror(errno));
- }
+ len = GETGROUPS(NGROUPS, list);
+ if (len < 0)
+ tst_brk(TBROK | TERRNO, "getgroups() Failed");
}
-/***************************************************************
- * cleanup() - performs all ONE TIME cleanup for this test at
- * completion or premature exit.
- ***************************************************************/
-void cleanup(void)
-{
-
-}
+static struct tst_test test = {
+ .test_all = verify_setgroups,
+ .setup = setup,
+ .needs_root = 1,
+};
diff --git a/testcases/kernel/syscalls/setgroups/setgroups02.c b/testcases/kernel/syscalls/setgroups/setgroups02.c
index de23a4a7f..2b7f95c87 100644
--- a/testcases/kernel/syscalls/setgroups/setgroups02.c
+++ b/testcases/kernel/syscalls/setgroups/setgroups02.c
@@ -1,180 +1,43 @@
+// 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
+ * Copyright (c) Linux Test Project, 2003-2023
+ * 07/2001 Ported by Wayne Boyer
*/
-/*
- * Test Name: setgroups02
- *
- * Test Description:
- * Verify that, only root process can invoke setgroups() system call to
- * set the supplementary group IDs of the process.
- *
- * Expected Result:
- * The call succeeds in setting all the supplementary group IDs of the
- * calling process. The new group should be set in the process supplemental
- * group list.
- *
- * Algorithm:
- * Setup:
- * Setup signal handling.
- * Pause for SIGUSR1 if option specified.
- *
- * Test:
- * Loop if the proper options are given.
- * Execute system call
- * Check return code, if system call failed (return=-1)
- * Log the errno and Issue a FAIL message.
- * Otherwise,
- * Verify the Functionality of system call
- * if successful,
- * Issue Functionality-Pass message.
- * Otherwise,
- * Issue Functionality-Fail message.
- * Cleanup:
- * Print errno log and/or timing stats if options given
- *
- * Usage: <for command-line>
- * setgroups02 [-c n] [-f] [-i n] [-I x] [-P x] [-t]
- * where, -c n : Run n copies concurrently.
- * -f : Turn off functionality Testing.
- * -i n : Execute test n times.
- * -I x : Execute test for x seconds.
- * -P x : Pause for x seconds between iterations.
- * -t : Turn on syscall timing.
- *
- * HISTORY
- * 07/2001 Ported by Wayne Boyer
- *
- * RESTRICTIONS:
- * This test should be run by 'super-user' (root) only.
+/*\
+ * [Description]
*
+ * Check that root process can setgroups() supplementary group ID and verify
+ * that getgroups() returns the previously set ID.
*/
-#include <sys/types.h>
-#include <unistd.h>
-#include <errno.h>
-#include <pwd.h>
-#include <grp.h>
-#include <sys/param.h>
-
-#include "test.h"
-
-#include "compat_16.h"
-#define TESTUSER "nobody"
-
-TCID_DEFINE(setgroups02);
-int TST_TOTAL = 1; /* Total number of test conditions */
-GID_T groups_list[NGROUPS]; /* Array to hold gids for getgroups() */
-
-struct passwd *user_info; /* struct. to hold test user info */
-void setup(); /* setup function for the test */
-void cleanup(); /* cleanup function for the test */
-
-int main(int ac, char **av)
-{
- int lc, i;
- int gidsetsize = 1; /* only one GID, the GID of TESTUSER */
- int PASS_FLAG = 0; /* used for checking group array */
-
- tst_parse_opts(ac, av, NULL, NULL);
-
- setup();
-
- for (lc = 0; TEST_LOOPING(lc); lc++) {
-
- tst_count = 0;
-
- /*
- * Call setgroups() to set supplimentary group IDs of
- * the calling super-user process to gid of TESTUSER.
- */
- TEST(SETGROUPS(cleanup, gidsetsize, groups_list));
-
- if (TEST_RETURN == -1) {
- tst_resm(TFAIL, "setgroups(%d, groups_list) Failed, "
- "errno=%d : %s", gidsetsize, TEST_ERRNO,
- strerror(TEST_ERRNO));
- continue;
- }
+#include <pwd.h>
- /*
- * Call getgroups(2) to verify that
- * setgroups(2) successfully set the
- * supp. gids of TESTUSER.
- */
- groups_list[0] = '\0';
- if (GETGROUPS(cleanup, gidsetsize, groups_list) < 0) {
- tst_brkm(TFAIL, cleanup, "getgroups() Fails, "
- "error=%d", errno);
- }
- for (i = 0; i < NGROUPS; i++) {
- if (groups_list[i] == user_info->pw_gid) {
- tst_resm(TPASS,
- "Functionality of setgroups"
- "(%d, groups_list) successful",
- gidsetsize);
- PASS_FLAG = 1;
- }
- }
- if (PASS_FLAG == 0) {
- tst_resm(TFAIL, "Supplimentary gid %d not set "
- "for the process", user_info->pw_gid);
- }
- }
+#include "tst_test.h"
+#include "compat_tst_16.h"
- cleanup();
- tst_exit();
-}
+static GID_T *groups_get, *groups_set;
-/*
- * setup() - performs all ONE TIME setup for this test.
- *
- * Make sure the test process uid is root.
- * Get the supplimentrary group id of test user from /etc/passwd file.
- */
-void setup(void)
+static void verify_setgroups(void)
{
+ groups_set[0] = 42;
- tst_require_root();
-
- tst_sig(NOFORK, DEF_HANDLER, cleanup);
+ TST_EXP_PASS(SETGROUPS(1, groups_set));
- TEST_PAUSE;
+ TST_EXP_VAL(GETGROUPS(1, groups_get), 1);
- /* Get the group id info. of TESTUSER from /etc/passwd */
- if ((user_info = getpwnam(TESTUSER)) == NULL) {
- tst_brkm(TFAIL, cleanup, "getpwnam(2) of %s Failed", TESTUSER);
- }
+ TST_EXP_EQ_LI(groups_get[0], groups_set[0]);
- if (!GID_SIZE_CHECK(user_info->pw_gid)) {
- tst_brkm(TBROK,
- cleanup,
- "gid returned from getpwnam is too large for testing setgroups16");
- }
-
- groups_list[0] = user_info->pw_gid;
+ groups_get[0] = 0;
}
-/*
- * cleanup() - performs all ONE TIME cleanup for this test at
- * completion or premature exit.
- */
-void cleanup(void)
-{
-
-}
+static struct tst_test test = {
+ .test_all = verify_setgroups,
+ .bufs = (struct tst_buffers []) {
+ {&groups_get, .size = sizeof(GID_T)},
+ {&groups_set, .size = sizeof(GID_T)},
+ {},
+ },
+ .needs_root = 1,
+};
diff --git a/testcases/kernel/syscalls/setgroups/setgroups03.c b/testcases/kernel/syscalls/setgroups/setgroups03.c
index 490b06996..fbf8de0bb 100644
--- a/testcases/kernel/syscalls/setgroups/setgroups03.c
+++ b/testcases/kernel/syscalls/setgroups/setgroups03.c
@@ -1,222 +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) Bull S.A. 2001
+ * Copyright (c) International Business Machines Corp., 2001
+ * Copyright (c) Linux Test Project, 2003-2023
+ * 07/2001 Ported by Wayne Boyer
+ * 05/2002 Ported by Andre Merlier
*/
-/*
- * Test Name: setgroups03
- *
- * Test Description:
- * Verify that,
- * 1. setgroups() fails with -1 and sets errno to EINVAL if the size
- * argument value is > NGROUPS
- * 2. setgroups() fails with -1 and sets errno to EPERM if the
- * calling process is not super-user.
+/*\
+ * [Description]
*
- * Expected Result:
- * setgroups() should fail with return value -1 and set expected errno.
+ * Test for EINVAL, EPERM, EFAULT errors.
*
- * Algorithm:
- * Setup:
- * Setup signal handling.
- * Pause for SIGUSR1 if option specified.
+ * - setgroups() fails with EINVAL if the size argument value is > NGROUPS.
*
- * Test:
- * Loop if the proper options are given.
- * Execute system call
- * Check return code, if system call failed (return=-1)
- * if errno set == expected errno
- * Issue sys call fails with expected return value and errno.
- * Otherwise,
- * Issue sys call fails with unexpected errno.
- * Otherwise,
- * Issue sys call returns unexpected value.
- *
- * Cleanup:
- * Print errno log and/or timing stats if options given
- *
- * Usage: <for command-line>
- * setgroups03 [-c n] [-e] [-i n] [-I x] [-P x] [-t]
- * where, -c n : Run n copies concurrently.
- * -f : Turn off functionality Testing.
- * -i n : Execute test n times.
- * -I x : Execute test for x seconds.
- * -P x : Pause for x seconds between iterations.
- * -t : Turn on syscall timing.
- *
- * HISTORY
- * 07/2001 Ported by Wayne Boyer
- *
- * RESTRICTIONS:
- * This test should be executed by 'non-super-user' only.
+ * - setgroups() fails with EPERM if the calling process is not super-user.
*
+ * - setgroups() fails with EFAULT if the list has an invalid address.
*/
-#include <limits.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <errno.h>
-#include <pwd.h>
-#include <grp.h>
-#include "test.h"
+#include <pwd.h>
+#include <stdlib.h>
-#include "compat_16.h"
+#include "tst_test.h"
+#include "compat_tst_16.h"
#define TESTUSER "nobody"
-char nobody_uid[] = "nobody";
-struct passwd *ltpuser;
+static GID_T *glist1, *glist2, *glist3;
+static struct passwd *user_info;
-TCID_DEFINE(setgroups03);
-int TST_TOTAL = 2;
-
-GID_T *groups_list; /* Array to hold gids for getgroups() */
-
-int setup1(); /* setup function to test error EPERM */
-void setup(); /* setup function for the test */
-void cleanup(); /* cleanup function for the test */
-
-struct test_case_t { /* test case struct. to hold ref. test cond's */
- size_t gsize_add;
- int list;
- char *desc;
+static struct tcase {
+ int gsize;
+ GID_T **glist;
int exp_errno;
- int (*setupfunc) ();
-} Test_cases[] = {
- {
- 1, 1, "Size is > sysconf(_SC_NGROUPS_MAX)", EINVAL, NULL}, {
- 0, 2, "Permission denied, not super-user", EPERM, setup1}
+} tcases[] = {
+ {NGROUPS + 1, &glist1, EINVAL},
+ {1, &glist2, EPERM},
+ {NGROUPS, &glist3, EFAULT},
};
-int main(int ac, char **av)
-{
- int lc;
- int gidsetsize; /* total no. of groups */
- int i;
- char *test_desc; /* test specific error message */
- int ngroups_max = sysconf(_SC_NGROUPS_MAX); /* max no. of groups in the current system */
-
- tst_parse_opts(ac, av, NULL, NULL);
-
- groups_list = malloc(ngroups_max * sizeof(GID_T));
- if (groups_list == NULL) {
- tst_brkm(TBROK, NULL, "malloc failed to alloc %zu errno "
- " %d ", ngroups_max * sizeof(GID_T), errno);
- }
-
- setup();
-
- for (lc = 0; TEST_LOOPING(lc); lc++) {
-
- tst_count = 0;
-
- for (i = 0; i < TST_TOTAL; i++) {
- if (Test_cases[i].setupfunc != NULL) {
- Test_cases[i].setupfunc();
- }
-
- gidsetsize = ngroups_max + Test_cases[i].gsize_add;
- test_desc = Test_cases[i].desc;
-
- /*
- * Call setgroups() to test different test conditions
- * verify that it fails with -1 return value and
- * sets appropriate errno.
- */
- TEST(SETGROUPS(cleanup, gidsetsize, groups_list));
-
- if (TEST_RETURN != -1) {
- tst_resm(TFAIL, "setgroups(%d) returned %ld, "
- "expected -1, errno=%d", gidsetsize,
- TEST_RETURN, Test_cases[i].exp_errno);
- continue;
- }
-
- if (TEST_ERRNO == Test_cases[i].exp_errno) {
- tst_resm(TPASS,
- "setgroups(%d) fails, %s, errno=%d",
- gidsetsize, test_desc, TEST_ERRNO);
- } else {
- tst_resm(TFAIL, "setgroups(%d) fails, %s, "
- "errno=%d, expected errno=%d",
- gidsetsize, test_desc, TEST_ERRNO,
- Test_cases[i].exp_errno);
- }
- }
-
- }
-
- cleanup();
-
- tst_exit();
-}
-
-/*
- * setup() - performs all ONE TIME setup for this test.
- *
- * Call individual test specific setup functions.
- */
-void setup(void)
+static void verify_setgroups(unsigned int i)
{
- tst_require_root();
+ struct tcase *tc = &tcases[i];
- tst_sig(NOFORK, DEF_HANDLER, cleanup);
+ if (tc->exp_errno == EPERM)
+ SAFE_SETEUID(user_info->pw_uid);
- TEST_PAUSE;
+ TST_EXP_FAIL(SETGROUPS(tc->gsize, *tc->glist), tc->exp_errno,
+ "setgroups(%d, groups_list)", tc->gsize);
+ if (tc->exp_errno == EPERM)
+ SAFE_SETEUID(0);
}
-/*
- * setup1 - Setup function to test setgroups() which returns -1
- * and sets errno to EPERM.
- *
- * Get the user info. from /etc/passwd file.
- * This function returns 0 on success.
- */
-int setup1(void)
+static void setup(void)
{
- struct passwd *user_info; /* struct. to hold test user info */
-
-/* Switch to nobody user for correct error code collection */
- ltpuser = getpwnam(nobody_uid);
- if (seteuid(ltpuser->pw_uid) == -1) {
- tst_resm(TINFO, "setreuid failed to "
- "to set the effective uid to %d", ltpuser->pw_uid);
- perror("setreuid");
- }
-
- if ((user_info = getpwnam(TESTUSER)) == NULL) {
- tst_brkm(TFAIL, cleanup, "getpwnam(2) of %s Failed", TESTUSER);
- }
-
- if (!GID_SIZE_CHECK(user_info->pw_gid)) {
- tst_brkm(TBROK,
- cleanup,
- "gid returned from getpwnam is too large for testing setgroups16");
- }
- groups_list[0] = user_info->pw_gid;
- return 0;
+ user_info = SAFE_GETPWNAM(TESTUSER);
+ glist2[0] = 42;
+ glist3 = tst_get_bad_addr(NULL);
}
-/*
- * cleanup() - performs all ONE TIME cleanup for this test at
- * completion or premature exit.
- */
-void cleanup(void)
-{
-
-}
+static struct tst_test test = {
+ .test = verify_setgroups,
+ .tcnt = ARRAY_SIZE(tcases),
+ .bufs = (struct tst_buffers []) {
+ {&glist1, .size = sizeof(GID_T) * (NGROUPS + 1)},
+ {&glist2, .size = sizeof(GID_T)},
+ {&user_info, .size = sizeof(struct passwd)},
+ {},
+ },
+ .setup = setup,
+ .needs_root = 1,
+};
diff --git a/testcases/kernel/syscalls/setgroups/setgroups04.c b/testcases/kernel/syscalls/setgroups/setgroups04.c
deleted file mode 100644
index 971c86bd2..000000000
--- a/testcases/kernel/syscalls/setgroups/setgroups04.c
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * Copyright (C) Bull S.A. 2001
- * 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
- */
-
-/*
- * Test Name: setgroups04
- *
- * Test Description:
- * Verify that, setgroups() fails with -1 and sets errno to EFAULT if the list has an invalid address.
- *
- * Expected Result:
- * setgroups() should fail with return value -1 and set expected errno.
- *
- * Algorithm:
- * Setup:
- * Setup signal handling.
- * Pause for SIGUSR1 if option specified.
- *
- * Test:
- * Loop if the proper options are given.
- * Execute system call
- * Check return code, if system call failed (return=-1)
- * if errno set == expected errno
- * Issue sys call fails with expected return value and errno.
- * Otherwise,
- * Issue sys call fails with unexpected errno.
- * Otherwise,
- * Issue sys call returns unexpected value.
- *
- * Cleanup:
- * Print errno log and/or timing stats if options given
- *
- * Usage: <for command-line>
- * setgroups04 [-c n] [-e] [-i n] [-I x] [-P x] [-t]
- * where, -c n : Run n copies concurrently.
- * -f : Turn off functionality Testing.
- * -i n : Execute test n times.
- * -I x : Execute test for x seconds.
- * -P x : Pause for x seconds between iterations.
- * -t : Turn on syscall timing.
- *
- * HISTORY
- * 05/2002 Ported by André Merlier
- *
- * RESTRICTIONS:
- * none.
- *
- */
-#include <sys/types.h>
-#include <sys/param.h>
-#include <unistd.h>
-#include <errno.h>
-#include <pwd.h>
-#include <grp.h>
-
-#include "test.h"
-
-#include "compat_16.h"
-
-TCID_DEFINE(setgroups04);
-int TST_TOTAL = 1;
-
-GID_T groups_list[NGROUPS];
-
-void setup(); /* setup function for the test */
-void cleanup(); /* cleanup function for the test */
-
-#if !defined(UCLINUX)
-
-int main(int ac, char **av)
-{
- int lc;
- int gidsetsize; /* total no. of groups */
- char *test_desc; /* test specific error message */
-
- tst_parse_opts(ac, av, NULL, NULL);
-
- /* Perform setup for test */
- setup();
-
- for (lc = 0; TEST_LOOPING(lc); lc++) {
-
- tst_count = 0;
-
- gidsetsize = NGROUPS;
- test_desc = "EFAULT";
-
- /*
- * Call setgroups() to test condition
- * verify that it fails with -1 return value and
- * sets appropriate errno.
- */
- TEST(SETGROUPS(cleanup, gidsetsize, sbrk(0)));
-
- if (TEST_RETURN != -1) {
- tst_resm(TFAIL, "setgroups() returned %ld, "
- "expected -1, errno=%d", TEST_RETURN,
- EFAULT);
- } else {
-
- if (TEST_ERRNO == EFAULT) {
- tst_resm(TPASS,
- "setgroups() fails with expected "
- "error EFAULT errno:%d", TEST_ERRNO);
- } else {
- tst_resm(TFAIL, "setgroups() fails, %s, "
- "errno=%d, expected errno=%d",
- test_desc, TEST_ERRNO, EFAULT);
- }
- }
-
- }
-
- cleanup();
- tst_exit();
-
-}
-
-#else
-
-int main(void)
-{
- tst_resm(TINFO, "test is not available on uClinux");
- tst_exit();
-}
-
-#endif /* if !defined(UCLINUX) */
-
-/*
- * setup()
- */
-void setup(void)
-{
- tst_require_root();
-
- tst_sig(NOFORK, DEF_HANDLER, cleanup);
-
- TEST_PAUSE;
-
-}
-
-/*
- * cleanup()
- */
-void cleanup(void)
-{
-
-}
diff --git a/testcases/kernel/syscalls/setpgid/setpgid02.c b/testcases/kernel/syscalls/setpgid/setpgid02.c
index 4b63afee8..b380d7df4 100644
--- a/testcases/kernel/syscalls/setpgid/setpgid02.c
+++ b/testcases/kernel/syscalls/setpgid/setpgid02.c
@@ -13,15 +13,15 @@
* - EINVAL when given pgid is less than 0.
* - ESRCH when pid is not the calling process and not a child of
* the calling process.
- * - EPERM when an attempt was made to move a process into a process
- * group in a different session.
+ * - EPERM when an attempt was made to move a process into a nonexisting
+ * process group.
*/
#include <errno.h>
#include <unistd.h>
#include "tst_test.h"
-static pid_t pgid, pid, ppid, init_pgid;
+static pid_t pgid, pid, ppid, inval_pgid;
static pid_t negative_pid = -1;
static struct tcase {
@@ -31,7 +31,7 @@ static struct tcase {
} tcases[] = {
{&pid, &negative_pid, EINVAL},
{&ppid, &pgid, ESRCH},
- {&pid, &init_pgid, EPERM}
+ {&pid, &inval_pgid, EPERM}
};
static void setup(void)
@@ -41,10 +41,10 @@ static void setup(void)
pgid = getpgrp();
/*
- * Getting pgid of init/systemd process to use it as a
- * process group from a different session for EPERM test
+ * pid_max would not be in use by another process and guarantees that
+ * it corresponds to an invalid PGID, generating EPERM.
*/
- init_pgid = SAFE_GETPGID(1);
+ SAFE_FILE_SCANF("/proc/sys/kernel/pid_max", "%d\n", &inval_pgid);
}
static void run(unsigned int n)
diff --git a/testcases/kernel/syscalls/setpgid/setpgid03.c b/testcases/kernel/syscalls/setpgid/setpgid03.c
index 79ca23e08..9ce2603d8 100644
--- a/testcases/kernel/syscalls/setpgid/setpgid03.c
+++ b/testcases/kernel/syscalls/setpgid/setpgid03.c
@@ -9,7 +9,9 @@
/*\
* [Description]
*
- * Tests setpgid() erorrs:
+ * Tests setpgid(2) errors:
+ *
+ * - EPERM The process specified by pid must not be a session leader.
*
* - EPERM The calling process, process specified by pid and the target
* process group must be in the same session.
@@ -43,6 +45,8 @@ static void run(void)
TST_CHECKPOINT_WAIT(0);
TST_EXP_FAIL(setpgid(child_pid, getppid()), EPERM);
+ /* Child did setsid(), so its PGID is set to its PID. */
+ TST_EXP_FAIL(setpgid(0, child_pid), EPERM);
TST_CHECKPOINT_WAKE(0);
diff --git a/testcases/kernel/syscalls/setreuid/setreuid04.c b/testcases/kernel/syscalls/setreuid/setreuid04.c
index 8eed90df0..06ffa32b0 100644
--- a/testcases/kernel/syscalls/setreuid/setreuid04.c
+++ b/testcases/kernel/syscalls/setreuid/setreuid04.c
@@ -1,141 +1,49 @@
+// 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
- *
* Ported by John George
+ * Copyright (c) 2022 SUSE LLC Avinesh Kumar <avinesh.kumar@suse.com>
*/
-/*
- * Test that root can change the real and effective uid to an
- * unpriviledged user.
+/*\
+ * [Description]
+ *
+ * Verify that root user can change the real and effective uid to an
+ * unprivileged user.
*/
-#include <errno.h>
-#include <stdlib.h>
#include <pwd.h>
-#include <sys/wait.h>
-
-#include "test.h"
-#include "compat_16.h"
-
-TCID_DEFINE(setreuid04);
-
-static uid_t neg_one = -1;
-
-static struct passwd nobody, root;
-
-/*
- * The following structure contains all test data. Each structure in the array
- * is used for a separate test. The tests are executed in the for loop below.
- */
-
-struct test_data_t {
- uid_t *real_uid;
- uid_t *eff_uid;
- struct passwd *exp_real_usr;
- struct passwd *exp_eff_usr;
- char *test_msg;
-} test_data[] = {
- {
- &neg_one, &neg_one, &root, &root, "After setreuid(-1, nobody),"}, {
-&nobody.pw_uid, &nobody.pw_uid, &nobody, &nobody,
- "After setreuid(-1, -1),"},};
-
-int TST_TOTAL = ARRAY_SIZE(test_data);
-
-static void setup(void);
-static void cleanup(void);
-static void uid_verify(struct passwd *, struct passwd *, char *);
-
-int main(int ac, char **av)
-{
- int lc;
-
- tst_parse_opts(ac, av, NULL, NULL);
-
- setup();
-
- for (lc = 0; TEST_LOOPING(lc); lc++) {
- int i, pid;
-
- tst_count = 0;
+#include "tst_test.h"
+#include "compat_tst_16.h"
- if ((pid = FORK_OR_VFORK()) == -1) {
- tst_brkm(TBROK, cleanup, "fork failed");
- } else if (pid == 0) { /* child */
-
- for (i = 0; i < TST_TOTAL; i++) {
-
- /* Set the real or effective user id */
- TEST(SETREUID(cleanup, *test_data[i].real_uid,
- *test_data[i].eff_uid));
-
- if (TEST_RETURN != -1) {
- tst_resm(TPASS, "setreuid(%d, %d) "
- "succeeded as expected.",
- *test_data[i].real_uid,
- *test_data[i].eff_uid);
- } else {
- tst_resm(TFAIL, "setreuid(%d, %d) "
- "did not return as expected.",
- *test_data[i].real_uid,
- *test_data[i].eff_uid);
- }
-
- uid_verify(test_data[i].exp_real_usr,
- test_data[i].exp_eff_usr,
- test_data[i].test_msg);
- }
- tst_exit();
- } else { /* parent */
- tst_record_childstatus(cleanup, pid);
- }
- }
- cleanup();
- tst_exit();
-}
+static uid_t root_uid, nobody_uid;
static void setup(void)
{
- tst_require_root();
-
- tst_sig(FORK, DEF_HANDLER, cleanup);
-
- if (getpwnam("nobody") == NULL)
- tst_brkm(TBROK, NULL, "nobody must be a valid user.");
+ struct passwd *nobody;
- root = *(getpwnam("root"));
- UID16_CHECK(root.pw_uid, setreuid, cleanup);
+ root_uid = getuid();
+ nobody = SAFE_GETPWNAM("nobody");
+ nobody_uid = nobody->pw_uid;
- nobody = *(getpwnam("nobody"));
- UID16_CHECK(nobody.pw_uid, setreuid, cleanup);
-
- TEST_PAUSE;
+ UID16_CHECK(nobody_uid, setreuid);
+ UID16_CHECK(root_uid, setreuid);
}
-static void cleanup(void)
+static void run(void)
{
-}
+ if (!SAFE_FORK()) {
+ TST_EXP_PASS(SETREUID(nobody_uid, nobody_uid));
-static void uid_verify(struct passwd *ru, struct passwd *eu, char *when)
-{
- if ((getuid() != ru->pw_uid) || (geteuid() != eu->pw_uid)) {
- tst_resm(TFAIL, "ERROR: %s real uid = %d; effective uid = %d",
- when, getuid(), geteuid());
- tst_resm(TINFO, "Expected: real uid = %d; effective uid = %d",
- ru->pw_uid, eu->pw_uid);
+ TST_EXP_EQ_LI(GETUID(), nobody_uid);
+ TST_EXP_EQ_LI(GETEUID(), nobody_uid);
}
+ tst_reap_children();
}
+
+static struct tst_test test = {
+ .setup = setup,
+ .test_all = run,
+ .needs_root = 1,
+ .forks_child = 1
+};
diff --git a/testcases/kernel/syscalls/setreuid/setreuid07.c b/testcases/kernel/syscalls/setreuid/setreuid07.c
index ff222cd00..5faf3cb7f 100644
--- a/testcases/kernel/syscalls/setreuid/setreuid07.c
+++ b/testcases/kernel/syscalls/setreuid/setreuid07.c
@@ -1,192 +1,64 @@
+// SPDX-License-Identifier: GPL-2.0-later
/*
* Copyright (c) Kerlabs 2008.
* Copyright (c) International Business Machines Corp., 2008
- *
- * 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
- *
* Created by Renaud Lottiaux
+ * Copyright (c) 2023 SUSE LLC Avinesh Kumar <avinesh.kumar@suse.com>
*/
-/*
+/*\
+ * [Description]
+ *
* Check if setreuid behaves correctly with file permissions.
* The test creates a file as ROOT with permissions 0644, does a setreuid
* and then tries to open the file with RDWR permissions.
* The same test is done in a fork to check if new UIDs are correctly
- * passed to the son.
+ * passed to the child process.
*/
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/wait.h>
-#include <fcntl.h>
-#include <unistd.h>
#include <pwd.h>
+#include <stdlib.h>
-#include "test.h"
-#include "safe_macros.h"
-#include "compat_16.h"
+#include "tst_test.h"
+#include "compat_tst_16.h"
-TCID_DEFINE(setreuid07);
-int TST_TOTAL = 1;
+#define TEMPFILE "testfile"
-static char testfile[256] = "";
static struct passwd *ltpuser;
-static int fd = -1;
-
-static void setup(void);
-static void cleanup(void);
-static void do_master_child(void);
-
-int main(int ac, char **av)
+static void setup(void)
{
- pid_t pid;
+ int fd;
- tst_parse_opts(ac, av, NULL, NULL);
+ ltpuser = SAFE_GETPWNAM("nobody");
- setup();
-
- pid = FORK_OR_VFORK();
- if (pid < 0)
- tst_brkm(TBROK, cleanup, "Fork failed");
-
- if (pid == 0)
- do_master_child();
-
- tst_record_childstatus(cleanup, pid);
-
- cleanup();
- tst_exit();
+ UID16_CHECK(ltpuser->pw_uid, setreuid);
+ fd = SAFE_OPEN(TEMPFILE, O_CREAT | O_RDWR, 0644);
+ SAFE_CLOSE(fd);
}
-static void do_master_child(void)
+static void run(void)
{
- int lc;
- int pid;
- int status;
-
- for (lc = 0; TEST_LOOPING(lc); lc++) {
- int tst_fd;
-
- tst_count = 0;
-
- if (SETREUID(NULL, 0, ltpuser->pw_uid) == -1) {
- perror("setreuid failed");
- exit(TFAIL);
- }
-
- /* Test 1: Check the process with new uid cannot open the file
- * with RDWR permissions.
- */
- TEST(tst_fd = open(testfile, O_RDWR));
-
- if (TEST_RETURN != -1) {
- printf("open succeeded unexpectedly\n");
- close(tst_fd);
- exit(TFAIL);
- }
-
- if (TEST_ERRNO == EACCES) {
- printf("open failed with EACCES as expected\n");
- } else {
- perror("open failed unexpectedly");
- exit(TFAIL);
- }
-
- /* Test 2: Check a son process cannot open the file
- * with RDWR permissions.
- */
- pid = FORK_OR_VFORK();
- if (pid < 0)
- tst_brkm(TBROK, cleanup, "Fork failed");
-
- if (pid == 0) {
- int tst_fd2;
-
- /* Test to open the file in son process */
- TEST(tst_fd2 = open(testfile, O_RDWR));
-
- if (TEST_RETURN != -1) {
- printf("call succeeded unexpectedly\n");
- close(tst_fd2);
- exit(TFAIL);
- }
-
- if (TEST_ERRNO == EACCES) {
- printf("open failed with EACCES as expected\n");
- exit(TPASS);
- } else {
- printf("open failed unexpectedly\n");
- exit(TFAIL);
- }
- } else {
- /* Wait for son completion */
- if (waitpid(pid, &status, 0) == -1) {
- perror("waitpid failed");
- exit(TFAIL);
- }
- if (!WIFEXITED(status) || (WEXITSTATUS(status) != 0))
- exit(WEXITSTATUS(status));
- }
-
- /* Test 3: Fallback to initial uid and check we can again open
- * the file with RDWR permissions.
- */
- tst_count++;
- if (SETREUID(NULL, 0, 0) == -1) {
- perror("setreuid failed");
- exit(TFAIL);
- }
+ pid_t pid;
- TEST(tst_fd = open(testfile, O_RDWR));
+ TST_EXP_PASS_SILENT(SETREUID(-1, ltpuser->pw_uid));
+ TST_EXP_FAIL2(open(TEMPFILE, O_RDWR), EACCES);
- if (TEST_RETURN == -1) {
- perror("open failed unexpectedly");
- exit(TFAIL);
- } else {
- printf("open call succeeded\n");
- close(tst_fd);
- }
+ pid = SAFE_FORK();
+ if (pid == 0) {
+ TST_EXP_FAIL2(open(TEMPFILE, O_RDWR), EACCES);
+ exit(0);
}
- exit(TPASS);
-}
+ tst_reap_children();
-static void setup(void)
-{
- tst_require_root();
-
- ltpuser = getpwnam("nobody");
- if (ltpuser == NULL)
- tst_brkm(TBROK, NULL, "nobody must be a valid user.");
-
- tst_tmpdir();
-
- sprintf(testfile, "setreuid07file%d.tst", getpid());
-
- /* Create test file */
- fd = SAFE_OPEN(cleanup, testfile, O_CREAT | O_RDWR, 0644);
-
- tst_sig(FORK, DEF_HANDLER, cleanup);
-
- TEST_PAUSE;
+ TST_EXP_PASS_SILENT(SETREUID(-1, 0));
+ TST_EXP_FD(open(TEMPFILE, O_RDWR));
+ SAFE_CLOSE(TST_RET);
}
-static void cleanup(void)
-{
- close(fd);
-
- tst_rmdir();
-}
+static struct tst_test test = {
+ .setup = setup,
+ .test_all = run,
+ .needs_root = 1,
+ .forks_child = 1
+};
diff --git a/testcases/kernel/syscalls/setsockopt/setsockopt02.c b/testcases/kernel/syscalls/setsockopt/setsockopt02.c
index e7621538b..3349c9970 100644
--- a/testcases/kernel/syscalls/setsockopt/setsockopt02.c
+++ b/testcases/kernel/syscalls/setsockopt/setsockopt02.c
@@ -96,4 +96,8 @@ static struct tst_test test = {
.needs_root = 1,
.setup = setup,
.cleanup = cleanup,
+ .tags = (const struct tst_tag[]) {
+ {"CVE", "2017-7308"},
+ {}
+ }
};
diff --git a/testcases/kernel/syscalls/setsockopt/setsockopt08.c b/testcases/kernel/syscalls/setsockopt/setsockopt08.c
index 5fc1a8b8e..7f8243de1 100644
--- a/testcases/kernel/syscalls/setsockopt/setsockopt08.c
+++ b/testcases/kernel/syscalls/setsockopt/setsockopt08.c
@@ -26,57 +26,63 @@
* ->targetsize: if OTOH the user specified ->u.user.target_size is
* too small, then the memset() destination address calculated by
* adding ->targetsize to the payload start will not point at, but
- * into or even past the padding. For the table's last entry's target
- * record, this will result in an out-of-bounds write past the
- * destination buffer allocated for the converted table. The code
- * below will create a (compat) table such that the converted table's
- * calculated size will fit exactly into a slab size of 1024 bytes and
- * that the memset() in xt_compat_target_from_user() will write past
- * this slab.
+ * into or even past the padding.
+ *
+ * For the table's last entry's target record, this will result in an
+ * out-of-bounds write past the destination buffer allocated for the converted
+ * table. The code below will create a (compat) table such that the converted
+ * table's calculated size will fit exactly into a slab size of 1024 bytes and
+ * that the memset() in xt_compat_target_from_user() will write past this slab.
*
* The table will consist of
- * - the mandatory struct compat_ipt_replace header,
- * - a single entry consisting of
- * - the mandatory compat_ipt_entry header
- * - a single 'state' match entry of appropriate size for
+ *
+ * * the mandatory struct compat_ipt_replace header,
+ * * a single entry consisting of
+ * ** the mandatory compat_ipt_entry header
+ * ** a single 'state' match entry of appropriate size for
* controlling the out-of-bounds write when converting
* the target entry following next,
- * - a single 'REJECT' target entry.
+ * ** a single 'REJECT' target entry.
+ *
* The kernel will transform this into a buffer containing (in
* this order)
- * - a xt_table_info
- * - a single entry consisting of
- * - its ipt_entry header
- * - a single 'state' match entry
- * - followed by a single 'REJECT' target entry.
+ *
+ * * a xt_table_info
+ * * a single entry consisting of
+ * ** its ipt_entry header
+ * ** a single 'state' match entry
+ * ** followed by a single 'REJECT' target entry.
*
* The expected sizes for the 'state' match entries as well as the
* 'REJECT' target are the size of the base header struct (32 bytes)
- * plus the size of an unsigned int (4 bytes) each. In the course of
- * the compat => non-compat conversion, the kernel will insert four
- * bytes of padding after the unsigned int payload (c.f. 'off'
- * adjustments via xt_compat_match_offset() and
- * xt_compat_target_offset() in xt_compat_match_from_user() and
- * xt_compat_target_from_user() resp.). This code is based on the
- * premise that the user sets the given ->u.user.match_size or
- * ->u.user.target_size consistent to the COMPAT_XT_ALIGN()ed payload
- * size as specified by the corresponding xt_match instance's
- * ->matchsize or xt_target instance's ->targetsize. That is, the
- * padding gets inserted unconditionally during the transformation,
+ * plus the size of an unsigned int (4 bytes) each.
+ *
+ * In the course of the compat => non-compat conversion, the kernel will insert
+ * four bytes of padding after the unsigned int payload (c.f. 'off' adjustments
+ * via xt_compat_match_offset() and xt_compat_target_offset() in
+ * xt_compat_match_from_user() and xt_compat_target_from_user() resp.).
+ *
+ * This code is based on the premise that the user sets the given
+ * ->u.user.match_size or ->u.user.target_size consistent to the
+ * COMPAT_XT_ALIGN()ed payload size as specified by the corresponding xt_match
+ * instance's ->matchsize or xt_target instance's ->targetsize.
+ *
+ * That is, the padding gets inserted unconditionally during the transformation,
* independent of the actual values of ->u.user.match_size or
- * ->u.user.target_size and the result ends up getting layed out with
- * proper alignment only if said values match the expectations. That's
- * not a problem in itself, but this unconditional insertion of
- * padding must be taken into account in the match_size calculation
- * below.
+ * ->u.user.target_size and the result ends up getting layed out with proper
+ * alignment only if said values match the expectations.
+ *
+ * That's not a problem in itself, but this unconditional insertion of padding
+ * must be taken into account in the match_size calculation below.
*
* For the match_size calculation below, note that the chosen
* target slab size is 1024 and that
- * - sizeof(xt_table_info) = 64
- * - sizeof(ipt_entry) = 112
- * - the kernel will insert four bytes of padding
+ *
+ * * sizeof(xt_table_info) = 64
+ * * sizeof(ipt_entry) = 112
+ * * the kernel will insert four bytes of padding
* after the match and target entries each.
- * - sizeof(struct xt_entry_target) = 32
+ * * sizeof(struct xt_entry_target) = 32
*/
#include <netinet/in.h>
diff --git a/testcases/kernel/syscalls/sockioctl/sockioctl01.c b/testcases/kernel/syscalls/sockioctl/sockioctl01.c
index 51dac9c16..ff3738f32 100644
--- a/testcases/kernel/syscalls/sockioctl/sockioctl01.c
+++ b/testcases/kernel/syscalls/sockioctl/sockioctl01.c
@@ -52,7 +52,7 @@ static struct ifreq ifr;
static int sinlen;
static int optval;
-static char buf[8192];
+static struct ifreq buf[200];
static void setup(void);
static void setup0(void);
@@ -218,7 +218,7 @@ static void setup2(void)
s = SAFE_SOCKET(cleanup, tdat[testno].domain, tdat[testno].type,
tdat[testno].proto);
ifc.ifc_len = sizeof(buf);
- ifc.ifc_buf = buf;
+ ifc.ifc_buf = (char *)buf;
}
static void setup3(void)
diff --git a/testcases/kernel/syscalls/stat/stat01.c b/testcases/kernel/syscalls/stat/stat01.c
index e0dbfbf2f..365cdac8a 100644
--- a/testcases/kernel/syscalls/stat/stat01.c
+++ b/testcases/kernel/syscalls/stat/stat01.c
@@ -8,9 +8,9 @@
/*\
* [Description]
*
- * Verify that, stat(2) succeeds to get the status of a file and fills the
- * stat structure elements regardless of whether process has or doesn't
- * have read access to the file.
+ * Verify that, stat(2) succeeds to get the status of a file and fills the
+ * stat structure elements regardless of whether process has or doesn't
+ * have read access to the file.
*/
#include <pwd.h>
diff --git a/testcases/kernel/syscalls/statvfs/statvfs02.c b/testcases/kernel/syscalls/statvfs/statvfs02.c
index 8aaa47318..6f36530bf 100644
--- a/testcases/kernel/syscalls/statvfs/statvfs02.c
+++ b/testcases/kernel/syscalls/statvfs/statvfs02.c
@@ -10,6 +10,7 @@
* [Description]
*
* Verify that statvfs() fails with:
+ *
* - EFAULT when path points to an invalid address.
* - ELOOP when too many symbolic links were encountered in translating path.
* - ENAMETOOLONG when path is too long.
diff --git a/testcases/kernel/syscalls/statx/.gitignore b/testcases/kernel/syscalls/statx/.gitignore
index 1cea43c0d..f6a423eed 100644
--- a/testcases/kernel/syscalls/statx/.gitignore
+++ b/testcases/kernel/syscalls/statx/.gitignore
@@ -7,3 +7,6 @@
/statx07
/statx08
/statx09
+/statx10
+/statx11
+/statx12
diff --git a/testcases/kernel/syscalls/statx/statx01.c b/testcases/kernel/syscalls/statx/statx01.c
index 68f56549f..f9c2748d2 100644
--- a/testcases/kernel/syscalls/statx/statx01.c
+++ b/testcases/kernel/syscalls/statx/statx01.c
@@ -33,6 +33,7 @@
#include "tst_test.h"
#include "tst_safe_macros.h"
#include "lapi/stat.h"
+#include "lapi/fcntl.h"
#include "tst_safe_stdio.h"
#include <string.h>
#include <inttypes.h>
diff --git a/testcases/kernel/syscalls/statx/statx02.c b/testcases/kernel/syscalls/statx/statx02.c
index a8e868d7a..5ed80894d 100644
--- a/testcases/kernel/syscalls/statx/statx02.c
+++ b/testcases/kernel/syscalls/statx/statx02.c
@@ -28,6 +28,7 @@
#include "tst_test.h"
#include "tst_safe_macros.h"
#include "lapi/stat.h"
+#include "lapi/fcntl.h"
#define TESTFILE "test_temp"
#define LINK_FILE "test_temp_ln"
diff --git a/testcases/kernel/syscalls/statx/statx03.c b/testcases/kernel/syscalls/statx/statx03.c
index b88809063..2465d8773 100644
--- a/testcases/kernel/syscalls/statx/statx03.c
+++ b/testcases/kernel/syscalls/statx/statx03.c
@@ -24,6 +24,7 @@
#include "tst_safe_macros.h"
#include "tst_get_bad_addr.h"
#include "lapi/stat.h"
+#include "lapi/fcntl.h"
#define TESTFILE "test_file"
#define MODE 0644
diff --git a/testcases/kernel/syscalls/statx/statx04.c b/testcases/kernel/syscalls/statx/statx04.c
index 3923b7f8e..58296bd24 100644
--- a/testcases/kernel/syscalls/statx/statx04.c
+++ b/testcases/kernel/syscalls/statx/statx04.c
@@ -52,10 +52,11 @@
*/
#define _GNU_SOURCE
+#include <stdlib.h>
#include "tst_test.h"
#include "lapi/fs.h"
-#include <stdlib.h>
#include "lapi/stat.h"
+#include "lapi/fcntl.h"
#define MOUNT_POINT "mntpoint"
#define TESTDIR MOUNT_POINT "/testdir"
diff --git a/testcases/kernel/syscalls/statx/statx05.c b/testcases/kernel/syscalls/statx/statx05.c
index f62dadd5c..9781b3e70 100644
--- a/testcases/kernel/syscalls/statx/statx05.c
+++ b/testcases/kernel/syscalls/statx/statx05.c
@@ -27,6 +27,7 @@
#include "tst_test.h"
#include "lapi/fs.h"
#include "lapi/stat.h"
+#include "lapi/fcntl.h"
#define MNTPOINT "mnt_point"
#define TESTDIR_FLAGGED MNTPOINT"/test_dir1"
diff --git a/testcases/kernel/syscalls/statx/statx06.c b/testcases/kernel/syscalls/statx/statx06.c
index fa75982b0..1771dff49 100644
--- a/testcases/kernel/syscalls/statx/statx06.c
+++ b/testcases/kernel/syscalls/statx/statx06.c
@@ -111,10 +111,10 @@ static void test_statx(unsigned int test_nr)
clock_wait_tick();
SAFE_CLOCK_GETTIME(CLOCK_REALTIME, &after_time);
- TEST(statx(AT_FDCWD, TEST_FILE, 0, STATX_ALL, &buff));
+ TEST(statx(AT_FDCWD, TEST_FILE, 0, STATX_BASIC_STATS | STATX_BTIME, &buff));
if (TST_RET != 0) {
tst_brk(TFAIL | TTERRNO,
- "statx(AT_FDCWD, %s, 0, STATX_ALL, &buff)",
+ "statx(AT_FDCWD, %s, 0, STATX_BASIC_STATS | STATX_BTIME, &buff)",
TEST_FILE);
}
diff --git a/testcases/kernel/syscalls/statx/statx07.c b/testcases/kernel/syscalls/statx/statx07.c
index 8cb3e9b6d..4dbf83e18 100644
--- a/testcases/kernel/syscalls/statx/statx07.c
+++ b/testcases/kernel/syscalls/statx/statx07.c
@@ -27,12 +27,7 @@
* but mode has been chaged in server file.
*
* The support for SYNC flags was implemented in NFS in:
- *
- * commit 9ccee940bd5b766b6dab6c1a80908b9490a4850d
- * Author: Trond Myklebust <trond.myklebust@primarydata.com>
- * Date: Thu Jan 4 17:46:09 2018 -0500
- *
- * Support statx() mask and query flags parameters
+ * 9ccee940bd5b ("Support statx() mask and query flags parameters")
*/
#define _GNU_SOURCE
@@ -44,6 +39,7 @@
#include <sys/mount.h>
#include "tst_test.h"
#include "lapi/stat.h"
+#include "lapi/fcntl.h"
#define MODE(X) (X & (~S_IFMT))
#define FLAG_NAME(x) .flag = x, .flag_name = #x
@@ -67,15 +63,15 @@ static int get_mode(char *file_name, int flag_type, char *flag_name)
{
struct statx buf;
- TEST(statx(AT_FDCWD, file_name, flag_type, STATX_ALL, &buf));
+ TEST(statx(AT_FDCWD, file_name, flag_type, STATX_BASIC_STATS, &buf));
if (TST_RET == -1) {
tst_brk(TFAIL | TST_ERR,
- "statx(AT_FDCWD, %s, %s, STATX_ALL, &buf)",
+ "statx(AT_FDCWD, %s, %s, STATX_BASIC_STATS, &buf)",
file_name, flag_name);
}
- tst_res(TINFO, "statx(AT_FDCWD, %s, %s, STATX_ALL, &buf) = %o",
+ tst_res(TINFO, "statx(AT_FDCWD, %s, %s, STATX_BASIC_STATS, &buf) = %o",
file_name, flag_name, buf.stx_mode);
return buf.stx_mode;
diff --git a/testcases/kernel/syscalls/statx/statx08.c b/testcases/kernel/syscalls/statx/statx08.c
index 10b1ca460..64b36986d 100644
--- a/testcases/kernel/syscalls/statx/statx08.c
+++ b/testcases/kernel/syscalls/statx/statx08.c
@@ -26,6 +26,7 @@
#include "lapi/fs.h"
#include <stdlib.h>
#include "lapi/stat.h"
+#include "lapi/fcntl.h"
#define MOUNT_POINT "mntpoint"
#define TESTDIR_FLAGGED MOUNT_POINT"/test_dir1"
diff --git a/testcases/kernel/syscalls/statx/statx09.c b/testcases/kernel/syscalls/statx/statx09.c
index aea329e08..6e75ff3ec 100644
--- a/testcases/kernel/syscalls/statx/statx09.c
+++ b/testcases/kernel/syscalls/statx/statx09.c
@@ -20,10 +20,12 @@
#define _GNU_SOURCE
#include <sys/mount.h>
#include <stdlib.h>
+#include <stdio.h>
#include "tst_test.h"
#include "lapi/fs.h"
#include "lapi/fsverity.h"
#include "lapi/stat.h"
+#include "lapi/fcntl.h"
#include <inttypes.h>
#define MNTPOINT "mnt_point"
@@ -79,8 +81,10 @@ static void flag_setup(void)
{
int fd, attr, ret;
struct fsverity_enable_arg enable;
+ struct stat statbuf;
fd = SAFE_OPEN(TESTFILE_FLAGGED, O_RDONLY, 0664);
+ SAFE_FSTAT(fd, &statbuf);
ret = ioctl(fd, FS_IOC_GETFLAGS, &attr);
if (ret < 0) {
@@ -93,7 +97,7 @@ static void flag_setup(void)
memset(&enable, 0, sizeof(enable));
enable.version = 1;
enable.hash_algorithm = hash_algorithms[0];
- enable.block_size = 4096;
+ enable.block_size = statbuf.st_blksize;
enable.salt_size = 0;
enable.salt_ptr = (intptr_t)NULL;
enable.sig_size = 0;
@@ -117,6 +121,12 @@ static void flag_setup(void)
static void setup(void)
{
+ char opt_bsize[32];
+ const char *const fs_opts[] = {"-O verity", opt_bsize, NULL};
+
+ snprintf(opt_bsize, sizeof(opt_bsize), "-b %i", getpagesize());
+ SAFE_MKFS(tst_device->dev, tst_device->fs_type, fs_opts, NULL);
+
TEST(mount(tst_device->dev, MNTPOINT, tst_device->fs_type, 0, NULL));
if (TST_RET) {
if (TST_ERR == EINVAL)
@@ -144,10 +154,9 @@ static struct tst_test test = {
.setup = setup,
.cleanup = cleanup,
.needs_root = 1,
+ .needs_device = 1,
.mntpoint = MNTPOINT,
- .format_device = 1,
.dev_fs_type = "ext4",
- .dev_fs_opts = (const char *const []){"-O verity", NULL},
.needs_kconfigs = (const char *[]) {
"CONFIG_FS_VERITY",
NULL
diff --git a/testcases/kernel/syscalls/statx/statx10.c b/testcases/kernel/syscalls/statx/statx10.c
new file mode 100644
index 000000000..42106285e
--- /dev/null
+++ b/testcases/kernel/syscalls/statx/statx10.c
@@ -0,0 +1,93 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2023 FUJITSU LIMITED. All rights reserved.
+ * Author: Yang Xu <xuyang2018.jy@fujitsu.com>
+ */
+
+/*\
+ * [Description]
+ *
+ * It is a basic test for STATX_DIOALIGN mask on ext4 and xfs filesystem.
+ *
+ * - STATX_DIOALIGN Want stx_dio_mem_align and stx_dio_offset_align value
+ *
+ * Check these two values are nonzero under dio situation when STATX_DIOALIGN
+ * in the request mask.
+ *
+ * On ext4, files that use certain filesystem features (data journaling,
+ * encryption, and verity) fall back to buffered I/O. But ltp creates own
+ * filesystem by enabling mount_device in tst_test struct. If we set block
+ * device to LTP_DEV environment, we use this block device to mount by using
+ * default mount option. Otherwise, use loop device to simuate it. So it can
+ * avoid these above situations and don't fall back to buffered I/O.
+ *
+ * Minimum Linux version required is v6.1.
+ */
+
+#define _GNU_SOURCE
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include "tst_test.h"
+#include "lapi/stat.h"
+#include "lapi/fcntl.h"
+
+#define MNTPOINT "mnt_point"
+#define TESTFILE MNTPOINT"/testfile"
+
+static void verify_statx(void)
+{
+ struct statx buf;
+
+ TST_EXP_PASS_SILENT(statx(AT_FDCWD, TESTFILE, 0, STATX_DIOALIGN, &buf),
+ "statx(AT_FDCWD, %s, 0, STATX_DIOALIGN, &buf)", TESTFILE);
+
+ if (!(buf.stx_mask & STATX_DIOALIGN)) {
+ tst_res(TCONF, "Filesystem does not support STATX_DIOALIGN");
+ return;
+ }
+
+#ifdef HAVE_STRUCT_STATX_STX_DIO_MEM_ALIGN
+ if (buf.stx_dio_mem_align != 0)
+ tst_res(TPASS, "stx_dio_mem_align:%u", buf.stx_dio_mem_align);
+ else
+ tst_res(TFAIL, "stx_dio_mem_align was 0, but DIO should be supported");
+
+ if (buf.stx_dio_offset_align != 0)
+ tst_res(TPASS, "stx_dio_offset_align:%u", buf.stx_dio_offset_align);
+ else
+ tst_res(TFAIL, "stx_dio_offset_align was 0, but DIO should be supported");
+#else
+ tst_res(TCONF, "glibc statx struct miss stx_dio_mem_align field");
+#endif
+}
+
+static void setup(void)
+{
+ int fd = -1;
+
+ if (strcmp(tst_device->fs_type, "xfs") && strcmp(tst_device->fs_type, "ext4"))
+ tst_brk(TCONF, "This test only supports ext4 and xfs");
+
+ SAFE_FILE_PRINTF(TESTFILE, "AAAA");
+ fd = open(TESTFILE, O_RDWR | O_DIRECT);
+ if (fd == -1) {
+ if (errno == EINVAL)
+ tst_brk(TCONF,
+ "The regular file is not on a filesystem that support DIO");
+ else
+ tst_brk(TBROK | TERRNO,
+ "The regular file is open with O_RDWR | O_DIRECT failed");
+ }
+ SAFE_CLOSE(fd);
+}
+
+static struct tst_test test = {
+ .test_all = verify_statx,
+ .setup = setup,
+ .needs_root = 1,
+ .mntpoint = MNTPOINT,
+ .mount_device = 1,
+ .all_filesystems = 1,
+};
diff --git a/testcases/kernel/syscalls/statx/statx11.c b/testcases/kernel/syscalls/statx/statx11.c
new file mode 100644
index 000000000..653050855
--- /dev/null
+++ b/testcases/kernel/syscalls/statx/statx11.c
@@ -0,0 +1,89 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2023 FUJITSU LIMITED. All rights reserved.
+ * Author: Yang Xu <xuyang2018.jy@fujitsu.com>
+ */
+
+/*\
+ * [Description]
+ *
+ * It is a basic test for STATX_DIOALIGN mask on block device.
+ *
+ * - STATX_DIOALIGN Want stx_dio_mem_align and stx_dio_offset_align value
+ *
+ * These two values are tightly coupled to the kernel's current DIO
+ * restrictions on block devices.
+ *
+ * Minimum Linux version required is v6.1.
+ */
+
+#define _GNU_SOURCE
+#include <sys/types.h>
+#include <sys/mount.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include "tst_test.h"
+#include "lapi/stat.h"
+
+static char sys_bdev_dma_path[1024], sys_bdev_logical_path[1024];
+
+static void verify_statx(void)
+{
+ struct statx buf;
+
+ TST_EXP_PASS_SILENT(statx(AT_FDCWD, tst_device->dev, 0, STATX_DIOALIGN, &buf),
+ "statx(AT_FDCWD, %s, 0, STATX_DIOALIGN, &buf)", tst_device->dev);
+
+ if (!(buf.stx_mask & STATX_DIOALIGN)) {
+ tst_res(TCONF, "Filesystem does not support STATX_DIOALIGN");
+ return;
+ }
+
+#ifdef HAVE_STRUCT_STATX_STX_DIO_MEM_ALIGN
+ /*
+ * This test is tightly coupled to the kernel's current DIO restrictions
+ * on block devices. The general rule of DIO needing to be aligned to the
+ * block device's logical block size was relaxed to allow user buffers
+ * (but not file offsets) aligned to the DMA alignment instead. See v6.0
+ * commit bf8d08532bc1 ("iomap: add support for dma aligned direct-io") and
+ * they are subject to further change in the future.
+ * Also can see commit 2d985f8c6b9 ("vfs: support STATX_DIOALIGN on block devices).
+ */
+ TST_ASSERT_ULONG(sys_bdev_dma_path, buf.stx_dio_mem_align - 1);
+ TST_ASSERT_ULONG(sys_bdev_logical_path, buf.stx_dio_offset_align);
+#else
+ tst_res(TCONF, "glibc statx struct miss stx_dio_mem_align field");
+#endif
+}
+
+static void setup(void)
+{
+ char full_name[256];
+ char *dev_name;
+
+ strcpy(full_name, tst_device->dev);
+ dev_name = SAFE_BASENAME(full_name);
+ sprintf(sys_bdev_logical_path, "/sys/block/%s/queue/logical_block_size", dev_name);
+
+ /*
+ * Since /sys/block/%s/queue doesn't exist for partition, we need to
+ * use a while to search block device instead of partition.
+ */
+ while (access(sys_bdev_logical_path, F_OK) != 0) {
+ dev_name[strlen(dev_name)-1] = '\0';
+ sprintf(sys_bdev_logical_path, "/sys/block/%s/queue/logical_block_size", dev_name);
+ }
+
+ sprintf(sys_bdev_dma_path, "/sys/block/%s/queue/dma_alignment", dev_name);
+ if (access(sys_bdev_dma_path, F_OK) != 0)
+ tst_brk(TCONF, "dma_alignment sysfs file doesn't exist");
+}
+
+static struct tst_test test = {
+ .test_all = verify_statx,
+ .setup = setup,
+ .needs_device = 1,
+ .needs_root = 1,
+};
diff --git a/testcases/kernel/syscalls/statx/statx12.c b/testcases/kernel/syscalls/statx/statx12.c
new file mode 100644
index 000000000..432f1cb77
--- /dev/null
+++ b/testcases/kernel/syscalls/statx/statx12.c
@@ -0,0 +1,95 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2023 FUJITSU LIMITED. All rights reserved.
+ * Author: Yang Xu <xuyang2018.jy@fujitsu.com>
+ */
+
+/*\
+ * [Description]
+ *
+ * It is a basic test for STATX_ATTR_MOUNT_ROOT flag.
+ *
+ * This flag indicates whether the path or fd refers to the root of a mount
+ * or not.
+ *
+ * Minimum Linux version required is v5.8.
+ */
+
+#define _GNU_SOURCE
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include "tst_test.h"
+#include "lapi/stat.h"
+
+#define MNTPOINT "mntpoint"
+#define TESTFILE MNTPOINT"/testfile"
+
+static int dir_fd = -1, file_fd = -1;
+
+static struct tcase {
+ const char *path;
+ bool mnt_root;
+ int *fd;
+} tcases[] = {
+ {MNTPOINT, 1, &dir_fd},
+ {TESTFILE, 0, &file_fd}
+};
+
+static void verify_statx(unsigned int n)
+{
+ struct tcase *tc = &tcases[n/2];
+ struct statx buf;
+ bool flag = n % 2;
+
+ if (flag) {
+ tst_res(TINFO, "Testing %s with STATX_ATTR_MOUNT_ROOT by fd",
+ tc->path);
+ TST_EXP_PASS_SILENT(statx(*tc->fd, "", AT_EMPTY_PATH, 0, &buf));
+ } else {
+ tst_res(TINFO, "Testing %s with STATX_ATTR_MOUNT_ROOT by path",
+ tc->path);
+ TST_EXP_PASS_SILENT(statx(AT_FDCWD, tc->path, 0, 0, &buf));
+ }
+
+ if (!(buf.stx_attributes_mask & STATX_ATTR_MOUNT_ROOT)) {
+ tst_res(TCONF, "Filesystem does not support STATX_ATTR_MOUNT_ROOT");
+ return;
+ }
+
+ if (buf.stx_attributes & STATX_ATTR_MOUNT_ROOT) {
+ tst_res(tc->mnt_root ? TPASS : TFAIL,
+ "STATX_ATTR_MOUNT_ROOT flag is set");
+ } else {
+ tst_res(tc->mnt_root ? TFAIL : TPASS,
+ "STATX_ATTR_MOUNT_ROOT flag is not set");
+ }
+}
+
+static void setup(void)
+{
+ SAFE_CREAT(TESTFILE, 0755);
+ dir_fd = SAFE_OPEN(MNTPOINT, O_DIRECTORY);
+ file_fd = SAFE_OPEN(TESTFILE, O_RDWR);
+}
+
+static void cleanup(void)
+{
+ if (dir_fd > -1)
+ SAFE_CLOSE(dir_fd);
+
+ if (file_fd > -1)
+ SAFE_CLOSE(file_fd);
+}
+
+static struct tst_test test = {
+ .test = verify_statx,
+ .setup = setup,
+ .cleanup = cleanup,
+ .mntpoint = MNTPOINT,
+ .mount_device = 1,
+ .all_filesystems = 1,
+ .needs_root = 1,
+ .tcnt = 2 * ARRAY_SIZE(tcases)
+};
diff --git a/testcases/kernel/syscalls/switch/endian_switch01.c b/testcases/kernel/syscalls/switch/endian_switch01.c
index bee35184a..fac9e2382 100644
--- a/testcases/kernel/syscalls/switch/endian_switch01.c
+++ b/testcases/kernel/syscalls/switch/endian_switch01.c
@@ -2,7 +2,7 @@
/*
* Copyright (c) International Business Machines Corp., 2008
* Copyright (c) Paul Mackerras, IBM Corp., 2008
- * Copyright (c) 2018 Linux Test Project
+ * Copyright (c) 2018-2023 Linux Test Project
*/
/*
@@ -17,14 +17,17 @@
#include <elf.h>
#include <sys/types.h>
#include <sys/wait.h>
+
#include "tst_test.h"
#if defined(__powerpc64__) || defined(__powerpc__)
+
# ifndef PPC_FEATURE_TRUE_LE
-# define PPC_FEATURE_TRUE_LE 0x00000002
+# define PPC_FEATURE_TRUE_LE 0x00000002
# endif
-# define TST_NO_DEFAULT_MAIN
+# ifdef HAVE_GETAUXVAL
+# include <sys/auxv.h>
/*
* Make minimal call to 0x1ebe. If we get ENOSYS then syscall is not
@@ -42,6 +45,9 @@ void check_le_switch_supported(void)
exit(errno);
}
+ if (!(getauxval(AT_HWCAP) & PPC_FEATURE_TRUE_LE))
+ tst_brk(TCONF, "Processor does not support little-endian mode");
+
SAFE_WAIT(&status);
if (WIFSIGNALED(status)) {
int sig = WTERMSIG(status);
@@ -96,18 +102,9 @@ static struct tst_test test = {
.forks_child = 1,
};
-int main4(int argc, char **argv, LTP_ATTRIBUTE_UNUSED char **envp,
- unsigned long *auxv)
-{
- for (; *auxv != AT_NULL && *auxv != AT_HWCAP; auxv += 2)
- ;
-
- if (!(auxv[0] == AT_HWCAP && (auxv[1] & PPC_FEATURE_TRUE_LE)))
- tst_brk(TCONF, "Processor does not support little-endian mode");
-
- tst_run_tcases(argc, argv, &test);
- return 0;
-}
+# else
+TST_TEST_TCONF("Toolchain does not have <sys/auxv.h>");
+# endif /* HAVE_GETAUXVAL */
#else /* defined (__powerpc64__) || (__powerpc__) */
TST_TEST_TCONF("This system does not support running of switch() syscall");
diff --git a/testcases/kernel/syscalls/symlink/symlink01.c b/testcases/kernel/syscalls/symlink/symlink01.c
index eba64f9bd..8cf0c8f1c 100644
--- a/testcases/kernel/syscalls/symlink/symlink01.c
+++ b/testcases/kernel/syscalls/symlink/symlink01.c
@@ -658,10 +658,10 @@ int creat_symlink(char *path1, char *path2, char *_path3)
path1, errno, strerror(errno));
return 0;
} else {
- sprintf(Buf, "symlink(%s, %s) was succesful.\n", path1, path2);
+ sprintf(Buf, "symlink(%s, %s) was successful.\n", path1, path2);
strcat(Buffer, Buf);
#if DEBUG
- tst_resm(TPASS, "symlink(%s, %s) was succesful.", path1, path2);
+ tst_resm(TPASS, "symlink(%s, %s) was successful.", path1, path2);
#endif
}
return 1;
@@ -685,10 +685,10 @@ int creat_object(char *path1, char *_path2, char *_path3)
path1, errno, strerror(errno));
return 0;
} else {
- sprintf(Buf, "creat(%s, %#o) was succesful.\n", path1, MODE);
+ sprintf(Buf, "creat(%s, %#o) was successful.\n", path1, MODE);
strcat(Buffer, Buf);
#if DEBUG
- tst_resm(TPASS, "creat(%s, %#o) was succesful.", path1, MODE);
+ tst_resm(TPASS, "creat(%s, %#o) was successful.", path1, MODE);
#endif
}
if (close(fd) == -1) {
diff --git a/testcases/kernel/syscalls/timerfd/timerfd_create01.c b/testcases/kernel/syscalls/timerfd/timerfd_create01.c
index 3d70b84f0..18a233586 100644
--- a/testcases/kernel/syscalls/timerfd/timerfd_create01.c
+++ b/testcases/kernel/syscalls/timerfd/timerfd_create01.c
@@ -1,95 +1,40 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* 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; if not, write the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ * Zeng Linggang <zenglg.jy@cn.fujitsu.com>
+ * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
*/
-/*
- * DESCRIPTION
- * Verify that,
- * 1. The clockid argument is neither CLOCK_MONOTONIC nor CLOCK_REALTIME,
- * EINVAL would return.
- * 2. flags is invalid, EINVAL would return.
+/*\
+ * [Description]
+ *
+ * This test verifies that:
+ * - clockid argument is neither CLOCK_MONOTONIC nor CLOCK_REALTIME,
+ * EINVAL would return.
+ * - flags is invalid, EINVAL would return.
*/
-#define _GNU_SOURCE
-
#include <errno.h>
-#include "test.h"
-#include "lapi/timerfd.h"
-
-char *TCID = "timerfd_create01";
+#include "tst_test.h"
+#include "tst_safe_timerfd.h"
static struct test_case_t {
int clockid;
int flags;
int exp_errno;
-} test_cases[] = {
- {-1, 0, EINVAL},
- {0, -1, EINVAL},
+} tcases[] = {
+ { -1, 0, EINVAL },
+ { 0, -1, EINVAL },
};
-int TST_TOTAL = ARRAY_SIZE(test_cases);
-static void setup(void);
-static void timerfd_create_verify(const struct test_case_t *);
-static void cleanup(void);
-
-int main(int argc, char *argv[])
+static void run(unsigned int i)
{
- int lc;
- int i;
-
- tst_parse_opts(argc, argv, NULL, NULL);
+ struct test_case_t *test = &tcases[i];
- setup();
-
- for (lc = 0; TEST_LOOPING(lc); lc++) {
- tst_count = 0;
- for (i = 0; i < TST_TOTAL; i++)
- timerfd_create_verify(&test_cases[i]);
- }
-
- cleanup();
- tst_exit();
+ TST_EXP_FAIL(timerfd_create(test->clockid, test->flags), test->exp_errno);
}
-static void setup(void)
-{
- tst_sig(NOFORK, DEF_HANDLER, cleanup);
-
- TEST_PAUSE;
-}
-
-static void timerfd_create_verify(const struct test_case_t *test)
-{
- TEST(timerfd_create(test->clockid, test->flags));
-
- if (TEST_RETURN != -1) {
- tst_resm(TFAIL, "timerfd_create() succeeded unexpectedly");
- return;
- }
-
- if (TEST_ERRNO == test->exp_errno) {
- tst_resm(TPASS | TTERRNO,
- "timerfd_create() failed as expected");
- } else {
- tst_resm(TFAIL | TTERRNO,
- "timerfd_create() failed unexpectedly; expected: "
- "%d - %s", test->exp_errno, strerror(test->exp_errno));
- }
-}
-
-static void cleanup(void)
-{
-}
+static struct tst_test test = {
+ .test = run,
+ .tcnt = ARRAY_SIZE(tcases),
+};
diff --git a/testcases/kernel/syscalls/uname/uname04.c b/testcases/kernel/syscalls/uname/uname04.c
index 2d0851c8b..885368c24 100644
--- a/testcases/kernel/syscalls/uname/uname04.c
+++ b/testcases/kernel/syscalls/uname/uname04.c
@@ -79,4 +79,8 @@ static void run(unsigned int test_nr)
static struct tst_test test = {
.test = run,
.tcnt = 2,
+ .tags = (const struct tst_tag[]) {
+ {"CVE", "2012-0957"},
+ {}
+ }
};
diff --git a/testcases/kernel/syscalls/utils/compat_uid.h b/testcases/kernel/syscalls/utils/compat_uid.h
index 94e54f310..7a345a654 100644
--- a/testcases/kernel/syscalls/utils/compat_uid.h
+++ b/testcases/kernel/syscalls/utils/compat_uid.h
@@ -26,7 +26,7 @@
#include "tst_common.h"
#ifdef TST_USE_COMPAT16_SYSCALL
-typedef __kernel_old_uid_t UID_T;
+typedef unsigned short UID_T;
int UID_SIZE_CHECK(uid_t uid)
{
/* See high2lowuid in linux/highuid.h
diff --git a/testcases/kernel/syscalls/utils/ioprio.h b/testcases/kernel/syscalls/utils/ioprio.h
deleted file mode 100644
index 07220945c..000000000
--- a/testcases/kernel/syscalls/utils/ioprio.h
+++ /dev/null
@@ -1,46 +0,0 @@
-#ifndef __IOPRIO_H__
-#define __IOPRIO_H__
-
-//----------------------------------------------------------------------------
-// Copy of the 2.6.18 kernel header (linux/ioprio.h)
-//
-
-/*
- * Gives us 8 prio classes with 13-bits of data for each class
- */
-#define IOPRIO_BITS (16)
-#define IOPRIO_CLASS_SHIFT (13)
-#define IOPRIO_PRIO_MASK ((1UL << IOPRIO_CLASS_SHIFT) - 1)
-
-#define IOPRIO_PRIO_CLASS(mask) ((mask) >> IOPRIO_CLASS_SHIFT)
-#define IOPRIO_PRIO_DATA(mask) ((mask) & IOPRIO_PRIO_MASK)
-#define IOPRIO_PRIO_VALUE(class, data) (((class) << IOPRIO_CLASS_SHIFT) | data)
-
-#define ioprio_valid(mask) (IOPRIO_PRIO_CLASS((mask)) != IOPRIO_CLASS_NONE)
-
-/*
- * These are the io priority groups as implemented by CFQ. RT is the realtime
- * class, it always gets premium service. BE is the best-effort scheduling
- * class, the default for any process. IDLE is the idle scheduling class, it
- * is only served when no one else is using the disk.
- */
-enum {
- IOPRIO_CLASS_NONE,
- IOPRIO_CLASS_RT,
- IOPRIO_CLASS_BE,
- IOPRIO_CLASS_IDLE,
-};
-
-/*
- * 8 best effort priority levels are supported
- */
-#define IOPRIO_BE_NR (8)
-
-enum {
- IOPRIO_WHO_PROCESS = 1,
- IOPRIO_WHO_PGRP,
- IOPRIO_WHO_USER,
-};
-//-----------------------------------------------------------------------------
-
-#endif /* __IOPRIO_H__ */
diff --git a/testcases/kernel/syscalls/utime/utime02.c b/testcases/kernel/syscalls/utime/utime02.c
index 54693899e..fdcd40f66 100644
--- a/testcases/kernel/syscalls/utime/utime02.c
+++ b/testcases/kernel/syscalls/utime/utime02.c
@@ -11,6 +11,7 @@
* Verify that the system call utime() successfully changes the last
* access and modification times of a file to the current time,
* under the following constraints:
+ *
* - The times argument is NULL.
* - The user ID of the process is not "root".
* - The file is owned by the user ID of the process.
diff --git a/testcases/kernel/syscalls/utime/utime04.c b/testcases/kernel/syscalls/utime/utime04.c
index 67e40127d..7b820ab06 100644
--- a/testcases/kernel/syscalls/utime/utime04.c
+++ b/testcases/kernel/syscalls/utime/utime04.c
@@ -1,8 +1,8 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
- * Copyright (c) International Business Machines Corp., 2001
- * 07/2001 ported by John George
- * Copyright (c) 2022 SUSE LLC Avinesh Kumar <avinesh.kumar@suse.com>
+ * Copyright (c) International Business Machines Corp., 2001
+ * 07/2001 ported by John George
+ * Copyright (c) 2022 SUSE LLC Avinesh Kumar <avinesh.kumar@suse.com>
*/
/*\
@@ -11,6 +11,7 @@
* Verify that the system call utime() successfully changes the last
* access and modification times of a file to the values specified by
* times argument, under the following constraints:
+ *
* - The times argument is not NULL.
* - The user ID of the process is "root".
*/
diff --git a/testcases/kernel/syscalls/utime/utime05.c b/testcases/kernel/syscalls/utime/utime05.c
index ce0aa5dbf..941a3ccee 100644
--- a/testcases/kernel/syscalls/utime/utime05.c
+++ b/testcases/kernel/syscalls/utime/utime05.c
@@ -11,6 +11,7 @@
* Verify that the system call utime() successfully changes the last
* access and modification times of a file to the values specified by
* times argument, under the following constraints:
+ *
* - The times argument is not NULL.
* - The user ID of the process is not "root".
* - The file is owned by the user ID of the process.
diff --git a/testcases/kernel/syscalls/utime/utime06.c b/testcases/kernel/syscalls/utime/utime06.c
index 9057c29da..3ba62a316 100644
--- a/testcases/kernel/syscalls/utime/utime06.c
+++ b/testcases/kernel/syscalls/utime/utime06.c
@@ -9,11 +9,12 @@
* [Description]
*
* Verify that system call utime() fails with
- * - EACCES when times argument is NULL and user does not have rights
- * to modify the file.
+ *
+ * - EACCES when times argument is NULL and user does not have rights to modify
+ * the file.
* - ENOENT when specified file does not exist.
- * - EPERM when times argument is not NULL and user does not have rights
- * to modify the file.
+ * - EPERM when times argument is not NULL and user does not have rights to
+ * modify the file.
* - EROFS when the path resides on a read-only filesystem.
*/
diff --git a/testcases/kernel/syscalls/utimensat/utimensat01.c b/testcases/kernel/syscalls/utimensat/utimensat01.c
index 71a0e8d0e..efcb5c7a4 100644
--- a/testcases/kernel/syscalls/utimensat/utimensat01.c
+++ b/testcases/kernel/syscalls/utimensat/utimensat01.c
@@ -233,7 +233,7 @@ static void run(unsigned int i)
dfd = SAFE_OPEN(TEST_DIR, tc->oflags);
if (tc->pathname) {
- fd = SAFE_OPEN(tc->pathname, O_WRONLY | O_CREAT);
+ fd = SAFE_OPEN(tc->pathname, O_WRONLY | O_CREAT, 0200);
pathname = tc->pathname;
SAFE_CHMOD(tc->pathname, tc->mode);
reset_time(pathname, dfd, tc->flags, i);
diff --git a/testcases/kernel/syscalls/write/write02.c b/testcases/kernel/syscalls/write/write02.c
index 2f630ab65..ab38dce77 100644
--- a/testcases/kernel/syscalls/write/write02.c
+++ b/testcases/kernel/syscalls/write/write02.c
@@ -2,27 +2,24 @@
/*
* Copyright (c) 2017 Carlo Marcelo Arenas Belon <carlo@gmail.com>
* Copyright (c) 2018 Cyril Hrubis <chrubis@suse.cz>
+ * Copyright (c) Linux Test Project, 2003-2023
*/
-/*
+
+/*\
+ * [Description]
+ *
* Tests for a special case NULL buffer with size 0 is expected to return 0.
*/
-#include <errno.h>
#include "tst_test.h"
static int fd;
static void verify_write(void)
{
- TEST(write(fd, NULL, 0));
-
- if (TST_RET != 0) {
- tst_res(TFAIL | TTERRNO,
- "write() should have succeeded with ret=0");
- return;
- }
+ TST_EXP_POSITIVE(write(fd, NULL, 0));
- tst_res(TPASS, "write(fd, NULL, 0) == 0");
+ TST_EXP_EXPR(TST_RET == 0, "write(fd, NULL, %ld) == %d", TST_RET, 0);
}
static void setup(void)
diff --git a/testcases/kernel/syscalls/write/write04.c b/testcases/kernel/syscalls/write/write04.c
index afbac0f09..a5d62e0f5 100644
--- a/testcases/kernel/syscalls/write/write04.c
+++ b/testcases/kernel/syscalls/write/write04.c
@@ -28,7 +28,7 @@ static void verify_write(void)
{
char wbuf[8 * page_size];
- TST_EXP_FAIL(write(wfd, wbuf, sizeof(wbuf)), EAGAIN);
+ TST_EXP_FAIL2(write(wfd, wbuf, sizeof(wbuf)), EAGAIN);
}
static void setup(void)
diff --git a/testcases/kernel/syscalls/write/write05.c b/testcases/kernel/syscalls/write/write05.c
index 79769621c..b907624a8 100644
--- a/testcases/kernel/syscalls/write/write05.c
+++ b/testcases/kernel/syscalls/write/write05.c
@@ -1,19 +1,22 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
- *
- * Copyright (c) International Business Machines Corp., 2001
- * 07/2001 Ported by John George
- * 04/2002 wjhuie sigset cleanups
- * 08/2007 Ricardo Salveti de Araujo <rsalveti@linux.vnet.ibm.com>
+ * Copyright (c) International Business Machines Corp., 2001
+ * 07/2001 Ported by John George
+ * 04/2002 wjhuie sigset cleanups
+ * 08/2007 Ricardo Salveti de Araujo <rsalveti@linux.vnet.ibm.com>
+ * Copyright (c) Linux Test Project, 2002-2023
*/
-/*
- * DESCRIPTION
+/*\
+ * [Description]
+ *
* Check the return value, and errnos of write(2)
+ *
* - when the file descriptor is invalid - EBADF
* - when the buf parameter is invalid - EFAULT
* - on an attempt to write to a pipe that is not open for reading - EPIPE
*/
+
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
@@ -42,7 +45,7 @@ static struct tcase {
{&pipefd[1], &buf, sizeof(buf), EPIPE},
};
-static int sigpipe_cnt;
+static volatile int sigpipe_cnt;
static void sighandler(int sig)
{
@@ -56,26 +59,12 @@ static void verify_write(unsigned int i)
sigpipe_cnt = 0;
- TEST(write(*tc->fd, *tc->buf, tc->size));
-
- if (TST_RET != -1) {
- tst_res(TFAIL, "write() succeeded unexpectedly");
- return;
- }
-
- if (TST_ERR != tc->exp_errno) {
- tst_res(TFAIL | TTERRNO,
- "write() failed unexpectedly, expected %s",
- tst_strerrno(tc->exp_errno));
+ TST_EXP_FAIL2(write(*tc->fd, *tc->buf, tc->size), tc->exp_errno);
+ if (TST_RET != -1)
return;
- }
- if (tc->exp_errno == EPIPE && sigpipe_cnt != 1) {
+ if (tc->exp_errno == EPIPE && sigpipe_cnt != 1)
tst_res(TFAIL, "sigpipe_cnt = %i", sigpipe_cnt);
- return;
- }
-
- tst_res(TPASS | TTERRNO, "write() failed expectedly");
}
static void setup(void)