aboutsummaryrefslogtreecommitdiff
path: root/testcases
diff options
context:
space:
mode:
Diffstat (limited to 'testcases')
-rwxr-xr-xtestcases/commands/df/df01.sh7
-rwxr-xr-xtestcases/commands/eject/eject-tests.sh2
-rw-r--r--testcases/commands/file/datafiles/in.csh4
-rw-r--r--testcases/commands/file/datafiles/in.ksh4
-rwxr-xr-xtestcases/commands/file/file01.sh35
-rwxr-xr-xtestcases/commands/insmod/insmod01.sh3
-rw-r--r--testcases/cve/.gitignore1
-rw-r--r--testcases/cve/cve-2015-3290.c3
-rw-r--r--testcases/cve/cve-2016-10044.c6
-rw-r--r--testcases/cve/stack_clash.c89
-rw-r--r--testcases/cve/tcindex01.c136
-rwxr-xr-xtestcases/kernel/connectors/pec/cn_pec.sh4
-rw-r--r--testcases/kernel/connectors/pec/pec_listener.c4
-rw-r--r--testcases/kernel/containers/.gitignore14
-rw-r--r--testcases/kernel/containers/Makefile27
-rw-r--r--testcases/kernel/containers/Makefile.inc45
-rw-r--r--testcases/kernel/containers/README50
-rw-r--r--testcases/kernel/containers/TEST_PLAN.txt27
-rw-r--r--testcases/kernel/containers/libclone/Makefile27
-rw-r--r--testcases/kernel/containers/libclone/libclone.c142
-rw-r--r--testcases/kernel/containers/libclone/libclone.h81
-rw-r--r--testcases/kernel/containers/mountns/.gitignore4
-rw-r--r--testcases/kernel/containers/mountns/mountns.h18
-rw-r--r--testcases/kernel/containers/mountns/mountns01.c23
-rw-r--r--testcases/kernel/containers/mountns/mountns02.c23
-rw-r--r--testcases/kernel/containers/mountns/mountns03.c23
-rw-r--r--testcases/kernel/containers/mountns/mountns04.c6
-rw-r--r--testcases/kernel/containers/mqns/Makefile27
-rw-r--r--testcases/kernel/containers/mqns/mqns.h11
-rw-r--r--testcases/kernel/containers/mqns/mqns_01.c188
-rw-r--r--testcases/kernel/containers/mqns/mqns_02.c248
-rw-r--r--testcases/kernel/containers/mqns/mqns_03.c305
-rw-r--r--testcases/kernel/containers/mqns/mqns_04.c274
-rw-r--r--testcases/kernel/containers/mqns/mqns_helper.h53
-rw-r--r--testcases/kernel/containers/netns/Makefile4
-rwxr-xr-xtestcases/kernel/containers/netns/netns_lib.sh25
-rwxr-xr-xtestcases/kernel/containers/netns/netns_sysfs.sh18
-rw-r--r--testcases/kernel/containers/pidns/Makefile3
-rw-r--r--testcases/kernel/containers/pidns/pidns01.c31
-rw-r--r--testcases/kernel/containers/pidns/pidns02.c36
-rw-r--r--testcases/kernel/containers/pidns/pidns03.c21
-rw-r--r--testcases/kernel/containers/pidns/pidns04.c174
-rw-r--r--testcases/kernel/containers/pidns/pidns05.c298
-rw-r--r--testcases/kernel/containers/pidns/pidns06.c151
-rw-r--r--testcases/kernel/containers/pidns/pidns10.c133
-rw-r--r--testcases/kernel/containers/pidns/pidns12.c29
-rw-r--r--testcases/kernel/containers/pidns/pidns13.c9
-rw-r--r--testcases/kernel/containers/pidns/pidns16.c192
-rw-r--r--testcases/kernel/containers/pidns/pidns17.c190
-rw-r--r--testcases/kernel/containers/pidns/pidns20.c35
-rw-r--r--testcases/kernel/containers/pidns/pidns30.c325
-rw-r--r--testcases/kernel/containers/pidns/pidns31.c360
-rw-r--r--testcases/kernel/containers/pidns/pidns32.c54
-rw-r--r--testcases/kernel/containers/pidns/pidns_helper.h34
-rw-r--r--testcases/kernel/containers/share/.gitignore4
-rw-r--r--testcases/kernel/containers/share/Makefile22
-rw-r--r--testcases/kernel/containers/share/ns_create.c108
-rw-r--r--testcases/kernel/containers/share/ns_exec.c157
-rw-r--r--testcases/kernel/containers/share/ns_ifmove.c134
-rw-r--r--testcases/kernel/containers/share/setns_check.c32
-rw-r--r--testcases/kernel/containers/sysvipc/common.h50
-rw-r--r--testcases/kernel/containers/sysvipc/mesgq_nstest.c13
-rw-r--r--testcases/kernel/containers/sysvipc/msg_comm.c19
-rw-r--r--testcases/kernel/containers/sysvipc/sem_comm.c19
-rw-r--r--testcases/kernel/containers/sysvipc/sem_nstest.c12
-rw-r--r--testcases/kernel/containers/sysvipc/semtest_2ns.c15
-rw-r--r--testcases/kernel/containers/sysvipc/shm_comm.c19
-rw-r--r--testcases/kernel/containers/sysvipc/shmem_2nstest.c15
-rw-r--r--testcases/kernel/containers/sysvipc/shmnstest.c10
-rw-r--r--testcases/kernel/containers/userns/.gitignore9
-rw-r--r--testcases/kernel/containers/userns/Makefile23
-rw-r--r--testcases/kernel/containers/userns/common.h20
-rw-r--r--testcases/kernel/containers/userns/userns01.c32
-rw-r--r--testcases/kernel/containers/userns/userns02.c34
-rw-r--r--testcases/kernel/containers/userns/userns03.c73
-rw-r--r--testcases/kernel/containers/userns/userns04.c48
-rw-r--r--testcases/kernel/containers/userns/userns05.c51
-rw-r--r--testcases/kernel/containers/userns/userns06.c44
-rw-r--r--testcases/kernel/containers/userns/userns06_capcheck.c19
-rw-r--r--testcases/kernel/containers/userns/userns07.c63
-rw-r--r--testcases/kernel/containers/userns/userns08.c5
-rw-r--r--testcases/kernel/containers/userns/userns_helper.h59
-rw-r--r--testcases/kernel/containers/utsname/.gitignore5
-rw-r--r--testcases/kernel/containers/utsname/Makefile25
-rwxr-xr-xtestcases/kernel/containers/utsname/runutstests_noltp.sh41
-rw-r--r--testcases/kernel/containers/utsname/utsname01.c56
-rw-r--r--testcases/kernel/containers/utsname/utsname02.c81
-rw-r--r--testcases/kernel/containers/utsname/utsname03.c121
-rw-r--r--testcases/kernel/containers/utsname/utsname04.c63
-rw-r--r--testcases/kernel/containers/utsname/utstest.c353
-rw-r--r--testcases/kernel/controllers/cgroup/.gitignore1
-rw-r--r--testcases/kernel/controllers/cgroup/cgroup_core03.c131
-rwxr-xr-xtestcases/kernel/controllers/cgroup_fj/cgroup_fj_stress.sh4
-rwxr-xr-xtestcases/kernel/controllers/cpuctl/run_cpuctl_stress_test.sh6
-rwxr-xr-xtestcases/kernel/controllers/cpuctl/run_cpuctl_test.sh6
-rwxr-xr-xtestcases/kernel/controllers/cpuctl_fj/run_cpuctl_test_fj.sh2
-rwxr-xr-xtestcases/kernel/controllers/cpuset/cpuset_funcs.sh2
-rwxr-xr-xtestcases/kernel/controllers/cpuset/cpuset_memory_pressure_test/cpuset_memory_pressure_testset.sh6
-rwxr-xr-xtestcases/kernel/controllers/cpuset/cpuset_memory_spread_test/cpuset_memory_spread_testset.sh10
-rwxr-xr-xtestcases/kernel/controllers/cpuset/cpuset_memory_test/cpuset_memory_testset.sh2
-rwxr-xr-xtestcases/kernel/controllers/cpuset/cpuset_regression_test.sh9
-rw-r--r--testcases/kernel/controllers/freezer/00_description.txt2
-rwxr-xr-xtestcases/kernel/controllers/freezer/freeze_self_thaw.sh2
-rwxr-xr-xtestcases/kernel/controllers/freezer/vfork_freeze.sh2
-rw-r--r--testcases/kernel/controllers/io/io_control01.c1
-rwxr-xr-xtestcases/kernel/controllers/memcg/functional/memcg_failcnt.sh4
-rwxr-xr-xtestcases/kernel/controllers/memcg/functional/memcg_lib.sh4
-rwxr-xr-xtestcases/kernel/controllers/memcg/stress/memcg_stress_test.sh19
-rw-r--r--testcases/kernel/crypto/pcrypt_aead01.c4
-rw-r--r--testcases/kernel/device-drivers/nls/README2
-rwxr-xr-xtestcases/kernel/device-drivers/zram/zram01.sh27
-rw-r--r--testcases/kernel/fs/doio/write_log.c22
-rw-r--r--testcases/kernel/fs/fs_bind/fs_bind_lib.sh7
-rw-r--r--testcases/kernel/fs/fs_fill/fs_fill.c9
-rw-r--r--testcases/kernel/fs/fsstress/fsstress.c3
-rw-r--r--testcases/kernel/fs/fsstress/global.h9
-rw-r--r--testcases/kernel/fs/lftest/lftest.c2
-rw-r--r--testcases/kernel/fs/read_all/Makefile1
-rw-r--r--testcases/kernel/fs/scsi/ltpscsi/scsimain.c5
-rw-r--r--testcases/kernel/io/direct_io/diotest3.c2
-rw-r--r--testcases/kernel/io/direct_io/diotest4.c1
-rw-r--r--testcases/kernel/io/direct_io/diotest6.c2
-rw-r--r--testcases/kernel/io/ltp-aiodio/aiocp.c4
-rw-r--r--testcases/kernel/ipc/semaphore/.gitignore2
-rw-r--r--testcases/kernel/ipc/semaphore/Makefile30
-rw-r--r--testcases/kernel/ipc/semaphore/sem01.c164
-rw-r--r--testcases/kernel/kvm/.gitignore3
-rw-r--r--testcases/kernel/kvm/Makefile7
-rw-r--r--testcases/kernel/kvm/bootstrap_x86.S103
-rw-r--r--testcases/kernel/kvm/bootstrap_x86_64.S110
-rw-r--r--testcases/kernel/kvm/include/kvm_common.h8
-rw-r--r--testcases/kernel/kvm/include/kvm_guest.h14
-rw-r--r--testcases/kernel/kvm/include/kvm_host.h20
-rw-r--r--testcases/kernel/kvm/include/kvm_x86.h72
-rw-r--r--testcases/kernel/kvm/include/kvm_x86_svm.h166
-rw-r--r--testcases/kernel/kvm/kvm_svm01.c123
-rw-r--r--testcases/kernel/kvm/kvm_svm02.c152
-rw-r--r--testcases/kernel/kvm/kvm_svm03.c169
-rw-r--r--testcases/kernel/kvm/lib_guest.c18
-rw-r--r--testcases/kernel/kvm/lib_host.c55
-rw-r--r--testcases/kernel/kvm/lib_x86.c247
-rw-r--r--testcases/kernel/kvm/linker/x86.lds5
-rw-r--r--testcases/kernel/kvm/linker/x86_64.lds5
-rw-r--r--testcases/kernel/mem/.gitignore1
-rw-r--r--testcases/kernel/mem/hugetlb/hugemmap/Makefile1
-rw-r--r--testcases/kernel/mem/hugetlb/hugemmap/hugemmap15.c13
-rw-r--r--testcases/kernel/mem/hugetlb/hugemmap/hugemmap24.c9
-rw-r--r--testcases/kernel/mem/hugetlb/hugemmap/hugemmap32.c95
-rw-r--r--testcases/kernel/mem/hugetlb/hugeshmat/hugeshmat04.c19
-rw-r--r--testcases/kernel/mem/hugetlb/hugeshmctl/hugeshmctl01.c29
-rw-r--r--testcases/kernel/mem/hugetlb/hugeshmctl/hugeshmctl02.c37
-rw-r--r--testcases/kernel/mem/hugetlb/hugeshmctl/hugeshmctl03.c14
-rw-r--r--testcases/kernel/mem/hugetlb/hugeshmget/hugeshmget03.c2
-rw-r--r--testcases/kernel/mem/hugetlb/lib/hugetlb.h6
-rw-r--r--testcases/kernel/mem/include/mem.h1
-rw-r--r--testcases/kernel/mem/ksm/ksm05.c4
-rw-r--r--testcases/kernel/mem/lib/mem.c2
-rw-r--r--testcases/kernel/mem/oom/oom01.c17
-rw-r--r--testcases/kernel/mem/oom/oom02.c14
-rw-r--r--testcases/kernel/mem/oom/oom03.c14
-rw-r--r--testcases/kernel/mem/oom/oom04.c14
-rw-r--r--testcases/kernel/mem/oom/oom05.c14
-rw-r--r--testcases/kernel/mem/thp/thp03.c1
-rw-r--r--testcases/kernel/mem/thp/thp04.c2
-rw-r--r--testcases/kernel/mem/tunable/max_map_count.c27
-rw-r--r--testcases/kernel/mem/tunable/min_free_kbytes.c16
-rw-r--r--testcases/kernel/mem/tunable/overcommit_memory.c20
-rwxr-xr-xtestcases/kernel/mem/vma/vma05.sh1
-rwxr-xr-xtestcases/kernel/numa/numa01.sh2
-rw-r--r--testcases/kernel/numa/support_numa.c1
-rw-r--r--testcases/kernel/sched/cfs-scheduler/.gitignore3
-rw-r--r--testcases/kernel/sched/cfs-scheduler/cfs_bandwidth01.c10
-rw-r--r--testcases/kernel/sched/cfs-scheduler/starvation.c113
-rw-r--r--testcases/kernel/security/dirtyc0w_shmem/dirtyc0w_shmem_child.c2
-rw-r--r--testcases/kernel/security/tomoyo/.gitignore9
-rw-r--r--testcases/kernel/security/tomoyo/Makefile29
-rw-r--r--testcases/kernel/security/tomoyo/README58
-rw-r--r--testcases/kernel/security/tomoyo/include.h379
-rw-r--r--testcases/kernel/security/tomoyo/newns.c49
-rw-r--r--testcases/kernel/security/tomoyo/testall.sh46
-rw-r--r--testcases/kernel/security/tomoyo/tomoyo_accept_test.c146
-rw-r--r--testcases/kernel/security/tomoyo/tomoyo_file_test.c304
-rw-r--r--testcases/kernel/security/tomoyo/tomoyo_filesystem_test.c633
-rw-r--r--testcases/kernel/security/tomoyo/tomoyo_new_file_test.c627
-rw-r--r--testcases/kernel/security/tomoyo/tomoyo_new_test.c652
-rw-r--r--testcases/kernel/security/tomoyo/tomoyo_policy_io_test.c195
-rw-r--r--testcases/kernel/security/tomoyo/tomoyo_policy_memory_test.c358
-rw-r--r--testcases/kernel/security/tomoyo/tomoyo_rewrite_test.c169
-rw-r--r--testcases/kernel/sound/snd_timer01.c2
-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.c (renamed from testcases/kernel/ipc/semaphore/sem02.c)0
-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
-rw-r--r--testcases/lib/.gitignore8
-rw-r--r--testcases/lib/Makefile3
-rw-r--r--testcases/lib/tst_fsfreeze.c38
-rw-r--r--testcases/lib/tst_get_free_pids.c2
-rw-r--r--testcases/lib/tst_kvcmp.c2
-rw-r--r--testcases/lib/tst_lockdown_enabled.c12
-rw-r--r--testcases/lib/tst_net.sh228
-rw-r--r--testcases/lib/tst_ns_common.h (renamed from testcases/kernel/containers/share/ns_common.h)6
-rw-r--r--testcases/lib/tst_ns_create.c92
-rw-r--r--testcases/lib/tst_ns_exec.c115
-rw-r--r--testcases/lib/tst_ns_ifmove.c92
-rw-r--r--testcases/lib/tst_secureboot_enabled.c12
-rw-r--r--testcases/lib/tst_test.sh14
-rwxr-xr-xtestcases/network/iptables/iptables_lib.sh8
-rw-r--r--testcases/network/lib6/asapi_01.c2
-rw-r--r--testcases/network/lib6/asapi_02.c336
-rw-r--r--testcases/network/lib6/asapi_03.c2
-rw-r--r--testcases/network/netstress/netstress.c1
-rw-r--r--testcases/network/nfs/nfs_stress/Makefile9
-rwxr-xr-xtestcases/network/nfs/nfs_stress/nfs03.sh2
-rwxr-xr-xtestcases/network/nfs/nfs_stress/nfs05.sh6
-rwxr-xr-xtestcases/network/nfs/nfs_stress/nfs06.sh5
-rwxr-xr-xtestcases/network/nfs/nfs_stress/nfs08.sh23
-rw-r--r--testcases/network/nfs/nfs_stress/nfs_lib.sh80
-rw-r--r--testcases/network/nfs/nfslock01/nfs_flock.c72
-rw-r--r--testcases/network/nfs/nfslock01/nfs_flock.h6
-rw-r--r--testcases/network/nfs/nfslock01/nfs_flock_dgen.c39
-rw-r--r--testcases/network/nfs/nfslock01/nfs_flock_func.c6
-rwxr-xr-xtestcases/network/nfs/nfslock01/nfslock01.sh45
-rw-r--r--testcases/network/rpc/rpc-tirpc/tests_pack/rpc_suite/rpc/rpc_broadc_clnt_broadcast/rpc_clnt_broadcast.c3
-rw-r--r--testcases/network/rpc/rpc-tirpc/tests_pack/rpc_suite/rpc/rpc_broadc_clnt_broadcast/rpc_clnt_broadcast_complex.c3
-rw-r--r--testcases/network/rpc/rpc-tirpc/tests_pack/rpc_suite/rpc/rpc_broadc_clnt_broadcast/rpc_clnt_broadcast_dataint.c15
-rw-r--r--testcases/network/rpc/rpc-tirpc/tests_pack/rpc_suite/rpc/rpc_broadc_clnt_broadcast/rpc_clnt_broadcast_performance.c2
-rw-r--r--testcases/network/rpc/rpc-tirpc/tests_pack/rpc_suite/rpc/rpc_broadc_clnt_broadcast/rpc_clnt_broadcast_scalability.c2
-rw-r--r--testcases/network/rpc/rpc-tirpc/tests_pack/rpc_suite/rpc/rpc_broadc_clnt_broadcast/rpc_clnt_broadcast_stress.c2
-rw-r--r--testcases/network/rpc/rpc-tirpc/tests_pack/rpc_suite/rpc/rpc_regunreg_registerrpc/rpc_registerrpc.c5
-rw-r--r--testcases/network/sctp/sctp_big_chunk.c35
-rw-r--r--testcases/network/sockets/vsock01.c3
-rw-r--r--testcases/network/stress/udp/multi-diffip/udp4-multi-diffip012
-rwxr-xr-xtestcases/network/tcp_cmds/ipneigh/ipneigh01.sh2
-rw-r--r--testcases/open_posix_testsuite/conformance/interfaces/aio_read/8-1.c2
-rw-r--r--testcases/open_posix_testsuite/conformance/interfaces/aio_read/assertions.xml8
-rw-r--r--testcases/open_posix_testsuite/conformance/interfaces/aio_write/6-1.c3
-rw-r--r--testcases/open_posix_testsuite/conformance/interfaces/aio_write/assertions.xml8
-rw-r--r--testcases/open_posix_testsuite/conformance/interfaces/fork/assertions.xml2
-rw-r--r--testcases/open_posix_testsuite/conformance/interfaces/lio_listio/13-1.c2
-rw-r--r--testcases/open_posix_testsuite/conformance/interfaces/lio_listio/assertions.xml2
-rw-r--r--testcases/open_posix_testsuite/conformance/interfaces/mmap/6-5.c2
-rw-r--r--testcases/open_posix_testsuite/conformance/interfaces/pthread_attr_getinheritsched/assertions.xml2
-rw-r--r--testcases/open_posix_testsuite/conformance/interfaces/pthread_attr_getscope/assertions.xml2
-rw-r--r--testcases/open_posix_testsuite/conformance/interfaces/pthread_cond_destroy/3-1.c3
-rw-r--r--testcases/open_posix_testsuite/conformance/interfaces/pthread_cond_init/3-1.c3
-rw-r--r--testcases/open_posix_testsuite/conformance/interfaces/pthread_detach/3-1.c4
-rw-r--r--testcases/open_posix_testsuite/conformance/interfaces/pthread_mutex_destroy/3-1.c3
-rw-r--r--testcases/open_posix_testsuite/conformance/interfaces/pthread_mutex_init/4-1.c3
-rw-r--r--testcases/open_posix_testsuite/conformance/interfaces/pthread_mutex_lock/2-1.c3
-rw-r--r--testcases/open_posix_testsuite/conformance/interfaces/pthread_mutex_trylock/3-1.c3
-rw-r--r--testcases/open_posix_testsuite/conformance/interfaces/pthread_mutex_unlock/3-1.c3
-rw-r--r--testcases/open_posix_testsuite/conformance/interfaces/pthread_sigmask/5-1.c2
-rw-r--r--testcases/open_posix_testsuite/conformance/interfaces/raise/2-1.c2
-rw-r--r--testcases/open_posix_testsuite/conformance/interfaces/sched_setparam/2-1.c4
-rw-r--r--testcases/open_posix_testsuite/conformance/interfaces/sched_setparam/2-2.c3
-rw-r--r--testcases/open_posix_testsuite/conformance/interfaces/sigqueue/assertions.xml2
-rw-r--r--testcases/realtime/func/matrix_mult/matrix_mult.c2
-rw-r--r--testcases/realtime/tools/ftqviz.py2
494 files changed, 10546 insertions, 16610 deletions
diff --git a/testcases/commands/df/df01.sh b/testcases/commands/df/df01.sh
index ae0449c3c..5af4f68e6 100755
--- a/testcases/commands/df/df01.sh
+++ b/testcases/commands/df/df01.sh
@@ -1,7 +1,7 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (c) 2015 Fujitsu Ltd.
-# Copyright (c) 2018-2022 Petr Vorel <pvorel@suse.cz>
+# Copyright (c) 2018-2023 Petr Vorel <pvorel@suse.cz>
# Author: Zhang Jin <jy_zhangjin@cn.fujitsu.com>
#
# Test df command with some basic options.
@@ -46,6 +46,11 @@ df_test()
ROD_SILENT rm -rf $TST_MNTPOINT/testimg
+ # force all the background garbage collection to run to completion
+ if [ "$TST_FS_TYPE" = "xfs" ]; then
+ tst_fsfreeze $TST_MNTPOINT
+ fi
+
# flush file system buffers, then we can get the actual sizes.
sync
}
diff --git a/testcases/commands/eject/eject-tests.sh b/testcases/commands/eject/eject-tests.sh
index 7b916cfb6..76a667aa3 100755
--- a/testcases/commands/eject/eject-tests.sh
+++ b/testcases/commands/eject/eject-tests.sh
@@ -99,7 +99,7 @@ test3()
if grep -q "$CD_DRIVE" /proc/mounts; then
tst_res TFAIL "$CD_DRIVE is stil moutned"
else
- tst_res TPASS "$CD_DRIVE umounted succesfully"
+ tst_res TPASS "$CD_DRIVE umounted successfully"
fi
}
diff --git a/testcases/commands/file/datafiles/in.csh b/testcases/commands/file/datafiles/in.csh
deleted file mode 100644
index c475aef9c..000000000
--- a/testcases/commands/file/datafiles/in.csh
+++ /dev/null
@@ -1,4 +0,0 @@
-#! /bin/csh
-
-echo "this is a shell script"
-echo "used to test file command"
diff --git a/testcases/commands/file/datafiles/in.ksh b/testcases/commands/file/datafiles/in.ksh
deleted file mode 100644
index 3ae45125c..000000000
--- a/testcases/commands/file/datafiles/in.ksh
+++ /dev/null
@@ -1,4 +0,0 @@
-#! /bin/ksh
-
-echo "this is a shell script"
-echo "used to test file command"
diff --git a/testcases/commands/file/file01.sh b/testcases/commands/file/file01.sh
index df152b656..f0c129f33 100755
--- a/testcases/commands/file/file01.sh
+++ b/testcases/commands/file/file01.sh
@@ -2,12 +2,13 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (c) International Business Machines Corp., 2001
# Copyright (c) 2016 Cyril Hrubis <chrubis@suse.cz>
+# Copyright (c) Linux Test Project, 2017-2023
#
# This program tests the file command. The tests are aimed at
# testing if the file command can recognize some of the commonly
# used file formats like, tar, tar.gz, rpm, C, ASCII, ELF etc.
-TST_CNT=20
+TST_CNT=18
TST_SETUP=setup
TST_TESTFUNC=do_test
TST_NEEDS_TMPDIR=1
@@ -61,30 +62,28 @@ do_test()
"POSIX shell script text executable" \
"POSIX shell script text" \
"Bourne shell script text executable";;
- 4) file_test in.ksh "Korn shell script";;
- 5) file_test in.csh "C shell script";;
- 6) file_test in.c "ASCII C program text" "C source, ASCII text";;
- 7) file_test in.pl "[pP]erl script, ASCII text executable" \
+ 4) file_test in.c "ASCII C program text" "C source, ASCII text";;
+ 5) file_test in.pl "[pP]erl script, ASCII text executable" \
"[pP]erl script text executable" \
"a /usr/bin/perl script text";;
- 8) file_test in.py "[pP]ython3\{0,1\} script, ASCII text executable" \
+ 6) file_test in.py "[pP]ython3\{0,1\} script, ASCII text executable" \
"[pP]ython3\{0,1\} script text executable";;
- 9) file_test in.m4 "M4 macro processor script, ASCII text" \
+ 7) file_test in.m4 "M4 macro processor script, ASCII text" \
"ASCII M4 macro language pre-processor text";;
- 10) file_test in "ELF .*-bit $TEST_ARCH executable, .*" \
+ 8) file_test in "ELF .*-bit $TEST_ARCH executable, .*" \
"ELF .*-bit $TEST_ARCH shared object, .*" \
"ELF .*-bit $TEST_ARCH pie executable, .*" \
"ELF .*-bit $TEST_ARCH pie shared object, .*";;
- 11) file_test in.ar "current ar archive";;
- 12) file_test in.tar "tar archive";;
- 13) file_test in.tar.gz "gzip compressed data, .*";;
- 14) file_test in.tar.bz2 "bzip2 compressed data, .*";;
- 15) file_test in.src.rpm "RPM v3 src" "RPM v3.0 src";;
- 16) file_test in.jpg "JPEG image data";;
- 17) file_test in.png "PNG image data";;
- 18) file_test in.wav "RIFF (little-endian) data, WAVE audio, Microsoft PCM";;
- 19) file_test in.mp3 "MPEG ADTS, layer III";;
- 20) file_test in.zip "Zip archive data";;
+ 9) file_test in.ar "current ar archive";;
+ 10) file_test in.tar "tar archive";;
+ 11) file_test in.tar.gz "gzip compressed data, .*";;
+ 12) file_test in.tar.bz2 "bzip2 compressed data, .*";;
+ 13) file_test in.src.rpm "RPM v3 src" "RPM v3.0 src";;
+ 14) file_test in.jpg "JPEG image data";;
+ 15) file_test in.png "PNG image data";;
+ 16) file_test in.wav "RIFF (little-endian) data, WAVE audio, Microsoft PCM";;
+ 17) file_test in.mp3 "MPEG ADTS, layer III";;
+ 18) file_test in.zip "Zip archive data";;
esac
}
diff --git a/testcases/commands/insmod/insmod01.sh b/testcases/commands/insmod/insmod01.sh
index 1881ba389..992b4a05a 100755
--- a/testcases/commands/insmod/insmod01.sh
+++ b/testcases/commands/insmod/insmod01.sh
@@ -1,6 +1,7 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (c) 2016 Fujitsu Ltd.
+# Copyright (c) Linux Test Project, 2016-2023
# Author: Guangwen Feng <fenggw-fnst@cn.fujitsu.com>
#
# Test basic functionality of insmod command.
@@ -10,6 +11,8 @@ TST_TESTFUNC=do_test
TST_NEEDS_ROOT=1
TST_NEEDS_CMDS="rmmod insmod"
TST_NEEDS_MODULE="ltp_insmod01.ko"
+TST_SKIP_IN_LOCKDOWN=1
+TST_SKIP_IN_SECUREBOOT=1
inserted=0
diff --git a/testcases/cve/.gitignore b/testcases/cve/.gitignore
index 90e8b191c..3a2b2bed6 100644
--- a/testcases/cve/.gitignore
+++ b/testcases/cve/.gitignore
@@ -12,3 +12,4 @@ cve-2017-16939
cve-2017-17053
cve-2022-4378
icmp_rate_limit01
+tcindex01
diff --git a/testcases/cve/cve-2015-3290.c b/testcases/cve/cve-2015-3290.c
index f61d2809b..a2a8fcedd 100644
--- a/testcases/cve/cve-2015-3290.c
+++ b/testcases/cve/cve-2015-3290.c
@@ -195,7 +195,8 @@ static void set_ldt(void)
.useable = 0
};
- TEST(tst_syscall(__NR_modify_ldt, 1, &data_desc, sizeof(data_desc)));
+ TEST((int)tst_syscall(__NR_modify_ldt, 1, &data_desc,
+ sizeof(data_desc)));
if (TST_RET == -EINVAL) {
tst_brk(TCONF | TRERRNO,
"modify_ldt: 16-bit data segments are probably disabled");
diff --git a/testcases/cve/cve-2016-10044.c b/testcases/cve/cve-2016-10044.c
index 9ac644fc2..6a8c77f3e 100644
--- a/testcases/cve/cve-2016-10044.c
+++ b/testcases/cve/cve-2016-10044.c
@@ -19,7 +19,7 @@
#include "tst_safe_stdio.h"
#include "lapi/syscalls.h"
-static FILE *f;
+static FILE * f;
static void cleanup(void)
{
@@ -29,7 +29,7 @@ static void cleanup(void)
static void run(void)
{
- void* ctx = 0;
+ void *ctx = 0;
char perms[8], line[BUFSIZ];
SAFE_PERSONALITY(READ_IMPLIES_EXEC);
@@ -44,7 +44,7 @@ static void run(void)
tst_brk(TCONF, "Could not find mapping in /proc/self/maps");
found_mapping:
- if (sscanf(line, "%*x-%*x %s7", perms) < 0)
+ if (sscanf(line, "%*x-%*x %s", perms) != 1)
tst_brk(TBROK, "failed to find permission string in %s", line);
if (strchr(perms, (int)'x'))
tst_res(TFAIL, "AIO mapping is executable: %s!", perms);
diff --git a/testcases/cve/stack_clash.c b/testcases/cve/stack_clash.c
index cd7f148c2..3a99c49bb 100644
--- a/testcases/cve/stack_clash.c
+++ b/testcases/cve/stack_clash.c
@@ -1,9 +1,14 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2017 Pavel Boldin <pboldin@cloudlinux.com>
+ * Copyright (c) 2023 Rick Edgecombe <rick.p.edgecombe@intel.com>
+ * Copyright (c) Linux Test Project, 2017-2023
*/
-/* This is a regression test of the Stack Clash [1] vulnerability. This tests
+/*\
+ * [Description]
+ *
+ * This is a regression test of the Stack Clash [1] vulnerability. This tests
* that there is at least 256 PAGE_SIZE of stack guard gap which is considered
* hard to hop above. Code adapted from the Novell's bugzilla [2].
*
@@ -18,11 +23,19 @@
* to infinity and preallocate REQ_STACK_SIZE bytes of stack so that no calls
* after `mmap` are moving stack further.
*
+ * If the architecture meets certain requirements (only x86_64 is verified)
+ * then the test also tests that new mmap()s can't be placed in the stack's
+ * guard gap. This part of the test works by forcing a bottom up search. The
+ * assumptions are that the stack grows down (start gap) and either:
+ *
+ * 1. The default search is top down, and will switch to bottom up if
+ * space is exhausted.
+ * 2. The default search is bottom up and the stack is above mmap base.
+ *
* [1] https://blog.qualys.com/securitylabs/2017/06/19/the-stack-clash
* [2] https://bugzilla.novell.com/show_bug.cgi?id=CVE-2017-1000364
*/
-#include <sys/mman.h>
#include <sys/wait.h>
#include <stdio.h>
#include <unistd.h>
@@ -32,6 +45,7 @@
#include "tst_test.h"
#include "tst_safe_stdio.h"
+#include "lapi/mmap.h"
static unsigned long page_size;
static unsigned long page_mask;
@@ -78,6 +92,49 @@ void segv_handler(int sig, siginfo_t *info, void *data LTP_ATTRIBUTE_UNUSED)
_exit(EXIT_SUCCESS);
}
+static void force_bottom_up(void)
+{
+ FILE *fh;
+ char buf[1024];
+ unsigned long start, end, size, lastend = 0;
+
+ /* start filling from mmap_min_addr */
+ SAFE_FILE_SCANF("/proc/sys/vm/mmap_min_addr", "%lu", &lastend);
+
+ fh = SAFE_FOPEN("/proc/self/maps", "r");
+
+ while (!feof(fh)) {
+ if (fgets(buf, sizeof(buf), fh) == NULL)
+ goto out;
+
+ if (sscanf(buf, "%lx-%lx", &start, &end) != 2) {
+ tst_brk(TBROK | TERRNO, "sscanf");
+ goto out;
+ }
+
+ size = start - lastend;
+
+ /* Skip the PROT_NONE that was just added (!size). */
+ if (!size) {
+ lastend = end;
+ continue;
+ }
+
+ /* If the next area is the stack, quit. */
+ if (!!strstr(buf, "[stack]"))
+ break;
+
+ /* This is not cleaned up. */
+ SAFE_MMAP((void *)lastend, size, PROT_NONE,
+ MAP_ANON|MAP_PRIVATE|MAP_FIXED_NOREPLACE, -1, 0);
+
+ lastend = end;
+ }
+
+out:
+ SAFE_FCLOSE(fh);
+}
+
unsigned long read_stack_addr_from_proc(unsigned long *stack_size)
{
FILE *fh;
@@ -130,6 +187,28 @@ void __attribute__((noinline)) preallocate_stack(unsigned long required)
garbage[0] = garbage[required - 1] = '\0';
}
+static void do_mmap_placement_test(unsigned long stack_addr, unsigned long gap)
+{
+ void *map_test_gap;
+
+ force_bottom_up();
+
+ /*
+ * force_bottom_up() used up all the spaces below the stack. The search down
+ * path should fail, and search up might take a look at the guard gap
+ * region. If it avoids it, the allocation will be above the stack. If it
+ * uses it, the allocation will be in the gap and the test should fail.
+ */
+ map_test_gap = SAFE_MMAP(0, MAPPED_LEN,
+ PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, 0, 0);
+
+ if (stack_addr - gap <= (unsigned long)map_test_gap &&
+ (unsigned long)map_test_gap <= stack_addr) {
+ tst_res(TFAIL, "New mmap was placed in the guard gap.");
+ SAFE_MUNMAP(map_test_gap, MAPPED_LEN);
+ }
+}
+
void do_child(void)
{
unsigned long stack_addr, stack_size;
@@ -179,6 +258,11 @@ void do_child(void)
dump_proc_self_maps();
#endif
+#ifdef __x86_64__
+ do_mmap_placement_test(stack_addr, gap);
+#endif
+
+ /* Now see if it can grow too close to an adjacent region. */
exhaust_stack_into_sigsegv();
}
@@ -252,6 +336,7 @@ static struct tst_test test = {
.test_all = stack_clash_test,
.tags = (const struct tst_tag[]) {
{"CVE", "2017-1000364"},
+ {"linux-git", "58c5d0d6d522"},
{}
}
};
diff --git a/testcases/cve/tcindex01.c b/testcases/cve/tcindex01.c
new file mode 100644
index 000000000..91bfafb53
--- /dev/null
+++ b/testcases/cve/tcindex01.c
@@ -0,0 +1,136 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2023 SUSE LLC
+ * Author: Marcos Paulo de Souza <mpdesouza@suse.com>
+ * LTP port: Martin Doucha <mdoucha@suse.cz>
+ */
+
+/*\
+ * CVE-2023-1829
+ *
+ * Test for use-after-free after removing tcindex traffic filter with certain
+ * parameters.
+ *
+ * Tcindex filter removed in:
+ *
+ * commit 8c710f75256bb3cf05ac7b1672c82b92c43f3d28
+ * Author: Jamal Hadi Salim <jhs@mojatatu.com>
+ * Date: Tue Feb 14 08:49:14 2023 -0500
+ *
+ * net/sched: Retire tcindex classifier
+ */
+
+#include <linux/netlink.h>
+#include <linux/pkt_sched.h>
+#include <linux/pkt_cls.h>
+#include "tst_test.h"
+#include "tst_rtnetlink.h"
+#include "tst_netdevice.h"
+#include "lapi/sched.h"
+#include "lapi/if_ether.h"
+#include "lapi/rtnetlink.h"
+
+#define DEVNAME "ltp_dummy1"
+
+static const uint32_t qd_handle = TC_H_MAKE(1 << 16, 0);
+static const uint32_t clsid = TC_H_MAKE(1 << 16, 1);
+static const uint32_t shift = 10;
+static const uint16_t mask = 0xffff;
+
+/* rtnetlink payloads */
+static const struct tc_htb_glob qd_opt = {
+ .rate2quantum = 10,
+ .version = 3,
+ .defcls = 30
+};
+static struct tc_htb_opt cls_opt = {};
+
+/* htb qdisc and class options */
+static const struct tst_rtnl_attr_list qd_config[] = {
+ {TCA_OPTIONS, NULL, 0, (const struct tst_rtnl_attr_list[]){
+ {TCA_HTB_INIT, &qd_opt, sizeof(qd_opt), NULL},
+ {0, NULL, -1, NULL}
+ }},
+ {0, NULL, -1, NULL}
+};
+static const struct tst_rtnl_attr_list cls_config[] = {
+ {TCA_OPTIONS, NULL, 0, (const struct tst_rtnl_attr_list[]){
+ {TCA_HTB_PARMS, &cls_opt, sizeof(cls_opt), NULL},
+ {0, NULL, -1, NULL}
+ }},
+ {0, NULL, -1, NULL}
+};
+
+/* tcindex filter options */
+static const struct tst_rtnl_attr_list f_config[] = {
+ {TCA_OPTIONS, NULL, 0, (const struct tst_rtnl_attr_list[]){
+ {TCA_TCINDEX_MASK, &mask, sizeof(mask), NULL},
+ {TCA_TCINDEX_SHIFT, &shift, sizeof(shift), NULL},
+ {TCA_TCINDEX_CLASSID, &clsid, sizeof(clsid), NULL},
+ {0, NULL, -1, NULL}
+ }},
+ {0, NULL, -1, NULL}
+};
+
+static void setup(void)
+{
+ tst_setup_netns();
+ NETDEV_ADD_DEVICE(DEVNAME, "dummy");
+
+ cls_opt.rate.rate = cls_opt.ceil.rate = 256000;
+ cls_opt.buffer = 1000000 * 1600 / cls_opt.rate.rate;
+ cls_opt.cbuffer = 1000000 * 1600 / cls_opt.ceil.rate;
+}
+
+static void run(void)
+{
+ int ret;
+
+ NETDEV_ADD_QDISC(DEVNAME, AF_UNSPEC, TC_H_ROOT, qd_handle, "htb",
+ qd_config);
+ NETDEV_ADD_TRAFFIC_CLASS(DEVNAME, qd_handle, clsid, "htb", cls_config);
+ NETDEV_ADD_TRAFFIC_FILTER(DEVNAME, qd_handle, 10, ETH_P_IP, 1,
+ "tcindex", f_config);
+ NETDEV_REMOVE_TRAFFIC_FILTER(DEVNAME, qd_handle, 10, ETH_P_IP,
+ 1, "tcindex");
+ ret = tst_netdev_add_traffic_filter(__FILE__, __LINE__, 0, DEVNAME,
+ qd_handle, 10, ETH_P_IP, 1, "tcindex", f_config);
+ TST_ERR = tst_rtnl_errno;
+ NETDEV_REMOVE_QDISC(DEVNAME, AF_UNSPEC, TC_H_ROOT, qd_handle, "htb");
+
+ if (ret)
+ tst_res(TPASS, "Removing tcindex filter works correctly");
+ else if (TST_ERR == EEXIST)
+ tst_res(TFAIL, "Kernel traffic filter list is corrupted");
+ else
+ tst_brk(TBROK | TTERRNO, "Unexpected rtnetlink error");
+}
+
+static void cleanup(void)
+{
+ NETDEV_REMOVE_DEVICE(DEVNAME);
+}
+
+static struct tst_test test = {
+ .test_all = run,
+ .setup = setup,
+ .cleanup = cleanup,
+ .taint_check = TST_TAINT_W | TST_TAINT_D,
+ .needs_kconfigs = (const char *[]) {
+ "CONFIG_VETH",
+ "CONFIG_USER_NS=y",
+ "CONFIG_NET_NS=y",
+ "CONFIG_NET_SCH_HTB",
+ "CONFIG_NET_CLS_TCINDEX",
+ NULL
+ },
+ .save_restore = (const struct tst_path_val[]) {
+ {"/proc/sys/user/max_user_namespaces", "1024", TST_SR_SKIP},
+ {}
+ },
+ .tags = (const struct tst_tag[]) {
+ {"linux-git", "8c710f75256b"},
+ {"CVE", "2023-1829"},
+ {}
+ }
+};
diff --git a/testcases/kernel/connectors/pec/cn_pec.sh b/testcases/kernel/connectors/pec/cn_pec.sh
index 082e30102..dce7f210b 100755
--- a/testcases/kernel/connectors/pec/cn_pec.sh
+++ b/testcases/kernel/connectors/pec/cn_pec.sh
@@ -11,7 +11,7 @@
TST_OPTS="n:"
TST_SETUP=setup
-TST_TESTFUNC=test
+TST_TESTFUNC=do_test
TST_PARSE_ARGS=parse_args
TST_USAGE=usage
TST_NEEDS_ROOT=1
@@ -66,7 +66,7 @@ setup()
tst_res TINFO "Test process events connector"
}
-test()
+do_test()
{
local event=$2
local gen_pid list_pid gen_rc lis_rc
diff --git a/testcases/kernel/connectors/pec/pec_listener.c b/testcases/kernel/connectors/pec/pec_listener.c
index 21ae53e87..01ee91d43 100644
--- a/testcases/kernel/connectors/pec/pec_listener.c
+++ b/testcases/kernel/connectors/pec/pec_listener.c
@@ -19,9 +19,9 @@
#include <signal.h>
#include <linux/types.h>
#include <linux/netlink.h>
-#include <tst_checkpoint.h>
#define TST_NO_DEFAULT_MAIN
-#include <tst_test.h>
+#include "tst_test.h"
+#include "tst_checkpoint.h"
#ifndef NETLINK_CONNECTOR
diff --git a/testcases/kernel/containers/.gitignore b/testcases/kernel/containers/.gitignore
deleted file mode 100644
index 5c2b90312..000000000
--- a/testcases/kernel/containers/.gitignore
+++ /dev/null
@@ -1,14 +0,0 @@
-/check_for_unshare
-mountns/mountns01
-mountns/mountns02
-mountns/mountns03
-mountns/mountns04
-userns/userns01
-userns/userns02
-userns/userns03
-userns/userns04
-userns/userns05
-userns/userns06_capcheck
-userns/userns06
-userns/userns07
-userns/userns08
diff --git a/testcases/kernel/containers/Makefile b/testcases/kernel/containers/Makefile
index 4285546e7..20d2424a5 100644
--- a/testcases/kernel/containers/Makefile
+++ b/testcases/kernel/containers/Makefile
@@ -1,33 +1,8 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (c) International Business Machines Corp., 2007
+# Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
top_srcdir ?= ../../..
include $(top_srcdir)/include/mk/env_pre.mk
-
-LIBDIR := libclone
-
-FILTER_OUT_DIRS := $(LIBDIR)
-
-LIB := $(LIBDIR)/libclone.a
-
-LDLIBS := -ldl -lltp
-
-INSTALL_TARGETS := *.sh
-
-$(LIBDIR):
- mkdir -p "$@"
-
-# Make the target the real lib so we don't have to deal with rebuilding this
-# every time the dependency is evaluated, like with PHONY rules.
-$(LIB): $(LIBDIR)
- $(MAKE) -C $^ -f "$(abs_srcdir)/$(LIBDIR)/Makefile" all
-
-MAKE_DEPS := $(LIB)
-
-trunk-clean:: | lib-clean
-
-lib-clean:: $(LIBDIR)
- $(MAKE) -C $^ -f "$(abs_srcdir)/$(LIBDIR)/Makefile" clean
-
include $(top_srcdir)/include/mk/generic_trunk_target.mk
diff --git a/testcases/kernel/containers/Makefile.inc b/testcases/kernel/containers/Makefile.inc
deleted file mode 100644
index 179809bc1..000000000
--- a/testcases/kernel/containers/Makefile.inc
+++ /dev/null
@@ -1,45 +0,0 @@
-#
-# kernel/containers testcase suite common definitions Makefile.
-#
-# Copyright (C) 2009, Cisco Systems Inc.
-#
-# 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.
-#
-# Ngie Cooper, July 2009
-#
-
-# DO NOT USE THIS FILE FOR containers / libclone!!!
-
-LIBDIR := ../libclone
-
-LIBS := $(LIBDIR)/libclone.a
-
-CPPFLAGS += -I$(abs_srcdir)/$(LIBDIR)
-
-LDFLAGS += -L$(abs_builddir)/$(LIBDIR)
-
-$(LIBDIR):
- mkdir -p "$@"
-
-# Make the target the real lib so we don't have to deal with rebuilding this
-# every time the dependency is evaluated, like with PHONY rules.
-$(LIBS): $(LIBDIR)
- $(MAKE) -C $^ -f "$(abs_srcdir)/$^/Makefile" all
-
-INSTALL_TARGETS ?= *.sh
-
-MAKE_DEPS := $(LIBS)
-
-# vim: syntax=make
diff --git a/testcases/kernel/containers/README b/testcases/kernel/containers/README
deleted file mode 100644
index c99cacd98..000000000
--- a/testcases/kernel/containers/README
+++ /dev/null
@@ -1,50 +0,0 @@
-################################################################################
-## ##
-## Copyright (c) International Business Machines Corp., 2007 ##
-## ##
-## 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 ##
-## ##
-################################################################################
-
-CONTAINER TESTS AUTOMATION SUITE
-----------------------------
-The tests requires the Kernel to be compiled with the following configs
-
-CONFIG_DUMMY=y(or =m)
-CONFIG_NAMESPACES=y
-CONFIG_UTS_NS=y
-CONFIG_IPC_NS=y
-CONFIG_USER_NS=y
-CONFIG_PID_NS=y
-CONFIG_NET_NS=y
-CONFIG_VETH=y(or =m)
-CONFIG_MACVLAN=y(optional)
-
-The container test automation suite helps run the container functionality
-(e.g: utsname etc..) tests and report results. Please refer the following
-each functionality README file for detail:
-
-sysvipc/*
- Contains all the testcases related to IPC NS tests.
-posixmq/*
- Contains all the testcases related to POSIX MQ NS tests. These
- are strictly speaking a part of the ipc namespaces, but can be
- enabled in the kernel without SYSV IPC support.
-utsname/*
- Contains all the testcases related to utsname tests.
-libclone/*
- Contains the library API for clone() .
-netns/*
- Contains the testcases related to the network NS tests.
diff --git a/testcases/kernel/containers/TEST_PLAN.txt b/testcases/kernel/containers/TEST_PLAN.txt
deleted file mode 100644
index 809abaecb..000000000
--- a/testcases/kernel/containers/TEST_PLAN.txt
+++ /dev/null
@@ -1,27 +0,0 @@
-################################################################################
-## Copyright (c) International Business Machines Corp., 2007
-##
-## 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
-################################################################################
-
-Following are tentative Testcases to be included into LTP-Containers in future:
-
-NAME TENTATIVE-TIME
-=================================================================================
-PID NAMESPACES (NEAR FUTURE)
-NETWORK NAMESPACES (NEAR FUTURE)
-POSIX IPC NAMESPACES (NEAR FUTURE)
-TTY+CONSOLE+DEVPTS NAMESPACES (NEAR FUTURE)
-PROC+SYSFS ISOLATION (NEAR FUTURE)
-PER-CONTAINER CAPABILITY/SECURITY TESTS (NEAR FUTURE)
-=================================================================================
diff --git a/testcases/kernel/containers/libclone/Makefile b/testcases/kernel/containers/libclone/Makefile
deleted file mode 100644
index 13af52b67..000000000
--- a/testcases/kernel/containers/libclone/Makefile
+++ /dev/null
@@ -1,27 +0,0 @@
-################################################################################
-## ##
-## Copyright (c) International Business Machines Corp., 2007 ##
-## ##
-## 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 ##
-## ##
-################################################################################
-
-top_srcdir ?= ../../../..
-
-include $(top_srcdir)/include/mk/testcases.mk
-
-INTERNAL_LIB := libclone.a
-
-include $(top_srcdir)/include/mk/lib.mk
diff --git a/testcases/kernel/containers/libclone/libclone.c b/testcases/kernel/containers/libclone/libclone.c
deleted file mode 100644
index db0d9b2a5..000000000
--- a/testcases/kernel/containers/libclone/libclone.c
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
-* Copyright (c) International Business Machines Corp., 2007
-* 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
-*
-***************************************************************************/
-#include "libclone.h"
-
-int do_clone_tests(unsigned long clone_flags,
- int (*fn1) (void *arg), void *arg1,
- int (*fn2) (void *arg), void *arg2)
-{
- int ret;
-
- ret = ltp_clone_quick(clone_flags | SIGCHLD, fn1, arg1);
-
- if (ret == -1) {
- return -1;
- }
- if (fn2)
- ret = fn2(arg2);
- else
- ret = 0;
-
- return ret;
-}
-
-int do_unshare_tests(unsigned long clone_flags,
- int (*fn1) (void *arg), void *arg1,
- int (*fn2) (void *arg), void *arg2)
-{
- int pid, ret = 0;
- int retpipe[2];
- char buf[2];
-
- if (pipe(retpipe) == -1) {
- perror("pipe");
- return -1;
- }
- pid = fork();
- if (pid == -1) {
- perror("fork");
- close(retpipe[0]);
- close(retpipe[1]);
- return -1;
- }
- if (pid == 0) {
- close(retpipe[0]);
- ret = tst_syscall(SYS_unshare, clone_flags);
- if (ret == -1) {
- if (write(retpipe[1], "0", 2) < 0) {
- perror("unshare:write(retpipe[1], ..)");
- }
- close(retpipe[1]);
- exit(1);
- } else {
- if (write(retpipe[1], "1", 2) < 0) {
- perror("unshare:write(retpipe[1], ..)");
- }
- }
- close(retpipe[1]);
- ret = fn1(arg1);
- exit(ret);
- } else {
- close(retpipe[1]);
- if (read(retpipe[0], &buf, 2) < 0) {
- perror("unshare:read(retpipe[0], ..)");
- }
- close(retpipe[0]);
- if (*buf == '0')
- return -1;
- if (fn2)
- ret = fn2(arg2);
- }
-
- return ret;
-}
-
-int do_plain_tests(int (*fn1) (void *arg), void *arg1,
- int (*fn2) (void *arg), void *arg2)
-{
- int ret = 0, pid;
-
- pid = fork();
- if (pid == -1) {
- perror("fork");
- return -1;
- }
- if (pid == 0)
- exit(fn1(arg1));
- if (fn2)
- ret = fn2(arg2);
- return ret;
-}
-
-int do_clone_unshare_test(int use_clone, unsigned long clone_flags,
- int (*fn1) (void *arg), void *arg1)
-{
- switch (use_clone) {
- case T_NONE:
- return do_plain_tests(fn1, arg1, NULL, NULL);
- case T_CLONE:
- return do_clone_tests(clone_flags, fn1, arg1, NULL, NULL);
- case T_UNSHARE:
- return do_unshare_tests(clone_flags, fn1, arg1, NULL, NULL);
- default:
- printf("%s: bad use_clone option: %d\n", __FUNCTION__,
- use_clone);
- return -1;
- }
-}
-
-/*
- * Run fn1 in a unshared environmnent, and fn2 in the original context
- */
-int do_clone_unshare_tests(int use_clone, unsigned long clone_flags,
- int (*fn1) (void *arg), void *arg1,
- int (*fn2) (void *arg), void *arg2)
-{
- switch (use_clone) {
- case T_NONE:
- return do_plain_tests(fn1, arg1, fn2, arg2);
- case T_CLONE:
- return do_clone_tests(clone_flags, fn1, arg1, fn2, arg2);
- case T_UNSHARE:
- return do_unshare_tests(clone_flags, fn1, arg1, fn2, arg2);
- default:
- printf("%s: bad use_clone option: %d\n", __FUNCTION__,
- use_clone);
- return -1;
- }
-}
diff --git a/testcases/kernel/containers/libclone/libclone.h b/testcases/kernel/containers/libclone/libclone.h
deleted file mode 100644
index e92fdca02..000000000
--- a/testcases/kernel/containers/libclone/libclone.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
-* Copyright (c) International Business Machines Corp., 2007
-* 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
-*
-***************************************************************************/
-#ifndef __LIBCLONE_H
-#define __LIBCLONE_H
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include <libgen.h>
-#include <sys/syscall.h>
-#include <signal.h>
-#include "lapi/syscalls.h"
-#include "test.h"
-#include "lapi/sched.h"
-
-#define T_UNSHARE 0
-#define T_CLONE 1
-#define T_NONE 2
-
-#ifndef SYS_unshare
-#ifdef __NR_unshare
-#define SYS_unshare __NR_unshare
-#elif __i386__
-#define SYS_unshare 310
-#elif __ia64__
-#define SYS_unshare 1296
-#elif __x86_64__
-#define SYS_unshare 272
-#elif __s390x__ || __s390__
-#define SYS_unshare 303
-#elif __powerpc__
-#define SYS_unshare 282
-#else
-#error "unshare not supported on this architecure."
-#endif
-#endif
-
-#ifndef __NR_unshare
-#define __NR_unshare SYS_unshare
-#endif
-
-/*
- * Run fn1 in a unshared environmnent, and fn2 in the original context
- * Fn2 may be NULL.
- */
-
-int do_clone_tests(unsigned long clone_flags,
- int(*fn1)(void *arg), void *arg1,
- int(*fn2)(void *arg), void *arg2);
-
-int do_unshare_tests(unsigned long clone_flags,
- int (*fn1)(void *arg), void *arg1,
- int (*fn2)(void *arg), void *arg2);
-
-int do_fork_tests(int (*fn1)(void *arg), void *arg1,
- int (*fn2)(void *arg), void *arg2);
-
-int do_clone_unshare_test(int use_clone, unsigned long clone_flags,
- int (*fn1)(void *arg), void *arg1);
-
-int do_clone_unshare_tests(int use_clone, unsigned long clone_flags,
- int (*fn1)(void *arg), void *arg1,
- int (*fn2)(void *arg), void *arg2);
-
-#endif
diff --git a/testcases/kernel/containers/mountns/.gitignore b/testcases/kernel/containers/mountns/.gitignore
new file mode 100644
index 000000000..0555e9b3b
--- /dev/null
+++ b/testcases/kernel/containers/mountns/.gitignore
@@ -0,0 +1,4 @@
+mountns01
+mountns02
+mountns03
+mountns04
diff --git a/testcases/kernel/containers/mountns/mountns.h b/testcases/kernel/containers/mountns/mountns.h
index 615f1a058..9bb854659 100644
--- a/testcases/kernel/containers/mountns/mountns.h
+++ b/testcases/kernel/containers/mountns/mountns.h
@@ -8,28 +8,10 @@
#define COMMON_H
#include "tst_test.h"
-#include "lapi/sched.h"
#define DIRA "LTP_DIR_A"
#define DIRB "LTP_DIR_B"
-static int dummy_child(void *v)
-{
- (void)v;
- return 0;
-}
-
-static void check_newns(void)
-{
- int pid, status;
-
- pid = ltp_clone_quick(CLONE_NEWNS | SIGCHLD, dummy_child, NULL);
- if (pid < 0)
- tst_brk(TCONF, "CLONE_NEWNS not supported");
-
- SAFE_WAIT(&status);
-}
-
static void umount_folders(void)
{
if (tst_is_mounted(DIRA))
diff --git a/testcases/kernel/containers/mountns/mountns01.c b/testcases/kernel/containers/mountns/mountns01.c
index e8f176920..8d821ea45 100644
--- a/testcases/kernel/containers/mountns/mountns01.c
+++ b/testcases/kernel/containers/mountns/mountns01.c
@@ -33,8 +33,9 @@
#include <sys/mount.h>
#include "mountns.h"
#include "tst_test.h"
+#include "lapi/sched.h"
-static int child_func(LTP_ATTRIBUTE_UNUSED void *arg)
+static void child_func(void)
{
TST_CHECKPOINT_WAIT(0);
@@ -51,13 +52,14 @@ static int child_func(LTP_ATTRIBUTE_UNUSED void *arg)
TST_CHECKPOINT_WAKE_AND_WAIT(0);
SAFE_UMOUNT(DIRA);
-
- return 0;
}
static void run(void)
{
- int ret;
+ const struct tst_clone_args args = {
+ .flags = CLONE_NEWNS,
+ .exit_signal = SIGCHLD,
+ };
SAFE_UNSHARE(CLONE_NEWNS);
@@ -67,9 +69,10 @@ static void run(void)
SAFE_MOUNT(DIRA, DIRA, "none", MS_BIND, NULL);
SAFE_MOUNT("none", DIRA, "none", MS_SHARED, NULL);
- ret = ltp_clone_quick(CLONE_NEWNS | SIGCHLD, child_func, NULL);
- if (ret < 0)
- tst_brk(TBROK, "clone failed");
+ if (!SAFE_CLONE(&args)) {
+ child_func();
+ return;
+ }
SAFE_MOUNT(DIRB, DIRA, "none", MS_BIND, NULL);
@@ -93,7 +96,6 @@ static void run(void)
static void setup(void)
{
- check_newns();
create_folders();
}
@@ -107,5 +109,10 @@ static struct tst_test test = {
.cleanup = cleanup,
.test_all = run,
.needs_root = 1,
+ .forks_child = 1,
.needs_checkpoints = 1,
+ .needs_kconfigs = (const char *[]) {
+ "CONFIG_USER_NS",
+ NULL,
+ },
};
diff --git a/testcases/kernel/containers/mountns/mountns02.c b/testcases/kernel/containers/mountns/mountns02.c
index 4b85fa79b..e7a80cbbf 100644
--- a/testcases/kernel/containers/mountns/mountns02.c
+++ b/testcases/kernel/containers/mountns/mountns02.c
@@ -34,8 +34,9 @@
#include <sys/mount.h>
#include "mountns.h"
#include "tst_test.h"
+#include "lapi/sched.h"
-static int child_func(LTP_ATTRIBUTE_UNUSED void *arg)
+static void child_func(void)
{
TST_CHECKPOINT_WAIT(0);
@@ -51,13 +52,14 @@ static int child_func(LTP_ATTRIBUTE_UNUSED void *arg)
TST_CHECKPOINT_WAKE_AND_WAIT(0);
SAFE_UMOUNT(DIRA);
-
- return 0;
}
static void run(void)
{
- int ret;
+ const struct tst_clone_args args = {
+ .flags = CLONE_NEWNS,
+ .exit_signal = SIGCHLD,
+ };
SAFE_UNSHARE(CLONE_NEWNS);
@@ -68,9 +70,10 @@ static void run(void)
SAFE_MOUNT("none", DIRA, "none", MS_PRIVATE, NULL);
- ret = ltp_clone_quick(CLONE_NEWNS | SIGCHLD, child_func, NULL);
- if (ret < 0)
- tst_brk(TBROK, "clone failed");
+ if (!SAFE_CLONE(&args)) {
+ child_func();
+ return;
+ }
SAFE_MOUNT(DIRB, DIRA, "none", MS_BIND, NULL);
@@ -94,7 +97,6 @@ static void run(void)
static void setup(void)
{
- check_newns();
create_folders();
}
@@ -108,5 +110,10 @@ static struct tst_test test = {
.cleanup = cleanup,
.test_all = run,
.needs_root = 1,
+ .forks_child = 1,
.needs_checkpoints = 1,
+ .needs_kconfigs = (const char *[]) {
+ "CONFIG_USER_NS",
+ NULL,
+ },
};
diff --git a/testcases/kernel/containers/mountns/mountns03.c b/testcases/kernel/containers/mountns/mountns03.c
index 1d26a25d8..6066d1c54 100644
--- a/testcases/kernel/containers/mountns/mountns03.c
+++ b/testcases/kernel/containers/mountns/mountns03.c
@@ -36,8 +36,9 @@
#include <sys/mount.h>
#include "mountns.h"
#include "tst_test.h"
+#include "lapi/sched.h"
-static int child_func(LTP_ATTRIBUTE_UNUSED void *arg)
+static void child_func(void)
{
/*
* makes mount DIRA a slave of DIRA (all slave mounts have
@@ -59,13 +60,14 @@ static int child_func(LTP_ATTRIBUTE_UNUSED void *arg)
TST_CHECKPOINT_WAKE_AND_WAIT(0);
SAFE_UMOUNT(DIRA);
-
- return 0;
}
static void run(void)
{
- int ret;
+ const struct tst_clone_args args = {
+ .flags = CLONE_NEWNS,
+ .exit_signal = SIGCHLD,
+ };
SAFE_UNSHARE(CLONE_NEWNS);
@@ -76,9 +78,10 @@ static void run(void)
SAFE_MOUNT("none", DIRA, "none", MS_SHARED, NULL);
- ret = ltp_clone_quick(CLONE_NEWNS | SIGCHLD, child_func, NULL);
- if (ret < 0)
- tst_brk(TBROK, "clone failed");
+ if (!SAFE_CLONE(&args)) {
+ child_func();
+ return;
+ }
TST_CHECKPOINT_WAIT(0);
@@ -104,7 +107,6 @@ static void run(void)
static void setup(void)
{
- check_newns();
create_folders();
}
@@ -118,5 +120,10 @@ static struct tst_test test = {
.cleanup = cleanup,
.test_all = run,
.needs_root = 1,
+ .forks_child = 1,
.needs_checkpoints = 1,
+ .needs_kconfigs = (const char *[]) {
+ "CONFIG_USER_NS",
+ NULL,
+ },
};
diff --git a/testcases/kernel/containers/mountns/mountns04.c b/testcases/kernel/containers/mountns/mountns04.c
index fc392f1a7..7b4dcb16d 100644
--- a/testcases/kernel/containers/mountns/mountns04.c
+++ b/testcases/kernel/containers/mountns/mountns04.c
@@ -22,6 +22,7 @@
#include <sys/mount.h>
#include "mountns.h"
#include "tst_test.h"
+#include "lapi/sched.h"
static void run(void)
{
@@ -46,7 +47,6 @@ static void run(void)
static void setup(void)
{
- check_newns();
create_folders();
}
@@ -61,4 +61,8 @@ static struct tst_test test = {
.test_all = run,
.needs_root = 1,
.needs_tmpdir = 1,
+ .needs_kconfigs = (const char *[]) {
+ "CONFIG_USER_NS",
+ NULL,
+ },
};
diff --git a/testcases/kernel/containers/mqns/Makefile b/testcases/kernel/containers/mqns/Makefile
index 64c3763ee..01e90ec33 100644
--- a/testcases/kernel/containers/mqns/Makefile
+++ b/testcases/kernel/containers/mqns/Makefile
@@ -1,29 +1,12 @@
-################################################################################
-## ##
-## Copyright (c) International Business Machines Corp., 2009 ##
-## Copyright (c) Nadia Derbey, 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 ##
-## ##
-################################################################################
+# SPDX-License-Identifier: GPL-2.0-or-later
+# Copyright (c) International Business Machines Corp., 2009
+# Copyright (c) Nadia Derbey, 2009
+# Copyright (C) 2021 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
top_srcdir ?= ../../../..
include $(top_srcdir)/include/mk/testcases.mk
-include $(abs_srcdir)/../Makefile.inc
-LDLIBS := -lpthread -lrt -lclone $(LDLIBS)
+LDLIBS := -lrt $(LDLIBS)
include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/containers/mqns/mqns.h b/testcases/kernel/containers/mqns/mqns.h
deleted file mode 100644
index 5a9056838..000000000
--- a/testcases/kernel/containers/mqns/mqns.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef __MQNS_H
-#define __MQNS_H
-
-#define DEV_MQUEUE "/dev/mqueue"
-#define DEV_MQUEUE2 "/dev/mqueue2"
-#define SLASH_MQ1 "/MQ1"
-#define NOSLASH_MQ1 "MQ1"
-#define SLASH_MQ2 "/MQ2"
-#define NOSLASH_MQ2 "MQ2"
-
-#endif /* __MQNS_H */
diff --git a/testcases/kernel/containers/mqns/mqns_01.c b/testcases/kernel/containers/mqns/mqns_01.c
index 1d109e020..d9f6e6c18 100644
--- a/testcases/kernel/containers/mqns/mqns_01.c
+++ b/testcases/kernel/containers/mqns/mqns_01.c
@@ -1,148 +1,86 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
-* Copyright (c) International Business Machines Corp., 2009
-* Copyright (c) Nadia Derbey, 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
-*
-* Author: Nadia Derbey <Nadia.Derbey@bull.net>
-*
-* Check mqns isolation: father mqns cannot be accessed from newinstance
-*
-* Mount mqueue fs
-* Create a posix mq -->mq1
-* unshare
-* In unshared process:
-* Mount newinstance mqueuefs
-* Check that mq1 is not readable from new ns
+ * Copyright (c) International Business Machines Corp., 2009
+ * Copyright (c) Nadia Derbey, 2009 <Nadia.Derbey@bull.net>
+ * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+ */
-***************************************************************************/
+/*\
+ * [Description]
+ *
+ * Create a mqueue inside the parent and check if it can be accessed from
+ * the child namespace. Isolated and unshared process can't access to parent,
+ * but plain process can.
+ */
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-#include <sys/wait.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include "mqns.h"
-#include "mqns_helper.h"
+#include "tst_test.h"
+#include "lapi/sched.h"
+#include "tst_safe_posix_ipc.h"
-char *TCID = "posixmq_namespace_01";
-int TST_TOTAL = 1;
+#define MQNAME "/MQ1"
-int p1[2];
-int p2[2];
+static mqd_t mqd;
+static char *str_op;
-int check_mqueue(void *vtest)
+static void run(void)
{
- char buf[30];
- mqd_t mqd;
+ const struct tst_clone_args clone_args = {
+ .flags = CLONE_NEWIPC,
+ .exit_signal = SIGCHLD,
+ };
- (void) vtest;
+ tst_res(TINFO, "Checking namespaces isolation from parent to child");
- close(p1[1]);
- close(p2[0]);
+ if (str_op && !strcmp(str_op, "clone")) {
+ tst_res(TINFO, "Spawning isolated process");
- if (read(p1[0], buf, strlen("go") + 1) < 0) {
- printf("read(p1[0], ...) failed: %s\n", strerror(errno));
- exit(1);
- }
- mqd = tst_syscall(__NR_mq_open, NOSLASH_MQ1, O_RDONLY);
- if (mqd == -1) {
- if (write(p2[1], "notfnd", strlen("notfnd") + 1) < 0) {
- perror("write(p2[1], ...) failed");
- exit(1);
+ if (!SAFE_CLONE(&clone_args)) {
+ TST_EXP_FAIL(mq_open(MQNAME, O_RDONLY), ENOENT);
+ return;
+ }
+ } else if (str_op && !strcmp(str_op, "unshare")) {
+ tst_res(TINFO, "Spawning unshared process");
+
+ if (!SAFE_FORK()) {
+ SAFE_UNSHARE(CLONE_NEWIPC);
+ TST_EXP_FAIL(mq_open(MQNAME, O_RDONLY), ENOENT);
+ return;
}
} else {
- if (write(p2[1], "exists", strlen("exists") + 1) < 0) {
- perror("write(p2[1], \"exists\", 7) failed");
- exit(1);
- } else if (mq_close(mqd) < 0) {
- perror("mq_close(mqd) failed");
- exit(1);
+ tst_res(TINFO, "Spawning plain process");
+
+ if (!SAFE_FORK()) {
+ TST_EXP_POSITIVE(mq_open(MQNAME, O_RDONLY));
+ return;
}
}
-
- exit(0);
}
static void setup(void)
{
- tst_require_root();
- check_mqns();
+ mqd = SAFE_MQ_OPEN(MQNAME, O_RDWR | O_CREAT | O_EXCL, 0777, NULL);
}
-int main(int argc, char *argv[])
+static void cleanup(void)
{
- int r;
- mqd_t mqd;
- char buf[30];
- int use_clone = T_UNSHARE;
-
- setup();
-
- if (argc == 2 && strcmp(argv[1], "-clone") == 0) {
- tst_resm(TINFO,
- "Testing posix mq namespaces through clone(2).");
- use_clone = T_CLONE;
- } else
- tst_resm(TINFO,
- "Testing posix mq namespaces through unshare(2).");
-
- if (pipe(p1) == -1 || pipe(p2) == -1) {
- tst_brkm(TBROK | TERRNO, NULL, "pipe failed");
- }
-
- mqd = tst_syscall(__NR_mq_open, NOSLASH_MQ1, O_RDWR | O_CREAT | O_EXCL,
- 0777, NULL);
- if (mqd == -1) {
- perror("mq_open");
- tst_brkm(TFAIL, NULL, "mq_open failed");
+ if (mqd != -1) {
+ SAFE_MQ_CLOSE(mqd);
+ SAFE_MQ_UNLINK(MQNAME);
}
-
- tst_resm(TINFO, "Checking namespaces isolation from parent to child");
- /* fire off the test */
- r = do_clone_unshare_test(use_clone, CLONE_NEWIPC, check_mqueue, NULL);
- if (r < 0) {
- tst_resm(TFAIL, "failed clone/unshare");
- mq_close(mqd);
- tst_syscall(__NR_mq_unlink, NOSLASH_MQ1);
- tst_exit();
- }
-
- close(p1[0]);
- close(p2[1]);
- if (write(p1[1], "go", strlen("go") + 1) < 0)
- tst_resm(TBROK | TERRNO, "write(p1[1], \"go\", ...) failed");
- else if (read(p2[0], buf, 7) < 0)
- tst_resm(TBROK | TERRNO, "read(p2[0], buf, ...) failed");
- else {
- if (!strcmp(buf, "exists")) {
- tst_resm(TFAIL, "child process found mqueue");
- } else if (!strcmp(buf, "notfnd")) {
- tst_resm(TPASS, "child process didn't find mqueue");
- } else {
- tst_resm(TFAIL, "UNKNOWN RESULT");
- }
- }
-
- /* destroy the mqueue */
- if (mq_close(mqd) == -1) {
- tst_brkm(TBROK | TERRNO, NULL, "mq_close failed");
- }
- tst_syscall(__NR_mq_unlink, NOSLASH_MQ1);
-
- tst_exit();
}
+
+static struct tst_test test = {
+ .test_all = run,
+ .setup = setup,
+ .cleanup = cleanup,
+ .needs_root = 1,
+ .forks_child = 1,
+ .options = (struct tst_option[]) {
+ { "m:", &str_op, "Child process isolation <clone|unshare>" },
+ {},
+ },
+ .needs_kconfigs = (const char *[]) {
+ "CONFIG_USER_NS",
+ NULL
+ },
+};
diff --git a/testcases/kernel/containers/mqns/mqns_02.c b/testcases/kernel/containers/mqns/mqns_02.c
index d4e785b59..4348be7fc 100644
--- a/testcases/kernel/containers/mqns/mqns_02.c
+++ b/testcases/kernel/containers/mqns/mqns_02.c
@@ -1,180 +1,114 @@
+// SPDX-License-Identifier: GPL-2.0
/*
-* Copyright (c) International Business Machines Corp., 2009
-* Copyright (c) Nadia Derbey, 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
-*
-* Author: Nadia Derbey <Nadia.Derbey@bull.net>
-*
-* Check mqns isolation: child mqns cannot be accessed from father
-*
-* Mount mqueue fs
-* unshare
-* In unshared process:
-* Mount newinstance mqueuefs
-* Create a posix mq -->mq1
-* Check that mq1 is not readable from father
-*
-* Changelog:
-* Dec 16: accomodate new mqns semantics (Serge Hallyn)
-
-***************************************************************************/
-
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-#include <sys/wait.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include "mqns.h"
-#include "mqns_helper.h"
-
-char *TCID = "posixmq_namespace_02";
-int TST_TOTAL = 1;
-
-int p1[2];
-int p2[2];
-
-int check_mqueue(void *vtest)
-{
- char buf[30];
- mqd_t mqd;
+ * Copyright (c) International Business Machines Corp., 2009
+ * Copyright (c) Nadia Derbey, 2009 <Nadia.Derbey@bull.net>
+ * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+ */
- (void) vtest;
+/*\
+ * [Description]
+ *
+ * Create a mqueue with the same name in both parent and isolated/forked child,
+ * then check namespace isolation.
+ */
- close(p1[1]);
- close(p2[0]);
+#include "tst_test.h"
+#include "lapi/sched.h"
+#include "tst_safe_posix_ipc.h"
- if (read(p1[0], buf, 3) < 0) {
- perror("read(p1[0], ..) failed");
- exit(1);
- } else {
+#define MQNAME "/MQ1"
- mqd =
- tst_syscall(__NR_mq_open, NOSLASH_MQ1,
- O_RDWR | O_CREAT | O_EXCL, 0777, NULL);
- if (mqd == -1) {
- if (write(p2[1], "mqfail", strlen("mqfail") + 1) < 0) {
- perror("write(p2[1], \"mqfail\", ..) failed");
- exit(1);
- }
- } else {
-
- if (write(p2[1], "mqopen", strlen("mqopen") + 1) < 0) {
- perror("write(p2[1], \"mqopen\", ..) failed");
- exit(1);
- } else {
-
- if (read(p1[0], buf, 5) < 0) {
- perror("read(p1[0], ..) failed");
- exit(1);
- } else {
-
- /* destroy the mqueue */
- if (mq_close(mqd) < 0) {
- perror("mq_close(mqd) failed");
- exit(1);
- } else if (tst_syscall(__NR_mq_unlink,
- NOSLASH_MQ1) < 0) {
- perror("mq_unlink(" NOSLASH_MQ1
- ") failed");
- exit(1);
- } else if (write(p2[1], "done",
- strlen("done") + 1)
- < 0) {
- perror("write(p2[1], "
- "\"done\", ..) failed");
- exit(1);
- }
-
- }
-
- }
+static mqd_t mqd;
+static char *str_op;
- }
+static int create_message_queue(void)
+{
+ return mq_open(MQNAME, O_RDWR | O_CREAT | O_EXCL, 0777, NULL);
+}
- }
- exit(0);
+static void shared_child(void)
+{
+ mqd_t mqd1 = -1;
+ TST_EXP_FAIL(mqd1 = create_message_queue(), EEXIST);
+
+ if (mqd1 != -1) {
+ SAFE_MQ_CLOSE(mqd1);
+ SAFE_MQ_UNLINK(MQNAME);
+ }
}
-static void setup(void)
+static void isolated_child(void)
{
- tst_require_root();
- check_mqns();
+ mqd_t mqd1 = -1;
+
+ TST_EXP_POSITIVE(mqd1 = create_message_queue());
+
+ if (mqd1 != -1) {
+ SAFE_MQ_CLOSE(mqd1);
+ SAFE_MQ_UNLINK(MQNAME);
+ }
}
-int main(int argc, char *argv[])
+static void run(void)
{
- int r;
- mqd_t mqd;
- char buf[30];
- int use_clone = T_UNSHARE;
-
- setup();
-
- if (argc == 2 && strcmp(argv[1], "-clone") == 0) {
- tst_resm(TINFO,
- "Testing posix mq namespaces through clone(2).");
- use_clone = T_CLONE;
- } else
- tst_resm(TINFO,
- "Testing posix mq namespaces through unshare(2).");
-
- if (pipe(p1) == -1 || pipe(p2) == -1) {
- tst_brkm(TBROK | TERRNO, NULL, "pipe");
- }
+ const struct tst_clone_args clone_args = {
+ .flags = CLONE_NEWIPC,
+ .exit_signal = SIGCHLD,
+ };
- /* fire off the test */
- r = do_clone_unshare_test(use_clone, CLONE_NEWIPC, check_mqueue, NULL);
- if (r < 0) {
- tst_brkm(TFAIL, NULL, "failed clone/unshare");
- }
+ tst_res(TINFO, "Checking namespaces isolation from parent to child");
- tst_resm(TINFO, "Checking namespaces isolation (child to parent)");
+ if (str_op && !strcmp(str_op, "clone")) {
+ tst_res(TINFO, "Spawning isolated process");
- close(p1[0]);
- close(p2[1]);
- if (write(p1[1], "go", strlen("go") + 1) < 0) {
- tst_brkm(TBROK, NULL, "write(p1[1], \"go\", ..) failed");
- }
+ if (!SAFE_CLONE(&clone_args)) {
+ isolated_child();
+ return;
+ }
+ } else if (str_op && !strcmp(str_op, "unshare")) {
+ tst_res(TINFO, "Spawning unshared process");
- if (read(p2[0], buf, 7) < 0) {
- tst_resm(TBROK | TERRNO, "read(p2[0], ..) failed");
- } else if (!strcmp(buf, "mqfail")) {
- tst_resm(TFAIL, "child process could not create mqueue");
- umount(DEV_MQUEUE);
- } else if (strcmp(buf, "mqopen")) {
- tst_resm(TFAIL, "child process could not create mqueue");
- umount(DEV_MQUEUE);
- } else {
- mqd = tst_syscall(__NR_mq_open, NOSLASH_MQ1, O_RDONLY);
- if (mqd == -1) {
- tst_resm(TPASS,
- "Parent process can't see the mqueue");
- } else {
- tst_resm(TFAIL | TERRNO,
- "Parent process found mqueue");
- mq_close(mqd);
+ if (!SAFE_FORK()) {
+ SAFE_UNSHARE(CLONE_NEWIPC);
+ isolated_child();
+ return;
}
- if (write(p1[1], "cont", 5) < 0) {
- tst_resm(TBROK | TERRNO, "write(p1[1], ..) failed");
+ } else {
+ tst_res(TINFO, "Spawning plain process");
+
+ if (!SAFE_FORK()) {
+ shared_child();
+ return;
}
- read(p2[0], buf, 7);
}
+}
- tst_exit();
+static void setup(void)
+{
+ mqd = SAFE_MQ_OPEN(MQNAME, O_RDWR | O_CREAT | O_EXCL, 0777, NULL);
}
+
+static void cleanup(void)
+{
+ if (mqd != -1) {
+ SAFE_MQ_CLOSE(mqd);
+ SAFE_MQ_UNLINK(MQNAME);
+ }
+}
+
+static struct tst_test test = {
+ .test_all = run,
+ .setup = setup,
+ .cleanup = cleanup,
+ .needs_root = 1,
+ .forks_child = 1,
+ .options = (struct tst_option[]) {
+ { "m:", &str_op, "Child process isolation <clone|unshare>" },
+ {},
+ },
+ .needs_kconfigs = (const char *[]) {
+ "CONFIG_USER_NS",
+ NULL
+ },
+};
diff --git a/testcases/kernel/containers/mqns/mqns_03.c b/testcases/kernel/containers/mqns/mqns_03.c
index a7452b970..4a0399ddb 100644
--- a/testcases/kernel/containers/mqns/mqns_03.c
+++ b/testcases/kernel/containers/mqns/mqns_03.c
@@ -1,207 +1,154 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
-* 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
-*
-* Author: Serge Hallyn <serue@us.ibm.com>
-*
-* Check ipcns+sb longevity
-*
-* Mount mqueue fs
-* unshare
-* In unshared process:
-* Create "/mq1" with mq_open()
-* Mount mqueuefs
-* Check that /mq1 exists
-* Create /dev/mqueue/mq2 through vfs (create(2))
-* Umount /dev/mqueue
-* Remount /dev/mqueue
-* Check that both /mq1 and /mq2 exist
-
-***************************************************************************/
-
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/wait.h>
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include "mqns.h"
-#include "mqns_helper.h"
-
-char *TCID = "posixmq_namespace_03";
-int TST_TOTAL = 1;
-
-int p1[2];
-int p2[2];
-
-#define FNAM1 DEV_MQUEUE2 SLASH_MQ1
-#define FNAM2 DEV_MQUEUE2 SLASH_MQ2
-
-int check_mqueue(void *vtest)
+ * Copyright (c) International Business Machines Corp., 2009
+ * Copyright (c) Serge Hallyn <serue@us.ibm.com>
+ * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * [Description]
+ *
+ * Test mqueuefs from an isolated/forked process namespace.
+ *
+ * [Algorithm]
+ *
+ * Inside new IPC namespace:
+ *
+ * - mq_open() /MQ1
+ * - mount mqueue inside the temporary folder
+ * - check for /MQ1 existance
+ * - creat() /MQ2 inside the temporary folder
+ * - umount
+ * - mount mqueue inside the temporary folder
+ * - check /MQ1 existance
+ * - check /MQ2 existance
+ * - umount
+ */
+
+#include "tst_test.h"
+#include "lapi/sched.h"
+#include "tst_safe_posix_ipc.h"
+#include "tst_safe_stdio.h"
+#include "tst_safe_macros.h"
+
+#define CHECK_MQ_OPEN_RET(x) ((x) >= 0 || ((x) == -1 && errno != EMFILE))
+
+#define DEVDIR "ltp_mqueue"
+#define MQNAME1 "/MQ1"
+#define MQNAME2 "/MQ2"
+#define MQUEUE1 DEVDIR MQNAME1
+#define MQUEUE2 DEVDIR MQNAME2
+
+static char *str_op;
+
+static void check_mqueue(void)
{
- char buf[30];
- mqd_t mqd;
int rc;
- struct stat statbuf;
+ mqd_t mqd;
- (void) vtest;
+ tst_res(TINFO, "Creating %s mqueue from within child process", MQNAME1);
- close(p1[1]);
- close(p2[0]);
+ mqd = TST_RETRY_FUNC(
+ mq_open(MQNAME1, O_RDWR | O_CREAT | O_EXCL, 0777, NULL),
+ CHECK_MQ_OPEN_RET);
+ if (mqd == -1)
+ tst_brk(TBROK | TERRNO, "mq_open failed");
- if (read(p1[0], buf, 3) != 3) { /* go */
- perror("read failed");
- exit(1);
- }
+ SAFE_MQ_CLOSE(mqd);
- mqd = tst_syscall(__NR_mq_open, NOSLASH_MQ1, O_RDWR | O_CREAT | O_EXCL,
- 0755, NULL);
- if (mqd == -1) {
- write(p2[1], "mqfail", 7);
- exit(1);
- }
+ tst_res(TINFO, "Mount %s from within child process", DEVDIR);
- mq_close(mqd);
+ SAFE_MOUNT("mqueue", DEVDIR, "mqueue", 0, NULL);
- rc = mount("mqueue", DEV_MQUEUE2, "mqueue", 0, NULL);
- if (rc == -1) {
- write(p2[1], "mount1", 7);
- exit(1);
- }
+ if (access(MQUEUE1, F_OK))
+ tst_res(TFAIL, MQUEUE1 " does not exist at first mount");
+ else
+ tst_res(TPASS, MQUEUE1 " exists at first mount");
- rc = stat(FNAM1, &statbuf);
- if (rc == -1) {
- write(p2[1], "stat1", 6);
- exit(1);
- }
+ tst_res(TINFO, "Creating %s from within child process", MQUEUE2);
- rc = creat(FNAM2, 0755);
- if (rc == -1) {
- write(p2[1], "creat", 6);
- exit(1);
- }
+ rc = SAFE_CREAT(MQUEUE2, 0755);
+ SAFE_CLOSE(rc);
- close(rc);
+ tst_res(TINFO, "Mount %s from within child process a second time", DEVDIR);
- rc = umount(DEV_MQUEUE2);
- if (rc == -1) {
- write(p2[1], "umount", 7);
- exit(1);
- }
+ SAFE_UMOUNT(DEVDIR);
+ SAFE_MOUNT("mqueue", DEVDIR, "mqueue", 0, NULL);
- rc = mount("mqueue", DEV_MQUEUE2, "mqueue", 0, NULL);
- if (rc == -1) {
- write(p2[1], "mount2", 7);
- exit(1);
- }
+ if (access(MQUEUE1, F_OK))
+ tst_res(TFAIL, MQUEUE1 " does not exist at second mount");
+ else
+ tst_res(TPASS, MQUEUE1 " exists at second mount");
- rc = stat(FNAM1, &statbuf);
- if (rc == -1) {
- write(p2[1], "stat2", 7);
- exit(1);
- }
+ if (access(MQUEUE2, F_OK))
+ tst_res(TFAIL, MQUEUE2 " does not exist at second mount");
+ else
+ tst_res(TPASS, MQUEUE2 " exists at second mount");
- rc = stat(FNAM2, &statbuf);
- if (rc == -1) {
- write(p2[1], "stat3", 7);
- exit(1);
- }
+ SAFE_UMOUNT(DEVDIR);
- write(p2[1], "done", 5);
+ SAFE_MQ_UNLINK(MQNAME1);
+ SAFE_MQ_UNLINK(MQNAME2);
+}
- exit(0);
+static void run(void)
+{
+ const struct tst_clone_args clone_args = {
+ .flags = CLONE_NEWIPC,
+ .exit_signal = SIGCHLD
+ };
+
+ if (str_op && !strcmp(str_op, "clone")) {
+ tst_res(TINFO, "Spawning isolated process");
+
+ if (!SAFE_CLONE(&clone_args)) {
+ check_mqueue();
+ return;
+ }
+ } else if (str_op && !strcmp(str_op, "unshare")) {
+ tst_res(TINFO, "Spawning unshared process");
+
+ if (!SAFE_FORK()) {
+ SAFE_UNSHARE(CLONE_NEWIPC);
+ check_mqueue();
+ return;
+ }
+ }
}
static void setup(void)
{
- tst_require_root();
- check_mqns();
+ if (!str_op || (strcmp(str_op, "clone") && strcmp(str_op, "unshare")))
+ tst_brk(TCONF, "Please specify clone|unshare child isolation");
+
+ SAFE_MKDIR(DEVDIR, 0755);
}
-int main(int argc, char *argv[])
+static void cleanup(void)
{
- int r;
- char buf[30];
- int use_clone = T_UNSHARE;
-
- setup();
-
- if (argc == 2 && strcmp(argv[1], "-clone") == 0) {
- tst_resm(TINFO, "Testing posix mq namespaces through clone(2)");
- use_clone = T_CLONE;
- } else
- tst_resm(TINFO,
- "Testing posix mq namespaces through unshare(2)");
-
- if (pipe(p1) == -1 || pipe(p2) == -1)
- tst_brkm(TBROK | TERRNO, NULL, "pipe failed");
-
- /* fire off the test */
- r = do_clone_unshare_test(use_clone, CLONE_NEWIPC, check_mqueue, NULL);
- if (r < 0) {
- tst_brkm(TBROK | TERRNO, NULL, "failed clone/unshare");
- }
-
- tst_resm(TINFO, "Checking correct umount+remount of mqueuefs");
-
- mkdir(DEV_MQUEUE2, 0755);
-
- close(p1[0]);
- close(p2[1]);
- write(p1[1], "go", 3);
-
- read(p2[0], buf, 7);
- r = TFAIL;
- if (!strcmp(buf, "mqfail")) {
- tst_resm(TFAIL, "child process could not create mqueue");
- goto fail;
- } else if (!strcmp(buf, "mount1")) {
- tst_resm(TFAIL, "child process could not mount mqueue");
- goto fail;
- } else if (!strcmp(buf, "stat1x")) {
- tst_resm(TFAIL, "mq created by child is not in mqueuefs");
- goto fail;
- } else if (!strcmp(buf, "creat")) {
- tst_resm(TFAIL, "child couldn't creat mq through mqueuefs");
- goto fail;
- } else if (!strcmp(buf, "umount")) {
- tst_resm(TFAIL, "child couldn't umount mqueuefs");
- goto fail;
- } else if (!strcmp(buf, "mount2")) {
- tst_resm(TFAIL, "child couldn't remount mqueuefs");
- goto fail;
- } else if (!strcmp(buf, "stat2")) {
- tst_resm(TFAIL,
- "mq_open()d file gone after remount of mqueuefs");
- goto fail;
- } else if (!strcmp(buf, "stat3")) {
- tst_resm(TFAIL,
- "creat(2)'d file gone after remount of mqueuefs");
- goto fail;
- }
+ if (!access(MQUEUE1, F_OK))
+ SAFE_MQ_UNLINK(MQNAME1);
- tst_resm(TPASS, "umount+remount of mqueuefs remounted the right fs");
+ if (!access(MQUEUE2, F_OK))
+ SAFE_MQ_UNLINK(MQNAME2);
- r = 0;
-fail:
- umount(DEV_MQUEUE2);
- rmdir(DEV_MQUEUE2);
- tst_exit();
+ if (tst_is_mounted(DEVDIR))
+ SAFE_UMOUNT(DEVDIR);
}
+
+static struct tst_test test = {
+ .test_all = run,
+ .setup = setup,
+ .cleanup = cleanup,
+ .needs_root = 1,
+ .forks_child = 1,
+ .needs_tmpdir = 1,
+ .options = (struct tst_option[]) {
+ { "m:", &str_op, "Child process isolation <clone|unshare>" },
+ {},
+ },
+ .needs_kconfigs = (const char *[]) {
+ "CONFIG_USER_NS",
+ NULL
+ },
+};
diff --git a/testcases/kernel/containers/mqns/mqns_04.c b/testcases/kernel/containers/mqns/mqns_04.c
index d07a85c04..2d943e1b6 100644
--- a/testcases/kernel/containers/mqns/mqns_04.c
+++ b/testcases/kernel/containers/mqns/mqns_04.c
@@ -1,187 +1,147 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
-* 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
-*
-* Author: Serge Hallyn <serue@us.ibm.com>
-*
-* Check mqueuefs lifetime
-* . parent creates /dev/mqueue2
-* . child mounts mqueue there
-* . child does mq_open("/ab")
-* . parent checks for /dev/mqueue2
-* . child exits
-* . parent checks for /dev/mqueue2
-* . parent tries 'touch /dev/mqueue2/dd' -> should fail
-* . parent umounts /dev/mqueue2
-
-***************************************************************************/
-
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-#include <sys/types.h>
-#include <sys/stat.h>
+ * Copyright (c) International Business Machines Corp., 2009
+ * Copyright (c) Serge Hallyn <serue@us.ibm.com>
+ * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * [Description]
+ *
+ * Test mqueuefs manipulation from child/parent namespaces.
+ *
+ * [Algorithm]
+ *
+ * - parent creates mqueue folder in <tmpdir>
+ * - child mq_open() /MQ1 mqueue
+ * - child mounts mqueue there
+ * - parent checks for <tmpdir>/mqueue/MQ1 existence
+ * - child exits
+ * - parent checks for <tmpdir>/mqueue/MQ1 existence
+ * - parent tries 'touch <tmpdir>/mqueue/MQ2' -> should fail
+ * - parent umount mqueuefs
+ */
+
#include <sys/wait.h>
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include "mqns.h"
-#include "mqns_helper.h"
+#include "tst_test.h"
+#include "lapi/sched.h"
+#include "tst_safe_posix_ipc.h"
+#include "tst_safe_stdio.h"
+#include "tst_safe_macros.h"
-char *TCID = "posixmq_namespace_04";
-int TST_TOTAL = 1;
+#define CHECK_MQ_OPEN_RET(x) ((x) >= 0 || ((x) == -1 && errno != EMFILE))
-int p1[2];
-int p2[2];
+#define DEVDIR "ltp_mqueue"
+#define MQNAME1 "/MQ1"
+#define MQNAME2 "/MQ2"
+#define MQUEUE1 DEVDIR MQNAME1
+#define MQUEUE2 DEVDIR MQNAME2
-#define FNAM1 DEV_MQUEUE2 SLASH_MQ1
-#define FNAM2 DEV_MQUEUE2 SLASH_MQ2
+static char *str_op;
-int check_mqueue(void *vtest)
+static void check_mqueue(void)
{
- char buf[30];
mqd_t mqd;
- int rc;
- (void) vtest;
+ tst_res(TINFO, "Creating %s mqueue from within child process", MQNAME1);
- close(p1[1]);
- close(p2[0]);
+ mqd = TST_RETRY_FUNC(
+ mq_open(MQNAME1, O_RDWR | O_CREAT | O_EXCL, 0755, NULL),
+ CHECK_MQ_OPEN_RET);
+ if (mqd == -1)
+ tst_brk(TBROK | TERRNO, "mq_open failed");
- read(p1[0], buf, 3); /* go */
+ SAFE_MQ_CLOSE(mqd);
- mqd = tst_syscall(__NR_mq_open, NOSLASH_MQ1, O_RDWR | O_CREAT | O_EXCL,
- 0755, NULL);
- if (mqd == -1) {
- write(p2[1], "mqfail", 7);
- tst_exit();
- }
+ tst_res(TINFO, "Mount %s from within child process", DEVDIR);
- mq_close(mqd);
+ SAFE_MOUNT("mqueue", DEVDIR, "mqueue", 0, NULL);
+
+ TST_CHECKPOINT_WAKE_AND_WAIT(0);
+}
- rc = mount("mqueue", DEV_MQUEUE2, "mqueue", 0, NULL);
- if (rc == -1) {
- perror("mount");
- write(p2[1], "mount", 6);
- tst_exit();
+static void run(void)
+{
+ const struct tst_clone_args clone_args = {
+ .flags = CLONE_NEWIPC,
+ .exit_signal = SIGCHLD
+ };
+
+ if (str_op && !strcmp(str_op, "clone")) {
+ tst_res(TINFO, "Spawning isolated process");
+
+ if (!SAFE_CLONE(&clone_args)) {
+ check_mqueue();
+ return;
+ }
+ } else if (str_op && !strcmp(str_op, "unshare")) {
+ tst_res(TINFO, "Spawning unshared process");
+
+ if (!SAFE_FORK()) {
+ SAFE_UNSHARE(CLONE_NEWIPC);
+ check_mqueue();
+ return;
+ }
}
- write(p2[1], "go", 3);
- read(p1[0], buf, 3);
+ TST_CHECKPOINT_WAIT(0);
- tst_exit();
-}
+ if (access(MQUEUE1, F_OK))
+ tst_res(TFAIL, MQUEUE1 " can't be accessed from parent");
+ else
+ tst_res(TPASS, MQUEUE1 " can be accessed from parent");
-static void setup(void)
-{
- tst_require_root();
- check_mqns();
-}
+ TST_CHECKPOINT_WAKE(0);
-int main(int argc, char *argv[])
-{
- int rc;
- int status;
- char buf[30];
- struct stat statbuf;
- int use_clone = T_UNSHARE;
-
- setup();
-
- if (argc == 2 && strcmp(argv[1], "-clone") == 0) {
- tst_resm(TINFO,
- "Testing posix mq namespaces through clone(2).");
- use_clone = T_CLONE;
- } else
- tst_resm(TINFO,
- "Testing posix mq namespaces through unshare(2).");
-
- if (pipe(p1) == -1) {
- perror("pipe");
- exit(EXIT_FAILURE);
- }
- if (pipe(p2) == -1) {
- perror("pipe");
- exit(EXIT_FAILURE);
- }
+ tst_res(TINFO, "Waiting child to exit");
- mkdir(DEV_MQUEUE2, 0755);
+ tst_reap_children();
- tst_resm(TINFO, "Checking mqueue filesystem lifetime");
+ if (access(MQUEUE1, F_OK))
+ tst_res(TFAIL, MQUEUE1 " can't be accessed from parent");
+ else
+ tst_res(TPASS, MQUEUE1 " can be accessed from parent");
- /* fire off the test */
- rc = do_clone_unshare_test(use_clone, CLONE_NEWIPC, check_mqueue, NULL);
- if (rc < 0) {
- tst_resm(TFAIL, "failed clone/unshare");
- goto fail;
- }
+ tst_res(TINFO, "Try to create %s from parent", MQUEUE2);
- close(p1[0]);
- close(p2[1]);
- write(p1[1], "go", 3);
-
- read(p2[0], buf, 7);
- if (!strcmp(buf, "mqfail")) {
- tst_resm(TFAIL, "child process could not create mqueue");
- goto fail;
- } else if (!strcmp(buf, "mount")) {
- tst_resm(TFAIL, "child process could not mount mqueue");
- goto fail;
- }
+ TST_EXP_FAIL(creat(MQUEUE2, 0755), EACCES);
- rc = stat(FNAM1, &statbuf);
- if (rc == -1) {
- perror("stat");
- write(p1[1], "go", 3);
- tst_resm(TFAIL, "parent could not see child's created mq");
- goto fail;
- }
- write(p1[1], "go", 3);
+ SAFE_UMOUNT(DEVDIR);
+}
- rc = wait(&status);
- if (rc == -1) {
- perror("wait");
- tst_resm(TFAIL, "error while parent waited on child to exit");
- goto fail;
- }
- if (!WIFEXITED(status)) {
- tst_resm(TFAIL, "Child did not exit normally (status %d)",
- status);
- goto fail;
- }
- rc = stat(FNAM1, &statbuf);
- if (rc == -1) {
- tst_resm(TFAIL,
- "parent's view of child's mq died with child");
- goto fail;
- }
+static void setup(void)
+{
+ if (!str_op || (strcmp(str_op, "clone") && strcmp(str_op, "unshare")))
+ tst_brk(TCONF, "Please specify clone|unshare child isolation");
- rc = creat(FNAM2, 0755);
- if (rc != -1) {
- tst_resm(TFAIL,
- "parent was able to create a file in dead child's mqfs");
- goto fail;
- }
+ SAFE_MKDIR(DEVDIR, 0755);
+}
- tst_resm(TPASS, "Child mqueue fs still visible for parent");
+static void cleanup(void)
+{
+ if (!access(MQUEUE1, F_OK))
+ SAFE_MQ_UNLINK(MQNAME1);
-fail:
- umount(DEV_MQUEUE2);
- rmdir(DEV_MQUEUE2);
+ if (!access(MQUEUE2, F_OK))
+ SAFE_MQ_UNLINK(MQNAME2);
- tst_exit();
+ if (tst_is_mounted(DEVDIR))
+ SAFE_UMOUNT(DEVDIR);
}
+
+static struct tst_test test = {
+ .test_all = run,
+ .setup = setup,
+ .cleanup = cleanup,
+ .needs_root = 1,
+ .forks_child = 1,
+ .needs_checkpoints = 1,
+ .options = (struct tst_option[]) {
+ { "m:", &str_op, "Child process isolation <clone|unshare>" },
+ {},
+ },
+ .needs_kconfigs = (const char *[]) {
+ "CONFIG_USER_NS",
+ NULL
+ },
+};
diff --git a/testcases/kernel/containers/mqns/mqns_helper.h b/testcases/kernel/containers/mqns/mqns_helper.h
deleted file mode 100644
index 03f50aa36..000000000
--- a/testcases/kernel/containers/mqns/mqns_helper.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) International Business Machines Corp., 2009
- * Copyright (c) Nadia Derbey, 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
- *
- * Author: Serge Hallyn <serue@us.ibm.com>
- ***************************************************************************/
-#include <sys/mount.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <mqueue.h>
-#include "../libclone/libclone.h"
-#include "lapi/syscalls.h"
-#include "safe_macros.h"
-#include "test.h"
-
-static int dummy_child(void *v)
-{
- (void) v;
- return 0;
-}
-
-static void check_mqns(void)
-{
- int pid, status;
- mqd_t mqd;
-
- mq_unlink("/checkmqnsenabled");
- mqd =
- mq_open("/checkmqnsenabled", O_RDWR | O_CREAT | O_EXCL, 0777, NULL);
- if (mqd == -1)
- tst_brkm(TCONF, NULL, "mq_open check failed");
-
- mq_close(mqd);
- mq_unlink("/checkmqnsenabled");
-
- pid = do_clone_unshare_test(T_CLONE, CLONE_NEWIPC, dummy_child, NULL);
- if (pid == -1)
- tst_brkm(TCONF | TERRNO, NULL, "CLONE_NEWIPC not supported");
-
- SAFE_WAIT(NULL, &status);
-}
diff --git a/testcases/kernel/containers/netns/Makefile b/testcases/kernel/containers/netns/Makefile
index 3cc2b4ae7..a8edd31b8 100644
--- a/testcases/kernel/containers/netns/Makefile
+++ b/testcases/kernel/containers/netns/Makefile
@@ -2,12 +2,12 @@
# Copyright (c) International Business Machines Corp., 2008
# Author: Veerendra <veeren@linux.vnet.ibm.com>
# Copyright (c) 2015 Red Hat, Inc.
+# Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
top_srcdir ?= ../../../..
include $(top_srcdir)/include/mk/testcases.mk
-include $(abs_srcdir)/../Makefile.inc
-LDLIBS := -lclone -lltp
+INSTALL_TARGETS := *.sh
include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/containers/netns/netns_lib.sh b/testcases/kernel/containers/netns/netns_lib.sh
index 79e90336a..f6977f729 100755
--- a/testcases/kernel/containers/netns/netns_lib.sh
+++ b/testcases/kernel/containers/netns/netns_lib.sh
@@ -1,7 +1,7 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (c) 2022 Petr Vorel <pvorel@suse.cz>
-# Copyright (c) Linux Test Project, 2014-2021
+# Copyright (c) Linux Test Project, 2014-2023
# Copyright (c) 2015 Red Hat, Inc.
TST_NEEDS_ROOT=1
@@ -20,7 +20,7 @@ TST_NET_SKIP_VARIABLE_INIT=1
IPV4_NET16_UNUSED="10.23"
IPV6_NET32_UNUSED="fd00:23"
-# Set to "net" for ns_create/ns_exec as their options requires
+# Set to "net" for tst_ns_create/tst_ns_exec as their options requires
# to specify a namespace type. Empty for ip command.
NS_TYPE=
@@ -28,7 +28,7 @@ NS_TYPE=
tping=
# Network namespaces handles for manipulating and executing commands inside
-# namespaces. For 'ns_exec' handles are PIDs of daemonized processes running
+# namespaces. For 'tst_ns_exec' handles are PIDs of daemonized processes running
# in namespaces.
NS_HANDLE0=
NS_HANDLE1=
@@ -40,7 +40,7 @@ NS_HANDLE1=
IFCONF_IN6_ARG=
# Program which will be used to enter and run other commands inside a network namespace.
-# (ns_exec|ip)
+# (tst_ns_exec|ip)
NS_EXEC="ip"
# Communication type between kernel and user space for basic setup: enabling and
@@ -54,7 +54,7 @@ do_cleanup=
netns_parse_args()
{
case $1 in
- e) NS_EXEC="ns_exec" ;;
+ e) NS_EXEC="tst_ns_exec" ;;
I) COMM_TYPE="ioctl"; tst_require_cmds ifconfig ;;
esac
}
@@ -63,7 +63,7 @@ netns_usage()
{
echo "usage: $0 [ -e ] [ -I ]"
echo "OPTIONS"
- echo "-e Use ns_exec instead of ip"
+ echo "-e Use tst_ns_exec instead of ip"
echo "-I Test ioctl (with ifconfig) instead of netlink (with ip)"
}
@@ -72,9 +72,6 @@ netns_setup()
if [ "$NS_EXEC" = "ip" ]; then
netns_ip_setup
else
- setns_check
- [ $? -eq 32 ] && tst_brk TCONF "setns not supported"
-
NS_TYPE="net"
netns_ns_exec_setup
fi
@@ -108,7 +105,7 @@ netns_cleanup()
fi
}
-# Sets up NS_EXEC to use 'ns_exec', creates two network namespaces and stores
+# Sets up NS_EXEC to use 'tst_ns_exec', creates two network namespaces and stores
# their handles into NS_HANDLE0 and NS_HANDLE1 variables (in this case handles
# are PIDs of daemonized processes running in these namespaces). Virtual
# ethernet device is then created for each namespace.
@@ -116,15 +113,15 @@ netns_ns_exec_setup()
{
local ret
- NS_EXEC="ns_exec"
+ NS_EXEC="tst_ns_exec"
- NS_HANDLE0=$(ns_create $NS_TYPE)
+ NS_HANDLE0=$(tst_ns_create $NS_TYPE)
if [ $? -eq 1 ]; then
tst_res TINFO "$NS_HANDLE0"
tst_brk TBROK "unable to create a new network namespace"
fi
- NS_HANDLE1=$(ns_create $NS_TYPE)
+ NS_HANDLE1=$(tst_ns_create $NS_TYPE)
if [ $? -eq 1 ]; then
tst_res TINFO "$NS_HANDLE1"
tst_brk TBROK "unable to create a new network namespace"
@@ -133,7 +130,7 @@ netns_ns_exec_setup()
$NS_EXEC $NS_HANDLE0 $NS_TYPE ip link add veth0 type veth peer name veth1 || \
tst_brk TBROK "unable to create veth pair devices"
- $NS_EXEC $NS_HANDLE0 $NS_TYPE ns_ifmove veth1 $NS_HANDLE1
+ $NS_EXEC $NS_HANDLE0 $NS_TYPE tst_ns_ifmove veth1 $NS_HANDLE1
ret=$?
[ $ret -eq 0 ] && return
[ $ret -eq 32 ] && tst_brk TCONF "IFLA_NET_NS_PID not supported"
diff --git a/testcases/kernel/containers/netns/netns_sysfs.sh b/testcases/kernel/containers/netns/netns_sysfs.sh
index 179242721..814274fd0 100755
--- a/testcases/kernel/containers/netns/netns_sysfs.sh
+++ b/testcases/kernel/containers/netns/netns_sysfs.sh
@@ -2,6 +2,7 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (c) Köry Maincent <kory.maincent@bootlin.com> 2020
# Copyright (c) 2015 Red Hat, Inc.
+# Copyright (c) Linux Test Project, 2015-2023
#
# Tests that a separate network namespace cannot affect sysfs contents
# of the main namespace.
@@ -18,12 +19,7 @@ do_setup()
DUMMYDEV_HOST="dummy_test0"
DUMMYDEV="dummy_test1"
- setns_check
- if [ $? -eq 32 ]; then
- tst_brk TCONF "setns not supported"
- fi
-
- NS_HANDLE=$(ns_create $NS_TYPE)
+ NS_HANDLE=$(tst_ns_create $NS_TYPE)
if [ $? -eq 1 ]; then
tst_res TINFO "$NS_HANDLE"
tst_brk TBROK "unable to create a new network namespace"
@@ -32,10 +28,10 @@ do_setup()
ip link add $DUMMYDEV_HOST type dummy || \
tst_brk TBROK "failed to add a new (host) dummy device"
- ns_exec $NS_HANDLE $NS_TYPE mount --make-rprivate /sys
- ns_exec $NS_HANDLE $NS_TYPE ip link add $DUMMYDEV type dummy || \
+ tst_ns_exec $NS_HANDLE $NS_TYPE mount --make-rprivate /sys
+ tst_ns_exec $NS_HANDLE $NS_TYPE ip link add $DUMMYDEV type dummy || \
tst_brk TBROK "failed to add a new dummy device"
- ns_exec $NS_HANDLE $NS_TYPE mount -t sysfs none /sys 2>/dev/null
+ tst_ns_exec $NS_HANDLE $NS_TYPE mount -t sysfs none /sys 2>/dev/null
}
do_cleanup()
@@ -47,8 +43,8 @@ do_cleanup()
do_test()
{
- EXPECT_PASS ns_exec $NS_HANDLE $NS_TYPE test -e /sys/class/net/$DUMMYDEV
- EXPECT_FAIL ns_exec $NS_HANDLE $NS_TYPE test -e /sys/class/net/$DUMMYDEV_HOST
+ EXPECT_PASS tst_ns_exec $NS_HANDLE $NS_TYPE test -e /sys/class/net/$DUMMYDEV
+ EXPECT_FAIL tst_ns_exec $NS_HANDLE $NS_TYPE test -e /sys/class/net/$DUMMYDEV_HOST
EXPECT_FAIL test -e /sys/class/net/$DUMMYDEV
}
diff --git a/testcases/kernel/containers/pidns/Makefile b/testcases/kernel/containers/pidns/Makefile
index 5f8383c3c..180bc7c90 100644
--- a/testcases/kernel/containers/pidns/Makefile
+++ b/testcases/kernel/containers/pidns/Makefile
@@ -4,8 +4,7 @@
top_srcdir ?= ../../../..
include $(top_srcdir)/include/mk/testcases.mk
-include $(abs_srcdir)/../Makefile.inc
-LDLIBS := -lpthread -lrt -lclone $(LDLIBS)
+LDLIBS := -lrt $(LDLIBS)
include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/containers/pidns/pidns01.c b/testcases/kernel/containers/pidns/pidns01.c
index 5080b6fad..8b856ec90 100644
--- a/testcases/kernel/containers/pidns/pidns01.c
+++ b/testcases/kernel/containers/pidns/pidns01.c
@@ -8,7 +8,7 @@
/*\
* [Description]
*
- * Clone a process with CLONE_NEWNS flag and check:
+ * Clone a process with CLONE_NEWPID flag and check:
*
* - child process ID must be 1
* - parent process ID must be 0
@@ -17,29 +17,36 @@
#include "tst_test.h"
#include "lapi/sched.h"
-static int child_func(LTP_ATTRIBUTE_UNUSED void *arg)
+static void child_func(void)
{
pid_t cpid, ppid;
- cpid = getpid();
+ cpid = tst_getpid();
ppid = getppid();
- TST_EXP_PASS(cpid == 1);
- TST_EXP_PASS(ppid == 0);
-
- return 0;
+ TST_EXP_EQ_LI(cpid, 1);
+ TST_EXP_EQ_LI(ppid, 0);
}
static void run(void)
{
- int ret;
-
- ret = ltp_clone_quick(CLONE_NEWNS | SIGCHLD, child_func, NULL);
- if (ret < 0)
- tst_brk(TBROK | TERRNO, "clone failed");
+ const struct tst_clone_args args = {
+ .flags = CLONE_NEWPID,
+ .exit_signal = SIGCHLD,
+ };
+
+ if (!SAFE_CLONE(&args)) {
+ child_func();
+ return;
+ }
}
static struct tst_test test = {
.test_all = run,
.needs_root = 1,
+ .forks_child = 1,
+ .needs_kconfigs = (const char *[]) {
+ "CONFIG_PID_NS",
+ NULL,
+ },
};
diff --git a/testcases/kernel/containers/pidns/pidns02.c b/testcases/kernel/containers/pidns/pidns02.c
index b8913d3f6..f23178cb6 100644
--- a/testcases/kernel/containers/pidns/pidns02.c
+++ b/testcases/kernel/containers/pidns/pidns02.c
@@ -7,7 +7,7 @@
/*\
* [Description]
*
- * Clone a process with CLONE_NEWNS flag and check:
+ * Clone a process with CLONE_NEWPID flag and check:
*
* - child session ID must be 1
* - parent process group ID must be 1
@@ -16,29 +16,37 @@
#include "tst_test.h"
#include "lapi/sched.h"
-static int child_func(LTP_ATTRIBUTE_UNUSED void *arg)
+static void child_func(void)
{
- pid_t sid, pgid;
+ TST_EXP_EQ_LI(getsid(0), 0);
+ TST_EXP_EQ_LI(getpgid(0), 0);
- sid = getsid(0);
- pgid = getpgid(0);
+ tst_res(TINFO, "setsid()");
+ SAFE_SETSID();
- TST_EXP_PASS(sid == 1);
- TST_EXP_PASS(pgid == 1);
-
- return 0;
+ TST_EXP_EQ_LI(getsid(0), 1);
+ TST_EXP_EQ_LI(getpgid(0), 1);
}
static void run(void)
{
- int ret;
-
- ret = ltp_clone_quick(CLONE_NEWNS | SIGCHLD, child_func, NULL);
- if (ret < 0)
- tst_brk(TBROK | TERRNO, "clone failed");
+ const struct tst_clone_args args = {
+ .flags = CLONE_NEWPID,
+ .exit_signal = SIGCHLD,
+ };
+
+ if (!SAFE_CLONE(&args)) {
+ child_func();
+ return;
+ }
}
static struct tst_test test = {
.test_all = run,
.needs_root = 1,
+ .forks_child = 1,
+ .needs_kconfigs = (const char *[]) {
+ "CONFIG_PID_NS",
+ NULL,
+ },
};
diff --git a/testcases/kernel/containers/pidns/pidns03.c b/testcases/kernel/containers/pidns/pidns03.c
index 122ba7891..d662ca9d5 100644
--- a/testcases/kernel/containers/pidns/pidns03.c
+++ b/testcases/kernel/containers/pidns/pidns03.c
@@ -17,7 +17,7 @@
#define PROCDIR "proc"
-static int child_func(LTP_ATTRIBUTE_UNUSED void *arg)
+static void child_func(void)
{
char proc_self[10];
@@ -28,8 +28,6 @@ static int child_func(LTP_ATTRIBUTE_UNUSED void *arg)
SAFE_UMOUNT(PROCDIR);
TST_EXP_PASS(strcmp(proc_self, "1"), PROCDIR"/self contains 1:");
-
- return 0;
}
static void setup(void)
@@ -45,11 +43,15 @@ static void cleanup(void)
static void run(void)
{
- int ret;
+ const struct tst_clone_args args = {
+ .flags = CLONE_NEWPID,
+ .exit_signal = SIGCHLD,
+ };
- ret = ltp_clone_quick(CLONE_NEWPID | SIGCHLD, child_func, NULL);
- if (ret < 0)
- tst_brk(TBROK | TERRNO, "clone failed");
+ if (!SAFE_CLONE(&args)) {
+ child_func();
+ return;
+ }
}
static struct tst_test test = {
@@ -57,5 +59,10 @@ static struct tst_test test = {
.setup = setup,
.cleanup = cleanup,
.needs_root = 1,
+ .forks_child = 1,
.needs_tmpdir = 1,
+ .needs_kconfigs = (const char *[]) {
+ "CONFIG_PID_NS",
+ NULL,
+ },
};
diff --git a/testcases/kernel/containers/pidns/pidns04.c b/testcases/kernel/containers/pidns/pidns04.c
index 9ac0e5aca..bed75a082 100644
--- a/testcases/kernel/containers/pidns/pidns04.c
+++ b/testcases/kernel/containers/pidns/pidns04.c
@@ -1,150 +1,54 @@
+// SPDX-License-Identifier: GPL-2.0
/*
-* Copyright (c) International Business Machines Corp., 2007
-* 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., 2008
+ * Copyright (C) 2022 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+ */
-* File: pidns04.c
-*
-* Description:
-* The pidns04.c testcase builds into the ltp framework to verify
-* the basic functionality of PID Namespace.
-*
-* Verify that:
-* 1. When parent clone a process with flag CLONE_NEWPID, the process ID of
-* child should be one.
-*
-* 2. When parent clone a process with flag CLONE_NEWPID, the parent process ID
-* of should be zero.
-*
-* 3. The container init process (one), should not get killed by the SIGKILL in
-* the childNS
-*
-* Total Tests:
-*
-* Test Name: pidns04
-*
-* Test Assertion & Strategy:
-*
-* From main() clone a new child process with passing the clone_flag as
-* CLONE_NEWPID.
-* The container init, should not get killed by the SIGKILL inside the child NS.
-* Usage: <for command-line>
-* pidns04
-*
-* History:
-*
-* FLAG DATE NAME DESCRIPTION
-* 08/10/08 Veerendra C <vechandr@in.ibm.com> Verifies killing of cont init.
-*
-*******************************************************************************/
-#define _GNU_SOURCE 1
-#include <sys/wait.h>
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#define CLEANUP cleanup
-#include "pidns_helper.h"
-#include "test.h"
-
-#define INIT_PID 1
-#define CHILD_PID 1
-#define PARENT_PID 0
+/*\
+ * [Description]
+ *
+ * Clone a process with CLONE_NEWPID flag and check that child container does
+ * not get kill itself with SIGKILL.
+ */
-char *TCID = "pidns04";
-int TST_TOTAL = 1;
-int fd[2];
+#include <sys/wait.h>
+#include "tst_test.h"
+#include "lapi/sched.h"
-/*
- * child_fn1() - Inside container
-*/
-static int child_fn1(void *ttype)
+static void child_func(void)
{
- int exit_val;
- pid_t cpid, ppid;
- cpid = getpid();
- ppid = getppid();
- char mesg[] = "I was not killed !";
- /* Child process closes up read side of pipe */
- close(fd[0]);
+ pid_t cpid = tst_getpid();
+ pid_t ppid = getppid();
- /* Comparing the values to make sure pidns is created correctly */
- if ((cpid == CHILD_PID) && (ppid == PARENT_PID)) {
- printf("PIDNS test is running inside container\n");
- kill(INIT_PID, SIGKILL);
- /* Verifying whether the container init is not killed, "
- If so writing into the pipe created in the parent NS" */
+ TST_EXP_EQ_LI(cpid, 1);
+ TST_EXP_EQ_LI(ppid, 0);
- /* Send "mesg" through the write side of pipe */
- write(fd[1], mesg, (strlen(mesg) + 1));
- exit_val = 0;
- } else {
- printf("got unexpected result of cpid=%d ppid=%d\n",
- cpid, ppid);
- exit_val = 1;
- }
- exit(exit_val);
-}
+ tst_res(TINFO, "Trying to kill container from within container");
-static void setup(void)
-{
- tst_require_root();
- check_newpid();
+ SAFE_KILL(1, SIGKILL);
+
+ tst_res(TINFO, "Container is up and running");
}
-int main(void)
+static void run(void)
{
- int nbytes, status;
- char readbuffer[80];
-
- setup();
-
- pipe(fd);
- TEST(do_clone_unshare_test(T_CLONE, CLONE_NEWPID, child_fn1, NULL));
- if (TEST_RETURN == -1) {
- tst_brkm(TFAIL | TTERRNO, CLEANUP, "clone failed");
- } else if (wait(&status) == -1) {
- tst_brkm(TFAIL | TERRNO, CLEANUP, "wait failed");
+ const struct tst_clone_args args = {
+ .flags = CLONE_NEWPID,
+ .exit_signal = SIGCHLD,
+ };
+ pid_t pid;
+
+ pid = SAFE_CLONE(&args);
+ if (!pid) {
+ child_func();
+ return;
}
- /* Parent process closes up write side of pipe */
- close(fd[1]);
- /* Read in a string from the pipe */
- nbytes = read(fd[0], readbuffer, sizeof(readbuffer));
-
- if (0 <= nbytes) {
- tst_resm(TPASS, "Container init : %s", readbuffer);
- } else {
- tst_brkm(TFAIL, CLEANUP,
- "Container init is killed by SIGKILL !!!");
- }
-
- if (WIFEXITED(status) && WEXITSTATUS(status) != 0) {
- tst_resm(TFAIL, "Container init pid exited abnormally");
- } else if (WIFSIGNALED(status)) {
- tst_resm(TFAIL, "Container init pid got killed by signal %d",
- WTERMSIG(status));
- }
- CLEANUP();
-
- tst_exit();
-
+ tst_reap_children();
}
-static void cleanup(void)
-{
- close(fd[0]);
-}
+static struct tst_test test = {
+ .test_all = run,
+ .needs_root = 1,
+ .forks_child = 1,
+};
diff --git a/testcases/kernel/containers/pidns/pidns05.c b/testcases/kernel/containers/pidns/pidns05.c
index 79e146e36..0e7739aaa 100644
--- a/testcases/kernel/containers/pidns/pidns05.c
+++ b/testcases/kernel/containers/pidns/pidns05.c
@@ -1,256 +1,124 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
-* Copyright (c) International Business Machines Corp., 2007
-* 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
-*
-***************************************************************************
-*
-* Assertion:
-* a) Create a container.
-* b) Create many levels of child containers inside this container.
-* c) Now do kill -9 init , outside of the container.
-* d) This should kill all the child containers.
-* (containers created at the level below)
-*
-* Description:
-* 1. Parent process clone a process with flag CLONE_NEWPID
-* 2. The container will recursively loop and creates 4 more containers.
-* 3. All the container init's goes into sleep(), waiting to be terminated.
-* 4. The parent process will kill child[3] by passing SIGKILL
-* 5. Now parent process, verifies the child containers 4 & 5 are destroyed.
-* 6. If they are killed then
-* Test passed
-* else Test failed.
-*
-* Test Name: pidns05
-*
-* History:
-*
-* FLAG DATE NAME DESCRIPTION
-* 31/10/08 Veerendra C <vechandr@in.ibm.com> Verifies killing of NestedCont's
-*
-*******************************************************************************/
-#define _GNU_SOURCE 1
+ * Copyright (c) Veerendra C <vechandr@in.ibm.com>, 2008
+ * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * [Description]
+ *
+ * Clone a process with CLONE_NEWPID flag and create many levels of child
+ * containers. Then kill container init process from parent and check if all
+ * containers have been killed.
+ */
+
#include <sys/wait.h>
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include "pidns_helper.h"
-#include "test.h"
-#include "safe_macros.h"
+#include "tst_test.h"
+#include "lapi/sched.h"
-#define INIT_PID 1
-#define CINIT_PID 1
-#define PARENT_PID 0
#define MAX_DEPTH 5
-char *TCID = "pidns05";
-int TST_TOTAL = 1;
-int fd[2];
-
-int max_pid(void)
-{
- FILE *fp;
- int ret;
-
- fp = fopen("/proc/sys/kernel/pid_max", "r");
- if (fp != NULL) {
- fscanf(fp, "%d", &ret);
- fclose(fp);
- } else {
- tst_resm(TBROK, "Cannot open /proc/sys/kernel/pid_max");
- ret = -1;
- }
- return ret;
-}
+static struct tst_clone_args clone_args = {
+ .flags = CLONE_NEWPID,
+ .exit_signal = SIGCHLD
+};
+static pid_t pid_max;
-/* find_cinit_pids() iteratively finds the pid's having same PGID as its parent.
- * Input parameter - Accepts pointer to pid_t : To copy the pid's matching.
- * Returns - the number of pids matched.
-*/
-int find_cinit_pids(pid_t * pids)
+static void child_func(int *level)
{
- int next = 0, pid_max, i;
- pid_t parentpid, pgid, pgid2;
+ pid_t cpid, ppid;
- pid_max = max_pid();
- parentpid = getpid();
- pgid = getpgid(parentpid);
+ cpid = tst_getpid();
+ ppid = getppid();
- /* The loop breaks, when the loop counter reaches the parentpid value */
- for (i = parentpid + 1; i != parentpid; i++) {
- if (i > pid_max)
- i = 2;
+ TST_EXP_EQ_LI(cpid, 1);
+ TST_EXP_EQ_LI(ppid, 0);
- pgid2 = getpgid(i);
- if (pgid2 == pgid) {
- pids[next] = i;
- next++;
- }
+ if (*level >= MAX_DEPTH) {
+ TST_CHECKPOINT_WAKE(0);
+ return;
}
- return next;
-}
-
-/*
-* create_nested_container() Recursively create MAX_DEPTH nested containers
-*/
-int create_nested_container(void *vtest)
-{
- int exit_val;
- int ret, count, *level;
- pid_t cpid, ppid;
- cpid = getpid();
- ppid = getppid();
- char mesg[] = "Nested Containers are created";
- level = (int *)vtest;
- count = *level;
+ (*level)++;
- /* Child process closes up read side of pipe */
- close(fd[0]);
-
- /* Comparing the values to make sure pidns is created correctly */
- if (cpid != CINIT_PID || ppid != PARENT_PID) {
- printf("Got unexpected cpid and/or ppid (cpid=%d ppid=%d)\n",
- cpid, ppid);
- exit_val = 1;
- }
- if (count > 1) {
- count--;
- ret = do_clone_unshare_test(T_CLONE, CLONE_NEWPID,
- create_nested_container,
- (void *)&count);
- if (ret == -1) {
- printf("clone failed; errno = %d : %s\n",
- ret, strerror(ret));
- exit_val = 1;
- } else
- exit_val = 0;
- } else {
- /* Sending mesg, 'Nested containers created' through the pipe */
- write(fd[1], mesg, (strlen(mesg) + 1));
- exit_val = 0;
+ if (!SAFE_CLONE(&clone_args)) {
+ child_func(level);
+ return;
}
- close(fd[1]);
pause();
-
- return exit_val;
}
-void kill_nested_containers()
+static int find_cinit_pids(pid_t *pids)
{
- int orig_count, new_count, status = 0, i;
- pid_t pids[MAX_DEPTH];
- pid_t pids_new[MAX_DEPTH];
+ int pid;
+ int next = 0;
+ pid_t parentpid, pgid, pgid2;
- orig_count = find_cinit_pids(pids);
- kill(pids[MAX_DEPTH - 3], SIGKILL);
- sleep(1);
+ parentpid = tst_getpid();
+ pgid = SAFE_GETPGID(parentpid);
- /* After killing child container, getting the New PID list */
- new_count = find_cinit_pids(pids_new);
+ for (pid = 2; pid < pid_max; pid++) {
+ if (pid == parentpid)
+ continue;
- /* Verifying that the child containers were destroyed when parent is killed */
- if (orig_count - 2 != new_count)
- status = -1;
+ pgid2 = getpgid(pid);
- for (i = 0; i < new_count; i++) {
- if (pids[i] != pids_new[i])
- status = -1;
+ if (pgid2 == pgid) {
+ pids[next] = pid;
+ next++;
+ }
}
- if (status == 0)
- tst_resm(TPASS, "The number of containers killed are %d",
- orig_count - new_count);
- else
- tst_resm(TFAIL, "Failed to kill the sub-containers of "
- "the container %d", pids[MAX_DEPTH - 3]);
-
- /* Loops through the containers created to exit from sleep() */
- for (i = 0; i < MAX_DEPTH; i++) {
- kill(pids[i], SIGKILL);
- waitpid(pids[i], &status, 0);
- }
+ return next;
}
static void setup(void)
{
- tst_require_root();
- check_newpid();
+ SAFE_FILE_SCANF("/proc/sys/kernel/pid_max", "%d\n", &pid_max);
}
-int main(void)
+static void run(void)
{
- int ret, nbytes, status;
- char readbuffer[80];
- pid_t pid, pgid;
- int count = MAX_DEPTH;
-
- setup();
+ int i, status, children;
+ int level = 0;
+ pid_t pids_new[MAX_DEPTH];
+ pid_t pids[MAX_DEPTH];
+ pid_t pid;
- /*
- * XXX (garrcoop): why in the hell is this fork-wait written this way?
- * This doesn't add up with the pattern used for the rest of the tests,
- * so I'm pretty damn sure this test is written incorrectly.
- */
- pid = fork();
- if (pid == -1) {
- tst_brkm(TBROK | TERRNO, NULL, "fork failed");
- } else if (pid != 0) {
- /*
- * NOTE: use waitpid so that we know we're waiting for the
- * _top-level_ child instead of a spawned subcontainer.
- *
- * XXX (garrcoop): Might want to mask SIGCHLD in the top-level
- * child too, or not *shrugs*.
- */
- if (waitpid(pid, &status, 0) == -1) {
- perror("wait failed");
- }
- if (WIFEXITED(status))
- exit(WEXITSTATUS(status));
- else
- exit(status);
+ pid = SAFE_CLONE(&clone_args);
+ if (!pid) {
+ child_func(&level);
+ return;
}
- /* To make all the containers share the same PGID as its parent */
- setpgid(0, 0);
+ TST_CHECKPOINT_WAIT(0);
- pid = getpid();
- pgid = getpgid(pid);
- SAFE_PIPE(NULL, fd);
+ TST_EXP_POSITIVE(find_cinit_pids(pids));
- TEST(do_clone_unshare_test(T_CLONE, CLONE_NEWPID,
- create_nested_container, (void *)&count));
- if (TEST_RETURN == -1) {
- tst_brkm(TFAIL | TTERRNO, NULL, "clone failed");
- }
+ SAFE_KILL(pid, SIGKILL);
+ SAFE_WAITPID(0, &status, 0);
- close(fd[1]);
- /* Waiting for the MAX_DEPTH number of containers to be created */
- nbytes = read(fd[0], readbuffer, sizeof(readbuffer));
- close(fd[0]);
- if (nbytes > 0)
- tst_resm(TINFO, " %d %s", MAX_DEPTH, readbuffer);
- else
- tst_brkm(TFAIL, NULL, "unable to create %d containers",
- MAX_DEPTH);
+ children = find_cinit_pids(pids_new);
- /* Kill the container created */
- kill_nested_containers();
+ if (children > 0) {
+ tst_res(TFAIL, "%d children left after sending SIGKILL", children);
- tst_exit();
+ for (i = 0; i < MAX_DEPTH; i++) {
+ kill(pids[i], SIGKILL);
+ waitpid(pids[i], &status, 0);
+ }
+
+ return;
+ }
+
+ tst_res(TPASS, "No children left after sending SIGKILL to the first child");
}
+
+static struct tst_test test = {
+ .test_all = run,
+ .setup = setup,
+ .needs_root = 1,
+ .needs_checkpoints = 1,
+ .forks_child = 1,
+};
diff --git a/testcases/kernel/containers/pidns/pidns06.c b/testcases/kernel/containers/pidns/pidns06.c
index d6623941a..c85a875e4 100644
--- a/testcases/kernel/containers/pidns/pidns06.c
+++ b/testcases/kernel/containers/pidns/pidns06.c
@@ -1,133 +1,48 @@
+// SPDX-License-Identifier: GPL-2.0
/*
-* 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
-
-*************************************************************************
-* Description:
-* Testcase tries killing of the parent namespace pid by the container-init.
-* It also tries killing of non-existent PID, by the container-init.
-* Returns Success if Unable to kill, and proper error number is set.
-* else Returns Failure
-*
-* Steps:
-* 1. Parent process clone a process with flag CLONE_NEWPID
-* 2. The pid of the parent namespace is passed to the container.
-* 3. Container receieves the PID and passes SIGKILL to this PID.
-* 4. If kill() is unsuccessful and the errno is set to 'No Such process'
-* then sets PASS
-* else,
-* sets FAIL
-* 5. It also verifies by passing SIGKILL to FAKE_PID
-* 6. If kill() is unsuccessful and the errno is set to 'No Such process'
-* then sets PASS
-* else,
-* sets FAIL
-*
-*******************************************************************************/
-#define _GNU_SOURCE 1
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/wait.h>
-#include <assert.h>
-#include <unistd.h>
-#include <errno.h>
-#include <signal.h>
-#include "pidns_helper.h"
-#include "test.h"
+ * Copyright (C) International Business Machines Corp., 2008
+ * Copyright (C) 2022 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+ */
-#define CINIT_PID 1
-#define PARENT_PID 0
-#define FAKE_PID -1
+/*\
+ * [Description]
+ *
+ * Clone a process with CLONE_NEWPID flag and check that parent process can't
+ * be killed from child namespace.
+ */
-char *TCID = "pidns06";
-int TST_TOTAL = 1;
+#include "tst_test.h"
+#include "lapi/sched.h"
-/*
- * kill_pid_in_childfun()
- * Cont-init tries to kill the parent-process using parent's global Pid.
- * Also checks passing SIGKILL to non existent PID in the container.
- */
-static int kill_pid_in_childfun(void *vtest)
+static void child_func(int pid)
{
- int cpid, ppid, *par_pid;
- int ret = 0;
- cpid = getpid();
- ppid = getppid();
- par_pid = (int *)vtest;
+ pid_t cpid = tst_getpid();
+ pid_t ppid = getppid();
- /* Checking the values to make sure pidns is created correctly */
- if (cpid != CINIT_PID || ppid != PARENT_PID) {
- printf("Unexpected result for Container: init "
- "pid=%d ppid=%d\n", cpid, ppid);
- exit(1);
- }
+ TST_EXP_EQ_LI(cpid, 1);
+ TST_EXP_EQ_LI(ppid, 0);
- /*
- * While trying kill() of the pid of the parent namespace..
- * Check to see if the errno was set to the expected, value of 3 : ESRCH
- */
- ret = kill(*par_pid, SIGKILL);
- if (ret == -1 && errno == ESRCH) {
- printf("Container: killing parent pid=%d failed as expected "
- "with ESRCH\n", *par_pid);
- } else {
- printf("Container: killing parent pid=%d, didn't fail as "
- "expected with ESRCH (%d) and a return value of -1. Got "
- "%d (\"%s\") and a return value of %d instead.\n",
- *par_pid, ESRCH, errno, strerror(errno), ret);
- exit(1);
- }
- /*
- * While killing non-existent pid in the container,
- * Check to see if the errno was set to the expected, value of 3 : ESRCH
- */
- ret = kill(FAKE_PID, SIGKILL);
- if (ret == -1 && errno == ESRCH) {
- printf("Container: killing non-existent pid failed as expected "
- "with ESRCH\n");
- } else {
- printf("Container: killing non-existent pid, didn't fail as "
- "expected with ESRCH (%d) and a return value of -1. Got "
- "%d (\"%s\") and a return value of %d instead.\n",
- ESRCH, errno, strerror(errno), ret);
- exit(1);
- }
+ tst_res(TINFO, "Trying to kill parent from within container");
- exit(0);
+ TST_EXP_FAIL(kill(pid, SIGKILL), ESRCH);
}
-static void setup(void)
+static void run(void)
{
- tst_require_root();
- check_newpid();
-}
-
-int main(void)
-{
- int status;
-
- setup();
-
+ const struct tst_clone_args args = {
+ .flags = CLONE_NEWPID,
+ .exit_signal = SIGCHLD,
+ };
pid_t pid = getpid();
- tst_resm(TINFO, "Parent: Passing the pid of the process %d", pid);
- TEST(do_clone_unshare_test(T_CLONE, CLONE_NEWPID, kill_pid_in_childfun,
- (void *)&pid));
- if (TEST_RETURN == -1) {
- tst_brkm(TFAIL | TTERRNO, NULL, "clone failed");
- } else if (wait(&status) == -1) {
- tst_brkm(TFAIL | TERRNO, NULL, "wait failed");
+ if (!SAFE_CLONE(&args)) {
+ child_func(pid);
+ return;
}
-
- tst_exit();
}
+
+static struct tst_test test = {
+ .test_all = run,
+ .needs_root = 1,
+ .forks_child = 1,
+};
diff --git a/testcases/kernel/containers/pidns/pidns10.c b/testcases/kernel/containers/pidns/pidns10.c
index b38b9fd18..c2a9094b6 100644
--- a/testcases/kernel/containers/pidns/pidns10.c
+++ b/testcases/kernel/containers/pidns/pidns10.c
@@ -1,112 +1,47 @@
+// SPDX-License-Identifier: GPL-2.0
/*
-* Copyright (c) International Business Machines Corp., 2007
-* 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: pidns10.c
-* *
-* * Description:
-* * The pidns10.c testcase verifies inside the container, if kill(-1, signal)
-* * fails with ESRCH when there are no processes in container.
-* *
-* * Test Assertion & Strategy:
-* * Create a PID namespace container.
-* * Invoke kill(-1, SIGUSR1) inside container and check return code and error.
-* * kill() should have failed;except swapper & init, no process is inside.
-* *
-* * Usage: <for command-line>
-* * pidns10
-* *
-* * History:
-* * DATE NAME DESCRIPTION
-* * 13/11/08 Gowrishankar M Creation of this test.
-* * <gowrishankar.m@in.ibm.com>
-*
-******************************************************************************/
-#define _GNU_SOURCE 1
-#include <sys/wait.h>
-#include <sys/types.h>
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <errno.h>
-#include "pidns_helper.h"
-#include "test.h"
-
-char *TCID = "pidns10";
-int TST_TOTAL = 1;
+ * Copyright (C) International Business Machines Corp., 2008
+ * Copyright (C) 2022 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+ */
-int child_fn(void *);
+/*\
+ * [Description]
+ *
+ * Clone a process with CLONE_NEWPID flag and check that killing subprocesses
+ * from child namespace will raise ESRCH error.
+ */
-#define CHILD_PID 1
-#define PARENT_PID 0
+#include "tst_test.h"
+#include "lapi/sched.h"
-/*
- * child_fn() - Inside container
- */
-int child_fn(void *arg)
+static void child_func(void)
{
- int exit_val, ret;
- pid_t pid, ppid;
+ pid_t cpid = tst_getpid();
+ pid_t ppid = getppid();
- /* Set process id and parent pid */
- pid = getpid();
- ppid = getppid();
- if (pid != CHILD_PID || ppid != PARENT_PID) {
- printf("cinit: pidns was not created.\n");
- return 1;
- }
+ TST_EXP_EQ_LI(cpid, 1);
+ TST_EXP_EQ_LI(ppid, 0);
- if ((ret = kill(-1, SIGUSR1)) == -1 && errno == ESRCH) {
- printf("cinit: kill(-1, sig) failed with -1 / ESRCH as "
- "expected\n");
- exit_val = 0;
- } else {
- printf("cinit: kill(-1, sig) didn't fail with -1 / ESRCH "
- "(%d); failed with %d / %d instead", ESRCH, ret, errno);
- exit_val = 1;
- }
- exit(exit_val);
-}
+ tst_res(TINFO, "Trying to kill all subprocesses from within container");
-static void setup(void)
-{
- tst_require_root();
- check_newpid();
+ TST_EXP_FAIL(kill(-1, SIGKILL), ESRCH);
}
-int main(void)
+static void run(void)
{
- int status;
- pid_t pid;
-
- setup();
-
- pid = getpid();
-
- /* Container creation on PID namespace */
- TEST(do_clone_unshare_test(T_CLONE, CLONE_NEWPID, child_fn, NULL));
- if (TEST_RETURN == -1) {
- tst_brkm(TBROK | TTERRNO, NULL, "clone failed");
+ const struct tst_clone_args args = {
+ .flags = CLONE_NEWPID,
+ .exit_signal = SIGCHLD,
+ };
+
+ if (!SAFE_CLONE(&args)) {
+ child_func();
+ return;
}
-
- sleep(1);
- if (wait(&status) < 0)
- tst_resm(TWARN, "parent: waitpid() failed.");
-
- if (WIFEXITED(status) && WEXITSTATUS(status) != 0)
- tst_resm(TBROK, "container was terminated abnormally");
-
- tst_exit();
}
+
+static struct tst_test test = {
+ .test_all = run,
+ .needs_root = 1,
+ .forks_child = 1,
+};
diff --git a/testcases/kernel/containers/pidns/pidns12.c b/testcases/kernel/containers/pidns/pidns12.c
index fb1ec90ca..1811dbc36 100644
--- a/testcases/kernel/containers/pidns/pidns12.c
+++ b/testcases/kernel/containers/pidns/pidns12.c
@@ -25,11 +25,11 @@ static void child_signal_handler(LTP_ATTRIBUTE_UNUSED int sig, siginfo_t *si, LT
sig_pid = si->si_pid;
}
-static int child_func(LTP_ATTRIBUTE_UNUSED void *arg)
+static void child_func(void)
{
struct sigaction sa;
- TST_EXP_EQ_LI(getpid(), 1);
+ TST_EXP_EQ_LI(tst_getpid(), 1);
TST_EXP_EQ_LI(getppid(), 0);
sa.sa_flags = SA_SIGINFO;
@@ -41,21 +41,25 @@ static int child_func(LTP_ATTRIBUTE_UNUSED void *arg)
TST_CHECKPOINT_WAKE_AND_WAIT(0);
TST_EXP_EQ_LI(sig_pid, 0);
-
- return 0;
}
static void run(void)
{
- int ret;
-
- ret = ltp_clone_quick(CLONE_NEWPID | SIGCHLD, child_func, NULL);
- if (ret < 0)
- tst_brk(TBROK | TERRNO, "clone failed");
+ const struct tst_clone_args args = {
+ .flags = CLONE_NEWPID,
+ .exit_signal = SIGCHLD,
+ };
+ int pid;
+
+ pid = SAFE_CLONE(&args);
+ if (!pid) {
+ child_func();
+ return;
+ }
TST_CHECKPOINT_WAIT(0);
- SAFE_KILL(ret, SIGUSR1);
+ SAFE_KILL(pid, SIGUSR1);
TST_CHECKPOINT_WAKE(0);
}
@@ -63,5 +67,10 @@ static void run(void)
static struct tst_test test = {
.test_all = run,
.needs_root = 1,
+ .forks_child = 1,
.needs_checkpoints = 1,
+ .needs_kconfigs = (const char *[]) {
+ "CONFIG_PID_NS",
+ NULL,
+ },
};
diff --git a/testcases/kernel/containers/pidns/pidns13.c b/testcases/kernel/containers/pidns/pidns13.c
index 6a155027c..65fcc4443 100644
--- a/testcases/kernel/containers/pidns/pidns13.c
+++ b/testcases/kernel/containers/pidns/pidns13.c
@@ -42,7 +42,7 @@ static void child_signal_handler(int sig, siginfo_t *si,
void *unused LTP_ATTRIBUTE_UNUSED)
{
tst_res(TWARN, "cinit(pid %d): Caught signal! sig=%d, si_fd=%d, si_code=%d",
- getpid(), sig, si->si_fd, si->si_code);
+ tst_getpid(), sig, si->si_fd, si->si_code);
}
static void child_fn(unsigned int cinit_no)
@@ -54,7 +54,7 @@ static void child_fn(unsigned int cinit_no)
pid_t pid, ppid;
int flags;
- pid = tst_syscall(__NR_getpid);
+ pid = tst_getpid();
ppid = getppid();
if (pid != CHILD_PID || ppid != PARENT_PID)
tst_brk(TBROK, "cinit%u: pidns not created.", cinit_no);
@@ -104,7 +104,10 @@ static void child_fn(unsigned int cinit_no)
static void run(void)
{
- const struct tst_clone_args cargs = { CLONE_NEWPID, SIGCHLD };
+ const struct tst_clone_args cargs = {
+ .flags = CLONE_NEWPID,
+ .exit_signal = SIGCHLD,
+ };
SAFE_PIPE(pipe_fd);
diff --git a/testcases/kernel/containers/pidns/pidns16.c b/testcases/kernel/containers/pidns/pidns16.c
index 2ee61065a..313b0a097 100644
--- a/testcases/kernel/containers/pidns/pidns16.c
+++ b/testcases/kernel/containers/pidns/pidns16.c
@@ -1,157 +1,87 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
-* Copyright (c) International Business Machines Corp., 2007
-* 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 Assertion.
-* *----------------
-* * kill -USR1 container_init
-* * - from the parent process and also inside a container
-* * - Where init has defined a custom handler for USR1
-* * - Should call the handler and
-* * - Verify whether the signal handler is called from the proper process.
-* *
-* * Description:
-* * Create PID namespace container.
-* * Container init defines the handler for SIGUSR1 and waits indefinetly.
-* * Parent sends SIGUSR1 to container init.
-* * The signal handler is handled and the cont-init resumes normally.
-* * From the container, again the signal SIGUSR1 is sent.
-* * In the sig-handler check if it's invoked from correct pid(parent/container)
-* * If cont-init wakes up properly -
-* * it will return expected value at exit which is verified at the end.
-* *
-* * History:
-* * DATE NAME DESCRIPTION
-* * 04/11/08 Veerendra C <vechandr@in.ibm.com> Verifying cont init kill -USR1
-*
-*******************************************************************************/
-#include "config.h"
+ * Copyright (c) International Business Machines Corp., 2007
+ * 04/11/08 Veerendra C <vechandr@in.ibm.com>
+ * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * [Description]
+ *
+ * Clone a process with CLONE_NEWPID flag and verifies that siginfo->si_pid is
+ * set to 0 if sender (parent process) sent the signal. Then send signal from
+ * container itself and check if siginfo->si_pid is set to 1.
+ */
#define _GNU_SOURCE 1
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/wait.h>
-#include <sys/types.h>
#include <signal.h>
-#include <unistd.h>
-#include "pidns_helper.h"
-#include "test.h"
-
-#define CHILD_PID 1
-#define PARENT_PID 0
+#include "tst_test.h"
+#include "lapi/sched.h"
-char *TCID = "pidns16";
-int TST_TOTAL = 3;
+static volatile int signal_pid;
-void child_signal_handler(int sig, siginfo_t * si, void *unused)
+static void child_signal_handler(LTP_ATTRIBUTE_UNUSED int sig, siginfo_t *si, LTP_ATTRIBUTE_UNUSED void *unused)
{
- static int c = 1;
- pid_t expected_pid;
-
- /* Verifying from which process the signal handler is signalled */
-
- switch (c) {
- case 1:
- expected_pid = PARENT_PID;
- break;
- case 2:
- expected_pid = CHILD_PID;
- break;
- default:
- tst_resm(TBROK, "child should NOT be signalled 3+ times");
- return;
- }
-
- if (si->si_pid == expected_pid)
- tst_resm(TPASS, "child is signalled from expected pid %d",
- expected_pid);
- else
- tst_resm(TFAIL, "child is signalled from unexpected pid %d,"
- " expecting pid %d", si->si_pid, expected_pid);
-
- c++;
+ signal_pid = si->si_pid;
}
-/*
- * child_fn() - Inside container
- */
-int child_fn(void *ttype)
+static void child_func(void)
{
struct sigaction sa;
- pid_t pid, ppid;
+ pid_t cpid, ppid;
- /* Set process id and parent pid */
- pid = getpid();
+ cpid = tst_getpid();
ppid = getppid();
- if ((pid != CHILD_PID) || (ppid != PARENT_PID))
- tst_resm(TBROK, "pidns is not created.");
+ TST_EXP_EQ_LI(cpid, 1);
+ TST_EXP_EQ_LI(ppid, 0);
+
+ tst_res(TINFO, "Catching SIGUSR1 signal");
- /* Set signal handler for SIGUSR1, also mask other signals */
sa.sa_flags = SA_SIGINFO;
- sigemptyset(&sa.sa_mask);
+ SAFE_SIGFILLSET(&sa.sa_mask);
sa.sa_sigaction = child_signal_handler;
- if (sigaction(SIGUSR1, &sa, NULL) == -1)
- tst_resm(TBROK, "%d: sigaction() failed", pid);
-
- pause();
- tst_resm(TINFO, "Container: Resumed after receiving SIGUSR1 "
- "from parentNS ");
- if (kill(pid, SIGUSR1) != 0) {
- tst_resm(TFAIL, "kill(SIGUSR1) fails.");
- }
- tst_resm(TINFO, "Container: Resumed after sending SIGUSR1 "
- "from container itself");
- _exit(10);
-}
+ SAFE_SIGACTION(SIGUSR1, &sa, NULL);
-static void setup(void)
-{
- tst_require_root();
- check_newpid();
+ TST_CHECKPOINT_WAKE_AND_WAIT(0);
+
+ TST_EXP_EQ_LI(signal_pid, 0);
+
+ tst_res(TINFO, "Sending SIGUSR1 from container itself");
+
+ SAFE_KILL(cpid, SIGUSR1);
+
+ TST_EXP_EQ_LI(signal_pid, 1);
}
-/***********************************************************************
-* M A I N
-***********************************************************************/
-int main()
+static void run(void)
{
- int status;
- pid_t cpid;
-
- setup();
+ const struct tst_clone_args args = {
+ .flags = CLONE_NEWPID,
+ .exit_signal = SIGCHLD,
+ };
+ pid_t pid;
- cpid = ltp_clone_quick(CLONE_NEWPID | SIGCHLD, child_fn, NULL);
+ signal_pid = -1;
- if (cpid < 0) {
- tst_resm(TBROK, "clone() failed.");
+ pid = SAFE_CLONE(&args);
+ if (!pid) {
+ child_func();
+ return;
}
- sleep(1);
- if (kill(cpid, SIGUSR1) != 0) {
- tst_resm(TFAIL, "kill(SIGUSR1) fails.");
- }
- sleep(1);
- if (waitpid(cpid, &status, 0) < 0)
- tst_resm(TWARN, "waitpid() failed.");
-
- if ((WIFEXITED(status)) && (WEXITSTATUS(status) == 10))
- tst_resm(TPASS, "container init continued successfuly, "
- "after handling signal -USR1");
- else
- tst_resm(TFAIL, "c-init failed to continue after "
- "passing kill -USR1");
- tst_exit();
+ TST_CHECKPOINT_WAIT(0);
+
+ tst_res(TINFO, "Sending SIGUSR1 from parent");
+
+ SAFE_KILL(pid, SIGUSR1);
+
+ TST_CHECKPOINT_WAKE(0);
}
+
+static struct tst_test test = {
+ .test_all = run,
+ .needs_root = 1,
+ .needs_checkpoints = 1,
+ .forks_child = 1,
+};
diff --git a/testcases/kernel/containers/pidns/pidns17.c b/testcases/kernel/containers/pidns/pidns17.c
index cf0c5826f..4633ec14b 100644
--- a/testcases/kernel/containers/pidns/pidns17.c
+++ b/testcases/kernel/containers/pidns/pidns17.c
@@ -1,162 +1,72 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
-* Copyright (c) International Business Machines Corp., 2007
-* 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: pidns17.c
-* *
-* * Description:
-* * The pidns17.c testcase verifies inside the container, if kill(-1, SIGUSR1)
-* * terminates all children running inside.
-* *
-* * Test Assertion & Strategy:
-* * Create a PID namespace container.
-* * Spawn many children inside it.
-* * Invoke kill(-1, SIGUSR1) inside container and check if it terminates
-* * all children.
-* *
-* * Usage: <for command-line>
-* * pidns17
-* *
-* * History:
-* * DATE NAME DESCRIPTION
-* * 13/11/08 Gowrishankar M Creation of this test.
-* * <gowrishankar.m@in.ibm.com>
-*
-******************************************************************************/
-#define _GNU_SOURCE 1
-#include <sys/wait.h>
-#include <sys/types.h>
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <errno.h>
-#include "pidns_helper.h"
-#include "test.h"
+ * Copyright (c) International Business Machines Corp., 2007
+ * 13/11/08 Gowrishankar M <gowrishankar.m@in.ibm.com>
+ * Copyright (C) 2022 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+ */
-char *TCID = "pidns17";
-int TST_TOTAL = 1;
+/*\
+ * [Description]
+ *
+ * Clone a process with CLONE_NEWPID flag and spawn many children inside the
+ * container. Then terminate all children and check if they were signaled.
+ */
-int child_fn(void *);
+#include <sys/wait.h>
+#include "tst_test.h"
+#include "lapi/sched.h"
-#define CHILD_PID 1
-#define PARENT_PID 0
+#define CHILDREN_NUM 10
-/*
- * child_fn() - Inside container
- */
-int child_fn(void *arg)
+static void child_func(void)
{
- int children[10], exit_val, i, status;
- pid_t pid, ppid;
+ int children[CHILDREN_NUM], status;
+ unsigned int i;
+ pid_t cpid, ppid;
- /* Set process id and parent pid */
- pid = getpid();
+ cpid = tst_getpid();
ppid = getppid();
- if (pid != CHILD_PID || ppid != PARENT_PID) {
- printf("cinit: pidns was not created\n");
- exit(1);
- }
- exit_val = 0;
+ TST_EXP_EQ_LI(cpid, 1);
+ TST_EXP_EQ_LI(ppid, 0);
+
+ tst_res(TINFO, "Spawning %d children", CHILDREN_NUM);
- /* Spawn many children */
- for (i = 0; i < ARRAY_SIZE(children); i++) {
- switch ((children[i] = fork())) {
- case -1:
- perror("fork failed");
- exit_val = 1;
- break;
- case 0:
+ for (i = 0; i < CHILDREN_NUM; i++) {
+ children[i] = SAFE_FORK();
+ if (!children[i]) {
pause();
- /* XXX (garrcoop): why exit with an exit code of 2? */
- exit(2);
- break;
- default:
- /* fork succeeded. */
- break;
+ return;
}
}
- /* wait for last child to get scheduled */
- sleep(1);
- if (kill(-1, SIGUSR1) == -1) {
- perror("cinit: kill(-1, SIGUSR1) failed");
- exit_val = 1;
- }
+ tst_res(TINFO, "Terminate children with SIGUSR1");
- for (i = 0; i < ARRAY_SIZE(children); i++) {
- if (waitpid(children[i], &status, 0) == -1) {
- perror("cinit: waitpid failed");
- kill(children[i], SIGTERM);
- waitpid(children[i], &status, 0);
- exit_val = 1;
- }
- if (!(WIFSIGNALED(status) || WTERMSIG(status) == SIGUSR1)) {
- /*
- * XXX (garrcoop): this status reporting is overly
- * noisy. Someone obviously needs to read the
- * constraints documented in wait(2) a bit more
- * closely -- in particular the relationship between
- * WIFEXITED and WEXITSTATUS, and WIFSIGNALED and
- * WTERMSIG.
- */
- printf("cinit: found a child alive still "
- "%d exit: %d, %d, signal %d, %d", i,
- WIFEXITED(status), WEXITSTATUS(status),
- WIFSIGNALED(status), WTERMSIG(status));
- exit_val = 1;
- }
- }
- if (exit_val == 0)
- printf("cinit: all children have terminated.\n");
+ SAFE_KILL(-1, SIGUSR1);
- exit(exit_val);
-}
+ for (i = 0; i < CHILDREN_NUM; i++) {
+ SAFE_WAITPID(children[i], &status, 0);
-static void setup(void)
-{
- tst_require_root();
- check_newpid();
+ TST_EXP_EQ_LI(WIFSIGNALED(status), 1);
+ TST_EXP_EQ_LI(WTERMSIG(status), SIGUSR1);
+ }
}
-int main(void)
+static void run(void)
{
- int status;
- pid_t pid;
-
- setup();
-
- pid = getpid();
-
- /* Container creation on PID namespace */
- TEST(do_clone_unshare_test(T_CLONE, CLONE_NEWPID, child_fn, NULL));
- if (TEST_RETURN == -1) {
- tst_brkm(TBROK | TTERRNO, NULL, "clone failed");
+ const struct tst_clone_args args = {
+ .flags = CLONE_NEWPID,
+ .exit_signal = SIGCHLD,
+ };
+
+ if (!SAFE_CLONE(&args)) {
+ child_func();
+ return;
}
-
- sleep(1);
- if (wait(&status) == -1)
- tst_resm(TFAIL, "waitpid failed");
-
- if (WIFEXITED(status) && WEXITSTATUS(status) != 0)
- tst_resm(TFAIL, "container exited abnormally");
- else if (WIFSIGNALED(status))
- tst_resm(TFAIL,
- "container was signaled with signal = %d",
- WTERMSIG(status));
-
- tst_exit();
-
}
+
+static struct tst_test test = {
+ .test_all = run,
+ .needs_root = 1,
+ .forks_child = 1,
+};
diff --git a/testcases/kernel/containers/pidns/pidns20.c b/testcases/kernel/containers/pidns/pidns20.c
index 9f369699a..914820865 100644
--- a/testcases/kernel/containers/pidns/pidns20.c
+++ b/testcases/kernel/containers/pidns/pidns20.c
@@ -26,18 +26,18 @@ static void child_signal_handler(LTP_ATTRIBUTE_UNUSED int sig, siginfo_t *si, LT
signals++;
}
-static int child_func(LTP_ATTRIBUTE_UNUSED void *arg)
+static void child_func(void)
{
struct sigaction sa;
sigset_t newset;
pid_t cpid, ppid;
- cpid = getpid();
+ cpid = tst_getpid();
ppid = getppid();
if (cpid != 1 || ppid != 0) {
tst_res(TFAIL, "Got unexpected result of cpid=%d ppid=%d", cpid, ppid);
- return 0;
+ return;
}
SAFE_SIGEMPTYSET(&newset);
@@ -56,30 +56,34 @@ static int child_func(LTP_ATTRIBUTE_UNUSED void *arg)
if (signals != 1) {
tst_res(TFAIL, "Received %d signals", signals);
- return 0;
+ return;
}
if (last_signo != SIGUSR1) {
tst_res(TFAIL, "Received %s signal", tst_strsig(last_signo));
- return 0;
+ return;
}
tst_res(TPASS, "Received SIGUSR1 signal after unblock");
-
- return 0;
}
static void run(void)
{
- int ret;
-
- ret = ltp_clone_quick(CLONE_NEWPID | SIGCHLD, child_func, NULL);
- if (ret < 0)
- tst_brk(TBROK | TERRNO, "clone failed");
+ const struct tst_clone_args args = {
+ .flags = CLONE_NEWPID,
+ .exit_signal = SIGCHLD,
+ };
+ int pid;
+
+ pid = SAFE_CLONE(&args);
+ if (!pid) {
+ child_func();
+ return;
+ }
TST_CHECKPOINT_WAIT(0);
- SAFE_KILL(ret, SIGUSR1);
+ SAFE_KILL(pid, SIGUSR1);
TST_CHECKPOINT_WAKE(0);
}
@@ -87,5 +91,10 @@ static void run(void)
static struct tst_test test = {
.test_all = run,
.needs_root = 1,
+ .forks_child = 1,
.needs_checkpoints = 1,
+ .needs_kconfigs = (const char *[]) {
+ "CONFIG_PID_NS",
+ NULL,
+ },
};
diff --git a/testcases/kernel/containers/pidns/pidns30.c b/testcases/kernel/containers/pidns/pidns30.c
index c8b0806c0..4a8bc5e2b 100644
--- a/testcases/kernel/containers/pidns/pidns30.c
+++ b/testcases/kernel/containers/pidns/pidns30.c
@@ -1,296 +1,121 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
-* Copyright (c) Bull S.A.S. 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
-*
-***************************************************************************
-* File: pidns30.c
-*
-* Description:
-* This testcase checks if the si_pid is correctly set when a process
-* that has registered for notification on a posix mqueue is in a
-* descendant namespace wrt the process that sends a message to that posix
-* mqueue.
-*
-* Test Assertion & Strategy:
-* Parent Child
-* --------------------------------------------------------------------------
-* Create a POSIX mqueue.
-* Create a PID namespace container.
-* Open that mqueue for reading
-* Register for notification when a
-* message arrives in that mqueue
-* Install a handler for SIGUSR1.
-* Write something to the mqueue.
-* Inside the handler, check that
-* si_pid is set to 0
-*
-* Usage: <for command-line>
-* pidns30
-*
-* History:
-* DATE NAME DESCRIPTION
-* 01/12/08 Nadia Derbey Creation of this test.
-* <Nadia.Derbey@bull.net>
-*
-******************************************************************************/
-#define _GNU_SOURCE 1
-#include <sys/wait.h>
-#include <sys/types.h>
-#include <signal.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <mqueue.h>
-#include "lapi/syscalls.h"
-#include "pidns_helper.h"
-#include "test.h"
-
-char *TCID = "pidns30";
-int TST_TOTAL = 1;
-
-char *mqname = "mq1";
-int result = TFAIL;
-
-int father_to_child[2];
-int child_to_father[2];
-
-#define CHILD_PID 1
-#define PARENT_PID 0
+ * Copyright (c) Bull S.A.S. 2008
+ * 01/12/08 Nadia Derbey <Nadia.Derbey@bull.net>
+ * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+ */
-#define MSG "HOW ARE YOU"
-#define MSG_PRIO 1
+/*\
+ * [Description]
+ *
+ * Clone a process with CLONE_NEWPID flag, register notification on a posix
+ * mqueue and send a mqueue message from the parent. Then check if signal
+ * notification contains si_pid of the parent.
+ */
-#define NO_STEP -1
-#define F_STEP_0 0x00
-#define F_STEP_1 0x01
-#define F_STEP_2 0x02
-#define F_STEP_3 0x03
-#define C_STEP_0 0x10
-#define C_STEP_1 0x11
-#define C_STEP_2 0x12
+#define _GNU_SOURCE
+#include <signal.h>
+#include <mqueue.h>
+#include "tst_test.h"
+#include "tst_safe_posix_ipc.h"
+#include "lapi/sched.h"
-mqd_t rc = -1;
-mqd_t mqd = -1;
+#define MQNAME "/LTP_PIDNS30_MQ"
-static void remove_pipe(int *fd)
-{
- close(fd[0]);
- close(fd[1]);
-}
+static mqd_t mqd = -1;
+static siginfo_t info;
+static volatile int received;
static void remove_mqueue(mqd_t mqd)
{
- mq_close(mqd);
- tst_syscall(__NR_mq_unlink, mqname);
-}
+ if (mqd != -1)
+ SAFE_MQ_CLOSE(mqd);
-static void cleanup(void)
-{
- if (mqd != -1) {
- remove_mqueue(mqd);
- }
- if (rc != -1) {
- remove_mqueue(rc);
- }
- remove_pipe(father_to_child);
- remove_pipe(child_to_father);
+ mq_unlink(MQNAME);
}
-static void cleanup_child(void)
+static void child_signal_handler(LTP_ATTRIBUTE_UNUSED int sig, siginfo_t *si, LTP_ATTRIBUTE_UNUSED void *unused)
{
- if (mqd != -1) {
- tst_syscall(__NR_mq_notify, mqd, NULL);
- }
- cleanup();
+ received = 1;
+ memcpy(&info, si, sizeof(info));
}
-/*
- * child_signal_handler() - to handle SIGUSR1
- *
- * XXX (garrcoop): add calls to cleanup_child() -- or should this be handled
- * from the libltp signal handler?
- */
-static void child_signal_handler(int sig, siginfo_t * si, void *unused)
+static void child_func(void)
{
- char buf[256];
- struct mq_attr attr;
-
- if (si->si_signo != SIGUSR1) {
- printf("received signal = %d unexpectedly\n", si->si_signo);
- return;
- }
-
- if (si->si_code != SI_MESGQ) {
- printf("expected signal code SI_MESGQ; got %d instead\n",
- si->si_code);
- return;
- }
-
- if (si->si_pid) {
- printf("expected signal originator PID = 0; got %d instead\n",
- si->si_pid);
- return;
- } else {
- printf("signal originator PID = 0\n");
- result = TPASS;
- }
-
- /*
- * Now read the message - Be silent on errors since this is not the
- * test purpose.
- */
- rc = mq_getattr(si->si_int, &attr);
- if (rc != -1)
- mq_receive(si->si_int, buf, attr.mq_msgsize, NULL);
-}
-
-/*
- * child_fn() - Inside container
- *
- * XXX (garrcoop): add more calls to cleanup_child()?
- */
-int child_fn(void *arg)
-{
- pid_t pid, ppid;
+ pid_t cpid, ppid;
struct sigaction sa;
struct sigevent notif;
- char buf[5];
+ mqd_t mqd_child;
- /* Set process id and parent pid */
- pid = getpid();
+ cpid = tst_getpid();
ppid = getppid();
- if (pid != CHILD_PID || ppid != PARENT_PID) {
- printf("pidns was not created\n");
- return 1;
- }
-
- /* Close the appropriate end of each pipe */
- close(child_to_father[0]);
- close(father_to_child[1]);
+ TST_EXP_EQ_LI(cpid, 1);
+ TST_EXP_EQ_LI(ppid, 0);
- while (read(father_to_child[0], buf, 1) != 1)
- sleep(1);
+ TST_CHECKPOINT_WAIT(0);
- mqd = tst_syscall(__NR_mq_open, mqname, O_RDONLY, 0, NULL);
- if (mqd == -1) {
- perror("mq_open failed");
- return 1;
- } else
- printf("mq_open succeeded\n");
+ tst_res(TINFO, "Register notification on posix mqueue");
- /* Register for notification on message arrival */
+ mqd_child = SAFE_MQ_OPEN(MQNAME, O_RDONLY, 0, NULL);
notif.sigev_notify = SIGEV_SIGNAL;
notif.sigev_signo = SIGUSR1;
- notif.sigev_value.sival_int = mqd;
- if (tst_syscall(__NR_mq_notify, mqd, &notif) == -1) {
- perror("mq_notify failed");
- return 1;
- } else
- printf("successfully registered for notification\n");
+ notif.sigev_value.sival_int = mqd_child;
+
+ SAFE_MQ_NOTIFY(mqd_child, &notif);
- /* Define handler for SIGUSR1 */
sa.sa_flags = SA_SIGINFO;
- sigemptyset(&sa.sa_mask);
+ SAFE_SIGEMPTYSET(&sa.sa_mask);
sa.sa_sigaction = child_signal_handler;
- if (sigaction(SIGUSR1, &sa, NULL) == -1) {
- perror("sigaction failed");
- return 1;
- } else
- printf("successfully registered handler for SIGUSR1\n");
-
- /* Ask parent to send a message to the mqueue */
- if (write(child_to_father[1], "c:ok", 5) != 5) {
- perror("write failed");
- return 1;
- }
+ SAFE_SIGACTION(SIGUSR1, &sa, NULL);
- sleep(3);
+ TST_CHECKPOINT_WAKE_AND_WAIT(0);
- /* Has parent sent a message? */
- read(father_to_child[0], buf, 5);
- if (strcmp(buf, "f:ok") != 0) {
- printf("parent did not send the message!\n");
- return 1;
- }
- printf("parent is done - cleaning up\n");
-
- cleanup_child();
+ if (received)
+ tst_res(TPASS, "Signal notification has been received");
+ else
+ tst_res(TFAIL, "Signal notification has not been received");
- exit(0);
+ TST_EXP_EQ_LI(info.si_signo, SIGUSR1);
+ TST_EXP_EQ_LI(info.si_code, SI_MESGQ);
+ TST_EXP_EQ_LI(info.si_pid, 0);
}
-static void setup(void)
+static void cleanup(void)
{
- tst_require_root();
- check_newpid();
+ remove_mqueue(mqd);
}
-int main(void)
+static void run(void)
{
- int status;
- char buf[5];
- pid_t cpid;
+ const struct tst_clone_args args = {
+ .flags = CLONE_NEWPID,
+ .exit_signal = SIGCHLD,
+ };
- setup();
+ remove_mqueue(mqd);
+ received = 0;
- if (pipe(child_to_father) == -1 || pipe(father_to_child) == -1) {
- tst_brkm(TBROK | TERRNO, cleanup, "pipe failed");
+ if (!SAFE_CLONE(&args)) {
+ child_func();
+ return;
}
- tst_syscall(__NR_mq_unlink, mqname);
-
- /* container creation on PID namespace */
- cpid = ltp_clone_quick(CLONE_NEWPID | SIGCHLD, child_fn, NULL);
- if (cpid == -1)
- tst_brkm(TBROK | TERRNO, cleanup, "clone failed");
-
- mqd =
- tst_syscall(__NR_mq_open, mqname, O_RDWR | O_CREAT | O_EXCL, 0777,
- NULL);
- if (mqd == -1)
- tst_brkm(TBROK | TERRNO, cleanup, "mq_open failed");
- else
- tst_resm(TINFO, "successfully created posix mqueue");
-
- if (write(father_to_child[1], buf, 1) != 1)
- tst_brkm(TBROK | TERRNO, cleanup, "write failed");
+ mqd = SAFE_MQ_OPEN(MQNAME, O_RDWR | O_CREAT | O_EXCL, 0777, 0);
- /* Close the appropriate end of each pipe */
- close(child_to_father[1]);
- close(father_to_child[0]);
+ TST_CHECKPOINT_WAKE_AND_WAIT(0);
- /* Is container ready */
- read(child_to_father[0], buf, 5);
- if (strcmp(buf, "c:ok") != 0)
- tst_brkm(TBROK, cleanup,
- "container did not respond as expected!");
-
- rc = mq_send(mqd, MSG, strlen(MSG), MSG_PRIO);
- if (rc == -1)
- tst_brkm(TBROK | TERRNO, cleanup, "mq_send failed");
- else
- tst_resm(TINFO, "mq_send succeeded");
+ tst_res(TINFO, "Send mqueue message");
- /* Tell the child the message has been sent */
- if (write(father_to_child[1], "f:ok", 5) != 5)
- tst_brkm(TBROK | TERRNO, cleanup, "write failed");
+ SAFE_MQ_SEND(mqd, "pippo", 5, 1);
- /* Wait for child to finish */
- if (wait(&status) == -1)
- tst_resm(TBROK | TERRNO, "wait failed");
-
- cleanup();
-
- tst_exit();
+ TST_CHECKPOINT_WAKE(0);
}
+
+static struct tst_test test = {
+ .test_all = run,
+ .cleanup = cleanup,
+ .forks_child = 1,
+ .needs_root = 1,
+ .needs_checkpoints = 1,
+};
diff --git a/testcases/kernel/containers/pidns/pidns31.c b/testcases/kernel/containers/pidns/pidns31.c
index 8821ec83c..7312f8bdc 100644
--- a/testcases/kernel/containers/pidns/pidns31.c
+++ b/testcases/kernel/containers/pidns/pidns31.c
@@ -1,330 +1,118 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
-* Copyright (c) Bull S.A.S. 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
-*
-***************************************************************************
-* File: pidns31.c
-*
-* Description:
-* This testcase checks if the si_pid is correctly set when a process
-* that has registered for notification on a posix mqueue is in an
-* ancestor namespace wrt the process that sends a message to that posix
-* mqueue.
-*
-* Test Assertion & Strategy:
-* Parent Child
-* --------------------------------------------------------------------------
-* Create a POSIX mqueue.
-* Create a PID namespace container.
-* Register for notification when a
-* message arrives in that mqueue
-* Install a handler for SIGUSR1.
-* Open that mqueue for writing
-* Write something to the mqueue.
-* Inside the handler, check that
-* si_pid is set to the child's pid
-*
-* Usage: <for command-line>
-* pidns31
-*
-* History:
-* DATE NAME DESCRIPTION
-* 04/12/08 Nadia Derbey Creation of this test.
-* <Nadia.Derbey@bull.net>
-*
-******************************************************************************/
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-#include <sys/wait.h>
-#include <sys/types.h>
-#include <signal.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <mqueue.h>
-#include "lapi/syscalls.h"
-#include "pidns_helper.h"
-#include "test.h"
-
-char *TCID = "pidns31";
-int TST_TOTAL = 1;
-
-char *mqname = "mq1";
-int result = TFAIL;
-
-int father_to_child[2];
-
-#define CHILD_PID 1
-#define PARENT_PID 0
+ * Copyright (c) Bull S.A.S. 2008
+ * 01/12/08 Nadia Derbey <Nadia.Derbey@bull.net>
+ * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+ */
-#define MSG "HOW ARE YOU"
-#define MSG_PRIO 1
+/*\
+ * [Description]
+ *
+ * Clone a process with CLONE_NEWPID flag, register notification on a posix
+ * mqueue and send a mqueue message from the child. Then check if signal
+ * notification contains si_pid of the child.
+ */
-#define NO_STEP -1
-#define F_STEP_0 0x00
-#define F_STEP_1 0x01
-#define F_STEP_2 0x02
-#define F_STEP_3 0x03
-#define C_STEP_0 0x10
-#define C_STEP_1 0x11
+#define _GNU_SOURCE 1
+#include <signal.h>
+#include <mqueue.h>
+#include "tst_test.h"
+#include "tst_safe_posix_ipc.h"
+#include "lapi/sched.h"
-struct notify_info {
- mqd_t mqd;
- pid_t pid;
-};
+#define MQNAME "/LTP_PIDNS30_MQ"
-static void remove_pipe(int *fd)
-{
- close(fd[0]);
- close(fd[1]);
-}
+static mqd_t mqd = -1;
+static volatile int received;
+static siginfo_t info;
static void remove_mqueue(mqd_t mqd)
{
- mq_close(mqd);
- tst_syscall(__NR_mq_unlink, mqname);
-}
+ if (mqd != -1)
+ SAFE_MQ_CLOSE(mqd);
-/*
- * steps F_STEP_XX : called from main
- * steps C_STEP_XX : called from child_fn
- */
-static void cleanup_resources(int step, mqd_t mqd)
-{
- switch (step) {
- case C_STEP_1:
- close(father_to_child[0]);
- /* fall through */
- case C_STEP_0:
- mq_close(mqd);
- break;
-
- case F_STEP_3:
- remove_mqueue(mqd);
- close(father_to_child[1]);
- break;
-
- case F_STEP_2:
- tst_syscall(__NR_mq_notify, mqd, NULL);
- /* fall through */
- case F_STEP_1:
- remove_mqueue(mqd);
- /* fall through */
- case F_STEP_0:
- remove_pipe(father_to_child);
- break;
- default:
- tst_resm(TWARN, "Unknown code - no resource removed.");
- break;
- }
+ mq_unlink(MQNAME);
}
-/*
- * cleanup_mqueue() - performs all ONE TIME cleanup for this test at
- * completion or premature exit.
- * step == -1 means no local resource to remove.
- */
-void cleanup_mqueue(int result, int step, mqd_t mqd)
+static void signal_handler(LTP_ATTRIBUTE_UNUSED int sig, siginfo_t *si, LTP_ATTRIBUTE_UNUSED void *unused)
{
- if (step != NO_STEP)
- cleanup_resources(step, mqd);
-
- tst_exit();
+ memcpy(&info, si, sizeof(info));
+ received++;
}
-/*
- * child_fn() - Inside container
- */
-int child_fn(void *arg)
+static void child_func(void)
{
- pid_t pid, ppid;
- mqd_t mqd;
- char buf[5];
+ pid_t cpid, ppid;
+ mqd_t mqd_child;
- /* Set process id and parent pid */
- pid = getpid();
+ cpid = tst_getpid();
ppid = getppid();
- if (pid != CHILD_PID || ppid != PARENT_PID) {
- tst_resm(TBROK, "cinit: pidns is not created");
- cleanup_mqueue(TBROK, NO_STEP, 0);
- }
-
- /* Close the appropriate end of pipe */
- close(father_to_child[1]);
-
- /* Is parent ready to receive a message? */
- read(father_to_child[0], buf, 5);
- if (strcmp(buf, "f:ok")) {
- tst_resm(TBROK, "cinit: parent did not send the message!");
- cleanup_mqueue(TBROK, NO_STEP, 0);
- }
- tst_resm(TINFO, "cinit: my father is ready to receive a message");
-
- mqd = tst_syscall(__NR_mq_open, mqname, O_WRONLY, 0, NULL);
- if (mqd == (mqd_t) - 1) {
- tst_resm(TBROK, "cinit: mq_open() failed (%s)",
- strerror(errno));
- cleanup_mqueue(TBROK, NO_STEP, 0);
- }
- tst_resm(TINFO, "cinit: mq_open succeeded");
-
- if (mq_send(mqd, MSG, strlen(MSG), MSG_PRIO) == (mqd_t) - 1) {
- tst_resm(TBROK, "cinit: mq_send() failed (%s)",
- strerror(errno));
- cleanup_mqueue(TBROK, C_STEP_0, mqd);
- }
- tst_resm(TINFO, "cinit: mq_send() succeeded");
-
- /* Cleanup and exit */
- cleanup_resources(C_STEP_1, mqd);
- exit(0);
-}
+ TST_EXP_EQ_LI(cpid, 1);
+ TST_EXP_EQ_LI(ppid, 0);
-/*
- * father_signal_handler()
- */
-static void father_signal_handler(int sig, siginfo_t * si, void *unused)
-{
- char buf[256];
- struct mq_attr attr;
- struct notify_info *info;
+ TST_CHECKPOINT_WAIT(0);
- if (si->si_signo != SIGUSR1) {
- tst_resm(TBROK, "father: received %s unexpectedly",
- strsignal(si->si_signo));
- return;
- }
-
- if (si->si_code != SI_MESGQ) {
- tst_resm(TBROK, "father: expected signal code SI_MESGQ - "
- "Got %d", si->si_code);
- return;
- }
-
- if (!si->si_ptr) {
- tst_resm(TBROK, "father: expected si_ptr - Got NULL");
- return;
- }
-
- info = (struct notify_info *)si->si_ptr;
-
- if (si->si_pid != info->pid) {
- tst_resm(TFAIL,
- "father: expected signal originator PID = %d - Got %d",
- info->pid, si->si_pid);
- return;
- }
+ tst_res(TINFO, "Send mqueue message from child");
- tst_resm(TPASS, "father: signal originator PID = %d", si->si_pid);
- result = TPASS;
+ mqd_child = SAFE_MQ_OPEN(MQNAME, O_WRONLY, 0, NULL);
+ SAFE_MQ_SEND(mqd_child, "pippo", 5, 1);
- /*
- * Now read the message - Be silent on errors since this is not the
- * test purpose.
- */
- if (!mq_getattr(info->mqd, &attr))
- mq_receive(info->mqd, buf, attr.mq_msgsize, NULL);
+ TST_CHECKPOINT_WAKE(0);
}
-static void setup(void)
+static void cleanup(void)
{
- tst_require_root();
- check_newpid();
+ remove_mqueue(mqd);
}
-/***********************************************************************
-* M A I N
-***********************************************************************/
-
-int main(void)
+static void run(void)
{
pid_t cpid;
- mqd_t mqd;
- struct sigevent notif;
struct sigaction sa;
- int status;
- struct notify_info info;
+ struct sigevent notif;
+ const struct tst_clone_args args = {
+ .flags = CLONE_NEWPID,
+ .exit_signal = SIGCHLD,
+ };
- setup();
+ remove_mqueue(mqd);
+ received = 0;
- if (pipe(father_to_child) == -1) {
- tst_resm(TBROK, "parent: pipe() failed. aborting!");
- cleanup_mqueue(TBROK, NO_STEP, 0);
+ cpid = SAFE_CLONE(&args);
+ if (!cpid) {
+ child_func();
+ return;
}
- tst_syscall(__NR_mq_unlink, mqname);
- mqd =
- tst_syscall(__NR_mq_open, mqname, O_RDWR | O_CREAT | O_EXCL, 0777,
- NULL);
- if (mqd == (mqd_t) - 1) {
- tst_resm(TBROK, "parent: mq_open() failed (%s)",
- strerror(errno));
- cleanup_mqueue(TBROK, F_STEP_0, 0);
- }
- tst_resm(TINFO, "parent: successfully created posix mqueue");
+ tst_res(TINFO, "Register notification on posix mqueue");
- /* container creation on PID namespace */
- cpid = ltp_clone_quick(CLONE_NEWPID | SIGCHLD, child_fn, NULL);
- if (cpid < 0) {
- tst_resm(TBROK, "parent: clone() failed(%s)", strerror(errno));
- cleanup_mqueue(TBROK, F_STEP_1, mqd);
- }
- tst_resm(TINFO, "parent: successfully created child (pid = %d)", cpid);
+ mqd = SAFE_MQ_OPEN(MQNAME, O_RDWR | O_CREAT | O_EXCL, 0777, NULL);
- /* Register for notification on message arrival */
notif.sigev_notify = SIGEV_SIGNAL;
notif.sigev_signo = SIGUSR1;
- info.mqd = mqd;
- info.pid = cpid;
- notif.sigev_value.sival_ptr = &info;
- if (tst_syscall(__NR_mq_notify, mqd, &notif) == (mqd_t) -1) {
- tst_resm(TBROK, "parent: mq_notify() failed (%s)",
- strerror(errno));
- cleanup_mqueue(TBROK, F_STEP_1, mqd);
- }
- tst_resm(TINFO, "parent: successfully registered for notification");
-
- /* Define handler for SIGUSR1 */
- sa.sa_flags = SA_SIGINFO;
- sigemptyset(&sa.sa_mask);
- sa.sa_sigaction = father_signal_handler;
- if (sigaction(SIGUSR1, &sa, NULL) == -1) {
- tst_resm(TBROK, "parent: sigaction() failed(%s)",
- strerror(errno));
- cleanup_mqueue(TBROK, F_STEP_2, mqd);
- }
- tst_resm(TINFO, "parent: successfully registered handler for SIGUSR1");
- /* Close the appropriate end of pipe */
- close(father_to_child[0]);
-
- /* Tell the child a message can be sent */
- if (write(father_to_child[1], "f:ok", 5) != 5) {
- tst_resm(TBROK, "parent: pipe is broken(%s)", strerror(errno));
- cleanup_mqueue(TBROK, F_STEP_2, mqd);
- }
+ SAFE_MQ_NOTIFY(mqd, &notif);
- sleep(3);
+ sa.sa_flags = SA_SIGINFO;
+ SAFE_SIGEMPTYSET(&sa.sa_mask);
+ sa.sa_sigaction = signal_handler;
+ SAFE_SIGACTION(SIGUSR1, &sa, NULL);
- /* Wait for child to finish */
- if (wait(&status) == -1) {
- tst_resm(TBROK, "parent: wait() failed(%s)", strerror(errno));
- cleanup_mqueue(TBROK, F_STEP_1, mqd);
- }
+ TST_CHECKPOINT_WAKE_AND_WAIT(0);
- cleanup_mqueue(result, F_STEP_3, mqd);
+ tst_reap_children();
- tst_exit();
+ TST_EXP_EQ_LI(received, 1);
+ TST_EXP_EQ_LI(info.si_signo, SIGUSR1);
+ TST_EXP_EQ_LI(info.si_code, SI_MESGQ);
+ TST_EXP_EQ_LI(info.si_pid, cpid);
}
+
+static struct tst_test test = {
+ .test_all = run,
+ .cleanup = cleanup,
+ .forks_child = 1,
+ .needs_root = 1,
+ .needs_checkpoints = 1,
+};
diff --git a/testcases/kernel/containers/pidns/pidns32.c b/testcases/kernel/containers/pidns/pidns32.c
index 3f7df788e..0738369b1 100644
--- a/testcases/kernel/containers/pidns/pidns32.c
+++ b/testcases/kernel/containers/pidns/pidns32.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) Huawei Technologies Co., Ltd., 2015
- * Copyright (C) 2022 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+ * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
*/
/*\
@@ -12,32 +12,35 @@
*/
#define _GNU_SOURCE
-
#include <sys/mman.h>
#include "tst_test.h"
+#include "tst_atomic.h"
#include "lapi/sched.h"
#define MAXNEST 32
+static const struct tst_clone_args args = {
+ .flags = CLONE_NEWPID,
+ .exit_signal = SIGCHLD,
+};
static int *level;
-static int child_func(LTP_ATTRIBUTE_UNUSED void *arg)
+static pid_t child_func(void)
{
- pid_t cpid;
- int status;
-
- if (*level == MAXNEST)
- return 0;
+ pid_t cpid = 0;
- (*level)++;
+ if (tst_atomic_inc(level) == MAXNEST)
+ return cpid;
- cpid = ltp_clone_quick(CLONE_NEWPID | SIGCHLD, child_func, 0);
- if (cpid < 0)
- tst_brk(TBROK | TERRNO, "clone failed");
+ cpid = SAFE_CLONE(&args);
+ if (!cpid) {
+ child_func();
+ return cpid;
+ }
- SAFE_WAITPID(cpid, &status, 0);
+ tst_reap_children();
- return 0;
+ return cpid;
}
static void setup(void)
@@ -45,28 +48,25 @@ static void setup(void)
level = SAFE_MMAP(NULL, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
}
-static void run(void)
+static void cleanup(void)
{
- int ret, status;
-
- *level = 1;
-
- ret = ltp_clone_quick(CLONE_NEWPID | SIGCHLD, child_func, 0);
- if (ret < 0)
- tst_brk(TBROK | TERRNO, "clone failed");
+ SAFE_MUNMAP(level, sizeof(int));
+}
- SAFE_WAITPID(ret, &status, 0);
+static void run(void)
+{
+ *level = 0;
- if (*level < MAXNEST) {
- tst_res(TFAIL, "Nested containers should be %d, but they are %d", MAXNEST, *level);
+ if (!child_func())
return;
- }
- tst_res(TPASS, "All %d containers have been nested", MAXNEST);
+ TST_EXP_EQ_LI(*level, MAXNEST);
}
static struct tst_test test = {
.test_all = run,
.needs_root = 1,
.setup = setup,
+ .cleanup = cleanup,
+ .forks_child = 1,
};
diff --git a/testcases/kernel/containers/pidns/pidns_helper.h b/testcases/kernel/containers/pidns/pidns_helper.h
deleted file mode 100644
index 3b356768f..000000000
--- a/testcases/kernel/containers/pidns/pidns_helper.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
-* Copyright (c) International Business Machines Corp., 2007
-* 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.
-*/
-
-#include "../libclone/libclone.h"
-#include "test.h"
-#include "safe_macros.h"
-
-static int dummy_child(void *v)
-{
- (void) v;
- return 0;
-}
-
-static int check_newpid(void)
-{
- int pid, status;
-
- pid = do_clone_unshare_test(T_CLONE, CLONE_NEWPID, dummy_child, NULL);
- if (pid == -1)
- tst_brkm(TCONF | TERRNO, NULL, "CLONE_NEWPID not supported");
- SAFE_WAIT(NULL, &status);
-
- return 0;
-}
diff --git a/testcases/kernel/containers/share/.gitignore b/testcases/kernel/containers/share/.gitignore
deleted file mode 100644
index 06615d9ea..000000000
--- a/testcases/kernel/containers/share/.gitignore
+++ /dev/null
@@ -1,4 +0,0 @@
-/ns_ifmove
-/ns_create
-/ns_exec
-/setns_check
diff --git a/testcases/kernel/containers/share/Makefile b/testcases/kernel/containers/share/Makefile
deleted file mode 100644
index 962d6889d..000000000
--- a/testcases/kernel/containers/share/Makefile
+++ /dev/null
@@ -1,22 +0,0 @@
-# Copyright (c) 2015 Red Hat, Inc.
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of version 2 the GNU General Public License as
-# published by the Free Software Foundation.
-#
-# 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/>.
-##############################################################################
-top_srcdir ?= ../../../..
-
-include $(top_srcdir)/include/mk/testcases.mk
-include $(abs_srcdir)/../Makefile.inc
-
-LDLIBS := -lltp
-
-include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/containers/share/ns_create.c b/testcases/kernel/containers/share/ns_create.c
deleted file mode 100644
index 3f09e71e0..000000000
--- a/testcases/kernel/containers/share/ns_create.c
+++ /dev/null
@@ -1,108 +0,0 @@
-/* Copyright (c) 2015 Red Hat, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of version 2 the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * 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/>.
- *
- * Written by Matus Marhefka <mmarhefk@redhat.com>
- *
- ***********************************************************************
- * Creates a child process in the new specified namespace(s), child is then
- * daemonized and is running in the background. PID of the daemonized child
- * process is printed on the stdout. As the new namespace(s) is(are) maintained
- * by the daemonized child process it(they) can be removed by killing this
- * process.
- *
- */
-
-#define _GNU_SOURCE
-#include <sys/syscall.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include "test.h"
-#include "lapi/sched.h"
-#include "ns_common.h"
-
-char *TCID = "ns_create";
-
-
-void print_help(void)
-{
- int i;
-
- printf("usage: ns_create <%s", params[0].name);
-
- for (i = 1; params[i].name; i++)
- printf("|,%s", params[i].name);
- printf(">\nThe only argument is a comma separated list "
- "of namespaces to create.\nExample: ns_create net,ipc\n");
-}
-
-static int child_fn(void *arg LTP_ATTRIBUTE_UNUSED)
-{
- int i;
-
- if (setsid() == -1) {
- tst_resm(TINFO | TERRNO, "setsid");
- exit(1);
- }
-
- if (chdir("/") == -1) {
- tst_resm(TINFO | TERRNO, "chdir");
- exit(1);
- }
-
- /* close all inherrited file descriptors */
- for (i = 0; i < sysconf(_SC_OPEN_MAX); i++)
- close(i);
-
- pause();
- return 0;
-}
-
-/*
- * ./ns_create <ipc,mnt,net,pid,user,uts>
- */
-int main(int argc, char *argv[])
-{
- int pid, flags;
- char *token;
-
- if (argc < 2) {
- print_help();
- return 1;
- }
-
- flags = 0;
- while ((token = strsep(&argv[1], ","))) {
- struct param *p = get_param(token);
-
- if (!p) {
- tst_resm(TINFO, "Unknown namespace: %s", token);
- print_help();
- return 1;
- }
-
- flags |= p->flag;
- }
-
- pid = ltp_clone_quick(flags | SIGCHLD, child_fn, NULL);
- if (pid == -1) {
- tst_resm(TINFO | TERRNO, "ltp_clone_quick");
- return 1;
- }
-
- printf("%d", pid);
- return 0;
-}
diff --git a/testcases/kernel/containers/share/ns_exec.c b/testcases/kernel/containers/share/ns_exec.c
deleted file mode 100644
index 4abd1063b..000000000
--- a/testcases/kernel/containers/share/ns_exec.c
+++ /dev/null
@@ -1,157 +0,0 @@
-/* Copyright (c) 2015 Red Hat, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of version 2 the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * 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/>.
- *
- * Written by Matus Marhefka <mmarhefk@redhat.com>
- *
- ***********************************************************************
- * Enters the namespace(s) of a process specified by a PID and then executes
- * the indicated program inside that namespace(s).
- *
- */
-
-#define _GNU_SOURCE
-#include <sys/syscall.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include "test.h"
-#include "lapi/syscalls.h"
-#include "lapi/sched.h"
-#include "ns_common.h"
-
-char *TCID = "ns_exec";
-int ns_fd[NS_TOTAL];
-int ns_fds;
-
-
-void print_help(void)
-{
- int i;
-
- printf("usage: ns_exec <NS_PID> <%s", params[0].name);
-
- for (i = 1; params[i].name; i++)
- printf("|,%s", params[i].name);
- printf("> <PROGRAM> [ARGS]\nSecond argument indicates the types"
- " of a namespaces maintained by NS_PID\nand is specified"
- " as a comma separated list.\nExample: ns_exec 1234 net,ipc"
- " ip a\n");
-}
-
-static int open_ns_fd(const char *pid, const char *ns)
-{
- int fd;
- char file_buf[30];
-
- sprintf(file_buf, "%s/%s/ns/%s", PROC_PATH, pid, ns);
-
- fd = open(file_buf, O_RDONLY);
- if (fd > 0) {
- ns_fd[ns_fds] = fd;
- ++ns_fds;
- return 0;
- } else if (fd == -1 && errno != ENOENT) {
- tst_resm(TINFO | TERRNO, "open");
- return -1;
- }
-
- return 0;
-}
-
-static void close_ns_fd(void)
-{
- int i;
-
- for (i = 0; i < ns_fds; i++)
- close(ns_fd[i]);
-}
-
-static int child_fn(void *arg)
-{
- char **args = (char **)arg;
-
- execvp(args[3], args+3);
- tst_resm(TINFO | TERRNO, "execvp");
- return 1;
-}
-
-/*
- * ./ns_exec <NS_PID> <ipc,mnt,net,pid,user,uts> <PROGRAM> [ARGS]
- */
-int main(int argc, char *argv[])
-{
- int i, rv, pid;
- char *token;
-
- rv = syscall(__NR_setns, -1, 0);
- if (rv == -1 && errno == ENOSYS) {
- tst_resm(TINFO, "setns is not supported in the kernel");
- return 1;
- }
-
- if (argc < 4) {
- print_help();
- return 1;
- }
-
- memset(ns_fd, 0, sizeof(ns_fd));
- while ((token = strsep(&argv[2], ","))) {
- struct param *p = get_param(token);
-
- if (!p) {
- tst_resm(TINFO, "Unknown namespace: %s", token);
- print_help();
- return 1;
- }
-
- if (open_ns_fd(argv[1], token) != 0)
- return 1;
- }
-
- if (ns_fds == 0) {
- tst_resm(TINFO, "no namespace entries in /proc/%s/ns/",
- argv[1]);
- return 1;
- }
-
- for (i = 0; i < ns_fds; i++) {
- if (syscall(__NR_setns, ns_fd[i], 0) == -1) {
- tst_resm(TINFO | TERRNO, "setns");
- close_ns_fd();
- return 1;
- }
- }
-
- pid = ltp_clone_quick(SIGCHLD, (void *)child_fn, (void *)argv);
- if (pid == -1) {
- tst_resm(TINFO | TERRNO, "ltp_clone_quick");
- close_ns_fd();
- return 1;
- }
-
- if (waitpid(pid, &rv, 0) == -1) {
- tst_resm(TINFO | TERRNO, "waitpid");
- return 1;
- }
-
- close_ns_fd();
-
- if (WIFEXITED(rv))
- return WEXITSTATUS(rv);
-
- return 0;
-}
diff --git a/testcases/kernel/containers/share/ns_ifmove.c b/testcases/kernel/containers/share/ns_ifmove.c
deleted file mode 100644
index 12642c6f4..000000000
--- a/testcases/kernel/containers/share/ns_ifmove.c
+++ /dev/null
@@ -1,134 +0,0 @@
-/* Copyright (c) 2015 Red Hat, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of version 2 the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * 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/>.
- *
- * Written by Matus Marhefka <mmarhefk@redhat.com>
- *
- ***********************************************************************
- * Moves a network interface to the namespace of a process specified by a PID.
- *
- */
-
-#define _GNU_SOURCE
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <asm/types.h>
-#include <sys/socket.h>
-#include <linux/rtnetlink.h>
-#include <sys/ioctl.h>
-#include <linux/if.h>
-#include <net/ethernet.h>
-#include <arpa/inet.h>
-#include "test.h"
-
-#include "config.h"
-
-char *TCID = "ns_ifmove";
-
-#if HAVE_DECL_IFLA_NET_NS_PID
-
-struct {
- struct nlmsghdr nh;
- struct ifinfomsg ifi;
- char attrbuf[512];
-} req;
-
-
-int get_intf_index_from_name(const char *intf_name)
-{
- struct ifreq ifr;
- int sock_fd;
-
- memset(&ifr, 0, sizeof(ifr));
- strncpy(ifr.ifr_name, intf_name, sizeof(ifr.ifr_name) - 1);
- ifr.ifr_name[sizeof(ifr.ifr_name)-1] = '\0';
-
- sock_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
- if (sock_fd == -1) {
- tst_resm(TINFO | TERRNO, "socket");
- return -1;
- }
-
- /* gets interface index */
- if (ioctl(sock_fd, SIOCGIFINDEX, &ifr) == -1) {
- tst_resm(TINFO | TERRNO, "ioctl");
- close(sock_fd);
- return -1;
- }
-
- close(sock_fd);
- return ifr.ifr_ifindex;
-}
-
-/*
- * ./ns_ifmove <INTERFACE_NAME> <NAMESPACE_PID>
- */
-int main(int argc, char **argv)
-{
- struct rtattr *rta;
- int intf_index, pid, rtnetlink_socket;
-
- if (argc != 3) {
- tst_resm(TINFO, "%s <INTERFACE_NAME> <NAMESPACE_PID>",
- argv[0]);
- return 1;
- }
-
- intf_index = get_intf_index_from_name(argv[1]);
- if (intf_index == -1) {
- tst_resm(TINFO , "unable to get interface index");
- return 1;
- }
-
- pid = atoi(argv[2]);
-
- rtnetlink_socket = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
- if (rtnetlink_socket == -1) {
- tst_resm(TINFO | TERRNO, "socket");
- return 1;
- }
-
- memset(&req, 0, sizeof(req));
- req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
- req.nh.nlmsg_flags = NLM_F_REQUEST;
- req.nh.nlmsg_type = RTM_NEWLINK;
- req.ifi.ifi_family = AF_UNSPEC;
- req.ifi.ifi_index = intf_index;
- req.ifi.ifi_change = 0xffffffff;
- rta = (struct rtattr *)(((char *) &req) +
- NLMSG_ALIGN(req.nh.nlmsg_len));
- rta->rta_type = IFLA_NET_NS_PID;
- rta->rta_len = RTA_LENGTH(sizeof(int));
- req.nh.nlmsg_len = NLMSG_ALIGN(req.nh.nlmsg_len) +
- RTA_LENGTH(sizeof(pid));
- memcpy(RTA_DATA(rta), &pid, sizeof(pid));
-
- if (send(rtnetlink_socket, &req, req.nh.nlmsg_len, 0) == -1) {
- tst_resm(TINFO | TERRNO, "send");
- return 1;
- }
-
- close(rtnetlink_socket);
- return 0;
-}
-
-#else
-
-int main(void)
-{
- tst_brkm(TCONF, NULL, "IFLA_NET_NS_PID not defined in linux/if_link.h");
-}
-
-#endif
diff --git a/testcases/kernel/containers/share/setns_check.c b/testcases/kernel/containers/share/setns_check.c
deleted file mode 100644
index 75aad17f3..000000000
--- a/testcases/kernel/containers/share/setns_check.c
+++ /dev/null
@@ -1,32 +0,0 @@
-/* Copyright (c) 2015 Fujitsu Ltd.
- * Author: Guangwen Feng <fenggw-fnst@cn.fujitsu.com>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of version 2 the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * 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/>.
- *
- ***********************************************************************
- * Check for setns() availability, should be called before ns_exec.
- *
- */
-
-#include "test.h"
-#include "lapi/syscalls.h"
-
-char *TCID = "setns_check";
-
-int main(void)
-{
- if (syscall(__NR_setns, -1, 0) == -1 && errno == ENOSYS)
- tst_brkm(TCONF, NULL, "setns is not supported in the kernel");
- else
- return 0;
-}
diff --git a/testcases/kernel/containers/sysvipc/common.h b/testcases/kernel/containers/sysvipc/common.h
index 9b0fc16e9..180cf9bd7 100644
--- a/testcases/kernel/containers/sysvipc/common.h
+++ b/testcases/kernel/containers/sysvipc/common.h
@@ -19,24 +19,7 @@ enum {
T_NONE,
};
-static int dummy_child(void *v)
-{
- (void)v;
- return 0;
-}
-
-static void check_newipc(void)
-{
- int pid, status;
-
- pid = ltp_clone_quick(CLONE_NEWIPC | SIGCHLD, dummy_child, NULL);
- if (pid < 0)
- tst_brk(TCONF | TERRNO, "CLONE_NEWIPC not supported");
-
- SAFE_WAITPID(pid, &status, 0);
-}
-
-static inline int get_clone_unshare_enum(const char* str_op)
+static inline int get_clone_unshare_enum(const char *str_op)
{
int use_clone;
@@ -54,16 +37,22 @@ static inline int get_clone_unshare_enum(const char* str_op)
return use_clone;
}
-static void clone_test(unsigned long clone_flags, int (*fn1)(void *arg), void *arg1)
+static void clone_test(unsigned long clone_flags, void (*fn1)())
{
+ const struct tst_clone_args clone_args = {
+ .flags = clone_flags,
+ .exit_signal = SIGCHLD,
+ };
int pid;
- pid = ltp_clone_quick(clone_flags | SIGCHLD, fn1, arg1);
- if (pid < 0)
- tst_brk(TBROK | TERRNO, "ltp_clone_quick error");
+ pid = SAFE_CLONE(&clone_args);
+ if (!pid) {
+ fn1();
+ exit(0);
+ }
}
-static void unshare_test(unsigned long clone_flags, int (*fn1)(void *arg), void *arg1)
+static void unshare_test(unsigned long clone_flags, void (*fn1)())
{
int pid;
@@ -71,34 +60,33 @@ static void unshare_test(unsigned long clone_flags, int (*fn1)(void *arg), void
if (!pid) {
SAFE_UNSHARE(clone_flags);
- fn1(arg1);
+ fn1();
exit(0);
}
}
-static void plain_test(int (*fn1)(void *arg), void *arg1)
+static void plain_test(void (*fn1)())
{
int pid;
pid = SAFE_FORK();
if (!pid) {
- fn1(arg1);
+ fn1();
exit(0);
}
}
-static void clone_unshare_test(int use_clone, unsigned long clone_flags,
- int (*fn1)(void *arg), void *arg1)
+static void clone_unshare_test(int use_clone, unsigned long clone_flags, void (*fn1)())
{
switch (use_clone) {
case T_NONE:
- plain_test(fn1, arg1);
+ plain_test(fn1);
break;
case T_CLONE:
- clone_test(clone_flags, fn1, arg1);
+ clone_test(clone_flags, fn1);
break;
case T_UNSHARE:
- unshare_test(clone_flags, fn1, arg1);
+ unshare_test(clone_flags, fn1);
break;
default:
tst_brk(TBROK, "%s: bad use_clone option: %d", __FUNCTION__, use_clone);
diff --git a/testcases/kernel/containers/sysvipc/mesgq_nstest.c b/testcases/kernel/containers/sysvipc/mesgq_nstest.c
index 056b5d086..4b12c1ce1 100644
--- a/testcases/kernel/containers/sysvipc/mesgq_nstest.c
+++ b/testcases/kernel/containers/sysvipc/mesgq_nstest.c
@@ -42,7 +42,7 @@ struct msg_buf {
char mtext[80];
};
-static int check_mesgq(LTP_ATTRIBUTE_UNUSED void *vtest)
+static void check_mesgq(void)
{
int id, n;
struct msg_buf msg = {};
@@ -55,7 +55,7 @@ static int check_mesgq(LTP_ATTRIBUTE_UNUSED void *vtest)
else
tst_res(TPASS, "%s: container didn't find mesgq", str_op);
- return 0;
+ return;
}
if (use_clone == T_NONE) {
@@ -68,11 +68,10 @@ static int check_mesgq(LTP_ATTRIBUTE_UNUSED void *vtest)
if (strcmp(msg.mtext, MSG_TEXT))
tst_res(TFAIL, "Received the wrong text message");
- return 0;
+ return;
}
tst_res(TFAIL, "%s: container init process found mesgq", str_op);
- return 0;
}
static void run(void)
@@ -87,16 +86,12 @@ static void run(void)
tst_res(TINFO, "mesgq namespaces test: %s", str_op);
- clone_unshare_test(use_clone, CLONE_NEWIPC, check_mesgq, NULL);
+ clone_unshare_test(use_clone, CLONE_NEWIPC, check_mesgq);
}
static void setup(void)
{
use_clone = get_clone_unshare_enum(str_op);
-
- if (use_clone != T_NONE)
- check_newipc();
-
ipc_id = SAFE_MSGGET(KEY_VAL, IPC_CREAT | IPC_EXCL | 0600);
}
diff --git a/testcases/kernel/containers/sysvipc/msg_comm.c b/testcases/kernel/containers/sysvipc/msg_comm.c
index 238863d9c..3762adb02 100644
--- a/testcases/kernel/containers/sysvipc/msg_comm.c
+++ b/testcases/kernel/containers/sysvipc/msg_comm.c
@@ -38,7 +38,7 @@ struct sysv_msg {
char mtext[1];
};
-static int chld1_msg(LTP_ATTRIBUTE_UNUSED void *arg)
+static void chld1_msg(void)
{
int id;
struct sysv_msg m = {
@@ -66,11 +66,9 @@ static int chld1_msg(LTP_ATTRIBUTE_UNUSED void *arg)
TST_CHECKPOINT_WAKE(0);
SAFE_MSGCTL(id, IPC_RMID, NULL);
-
- return 0;
}
-static int chld2_msg(LTP_ATTRIBUTE_UNUSED void *arg)
+static void chld2_msg(void)
{
int id;
struct sysv_msg m = {
@@ -85,24 +83,17 @@ static int chld2_msg(LTP_ATTRIBUTE_UNUSED void *arg)
TST_CHECKPOINT_WAKE_AND_WAIT(0);
SAFE_MSGCTL(id, IPC_RMID, NULL);
-
- return 0;
}
static void run(void)
{
- clone_unshare_test(T_CLONE, CLONE_NEWIPC, chld1_msg, NULL);
- clone_unshare_test(T_CLONE, CLONE_NEWIPC, chld2_msg, NULL);
-}
-
-static void setup(void)
-{
- check_newipc();
+ clone_unshare_test(T_CLONE, CLONE_NEWIPC, chld1_msg);
+ clone_unshare_test(T_CLONE, CLONE_NEWIPC, chld2_msg);
}
static struct tst_test test = {
.test_all = run,
- .setup = setup,
.needs_root = 1,
.needs_checkpoints = 1,
+ .forks_child = 1,
};
diff --git a/testcases/kernel/containers/sysvipc/sem_comm.c b/testcases/kernel/containers/sysvipc/sem_comm.c
index 3323ec09f..d8f0956a7 100644
--- a/testcases/kernel/containers/sysvipc/sem_comm.c
+++ b/testcases/kernel/containers/sysvipc/sem_comm.c
@@ -33,7 +33,7 @@
#define TESTKEY 124426L
-static int chld1_sem(LTP_ATTRIBUTE_UNUSED void *arg)
+static void chld1_sem(void)
{
int id;
struct sembuf sm = {
@@ -56,11 +56,9 @@ static int chld1_sem(LTP_ATTRIBUTE_UNUSED void *arg)
TST_CHECKPOINT_WAKE_AND_WAIT(0);
SAFE_SEMCTL(id, 0, IPC_RMID);
-
- return 0;
}
-static int chld2_sem(LTP_ATTRIBUTE_UNUSED void *arg)
+static void chld2_sem(void)
{
int id;
struct sembuf sm = {
@@ -93,24 +91,17 @@ static int chld2_sem(LTP_ATTRIBUTE_UNUSED void *arg)
TST_CHECKPOINT_WAKE(0);
SAFE_SEMCTL(id, 0, IPC_RMID);
-
- return 0;
}
static void run(void)
{
- clone_unshare_test(T_CLONE, CLONE_NEWIPC, chld1_sem, NULL);
- clone_unshare_test(T_CLONE, CLONE_NEWIPC, chld2_sem, NULL);
-}
-
-static void setup(void)
-{
- check_newipc();
+ clone_unshare_test(T_CLONE, CLONE_NEWIPC, chld1_sem);
+ clone_unshare_test(T_CLONE, CLONE_NEWIPC, chld2_sem);
}
static struct tst_test test = {
.test_all = run,
- .setup = setup,
.needs_root = 1,
.needs_checkpoints = 1,
+ .forks_child = 1,
};
diff --git a/testcases/kernel/containers/sysvipc/sem_nstest.c b/testcases/kernel/containers/sysvipc/sem_nstest.c
index ac1dae443..35d55cbac 100644
--- a/testcases/kernel/containers/sysvipc/sem_nstest.c
+++ b/testcases/kernel/containers/sysvipc/sem_nstest.c
@@ -35,7 +35,7 @@ static char *str_op;
static int use_clone;
static int ipc_id = -1;
-static int check_semaphore(LTP_ATTRIBUTE_UNUSED void *vtest)
+static void check_semaphore(void)
{
int id;
@@ -47,7 +47,7 @@ static int check_semaphore(LTP_ATTRIBUTE_UNUSED void *vtest)
else
tst_res(TPASS, "%s: container didn't find semaphore", str_op);
- return 0;
+ return;
}
tst_res(TINFO, "PID %d: fetched existing semaphore..id = %d", getpid(), id);
@@ -56,22 +56,16 @@ static int check_semaphore(LTP_ATTRIBUTE_UNUSED void *vtest)
tst_res(TPASS, "Plain cloned process found semaphore inside container");
else
tst_res(TFAIL, "%s: Container init process found semaphore", str_op);
-
- return 0;
}
static void run(void)
{
- clone_unshare_test(use_clone, CLONE_NEWIPC, check_semaphore, NULL);
+ clone_unshare_test(use_clone, CLONE_NEWIPC, check_semaphore);
}
static void setup(void)
{
use_clone = get_clone_unshare_enum(str_op);
-
- if (use_clone != T_NONE)
- check_newipc();
-
ipc_id = SAFE_SEMGET(MY_KEY, 1, IPC_CREAT | IPC_EXCL | 0666);
}
diff --git a/testcases/kernel/containers/sysvipc/semtest_2ns.c b/testcases/kernel/containers/sysvipc/semtest_2ns.c
index edff3f522..f03b18f72 100644
--- a/testcases/kernel/containers/sysvipc/semtest_2ns.c
+++ b/testcases/kernel/containers/sysvipc/semtest_2ns.c
@@ -40,7 +40,7 @@
static char *str_op;
static int use_clone;
-static int check_sem1(LTP_ATTRIBUTE_UNUSED void *vtest)
+static void check_sem1(void)
{
int id;
struct sembuf sm = {
@@ -62,11 +62,9 @@ static int check_sem1(LTP_ATTRIBUTE_UNUSED void *vtest)
TST_CHECKPOINT_WAKE_AND_WAIT(0);
SAFE_SEMCTL(id, IPC_RMID, 0);
-
- return 0;
}
-static int check_sem2(LTP_ATTRIBUTE_UNUSED void *vtest)
+static void check_sem2(void)
{
int id;
struct sembuf sm = {
@@ -112,22 +110,17 @@ static int check_sem2(LTP_ATTRIBUTE_UNUSED void *vtest)
}
TST_CHECKPOINT_WAKE(0);
-
- return 0;
}
static void run(void)
{
- clone_unshare_test(use_clone, CLONE_NEWIPC, check_sem1, NULL);
- clone_unshare_test(use_clone, CLONE_NEWIPC, check_sem2, NULL);
+ clone_unshare_test(use_clone, CLONE_NEWIPC, check_sem1);
+ clone_unshare_test(use_clone, CLONE_NEWIPC, check_sem2);
}
static void setup(void)
{
use_clone = get_clone_unshare_enum(str_op);
-
- if (use_clone != T_NONE)
- check_newipc();
}
static void cleanup(void)
diff --git a/testcases/kernel/containers/sysvipc/shm_comm.c b/testcases/kernel/containers/sysvipc/shm_comm.c
index 12ad49110..e7ba8c8de 100644
--- a/testcases/kernel/containers/sysvipc/shm_comm.c
+++ b/testcases/kernel/containers/sysvipc/shm_comm.c
@@ -35,7 +35,7 @@
#define TESTKEY 124426L
#define SHMSIZE 50
-static int chld1_shm(LTP_ATTRIBUTE_UNUSED void *arg)
+static void chld1_shm(void)
{
int id;
char *shmem;
@@ -56,11 +56,9 @@ static int chld1_shm(LTP_ATTRIBUTE_UNUSED void *arg)
SAFE_SHMDT(shmem);
SAFE_SHMCTL(id, IPC_RMID, NULL);
-
- return 0;
}
-static int chld2_shm(LTP_ATTRIBUTE_UNUSED void *arg)
+static void chld2_shm(void)
{
int id;
char *shmem;
@@ -77,24 +75,17 @@ static int chld2_shm(LTP_ATTRIBUTE_UNUSED void *arg)
SAFE_SHMDT(shmem);
SAFE_SHMCTL(id, IPC_RMID, NULL);
-
- return 0;
}
static void run(void)
{
- clone_unshare_test(T_CLONE, CLONE_NEWIPC, chld1_shm, NULL);
- clone_unshare_test(T_CLONE, CLONE_NEWIPC, chld2_shm, NULL);
-}
-
-static void setup(void)
-{
- check_newipc();
+ clone_unshare_test(T_CLONE, CLONE_NEWIPC, chld1_shm);
+ clone_unshare_test(T_CLONE, CLONE_NEWIPC, chld2_shm);
}
static struct tst_test test = {
.test_all = run,
- .setup = setup,
.needs_root = 1,
.needs_checkpoints = 1,
+ .forks_child = 1,
};
diff --git a/testcases/kernel/containers/sysvipc/shmem_2nstest.c b/testcases/kernel/containers/sysvipc/shmem_2nstest.c
index ea3de94bd..a184cfcb4 100644
--- a/testcases/kernel/containers/sysvipc/shmem_2nstest.c
+++ b/testcases/kernel/containers/sysvipc/shmem_2nstest.c
@@ -40,7 +40,7 @@
static char *str_op;
static int use_clone;
-static int check_shmem1(LTP_ATTRIBUTE_UNUSED void *vtest)
+static void check_shmem1(void)
{
int id;
@@ -51,11 +51,9 @@ static int check_shmem1(LTP_ATTRIBUTE_UNUSED void *vtest)
TST_CHECKPOINT_WAKE_AND_WAIT(0);
SAFE_SHMCTL(id, IPC_RMID, NULL);
-
- return 0;
}
-static int check_shmem2(LTP_ATTRIBUTE_UNUSED void *vtest)
+static void check_shmem2(void)
{
TST_CHECKPOINT_WAIT(0);
@@ -74,22 +72,17 @@ static int check_shmem2(LTP_ATTRIBUTE_UNUSED void *vtest)
}
TST_CHECKPOINT_WAKE(0);
-
- return 0;
}
static void run(void)
{
- clone_unshare_test(use_clone, CLONE_NEWIPC, check_shmem1, NULL);
- clone_unshare_test(use_clone, CLONE_NEWIPC, check_shmem2, NULL);
+ clone_unshare_test(use_clone, CLONE_NEWIPC, check_shmem1);
+ clone_unshare_test(use_clone, CLONE_NEWIPC, check_shmem2);
}
static void setup(void)
{
use_clone = get_clone_unshare_enum(str_op);
-
- if (use_clone != T_NONE)
- check_newipc();
}
static struct tst_test test = {
diff --git a/testcases/kernel/containers/sysvipc/shmnstest.c b/testcases/kernel/containers/sysvipc/shmnstest.c
index d8ace723e..63ae62aa6 100644
--- a/testcases/kernel/containers/sysvipc/shmnstest.c
+++ b/testcases/kernel/containers/sysvipc/shmnstest.c
@@ -27,7 +27,7 @@ static char *str_op;
static int use_clone;
static int ipc_id = -1;
-static int check_shmid(LTP_ATTRIBUTE_UNUSED void *vtest)
+static void check_shmid(void)
{
TEST(shmget(TESTKEY, 100, 0));
if (TST_RET < 0) {
@@ -41,22 +41,16 @@ static int check_shmid(LTP_ATTRIBUTE_UNUSED void *vtest)
else
tst_res(TFAIL, "%s: child process found shmid", str_op);
}
-
- return 0;
}
static void run(void)
{
- clone_unshare_test(use_clone, CLONE_NEWIPC, check_shmid, NULL);
+ clone_unshare_test(use_clone, CLONE_NEWIPC, check_shmid);
}
static void setup(void)
{
use_clone = get_clone_unshare_enum(str_op);
-
- if (use_clone != T_NONE)
- check_newipc();
-
ipc_id = shmget(TESTKEY, 100, IPC_CREAT);
}
diff --git a/testcases/kernel/containers/userns/.gitignore b/testcases/kernel/containers/userns/.gitignore
new file mode 100644
index 000000000..dbd4aee27
--- /dev/null
+++ b/testcases/kernel/containers/userns/.gitignore
@@ -0,0 +1,9 @@
+userns01
+userns02
+userns03
+userns04
+userns05
+userns06_capcheck
+userns06
+userns07
+userns08
diff --git a/testcases/kernel/containers/userns/Makefile b/testcases/kernel/containers/userns/Makefile
index 80681096d..1531d1de6 100644
--- a/testcases/kernel/containers/userns/Makefile
+++ b/testcases/kernel/containers/userns/Makefile
@@ -1,26 +1,11 @@
-###############################################################################
-# ##
-# Copyright (c) Huawei Technologies Co., Ltd., 2015 ##
-# ##
-# 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. ##
-###############################################################################
+# SPDX-License-Identifier: GPL-2.0-or-later
+# Copyright (c) Huawei Technologies Co., Ltd., 2015
+# Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
top_srcdir ?= ../../../..
include $(top_srcdir)/include/mk/testcases.mk
-include $(abs_srcdir)/../Makefile.inc
-LDLIBS := -lclone $(LDLIBS) $(CAP_LIBS)
+LDLIBS := $(LDLIBS) $(CAP_LIBS)
include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/containers/userns/common.h b/testcases/kernel/containers/userns/common.h
index 635d0f190..9b3a47b69 100644
--- a/testcases/kernel/containers/userns/common.h
+++ b/testcases/kernel/containers/userns/common.h
@@ -8,35 +8,17 @@
#define COMMON_H
#include "tst_test.h"
-#include "lapi/sched.h"
#define UID_MAP 0
#define GID_MAP 1
-static int dummy_child(void *v)
-{
- (void)v;
- return 0;
-}
-
-static inline void check_newuser(void)
-{
- int pid, status;
-
- pid = ltp_clone_quick(CLONE_NEWUSER | SIGCHLD, dummy_child, NULL);
- if (pid == -1)
- tst_brk(TCONF | TTERRNO, "CLONE_NEWUSER not supported");
-
- SAFE_WAIT(&status);
-}
-
static inline void updatemap(int cpid, int type, int idnum, int parentmappid)
{
char path[BUFSIZ];
char content[BUFSIZ];
int fd;
- switch(type) {
+ switch (type) {
case UID_MAP:
sprintf(path, "/proc/%d/uid_map", cpid);
break;
diff --git a/testcases/kernel/containers/userns/userns01.c b/testcases/kernel/containers/userns/userns01.c
index 8ed7a9f41..6fe0cd637 100644
--- a/testcases/kernel/containers/userns/userns01.c
+++ b/testcases/kernel/containers/userns/userns01.c
@@ -20,9 +20,9 @@
#define _GNU_SOURCE
#include <stdio.h>
-#include "common.h"
#include "config.h"
#include <sys/capability.h>
+#include "lapi/sched.h"
#define OVERFLOWUIDPATH "/proc/sys/kernel/overflowuid"
#define OVERFLOWGIDPATH "/proc/sys/kernel/overflowgid"
@@ -30,10 +30,7 @@
static long overflowuid;
static long overflowgid;
-/*
- * child_fn1() - Inside a new user namespace
- */
-static int child_fn1(LTP_ATTRIBUTE_UNUSED void *arg)
+static void child_fn1(void)
{
int uid, gid;
cap_t caps;
@@ -45,10 +42,8 @@ static int child_fn1(LTP_ATTRIBUTE_UNUSED void *arg)
tst_res(TINFO, "USERNS test is running in a new user namespace.");
- if (uid != overflowuid || gid != overflowgid)
- tst_res(TFAIL, "got unexpected uid=%d gid=%d", uid, gid);
- else
- tst_res(TPASS, "got expected uid and gid");
+ TST_EXP_EQ_LI(uid, overflowuid);
+ TST_EXP_EQ_LI(gid, overflowgid);
caps = cap_get_proc();
@@ -68,31 +63,32 @@ static int child_fn1(LTP_ATTRIBUTE_UNUSED void *arg)
tst_res(TFAIL, "unexpected effective/permitted caps at %d", i);
else
tst_res(TPASS, "expected capabilities");
-
- return 0;
}
static void setup(void)
{
- check_newuser();
-
SAFE_FILE_SCANF(OVERFLOWUIDPATH, "%ld", &overflowuid);
SAFE_FILE_SCANF(OVERFLOWGIDPATH, "%ld", &overflowgid);
}
static void run(void)
{
- int pid;
-
- pid = ltp_clone_quick(CLONE_NEWUSER | SIGCHLD, child_fn1, NULL);
- if (pid < 0)
- tst_brk(TBROK | TTERRNO, "clone failed");
+ const struct tst_clone_args args = {
+ .flags = CLONE_NEWUSER,
+ .exit_signal = SIGCHLD,
+ };
+
+ if (!SAFE_CLONE(&args)) {
+ child_fn1();
+ return;
+ }
}
static struct tst_test test = {
.setup = setup,
.test_all = run,
.needs_root = 1,
+ .forks_child = 1,
.caps = (struct tst_cap []) {
TST_CAP(TST_CAP_DROP, CAP_NET_RAW),
{}
diff --git a/testcases/kernel/containers/userns/userns02.c b/testcases/kernel/containers/userns/userns02.c
index dd784000e..3c8ce2133 100644
--- a/testcases/kernel/containers/userns/userns02.c
+++ b/testcases/kernel/containers/userns/userns02.c
@@ -14,13 +14,10 @@
#define _GNU_SOURCE
#include <stdio.h>
-#include "common.h"
#include "tst_test.h"
+#include "lapi/sched.h"
-/*
- * child_fn1() - Inside a new user namespace
- */
-static int child_fn1(LTP_ATTRIBUTE_UNUSED void *arg)
+static void child_fn1(void)
{
int uid, gid;
@@ -29,29 +26,26 @@ static int child_fn1(LTP_ATTRIBUTE_UNUSED void *arg)
uid = geteuid();
gid = getegid();
- if (uid == 100 && gid == 100)
- tst_res(TPASS, "got expected uid and gid");
- else
- tst_res(TFAIL, "got unexpected uid=%d gid=%d", uid, gid);
-
- return 0;
-}
-
-static void setup(void)
-{
- check_newuser();
+ TST_EXP_EQ_LI(uid, 100);
+ TST_EXP_EQ_LI(gid, 100);
}
static void run(void)
{
+ const struct tst_clone_args args = {
+ .flags = CLONE_NEWUSER,
+ .exit_signal = SIGCHLD,
+ };
int childpid;
int parentuid;
int parentgid;
char path[BUFSIZ];
- childpid = ltp_clone_quick(CLONE_NEWUSER | SIGCHLD, child_fn1, NULL);
- if (childpid < 0)
- tst_brk(TBROK | TTERRNO, "clone failed");
+ childpid = SAFE_CLONE(&args);
+ if (!childpid) {
+ child_fn1();
+ return;
+ }
parentuid = geteuid();
parentgid = getegid();
@@ -71,9 +65,9 @@ static void run(void)
}
static struct tst_test test = {
- .setup = setup,
.test_all = run,
.needs_root = 1,
+ .forks_child = 1,
.needs_checkpoints = 1,
.needs_kconfigs = (const char *[]) {
"CONFIG_USER_NS",
diff --git a/testcases/kernel/containers/userns/userns03.c b/testcases/kernel/containers/userns/userns03.c
index b90cc09ba..fca858702 100644
--- a/testcases/kernel/containers/userns/userns03.c
+++ b/testcases/kernel/containers/userns/userns03.c
@@ -32,8 +32,9 @@
#include <stdio.h>
#include <stdbool.h>
-#include "common.h"
#include "tst_test.h"
+#include "lapi/sched.h"
+#include "common.h"
#define CHILD1UID 0
#define CHILD1GID 0
@@ -42,23 +43,12 @@
#define UID_MAP 0
#define GID_MAP 1
-static int cpid1;
-static int parentuid;
-static int parentgid;
-
-/*
- * child_fn1() - Inside a new user namespace
- */
-static int child_fn1(LTP_ATTRIBUTE_UNUSED void *arg)
+static void child_fn1(void)
{
TST_CHECKPOINT_WAIT(0);
- return 0;
}
-/*
- * child_fn2() - Inside a new user namespace
- */
-static int child_fn2(LTP_ATTRIBUTE_UNUSED void *arg)
+static void child_fn2(int cpid1, int parentuid, int parentgid)
{
int uid, gid;
char cpid1uidpath[BUFSIZ];
@@ -70,12 +60,8 @@ static int child_fn2(LTP_ATTRIBUTE_UNUSED void *arg)
uid = geteuid();
gid = getegid();
- tst_res(TINFO, "uid=%d, gid=%d", uid, gid);
-
- if (uid != CHILD2UID || gid != CHILD2GID)
- tst_res(TFAIL, "unexpected uid=%d gid=%d", uid, gid);
- else
- tst_res(TPASS, "expected uid and gid");
+ TST_EXP_EQ_LI(uid, CHILD2UID);
+ TST_EXP_EQ_LI(gid, CHILD2GID);
/* Get the uid parameters of the child_fn2 process */
SAFE_FILE_SCANF("/proc/self/uid_map", "%d %d %d", &idinsidens, &idoutsidens, &length);
@@ -127,32 +113,34 @@ static int child_fn2(LTP_ATTRIBUTE_UNUSED void *arg)
TST_CHECKPOINT_WAKE(0);
TST_CHECKPOINT_WAKE(1);
-
- return 0;
-}
-
-static void setup(void)
-{
- check_newuser();
}
static void run(void)
{
- pid_t cpid2;
+ const struct tst_clone_args args = {
+ .flags = CLONE_NEWUSER,
+ .exit_signal = SIGCHLD,
+ };
+ pid_t cpid1, cpid2;
+ uid_t parentuid;
+ gid_t parentgid;
char path[BUFSIZ];
int fd;
- int ret;
parentuid = geteuid();
parentgid = getegid();
- cpid1 = ltp_clone_quick(CLONE_NEWUSER | SIGCHLD, child_fn1, NULL);
- if (cpid1 < 0)
- tst_brk(TBROK | TTERRNO, "cpid1 clone failed");
+ cpid1 = SAFE_CLONE(&args);
+ if (!cpid1) {
+ child_fn1();
+ return;
+ }
- cpid2 = ltp_clone_quick(CLONE_NEWUSER | SIGCHLD, child_fn2, NULL);
- if (cpid2 < 0)
- tst_brk(TBROK | TTERRNO, "cpid2 clone failed");
+ cpid2 = SAFE_CLONE(&args);
+ if (!cpid2) {
+ child_fn2(cpid1, parentuid, parentgid);
+ return;
+ }
if (access("/proc/self/setgroups", F_OK) == 0) {
sprintf(path, "/proc/%d/setgroups", cpid1);
@@ -168,19 +156,12 @@ static void run(void)
* do so will fail with the error EPERM.)
*/
- /* test that setgroups can't be re-enabled */
- fd = SAFE_OPEN(path, O_WRONLY, 0644);
- ret = write(fd, "allow", 5);
-
- if (ret != -1)
- tst_brk(TBROK, "write action should fail");
- else if (errno != EPERM)
- tst_brk(TBROK | TTERRNO, "unexpected error");
+ tst_res(TINFO, "Check if setgroups can be re-enabled");
+ fd = SAFE_OPEN(path, O_WRONLY, 0644);
+ TST_EXP_FAIL2(write(fd, "allow", 5), EPERM);
SAFE_CLOSE(fd);
- tst_res(TPASS, "setgroups can't be re-enabled");
-
sprintf(path, "/proc/%d/setgroups", cpid2);
fd = SAFE_OPEN(path, O_WRONLY, 0644);
@@ -198,9 +179,9 @@ static void run(void)
}
static struct tst_test test = {
- .setup = setup,
.test_all = run,
.needs_root = 1,
+ .forks_child = 1,
.needs_checkpoints = 1,
.needs_kconfigs = (const char *[]) {
"CONFIG_USER_NS",
diff --git a/testcases/kernel/containers/userns/userns04.c b/testcases/kernel/containers/userns/userns04.c
index d8639502e..d20041f06 100644
--- a/testcases/kernel/containers/userns/userns04.c
+++ b/testcases/kernel/containers/userns/userns04.c
@@ -15,56 +15,49 @@
#define _GNU_SOURCE
#include <stdio.h>
-#include "common.h"
#include "tst_test.h"
-#include "lapi/syscalls.h"
+#include "lapi/sched.h"
-static void setup(void)
-{
- check_newuser();
- tst_syscall(__NR_setns, -1, 0);
-}
-
-static int child_fn1(LTP_ATTRIBUTE_UNUSED void *arg)
+static void child_fn1(void)
{
TST_CHECKPOINT_WAIT(0);
- return 0;
}
-static int child_fn2(void *arg)
+static void child_fn2(int fd)
{
- TEST(tst_syscall(__NR_setns, ((long)arg), CLONE_NEWUSER));
- if (TST_RET != -1 || TST_ERR != EPERM)
- tst_res(TFAIL | TERRNO, "child2 setns() error");
- else
- tst_res(TPASS, "child2 setns() failed as expected");
-
+ TST_EXP_FAIL(setns(fd, CLONE_NEWUSER), EPERM);
TST_CHECKPOINT_WAIT(1);
-
- return 0;
}
static void run(void)
{
+ const struct tst_clone_args args = {
+ .flags = CLONE_NEWUSER,
+ .exit_signal = SIGCHLD,
+ };
pid_t cpid1, cpid2, cpid3;
char path[BUFSIZ];
int fd;
- cpid1 = ltp_clone_quick(CLONE_NEWUSER | SIGCHLD, (void *)child_fn1, NULL);
- if (cpid1 < 0)
- tst_brk(TBROK | TTERRNO, "clone failed");
+ cpid1 = SAFE_CLONE(&args);
+ if (!cpid1) {
+ child_fn1();
+ return;
+ }
sprintf(path, "/proc/%d/ns/user", cpid1);
fd = SAFE_OPEN(path, O_RDONLY, 0644);
- cpid2 = ltp_clone_quick(CLONE_NEWUSER | SIGCHLD, (void *)child_fn2, (void *)((long)fd));
- if (cpid2 < 0)
- tst_brk(TBROK | TTERRNO, "clone failed");
- /* child 3 - throw-away process changing ns to child1 */
+ cpid2 = SAFE_CLONE(&args);
+ if (!cpid2) {
+ child_fn2(fd);
+ return;
+ }
+
cpid3 = SAFE_FORK();
if (!cpid3) {
- TST_EXP_PASS(tst_syscall(__NR_setns, fd, CLONE_NEWUSER));
+ TST_EXP_PASS(setns(fd, CLONE_NEWUSER));
return;
}
@@ -75,7 +68,6 @@ static void run(void)
}
static struct tst_test test = {
- .setup = setup,
.test_all = run,
.needs_root = 1,
.forks_child = 1,
diff --git a/testcases/kernel/containers/userns/userns05.c b/testcases/kernel/containers/userns/userns05.c
index 4c16694b1..e7a00af18 100644
--- a/testcases/kernel/containers/userns/userns05.c
+++ b/testcases/kernel/containers/userns/userns05.c
@@ -18,15 +18,12 @@
#include <stdio.h>
#include "tst_test.h"
+#include "lapi/sched.h"
#include "common.h"
-/*
- * child_fn1() - Inside a new user namespace
- */
-static int child_fn1(void)
+static void child_fn1(void)
{
TST_CHECKPOINT_WAIT(0);
- return 0;
}
static unsigned int getusernsidbypid(int pid)
@@ -47,14 +44,21 @@ static unsigned int getusernsidbypid(int pid)
static void run(void)
{
+ const struct tst_clone_args args1 = { .exit_signal = SIGCHLD };
+ const struct tst_clone_args args2 = {
+ .flags = CLONE_NEWUSER,
+ .exit_signal = SIGCHLD,
+ };
int cpid1, cpid2, cpid3;
unsigned int parentuserns, cpid1userns, cpid2userns, newparentuserns;
parentuserns = getusernsidbypid(getpid());
- cpid1 = ltp_clone_quick(SIGCHLD, (void *)child_fn1, NULL);
- if (cpid1 < 0)
- tst_brk(TBROK | TTERRNO, "clone failed");
+ cpid1 = SAFE_CLONE(&args1);
+ if (!cpid1) {
+ child_fn1();
+ return;
+ }
cpid1userns = getusernsidbypid(cpid1);
@@ -64,23 +68,20 @@ static void run(void)
* CLONE_NEWUSER flag is a member of the same user namespace as its
* parent
*/
- if (parentuserns != cpid1userns)
- tst_res(TFAIL, "userns:parent should be equal to cpid1");
- else
- tst_res(TPASS, "userns:parent is equal to cpid1");
+ TST_EXP_EQ_LI(parentuserns, cpid1userns);
- cpid2 = ltp_clone_quick(CLONE_NEWUSER | SIGCHLD, (void *)child_fn1, NULL);
- if (cpid2 < 0)
- tst_brk(TBROK | TTERRNO, "clone failed");
+ cpid2 = SAFE_CLONE(&args2);
+ if (!cpid2) {
+ child_fn1();
+ return;
+ }
cpid2userns = getusernsidbypid(cpid2);
TST_CHECKPOINT_WAKE(0);
- if (parentuserns == cpid2userns)
- tst_res(TFAIL, "userns:parent should be not equal to cpid2");
- else
- tst_res(TPASS, "userns:parent is not equal to cpid2");
+ TST_EXP_EXPR(parentuserns != cpid2userns,
+ "parent namespace != child namespace");
cpid3 = SAFE_FORK();
if (!cpid3) {
@@ -91,20 +92,12 @@ static void run(void)
* is moved into a new user namespace which is not shared
* with any previously existing process
*/
- if (parentuserns == newparentuserns)
- tst_res(TFAIL, "unshared namespaces with same id");
- else
- tst_res(TPASS, "unshared namespaces with different id");
+ TST_EXP_EXPR(parentuserns != newparentuserns,
+ "parent namespace != unshared child namespace");
}
}
-static void setup(void)
-{
- check_newuser();
-}
-
static struct tst_test test = {
- .setup = setup,
.test_all = run,
.needs_root = 1,
.forks_child = 1,
diff --git a/testcases/kernel/containers/userns/userns06.c b/testcases/kernel/containers/userns/userns06.c
index 39f02e38a..a270dafdc 100644
--- a/testcases/kernel/containers/userns/userns06.c
+++ b/testcases/kernel/containers/userns/userns06.c
@@ -20,6 +20,7 @@
#define _GNU_SOURCE
#include <stdio.h>
+#include "lapi/sched.h"
#include "common.h"
#define TEST_APP "userns06_capcheck"
@@ -29,7 +30,7 @@
#define CHILD2UID 200
#define CHILD2GID 200
-static int child_fn1(void)
+static void child_fn1(void)
{
char *const args[] = { TEST_APP, "privileged", NULL };
int ret;
@@ -39,11 +40,9 @@ static int child_fn1(void)
ret = execv(args[0], args);
if (ret == -1)
tst_brk(TBROK | TERRNO, "execv: unexpected error");
-
- return 0;
}
-static int child_fn2(void)
+static void child_fn2(void)
{
int uid, gid, ret;
char *const args[] = { TEST_APP, "unprivileged", NULL };
@@ -53,27 +52,20 @@ static int child_fn2(void)
uid = geteuid();
gid = getegid();
- if (uid != CHILD2UID || gid != CHILD2GID) {
- tst_res(TFAIL, "unexpected uid=%d gid=%d", uid, gid);
- return 1;
- }
-
- tst_res(TPASS, "expected uid and gid");
+ TST_EXP_EQ_LI(uid, CHILD2UID);
+ TST_EXP_EQ_LI(gid, CHILD2GID);
ret = execv(args[0], args);
if (ret == -1)
tst_brk(TBROK | TERRNO, "execv: unexpected error");
-
- return 0;
-}
-
-static void setup(void)
-{
- check_newuser();
}
static void run(void)
{
+ const struct tst_clone_args args = {
+ .flags = CLONE_NEWUSER,
+ .exit_signal = SIGCHLD,
+ };
pid_t cpid1;
pid_t cpid2;
int parentuid;
@@ -84,13 +76,17 @@ static void run(void)
parentuid = geteuid();
parentgid = getegid();
- cpid1 = ltp_clone_quick(CLONE_NEWUSER | SIGCHLD, (void *)child_fn1, NULL);
- if (cpid1 < 0)
- tst_brk(TBROK | TTERRNO, "cpid1 clone failed");
+ cpid1 = SAFE_CLONE(&args);
+ if (!cpid1) {
+ child_fn1();
+ return;
+ }
- cpid2 = ltp_clone_quick(CLONE_NEWUSER | SIGCHLD, (void *)child_fn2, NULL);
- if (cpid2 < 0)
- tst_brk(TBROK | TTERRNO, "cpid2 clone failed");
+ cpid2 = SAFE_CLONE(&args);
+ if (!cpid2) {
+ child_fn2();
+ return;
+ }
if (access("/proc/self/setgroups", F_OK) == 0) {
sprintf(path, "/proc/%d/setgroups", cpid1);
@@ -117,9 +113,9 @@ static void run(void)
}
static struct tst_test test = {
- .setup = setup,
.test_all = run,
.needs_root = 1,
+ .forks_child = 1,
.needs_checkpoints = 1,
.resource_files = (const char *[]) {
TEST_APP,
diff --git a/testcases/kernel/containers/userns/userns06_capcheck.c b/testcases/kernel/containers/userns/userns06_capcheck.c
index c048ef63f..8669657b9 100644
--- a/testcases/kernel/containers/userns/userns06_capcheck.c
+++ b/testcases/kernel/containers/userns/userns06_capcheck.c
@@ -24,8 +24,8 @@ int main(int argc, char *argv[])
{
cap_t caps;
int i, last_cap;
- cap_flag_value_t flag_val;
- cap_flag_value_t expected_flag = 1;
+ cap_flag_value_t cap_flag;
+ cap_flag_value_t expected_cap_flag = 1;
tst_reinit();
@@ -35,24 +35,21 @@ int main(int argc, char *argv[])
SAFE_FILE_SCANF("/proc/sys/kernel/cap_last_cap", "%d", &last_cap);
if (strcmp("privileged", argv[1]))
- expected_flag = 0;
+ expected_cap_flag = 0;
caps = cap_get_proc();
for (i = 0; i <= last_cap; i++) {
- cap_get_flag(caps, i, CAP_EFFECTIVE, &flag_val);
- if (flag_val != expected_flag)
+ cap_get_flag(caps, i, CAP_EFFECTIVE, &cap_flag);
+ if (cap_flag != expected_cap_flag)
break;
- cap_get_flag(caps, i, CAP_PERMITTED, &flag_val);
- if (flag_val != expected_flag)
+ cap_get_flag(caps, i, CAP_PERMITTED, &cap_flag);
+ if (cap_flag != expected_cap_flag)
break;
}
- if (flag_val != expected_flag)
- tst_res(TFAIL, "unexpected effective/permitted caps at %d", i);
- else
- tst_res(TPASS, "expected caps at %d", i);
+ TST_EXP_EQ_LI(cap_flag, expected_cap_flag);
return 0;
}
diff --git a/testcases/kernel/containers/userns/userns07.c b/testcases/kernel/containers/userns/userns07.c
index 4659de636..2217a5ed0 100644
--- a/testcases/kernel/containers/userns/userns07.c
+++ b/testcases/kernel/containers/userns/userns07.c
@@ -16,19 +16,17 @@
#include <sys/wait.h>
#include "common.h"
#include "tst_test.h"
+#include "lapi/sched.h"
#define MAXNEST 32
-static void setup(void)
+static void child_fn1(const int level)
{
- check_newuser();
-}
-
-static int child_fn1(void *arg)
-{
- pid_t cpid1;
- long level = (long)arg;
- int status;
+ const struct tst_clone_args args = {
+ .flags = CLONE_NEWUSER,
+ .exit_signal = SIGCHLD,
+ };
+ pid_t cpid;
int parentuid;
int parentgid;
@@ -36,63 +34,68 @@ static int child_fn1(void *arg)
if (level == MAXNEST) {
tst_res(TPASS, "nested all children");
- return 0;
+ return;
}
- cpid1 = ltp_clone_quick(CLONE_NEWUSER | SIGCHLD, (void *)child_fn1, (void *)(level + 1));
- if (cpid1 < 0) {
- tst_res(TFAIL | TERRNO, "level %ld, unexpected error", level);
- return 1;
+ cpid = SAFE_CLONE(&args);
+ if (!cpid) {
+ child_fn1(level + 1);
+ return;
}
parentuid = geteuid();
parentgid = getegid();
- updatemap(cpid1, UID_MAP, 0, parentuid);
- updatemap(cpid1, GID_MAP, 0, parentgid);
+ updatemap(cpid, UID_MAP, 0, parentuid);
+ updatemap(cpid, GID_MAP, 0, parentgid);
TST_CHECKPOINT_WAKE(0);
- SAFE_WAITPID(cpid1, &status, 0);
-
- if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
- tst_brk(TBROK, "child %s", tst_strstatus(status));
-
- return 0;
+ tst_reap_children();
}
static void run(void)
{
- pid_t cpid1;
+ const struct tst_clone_args args = {
+ .flags = CLONE_NEWUSER,
+ .exit_signal = SIGCHLD,
+ };
+ pid_t cpid;
int parentuid;
int parentgid;
char path[BUFSIZ];
- cpid1 = ltp_clone_quick(CLONE_NEWUSER | SIGCHLD, (void *)child_fn1, (void *)0);
- if (cpid1 < 0)
- tst_brk(TBROK | TTERRNO, "clone failed");
+ cpid = SAFE_CLONE(&args);
+ if (!cpid) {
+ child_fn1(0);
+ return;
+ }
parentuid = geteuid();
parentgid = getegid();
if (access("/proc/self/setgroups", F_OK) == 0) {
- sprintf(path, "/proc/%d/setgroups", cpid1);
+ sprintf(path, "/proc/%d/setgroups", cpid);
SAFE_FILE_PRINTF(path, "deny");
}
- updatemap(cpid1, UID_MAP, 0, parentuid);
- updatemap(cpid1, GID_MAP, 0, parentgid);
+ updatemap(cpid, UID_MAP, 0, parentuid);
+ updatemap(cpid, GID_MAP, 0, parentgid);
TST_CHECKPOINT_WAKE(0);
}
static struct tst_test test = {
- .setup = setup,
.test_all = run,
.needs_root = 1,
+ .forks_child = 1,
.needs_checkpoints = 1,
.needs_kconfigs = (const char *[]) {
"CONFIG_USER_NS",
NULL,
},
+ .save_restore = (const struct tst_path_val[]) {
+ {"/proc/sys/kernel/unprivileged_userns_clone", "1", TST_SR_SKIP},
+ {}
+ },
};
diff --git a/testcases/kernel/containers/userns/userns08.c b/testcases/kernel/containers/userns/userns08.c
index 2697d874b..72d7f8d12 100644
--- a/testcases/kernel/containers/userns/userns08.c
+++ b/testcases/kernel/containers/userns/userns08.c
@@ -31,8 +31,8 @@
static pid_t clone_newuser(void)
{
const struct tst_clone_args cargs = {
- CLONE_NEWUSER,
- SIGCHLD
+ .flags = CLONE_NEWUSER,
+ .exit_signal = SIGCHLD,
};
return SAFE_CLONE(&cargs);
@@ -136,6 +136,7 @@ static struct tst_test test = {
},
.save_restore = (const struct tst_path_val[]) {
{"/proc/sys/user/max_user_namespaces", NULL, TST_SR_SKIP},
+ {"/proc/sys/kernel/unprivileged_userns_clone", "1", TST_SR_SKIP},
{}
},
.tags = (const struct tst_tag[]) {
diff --git a/testcases/kernel/containers/userns/userns_helper.h b/testcases/kernel/containers/userns/userns_helper.h
deleted file mode 100644
index be47690ea..000000000
--- a/testcases/kernel/containers/userns/userns_helper.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (c) Huawei Technologies Co., Ltd., 2015
- * 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.
- */
-
-#include "../libclone/libclone.h"
-#include "test.h"
-#include "safe_macros.h"
-#include <stdbool.h>
-
-#define UID_MAP 0
-#define GID_MAP 1
-
-static int dummy_child(void *v)
-{
- (void) v;
- return 0;
-}
-
-static int check_newuser(void)
-{
- int pid, status;
-
- pid = do_clone_unshare_test(T_CLONE, CLONE_NEWUSER, dummy_child, NULL);
- if (pid == -1)
- tst_brkm(TCONF | TERRNO, NULL, "CLONE_NEWUSER not supported");
- SAFE_WAIT(NULL, &status);
-
- return 0;
-}
-
-LTP_ATTRIBUTE_UNUSED static int updatemap(int cpid, bool type, int idnum,
- int parentmappid, void (*cleanup)(void))
-{
- char path[BUFSIZ];
- char content[BUFSIZ];
- int fd;
-
- if (type == UID_MAP)
- sprintf(path, "/proc/%d/uid_map", cpid);
- else if (type == GID_MAP)
- sprintf(path, "/proc/%d/gid_map", cpid);
- else
- tst_brkm(TBROK, cleanup, "invalid type parameter");
-
- sprintf(content, "%d %d 1", idnum, parentmappid);
- fd = SAFE_OPEN(cleanup, path, O_WRONLY, 0644);
- SAFE_WRITE(cleanup, SAFE_WRITE_ALL, fd, content, strlen(content));
- SAFE_CLOSE(cleanup, fd);
- return 0;
-}
diff --git a/testcases/kernel/containers/utsname/.gitignore b/testcases/kernel/containers/utsname/.gitignore
index 0e1f41dc8..945ed280e 100644
--- a/testcases/kernel/containers/utsname/.gitignore
+++ b/testcases/kernel/containers/utsname/.gitignore
@@ -1 +1,4 @@
-/utstest
+/utsname01
+/utsname02
+/utsname03
+/utsname04
diff --git a/testcases/kernel/containers/utsname/Makefile b/testcases/kernel/containers/utsname/Makefile
index 5efcbf648..b6beb8b8f 100644
--- a/testcases/kernel/containers/utsname/Makefile
+++ b/testcases/kernel/containers/utsname/Makefile
@@ -1,28 +1,7 @@
-################################################################################
-## ##
-## Copyright (c) International Business Machines Corp., 2007 ##
-## ##
-## 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 ##
-## ##
-################################################################################
+# SPDX-License-Identifier: GPL-2.0-or-later
+# Copyright (C) 2021 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
top_srcdir ?= ../../../..
include $(top_srcdir)/include/mk/testcases.mk
-include $(abs_srcdir)/../Makefile.inc
-
-LDLIBS := -lclone -lpthread -lrt $(LDLIBS)
-
include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/containers/utsname/runutstests_noltp.sh b/testcases/kernel/containers/utsname/runutstests_noltp.sh
deleted file mode 100755
index 43cb7e26b..000000000
--- a/testcases/kernel/containers/utsname/runutstests_noltp.sh
+++ /dev/null
@@ -1,41 +0,0 @@
-#!/bin/sh
-################################################################################
-## ##
-## Copyright (c) International Business Machines Corp., 2007 ##
-## ##
-## 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 ##
-## ##
-################################################################################
-
-oldhostname=`hostname`
-exit_code=0
-echo "unshare tests"
-for i in `seq 1 5`; do
- echo "test $i (unshare)"
- ./utstest_noltp unshare $i
- if [ $? -ne 0 ]; then
- exit_code=$?
- fi
-done
-echo "clone tests"
-for i in `seq 1 5`; do
- echo "test $i (clone)"
- ./utstest_noltp clone $i
- if [ $? -ne 0 ]; then
- exit_code=$?
- fi
-done
-hostname "$oldhostname"
-exit $exit_code
diff --git a/testcases/kernel/containers/utsname/utsname01.c b/testcases/kernel/containers/utsname/utsname01.c
new file mode 100644
index 000000000..fc5c1a271
--- /dev/null
+++ b/testcases/kernel/containers/utsname/utsname01.c
@@ -0,0 +1,56 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * [Description]
+ *
+ * Clone two plain processes and check if both read the same hostname.
+ */
+
+#define _GNU_SOURCE
+
+#include "tst_test.h"
+
+static char *hostname1;
+static char *hostname2;
+
+static void run(void)
+{
+ memset(hostname1, 0, HOST_NAME_MAX);
+ memset(hostname2, 0, HOST_NAME_MAX);
+
+ if (!SAFE_FORK()) {
+ SAFE_GETHOSTNAME(hostname1, HOST_NAME_MAX);
+ return;
+ }
+
+ if (!SAFE_FORK()) {
+ SAFE_GETHOSTNAME(hostname2, HOST_NAME_MAX);
+ return;
+ }
+
+ tst_reap_children();
+
+ TST_EXP_PASS(strcmp(hostname1, hostname2));
+}
+
+static void setup(void)
+{
+ hostname1 = SAFE_MMAP(NULL, HOST_NAME_MAX, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
+ hostname2 = SAFE_MMAP(NULL, HOST_NAME_MAX, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
+}
+
+static void cleanup(void)
+{
+ SAFE_MUNMAP(hostname1, HOST_NAME_MAX);
+ SAFE_MUNMAP(hostname2, HOST_NAME_MAX);
+}
+
+static struct tst_test test = {
+ .test_all = run,
+ .setup = setup,
+ .cleanup = cleanup,
+ .forks_child = 1,
+};
diff --git a/testcases/kernel/containers/utsname/utsname02.c b/testcases/kernel/containers/utsname/utsname02.c
new file mode 100644
index 000000000..aa90596d4
--- /dev/null
+++ b/testcases/kernel/containers/utsname/utsname02.c
@@ -0,0 +1,81 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * [Description]
+ *
+ * Clone two plain processes, change hostname in the first one then check if
+ * hostaname has changed inside the second one as well.
+ */
+
+#define _GNU_SOURCE
+
+#include "tst_test.h"
+
+#define HOSTNAME "LTP_HOSTNAME"
+
+static char *hostname1;
+static char *hostname2;
+static char originalhost[HOST_NAME_MAX];
+
+static void reset_hostname(void)
+{
+ SAFE_SETHOSTNAME(originalhost, strlen(originalhost));
+}
+
+static void run(void)
+{
+ memset(hostname1, 0, HOST_NAME_MAX);
+ memset(hostname2, 0, HOST_NAME_MAX);
+
+ if (!SAFE_FORK()) {
+ SAFE_SETHOSTNAME(HOSTNAME, strlen(HOSTNAME));
+ SAFE_GETHOSTNAME(hostname1, HOST_NAME_MAX);
+
+ TST_CHECKPOINT_WAKE(0);
+ return;
+ }
+
+ if (!SAFE_FORK()) {
+ TST_CHECKPOINT_WAIT(0);
+
+ SAFE_GETHOSTNAME(hostname2, HOST_NAME_MAX);
+ return;
+ }
+
+ tst_reap_children();
+
+ TST_EXP_PASS(strcmp(hostname1, HOSTNAME));
+ TST_EXP_PASS(strcmp(hostname2, HOSTNAME));
+
+ reset_hostname();
+}
+
+static void setup(void)
+{
+ hostname1 = SAFE_MMAP(NULL, HOST_NAME_MAX, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
+ hostname2 = SAFE_MMAP(NULL, HOST_NAME_MAX, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
+
+ memset(originalhost, 0, HOST_NAME_MAX);
+
+ SAFE_GETHOSTNAME(originalhost, HOST_NAME_MAX);
+}
+
+static void cleanup(void)
+{
+ SAFE_MUNMAP(hostname1, HOST_NAME_MAX);
+ SAFE_MUNMAP(hostname2, HOST_NAME_MAX);
+
+ reset_hostname();
+}
+
+static struct tst_test test = {
+ .test_all = run,
+ .setup = setup,
+ .cleanup = cleanup,
+ .needs_root = 1,
+ .forks_child = 1,
+ .needs_checkpoints = 1,
+};
diff --git a/testcases/kernel/containers/utsname/utsname03.c b/testcases/kernel/containers/utsname/utsname03.c
new file mode 100644
index 000000000..e5a4a56dc
--- /dev/null
+++ b/testcases/kernel/containers/utsname/utsname03.c
@@ -0,0 +1,121 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) International Business Machines Corp., 2007
+ * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * [Description]
+ *
+ * Clone two processes using CLONE_NEWUTS, change hostname from the first
+ * container and check if hostname didn't change inside the second one.
+ */
+
+#define _GNU_SOURCE
+
+#include "tst_test.h"
+#include "lapi/sched.h"
+
+#define HOSTNAME "LTP_HOSTNAME"
+
+static char *str_op;
+static char *hostname1;
+static char *hostname2;
+static char originalhost[HOST_NAME_MAX];
+
+static void reset_hostname(void)
+{
+ SAFE_SETHOSTNAME(originalhost, strlen(originalhost));
+}
+
+static void child1_run(void)
+{
+ SAFE_SETHOSTNAME(HOSTNAME, strlen(HOSTNAME));
+ SAFE_GETHOSTNAME(hostname1, HOST_NAME_MAX);
+
+ TST_CHECKPOINT_WAKE(0);
+}
+
+static void child2_run(void)
+{
+ TST_CHECKPOINT_WAIT(0);
+
+ SAFE_GETHOSTNAME(hostname2, HOST_NAME_MAX);
+}
+
+static void run(void)
+{
+ const struct tst_clone_args cargs = {
+ .flags = CLONE_NEWUTS,
+ .exit_signal = SIGCHLD,
+ };
+
+ memset(hostname1, 0, HOST_NAME_MAX);
+ memset(hostname2, 0, HOST_NAME_MAX);
+
+ if (!str_op || !strcmp(str_op, "clone")) {
+ tst_res(TINFO, "clone() with CLONE_NEWUTS");
+
+ if (!SAFE_CLONE(&cargs)) {
+ child1_run();
+ return;
+ }
+
+ if (!SAFE_CLONE(&cargs)) {
+ child2_run();
+ return;
+ }
+ } else {
+ tst_res(TINFO, "unshare() with CLONE_NEWUTS");
+
+ if (!SAFE_FORK()) {
+ SAFE_UNSHARE(CLONE_NEWUTS);
+ child1_run();
+ return;
+ }
+
+ if (!SAFE_FORK()) {
+ SAFE_UNSHARE(CLONE_NEWUTS);
+ child2_run();
+ return;
+ }
+ }
+
+ tst_reap_children();
+
+ TST_EXP_PASS(strcmp(hostname1, HOSTNAME));
+ TST_EXP_PASS(strcmp(hostname2, originalhost));
+
+ reset_hostname();
+}
+
+static void setup(void)
+{
+ hostname1 = SAFE_MMAP(NULL, HOST_NAME_MAX, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
+ hostname2 = SAFE_MMAP(NULL, HOST_NAME_MAX, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
+
+ memset(originalhost, 0, HOST_NAME_MAX);
+
+ SAFE_GETHOSTNAME(originalhost, HOST_NAME_MAX);
+}
+
+static void cleanup(void)
+{
+ SAFE_MUNMAP(hostname1, HOST_NAME_MAX);
+ SAFE_MUNMAP(hostname2, HOST_NAME_MAX);
+
+ reset_hostname();
+}
+
+static struct tst_test test = {
+ .test_all = run,
+ .setup = setup,
+ .cleanup = cleanup,
+ .needs_root = 1,
+ .forks_child = 1,
+ .needs_checkpoints = 1,
+ .options = (struct tst_option[]) {
+ { "m:", &str_op, "Test execution mode <clone|unshare>" },
+ {},
+ },
+};
diff --git a/testcases/kernel/containers/utsname/utsname04.c b/testcases/kernel/containers/utsname/utsname04.c
new file mode 100644
index 000000000..bf97880ba
--- /dev/null
+++ b/testcases/kernel/containers/utsname/utsname04.c
@@ -0,0 +1,63 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * [Description]
+ *
+ * Drop root privileges, create a container with CLONE_NEWUTS and verify that
+ * we receive a permission error.
+ */
+
+#define _GNU_SOURCE
+
+#include <pwd.h>
+#include "tst_test.h"
+#include "lapi/sched.h"
+
+static char *str_op;
+
+static void run(void)
+{
+ const struct tst_clone_args cargs = {
+ .flags = CLONE_NEWUTS,
+ .exit_signal = SIGCHLD,
+ };
+ struct passwd *pw;
+
+ tst_res(TINFO, "Dropping root privileges");
+
+ pw = SAFE_GETPWNAM("nobody");
+ SAFE_SETRESUID(pw->pw_uid, pw->pw_uid, pw->pw_uid);
+
+ if (!str_op || !strcmp(str_op, "clone")) {
+ TEST(tst_clone(&cargs));
+
+ if (TST_RET == -1)
+ tst_res(TPASS, "clone3() fails as expected");
+ else if (TST_RET == -2)
+ tst_res(TPASS, "clone() fails as expected");
+ else
+ tst_res(TFAIL, "tst_clone returns %ld", TST_RET);
+
+ TST_EXP_PASS(errno == EPERM);
+ } else {
+ if (!SAFE_FORK()) {
+ TST_EXP_EQ_LI(unshare(CLONE_NEWUTS), -1);
+ TST_EXP_PASS(errno == EPERM);
+ return;
+ }
+ }
+}
+
+static struct tst_test test = {
+ .test_all = run,
+ .needs_root = 1,
+ .forks_child = 1,
+ .needs_checkpoints = 1,
+ .options = (struct tst_option[]) {
+ { "m:", &str_op, "Test execution mode <clone|unshare>" },
+ {},
+ },
+};
diff --git a/testcases/kernel/containers/utsname/utstest.c b/testcases/kernel/containers/utsname/utstest.c
deleted file mode 100644
index 9ad19b6b2..000000000
--- a/testcases/kernel/containers/utsname/utstest.c
+++ /dev/null
@@ -1,353 +0,0 @@
-/*
-* Copyright (c) International Business Machines Corp., 2007
-* 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 2007 IBM
- * Author: Serge Hallyn <serue@us.ibm.com>
- *
- * test1:
- P1: A=gethostname
- P2: B=gethostname
- Ensure(A==B)
-
- * test2:
- P1: sethostname(A);
- P2: (wait); B=gethostname
- Ensure (A==B)
-
- * test3:
- P1: A=gethostname; unshare(utsname); sethostname(newname); C=gethostname
- P2: B=gethostname; (wait); (wait); D=gethostname
- Ensure (A==B && A==D && C!=D)
-
- * test4:
- P1: A=gethostname; unshare(utsname); (wait); C=gethostname
- P2: B=gethostname; (wait); sethostname(newname); D=gethostname
- Ensure (A==B && A==C && C!=D)
-
- * test5:
- P1: drop_privs(); unshare(utsname); (wait); C=gethostname
- P2: (wait); sethostname(B); D=gethostname
- Ensure (B==C==D) and state is ok.
- *
- */
-
-#define _GNU_SOURCE 1
-#include <sys/wait.h>
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include "libclone.h"
-#include "test.h"
-#include "safe_macros.h"
-
-char *TCID = "uts_namespace";
-int TST_TOTAL = 1;
-
-static int dummy_child(void *v)
-{
- (void) v;
- return 0;
-}
-
-static void check_newuts(void)
-{
- int pid, status;
-
- pid = do_clone_unshare_test(T_CLONE, CLONE_NEWUTS, dummy_child, NULL);
- if (pid == -1)
- tst_brkm(TCONF | TERRNO, NULL, "CLONE_NEWUTS not supported");
-
- SAFE_WAIT(NULL, &status);
-}
-
-int drop_root(void)
-{
- int ret;
- ret = setresuid(1000, 1000, 1000);
- if (ret) {
- perror("setresuid");
- exit(4);
- }
- return 1;
-}
-
-#define HLEN 100
-#define NAME1 "serge1"
-#define NAME2 "serge2"
-
-int p1fd[2], p2fd[2];
-static char oldhost[HLEN];
-pid_t cpid;
-
-void picknewhostname(char *orig, char *new)
-{
- memset(new, 0, HLEN);
- if (strcmp(orig, NAME1) == 0)
- strcpy(new, NAME2);
- else
- strcpy(new, NAME1);
-}
-
-void zeroize(char *s)
-{
- memset(s, 0, HLEN);
-}
-
-char *tsttype;
-int P1(void *vtest)
-{
- char hostname[HLEN], newhostname[HLEN], rhostname[HLEN];
- int err;
- int len;
- int testnum;
-
- testnum = atoi((char *)vtest);
-
- close(p1fd[1]);
- close(p2fd[0]);
-
- switch (testnum) {
- case 1:
- gethostname(hostname, HLEN);
- zeroize(rhostname);
- len = read(p1fd[0], rhostname, HLEN);
- if (strcmp(hostname, rhostname) == 0) {
- tst_resm(TPASS, "test 1 (%s): success", tsttype);
- tst_exit();
- }
- tst_brkm(TFAIL, NULL,
- "test 1 (%s): hostname 1 %s, hostname 2 %s",
- tsttype, hostname, rhostname);
- case 2:
- gethostname(hostname, HLEN);
- picknewhostname(hostname, newhostname);
- err = sethostname(newhostname, strlen(newhostname));
- write(p2fd[1], "1", 1);
- if (err == -1) {
- tst_brkm(TFAIL, NULL,
- "test 2 (%s): failed to sethostname",
- tsttype);
- }
- zeroize(rhostname);
- len = read(p1fd[0], rhostname, HLEN);
- if (strcmp(newhostname, rhostname) == 0) {
- tst_resm(TPASS, "test 2 (%s): success", tsttype);
- tst_exit();
- }
- tst_brkm(TFAIL, NULL,
- "test 2 (%s) hostname 1 %s, hostname 2 %s",
- tsttype, newhostname, rhostname);
- case 3:
- gethostname(hostname, HLEN);
- picknewhostname(hostname, newhostname);
- err = sethostname(newhostname, strlen(newhostname));
- write(p2fd[1], "1", 1);
- if (err == -1) {
- tst_brkm(TFAIL, NULL,
- "test 3 (%s): failed to sethostname",
- tsttype);
- }
-
- zeroize(rhostname);
- len = read(p1fd[0], rhostname, HLEN);
- if (strcmp(newhostname, rhostname) == 0) {
- tst_brkm(TFAIL,
- NULL,
- "test 3 (%s): hostname 1 %s, hostname 2 %s, these should have been different",
- tsttype, newhostname, rhostname);
- }
- if (strcmp(hostname, rhostname) == 0) {
- tst_resm(TPASS, "test 3 (%s): success", tsttype);
- tst_exit();
- }
- tst_brkm(TFAIL,
- NULL,
- "test 3 (%s): hostname 1 %s, hostname 2 %s, should have been same",
- tsttype, hostname, rhostname);
-
- case 4:
- gethostname(hostname, HLEN);
- write(p2fd[1], "1", 1); /* tell p2 to go ahead and sethostname */
- zeroize(rhostname);
- len = read(p1fd[0], rhostname, HLEN);
- gethostname(newhostname, HLEN);
- if (strcmp(hostname, newhostname) != 0) {
- tst_brkm(TFAIL,
- NULL,
- "test 4 (%s): hostname 1 %s, hostname 2 %s, should be same",
- tsttype, hostname, newhostname);
- }
- if (strcmp(hostname, rhostname) == 0) {
- tst_brkm(TFAIL,
- NULL,
- "test 4 (%s): hostname 1 %s, hostname 2 %s, should be different",
- tsttype, hostname, rhostname);
- }
- tst_resm(TPASS, "test 4 (%s): successful", tsttype);
- tst_exit();
- case 5:
- write(p2fd[1], "1", 1); /* tell p2 to go ahead and sethostname */
- zeroize(rhostname);
- len = read(p1fd[0], rhostname, HLEN);
- gethostname(newhostname, HLEN);
- if (strcmp(rhostname, newhostname) != 0) {
- tst_brkm(TFAIL,
- NULL,
- "test 5 (%s): hostnames %s and %s should be same",
- tsttype, rhostname, newhostname);
- }
- tst_resm(TPASS, "test 5 (%s): successful", tsttype);
- tst_exit();
- default:
- break;
- }
- tst_exit();
-}
-
-int P2(void *vtest)
-{
- char hostname[HLEN], newhostname[HLEN];
- int len;
- int testnum;
-
- testnum = atoi((char *)vtest);
-
- close(p1fd[0]);
- close(p2fd[1]);
-
- switch (testnum) {
- case 1:
- gethostname(hostname, HLEN);
- write(p1fd[1], hostname, strlen(hostname));
- break;
- case 2:
- case 3:
- len = 0;
- while (!len) {
- len = read(p2fd[0], hostname, 1);
- }
- gethostname(hostname, HLEN);
- write(p1fd[1], hostname, strlen(hostname));
- break;
- case 4:
- case 5:
- len = 0;
- while (!len) {
- len = read(p2fd[0], hostname, 1);
- }
- if (hostname[0] == '0') {
- tst_resm(TPASS, "P2: P1 claims error");
- return 0;
- }
- gethostname(hostname, HLEN);
- picknewhostname(hostname, newhostname);
- sethostname(newhostname, strlen(newhostname));
- write(p1fd[1], newhostname, strlen(newhostname));
- break;
- default:
- tst_resm(TFAIL, "undefined test: %d", testnum);
- break;
- }
- return 0;
-}
-
-static void setup(void)
-{
- gethostname(oldhost, HLEN);
- tst_require_root();
- check_newuts();
-}
-
-static void cleanup(void)
-{
- sethostname(oldhost, strlen(oldhost));
-}
-
-#define UNSHARESTR "unshare"
-#define CLONESTR "clone"
-int main(int argc, char *argv[])
-{
- int r, pid, use_clone = T_UNSHARE;
- int testnum;
- void *vtest;
-
- setup();
- if (argc != 3) {
- tst_resm(TFAIL, "Usage: %s <clone|unshare> <testnum>",
- argv[0]);
- tst_resm(TFAIL,
- " where clone or unshare specifies unshare method,");
- tst_resm(TFAIL, " and testnum is between 1 and 5 inclusive");
- exit(2);
- }
- if (pipe(p1fd) == -1) {
- perror("pipe");
- exit(EXIT_FAILURE);
- }
- if (pipe(p2fd) == -1) {
- perror("pipe");
- exit(EXIT_FAILURE);
- }
-
- tsttype = UNSHARESTR;
- if (strcmp(argv[1], "clone") == 0) {
- use_clone = T_CLONE;
- tsttype = CLONESTR;
- }
-
- testnum = atoi(argv[2]);
-
- vtest = (void *)argv[2];
- switch (testnum) {
- case 1:
- case 2:
- r = do_clone_unshare_tests(T_NONE, 0, P1, vtest, P2, vtest);
- break;
- case 3:
- case 4:
- r = do_clone_unshare_tests(use_clone, CLONE_NEWUTS,
- P1, vtest, P2, vtest);
- break;
- case 5:
- pid = fork();
- if (pid == -1) {
- perror("fork");
- exit(2);
- }
- if (pid == 0) {
- if (!drop_root()) {
- tst_brkm(TFAIL, NULL, "failed to drop root.");
- }
- r = do_clone_unshare_test(use_clone, CLONE_NEWUTS,
- P1, vtest);
- write(p2fd[1], "0", 1); /* don't let p2 hang */
- exit(0);
- } else {
- P2(vtest);
- }
- break;
- default:
- tst_resm(TFAIL,
- "testnum should be between 1 and 5 inclusive.");
- break;
- }
-
- cleanup();
- tst_exit();
-}
diff --git a/testcases/kernel/controllers/cgroup/.gitignore b/testcases/kernel/controllers/cgroup/.gitignore
index 8deae77da..9f1d1ada9 100644
--- a/testcases/kernel/controllers/cgroup/.gitignore
+++ b/testcases/kernel/controllers/cgroup/.gitignore
@@ -2,3 +2,4 @@
/cgroup_regression_getdelays
/cgroup_core01
/cgroup_core02
+/cgroup_core03
diff --git a/testcases/kernel/controllers/cgroup/cgroup_core03.c b/testcases/kernel/controllers/cgroup/cgroup_core03.c
new file mode 100644
index 000000000..7d40d47f9
--- /dev/null
+++ b/testcases/kernel/controllers/cgroup/cgroup_core03.c
@@ -0,0 +1,131 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2012 Christian Brauner <brauner-AT-kernel.org>
+ * Copyright (c) 2023 SUSE LLC <wegao@suse.com>
+ */
+
+/*\
+ * [Description]
+ *
+ * This test is copied from kselftest
+ * tools/testing/selftests/cgroup/test_kill.c.
+ *
+ * Only simple test implemented within current case, the other cases such
+ * as test_cgkill_tree and test_cgkill_forkbomb can be created later.
+ *
+ */
+
+#include <sys/wait.h>
+
+#include "lapi/syscalls.h"
+#include "tst_test.h"
+
+#define MAX_PID_NUM 100
+#define PID_NUM MIN(MAX_PID_NUM, (tst_ncpus_available() + 1))
+#define BUF_LEN (20 * PID_NUM)
+
+static int *data_ptr;
+static char *buf;
+static struct tst_cg_group *cg_child_test_simple;
+
+static int wait_for_pid(pid_t pid)
+{
+ int status, ret;
+
+again:
+ ret = waitpid(pid, &status, 0);
+ if (ret == -1) {
+ if (errno == EINTR)
+ goto again;
+
+ return -1;
+ }
+
+ if (WIFSIGNALED(status))
+ return 0;
+
+ return -1;
+}
+
+static int cg_run_nowait(const struct tst_cg_group *const cg)
+{
+ int pid;
+
+ pid = SAFE_FORK();
+ if (pid == 0) {
+ SAFE_CG_PRINTF(cg, "cgroup.procs", "%d", getpid());
+ if (tst_atomic_inc(data_ptr) == PID_NUM)
+ TST_CHECKPOINT_WAKE(0);
+ pause();
+ }
+
+ return pid;
+}
+
+static int cg_count_procs(const struct tst_cg_group *cg)
+{
+ char *ptr;
+
+ int nr = 0;
+
+ SAFE_CG_READ(cg, "cgroup.procs", buf, BUF_LEN);
+
+ for (ptr = buf; *ptr; ptr++)
+ if (*ptr == '\n')
+ nr++;
+
+ return nr;
+}
+
+static void run(void)
+{
+ pid_t pids[MAX_PID_NUM];
+ int i;
+ *data_ptr = 0;
+
+ cg_child_test_simple = tst_cg_group_mk(tst_cg, "cg_test_simple");
+
+ if (!SAFE_CG_HAS(cg_child_test_simple, "cgroup.kill")) {
+ cg_child_test_simple = tst_cg_group_rm(cg_child_test_simple);
+ tst_brk(TCONF, "cgroup.kill is not supported on your distribution");
+ }
+
+ memset(buf, 0, BUF_LEN);
+
+ for (i = 0; i < PID_NUM; i++)
+ pids[i] = cg_run_nowait(cg_child_test_simple);
+
+ TST_CHECKPOINT_WAIT(0);
+ TST_EXP_VAL(cg_count_procs(cg_child_test_simple), PID_NUM);
+ SAFE_CG_PRINTF(cg_child_test_simple, "cgroup.kill", "%d", 1);
+
+ for (i = 0; i < PID_NUM; i++)
+ TST_EXP_PASS_SILENT(wait_for_pid(pids[i]));
+
+ TST_EXP_VAL(cg_count_procs(cg_child_test_simple), 0);
+ cg_child_test_simple = tst_cg_group_rm(cg_child_test_simple);
+}
+
+static void setup(void)
+{
+ buf = tst_alloc(BUF_LEN);
+ data_ptr = SAFE_MMAP(NULL, sizeof(uintptr_t), PROT_READ | PROT_WRITE,
+ MAP_SHARED | MAP_ANONYMOUS, -1, 0);
+}
+
+static void cleanup(void)
+{
+ if (data_ptr)
+ SAFE_MUNMAP(data_ptr, sizeof(uintptr_t));
+}
+
+static struct tst_test test = {
+ .test_all = run,
+ .setup = setup,
+ .cleanup = cleanup,
+ .forks_child = 1,
+ .max_runtime = 20,
+ .needs_cgroup_ctrls = (const char *const []){ "base", NULL },
+ .needs_cgroup_ver = TST_CG_V2,
+ .needs_checkpoints = 1,
+};
diff --git a/testcases/kernel/controllers/cgroup_fj/cgroup_fj_stress.sh b/testcases/kernel/controllers/cgroup_fj/cgroup_fj_stress.sh
index d80b83bbd..72d3c53f4 100755
--- a/testcases/kernel/controllers/cgroup_fj/cgroup_fj_stress.sh
+++ b/testcases/kernel/controllers/cgroup_fj/cgroup_fj_stress.sh
@@ -7,7 +7,7 @@
TCID="cgroup_fj_stress"
TST_CNT=1
-TST_TESTFUNC=test
+TST_TESTFUNC=do_test
TST_SETUP=setup
TST_CLEANUP=cleanup
TST_POS_ARGS=4
@@ -126,7 +126,7 @@ cleanup()
common_cleanup
}
-test()
+do_test()
{
tst_res TINFO "Creating subgroups ..."
diff --git a/testcases/kernel/controllers/cpuctl/run_cpuctl_stress_test.sh b/testcases/kernel/controllers/cpuctl/run_cpuctl_stress_test.sh
index 3fcba1491..5b53544cf 100755
--- a/testcases/kernel/controllers/cpuctl/run_cpuctl_stress_test.sh
+++ b/testcases/kernel/controllers/cpuctl/run_cpuctl_stress_test.sh
@@ -200,7 +200,7 @@ usage ()
cleanup;
exit -1;
else
- echo "Succesfully launched def task $! too";
+ echo "Successfully launched def task $! too";
fi
;;
"9" )
@@ -279,7 +279,7 @@ usage ()
cleanup;
exit -1;
else
- echo "Succesfully launched def task $! too";
+ echo "Successfully launched def task $! too";
fi
;;
"10" )
@@ -346,7 +346,7 @@ usage ()
cleanup;
exit -1;
else
- echo "Succesfully launched def task $! too";
+ echo "Successfully launched def task $! too";
fi
;;
* )
diff --git a/testcases/kernel/controllers/cpuctl/run_cpuctl_test.sh b/testcases/kernel/controllers/cpuctl/run_cpuctl_test.sh
index bbbd2fbcb..5b09fb273 100755
--- a/testcases/kernel/controllers/cpuctl/run_cpuctl_test.sh
+++ b/testcases/kernel/controllers/cpuctl/run_cpuctl_test.sh
@@ -144,7 +144,7 @@ NUM_CPUS=`tst_ncpus`
cleanup;
exit -1;
else
- echo "Succesfully launched def task $! too";
+ echo "Successfully launched def task $! too";
fi
;;
"4" )
@@ -210,7 +210,7 @@ NUM_CPUS=`tst_ncpus`
cleanup;
exit -1;
else
- echo "Succesfully launched def task $! too";
+ echo "Successfully launched def task $! too";
fi
;;
"5" )
@@ -270,7 +270,7 @@ NUM_CPUS=`tst_ncpus`
cleanup;
exit -1;
else
- echo "Succesfully launched def task $! too";
+ echo "Successfully launched def task $! too";
fi
;;
diff --git a/testcases/kernel/controllers/cpuctl_fj/run_cpuctl_test_fj.sh b/testcases/kernel/controllers/cpuctl_fj/run_cpuctl_test_fj.sh
index ab73c801b..5cb6bb566 100755
--- a/testcases/kernel/controllers/cpuctl_fj/run_cpuctl_test_fj.sh
+++ b/testcases/kernel/controllers/cpuctl_fj/run_cpuctl_test_fj.sh
@@ -63,7 +63,7 @@ cleanup()
return 0
}
- find $CPUCTL -type d | sort | sed -n '2,$p' | tac | while read tmpdir
+ find $CPUCTL -type d | sort | sed -n '2,$p' | tac | while read -r tmpdir
do
while read tmppid
do
diff --git a/testcases/kernel/controllers/cpuset/cpuset_funcs.sh b/testcases/kernel/controllers/cpuset/cpuset_funcs.sh
index 87ba7da1f..0cfa0c17e 100755
--- a/testcases/kernel/controllers/cpuset/cpuset_funcs.sh
+++ b/testcases/kernel/controllers/cpuset/cpuset_funcs.sh
@@ -184,7 +184,7 @@ cleanup()
echo $CHILDREN_VALUE > $CLONE_CHILDREN
echo $SCHED_LB_VALUE > $SCHED_LB
- find "$CPUSET" -type d | sort | sed -n '2,$p' | tac | while read subdir
+ find "$CPUSET" -type d | sort | sed -n '2,$p' | tac | while read -r subdir
do
while read pid
do
diff --git a/testcases/kernel/controllers/cpuset/cpuset_memory_pressure_test/cpuset_memory_pressure_testset.sh b/testcases/kernel/controllers/cpuset/cpuset_memory_pressure_test/cpuset_memory_pressure_testset.sh
index eddd7f6c5..fff0ab318 100755
--- a/testcases/kernel/controllers/cpuset/cpuset_memory_pressure_test/cpuset_memory_pressure_testset.sh
+++ b/testcases/kernel/controllers/cpuset/cpuset_memory_pressure_test/cpuset_memory_pressure_testset.sh
@@ -33,10 +33,12 @@ check
exit_status=0
# usable physical memory
-py_mem=$(free -m | awk '{if(NR==2) print $4 + $6 + $7}')
+py_mem=$(awk '/MemAvailable/ {print $2}' /proc/meminfo)
+py_mem=$(( $py_mem / 1024 ))
# free swap space
-sw_mem=$(free -m | awk '{if(NR==4) print $4}')
+sw_mem=$(awk '/SwapFree/ {print $2}' /proc/meminfo)
+sw_mem=$(( $sw_mem / 1024 ))
# the memory which is going to be used
usemem=$((py_mem - 20))
diff --git a/testcases/kernel/controllers/cpuset/cpuset_memory_spread_test/cpuset_memory_spread_testset.sh b/testcases/kernel/controllers/cpuset/cpuset_memory_spread_test/cpuset_memory_spread_testset.sh
index e2767ef05..f7230a4ea 100755
--- a/testcases/kernel/controllers/cpuset/cpuset_memory_spread_test/cpuset_memory_spread_testset.sh
+++ b/testcases/kernel/controllers/cpuset/cpuset_memory_spread_test/cpuset_memory_spread_testset.sh
@@ -38,7 +38,15 @@ nr_mems=$N_NODES
# on which it is running. The other nodes' slab space has littler change.(less
# than 1000 kb).
upperlimit=10000
-lowerlimit=2000
+
+# set lowerlimit according to pagesize
+# pagesize(bytes) | lowerlimit(kb)
+# ------------------------------------
+# 4096 | 2048
+# 16384 | 8192
+
+PAGE_SIZE=`tst_getconf PAGESIZE`
+lowerlimit=$((PAGE_SIZE * 512 / 1024))
cpus_all="$(seq -s, 0 $((nr_cpus-1)))"
mems_all="$(seq -s, 0 $((nr_mems-1)))"
diff --git a/testcases/kernel/controllers/cpuset/cpuset_memory_test/cpuset_memory_testset.sh b/testcases/kernel/controllers/cpuset/cpuset_memory_test/cpuset_memory_testset.sh
index cb7dbd867..c1e7cea8f 100755
--- a/testcases/kernel/controllers/cpuset/cpuset_memory_test/cpuset_memory_testset.sh
+++ b/testcases/kernel/controllers/cpuset/cpuset_memory_test/cpuset_memory_testset.sh
@@ -41,7 +41,7 @@ mems_all="$(seq -s, 0 $((nr_mems-1)))"
cpu_of_node0=0
HUGEPAGESIZE=$(awk '/Hugepagesize/{ print $2 }' /proc/meminfo)
-HUGEPAGESIZE=$(($HUGEPAGESIZE * 1024))
+HUGEPAGESIZE=$((${HUGEPAGESIZE:-0} * 1024))
MEMORY_RESULT="$CPUSET_TMP/memory_result"
diff --git a/testcases/kernel/controllers/cpuset/cpuset_regression_test.sh b/testcases/kernel/controllers/cpuset/cpuset_regression_test.sh
index 8e87d20e4..a5757309f 100755
--- a/testcases/kernel/controllers/cpuset/cpuset_regression_test.sh
+++ b/testcases/kernel/controllers/cpuset/cpuset_regression_test.sh
@@ -12,7 +12,7 @@
TST_SETUP=setup
TST_CLEANUP=cleanup
-TST_TESTFUNC=test
+TST_TESTFUNC=do_test
TST_NEEDS_ROOT=1
TST_NEEDS_TMPDIR=1
TST_MIN_KVER="3.18"
@@ -130,6 +130,11 @@ setup()
tst_res TINFO "test starts with cgroup version $cgroup_version"
+ if [ "$cgroup_version" = "2" ]; then
+ tst_brk TCONF "cgroup v2 found, skipping test"
+ return
+ fi
+
if ! [ -f ${root_cpuset_dir}/${cpu_exclusive} ]; then
cpu_exclusive=cpu_exclusive
cpus=cpus
@@ -178,7 +183,7 @@ cleanup()
cgroup_cleanup
}
-test()
+do_test()
{
local cpu_exclusive_tmp cpus_value
diff --git a/testcases/kernel/controllers/freezer/00_description.txt b/testcases/kernel/controllers/freezer/00_description.txt
index b59741282..989a4a405 100644
--- a/testcases/kernel/controllers/freezer/00_description.txt
+++ b/testcases/kernel/controllers/freezer/00_description.txt
@@ -21,7 +21,7 @@ freeze_self_thaw.sh
The subshell process sleeps and then freezes the control group it is a
part of. We then thaw the subshell process. We expect the unthawed
subshell process to need cleanup afterwards (allows us to test
- successfull thawing).
+ successful thawing).
freeze_sleep_thaw.sh
This bash script tests freezer code by starting a long sleep process.
diff --git a/testcases/kernel/controllers/freezer/freeze_self_thaw.sh b/testcases/kernel/controllers/freezer/freeze_self_thaw.sh
index 773c4afa1..f6943cda8 100755
--- a/testcases/kernel/controllers/freezer/freeze_self_thaw.sh
+++ b/testcases/kernel/controllers/freezer/freeze_self_thaw.sh
@@ -22,7 +22,7 @@
# This bash script tests freezer code by starting a long subshell process.
# The subshell process sleeps and then freezes the control group it is a
# part of. We then thaw the subshell process. We expect the unthawed subshell
-# process to need cleanup afterwards (allows us to test successfull thawing).
+# process to need cleanup afterwards (allows us to test successful thawing).
#
. "${CGROUPS_TESTROOT}/libcgroup_freezer"
diff --git a/testcases/kernel/controllers/freezer/vfork_freeze.sh b/testcases/kernel/controllers/freezer/vfork_freeze.sh
index 4bb844ff4..6d3487600 100755
--- a/testcases/kernel/controllers/freezer/vfork_freeze.sh
+++ b/testcases/kernel/controllers/freezer/vfork_freeze.sh
@@ -60,7 +60,7 @@ TMPLOG="$TMPDIR/${0##*/}.$$.txt"
# create new processes. The vfork'ed processes then sleep, causing the
# parent process ($sample_proc) to enter the TASK_UNINTERRUPTIBLE state
# for the duration of the sleep.
-function vfork_sleep()
+vfork_sleep()
{
vfork -s$sample_sleep 1 -f "$TMPLOG" &
local rc=$?
diff --git a/testcases/kernel/controllers/io/io_control01.c b/testcases/kernel/controllers/io/io_control01.c
index c4e171af5..691196886 100644
--- a/testcases/kernel/controllers/io/io_control01.c
+++ b/testcases/kernel/controllers/io/io_control01.c
@@ -55,6 +55,7 @@ static void run(void)
char *buf = SAFE_MALLOC(MAX((size_t)BUFSIZ, pgsz));
struct io_stats start;
+ memset(&start, 0, sizeof(struct io_stats));
SAFE_CG_READ(tst_cg, "io.stat", buf, BUFSIZ - 1);
line = strtok_r(buf, "\n", &buf_ptr);
while (line) {
diff --git a/testcases/kernel/controllers/memcg/functional/memcg_failcnt.sh b/testcases/kernel/controllers/memcg/functional/memcg_failcnt.sh
index 1be98a056..3a02d16c2 100755
--- a/testcases/kernel/controllers/memcg/functional/memcg_failcnt.sh
+++ b/testcases/kernel/controllers/memcg/functional/memcg_failcnt.sh
@@ -8,11 +8,11 @@
# Restructure for LTP: Shi Weihua <shiwh@cn.fujitsu.com>
# Added memcg enable/disable functionality: Rishikesh K Rajak <risrajak@linux.vnet.ibm.com>
-MEMCG_TESTFUNC=test
+MEMCG_TESTFUNC=do_test
MEMCG_SHMMAX=1
TST_TEST_DATA="--mmap-anon --mmap-file --shm"
-test()
+do_test()
{
ROD echo $MEMORY_LIMIT \> memory.limit_in_bytes
diff --git a/testcases/kernel/controllers/memcg/functional/memcg_lib.sh b/testcases/kernel/controllers/memcg/functional/memcg_lib.sh
index dbb61e6b1..5efede9cf 100755
--- a/testcases/kernel/controllers/memcg/functional/memcg_lib.sh
+++ b/testcases/kernel/controllers/memcg/functional/memcg_lib.sh
@@ -404,8 +404,8 @@ fi
# Post 4.16 kernel updates stat in batch (> 32 pages) every time
# Post 6.1 kernel updates stat in batch (> 64 pages) every time
# 1813e51eece0ad6 ("memcg: increase MEMCG_CHARGE_BATCH to 64")
-# has been merged since 5.14.0-191.el9.
-if tst_kvcmp -lt "6.1 RHEL9:5.14.0-191" ; then
+# has been merged since 5.14.0-191.el9 and 4.18.0-438.el8.
+if tst_kvcmp -lt "6.1 RHEL9:5.14.0-191 RHEL8:4.18.0-438" ; then
PAGESIZES=$(($PAGESIZE * 33))
else
PAGESIZES=$(($PAGESIZE * 65))
diff --git a/testcases/kernel/controllers/memcg/stress/memcg_stress_test.sh b/testcases/kernel/controllers/memcg/stress/memcg_stress_test.sh
index cb52840d7..47cac9af8 100755
--- a/testcases/kernel/controllers/memcg/stress/memcg_stress_test.sh
+++ b/testcases/kernel/controllers/memcg/stress/memcg_stress_test.sh
@@ -33,14 +33,17 @@ setup()
echo 3 > /proc/sys/vm/drop_caches
sleep 2
- local mem_free=`cat /proc/meminfo | grep MemFree | awk '{ print $2 }'`
- local swap_free=`cat /proc/meminfo | grep SwapFree | awk '{ print $2 }'`
- local pgsize=`tst_getconf PAGESIZE`
-
- MEM=$(( $mem_free + $swap_free / 2 ))
+ local mem_free=$(awk '/MemFree/ {print $2}' /proc/meminfo)
+ local mem_available=$(awk '/MemAvailable/ {print $2}' /proc/meminfo)
+ local swap_free=$(awk '/SwapFree/ {print $2}' /proc/meminfo)
+ local mem_min=$(cat /proc/sys/vm/min_free_kbytes)
+
+ mem_min=$(( $mem_min + $mem_min/10 ))
+ [ $swap_free -gt $mem_min ] && RESERVED_MEM=0 || RESERVED_MEM=$mem_min
+ [ $mem_free -lt $mem_available ] && MEM=$mem_free || MEM=$mem_available
+ MEM=$(( $MEM - $RESERVED_MEM ))
MEM=$(( $MEM / 1024 ))
RUN_TIME=$(( 15 * 60 ))
- [ "$pgsize" = "4096" ] && THREAD_SPARE_MB=1 || THREAD_SPARE_MB=8
tst_res TINFO "Calculated available memory $MEM MB"
}
@@ -93,12 +96,12 @@ run_stress()
test1()
{
- run_stress 150 $(( ($MEM - 150 * $THREAD_SPARE_MB) / 150 )) 5 $RUN_TIME
+ run_stress 150 $(( $MEM / 150 )) 5 $RUN_TIME
}
test2()
{
- run_stress 1 $(( $MEM - $THREAD_SPARE_MB)) 5 $RUN_TIME
+ run_stress 1 $MEM 5 $RUN_TIME
}
. cgroup_lib.sh
diff --git a/testcases/kernel/crypto/pcrypt_aead01.c b/testcases/kernel/crypto/pcrypt_aead01.c
index 5eefee4cb..3b4f5d8d1 100644
--- a/testcases/kernel/crypto/pcrypt_aead01.c
+++ b/testcases/kernel/crypto/pcrypt_aead01.c
@@ -7,7 +7,7 @@
* Originally found by syzkaller:
* https://groups.google.com/forum/#!topic/syzkaller-bugs/NKn_ivoPOpk
*
- * Test for CVE-2017-5754 - pcrypt mishandles freeing instances.
+ * Test for CVE-2017-18075 - pcrypt mishandles freeing instances.
*
* The test works by adding and then removing pcrypt-AEAD instances.
* See commit d76c68109f37 crypto: pcrypt - fix freeing pcrypt instances.
@@ -78,7 +78,7 @@ static struct tst_test test = {
.max_runtime = 300,
.tags = (const struct tst_tag[]) {
{"linux-git", "d76c68109f37"},
- {"CVE", "2017-5754"},
+ {"CVE", "2017-18075"},
{}
}
};
diff --git a/testcases/kernel/device-drivers/nls/README b/testcases/kernel/device-drivers/nls/README
index 67c1d8f0c..1de4ec442 100644
--- a/testcases/kernel/device-drivers/nls/README
+++ b/testcases/kernel/device-drivers/nls/README
@@ -11,7 +11,7 @@ Before loading nlsTest.ko the nls_base.ko module must already be loaded.
Building
--------
-To build nlsTest.ko you will need to have the the Linux kernel sources installed
+To build nlsTest.ko you will need to have the Linux kernel sources installed
on your build environment. Execute "make" from the current directory should
build the nlsTest.ko.
diff --git a/testcases/kernel/device-drivers/zram/zram01.sh b/testcases/kernel/device-drivers/zram/zram01.sh
index 58d233f91..6bc305f2c 100755
--- a/testcases/kernel/device-drivers/zram/zram01.sh
+++ b/testcases/kernel/device-drivers/zram/zram01.sh
@@ -105,6 +105,26 @@ zram_mount()
tst_res TPASS "mount of zram device(s) succeeded"
}
+read_mem_used_total()
+{
+ echo $(awk '{print $3}' $1)
+}
+
+# Reads /sys/block/zram*/mm_stat until mem_used_total is not 0.
+check_read_mem_used_total()
+{
+ local file="$1"
+ local mem_used_total
+
+ tst_res TINFO "$file"
+ cat $file >&2
+
+ mem_used_total=$(read_mem_used_total $file)
+ [ "$mem_used_total" -eq 0 ] && return 1
+
+ return 0
+}
+
zram_fill_fs()
{
local mem_used_total
@@ -133,9 +153,12 @@ zram_fill_fs()
continue
fi
- mem_used_total=`awk '{print $3}' "/sys/block/zram$i/mm_stat"`
+ TST_RETRY_FUNC "check_read_mem_used_total /sys/block/zram$i/mm_stat" 0
+ mem_used_total=$(read_mem_used_total /sys/block/zram$i/mm_stat)
+ tst_res TINFO "mem_used_total: $mem_used_total"
+
v=$((100 * 1024 * $b / $mem_used_total))
- r=`echo "scale=2; $v / 100 " | bc`
+ r=$(echo "scale=2; $v / 100 " | bc)
if [ "$v" -lt 100 ]; then
tst_res TFAIL "compression ratio: $r:1"
diff --git a/testcases/kernel/fs/doio/write_log.c b/testcases/kernel/fs/doio/write_log.c
index e8ef9c7cb..c06677fc6 100644
--- a/testcases/kernel/fs/doio/write_log.c
+++ b/testcases/kernel/fs/doio/write_log.c
@@ -87,7 +87,7 @@
/*#define PATH_MAX pathconf("/", _PC_PATH_MAX)*/
#endif
-char Wlog_Error_String[256];
+char Wlog_Error_String[2048];
#if __STDC__
static int wlog_rec_pack(struct wlog_rec *wrec, char *buf, int flag);
@@ -129,7 +129,7 @@ int wlog_open(struct wlog_file *wfile, int trunc, int mode)
umask(omask);
if (wfile->w_afd == -1) {
- sprintf(Wlog_Error_String,
+ snprintf(Wlog_Error_String, sizeof(Wlog_Error_String),
"Could not open write_log - open(%s, %#o, %#o) failed: %s\n",
wfile->w_file, oflags, mode, strerror(errno));
return -1;
@@ -141,7 +141,7 @@ int wlog_open(struct wlog_file *wfile, int trunc, int mode)
oflags = O_RDWR;
if ((wfile->w_rfd = open(wfile->w_file, oflags)) == -1) {
- sprintf(Wlog_Error_String,
+ snprintf(Wlog_Error_String, sizeof(Wlog_Error_String),
"Could not open write log - open(%s, %#o) failed: %s\n",
wfile->w_file, oflags, strerror(errno));
close(wfile->w_afd);
@@ -218,14 +218,14 @@ int wlog_record_write(struct wlog_file *wfile, struct wlog_rec *wrec,
reclen += 2;
if (write(wfile->w_afd, wbuf, reclen) == -1) {
- sprintf(Wlog_Error_String,
+ snprintf(Wlog_Error_String, sizeof(Wlog_Error_String),
"Could not write log - write(%s, %s, %d) failed: %s\n",
wfile->w_file, wbuf, reclen, strerror(errno));
return -1;
} else {
offset = lseek(wfile->w_afd, 0, SEEK_CUR) - reclen;
if (offset == -1) {
- sprintf(Wlog_Error_String,
+ snprintf(Wlog_Error_String, sizeof(Wlog_Error_String),
"Could not reposition file pointer - lseek(%s, 0, SEEK_CUR) failed: %s\n",
wfile->w_file, strerror(errno));
return -1;
@@ -233,13 +233,13 @@ int wlog_record_write(struct wlog_file *wfile, struct wlog_rec *wrec,
}
} else {
if ((lseek(wfile->w_rfd, offset, SEEK_SET)) == -1) {
- sprintf(Wlog_Error_String,
+ snprintf(Wlog_Error_String, sizeof(Wlog_Error_String),
"Could not reposition file pointer - lseek(%s, %ld, SEEK_SET) failed: %s\n",
wfile->w_file, offset, strerror(errno));
return -1;
} else {
if ((write(wfile->w_rfd, wbuf, reclen)) == -1) {
- sprintf(Wlog_Error_String,
+ snprintf(Wlog_Error_String, sizeof(Wlog_Error_String),
"Could not write log - write(%s, %s, %d) failed: %s\n",
wfile->w_file, wbuf, reclen,
strerror(errno));
@@ -274,14 +274,14 @@ int wlog_scan_backward(struct wlog_file *wfile, int nrecs,
*/
if ((lseek(fd, 0, SEEK_END)) == -1) {
- sprintf(Wlog_Error_String,
+ snprintf(Wlog_Error_String, sizeof(Wlog_Error_String),
"Could not reposition file pointer - lseek(%s, 0, SEEK_END) failed: %s\n",
wfile->w_file, strerror(errno));
return -1;
}
offset = lseek(fd, 0, SEEK_CUR);
if ((offset == -1)) {
- sprintf(Wlog_Error_String,
+ snprintf(Wlog_Error_String, sizeof(Wlog_Error_String),
"Could not reposition file pointer - lseek(%s, 0, SEEK_CUR) failed: %s\n",
wfile->w_file, strerror(errno));
return -1;
@@ -309,7 +309,7 @@ int wlog_scan_backward(struct wlog_file *wfile, int nrecs,
* Move to the proper file offset, and read into buf
*/
if ((lseek(fd, offset, SEEK_SET)) == -1) {
- sprintf(Wlog_Error_String,
+ snprintf(Wlog_Error_String, sizeof(Wlog_Error_String),
"Could not reposition file pointer - lseek(%s, %d, SEEK_SET) failed: %s\n",
wfile->w_file, offset, strerror(errno));
return -1;
@@ -318,7 +318,7 @@ int wlog_scan_backward(struct wlog_file *wfile, int nrecs,
nbytes = read(fd, bufstart, bufend - bufstart - leftover);
if (nbytes == -1) {
- sprintf(Wlog_Error_String,
+ snprintf(Wlog_Error_String, sizeof(Wlog_Error_String),
"Could not read history file at offset %d - read(%d, %p, %d) failed: %s\n",
offset, fd, bufstart,
(int)(bufend - bufstart - leftover),
diff --git a/testcases/kernel/fs/fs_bind/fs_bind_lib.sh b/testcases/kernel/fs/fs_bind/fs_bind_lib.sh
index 2dd9ef08f..52190a7ca 100644
--- a/testcases/kernel/fs/fs_bind/fs_bind_lib.sh
+++ b/testcases/kernel/fs/fs_bind/fs_bind_lib.sh
@@ -2,6 +2,7 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (c) International Business Machines Corp., 2005
# Copyright (c) 2021 Joerg Vehlow <joerg.vehlow@aox-tech.de>
+# Copyright (c) Linux Test Project, 2022-2023
# Based on work by: Avantika Mathur (mathurav@us.ibm.com)
TST_NEEDS_TMPDIR=1
@@ -109,7 +110,7 @@ fs_bind_check()
fi
if [ $use_ns -eq 1 ]; then
- output="$(ns_exec ${FS_BIND_MNTNS_PID} mnt diff -r "$PWD/$dir1" "$PWD/$dir2" 2> /dev/null)"
+ output="$(tst_ns_exec ${FS_BIND_MNTNS_PID} mnt diff -r "$PWD/$dir1" "$PWD/$dir2" 2> /dev/null)"
else
output="$(diff -r "$dir1" "$dir2" 2> /dev/null)"
fi
@@ -197,13 +198,13 @@ _fs_bind_setup_test()
fs_bind_create_ns()
{
[ -n "$FS_BIND_MNTNS_PID" ] && tst_brk TBROK "Namespace exist already"
- FS_BIND_MNTNS_PID=$(ns_create mnt)
+ FS_BIND_MNTNS_PID=$(tst_ns_create mnt)
}
fs_bind_exec_ns()
{
[ -z "$FS_BIND_MNTNS_PID" ] && tst_brk TBROK "Namespace does not exist"
- EXPECT_PASS ns_exec $FS_BIND_MNTNS_PID mnt "$@"
+ EXPECT_PASS tst_ns_exec $FS_BIND_MNTNS_PID mnt "$@"
}
fs_bind_destroy_ns()
diff --git a/testcases/kernel/fs/fs_fill/fs_fill.c b/testcases/kernel/fs/fs_fill/fs_fill.c
index 2027b6df1..2ecd8e2ad 100644
--- a/testcases/kernel/fs/fs_fill/fs_fill.c
+++ b/testcases/kernel/fs/fs_fill/fs_fill.c
@@ -18,6 +18,7 @@
#include "tst_test.h"
#define MNTPOINT "mntpoint"
+#define THREADS_DIR MNTPOINT "/subdir"
static volatile int run;
static unsigned int nthreads;
@@ -99,9 +100,15 @@ static void setup(void)
nthreads = tst_ncpus_conf() + 2;
workers = SAFE_MALLOC(sizeof(struct worker) * nthreads);
+ /*
+ * Avoid creating the thread directories in the root of the filesystem
+ * to not hit the root entries limit on a FAT16 filesystem.
+ */
+ SAFE_MKDIR(THREADS_DIR, 0700);
+
for (i = 0; i < nthreads; i++) {
snprintf(workers[i].dir, sizeof(workers[i].dir),
- MNTPOINT "/thread%i", i + 1);
+ THREADS_DIR "/thread%i", i + 1);
SAFE_MKDIR(workers[i].dir, 0700);
}
diff --git a/testcases/kernel/fs/fsstress/fsstress.c b/testcases/kernel/fs/fsstress/fsstress.c
index 42ee696a5..272d87a1f 100644
--- a/testcases/kernel/fs/fsstress/fsstress.c
+++ b/testcases/kernel/fs/fsstress/fsstress.c
@@ -32,7 +32,8 @@
#include "config.h"
#include "global.h"
-#include <tst_common.h>
+#include "tst_common.h"
+
#ifdef HAVE_SYS_PRCTL_H
# include <sys/prctl.h>
#endif
diff --git a/testcases/kernel/fs/fsstress/global.h b/testcases/kernel/fs/fsstress/global.h
index 4ec382426..e7d0cde47 100644
--- a/testcases/kernel/fs/fsstress/global.h
+++ b/testcases/kernel/fs/fsstress/global.h
@@ -33,7 +33,7 @@
#ifndef GLOBAL_H
#define GLOBAL_H
-/* xfs-specific includes */
+#define _GNU_SOURCE
#if defined(NO_XFS)
# include "xfscompat.h"
@@ -42,8 +42,6 @@
# include <attr/attributes.h>
#endif
-/* libc includes */
-
#include <sys/stat.h>
#include <sys/statvfs.h>
#include <sys/time.h>
@@ -58,9 +56,6 @@
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
-
-#ifndef O_DIRECT
-#define O_DIRECT 040000
-#endif
+#include "lapi/fcntl.h"
#endif
diff --git a/testcases/kernel/fs/lftest/lftest.c b/testcases/kernel/fs/lftest/lftest.c
index 7290fb0df..9e293d9e3 100644
--- a/testcases/kernel/fs/lftest/lftest.c
+++ b/testcases/kernel/fs/lftest/lftest.c
@@ -65,7 +65,7 @@ static void run(void)
tst_res(TINFO, "total time for test to run: %d minute(s) and %d seconds",
diff / 60, diff % 60);
- tst_res(TPASS, "test successfull");
+ tst_res(TPASS, "test successful");
}
static struct tst_test test = {
diff --git a/testcases/kernel/fs/read_all/Makefile b/testcases/kernel/fs/read_all/Makefile
index 0e6dec2d3..fb73e8fbc 100644
--- a/testcases/kernel/fs/read_all/Makefile
+++ b/testcases/kernel/fs/read_all/Makefile
@@ -6,5 +6,6 @@ top_srcdir ?= ../../../..
include $(top_srcdir)/include/mk/testcases.mk
CFLAGS += -D_GNU_SOURCE -pthread
+read_all: LDLIBS+=-lrt
include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/fs/scsi/ltpscsi/scsimain.c b/testcases/kernel/fs/scsi/ltpscsi/scsimain.c
index ae484e0f1..ce23ae1e7 100644
--- a/testcases/kernel/fs/scsi/ltpscsi/scsimain.c
+++ b/testcases/kernel/fs/scsi/ltpscsi/scsimain.c
@@ -28,6 +28,7 @@
[0x12][ |lu][pg cde][res ][al len][cntrl ]
*/
+#define _GNU_SOURCE
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
@@ -53,10 +54,6 @@
#define ME "scsimain: "
-#ifndef O_DIRECT
-#define O_DIRECT 040000
-#endif
-
#define NUMERIC_SCAN_DEF 1 /* change to 0 to make alpha scan default */
//static char * version_str = "0.21 20030513";
diff --git a/testcases/kernel/io/direct_io/diotest3.c b/testcases/kernel/io/direct_io/diotest3.c
index 92f7afaad..ba2fd0473 100644
--- a/testcases/kernel/io/direct_io/diotest3.c
+++ b/testcases/kernel/io/direct_io/diotest3.c
@@ -292,6 +292,7 @@ int main(int argc, char *argv[])
}
unlink(filename);
free(pidlst);
+ fflush(stdout);
total++;
/* Testblock-2: Write with Direct IO, Read without */
@@ -309,6 +310,7 @@ int main(int argc, char *argv[])
}
unlink(filename);
free(pidlst);
+ fflush(stdout);
total++;
/* Testblock-3: Read, Write with Direct IO. */
diff --git a/testcases/kernel/io/direct_io/diotest4.c b/testcases/kernel/io/direct_io/diotest4.c
index f3c9c19d7..45c677b5b 100644
--- a/testcases/kernel/io/direct_io/diotest4.c
+++ b/testcases/kernel/io/direct_io/diotest4.c
@@ -62,7 +62,6 @@
#include <sys/file.h>
#include <fcntl.h>
#include <sys/types.h>
-#include <sys/mman.h>
#include <sys/syscall.h>
#include <errno.h>
diff --git a/testcases/kernel/io/direct_io/diotest6.c b/testcases/kernel/io/direct_io/diotest6.c
index 1905380f0..fb925ff0a 100644
--- a/testcases/kernel/io/direct_io/diotest6.c
+++ b/testcases/kernel/io/direct_io/diotest6.c
@@ -320,6 +320,7 @@ int main(int argc, char *argv[])
}
unlink(filename);
free(pidlst);
+ fflush(stdout);
total++;
/* Testblock-2: Write with Direct IO, Read without */
@@ -337,6 +338,7 @@ int main(int argc, char *argv[])
}
unlink(filename);
free(pidlst);
+ fflush(stdout);
total++;
/* Testblock-3: Read, Write with Direct IO. */
diff --git a/testcases/kernel/io/ltp-aiodio/aiocp.c b/testcases/kernel/io/ltp-aiodio/aiocp.c
index bc0e209b2..6212d8ee8 100644
--- a/testcases/kernel/io/ltp-aiodio/aiocp.c
+++ b/testcases/kernel/io/ltp-aiodio/aiocp.c
@@ -297,8 +297,8 @@ static void run(void)
return;
}
- srcfd = SAFE_OPEN(srcname, srcflags | O_RDONLY, 0666);
- dstfd = SAFE_OPEN(dstname, srcflags | O_RDONLY, 0666);
+ srcfd = SAFE_OPEN(srcname, O_RDONLY, 0666);
+ dstfd = SAFE_OPEN(dstname, O_RDONLY, 0666);
reads = howmany(filesize, buffsize);
diff --git a/testcases/kernel/ipc/semaphore/.gitignore b/testcases/kernel/ipc/semaphore/.gitignore
deleted file mode 100644
index 944e5ca1e..000000000
--- a/testcases/kernel/ipc/semaphore/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-/sem01
-/sem02
diff --git a/testcases/kernel/ipc/semaphore/Makefile b/testcases/kernel/ipc/semaphore/Makefile
deleted file mode 100644
index 9ab85745d..000000000
--- a/testcases/kernel/ipc/semaphore/Makefile
+++ /dev/null
@@ -1,30 +0,0 @@
-#
-# testcases/kernel/ipc/semaphore Makefile.
-#
-# Copyright (C) 2009, Cisco Systems Inc.
-#
-# 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.
-#
-# Ngie Cooper, July 2009
-#
-
-top_srcdir ?= ../../../..
-
-include $(top_srcdir)/include/mk/testcases.mk
-
-CPPFLAGS += -I../include
-LDLIBS += -lpthread
-
-include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/ipc/semaphore/sem01.c b/testcases/kernel/ipc/semaphore/sem01.c
deleted file mode 100644
index 582624d60..000000000
--- a/testcases/kernel/ipc/semaphore/sem01.c
+++ /dev/null
@@ -1,164 +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
- */
-
-/*
- * FILE : sem01.c
- * 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.
- * HISTORY:
- * 01/15/2001 Paul Larson (plars@us.ibm.com)
- * -written
- * 11/09/2001 Manoj Iyer (manjo@ausin.ibm.com)
- * Modified.
- * - Removed compiler warnings.
- * added exit to the end of function main()
- *
- */
-
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <sys/ipc.h>
-#include "lapi/sem.h"
-
-int verbose = 0;
-int loops = 100;
-int errors = 0;
-
-int semup(int semid)
-{
- struct sembuf semops;
- semops.sem_num = 0;
- semops.sem_op = 1;
- semops.sem_flg = SEM_UNDO;
- if (semop(semid, &semops, 1) == -1) {
- perror("semup");
- errors++;
- return 1;
- }
- return 0;
-}
-
-int semdown(int semid)
-{
- struct sembuf semops;
- semops.sem_num = 0;
- semops.sem_op = -1;
- semops.sem_flg = SEM_UNDO;
- if (semop(semid, &semops, 1) == -1) {
- perror("semdown");
- errors++;
- return 1;
- }
- return 0;
-}
-
-void delayloop()
-{
- int delay;
- delay = 1 + ((100.0 * rand()) / RAND_MAX);
- if (verbose)
- printf("in delay function for %d microseconds\n", delay);
- usleep(delay);
-}
-
-void mainloop(int semid)
-{
- int i;
- for (i = 0; i < loops; i++) {
- if (semdown(semid)) {
- printf("semdown failed\n");
- }
- if (verbose)
- printf("sem is down\n");
- delayloop();
- if (semup(semid)) {
- printf("semup failed\n");
- }
- if (verbose)
- printf("sem is up\n");
- }
-}
-
-int main(int argc, char *argv[])
-{
- int semid, opt;
- union semun semunion;
- extern char *optarg;
- pid_t pid;
- int chstat;
-
- while ((opt = getopt(argc, argv, "l:vh")) != EOF) {
- switch ((char)opt) {
- case 'l':
- loops = atoi(optarg);
- break;
- case 'v':
- verbose = 1;
- break;
- case 'h':
- default:
- printf("Usage: -l loops [-v]\n");
- exit(1);
- }
- }
-
- /* set up the semaphore */
- if ((semid = semget((key_t) 9142, 1, 0666 | IPC_CREAT)) < 0) {
- printf("error in semget()\n");
- exit(-1);
- }
- semunion.val = 1;
- if (semctl(semid, 0, SETVAL, semunion) == -1) {
- printf("error in semctl\n");
- }
-
- if ((pid = fork()) < 0) {
- printf("fork error\n");
- exit(-1);
- }
- if (pid) {
- /* parent */
- srand(pid);
- mainloop(semid);
- waitpid(pid, &chstat, 0);
- if (!WIFEXITED(chstat)) {
- printf("child exited with status\n");
- exit(-1);
- }
- if (semctl(semid, 0, IPC_RMID, semunion) == -1) {
- printf("error in semctl\n");
- }
- if (errors) {
- printf("FAIL: there were %d errors\n", errors);
- } else {
- printf("PASS: error count is 0\n");
- }
- exit(errors);
- } else {
- /* child */
- mainloop(semid);
- }
- exit(0);
-}
diff --git a/testcases/kernel/kvm/.gitignore b/testcases/kernel/kvm/.gitignore
index 349260359..9638a6fc7 100644
--- a/testcases/kernel/kvm/.gitignore
+++ b/testcases/kernel/kvm/.gitignore
@@ -1 +1,4 @@
/kvm_pagefault01
+/kvm_svm01
+/kvm_svm02
+/kvm_svm03
diff --git a/testcases/kernel/kvm/Makefile b/testcases/kernel/kvm/Makefile
index 6986844be..ce4a5ede2 100644
--- a/testcases/kernel/kvm/Makefile
+++ b/testcases/kernel/kvm/Makefile
@@ -8,8 +8,8 @@ include $(top_srcdir)/include/mk/testcases.mk
ASFLAGS =
CPPFLAGS += -I$(abs_srcdir)/include
GUEST_CPPFLAGS = $(CPPFLAGS) -DCOMPILE_PAYLOAD
-GUEST_CFLAGS = -ffreestanding -O2 -Wall -fno-asynchronous-unwind-tables -mno-mmx -mno-sse
-GUEST_LDFLAGS = -nostdlib -Wl,--build-id=none -fno-stack-protector
+GUEST_CFLAGS = -ffreestanding -O2 -Wall -fno-asynchronous-unwind-tables -fno-stack-protector -mno-mmx -mno-sse
+GUEST_LDFLAGS = -nostdlib -Wl,--build-id=none -z noexecstack
GUEST_LDLIBS =
KVM_LD ?= $(LD)
@@ -48,6 +48,9 @@ endif
lib_guest.o $(ARCH_OBJ): CPPFLAGS := $(GUEST_CPPFLAGS)
lib_guest.o $(ARCH_OBJ): CFLAGS := $(GUEST_CFLAGS)
+kvm_svm03: CFLAGS += -pthread
+kvm_svm03: LDLIBS += -pthread
+
include $(top_srcdir)/include/mk/generic_leaf_target.mk
%-payload.o: %.c lib_guest.o $(ARCH_OBJ)
diff --git a/testcases/kernel/kvm/bootstrap_x86.S b/testcases/kernel/kvm/bootstrap_x86.S
index 5ec4c0b7e..a39c6bea7 100644
--- a/testcases/kernel/kvm/bootstrap_x86.S
+++ b/testcases/kernel/kvm/bootstrap_x86.S
@@ -7,6 +7,9 @@
.set KVM_TEXIT, 0xff
.set RESULT_ADDRESS, 0xfffff000
+.set KVM_GDT_SIZE, 32
+
+.set MSR_VM_HSAVE_PA, 0xc0010117
/*
* This section will be allocated at address 0x1000 and
@@ -31,7 +34,7 @@ protected_mode_entry:
mov %eax, %es
jmp init_memlayout
-.section .data.gdt32, "a", @progbits
+.section .init.gdt32, "a", @progbits
.macro gdt32_entry type:req l=0 d=0 dpl=0 limit=0xfffff g=1 p=1
.4byte \limit & 0xffff
@@ -44,7 +47,7 @@ kvm_gdt:
.8byte 0
gdt32_entry type=0x1a l=0 d=1 /* Code segment protected_mode, 32bits */
gdt32_entry type=0x12 /* Data segment, writable */
- .skip 16 /* Stack and TSS segment descriptors */
+ .skip (KVM_GDT_SIZE-3)*8 /* Stack, TSS and other segment descriptors */
.Lgdt_end:
.global kvm_gdt_desc
@@ -196,6 +199,25 @@ kvm_read_cregs:
pop %edi
ret
+.global kvm_read_sregs
+kvm_read_sregs:
+ push %edi
+ mov 8(%esp), %edi
+ mov %cs, %ax
+ movw %ax, (%edi)
+ mov %ds, %ax
+ movw %ax, 2(%edi)
+ mov %es, %ax
+ movw %ax, 4(%edi)
+ mov %fs, %ax
+ movw %ax, 6(%edi)
+ mov %gs, %ax
+ movw %ax, 8(%edi)
+ mov %ss, %ax
+ movw %ax, 10(%edi)
+ pop %edi
+ ret
+
handle_interrupt:
/* save CPU state */
push %ebp
@@ -331,6 +353,83 @@ kvm_yield:
hlt
ret
+.global kvm_svm_guest_entry
+kvm_svm_guest_entry:
+ call *%eax
+1: hlt
+ jmp 1b
+
+.global kvm_svm_vmrun
+kvm_svm_vmrun:
+ push %edi
+ mov 8(%esp), %edi
+ push %ebx
+ push %esi
+ push %ebp
+
+ clgi
+
+ /* Save full host state */
+ movl $MSR_VM_HSAVE_PA, %ecx
+ rdmsr
+ vmsave
+ push %eax
+
+ /* Load guest registers */
+ push %edi
+ movl (%edi), %eax
+ /* %eax is loaded by vmrun from VMCB */
+ movl 0x0c(%edi), %ebx
+ movl 0x14(%edi), %ecx
+ movl 0x1c(%edi), %edx
+ movl 0x2c(%edi), %esi
+ movl 0x34(%edi), %ebp
+ /* %esp is loaded by vmrun from VMCB */
+ movl 0x24(%edi), %edi
+
+ vmload
+ vmrun
+ vmsave
+
+ /* Clear guest register buffer */
+ push %edi
+ push %ecx
+ movl 8(%esp), %edi
+ addl $4, %edi
+ xorl %eax, %eax
+ mov $32, %ecx
+ pushfl
+ cld
+ rep stosl
+ popfl
+
+ /* Save guest registers */
+ pop %ecx
+ pop %eax
+ pop %edi
+ movl %ebx, 0x0c(%edi)
+ movl %ecx, 0x14(%edi)
+ movl %edx, 0x1c(%edi)
+ movl %eax, 0x24(%edi)
+ movl %esi, 0x2c(%edi)
+ movl %ebp, 0x34(%edi)
+ /* Copy %eax and %esp from VMCB */
+ movl (%edi), %esi
+ movl 0x5f8(%esi), %eax
+ movl %eax, 0x04(%edi)
+ movl 0x5d8(%esi), %eax
+ movl %eax, 0x3c(%edi)
+
+ pop %eax
+ vmload
+ stgi
+
+ pop %ebp
+ pop %esi
+ pop %ebx
+ pop %edi
+ ret
+
.section .bss.pgtables, "aw", @nobits
.global kvm_pagetable
diff --git a/testcases/kernel/kvm/bootstrap_x86_64.S b/testcases/kernel/kvm/bootstrap_x86_64.S
index 9ddbd17ed..b02dd4d92 100644
--- a/testcases/kernel/kvm/bootstrap_x86_64.S
+++ b/testcases/kernel/kvm/bootstrap_x86_64.S
@@ -8,6 +8,9 @@
.set KVM_TCONF, 32
.set KVM_TEXIT, 0xff
.set RESULT_ADDRESS, 0xfffff000
+.set KVM_GDT_SIZE, 32
+
+.set MSR_VM_HSAVE_PA, 0xc0010117
/*
* This section will be allocated at address 0x1000 and
@@ -32,7 +35,7 @@ protected_mode_entry:
mov %eax, %es
jmp init_memlayout
-.section .data.gdt32, "a", @progbits
+.section .init.gdt32, "a", @progbits
.macro gdt32_entry type:req l=0 d=0 dpl=0 limit=0xfffff g=1 p=1
.4byte \limit & 0xffff
@@ -302,6 +305,22 @@ kvm_read_cregs:
mov %rax, 24(%rdi)
retq
+.global kvm_read_sregs
+kvm_read_sregs:
+ mov %cs, %ax
+ movw %ax, (%rdi)
+ mov %ds, %ax
+ movw %ax, 2(%rdi)
+ mov %es, %ax
+ movw %ax, 4(%rdi)
+ mov %fs, %ax
+ movw %ax, 6(%rdi)
+ mov %gs, %ax
+ movw %ax, 8(%rdi)
+ mov %ss, %ax
+ movw %ax, 10(%rdi)
+ retq
+
handle_interrupt:
/* push CPU state */
push %rbp
@@ -457,6 +476,93 @@ kvm_yield:
hlt
ret
+.global kvm_svm_guest_entry
+kvm_svm_guest_entry:
+ call *%rax
+1: hlt
+ jmp 1b
+
+.global kvm_svm_vmrun
+kvm_svm_vmrun:
+ pushq %rbx
+ pushq %rbp
+ pushq %r12
+ pushq %r13
+ pushq %r14
+ pushq %r15
+
+ clgi
+
+ /* Save full host state */
+ movq $MSR_VM_HSAVE_PA, %rcx
+ rdmsr
+ shlq $32, %rdx
+ orq %rdx, %rax
+ vmsave
+ pushq %rax
+
+ /* Load guest registers */
+ pushq %rdi
+ movq (%rdi), %rax
+ /* %rax is loaded by vmrun from VMCB */
+ movq 0x10(%rdi), %rbx
+ movq 0x18(%rdi), %rcx
+ movq 0x20(%rdi), %rdx
+ movq 0x30(%rdi), %rsi
+ movq 0x38(%rdi), %rbp
+ /* %rsp is loaded by vmrun from VMCB */
+ movq 0x48(%rdi), %r8
+ movq 0x50(%rdi), %r9
+ movq 0x58(%rdi), %r10
+ movq 0x60(%rdi), %r11
+ movq 0x68(%rdi), %r12
+ movq 0x70(%rdi), %r13
+ movq 0x78(%rdi), %r14
+ movq 0x80(%rdi), %r15
+ movq 0x28(%rdi), %rdi
+
+ vmload
+ vmrun
+ vmsave
+
+ /* Save guest registers */
+ movq %rdi, %rax
+ popq %rdi
+ movq %rbx, 0x10(%rdi)
+ movq %rcx, 0x18(%rdi)
+ movq %rdx, 0x20(%rdi)
+ /* %rax contains guest %rdi */
+ movq %rax, 0x28(%rdi)
+ movq %rsi, 0x30(%rdi)
+ movq %rbp, 0x38(%rdi)
+ movq %r8, 0x48(%rdi)
+ movq %r9, 0x50(%rdi)
+ movq %r10, 0x58(%rdi)
+ movq %r11, 0x60(%rdi)
+ movq %r12, 0x68(%rdi)
+ movq %r13, 0x70(%rdi)
+ movq %r14, 0x78(%rdi)
+ movq %r15, 0x80(%rdi)
+ /* copy guest %rax and %rsp from VMCB*/
+ movq (%rdi), %rsi
+ movq 0x5f8(%rsi), %rax
+ movq %rax, 0x08(%rdi)
+ movq 0x5d8(%rsi), %rax
+ movq %rax, 0x40(%rdi)
+
+ /* Reload host state */
+ popq %rax
+ vmload
+
+ stgi
+
+ popq %r15
+ popq %r14
+ popq %r13
+ popq %r12
+ popq %rbp
+ popq %rbx
+ retq
.section .bss.pgtables, "aw", @nobits
.global kvm_pagetable
@@ -478,7 +584,7 @@ kvm_pgtable_l4:
kvm_gdt:
.8byte 0
gdt32_entry type=0x1a l=1 limit=0 g=0 /* Code segment long mode */
- .skip 16 /* TSS segment descriptor */
+ .skip (KVM_GDT_SIZE-2)*8 /* TSS and other segment descriptors */
.Lgdt_end:
.global kvm_gdt_desc
diff --git a/testcases/kernel/kvm/include/kvm_common.h b/testcases/kernel/kvm/include/kvm_common.h
index 4e81d8302..377e3f6aa 100644
--- a/testcases/kernel/kvm/include/kvm_common.h
+++ b/testcases/kernel/kvm/include/kvm_common.h
@@ -11,6 +11,14 @@
#define KVM_TNONE -1 /* "No result" status value */
/*
+ * Result value for asynchronous notifications between guest and host.
+ * Do not use this value directly. Call tst_signal_host() or tst_wait_host()
+ * in guest code. The notification must be handled by another host thread
+ * and then the result value must be reset to KVM_TNONE.
+ */
+#define KVM_TSYNC 0xfe
+
+/*
* Result value indicating end of test. If the test program exits using
* the HLT instruction with any valid result value other than KVM_TEXIT or
* TBROK, KVM runner will automatically resume VM execution after printing
diff --git a/testcases/kernel/kvm/include/kvm_guest.h b/testcases/kernel/kvm/include/kvm_guest.h
index ec13c5845..96f246155 100644
--- a/testcases/kernel/kvm/include/kvm_guest.h
+++ b/testcases/kernel/kvm/include/kvm_guest.h
@@ -64,6 +64,20 @@ void tst_brk_(const char *file, const int lineno, int result,
const char *message) __attribute__((noreturn));
#define tst_brk(result, msg) tst_brk_(__FILE__, __LINE__, (result), (msg))
+/*
+ * Send asynchronous notification to host without stopping VM execution and
+ * return immediately. The notification must be handled by another host thread.
+ * The data argument will be passed to host in test_result->file_addr and
+ * can be used to send additional data both ways.
+ */
+void tst_signal_host(void *data);
+
+/*
+ * Call tst_signal_host(data) and wait for host to call
+ * tst_kvm_clear_guest_signal().
+ */
+void tst_wait_host(void *data);
+
void *tst_heap_alloc_aligned(size_t size, size_t align);
void *tst_heap_alloc(size_t size);
diff --git a/testcases/kernel/kvm/include/kvm_host.h b/testcases/kernel/kvm/include/kvm_host.h
index 2359944fd..06bcb5d45 100644
--- a/testcases/kernel/kvm/include/kvm_host.h
+++ b/testcases/kernel/kvm/include/kvm_host.h
@@ -125,13 +125,29 @@ struct kvm_cpuid2 *tst_kvm_get_cpuid(int sysfd);
void tst_kvm_create_instance(struct tst_kvm_instance *inst, size_t ram_size);
/*
- * Execute the given KVM instance and print results.
+ * Execute the given KVM instance and print results. If ioctl(KVM_RUN) is
+ * expected to fail, pass the expected error code in exp_errno, otherwise
+ * set it to zero. Returns last value returned by ioctl(KVM_RUN).
*/
-void tst_kvm_run_instance(struct tst_kvm_instance *inst);
+int tst_kvm_run_instance(struct tst_kvm_instance *inst, int exp_errno);
/*
* Close the given KVM instance.
*/
void tst_kvm_destroy_instance(struct tst_kvm_instance *inst);
+/*
+ * Wait for given VM to call tst_signal_host() or tst_wait_host(). Timeout
+ * value is in milliseconds. Zero means no wait, negative value means wait
+ * forever. Returns 0 if signal was received, KVM_TEXIT if the VM exited
+ * without sending a signal, or -1 if timeout was reached.
+ */
+int tst_kvm_wait_guest(struct tst_kvm_instance *inst, int timeout_ms);
+
+/*
+ * Clear VM signal sent by tst_signal_host(). If the VM is waiting
+ * in tst_wait_host(), this function will signal the VM to resume execution.
+ */
+void tst_kvm_clear_guest_signal(struct tst_kvm_instance *inst);
+
#endif /* KVM_HOST_H_ */
diff --git a/testcases/kernel/kvm/include/kvm_x86.h b/testcases/kernel/kvm/include/kvm_x86.h
index 4f3671135..bc36c0e0f 100644
--- a/testcases/kernel/kvm/include/kvm_x86.h
+++ b/testcases/kernel/kvm/include/kvm_x86.h
@@ -10,6 +10,9 @@
#include "kvm_test.h"
+#define PAGESIZE 0x1000
+#define KVM_GDT_SIZE 32
+
/* Interrupts */
#define X86_INTR_COUNT 256
@@ -38,19 +41,48 @@
#define INTR_SECURITY_ERROR 30
+/* Segment descriptor flags */
+#define SEGTYPE_LDT 0x02
+#define SEGTYPE_TSS 0x09
+#define SEGTYPE_TSS_BUSY 0x0b
+#define SEGTYPE_CALL_GATE 0x0c
+#define SEGTYPE_INTR_GATE 0x0e
+#define SEGTYPE_TRAP_GATE 0x0f
+#define SEGTYPE_RODATA 0x10
+#define SEGTYPE_RWDATA 0x12
+#define SEGTYPE_STACK 0x16
+#define SEGTYPE_CODE 0x1a
+#define SEGTYPE_MASK 0x1f
+
+#define SEGFLAG_NSYSTEM 0x10
+#define SEGFLAG_PRESENT 0x80
+#define SEGFLAG_CODE64 0x200
+#define SEGFLAG_32BIT 0x400
+#define SEGFLAG_PAGE_LIMIT 0x800
+
+
/* CPUID constants */
#define CPUID_GET_INPUT_RANGE 0x80000000
#define CPUID_GET_EXT_FEATURES 0x80000001
+#define CPUID_GET_SVM_FEATURES 0x8000000a
/* Model-specific CPU register constants */
#define MSR_EFER 0xc0000080
+#define MSR_VM_CR 0xc0010114
+#define MSR_VM_HSAVE_PA 0xc0010117
#define EFER_SCE (1 << 0) /* SYSCALL/SYSRET instructions enabled */
#define EFER_LME (1 << 8) /* CPU is running in 64bit mode */
#define EFER_LMA (1 << 10) /* CPU uses 64bit memory paging (read-only) */
#define EFER_NXE (1 << 11) /* Execute disable bit active */
+#define EFER_SVME (1 << 12) /* AMD SVM instructions enabled */
+#define VM_CR_DPD (1 << 0)
+#define VM_CR_R_INIT (1 << 1)
+#define VM_CR_DIS_A20M (1 << 2)
+#define VM_CR_LOCK (1 << 3)
+#define VM_CR_SVMDIS (1 << 4)
/* Control register constants */
#define CR4_VME (1 << 0)
@@ -91,6 +123,25 @@ struct intr_descriptor {
#endif /* defined(__x86_64__) */
} __attribute__((__packed__));
+struct segment_descriptor {
+ unsigned int limit_lo : 16;
+ unsigned int baseaddr_lo : 24;
+ unsigned int flags_lo : 8;
+ unsigned int limit_hi : 4;
+ unsigned int flags_hi : 4;
+ unsigned int baseaddr_hi : 8;
+} __attribute__((__packed__));
+
+struct segment_descriptor64 {
+ unsigned int limit_lo : 16;
+ unsigned int baseaddr_lo : 24;
+ unsigned int flags_lo : 8;
+ unsigned int limit_hi : 4;
+ unsigned int flags_hi : 4;
+ uint64_t baseaddr_hi : 40;
+ uint32_t reserved;
+} __attribute__((__packed__));
+
struct page_table_entry_pae {
unsigned int present: 1;
unsigned int writable: 1;
@@ -116,15 +167,36 @@ struct kvm_cregs {
unsigned long cr0, cr2, cr3, cr4;
};
+struct kvm_sregs {
+ uint16_t cs, ds, es, fs, gs, ss;
+};
+
+struct kvm_regs64 {
+ uint64_t rax, rbx, rcx, rdx, rdi, rsi, rbp, rsp;
+ uint64_t r8, r9, r10, r11, r12, r13, r14, r15;
+};
+
extern struct page_table_entry_pae kvm_pagetable[];
extern struct intr_descriptor kvm_idt[X86_INTR_COUNT];
+extern struct segment_descriptor kvm_gdt[KVM_GDT_SIZE];
/* Page table helper functions */
uintptr_t kvm_get_page_address_pae(const struct page_table_entry_pae *entry);
+/* Segment descriptor table functions */
+void kvm_set_segment_descriptor(struct segment_descriptor *dst,
+ uint64_t baseaddr, uint32_t limit, unsigned int flags);
+void kvm_parse_segment_descriptor(struct segment_descriptor *src,
+ uint64_t *baseaddr, uint32_t *limit, unsigned int *flags);
+int kvm_find_free_descriptor(const struct segment_descriptor *table,
+ size_t size);
+unsigned int kvm_create_stack_descriptor(struct segment_descriptor *table,
+ size_t tabsize, void *stack_base);
+
/* Functions for querying CPU info and status */
void kvm_get_cpuid(unsigned int eax, unsigned int ecx, struct kvm_cpuid *buf);
void kvm_read_cregs(struct kvm_cregs *buf);
+void kvm_read_sregs(struct kvm_sregs *buf);
uint64_t kvm_rdmsr(unsigned int msr);
void kvm_wrmsr(unsigned int msr, uint64_t value);
diff --git a/testcases/kernel/kvm/include/kvm_x86_svm.h b/testcases/kernel/kvm/include/kvm_x86_svm.h
new file mode 100644
index 000000000..b4b1b80e2
--- /dev/null
+++ b/testcases/kernel/kvm/include/kvm_x86_svm.h
@@ -0,0 +1,166 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2023 SUSE LLC <mdoucha@suse.cz>
+ *
+ * x86-specific KVM helper functions and structures for AMD SVM
+ */
+
+#ifndef KVM_X86_SVM_H_
+#define KVM_X86_SVM_H_
+
+#include "kvm_x86.h"
+
+/* CPUID_GET_SVM_FEATURES flags returned in EDX */
+#define SVM_CPUID_NESTED_PAGING (1 << 0)
+#define SVM_CPUID_LBR_VIRT (1 << 1)
+#define SVM_CPUID_LOCK (1 << 2)
+#define SVM_CPUID_NRIP_SAVE (1 << 3)
+#define SVM_CPUID_TSC_RATE_MSR (1 << 4)
+#define SVM_CPUID_VMCB_CLEAN (1 << 5)
+#define SVM_CPUID_FLUSH_ASID (1 << 6)
+#define SVM_CPUID_DECODE_ASSIST (1 << 7)
+#define SVM_CPUID_PAUSE_FILTER (1 << 10)
+#define SVM_CPUID_PAUSE_THRESHOLD (1 << 12)
+#define SVM_CPUID_AVIC (1 << 13)
+#define SVM_CPUID_VMSAVE_VIRT (1 << 15)
+#define SVM_CPUID_VGIF (1 << 16)
+#define SVM_CPUID_GMET (1 << 17)
+#define SVM_CPUID_X2AVIC (1 << 18)
+#define SVM_CPUID_SSSCHECK (1 << 19)
+#define SVM_CPUID_SPEC_CTRL (1 << 20)
+#define SVM_CPUID_ROGPT (1 << 21)
+#define SVM_CPUID_HOST_MCE_OVERRIDE (1 << 23)
+#define SVM_CPUID_TLBI_CTL (1 << 24)
+#define SVM_CPUID_NMI_VIRT (1 << 25)
+#define SVM_CPUID_IBS_VIRT (1 << 26)
+
+/* SVM event intercept IDs */
+#define SVM_INTERCEPT_HLT 0x78
+#define SVM_INTERCEPT_VMRUN 0x80
+#define SVM_INTERCEPT_VMLOAD 0x82
+#define SVM_INTERCEPT_VMSAVE 0x83
+#define SVM_INTERCEPT_STGI 0x84
+#define SVM_INTERCEPT_CLGI 0x85
+#define SVM_INTERCEPT_MAX 0x95
+
+/* SVM vmrun exit codes */
+#define SVM_EXIT_HLT 0x78
+#define SVM_EXIT_VMRUN 0x80
+#define SVM_EXIT_VMLOAD 0x82
+#define SVM_EXIT_VMSAVE 0x83
+#define SVM_EXIT_STGI 0x84
+#define SVM_EXIT_CLGI 0x85
+#define SVM_EXIT_AVIC_NOACCEL 0x402
+#define SVM_EXIT_INVALID ((uint64_t)-1)
+
+/* SVM VMCB flags */
+#define SVM_INTR_AVIC (1 << 7)
+
+struct kvm_vmcb_descriptor {
+ uint16_t selector;
+ uint16_t attrib;
+ uint32_t limit;
+ uint64_t base;
+};
+
+struct kvm_vmcb {
+ /* VMCB control area */
+ uint8_t intercepts[20];
+ uint8_t reserved1[44];
+ uint64_t iopm_base_addr;
+ uint64_t msrpm_base_addr;
+ uint64_t tsc_offset;
+ uint32_t guest_asid;
+ uint32_t tlb_control;
+ uint8_t virtual_tpr;
+ uint8_t virtual_irq;
+ unsigned char virt_intr_prio: 4;
+ unsigned char virt_ignore_tpr: 4;
+ uint8_t virt_intr_ctl;
+ uint8_t virt_intr_vector;
+ uint8_t reserved2[3];
+ uint64_t interrupt_shadow;
+ uint64_t exitcode;
+ uint64_t exitinfo1;
+ uint64_t exitinfo2;
+ uint64_t exit_int_info;
+ uint64_t enable_nested_paging;
+ uint64_t avic_bar;
+ uint64_t ghcb_gpa;
+ uint64_t event_injection;
+ uint64_t nested_cr3;
+ uint64_t virt_ext;
+ uint32_t vmcb_clean;
+ uint8_t reserved3[4];
+ uint64_t next_rip;
+ uint8_t instr_len;
+ uint8_t instr_bytes[15];
+ uint64_t avic_backing_page;
+ uint8_t reserved4[8];
+ uint64_t avic_logical_ptr;
+ uint64_t avic_physical_ptr;
+ uint8_t reserved5[8];
+ uint64_t vmsa_pa;
+ uint64_t vmgexit_rax;
+ uint8_t vmgexit_cpl;
+ uint8_t reserved6[0x2e7];
+
+ /* VMCB state save area */
+ struct kvm_vmcb_descriptor es, cs, ss, ds, fs, gs;
+ struct kvm_vmcb_descriptor gdtr, ldtr, idtr, tr;
+ uint8_t reserved7[43];
+ uint8_t cpl;
+ uint8_t reserved8[4];
+ uint64_t efer;
+ uint8_t reserved9[112];
+ uint64_t cr4;
+ uint64_t cr3;
+ uint64_t cr0;
+ uint64_t dr7;
+ uint64_t dr6;
+ uint64_t rflags;
+ uint64_t rip;
+ uint8_t reserved10[88];
+ uint64_t rsp;
+ uint64_t s_cet;
+ uint64_t ssp;
+ uint64_t isst_addr;
+ uint64_t rax;
+ uint64_t star;
+ uint64_t lstar;
+ uint64_t cstar;
+ uint64_t sfmask;
+ uint64_t kernel_gs_base;
+ uint64_t sysenter_cs;
+ uint64_t sysenter_esp;
+ uint64_t sysenter_eip;
+ uint64_t cr2;
+ uint8_t reserved11[32];
+ uint64_t guest_pat;
+ uint8_t padding[0x990];
+};
+
+struct kvm_svm_vcpu {
+ struct kvm_vmcb *vmcb;
+ struct kvm_regs64 regs;
+};
+
+/* AMD SVM virtualization helper functions */
+int kvm_is_svm_supported(void);
+int kvm_get_svm_state(void);
+void kvm_set_svm_state(int enabled);
+
+void kvm_init_svm(void); /* Fully initialize host SVM environment */
+struct kvm_vmcb *kvm_alloc_vmcb(void);
+void kvm_vmcb_copy_gdt_descriptor(struct kvm_vmcb_descriptor *dst,
+ unsigned int gdt_id);
+void kvm_vmcb_set_intercept(struct kvm_vmcb *vmcb, unsigned int id,
+ unsigned int state);
+void kvm_init_guest_vmcb(struct kvm_vmcb *vmcb, uint32_t asid, uint16_t ss,
+ void *rsp, int (*guest_main)(void));
+struct kvm_svm_vcpu *kvm_create_svm_vcpu(int (*guest_main)(void),
+ int alloc_stack);
+
+void kvm_svm_vmrun(struct kvm_svm_vcpu *cpu);
+
+#endif /* KVM_X86_SVM_H_ */
diff --git a/testcases/kernel/kvm/kvm_svm01.c b/testcases/kernel/kvm/kvm_svm01.c
new file mode 100644
index 000000000..32d15526b
--- /dev/null
+++ b/testcases/kernel/kvm/kvm_svm01.c
@@ -0,0 +1,123 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2023 SUSE LLC
+ * Author: Nicolai Stange <nstange@suse.de>
+ * LTP port: Martin Doucha <mdoucha@suse.cz>
+ */
+
+/*\
+ * CVE 2021-3653
+ *
+ * Check that KVM either blocks enabling virtual interrupt controller (AVIC)
+ * in nested VMs or correctly sets up the required memory address translation.
+ * If AVIC is enabled without address translation in the host kernel,
+ * the nested VM will be able to read and write an arbitraty physical memory
+ * page specified by the parent VM. Unauthorized memory access fixed in:
+ *
+ * commit 0f923e07124df069ba68d8bb12324398f4b6b709
+ * Author: Maxim Levitsky <mlevitsk@redhat.com>
+ * Date: Thu Jul 15 01:56:24 2021 +0300
+ *
+ * KVM: nSVM: avoid picking up unsupported bits from L2 in int_ctl (CVE-2021-3653)
+ */
+
+#include "kvm_test.h"
+
+#ifdef COMPILE_PAYLOAD
+#if defined(__i386__) || defined(__x86_64__)
+
+#include "kvm_x86_svm.h"
+
+#define AVIC_REG_ADDR 0x280
+#define AVIC_TEST_VAL 0xec
+#define AVIC_READ_FAIL 0x12ead
+
+#define AVIC_INFO_MASK ((1ULL << 32) | 0xff0)
+#define AVIC_INFO_EXP ((1ULL << 32) | AVIC_REG_ADDR)
+
+static uint32_t * const avic_ptr = (uint32_t *)AVIC_REG_ADDR;
+
+static int guest_main(void)
+{
+ if (*avic_ptr != 0xaaaaaaaa)
+ return AVIC_READ_FAIL;
+
+ *avic_ptr = AVIC_TEST_VAL;
+ return 0;
+}
+
+void main(void)
+{
+ struct kvm_svm_vcpu *vcpu;
+
+ kvm_init_svm();
+ vcpu = kvm_create_svm_vcpu(guest_main, 1);
+
+ /*
+ * Enable AVIC and set both the AVIC base address (where the nested VM
+ * will write) and backing page address (where the parent VM expects
+ * to see the changes) to 0
+ */
+ vcpu->vmcb->virt_intr_ctl |= SVM_INTR_AVIC;
+ vcpu->vmcb->avic_backing_page = 0;
+ vcpu->vmcb->avic_bar = 0;
+ memset((void *)8, 0xaa, PAGESIZE - 8);
+
+ /* Write into AVIC backing page in the nested VM */
+ kvm_svm_vmrun(vcpu);
+
+ switch (vcpu->vmcb->exitcode) {
+ case SVM_EXIT_HLT:
+ if (vcpu->vmcb->rax == AVIC_READ_FAIL) {
+ tst_res(TFAIL, "Nested VM can read host memory");
+ return;
+ }
+
+ if (vcpu->vmcb->rax)
+ tst_brk(TBROK, "Unexpected guest_main() return value");
+
+ break;
+
+ case SVM_EXIT_AVIC_NOACCEL:
+ if ((vcpu->vmcb->exitinfo1 & AVIC_INFO_MASK) == AVIC_INFO_EXP) {
+ tst_res(TPASS, "AVIC register write caused VMEXIT");
+ break;
+ }
+
+ /* unexpected exit, fall through */
+
+ default:
+ tst_brk(TBROK, "Nested VM exited unexpectedly");
+ }
+
+ if (*avic_ptr != AVIC_TEST_VAL) {
+ tst_res(TFAIL, "Write into AVIC ESR redirected to host memory");
+ return;
+ }
+
+ tst_res(TPASS, "Writes into AVIC backing page were not redirected");
+}
+
+#else /* defined(__i386__) || defined(__x86_64__) */
+TST_TEST_TCONF("Test supported only on x86");
+#endif /* defined(__i386__) || defined(__x86_64__) */
+
+#else /* COMPILE_PAYLOAD */
+
+static struct tst_test test = {
+ .test_all = tst_kvm_run,
+ .setup = tst_kvm_setup,
+ .cleanup = tst_kvm_cleanup,
+ .supported_archs = (const char *const []) {
+ "x86_64",
+ "x86",
+ NULL
+ },
+ .tags = (struct tst_tag[]){
+ {"linux-git", "0f923e07124d"},
+ {"CVE", "2021-3653"},
+ {}
+ }
+};
+
+#endif /* COMPILE_PAYLOAD */
diff --git a/testcases/kernel/kvm/kvm_svm02.c b/testcases/kernel/kvm/kvm_svm02.c
new file mode 100644
index 000000000..5d2e2ce37
--- /dev/null
+++ b/testcases/kernel/kvm/kvm_svm02.c
@@ -0,0 +1,152 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2023 SUSE LLC
+ * Author: Nicolai Stange <nstange@suse.de>
+ * LTP port: Martin Doucha <mdoucha@suse.cz>
+ */
+
+/*\
+ * CVE 2021-3656
+ *
+ * Check that KVM correctly intercepts VMSAVE and VMLOAD instructions
+ * in a nested virtual machine even when the parent guest disables
+ * intercepting either instruction. If KVM does not override the disabled
+ * intercepts, it'll give the nested VM read/write access to a few bytes
+ * of an arbitrary physical memory page. Unauthorized memory access fixed in:
+ *
+ * commit c7dfa4009965a9b2d7b329ee970eb8da0d32f0bc
+ * Author: Maxim Levitsky <mlevitsk@redhat.com>
+ * Date: Mon Jul 19 16:05:00 2021 +0300
+ *
+ * KVM: nSVM: always intercept VMLOAD/VMSAVE when nested (CVE-2021-3656)
+ */
+
+#include "kvm_test.h"
+
+#ifdef COMPILE_PAYLOAD
+#if defined(__i386__) || defined(__x86_64__)
+
+#include "kvm_x86_svm.h"
+
+static void *vmsave_buf;
+
+/* Load FS, GS, TR and LDTR state from vmsave_buf */
+static int guest_vmload(void)
+{
+ asm (
+ "vmload %0\n"
+ :
+ : "a" (vmsave_buf)
+ );
+ return 0;
+}
+
+/* Save current FS, GS, TR and LDTR state to vmsave_buf */
+static int guest_vmsave(void)
+{
+ asm (
+ "vmsave %0\n"
+ :
+ : "a" (vmsave_buf)
+ );
+ return 0;
+}
+
+static int cmp_descriptor(const struct kvm_vmcb_descriptor *a,
+ const struct kvm_vmcb_descriptor *b)
+{
+ int ret;
+
+ ret = a->selector != b->selector;
+ ret = ret || a->attrib != b->attrib;
+ ret = ret || a->limit != b->limit;
+ ret = ret || a->base != b->base;
+ return ret;
+}
+
+/* Return non-zero if the VMCB fields touched by vmsave/vmload differ */
+static int cmp_vmcb(const struct kvm_vmcb *a, const struct kvm_vmcb *b)
+{
+ int ret;
+
+ ret = cmp_descriptor(&a->fs, &b->fs);
+ ret = ret || cmp_descriptor(&a->gs, &b->gs);
+ ret = ret || cmp_descriptor(&a->tr, &b->tr);
+ ret = ret || cmp_descriptor(&a->ldtr, &b->ldtr);
+ ret = ret || a->kernel_gs_base != b->kernel_gs_base;
+ ret = ret || a->star != b->star;
+ ret = ret || a->lstar != b->lstar;
+ ret = ret || a->cstar != b->cstar;
+ ret = ret || a->sfmask != b->sfmask;
+ ret = ret || a->sysenter_cs != b->sysenter_cs;
+ ret = ret || a->sysenter_esp != b->sysenter_esp;
+ ret = ret || a->sysenter_eip != b->sysenter_eip;
+ return ret;
+}
+
+void main(void)
+{
+ uint16_t ss;
+ uint64_t rsp;
+ struct kvm_svm_vcpu *vcpu;
+
+ kvm_init_svm();
+ vcpu = kvm_create_svm_vcpu(guest_vmload, 1);
+ kvm_vmcb_set_intercept(vcpu->vmcb, SVM_INTERCEPT_VMLOAD, 0);
+ vmsave_buf = kvm_alloc_vmcb();
+
+ /* Save allocated stack for later VM reinit */
+ ss = vcpu->vmcb->ss.selector;
+ rsp = vcpu->vmcb->rsp;
+
+ /* Load partial state from vmsave_buf and save it to vcpu->vmcb */
+ kvm_svm_vmrun(vcpu);
+
+ if (vcpu->vmcb->exitcode != SVM_EXIT_HLT)
+ tst_brk(TBROK, "Nested VM exited unexpectedly");
+
+ if (cmp_vmcb(vcpu->vmcb, vmsave_buf)) {
+ tst_res(TFAIL, "Nested VM can read host memory");
+ return;
+ }
+
+ /* Load state from vcpu->vmcb and save it to vmsave_buf */
+ memset(vmsave_buf, 0xaa, sizeof(struct kvm_vmcb));
+ kvm_init_guest_vmcb(vcpu->vmcb, 1, ss, (void *)rsp, guest_vmsave);
+ kvm_vmcb_set_intercept(vcpu->vmcb, SVM_INTERCEPT_VMSAVE, 0);
+ kvm_svm_vmrun(vcpu);
+
+ if (vcpu->vmcb->exitcode != SVM_EXIT_HLT)
+ tst_brk(TBROK, "Nested VM exited unexpectedly");
+
+ if (cmp_vmcb(vcpu->vmcb, vmsave_buf)) {
+ tst_res(TFAIL, "Nested VM can overwrite host memory");
+ return;
+ }
+
+ tst_res(TPASS, "VMLOAD and VMSAVE were intercepted by kernel");
+}
+
+#else /* defined(__i386__) || defined(__x86_64__) */
+TST_TEST_TCONF("Test supported only on x86");
+#endif /* defined(__i386__) || defined(__x86_64__) */
+
+#else /* COMPILE_PAYLOAD */
+
+static struct tst_test test = {
+ .test_all = tst_kvm_run,
+ .setup = tst_kvm_setup,
+ .cleanup = tst_kvm_cleanup,
+ .supported_archs = (const char *const []) {
+ "x86_64",
+ "x86",
+ NULL
+ },
+ .tags = (struct tst_tag[]){
+ {"linux-git", "c7dfa4009965"},
+ {"CVE", "2021-3656"},
+ {}
+ }
+};
+
+#endif /* COMPILE_PAYLOAD */
diff --git a/testcases/kernel/kvm/kvm_svm03.c b/testcases/kernel/kvm/kvm_svm03.c
new file mode 100644
index 000000000..87164d013
--- /dev/null
+++ b/testcases/kernel/kvm/kvm_svm03.c
@@ -0,0 +1,169 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2023 SUSE LLC
+ * Author: Nicolai Stange <nstange@suse.de>
+ * LTP port: Martin Doucha <mdoucha@suse.cz>
+ */
+
+/*\
+ * Check that KVM correctly intercepts the CLGI instruction in a nested
+ * virtual machine even when the parent guest disables intercept.
+ * If KVM does not override the disabled intercept, it'll allow the nested VM
+ * to hold the physical CPU indefinitely and potentially perform a denial
+ * of service attack against the host kernel. CPU lockup fixed in:
+ *
+ * commit 91b7130cb6606d8c6b3b77e54426b3f3a83f48b1
+ * Author: Paolo Bonzini <pbonzini@redhat.com>
+ * Date: Fri May 22 12:28:52 2020 -0400
+ *
+ * KVM: SVM: preserve VGIF across VMCB switch
+ */
+
+#include "kvm_test.h"
+
+#ifdef COMPILE_PAYLOAD
+#if defined(__i386__) || defined(__x86_64__)
+
+#include "kvm_x86_svm.h"
+
+/* Disable global interrupts */
+static int guest_clgi(void)
+{
+ int ret, *result = (int *)KVM_RESULT_BASEADDR;
+
+ /*
+ * Make sure that result page is present in memory. CLGI may disable
+ * page fault handling on the current CPU. The actual value
+ * at that address is irrelevant.
+ */
+ ret = *result;
+
+ /* Disable global interrupts */
+ asm ("clgi");
+
+ /* Signal host to kill the VM and wait */
+ tst_wait_host(NULL);
+ return ret;
+}
+
+void main(void)
+{
+ struct kvm_svm_vcpu *vcpu;
+
+ kvm_init_svm();
+ vcpu = kvm_create_svm_vcpu(guest_clgi, 1);
+ kvm_vmcb_set_intercept(vcpu->vmcb, SVM_INTERCEPT_CLGI, 0);
+ kvm_svm_vmrun(vcpu);
+
+ if (vcpu->vmcb->exitcode != SVM_EXIT_HLT)
+ tst_brk(TBROK, "Nested VM exited unexpectedly");
+}
+
+#else /* defined(__i386__) || defined(__x86_64__) */
+TST_TEST_TCONF("Test supported only on x86");
+#endif /* defined(__i386__) || defined(__x86_64__) */
+
+#else /* COMPILE_PAYLOAD */
+
+#include <pthread.h>
+#include "tst_safe_pthread.h"
+#include "tst_safe_clocks.h"
+
+static struct tst_kvm_instance test_vm = { .vm_fd = -1 };
+static pthread_mutex_t mutex;
+static int mutex_init;
+
+static void sighandler(int sig LTP_ATTRIBUTE_UNUSED)
+{
+
+}
+
+static void *vm_thread(void *arg)
+{
+ SAFE_PTHREAD_MUTEX_LOCK(&mutex);
+ tst_kvm_run_instance(&test_vm, EINTR);
+ SAFE_PTHREAD_MUTEX_UNLOCK(&mutex);
+ return arg;
+}
+
+static void setup(void)
+{
+ struct sigaction sa = { .sa_handler = sighandler };
+ pthread_mutexattr_t attr;
+
+ SAFE_PTHREAD_MUTEXATTR_INIT(&attr);
+ SAFE_PTHREAD_MUTEXATTR_SETTYPE(&attr, PTHREAD_MUTEX_NORMAL);
+ SAFE_PTHREAD_MUTEX_INIT(&mutex, &attr);
+ mutex_init = 1;
+ SAFE_PTHREAD_MUTEXATTR_DESTROY(&attr);
+ SAFE_SIGACTION(SIGUSR1, &sa, NULL);
+}
+
+static void run(void)
+{
+ struct timespec timeout;
+ pthread_t tid;
+ int ret;
+
+ tst_kvm_create_instance(&test_vm, DEFAULT_RAM_SIZE);
+
+ SAFE_PTHREAD_CREATE(&tid, NULL, vm_thread, NULL);
+ ret = tst_kvm_wait_guest(&test_vm, 2000);
+
+ if (ret == KVM_TEXIT) {
+ SAFE_PTHREAD_JOIN(tid, NULL);
+ tst_brk(TCONF, "Guest exited early");
+ }
+
+ if (ret)
+ tst_brk(TBROK, "Wait for guest initialization timed out");
+
+ SAFE_PTHREAD_KILL(tid, SIGUSR1);
+ SAFE_CLOCK_GETTIME(CLOCK_REALTIME, &timeout);
+ timeout.tv_sec += 2;
+
+ if (SAFE_PTHREAD_MUTEX_TIMEDLOCK(&mutex, &timeout)) {
+ tst_kvm_clear_guest_signal(&test_vm);
+ tst_res(TFAIL, "VM thread does not respond to signals");
+ } else {
+ SAFE_PTHREAD_MUTEX_UNLOCK(&mutex);
+ tst_res(TPASS, "VM thread was interrupted by signal");
+ }
+
+ SAFE_PTHREAD_JOIN(tid, NULL);
+ tst_kvm_destroy_instance(&test_vm);
+ tst_free_all();
+}
+
+static void cleanup(void)
+{
+ /*
+ * If the mutex is locked, the VM is likely still running, cannot
+ * clean up anything
+ */
+ if (!mutex_init || SAFE_PTHREAD_MUTEX_TRYLOCK(&mutex))
+ return;
+
+ if (!SAFE_PTHREAD_MUTEX_UNLOCK(&mutex))
+ SAFE_PTHREAD_MUTEX_DESTROY(&mutex);
+
+ tst_kvm_destroy_instance(&test_vm);
+}
+
+static struct tst_test test = {
+ .test_all = run,
+ .setup = setup,
+ .cleanup = cleanup,
+ .min_cpus = 2,
+ .supported_archs = (const char *const []) {
+ "x86_64",
+ "x86",
+ NULL
+ },
+ .tags = (struct tst_tag[]){
+ {"linux-git", "91b7130cb660"},
+ {}
+ }
+};
+
+#endif /* COMPILE_PAYLOAD */
diff --git a/testcases/kernel/kvm/lib_guest.c b/testcases/kernel/kvm/lib_guest.c
index d237293fc..f3e21d3d6 100644
--- a/testcases/kernel/kvm/lib_guest.c
+++ b/testcases/kernel/kvm/lib_guest.c
@@ -82,7 +82,7 @@ char *ptr2hex(char *dest, uintptr_t val)
uintptr_t tmp;
char *ret = dest;
- for (i = 4; val >> i; i += 4)
+ for (i = 4, tmp = val >> 4; tmp; i += 4, tmp >>= 4)
;
do {
@@ -155,6 +155,22 @@ void tst_brk_(const char *file, const int lineno, int result,
kvm_exit();
}
+void tst_signal_host(void *data)
+{
+ test_result->file_addr = (uintptr_t)data;
+ test_result->result = KVM_TSYNC;
+}
+
+void tst_wait_host(void *data)
+{
+ volatile int32_t *vres = &test_result->result;
+
+ tst_signal_host(data);
+
+ while (*vres != KVM_TNONE)
+ ;
+}
+
void tst_handle_interrupt(struct kvm_interrupt_frame *ifrm, long vector,
unsigned long errcode)
{
diff --git a/testcases/kernel/kvm/lib_host.c b/testcases/kernel/kvm/lib_host.c
index 2782e68b0..8e3d6094e 100644
--- a/testcases/kernel/kvm/lib_host.c
+++ b/testcases/kernel/kvm/lib_host.c
@@ -10,6 +10,8 @@
#define TST_NO_DEFAULT_MAIN
#include "tst_test.h"
+#include "tst_clocks.h"
+#include "tst_timer.h"
#include "kvm_host.h"
static struct tst_kvm_instance test_vm = { .vm_fd = -1 };
@@ -234,14 +236,28 @@ void tst_kvm_create_instance(struct tst_kvm_instance *inst, size_t ram_size)
inst->result->message[0] = '\0';
}
-void tst_kvm_run_instance(struct tst_kvm_instance *inst)
+int tst_kvm_run_instance(struct tst_kvm_instance *inst, int exp_errno)
{
struct kvm_regs regs;
+ int ret;
while (1) {
inst->result->result = KVM_TNONE;
inst->result->message[0] = '\0';
- SAFE_IOCTL(inst->vcpu_fd, KVM_RUN, 0);
+ errno = 0;
+ ret = ioctl(inst->vcpu_fd, KVM_RUN, 0);
+
+ if (ret == -1) {
+ if (errno == exp_errno)
+ return ret;
+
+ tst_brk(TBROK | TERRNO, "ioctl(KVM_RUN) failed");
+ }
+
+ if (ret < 0) {
+ tst_brk(TBROK | TERRNO,
+ "Invalid ioctl(KVM_RUN) return value %d", ret);
+ }
if (inst->vcpu_info->exit_reason != KVM_EXIT_HLT) {
SAFE_IOCTL(inst->vcpu_fd, KVM_GET_REGS, &regs);
@@ -255,6 +271,8 @@ void tst_kvm_run_instance(struct tst_kvm_instance *inst)
tst_kvm_print_result(inst);
}
+
+ return ret;
}
void tst_kvm_destroy_instance(struct tst_kvm_instance *inst)
@@ -272,6 +290,37 @@ void tst_kvm_destroy_instance(struct tst_kvm_instance *inst)
memset(inst->ram, 0, sizeof(inst->ram));
}
+int tst_kvm_wait_guest(struct tst_kvm_instance *inst, int timeout_ms)
+{
+ volatile struct tst_kvm_result *result = inst->result;
+ int32_t res;
+ struct timespec start, now;
+
+ if (timeout_ms >= 0)
+ tst_clock_gettime(CLOCK_MONOTONIC, &start);
+
+ while ((res = result->result) != KVM_TSYNC) {
+ if (res == KVM_TEXIT)
+ return res;
+
+ if (timeout_ms >= 0) {
+ tst_clock_gettime(CLOCK_MONOTONIC, &now);
+
+ if (tst_timespec_diff_ms(now, start) >= timeout_ms)
+ return -1;
+ }
+
+ usleep(1000);
+ }
+
+ return 0;
+}
+
+void tst_kvm_clear_guest_signal(struct tst_kvm_instance *inst)
+{
+ inst->result->result = KVM_TNONE;
+}
+
void tst_kvm_setup(void)
{
@@ -280,7 +329,7 @@ void tst_kvm_setup(void)
void tst_kvm_run(void)
{
tst_kvm_create_instance(&test_vm, DEFAULT_RAM_SIZE);
- tst_kvm_run_instance(&test_vm);
+ tst_kvm_run_instance(&test_vm, 0);
tst_kvm_destroy_instance(&test_vm);
tst_free_all();
}
diff --git a/testcases/kernel/kvm/lib_x86.c b/testcases/kernel/kvm/lib_x86.c
index dc2354b10..3e6656f11 100644
--- a/testcases/kernel/kvm/lib_x86.c
+++ b/testcases/kernel/kvm/lib_x86.c
@@ -5,7 +5,9 @@
* x86-specific KVM helper functions
*/
-#include "kvm_x86.h"
+#include "kvm_x86_svm.h"
+
+void kvm_svm_guest_entry(void);
struct kvm_interrupt_frame {
uintptr_t eip, cs, eflags, esp, ss;
@@ -110,6 +112,98 @@ uintptr_t kvm_get_page_address_pae(const struct page_table_entry_pae *entry)
return entry->address << 12;
}
+#ifdef __x86_64__
+static void kvm_set_segment_descriptor64(struct segment_descriptor64 *dst,
+ uint64_t baseaddr, uint32_t limit, unsigned int flags)
+{
+
+ dst->baseaddr_lo = baseaddr & 0xffffff;
+ dst->baseaddr_hi = baseaddr >> 24;
+ dst->limit_lo = limit & 0xffff;
+ dst->limit_hi = limit >> 16;
+ dst->flags_lo = flags & 0xff;
+ dst->flags_hi = (flags >> 8) & 0xf;
+ dst->reserved = 0;
+}
+#endif
+
+void kvm_set_segment_descriptor(struct segment_descriptor *dst,
+ uint64_t baseaddr, uint32_t limit, unsigned int flags)
+{
+ if (limit >> 20)
+ tst_brk(TBROK, "Segment limit out of range");
+
+#ifdef __x86_64__
+ /* System descriptors have double size in 64bit mode */
+ if (!(flags & SEGFLAG_NSYSTEM)) {
+ kvm_set_segment_descriptor64((struct segment_descriptor64 *)dst,
+ baseaddr, limit, flags);
+ return;
+ }
+#endif
+
+ if (baseaddr >> 32)
+ tst_brk(TBROK, "Segment base address out of range");
+
+ dst->baseaddr_lo = baseaddr & 0xffffff;
+ dst->baseaddr_hi = baseaddr >> 24;
+ dst->limit_lo = limit & 0xffff;
+ dst->limit_hi = limit >> 16;
+ dst->flags_lo = flags & 0xff;
+ dst->flags_hi = (flags >> 8) & 0xf;
+}
+
+void kvm_parse_segment_descriptor(struct segment_descriptor *src,
+ uint64_t *baseaddr, uint32_t *limit, unsigned int *flags)
+{
+ if (baseaddr) {
+ *baseaddr = (((uint64_t)src->baseaddr_hi) << 24) |
+ src->baseaddr_lo;
+ }
+
+ if (limit)
+ *limit = (((uint32_t)src->limit_hi) << 16) | src->limit_lo;
+
+ if (flags)
+ *flags = (((uint32_t)src->flags_hi) << 8) | src->flags_lo;
+}
+
+int kvm_find_free_descriptor(const struct segment_descriptor *table,
+ size_t size)
+{
+ const struct segment_descriptor *ptr;
+ size_t i;
+
+ for (i = 0, ptr = table; i < size; i++, ptr++) {
+ if (!(ptr->flags_lo & SEGFLAG_PRESENT))
+ return i;
+
+#ifdef __x86_64__
+ /* System descriptors have double size in 64bit mode */
+ if (!(ptr->flags_lo & SEGFLAG_NSYSTEM)) {
+ ptr++;
+ i++;
+ }
+#endif
+ }
+
+ return -1;
+}
+
+unsigned int kvm_create_stack_descriptor(struct segment_descriptor *table,
+ size_t tabsize, void *stack_base)
+{
+ int ret = kvm_find_free_descriptor(table, tabsize);
+
+ if (ret < 0)
+ tst_brk(TBROK, "Descriptor table is full");
+
+ kvm_set_segment_descriptor(table + ret, 0,
+ (((uintptr_t)stack_base) - 1) >> 12, SEGTYPE_STACK |
+ SEGFLAG_PRESENT | SEGFLAG_32BIT | SEGFLAG_PAGE_LIMIT);
+ return ret;
+}
+
void kvm_get_cpuid(unsigned int eax, unsigned int ecx, struct kvm_cpuid *buf)
{
asm (
@@ -148,3 +242,154 @@ uintptr_t kvm_get_interrupt_ip(const struct kvm_interrupt_frame *ifrm)
{
return ifrm->eip;
}
+
+int kvm_is_svm_supported(void)
+{
+ struct kvm_cpuid buf;
+
+ kvm_get_cpuid(CPUID_GET_INPUT_RANGE, 0, &buf);
+
+ if (buf.eax < CPUID_GET_EXT_FEATURES)
+ return 0;
+
+ kvm_get_cpuid(CPUID_GET_EXT_FEATURES, 0, &buf);
+ return buf.ecx & 0x4;
+}
+
+int kvm_get_svm_state(void)
+{
+ return kvm_rdmsr(MSR_EFER) & EFER_SVME;
+}
+
+void kvm_set_svm_state(int enabled)
+{
+ uint64_t value;
+
+ if (!kvm_is_svm_supported())
+ tst_brk(TCONF, "CPU does not support SVM");
+
+ if (kvm_rdmsr(MSR_VM_CR) & VM_CR_SVMDIS)
+ tst_brk(TCONF, "SVM is supported but disabled");
+
+ value = kvm_rdmsr(MSR_EFER);
+
+ if (enabled)
+ value |= EFER_SVME;
+ else
+ value &= ~EFER_SVME;
+
+ kvm_wrmsr(MSR_EFER, value);
+}
+
+struct kvm_vmcb *kvm_alloc_vmcb(void)
+{
+ struct kvm_vmcb *ret;
+
+ ret = tst_heap_alloc_aligned(sizeof(struct kvm_vmcb), PAGESIZE);
+ memset(ret, 0, sizeof(struct kvm_vmcb));
+ return ret;
+}
+
+void kvm_init_svm(void)
+{
+ kvm_set_svm_state(1);
+ kvm_wrmsr(MSR_VM_HSAVE_PA, (uintptr_t)kvm_alloc_vmcb());
+}
+
+void kvm_vmcb_copy_gdt_descriptor(struct kvm_vmcb_descriptor *dst,
+ unsigned int gdt_id)
+{
+ uint64_t baseaddr;
+ uint32_t limit;
+ unsigned int flags;
+
+ if (gdt_id >= KVM_GDT_SIZE)
+ tst_brk(TBROK, "GDT descriptor ID out of range");
+
+ kvm_parse_segment_descriptor(kvm_gdt + gdt_id, &baseaddr, &limit,
+ &flags);
+
+ if (!(flags & SEGFLAG_PRESENT)) {
+ memset(dst, 0, sizeof(struct kvm_vmcb_descriptor));
+ return;
+ }
+
+ if (flags & SEGFLAG_PAGE_LIMIT)
+ limit = (limit << 12) | 0xfff;
+
+ dst->selector = gdt_id << 3;
+ dst->attrib = flags;
+ dst->limit = limit;
+ dst->base = baseaddr;
+}
+
+void kvm_vmcb_set_intercept(struct kvm_vmcb *vmcb, unsigned int id,
+ unsigned int state)
+{
+ unsigned int addr = id / 8, bit = 1 << (id % 8);
+
+ if (id >= SVM_INTERCEPT_MAX)
+ tst_brk(TBROK, "Invalid SVM intercept ID");
+
+ if (state)
+ vmcb->intercepts[addr] |= bit;
+ else
+ vmcb->intercepts[addr] &= ~bit;
+}
+
+void kvm_init_guest_vmcb(struct kvm_vmcb *vmcb, uint32_t asid, uint16_t ss,
+ void *rsp, int (*guest_main)(void))
+{
+ struct kvm_cregs cregs;
+ struct kvm_sregs sregs;
+
+ kvm_read_cregs(&cregs);
+ kvm_read_sregs(&sregs);
+
+ kvm_vmcb_set_intercept(vmcb, SVM_INTERCEPT_VMRUN, 1);
+ kvm_vmcb_set_intercept(vmcb, SVM_INTERCEPT_HLT, 1);
+
+ kvm_vmcb_copy_gdt_descriptor(&vmcb->es, sregs.es >> 3);
+ kvm_vmcb_copy_gdt_descriptor(&vmcb->cs, sregs.cs >> 3);
+ kvm_vmcb_copy_gdt_descriptor(&vmcb->ss, ss);
+ kvm_vmcb_copy_gdt_descriptor(&vmcb->ds, sregs.ds >> 3);
+ kvm_vmcb_copy_gdt_descriptor(&vmcb->fs, sregs.fs >> 3);
+ kvm_vmcb_copy_gdt_descriptor(&vmcb->gs, sregs.gs >> 3);
+ vmcb->gdtr.base = (uintptr_t)kvm_gdt;
+ vmcb->gdtr.limit = (KVM_GDT_SIZE*sizeof(struct segment_descriptor)) - 1;
+ vmcb->idtr.base = (uintptr_t)kvm_idt;
+ vmcb->idtr.limit = (X86_INTR_COUNT*sizeof(struct intr_descriptor)) - 1;
+
+ vmcb->guest_asid = asid;
+ vmcb->efer = kvm_rdmsr(MSR_EFER);
+ vmcb->cr0 = cregs.cr0;
+ vmcb->cr3 = cregs.cr3;
+ vmcb->cr4 = cregs.cr4;
+ vmcb->rip = (uintptr_t)kvm_svm_guest_entry;
+ vmcb->rax = (uintptr_t)guest_main;
+ vmcb->rsp = (uintptr_t)rsp;
+ vmcb->rflags = 0x200; /* Interrupts enabled */
+}
+
+struct kvm_svm_vcpu *kvm_create_svm_vcpu(int (*guest_main)(void),
+ int alloc_stack)
+{
+ uint16_t ss = 0;
+ char *stack = NULL;
+ struct kvm_vmcb *vmcb;
+ struct kvm_svm_vcpu *ret;
+
+ vmcb = kvm_alloc_vmcb();
+
+ if (alloc_stack) {
+ stack = tst_heap_alloc_aligned(2 * PAGESIZE, PAGESIZE);
+ ss = kvm_create_stack_descriptor(kvm_gdt, KVM_GDT_SIZE, stack);
+ stack += 2 * PAGESIZE;
+ }
+
+ kvm_init_guest_vmcb(vmcb, 1, ss, stack, guest_main);
+ ret = tst_heap_alloc(sizeof(struct kvm_svm_vcpu));
+ memset(ret, 0, sizeof(struct kvm_svm_vcpu));
+ ret->vmcb = vmcb;
+ return ret;
+}
diff --git a/testcases/kernel/kvm/linker/x86.lds b/testcases/kernel/kvm/linker/x86.lds
index 95edb0be0..6e69c4d0f 100644
--- a/testcases/kernel/kvm/linker/x86.lds
+++ b/testcases/kernel/kvm/linker/x86.lds
@@ -4,6 +4,7 @@ PHDRS
{
headers PT_PHDR PHDRS ;
text PT_LOAD FILEHDR PHDRS ;
+ data PT_LOAD ;
bss PT_LOAD ;
}
@@ -18,7 +19,7 @@ SECTIONS
.init.boot :
{
*(.init.protected_mode)
- *(.data.gdt32)
+ *(.init.gdt32)
*(.init.memlayout)
} :text
@@ -40,7 +41,7 @@ SECTIONS
{
*(.data.strings)
*(.data)
- }
+ } :data
.preinit_array :
{
diff --git a/testcases/kernel/kvm/linker/x86_64.lds b/testcases/kernel/kvm/linker/x86_64.lds
index ac372f863..9e62aa5ad 100644
--- a/testcases/kernel/kvm/linker/x86_64.lds
+++ b/testcases/kernel/kvm/linker/x86_64.lds
@@ -4,6 +4,7 @@ PHDRS
{
headers PT_PHDR PHDRS ;
text PT_LOAD FILEHDR PHDRS ;
+ data PT_LOAD ;
bss PT_LOAD ;
}
@@ -18,7 +19,7 @@ SECTIONS
.init.boot :
{
*(.init.protected_mode)
- *(.data.gdt32)
+ *(.init.gdt32)
*(.init.memlayout)
} :text
@@ -40,7 +41,7 @@ SECTIONS
{
*(.data.strings)
*(.data)
- }
+ } :data
.preinit_array :
{
diff --git a/testcases/kernel/mem/.gitignore b/testcases/kernel/mem/.gitignore
index 06e125d03..7258489ed 100644
--- a/testcases/kernel/mem/.gitignore
+++ b/testcases/kernel/mem/.gitignore
@@ -33,6 +33,7 @@
/hugetlb/hugemmap/hugemmap29
/hugetlb/hugemmap/hugemmap30
/hugetlb/hugemmap/hugemmap31
+/hugetlb/hugemmap/hugemmap32
/hugetlb/hugeshmat/hugeshmat01
/hugetlb/hugeshmat/hugeshmat02
/hugetlb/hugeshmat/hugeshmat03
diff --git a/testcases/kernel/mem/hugetlb/hugemmap/Makefile b/testcases/kernel/mem/hugetlb/hugemmap/Makefile
index 6f10807cd..2d651b4aa 100644
--- a/testcases/kernel/mem/hugetlb/hugemmap/Makefile
+++ b/testcases/kernel/mem/hugetlb/hugemmap/Makefile
@@ -8,5 +8,4 @@ include $(top_srcdir)/include/mk/testcases.mk
include $(abs_srcdir)/../Makefile.inc
include $(top_srcdir)/include/mk/generic_leaf_target.mk
-hugemmap15: CFLAGS+=-O0
hugemmap06: CFLAGS+=-pthread
diff --git a/testcases/kernel/mem/hugetlb/hugemmap/hugemmap15.c b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap15.c
index 07e65a160..4d1984070 100644
--- a/testcases/kernel/mem/hugetlb/hugemmap/hugemmap15.c
+++ b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap15.c
@@ -19,6 +19,10 @@
* remap, or because the icache happens to get flushed in the interim.
*/
+#if defined(__clang__)
+ #pragma clang optimize off
+#endif
+
#define _GNU_SOURCE
#include "hugetlb.h"
@@ -27,16 +31,7 @@
defined(__aarch64__) || (defined(__riscv) && __riscv_xlen == 64) || \
defined(__i386__) || defined(__x86_64__) || defined(__arm__)
-#include <stdio.h>
-#include <stdlib.h>
#include <setjmp.h>
-#include <unistd.h>
-#include <signal.h>
-#include <sys/mman.h>
-#include <ucontext.h>
-#include <limits.h>
-#include <sys/param.h>
-#include <sys/types.h>
#define SUCC_JMP 1
#define FAIL_JMP 2
diff --git a/testcases/kernel/mem/hugetlb/hugemmap/hugemmap24.c b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap24.c
index a465aadec..158a03010 100644
--- a/testcases/kernel/mem/hugetlb/hugemmap/hugemmap24.c
+++ b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap24.c
@@ -23,7 +23,7 @@
static int fd = -1;
static unsigned long slice_boundary;
-static long hpage_size, page_size;
+static unsigned long hpage_size, page_size;
static int init_slice_boundary(int fd)
{
@@ -44,6 +44,13 @@ static int init_slice_boundary(int fd)
heap = malloc(1);
free(heap);
+ /* Avoid underflow on systems with large huge pages.
+ * The additionally plus heap address is to reduce the possibility
+ * of MAP_FIXED stomp over existing mappings.
+ */
+ while (slice_boundary + slice_size < (unsigned long)heap + 2*hpage_size)
+ slice_boundary += slice_size;
+
/* Find 2 neighbour slices with couple huge pages free
* around slice boundary.
* 16 is the maximum number of slices (low/high)
diff --git a/testcases/kernel/mem/hugetlb/hugemmap/hugemmap32.c b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap32.c
new file mode 100644
index 000000000..d27e5b8b2
--- /dev/null
+++ b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap32.c
@@ -0,0 +1,95 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2023, IBM Corporation.
+ * Author: Tarun Sahu
+ */
+
+/*\
+ * [Description]
+ *
+ * Before kernel version 5.10-rc7, there was a bug that resulted in a "Bad Page
+ * State" error when freeing gigantic hugepages. This happened because the
+ * struct page entry compound_nr, which overlapped with page->mapping in the
+ * first tail page, was not cleared, causing the error. To ensure that this
+ * issue does not reoccur as struct page keeps changing and some fields are
+ * managed by folio, this test checks that freeing gigantic hugepages does not
+ * produce the above-mentioned error.
+ */
+
+#define _GNU_SOURCE
+#include <dirent.h>
+
+#include <stdio.h>
+
+#include "hugetlb.h"
+
+#define PATH_HUGEPAGE "/sys/kernel/mm/hugepages"
+#define GIGANTIC_MIN_ORDER 10
+
+static int org_g_hpages;
+static char g_hpage_path[4096];
+
+static void run_test(void)
+{
+ if (FILE_PRINTF(g_hpage_path, "%d", 1))
+ tst_brk(TCONF, "Can't update the gigantic hugepages.");
+ SAFE_FILE_PRINTF(g_hpage_path, "%d", 0);
+
+ if (tst_taint_check())
+ tst_res(TFAIL, "Freeing Gigantic pages resulted in Bad Page State bug.");
+ else
+ tst_res(TPASS, "Successfully freed the gigantic hugepages");
+}
+
+static void setup(void)
+{
+ DIR *dir;
+ struct dirent *ent;
+ unsigned long hpage_size;
+
+ if (access(PATH_HUGEPAGE, F_OK))
+ tst_brk(TCONF, "hugetlbfs is not supported");
+
+ dir = SAFE_OPENDIR(PATH_HUGEPAGE);
+ while ((ent = SAFE_READDIR(dir))) {
+ if ((sscanf(ent->d_name, "hugepages-%lukB", &hpage_size) == 1) &&
+ is_hugetlb_gigantic(hpage_size * 1024)) {
+ sprintf(g_hpage_path, "%s/%s/%s", PATH_HUGEPAGE,
+ ent->d_name, "nr_hugepages");
+ break;
+ }
+ }
+ if (!g_hpage_path[0])
+ tst_brk(TCONF, "Gigantic hugepages not supported");
+
+ SAFE_CLOSEDIR(dir);
+
+ SAFE_FILE_PRINTF("/proc/sys/vm/drop_caches", "3");
+ SAFE_FILE_PRINTF("/proc/sys/vm/compact_memory", "1");
+
+ if (tst_available_mem() < (long long)hpage_size) {
+ g_hpage_path[0] = '\0';
+ tst_brk(TCONF, "No enough memory for gigantic hugepage reservation");
+ }
+
+ SAFE_FILE_LINES_SCANF(g_hpage_path, "%d", &org_g_hpages);
+}
+
+static void cleanup(void)
+{
+ if (g_hpage_path[0])
+ SAFE_FILE_PRINTF(g_hpage_path, "%d", org_g_hpages);
+}
+
+static struct tst_test test = {
+ .tags = (struct tst_tag[]) {
+ {"linux-git", "ba9c1201beaa"},
+ {"linux-git", "a01f43901cfb"},
+ {}
+ },
+ .needs_root = 1,
+ .setup = setup,
+ .cleanup = cleanup,
+ .test_all = run_test,
+ .taint_check = TST_TAINT_B,
+};
diff --git a/testcases/kernel/mem/hugetlb/hugeshmat/hugeshmat04.c b/testcases/kernel/mem/hugetlb/hugeshmat/hugeshmat04.c
index 50efa8a52..8ad745d5b 100644
--- a/testcases/kernel/mem/hugetlb/hugeshmat/hugeshmat04.c
+++ b/testcases/kernel/mem/hugetlb/hugeshmat/hugeshmat04.c
@@ -27,7 +27,6 @@
static long huge_free;
static long huge_free2;
-static long orig_shmmax = -1, new_shmmax;
static void shared_hugepage(void);
@@ -81,14 +80,13 @@ static void shared_hugepage(void)
static void setup(void)
{
long hpage_size, orig_hugepages;
+ unsigned long new_shmmax;
orig_hugepages = get_sys_tune("nr_hugepages");
- SAFE_FILE_SCANF(PATH_SHMMAX, "%ld", &orig_shmmax);
- SAFE_FILE_PRINTF(PATH_SHMMAX, "%ld", (long)SIZE);
- SAFE_FILE_SCANF(PATH_SHMMAX, "%ld", &new_shmmax);
+ SAFE_FILE_SCANF(PATH_SHMMAX, "%lu", &new_shmmax);
if (new_shmmax < SIZE)
- tst_brk(TCONF, "shmmax too low, have: %ld", new_shmmax);
+ tst_brk(TCONF, "shmmax too low, have: %lu", new_shmmax);
hpage_size = SAFE_READ_MEMINFO("Hugepagesize:") * 1024;
@@ -96,12 +94,6 @@ static void setup(void)
tst_reserve_hugepages(&hp);
}
-static void cleanup(void)
-{
- if (orig_shmmax != -1)
- SAFE_FILE_PRINTF(PATH_SHMMAX, "%ld", orig_shmmax);
-}
-
static struct tst_test test = {
.tags = (const struct tst_tag[]) {
{"linux-git", "c5c99429fa57"},
@@ -114,6 +106,9 @@ static struct tst_test test = {
.test = test_hugeshmat,
.min_mem_avail = 2048,
.setup = setup,
- .cleanup = cleanup,
.hugepages = {1, TST_NEEDS},
+ .save_restore = (const struct tst_path_val[]) {
+ {PATH_SHMMAX, "1073741824", TST_SR_TCONF_MISSING | TST_SR_TBROK_RO},
+ {}
+ },
};
diff --git a/testcases/kernel/mem/hugetlb/hugeshmctl/hugeshmctl01.c b/testcases/kernel/mem/hugetlb/hugeshmctl/hugeshmctl01.c
index 11cd69050..a68b0da75 100644
--- a/testcases/kernel/mem/hugetlb/hugeshmctl/hugeshmctl01.c
+++ b/testcases/kernel/mem/hugetlb/hugeshmctl/hugeshmctl01.c
@@ -53,10 +53,10 @@ static void func_set(void);
static void func_rmid(void);
static void *set_shmat(void);
-struct tcase {
+static struct tcase {
int cmd;
- void (*func_test) (void);
- void (*func_setup) (void);
+ void (*func_test)(void);
+ void (*func_setup)(void);
} tcases[] = {
{IPC_STAT, func_stat, stat_setup_1},
{IPC_STAT, func_stat, stat_setup_2},
@@ -90,7 +90,7 @@ static void test_hugeshmctl(unsigned int i)
/*
* set_shmat() - Attach the shared memory and return the pointer.
*/
-void *set_shmat(void)
+static void *set_shmat(void)
{
void *rval;
@@ -103,8 +103,8 @@ void *set_shmat(void)
/*
* stat_setup_2() - Set up for the IPC_STAT command with shmctl().
- * Attach the shared memory to parent process and
- * some children will inherit the shared memory.
+ * Attach the shared memory to parent process and
+ * some children will inherit the shared memory.
*/
static void stat_setup_2(void)
{
@@ -139,7 +139,7 @@ static void stat_setup_1(void)
/* now we're back - detach the memory and exit */
if (shmdt(test) == -1)
tst_brk(TBROK | TERRNO,
- "shmdt in stat_setup()");
+ "shmdt in this function broke");
exit(0);
default:
@@ -220,7 +220,8 @@ static void stat_cleanup(void)
/* remove the parent's shared memory if we set*/
if (attach_to_parent) {
if (shmdt(attach_to_parent) == -1)
- tst_res(TFAIL | TERRNO, "shmdt in stat_cleanup()");
+ tst_res(TFAIL | TERRNO,
+ "shmdt in this function failed");
attach_to_parent = NULL;
}
}
@@ -244,7 +245,7 @@ static void func_set(void)
{
/* first stat the shared memory to get the new data */
if (shmctl(shm_id_1, IPC_STAT, &buf) == -1) {
- tst_res(TFAIL | TERRNO, "shmctl in func_set()");
+ tst_res(TFAIL | TERRNO, "shmctl in this function failed");
return;
}
@@ -268,18 +269,18 @@ static void func_rmid(void)
{
/* Do another shmctl() - we should get EINVAL */
if (shmctl(shm_id_1, IPC_STAT, &buf) != -1)
- tst_brk(TBROK, "shmctl in func_rmid() "
+ tst_brk(TBROK, "shmctl in this function "
"succeeded unexpectedly");
if (errno != EINVAL)
- tst_res(TFAIL | TERRNO, "shmctl in func_rmid() failed "
+ tst_res(TFAIL | TERRNO, "shmctl in this function failed "
"unexpectedly - expect errno=EINVAL, got");
else
- tst_res(TPASS, "shmctl in func_rmid() failed as expected, "
+ tst_res(TPASS, "shmctl in this function failed as expected, "
"shared memory appears to be removed");
shm_id_1 = -1;
}
-void setup(void)
+static void setup(void)
{
long hpage_size;
@@ -293,7 +294,7 @@ void setup(void)
shmkey = getipckey();
}
-void cleanup(void)
+static void cleanup(void)
{
rm_shm(shm_id_1);
}
diff --git a/testcases/kernel/mem/hugetlb/hugeshmctl/hugeshmctl02.c b/testcases/kernel/mem/hugetlb/hugeshmctl/hugeshmctl02.c
index 0bc9ffd74..d3f711129 100644
--- a/testcases/kernel/mem/hugetlb/hugeshmctl/hugeshmctl02.c
+++ b/testcases/kernel/mem/hugetlb/hugeshmctl/hugeshmctl02.c
@@ -27,6 +27,7 @@
#include <pwd.h>
#include <limits.h>
#include "hugetlb.h"
+#include "lapi/syscalls.h"
static size_t shm_size;
static int shm_id_1 = -1;
@@ -34,7 +35,7 @@ static int shm_id_2 = -1;
static int shm_id_3 = -1;
static struct shmid_ds buf;
-struct tcase {
+static struct tcase {
int *shmid;
int cmd;
struct shmid_ds *sbuf;
@@ -50,9 +51,37 @@ struct tcase {
{&shm_id_2, -1, &buf, EINVAL},
};
+static int libc_shmctl(int shmid, int cmd, void *buf)
+{
+ return shmctl(shmid, cmd, buf);
+}
+
+static int sys_shmctl(int shmid, int cmd, void *buf)
+{
+ return tst_syscall(__NR_shmctl, shmid, cmd, buf);
+}
+
+static struct test_variants
+{
+ int (*shmctl)(int shmid, int cmd, void *buf);
+ char *desc;
+} variants[] = {
+ { .shmctl = libc_shmctl, .desc = "libc shmctl()"},
+#if (__NR_shmctl != __LTP__NR_INVALID_SYSCALL)
+ { .shmctl = sys_shmctl, .desc = "__NR_shmctl syscall"},
+#endif
+};
+
static void test_hugeshmctl(unsigned int i)
{
- TEST(shmctl(*(tcases[i].shmid), tcases[i].cmd, tcases[i].sbuf));
+ struct test_variants *tv = &variants[tst_variant];
+
+ if (tcases[i].error == EFAULT && tv->shmctl == libc_shmctl) {
+ tst_res(TCONF, "EFAULT is skipped for libc variant");
+ return;
+ }
+
+ TEST(tv->shmctl(*(tcases[i].shmid), tcases[i].cmd, tcases[i].sbuf));
if (TST_RET != -1) {
tst_res(TFAIL, "shmctl succeeded unexpectedly");
return;
@@ -70,8 +99,11 @@ static void test_hugeshmctl(unsigned int i)
static void setup(void)
{
+ struct test_variants *tv = &variants[tst_variant];
long hpage_size;
+ tst_res(TINFO, "Testing variant: %s", tv->desc);
+
if (tst_hugepages == 0)
tst_brk(TCONF, "No enough hugepages for testing.");
@@ -101,6 +133,7 @@ static void cleanup(void)
static struct tst_test test = {
.test = test_hugeshmctl,
+ .test_variants = ARRAY_SIZE(variants),
.tcnt = ARRAY_SIZE(tcases),
.needs_root = 1,
.needs_tmpdir = 1,
diff --git a/testcases/kernel/mem/hugetlb/hugeshmctl/hugeshmctl03.c b/testcases/kernel/mem/hugetlb/hugeshmctl/hugeshmctl03.c
index 21ec6bf78..ec4640686 100644
--- a/testcases/kernel/mem/hugetlb/hugeshmctl/hugeshmctl03.c
+++ b/testcases/kernel/mem/hugetlb/hugeshmctl/hugeshmctl03.c
@@ -41,10 +41,10 @@
static size_t shm_size;
static int shm_id_1 = -1;
static struct shmid_ds buf;
-static uid_t ltp_uid;
-static char *ltp_user = "nobody";
+static uid_t test_uid;
+static char *test_user = "nobody";
-struct tcase {
+static struct tcase {
int *shmid;
int cmd;
struct shmid_ds *sbuf;
@@ -68,7 +68,7 @@ static void test_hugeshmctl(void)
switch (pid = SAFE_FORK()) {
case 0:
/* set the user ID of the child to the non root user */
- SAFE_SETUID(ltp_uid);
+ SAFE_SETUID(test_uid);
do_child();
exit(0);
default:
@@ -97,7 +97,7 @@ static void do_child(void)
}
}
-void setup(void)
+static void setup(void)
{
long hpage_size;
@@ -115,10 +115,10 @@ void setup(void)
tst_brk(TBROK | TERRNO, "shmget");
/* get the userid for a non root user */
- ltp_uid = getuserid(ltp_user);
+ test_uid = getuserid(test_user);
}
-void cleanup(void)
+static void cleanup(void)
{
rm_shm(shm_id_1);
}
diff --git a/testcases/kernel/mem/hugetlb/hugeshmget/hugeshmget03.c b/testcases/kernel/mem/hugetlb/hugeshmget/hugeshmget03.c
index 7e72a19ca..625761f6e 100644
--- a/testcases/kernel/mem/hugetlb/hugeshmget/hugeshmget03.c
+++ b/testcases/kernel/mem/hugetlb/hugeshmget/hugeshmget03.c
@@ -84,7 +84,7 @@ static void cleanup(void)
rm_shm(shm_id_arr[i]);
if (orig_shmmni != -1)
- FILE_PRINTF(PATH_SHMMNI, "%ld", orig_shmmni);
+ SAFE_FILE_PRINTF(PATH_SHMMNI, "%ld", orig_shmmni);
}
static struct tst_test test = {
diff --git a/testcases/kernel/mem/hugetlb/lib/hugetlb.h b/testcases/kernel/mem/hugetlb/lib/hugetlb.h
index 241dab708..34fe08c24 100644
--- a/testcases/kernel/mem/hugetlb/lib/hugetlb.h
+++ b/testcases/kernel/mem/hugetlb/lib/hugetlb.h
@@ -39,6 +39,12 @@
# endif
#endif
+/* Check if hugetlb page is gigantic */
+static inline int is_hugetlb_gigantic(unsigned long hpage_size)
+{
+ return (hpage_size / getpagesize()) >> 11;
+}
+
/*
* to get the lower nine permission bits
* from shmid_ds.ipc_perm.mode
diff --git a/testcases/kernel/mem/include/mem.h b/testcases/kernel/mem/include/mem.h
index 776809113..cdc3ca146 100644
--- a/testcases/kernel/mem/include/mem.h
+++ b/testcases/kernel/mem/include/mem.h
@@ -42,7 +42,6 @@ static inline void clean_node(unsigned long *array)
#define MLOCK 2
#define KSM 3
-extern long overcommit;
void oom(int testcase, int lite, int retcode, int allow_sigkill);
void testoom(int mempolicy, int lite, int retcode, int allow_sigkill);
diff --git a/testcases/kernel/mem/ksm/ksm05.c b/testcases/kernel/mem/ksm/ksm05.c
index 25f3435b2..1f58c8325 100644
--- a/testcases/kernel/mem/ksm/ksm05.c
+++ b/testcases/kernel/mem/ksm/ksm05.c
@@ -95,6 +95,10 @@ static struct tst_test test = {
"CONFIG_KSM=y",
NULL
},
+ .tags = (const struct tst_tag[]) {
+ {"CVE", "2011-2183"},
+ {}
+ }
};
#else
diff --git a/testcases/kernel/mem/lib/mem.c b/testcases/kernel/mem/lib/mem.c
index 8ddd7adf7..fbfeef026 100644
--- a/testcases/kernel/mem/lib/mem.c
+++ b/testcases/kernel/mem/lib/mem.c
@@ -27,8 +27,6 @@
/* OOM */
-long overcommit = -1;
-
static int alloc_mem(long int length, int testcase)
{
char *s;
diff --git a/testcases/kernel/mem/oom/oom01.c b/testcases/kernel/mem/oom/oom01.c
index 9f7d76587..b13699898 100644
--- a/testcases/kernel/mem/oom/oom01.c
+++ b/testcases/kernel/mem/oom/oom01.c
@@ -49,22 +49,13 @@ static void verify_oom(void)
testoom(0, 0, ENOMEM, 1);
}
-static void setup(void)
-{
- overcommit = get_sys_tune("overcommit_memory");
-}
-
-static void cleanup(void)
-{
- if (overcommit != -1)
- set_sys_tune("overcommit_memory", overcommit, 0);
-}
-
static struct tst_test test = {
.needs_root = 1,
.forks_child = 1,
.max_runtime = TST_UNLIMITED_RUNTIME,
- .setup = setup,
- .cleanup = cleanup,
.test_all = verify_oom,
+ .save_restore = (const struct tst_path_val[]) {
+ {"/proc/sys/vm/overcommit_memory", NULL, TST_SR_TBROK},
+ {}
+ },
};
diff --git a/testcases/kernel/mem/oom/oom02.c b/testcases/kernel/mem/oom/oom02.c
index b3719f723..8d565d12a 100644
--- a/testcases/kernel/mem/oom/oom02.c
+++ b/testcases/kernel/mem/oom/oom02.c
@@ -56,15 +56,6 @@ static void setup(void)
{
if (!is_numa(NULL, NH_MEMS, 2))
tst_brk(TCONF, "The case need a NUMA system.");
-
- overcommit = get_sys_tune("overcommit_memory");
- set_sys_tune("overcommit_memory", 1, 1);
-}
-
-static void cleanup(void)
-{
- if (overcommit != -1)
- set_sys_tune("overcommit_memory", overcommit, 0);
}
static struct tst_test test = {
@@ -72,8 +63,11 @@ static struct tst_test test = {
.forks_child = 1,
.max_runtime = TST_UNLIMITED_RUNTIME,
.setup = setup,
- .cleanup = cleanup,
.test_all = verify_oom,
+ .save_restore = (const struct tst_path_val[]) {
+ {"/proc/sys/vm/overcommit_memory", "1", TST_SR_TBROK},
+ {}
+ },
};
#else
diff --git a/testcases/kernel/mem/oom/oom03.c b/testcases/kernel/mem/oom/oom03.c
index 0882c9bbe..778055d03 100644
--- a/testcases/kernel/mem/oom/oom03.c
+++ b/testcases/kernel/mem/oom/oom03.c
@@ -79,27 +79,21 @@ static void verify_oom(void)
static void setup(void)
{
- overcommit = get_sys_tune("overcommit_memory");
- set_sys_tune("overcommit_memory", 1, 1);
-
SAFE_CG_PRINTF(tst_cg, "cgroup.procs", "%d", getpid());
SAFE_CG_PRINTF(tst_cg, "memory.max", "%lu", TESTMEM);
}
-static void cleanup(void)
-{
- if (overcommit != -1)
- set_sys_tune("overcommit_memory", overcommit, 0);
-}
-
static struct tst_test test = {
.needs_root = 1,
.forks_child = 1,
.max_runtime = TST_UNLIMITED_RUNTIME,
.setup = setup,
- .cleanup = cleanup,
.test_all = verify_oom,
.needs_cgroup_ctrls = (const char *const []){ "memory", NULL },
+ .save_restore = (const struct tst_path_val[]) {
+ {"/proc/sys/vm/overcommit_memory", "1", TST_SR_TBROK},
+ {}
+ },
};
#else
diff --git a/testcases/kernel/mem/oom/oom04.c b/testcases/kernel/mem/oom/oom04.c
index ad39f7e77..d27d9d9e7 100644
--- a/testcases/kernel/mem/oom/oom04.c
+++ b/testcases/kernel/mem/oom/oom04.c
@@ -65,9 +65,6 @@ static void setup(void)
if (!is_numa(NULL, NH_MEMS, 1))
tst_brk(TCONF, "requires NUMA with at least 1 node");
- overcommit = get_sys_tune("overcommit_memory");
- set_sys_tune("overcommit_memory", 1, 1);
-
/*
* Some nodes do not contain memory, so use
* get_allowed_nodes(NH_MEMS) to get a memory
@@ -82,20 +79,17 @@ static void setup(void)
SAFE_CG_PRINTF(tst_cg, "cgroup.procs", "%d", getpid());
}
-static void cleanup(void)
-{
- if (overcommit != -1)
- set_sys_tune("overcommit_memory", overcommit, 0);
-}
-
static struct tst_test test = {
.needs_root = 1,
.forks_child = 1,
.max_runtime = TST_UNLIMITED_RUNTIME,
.setup = setup,
- .cleanup = cleanup,
.test_all = verify_oom,
.needs_cgroup_ctrls = (const char *const []){ "cpuset", NULL },
+ .save_restore = (const struct tst_path_val[]) {
+ {"/proc/sys/vm/overcommit_memory", "1", TST_SR_TBROK},
+ {}
+ },
};
#else
diff --git a/testcases/kernel/mem/oom/oom05.c b/testcases/kernel/mem/oom/oom05.c
index e31146e7a..eb1a64267 100644
--- a/testcases/kernel/mem/oom/oom05.c
+++ b/testcases/kernel/mem/oom/oom05.c
@@ -85,9 +85,6 @@ void setup(void)
if (!is_numa(NULL, NH_MEMS, 1))
tst_brk(TCONF, "requires NUMA with at least 1 node");
- overcommit = get_sys_tune("overcommit_memory");
- set_sys_tune("overcommit_memory", 1, 1);
-
/*
* Some nodes do not contain memory, so use
* get_allowed_nodes(NH_MEMS) to get a memory
@@ -104,22 +101,19 @@ void setup(void)
SAFE_CG_PRINTF(tst_cg, "memory.max", "%lu", TESTMEM);
}
-void cleanup(void)
-{
- if (overcommit != -1)
- set_sys_tune("overcommit_memory", overcommit, 0);
-}
-
static struct tst_test test = {
.needs_root = 1,
.forks_child = 1,
.max_runtime = TST_UNLIMITED_RUNTIME,
.setup = setup,
- .cleanup = cleanup,
.test_all = verify_oom,
.needs_cgroup_ctrls = (const char *const []){
"memory", "cpuset", NULL
},
+ .save_restore = (const struct tst_path_val[]) {
+ {"/proc/sys/vm/overcommit_memory", "1", TST_SR_TBROK},
+ {}
+ },
};
#else
diff --git a/testcases/kernel/mem/thp/thp03.c b/testcases/kernel/mem/thp/thp03.c
index c6062505f..839efcb0e 100644
--- a/testcases/kernel/mem/thp/thp03.c
+++ b/testcases/kernel/mem/thp/thp03.c
@@ -30,7 +30,6 @@
* corruption and no data corruption (nor userland nor kernel).
*/
-#include <sys/mman.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>
diff --git a/testcases/kernel/mem/thp/thp04.c b/testcases/kernel/mem/thp/thp04.c
index 7cab5d76b..b5f518ac5 100644
--- a/testcases/kernel/mem/thp/thp04.c
+++ b/testcases/kernel/mem/thp/thp04.c
@@ -26,8 +26,6 @@
* commit 8310d48b125d("huge_memory.c: respect FOLL_FORCE/FOLL_COW for thp").
*/
-#include <sys/mman.h>
-
#include "tst_test.h"
#include "lapi/mmap.h"
#include "tst_fuzzy_sync.h"
diff --git a/testcases/kernel/mem/tunable/max_map_count.c b/testcases/kernel/mem/tunable/max_map_count.c
index caf8972e0..f33095473 100644
--- a/testcases/kernel/mem/tunable/max_map_count.c
+++ b/testcases/kernel/mem/tunable/max_map_count.c
@@ -53,26 +53,6 @@
#define MAP_COUNT_DEFAULT 1024
#define MAX_MAP_COUNT 65536L
-static long old_max_map_count = -1;
-static long old_overcommit = -1;
-
-static void setup(void)
-{
- SAFE_ACCESS(PATH_SYSVM "max_map_count", F_OK);
-
- old_max_map_count = get_sys_tune("max_map_count");
- old_overcommit = get_sys_tune("overcommit_memory");
- set_sys_tune("overcommit_memory", 0, 1);
-}
-
-static void cleanup(void)
-{
- if (old_overcommit != -1)
- set_sys_tune("overcommit_memory", old_overcommit, 0);
- if (old_max_map_count != -1)
- set_sys_tune("max_map_count", old_max_map_count, 0);
-}
-
/* This is a filter to exclude map entries which aren't accounted
* for in the vm_area_struct's map_count.
*/
@@ -210,7 +190,10 @@ static void max_map_count_test(void)
static struct tst_test test = {
.needs_root = 1,
.forks_child = 1,
- .setup = setup,
- .cleanup = cleanup,
.test_all = max_map_count_test,
+ .save_restore = (const struct tst_path_val[]) {
+ {"/proc/sys/vm/overcommit_memory", "0", TST_SR_TBROK},
+ {"/proc/sys/vm/max_map_count", NULL, TST_SR_TBROK},
+ {}
+ },
};
diff --git a/testcases/kernel/mem/tunable/min_free_kbytes.c b/testcases/kernel/mem/tunable/min_free_kbytes.c
index eab6c8b2e..19da409e8 100644
--- a/testcases/kernel/mem/tunable/min_free_kbytes.c
+++ b/testcases/kernel/mem/tunable/min_free_kbytes.c
@@ -41,7 +41,6 @@
volatile int end;
static long default_tune = -1;
-static long orig_overcommit = -1;
static unsigned long total_mem;
static void test_tune(unsigned long overcommit_policy);
@@ -217,15 +216,6 @@ static void setup(void)
total_mem = SAFE_READ_MEMINFO("MemTotal:") + SAFE_READ_MEMINFO("SwapTotal:");
default_tune = get_sys_tune("min_free_kbytes");
- orig_overcommit = get_sys_tune("overcommit_memory");
-}
-
-static void cleanup(void)
-{
- if (default_tune != -1)
- set_sys_tune("min_free_kbytes", default_tune, 0);
- if (orig_overcommit != -1)
- set_sys_tune("overcommit_memory", orig_overcommit, 0);
}
static struct tst_test test = {
@@ -233,6 +223,10 @@ static struct tst_test test = {
.forks_child = 1,
.max_runtime = TST_UNLIMITED_RUNTIME,
.setup = setup,
- .cleanup = cleanup,
.test_all = min_free_kbytes_test,
+ .save_restore = (const struct tst_path_val[]) {
+ {"/proc/sys/vm/overcommit_memory", NULL, TST_SR_TBROK},
+ {"/proc/sys/vm/min_free_kbytes", NULL, TST_SR_TBROK},
+ {}
+ },
};
diff --git a/testcases/kernel/mem/tunable/overcommit_memory.c b/testcases/kernel/mem/tunable/overcommit_memory.c
index 7fe8fe14c..ffb7a6d9d 100644
--- a/testcases/kernel/mem/tunable/overcommit_memory.c
+++ b/testcases/kernel/mem/tunable/overcommit_memory.c
@@ -70,7 +70,6 @@
#define EXPECT_FAIL 1
static char *R_opt;
-static long old_overcommit_memory = -1;
static long old_overcommit_ratio = -1;
static long overcommit_ratio;
static long sum_total;
@@ -90,16 +89,11 @@ static void setup(void)
long mem_total, swap_total;
struct rlimit lim;
- if (access(PATH_SYSVM "overcommit_memory", F_OK) == -1 ||
- access(PATH_SYSVM "overcommit_ratio", F_OK) == -1)
- tst_brk(TCONF, "system doesn't support overcommit_memory");
-
if (R_opt)
overcommit_ratio = SAFE_STRTOL(R_opt, 0, LONG_MAX);
else
overcommit_ratio = DEFAULT_OVER_RATIO;
- old_overcommit_memory = get_sys_tune("overcommit_memory");
old_overcommit_ratio = get_sys_tune("overcommit_ratio");
mem_total = SAFE_READ_MEMINFO("MemTotal:");
@@ -128,14 +122,6 @@ static void setup(void)
tst_res(TINFO, "TotalBatchSize is %ld kB", total_batch_size);
}
-static void cleanup(void)
-{
- if (old_overcommit_memory != -1)
- set_sys_tune("overcommit_memory", old_overcommit_memory, 0);
- if (old_overcommit_ratio != -1)
- set_sys_tune("overcommit_ratio", old_overcommit_ratio, 0);
-}
-
static void overcommit_memory_test(void)
{
@@ -269,6 +255,10 @@ static struct tst_test test = {
{}
},
.setup = setup,
- .cleanup = cleanup,
.test_all = overcommit_memory_test,
+ .save_restore = (const struct tst_path_val[]) {
+ {"/proc/sys/vm/overcommit_memory", NULL, TST_SR_TBROK},
+ {"/proc/sys/vm/overcommit_ratio", NULL, TST_SR_TBROK},
+ {}
+ },
};
diff --git a/testcases/kernel/mem/vma/vma05.sh b/testcases/kernel/mem/vma/vma05.sh
index 9ef6f0a23..c9e4becdb 100755
--- a/testcases/kernel/mem/vma/vma05.sh
+++ b/testcases/kernel/mem/vma/vma05.sh
@@ -30,6 +30,7 @@ setup()
{
ulimit -c unlimited
echo "core" > /proc/sys/kernel/core_pattern
+ unset DEBUGINFOD_URLS
}
cleanup()
diff --git a/testcases/kernel/numa/numa01.sh b/testcases/kernel/numa/numa01.sh
index 367813ce9..0181cd8f5 100755
--- a/testcases/kernel/numa/numa01.sh
+++ b/testcases/kernel/numa/numa01.sh
@@ -183,7 +183,7 @@ test4()
no_of_cpus=$(tst_ncpus)
# not sure whether cpu's can't be in odd number
run_on_cpu=$(($((no_of_cpus+1))/2))
- numactl --physcpubind=$run_on_cpu support_numa pause & #just waits for sigint
+ numactl --all --physcpubind=$run_on_cpu support_numa pause & #just waits for sigint
pid=$!
var=`awk '{ print $2 }' /proc/$pid/stat`
while [ $var = '(numactl)' ]; do
diff --git a/testcases/kernel/numa/support_numa.c b/testcases/kernel/numa/support_numa.c
index a0afee554..6fb82f374 100644
--- a/testcases/kernel/numa/support_numa.c
+++ b/testcases/kernel/numa/support_numa.c
@@ -37,7 +37,6 @@
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
-#include <sys/mman.h>
#include <fcntl.h>
#include "lapi/mmap.h"
diff --git a/testcases/kernel/sched/cfs-scheduler/.gitignore b/testcases/kernel/sched/cfs-scheduler/.gitignore
index c5dacd6ef..3ea3f75fc 100644
--- a/testcases/kernel/sched/cfs-scheduler/.gitignore
+++ b/testcases/kernel/sched/cfs-scheduler/.gitignore
@@ -1,2 +1,3 @@
/hackbench
-cfs_bandwidth01
+/cfs_bandwidth01
+/starvation
diff --git a/testcases/kernel/sched/cfs-scheduler/cfs_bandwidth01.c b/testcases/kernel/sched/cfs-scheduler/cfs_bandwidth01.c
index 8f2da4493..27fc0fc5d 100644
--- a/testcases/kernel/sched/cfs-scheduler/cfs_bandwidth01.c
+++ b/testcases/kernel/sched/cfs-scheduler/cfs_bandwidth01.c
@@ -1,7 +1,10 @@
// SPDX-License-Identifier: GPL-2.0-or-later
-/* Copyright (c) 2021 SUSE LLC <rpalethorpe@suse.com> */
+/*
+ * Copyright (c) 2021 SUSE LLC <rpalethorpe@suse.com>
+ * Copyright (c) Linux Test Project, 2021-2023
+ */
+
/*\
- *
* [Description]
*
* Creates a multi-level CGroup hierarchy with the cpu controller
@@ -15,7 +18,8 @@
* them to be unthrottle.
*
* The test is known to reproduce an issue with an update to
- * SLE-15-SP1 (kernel 4.12.14-197.64, bsc#1179093).
+ * SLE-15-SP1 (kernel 4.12.14-197.64,
+ * https://bugzilla.suse.com/show_bug.cgi?id=1179093).
*
* Also as an reproducer for another bug:
*
diff --git a/testcases/kernel/sched/cfs-scheduler/starvation.c b/testcases/kernel/sched/cfs-scheduler/starvation.c
new file mode 100644
index 000000000..eb9fd6ff5
--- /dev/null
+++ b/testcases/kernel/sched/cfs-scheduler/starvation.c
@@ -0,0 +1,113 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/* Copyright 2023 Mike Galbraith <efault-AT-gmx.de> */
+/* Copyright 2023 Wei Gao <wegao@suse.com> */
+/*\
+ *
+ * [Description]
+ *
+ * Thread starvation test. On fauluty kernel the test timeouts.
+ *
+ * Original reproducer taken from:
+ * https://lore.kernel.org/lkml/9fd2c37a05713c206dcbd5866f67ce779f315e9e.camel@gmx.de/
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <signal.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+#include <sched.h>
+
+#include "tst_test.h"
+
+static char *str_loop;
+static long loop = 2000000;
+static char *str_timeout;
+static int timeout = 240;
+
+static int wait_for_pid(pid_t pid)
+{
+ int status, ret;
+
+again:
+ ret = waitpid(pid, &status, 0);
+ if (ret == -1) {
+ if (errno == EINTR)
+ goto again;
+
+ return -1;
+ }
+
+ if (WIFSIGNALED(status))
+ return 0;
+
+ return -1;
+}
+
+static void setup(void)
+{
+ cpu_set_t mask;
+
+ CPU_ZERO(&mask);
+
+ CPU_SET(0, &mask);
+
+ TST_EXP_POSITIVE(sched_setaffinity(0, sizeof(mask), &mask));
+
+ if (tst_parse_long(str_loop, &loop, 1, LONG_MAX))
+ tst_brk(TBROK, "Invalid number of loop number '%s'", str_loop);
+
+ if (tst_parse_int(str_timeout, &timeout, 1, INT_MAX))
+ tst_brk(TBROK, "Invalid number of timeout '%s'", str_timeout);
+
+ tst_set_max_runtime(timeout);
+}
+
+static void handler(int sig LTP_ATTRIBUTE_UNUSED)
+{
+ if (loop > 0)
+ --loop;
+}
+
+static void child(void)
+{
+ pid_t ppid = getppid();
+
+ TST_CHECKPOINT_WAIT(0);
+
+ while (1)
+ SAFE_KILL(ppid, SIGUSR1);
+}
+
+static void do_test(void)
+{
+ pid_t child_pid;
+
+ child_pid = SAFE_FORK();
+
+ if (!child_pid)
+ child();
+
+ SAFE_SIGNAL(SIGUSR1, handler);
+ TST_CHECKPOINT_WAKE(0);
+
+ while (loop)
+ sleep(1);
+
+ SAFE_KILL(child_pid, SIGTERM);
+ TST_EXP_PASS(wait_for_pid(child_pid));
+}
+
+static struct tst_test test = {
+ .test_all = do_test,
+ .setup = setup,
+ .forks_child = 1,
+ .options = (struct tst_option[]) {
+ {"l:", &str_loop, "Number of loops (default 2000000)"},
+ {"t:", &str_timeout, "Max timeout (default 240s)"},
+ {}
+ },
+ .needs_checkpoints = 1,
+};
diff --git a/testcases/kernel/security/dirtyc0w_shmem/dirtyc0w_shmem_child.c b/testcases/kernel/security/dirtyc0w_shmem/dirtyc0w_shmem_child.c
index 9c2b03994..2a982347c 100644
--- a/testcases/kernel/security/dirtyc0w_shmem/dirtyc0w_shmem_child.c
+++ b/testcases/kernel/security/dirtyc0w_shmem/dirtyc0w_shmem_child.c
@@ -115,7 +115,7 @@ static void *uffd_thread_fn(void *arg)
if (ioctl(uffd, UFFDIO_CONTINUE, &uffdio) < 0) {
if (errno == EEXIST) {
uffdio_wake.start = (unsigned long) map;
- uffdio_wake.len = 4096;
+ uffdio_wake.len = page_size;
SAFE_IOCTL(uffd, UFFDIO_WAKE, &uffdio_wake);
}
}
diff --git a/testcases/kernel/security/tomoyo/.gitignore b/testcases/kernel/security/tomoyo/.gitignore
deleted file mode 100644
index 698646d93..000000000
--- a/testcases/kernel/security/tomoyo/.gitignore
+++ /dev/null
@@ -1,9 +0,0 @@
-/newns
-/tomoyo_accept_test
-/tomoyo_file_test
-/tomoyo_filesystem_test
-/tomoyo_new_file_test
-/tomoyo_new_test
-/tomoyo_policy_io_test
-/tomoyo_policy_memory_test
-/tomoyo_rewrite_test
diff --git a/testcases/kernel/security/tomoyo/Makefile b/testcases/kernel/security/tomoyo/Makefile
deleted file mode 100644
index 00e4cc3ed..000000000
--- a/testcases/kernel/security/tomoyo/Makefile
+++ /dev/null
@@ -1,29 +0,0 @@
-#
-# kernel/security/smack testcase Makefile
-#
-# Copyright (C) 2009, Cisco Systems Inc.
-#
-# 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.
-#
-# Ngie Cooper, July 2009
-#
-
-top_srcdir ?= ../../../..
-
-include $(top_srcdir)/include/mk/testcases.mk
-
-INSTALL_TARGETS := testall.sh
-
-include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/security/tomoyo/README b/testcases/kernel/security/tomoyo/README
deleted file mode 100644
index 0cb538868..000000000
--- a/testcases/kernel/security/tomoyo/README
+++ /dev/null
@@ -1,58 +0,0 @@
-Always look here for latest version of these tests:
-http://sourceforge.jp/projects/tomoyo/svn/view/trunk/2.3.x/tomoyo-tools/kernel_test/?root=tomoyo
-
-These testcases test the TOMOYO Security Module. And they are not part of
-default LTP build/install/run.
-
-A kernel with TOMOYO configured is required to run the TOMOYO testsuite.
-The securityfs filesystem must be mounted at /sys/kernel/security .
-
-Preparation steps are:
-
-1) Download tomoyo-tools package and extract and build and install.
-
- # wget -O tomoyo-tools.tar.gz 'http://sourceforge.jp/projects/tomoyo/svn/view/trunk/2.3.x/tomoyo-tools.tar.gz?root=tomoyo&view=tar'
- # tar -zxf tomoyo-tools.tar.gz
- # make -C tomoyo-tools/ install
-
- Programs are installed in /usr/sbin/ with prefix "tomoyo-" and
- /usr/lib/tomoyo/ directory without prefix "tomoyo-".
-
- You can make a RPM package by "rpmbuild -bb tomoyo-tools/tomoyo-tools.spec" and
- a DEB package by "alien -k" after "rpmbuild -bb".
-
-2) Run /usr/lib/tomoyo/init_policy .
-
- This will take several minutes.
-
- Hiding kernel source directory by "mount -t tmpfs none /usr/src/linux/"
- would save some time.
-
- Configuration files are saved in /etc/tomoyo/ directory.
- You can do "rm -fR /etc/tomoyo/" if you want to uninstall.
-
-3) Reboot the system with TOMOYO enabled kernel.
-
- To make sure TOMOYO is selected, you can add security=tomoyo to kernel's
- command line.
-
-4) Build the tests.
-
- # (extract the tar ball containing the tests.)
- # make autotools
- # ./configure
- # cd testcases/kernel/security/tomoyo/
- # make
- # find `/bin/pwd` -type f -perm +100 >> /etc/tomoyo/manager.conf
- # /usr/sbin/tomoyo-loadpolicy m
-
-Test steps are:
-
-1) Run the tests from the directory you ran "make".
-
- # ./testall.sh
-
- Please don't run the tests inside /tmp/ directory, for /tmp/ directory is
- hidden by "newns" (a wrapper program to run the test in a new namespace).
-
- You can use "| grep -vF OK" to pick up only failed tests as testall.sh does.
diff --git a/testcases/kernel/security/tomoyo/include.h b/testcases/kernel/security/tomoyo/include.h
deleted file mode 100644
index edaf1170f..000000000
--- a/testcases/kernel/security/tomoyo/include.h
+++ /dev/null
@@ -1,379 +0,0 @@
-/******************************************************************************/
-/* */
-/* Copyright (c) Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>, 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 */
-/* */
-/******************************************************************************/
-/*
- * include.h
- *
- * Common functions for testing TOMOYO Linux's kernel.
- *
- * Copyright (C) 2005-2010 NTT DATA CORPORATION
- */
-#include <errno.h>
-#include <fcntl.h>
-#include <linux/kdev_t.h>
-#include <linux/unistd.h>
-#include <pty.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <sys/syscall.h>
-#include <sys/time.h>
-#include <sys/timex.h>
-#include <sys/types.h>
-#include <sys/un.h>
-#include <sys/wait.h>
-#include <time.h>
-#include <unistd.h>
-#include <utime.h>
-#include <sched.h>
-#include <stdarg.h>
-#include <sys/mount.h>
-#include <arpa/inet.h>
-#include <net/if.h>
-#include <linux/ip.h>
-#include <err.h>
-#include "test.h"
-
-/*
- * Some architectures like mips n32 don't have __NR_uselib defined in the
- * system headers.
- */
-#ifdef __NR_uselib
-static inline int uselib(const char *library)
-{
- return syscall(__NR_uselib, library);
-}
-#else
-static inline int uselib(const char *library)
-{
- errno = ENOSYS;
- return -1;
-}
-#endif
-
-/* Is there an architecture without __NR_pivot_root defined? */
-#ifdef __NR_pivot_root
-static inline int pivot_root(const char *new_root, const char *put_old)
-{
- return syscall(__NR_pivot_root, new_root, put_old);
-}
-#else
-static inline int pivot_root(const char *new_root, const char *put_old)
-{
- errno = ENOSYS;
- return -1;
-}
-#endif
-
-/* The sysctl() wrapper is dead and newer arches omit it now. */
-static inline int write_sysctl(const char *path, const char *value)
-{
- FILE *fp = fopen(path, "w");
- if (!fp)
- return 1;
- fputs(value, fp);
- fclose(fp);
- return 0;
-}
-
-static inline int read_sysctl(const char *path, char *value, int len)
-{
- char scratch[100];
- FILE *fp = fopen(path, "r");
- if (!fp)
- return 1;
- if (!value) {
- value = scratch;
- len = sizeof(scratch);
- }
- if (fgets(value, len, fp))
- /* ignore */;
- fclose(fp);
- return 0;
-}
-
-/* Should be a fairly benign path to bang on. */
-#define TEST_SYSCTL_PATH "/proc/sys/net/ipv4/ip_local_port_range"
-
-#define proc_policy_dir "/sys/kernel/security/tomoyo/"
-#define proc_policy_domain_policy "/sys/kernel/security/tomoyo/domain_policy"
-#define proc_policy_exception_policy "/sys/kernel/security/tomoyo/exception_policy"
-#define proc_policy_profile "/sys/kernel/security/tomoyo/profile"
-#define proc_policy_manager "/sys/kernel/security/tomoyo/manager"
-#define proc_policy_query "/sys/kernel/security/tomoyo/query"
-#define proc_policy_grant_log "/sys/kernel/security/tomoyo/grant_log"
-#define proc_policy_reject_log "/sys/kernel/security/tomoyo/reject_log"
-#define proc_policy_domain_status "/sys/kernel/security/tomoyo/.domain_status"
-#define proc_policy_process_status "/sys/kernel/security/tomoyo/.process_status"
-#define proc_policy_self_domain "/sys/kernel/security/tomoyo/self_domain"
-
-static FILE *profile_fp = NULL;
-static FILE *domain_fp = NULL;
-static FILE *exception_fp = NULL;
-static char self_domain[4096] = "";
-static pid_t pid = 0;
-
-static void clear_status(void)
-{
- static const char *keywords[] = {
- "file::execute",
- "file::open",
- "file::create",
- "file::unlink",
- "file::mkdir",
- "file::rmdir",
- "file::mkfifo",
- "file::mksock",
- "file::truncate",
- "file::symlink",
- "file::rewrite",
- "file::mkblock",
- "file::mkchar",
- "file::link",
- "file::rename",
- "file::chmod",
- "file::chown",
- "file::chgrp",
- "file::ioctl",
- "file::chroot",
- "file::mount",
- "file::umount",
- "file::pivot_root",
- NULL
- };
- int i;
- FILE *fp = fopen(proc_policy_profile, "r");
- static char buffer[4096];
- if (!fp) {
- fprintf(stderr, "Can't open %s\n", proc_policy_profile);
- exit(1);
- }
- for (i = 0; keywords[i]; i++)
- fprintf(profile_fp,
- "255-CONFIG::%s={ mode=disabled }\n",
- keywords[i]);
- while (memset(buffer, 0, sizeof(buffer)),
- fgets(buffer, sizeof(buffer) - 10, fp)) {
- const char *mode;
- char *cp = strchr(buffer, '=');
- if (!cp)
- continue;
- *cp = '\0';
- mode = cp + 1;
- cp = strchr(buffer, '-');
- if (!cp)
- continue;
- *cp++ = '\0';
- if (strcmp(buffer, "0"))
- continue;
- fprintf(profile_fp, "255-%s", cp);
- if (!strcmp(cp, "COMMENT"))
- mode = "Profile for kernel test\n";
- else
- mode = "{ mode=disabled verbose=no }\n";
- fprintf(profile_fp, "255-%s=%s", cp, mode);
- }
- fprintf(profile_fp, "255-PREFERENCE::learning= verbose=no\n");
- fprintf(profile_fp, "255-PREFERENCE::enforcing= verbose=no\n");
- fprintf(profile_fp, "255-PREFERENCE::permissive= verbose=no\n");
- fprintf(profile_fp, "255-PREFERENCE::disabled= verbose=no\n");
- fprintf(profile_fp, "255-PREFERENCE::learning= max_entry=2048\n");
- fflush(profile_fp);
- fclose(fp);
-}
-
-static void tomoyo_test_init(void)
-{
- pid = getpid();
- if (access(proc_policy_dir, F_OK)) {
- fprintf(stderr, "You can't use this program for this kernel."
- "\n");
- exit(1);
- }
- profile_fp = fopen(proc_policy_profile, "w");
- if (!profile_fp) {
- fprintf(stderr, "Can't open %s .\n", proc_policy_profile);
- exit(1);
- }
- setlinebuf(profile_fp);
- domain_fp = fopen(proc_policy_domain_policy, "w");
- if (!domain_fp) {
- fprintf(stderr, "Can't open %s .\n",
- proc_policy_domain_policy);
- exit(1);
- }
- setlinebuf(domain_fp);
- exception_fp = fopen(proc_policy_exception_policy, "w");
- if (!exception_fp) {
- fprintf(stderr, "Can't open %s .\n",
- proc_policy_exception_policy);
- exit(1);
- }
- setlinebuf(exception_fp);
- if (fputc('\n', profile_fp) != '\n' || fflush(profile_fp)) {
- fprintf(stderr, "You need to register this program to %s to "
- "run this program.\n", proc_policy_manager);
- exit(1);
- }
- clear_status();
- {
- FILE *fp = fopen(proc_policy_self_domain, "r");
- memset(self_domain, 0, sizeof(self_domain));
- if (!fp || !fgets(self_domain, sizeof(self_domain) - 1, fp) ||
- fclose(fp)) {
- fprintf(stderr, "Can't open %s .\n",
- proc_policy_self_domain);
- exit(1);
- }
- }
- fprintf(domain_fp, "select pid=%u\n", pid);
- fprintf(domain_fp, "use_profile 255\n");
- fprintf(domain_fp, "allow_read/write /sys/kernel/security/tomoyo/domain_policy\n");
- fprintf(domain_fp, "allow_truncate /sys/kernel/security/tomoyo/domain_policy\n");
- fprintf(domain_fp, "allow_read/write /sys/kernel/security/tomoyo/exception_policy\n");
- fprintf(domain_fp, "allow_truncate /sys/kernel/security/tomoyo/exception_policy\n");
- fprintf(domain_fp, "allow_read/write /sys/kernel/security/tomoyo/profile\n");
- fprintf(domain_fp, "allow_truncate /sys/kernel/security/tomoyo/profile\n");
-}
-
-static void BUG(const char *fmt, ...)
- __attribute__ ((format(printf, 1, 2)));
-
-static void BUG(const char *fmt, ...)
-{
- va_list args;
- printf("BUG: ");
- va_start(args, fmt);
- vprintf(fmt, args);
- va_end(args);
- putchar('\n');
- fflush(stdout);
- while (1)
- sleep(100);
-}
-
-int write_domain_policy(const char *policy, int is_delete)
-{
- FILE *fp = fopen(proc_policy_domain_policy, "r");
- char buffer[8192];
- int domain_found = 0;
- int policy_found = 0;
- memset(buffer, 0, sizeof(buffer));
- if (!fp) {
- BUG("Can't read %s", proc_policy_domain_policy);
- return 0;
- }
- if (is_delete)
- fprintf(domain_fp, "delete ");
- fprintf(domain_fp, "%s\n", policy);
- while (fgets(buffer, sizeof(buffer) - 1, fp)) {
- char *cp = strchr(buffer, '\n');
- if (cp)
- *cp = '\0';
- if (!strncmp(buffer, "<kernel>", 8))
- domain_found = !strcmp(self_domain, buffer);
- if (!domain_found)
- continue;
- /* printf("<%s>\n", buffer); */
- if (strcmp(buffer, policy))
- continue;
- policy_found = 1;
- break;
- }
- fclose(fp);
- if (policy_found == is_delete) {
- BUG("Can't %s %s", is_delete ? "delete" : "append",
- policy);
- return 0;
- }
- errno = 0;
- return 1;
-
-}
-
-int write_exception_policy(const char *policy, int is_delete)
-{
- FILE *fp = fopen(proc_policy_exception_policy, "r");
- char buffer[8192];
- int policy_found = 0;
- memset(buffer, 0, sizeof(buffer));
- if (!fp) {
- BUG("Can't read %s", proc_policy_exception_policy);
- return 0;
- }
- if (is_delete)
- fprintf(exception_fp, "delete ");
- fprintf(exception_fp, "%s\n", policy);
- while (fgets(buffer, sizeof(buffer) - 1, fp)) {
- char *cp = strchr(buffer, '\n');
- if (cp)
- *cp = '\0';
- if (strcmp(buffer, policy))
- continue;
- policy_found = 1;
- break;
- }
- fclose(fp);
- if (policy_found == is_delete) {
- BUG("Can't %s %s", is_delete ? "delete" : "append",
- policy);
- return 0;
- }
- errno = 0;
- return 1;
-
-}
-
-int set_profile(const int mode, const char *name)
-{
- static const char *modes[4] = { "disabled", "learning", "permissive",
- "enforcing" };
- FILE *fp = fopen(proc_policy_profile, "r");
- char buffer[8192];
- int policy_found = 0;
- const int len = strlen(name);
- if (!fp) {
- BUG("Can't read %s", proc_policy_profile);
- return 0;
- }
- fprintf(profile_fp, "255-CONFIG::%s=%s\n", name, modes[mode]);
- while (memset(buffer, 0, sizeof(buffer)),
- fgets(buffer, sizeof(buffer) - 1, fp)) {
- char *cp = strchr(buffer, '\n');
- if (cp)
- *cp = '\0';
- if (strncmp(buffer, "255-CONFIG::", 12) ||
- strncmp(buffer + 12, name, len) ||
- buffer[12 + len] != '=')
- continue;
- if (strstr(buffer + 13 + len, modes[mode]))
- policy_found = 1;
- break;
- }
- fclose(fp);
- if (!policy_found) {
- BUG("Can't change profile to 255-CONFIG::%s=%s",
- name, modes[mode]);
- return 0;
- }
- errno = 0;
- return 1;
-}
diff --git a/testcases/kernel/security/tomoyo/newns.c b/testcases/kernel/security/tomoyo/newns.c
deleted file mode 100644
index f888ca31f..000000000
--- a/testcases/kernel/security/tomoyo/newns.c
+++ /dev/null
@@ -1,49 +0,0 @@
-/******************************************************************************/
-/* */
-/* Copyright (c) Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>, 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 */
-/* */
-/******************************************************************************/
-
-#define _GNU_SOURCE
-
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <sys/mount.h>
-#include <unistd.h>
-#include <sched.h>
-#include <errno.h>
-#include <stdlib.h>
-#include "test.h"
-
-static int child(void *arg)
-{
- char **argv = (char **)arg;
- argv++;
- mount("/tmp/", "/tmp/", "tmpfs", 0, NULL);
- execvp(argv[0], argv);
- _exit(1);
-}
-
-int main(int argc, char *argv[])
-{
- char c = 0;
- const pid_t pid = ltp_clone_quick(CLONE_NEWNS, child, (void *)argv);
- while (waitpid(pid, NULL, __WALL) == EOF && errno == EINTR)
- c++; /* Dummy. */
- return 0;
-}
diff --git a/testcases/kernel/security/tomoyo/testall.sh b/testcases/kernel/security/tomoyo/testall.sh
deleted file mode 100644
index b103be6c6..000000000
--- a/testcases/kernel/security/tomoyo/testall.sh
+++ /dev/null
@@ -1,46 +0,0 @@
-#! /bin/sh
-################################################################################
-## ##
-## Copyright (c) Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>, 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 ##
-## ##
-################################################################################
-
-cd ${0%/*}
-export PATH=$PWD:${PATH}
-
-echo "Testing all. (All results are reported)"
-newns tomoyo_accept_test
-newns tomoyo_filesystem_test
-newns tomoyo_file_test
-newns tomoyo_rewrite_test
-newns tomoyo_new_file_test
-newns tomoyo_new_test
-echo
-echo
-echo
-echo "Testing all. (Only ERRORS are reported)"
-newns tomoyo_accept_test | grep -vF Done
-newns tomoyo_filesystem_test | grep -vF OK | grep -F '('
-newns tomoyo_file_test | grep -vF OK | grep -F '('
-newns tomoyo_rewrite_test | grep -vF OK | grep -F '('
-newns tomoyo_new_test | grep -vF OK
-echo
-echo
-echo
-echo "Testing policy I/O. (Only ERRORS are reported)"
-newns tomoyo_policy_io_test | grep -vF OK
-newns tomoyo_new_file_test | grep -vF OK
diff --git a/testcases/kernel/security/tomoyo/tomoyo_accept_test.c b/testcases/kernel/security/tomoyo/tomoyo_accept_test.c
deleted file mode 100644
index 335818a25..000000000
--- a/testcases/kernel/security/tomoyo/tomoyo_accept_test.c
+++ /dev/null
@@ -1,146 +0,0 @@
-/******************************************************************************/
-/* 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 */
-/* */
-/******************************************************************************/
-/*
- * tomoyo_accept_test.c
- *
- * Testing program for security/tomoyo/
- *
- * Copyright (C) 2005-2010 NTT DATA CORPORATION
- */
-#include "include.h"
-
-static void set_level(const int i)
-{
- set_profile(i, "file::execute");
- set_profile(i, "file::open");
- set_profile(i, "file::create");
- set_profile(i, "file::unlink");
- set_profile(i, "file::mkdir");
- set_profile(i, "file::rmdir");
- set_profile(i, "file::mkfifo");
- set_profile(i, "file::mksock");
- set_profile(i, "file::truncate");
- set_profile(i, "file::symlink");
- set_profile(i, "file::rewrite");
- set_profile(i, "file::mkblock");
- set_profile(i, "file::mkchar");
- set_profile(i, "file::link");
- set_profile(i, "file::rename");
- set_profile(i, "file::chmod");
- set_profile(i, "file::chown");
- set_profile(i, "file::chgrp");
- set_profile(i, "file::ioctl");
- set_profile(i, "file::chroot");
- set_profile(i, "file::mount");
- set_profile(i, "file::umount");
- set_profile(i, "file::pivot_root");
-}
-
-static void test(int rw_loop, int truncate_loop, int append_loop,
- int create_loop)
-{
- static const int rw_flags[4] = { 0, O_RDONLY, O_WRONLY, O_RDWR };
- static const int create_flags[3] = { 0, O_CREAT /* nonexistent */ ,
- O_CREAT /* existent */
- };
- static const int truncate_flags[2] = { 0, O_TRUNC };
- static const int append_flags[2] = { 0, O_APPEND };
- int level;
- int flags;
- int i;
- int fd;
- static char buffer[1024];
- memset(buffer, 0, sizeof(buffer));
- snprintf(buffer, sizeof(buffer) - 1, "/tmp/file:a=%d:t=%d:c=%d:m=%d",
- append_loop, truncate_loop, create_loop, rw_loop);
- fprintf(exception_fp, "deny_rewrite %s\n", buffer);
- flags = rw_flags[rw_loop] | truncate_flags[truncate_loop] |
- append_flags[append_loop] | create_flags[create_loop];
- for (i = 1; i < 8; i++)
- fprintf(domain_fp, "delete %d %s\n", i, buffer);
- for (level = 0; level < 4; level++) {
- set_level(0);
- if (create_loop == 1)
- unlink(buffer);
- else
- close(open(buffer, O_CREAT, 0644));
- set_level(level);
- fd = open(buffer, flags, 0644);
- if (fd != EOF)
- close(fd);
- else
- fprintf(stderr, "%d: open(%04o) failed\n", level,
- flags);
- /*
- fd = open(buffer, flags, 0644)
- if (fd != EOF)
- close(fd);
- else
- fprintf(stderr, "%d: open(%04o) failed\n", level, flags);
- */
- /*
- fd = open(buffer, flags, 0644);
- if (fd != EOF)
- close(fd);
- else
- fprintf(stderr, "%d: open(%04o) failed\n", level, flags);
- */
- }
- for (i = 1; i < 8; i++)
- fprintf(domain_fp, "delete %d %s\n", i, buffer);
- fprintf(domain_fp, "delete allow_truncate %s\n", buffer);
- fprintf(domain_fp, "delete allow_create %s 0644\n", buffer);
- fprintf(domain_fp, "delete allow_rewrite %s\n", buffer);
- fd = open(buffer, flags, 0644);
- if (fd != EOF) {
- close(fd);
- fprintf(stderr, "%d: open(%04o) didn't fail\n", 3, flags);
- }
-}
-
-int main(void)
-{
- tomoyo_test_init();
- fprintf(profile_fp, "255-PREFERENCE::learning={ verbose=no }\n");
- fprintf(profile_fp, "255-PREFERENCE::enforcing={ verbose=no }\n");
- fprintf(profile_fp, "255-PREFERENCE::permissive={ verbose=no }\n");
- fprintf(profile_fp, "255-PREFERENCE::disabled={ verbose=no }\n");
- set_profile(0, "file");
- fprintf(profile_fp, "255-PREFERENCE::learning={ max_entry=2048 }\n");
- {
- int append_loop;
- for (append_loop = 0; append_loop < 2; append_loop++) {
- int truncate_loop;
- for (truncate_loop = 0; truncate_loop < 2;
- truncate_loop++) {
- int create_loop;
- for (create_loop = 0; create_loop < 3;
- create_loop++) {
- int rw_loop;
- for (rw_loop = 0; rw_loop < 4;
- rw_loop++)
- test(rw_loop, truncate_loop,
- append_loop, create_loop);
- }
- }
- }
- }
- fprintf(profile_fp, "255-CONFIG::file=disabled\n");
- printf("Done\n");
- clear_status();
- return 0;
-}
diff --git a/testcases/kernel/security/tomoyo/tomoyo_file_test.c b/testcases/kernel/security/tomoyo/tomoyo_file_test.c
deleted file mode 100644
index 003f47720..000000000
--- a/testcases/kernel/security/tomoyo/tomoyo_file_test.c
+++ /dev/null
@@ -1,304 +0,0 @@
-/******************************************************************************/
-/* 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 */
-/* */
-/******************************************************************************/
-/*
- * tomoyo_file_test.c
- *
- * Testing program for security/tomoyo/
- *
- * Copyright (C) 2005-2010 NTT DATA CORPORATION
- */
-#include "include.h"
-
-static int should_fail = 0;
-
-static void show_prompt(const char *str)
-{
- printf("Testing %35s: (%s) ", str,
- should_fail ? "must fail" : "should success");
- errno = 0;
-}
-
-static void show_result(int result)
-{
- if (should_fail) {
- if (result == EOF) {
- if (errno == EPERM)
- printf("OK: Permission denied.\n");
- else
- printf("FAILED: %s\n", strerror(errno));
- } else {
- printf("BUG!\n");
- }
- } else {
- if (result != EOF)
- printf("OK\n");
- else
- printf("%s\n", strerror(errno));
- }
-}
-
-static const char *dev_null_path = "/dev/null";
-static const char *truncate_path = "/tmp/truncate_test";
-static const char *ftruncate_path = "/tmp/ftruncate_test";
-static const char *open_creat_path = "/tmp/open_test";
-static const char *mknod_reg_path = "/tmp/mknod_reg_test";
-static const char *mknod_chr_path = "/tmp/mknod_chr_test";
-static const char *mknod_blk_path = "/tmp/mknod_blk_test";
-static const char *mknod_fifo_path = "/tmp/mknod_fifo_test";
-static const char *mknod_sock_path = "/tmp/mknod_sock_test";
-static const char *unlink_path = "/tmp/unlink_test";
-static const char *mkdir_path = "/tmp/mkdir_test";
-static const char *rmdir_path = "/tmp/rmdir_test";
-static const char *link_source_path = "/tmp/link_source_test";
-static const char *link_dest_path = "/tmp/link_dest_test";
-static const char *symlink_source_path = "/tmp/symlink_source_test";
-static const char *symlink_dest_path = "/tmp/symlink_dest_test";
-static const char *rename_source_path = "/tmp/rename_source_test";
-static const char *rename_dest_path = "/tmp/rename_dest_test";
-static const char *socket_path = "/tmp/socket_test";
-
-static int ftruncate_fd = EOF;
-
-static void stage_file_test(void)
-{
- int fd;
- {
- const char buffer[] = "32768 61000";
- show_prompt("sysctl(READ)");
- show_result(read_sysctl(TEST_SYSCTL_PATH, NULL, 0));
- show_prompt("sysctl(WRITE)");
- show_result(write_sysctl(TEST_SYSCTL_PATH, buffer));
- }
-
- /* QUESTION: Is there a file which can be passed to uselib()? */
- show_prompt("uselib()");
- show_result(uselib("/bin/true"));
-
- {
- int pipe_fd[2] = { EOF, EOF };
- int error = 0;
- fflush(stdout);
- fflush(stderr);
- if (pipe(pipe_fd) == -1)
- err(1, "pipe");
- if (fork() == 0) {
- execl("/bin/true", "/bin/true", NULL);
- if (write(pipe_fd[1], &errno, sizeof(errno)) == -1)
- err(1, "write");
- _exit(0);
- }
- close(pipe_fd[1]);
- (void)read(pipe_fd[0], &error, sizeof(error));
- show_prompt("execve()");
- errno = error;
- show_result(error ? EOF : 0);
- }
-
- show_prompt("open(O_RDONLY)");
- fd = open(dev_null_path, O_RDONLY);
- show_result(fd);
- if (fd != EOF)
- close(fd);
-
- show_prompt("open(O_WRONLY)");
- fd = open(dev_null_path, O_WRONLY);
- show_result(fd);
- if (fd != EOF)
- close(fd);
-
- show_prompt("open(O_RDWR)");
- fd = open(dev_null_path, O_RDWR);
- show_result(fd);
- if (fd != EOF)
- close(fd);
-
- show_prompt("open(O_CREAT | O_EXCL)");
- fd = open(open_creat_path, O_CREAT | O_EXCL, 0666);
- show_result(fd);
- if (fd != EOF)
- close(fd);
-
- show_prompt("open(O_TRUNC)");
- fd = open(truncate_path, O_TRUNC);
- show_result(fd);
- if (fd != EOF)
- close(fd);
-
- show_prompt("truncate()");
- show_result(truncate(truncate_path, 0));
-
- show_prompt("ftruncate()");
- show_result(ftruncate(ftruncate_fd, 0));
-
- show_prompt("mknod(S_IFREG)");
- show_result(mknod(mknod_reg_path, S_IFREG, 0));
-
- show_prompt("mknod(S_IFCHR)");
- show_result(mknod(mknod_chr_path, S_IFCHR, MKDEV(1, 3)));
-
- show_prompt("mknod(S_IFBLK)");
- show_result(mknod(mknod_blk_path, S_IFBLK, MKDEV(1, 0)));
-
- show_prompt("mknod(S_IFIFO)");
- show_result(mknod(mknod_fifo_path, S_IFIFO, 0));
-
- show_prompt("mknod(S_IFSOCK)");
- show_result(mknod(mknod_sock_path, S_IFSOCK, 0));
-
- show_prompt("mkdir()");
- show_result(mkdir(mkdir_path, 0600));
-
- show_prompt("rmdir()");
- show_result(rmdir(rmdir_path));
-
- show_prompt("unlink()");
- show_result(unlink(unlink_path));
-
- show_prompt("symlink()");
- show_result(symlink(symlink_dest_path, symlink_source_path));
-
- show_prompt("link()");
- show_result(link(link_source_path, link_dest_path));
-
- show_prompt("rename()");
- show_result(rename(rename_source_path, rename_dest_path));
-
- {
- struct sockaddr_un addr;
- int fd;
- memset(&addr, 0, sizeof(addr));
- addr.sun_family = AF_UNIX;
- strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path) - 1);
- fd = socket(AF_UNIX, SOCK_STREAM, 0);
- show_prompt("unix_bind()");
- show_result(bind(fd, (struct sockaddr *)&addr, sizeof(addr)));
- if (fd != EOF)
- close(fd);
- }
-
- printf("\n\n");
-}
-
-static void create_files(void)
-{
- mkdir(rmdir_path, 0700);
- close(creat(link_source_path, 0600));
- close(creat(rename_source_path, 0600));
- close(creat(truncate_path, 0600));
- close(creat(unlink_path, 0600));
- ftruncate_fd = open(ftruncate_path, O_WRONLY | O_CREAT, 0600);
-}
-
-static void creanup_files(void)
-{
- if (ftruncate_fd != EOF)
- close(ftruncate_fd);
- ftruncate_fd = EOF;
- unlink(open_creat_path);
- unlink(mknod_reg_path);
- unlink(mknod_chr_path);
- unlink(mknod_blk_path);
- unlink(mknod_fifo_path);
- unlink(mknod_sock_path);
- rmdir(mkdir_path);
- unlink(symlink_source_path);
- unlink(symlink_dest_path);
- unlink(link_source_path);
- unlink(link_dest_path);
- unlink(rename_source_path);
- unlink(rename_dest_path);
- unlink(truncate_path);
- unlink(ftruncate_path);
- unlink(socket_path);
-}
-
-static void set_file_enforce(int enforce)
-{
- if (enforce) {
- set_profile(3, "file::execute");
- set_profile(3, "file::open");
- set_profile(3, "file::create");
- set_profile(3, "file::unlink");
- set_profile(3, "file::mkdir");
- set_profile(3, "file::rmdir");
- set_profile(3, "file::mkfifo");
- set_profile(3, "file::mksock");
- set_profile(3, "file::truncate");
- set_profile(3, "file::symlink");
- set_profile(3, "file::rewrite");
- set_profile(3, "file::mkblock");
- set_profile(3, "file::mkchar");
- set_profile(3, "file::link");
- set_profile(3, "file::rename");
- set_profile(3, "file::chmod");
- set_profile(3, "file::chown");
- set_profile(3, "file::chgrp");
- set_profile(3, "file::ioctl");
- set_profile(3, "file::chroot");
- set_profile(3, "file::mount");
- set_profile(3, "file::umount");
- set_profile(3, "file::pivot_root");
- } else {
- set_profile(0, "file::execute");
- set_profile(0, "file::open");
- set_profile(0, "file::create");
- set_profile(0, "file::unlink");
- set_profile(0, "file::mkdir");
- set_profile(0, "file::rmdir");
- set_profile(0, "file::mkfifo");
- set_profile(0, "file::mksock");
- set_profile(0, "file::truncate");
- set_profile(0, "file::symlink");
- set_profile(0, "file::rewrite");
- set_profile(0, "file::mkblock");
- set_profile(0, "file::mkchar");
- set_profile(0, "file::link");
- set_profile(0, "file::rename");
- set_profile(0, "file::chmod");
- set_profile(0, "file::chown");
- set_profile(0, "file::chgrp");
- set_profile(0, "file::ioctl");
- set_profile(0, "file::chroot");
- set_profile(0, "file::mount");
- set_profile(0, "file::umount");
- set_profile(0, "file::pivot_root");
- }
-}
-
-int main(void)
-{
- tomoyo_test_init();
-
- printf("***** Testing file hooks in enforce mode. *****\n");
- create_files();
- should_fail = 1;
- set_file_enforce(1);
- stage_file_test();
- set_file_enforce(0);
- clear_status();
- creanup_files();
-
- printf("***** Testing file hooks in permissive mode. *****\n");
- should_fail = 0;
- create_files();
- set_file_enforce(0);
- stage_file_test();
- creanup_files();
-
- clear_status();
- return 0;
-}
diff --git a/testcases/kernel/security/tomoyo/tomoyo_filesystem_test.c b/testcases/kernel/security/tomoyo/tomoyo_filesystem_test.c
deleted file mode 100644
index e6e3bb087..000000000
--- a/testcases/kernel/security/tomoyo/tomoyo_filesystem_test.c
+++ /dev/null
@@ -1,633 +0,0 @@
-/******************************************************************************/
-/* 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 */
-/* */
-/******************************************************************************/
-/*
- * tomoyo_filesystem_test.c
- *
- * Testing program for security/tomoyo/
- *
- * Copyright (C) 2005-2010 NTT DATA CORPORATION
- */
-#define _GNU_SOURCE
-#include "include.h"
-
-static void show_prompt(const char *str, const int should_fail)
-{
- printf("Testing %60s: (%s) ", str,
- should_fail ? "must fail" : "should success");
- errno = 0;
-}
-
-#ifndef MS_MOVE
-#define MS_MOVE 8192
-#endif
-
-static const char *pivot_root_dir = "/sys/kernel/security/";
-
-static int child(void *arg)
-{
- errno = 0;
- pivot_root(pivot_root_dir, proc_policy_dir);
- return errno;
-}
-
-static void mount2(const char *source, const char *target,
- const char *filesystemtype)
-{
- if (mount(source, target, filesystemtype, 0, NULL)) {
- printf("BUG: mount() failed\n");
- fflush(stdout);
- }
-}
-
-static const unsigned char compressed_ext2_image_sample[1350] = {
- 0x1F, 0x8B, 0x08, 0x00, 0xA8, 0xF2, 0x96, 0x4B, 0x02, 0x03, 0xED, 0xDC,
- 0x3D, 0x4B, 0x5B, 0x51, 0x18, 0x07, 0xF0, 0xE7, 0xDE, 0xAB, 0x14, 0x8C,
- 0xAB, 0xD5, 0x9A, 0xF8, 0x36, 0x0B, 0xA1, 0xE0, 0xE0, 0xDC, 0xD0, 0xAD,
- 0xD0, 0xC5, 0xAF, 0x50, 0x9C, 0x42, 0x1D, 0x6A, 0xE6, 0xA6, 0x9B, 0x9B,
- 0x8B, 0xD8, 0xA5, 0x5B, 0x97, 0x2E, 0xF9, 0x0E, 0x85, 0x4C, 0xF6, 0x23,
- 0x74, 0x70, 0x55, 0x28, 0x52, 0xA8, 0xDD, 0xED, 0xB9, 0xB9, 0xB1, 0xA6,
- 0xEA, 0x24, 0xA5, 0x81, 0xDE, 0xDF, 0x0F, 0x9E, 0xDC, 0xB7, 0x13, 0x2E,
- 0xF7, 0xC0, 0xFF, 0x70, 0xCE, 0x85, 0x24, 0x02, 0xA8, 0xAB, 0x7E, 0xF9,
- 0x31, 0x13, 0xB1, 0x95, 0x36, 0xA7, 0x45, 0x44, 0x2F, 0x6D, 0xB3, 0xC9,
- 0x06, 0xEB, 0x55, 0xF5, 0xC7, 0x87, 0x9F, 0x7E, 0x1C, 0xBF, 0x88, 0x68,
- 0xC5, 0xCE, 0xF7, 0x6C, 0xD4, 0x6E, 0x74, 0xFC, 0xF2, 0x62, 0x74, 0xED,
- 0xFA, 0x7B, 0x8D, 0xB8, 0x69, 0x9F, 0x8F, 0xCF, 0x9F, 0x1D, 0x7E, 0x78,
- 0xF7, 0x6D, 0xD8, 0x79, 0xFF, 0x71, 0xD0, 0xED, 0xBC, 0xCD, 0x9A, 0xBD,
- 0x69, 0x3C, 0xEB, 0xE0, 0xCB, 0xF0, 0xA4, 0xF9, 0xF5, 0xF9, 0xCA, 0xE0,
- 0xE0, 0x72, 0xBB, 0x7B, 0xD4, 0x1A, 0xE6, 0x13, 0xD7, 0xAA, 0xE7, 0x82,
- 0x7A, 0x29, 0xAA, 0xF8, 0xC7, 0xEC, 0x28, 0xFF, 0xBD, 0xC8, 0x75, 0x09,
- 0xD4, 0xC6, 0x55, 0x92, 0x4D, 0x71, 0xFA, 0x71, 0x05, 0x4C, 0xCF, 0xA3,
- 0xBB, 0xE3, 0x01, 0x50, 0x0F, 0x93, 0xEB, 0xDF, 0xEB, 0xFA, 0x97, 0x13,
- 0x80, 0x8B, 0x67, 0xD5, 0x02, 0xE4, 0xEE, 0xFD, 0x8B, 0x3F, 0xD6, 0x22,
- 0x0B, 0xA6, 0x6A, 0xC0, 0x5F, 0xF6, 0xB9, 0x1C, 0x7F, 0x9E, 0xDE, 0x37,
- 0xFE, 0xE4, 0xB1, 0x34, 0xD1, 0xEE, 0x71, 0xAA, 0xC5, 0x54, 0xE5, 0xB9,
- 0x27, 0xA9, 0x96, 0x53, 0x35, 0xA3, 0x7C, 0x13, 0x1A, 0xB1, 0x92, 0x6A,
- 0x35, 0xD5, 0xDA, 0xF8, 0x75, 0xE9, 0x86, 0x6E, 0x05, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x81,
- 0xCA, 0xDF, 0xD8, 0xCF, 0x47, 0x96, 0xB7, 0x7F, 0xEF, 0xE7, 0x79, 0xBB,
- 0x5D, 0xFD, 0x87, 0xDF, 0x79, 0x31, 0x97, 0x77, 0xF7, 0xDE, 0xEC, 0x6F,
- 0xEE, 0xEE, 0xF5, 0x5E, 0xBF, 0xD2, 0x57, 0xF0, 0xBF, 0x69, 0xDC, 0xCA,
- 0xFF, 0xCF, 0xA2, 0xCA, 0x3F, 0x50, 0x13, 0x33, 0xBA, 0x00, 0xE4, 0x1F,
- 0x90, 0x7F, 0x40, 0xFE, 0x01, 0xF9, 0x07, 0xE4, 0x1F, 0x90, 0x7F, 0x40,
- 0xFE, 0x01, 0xF9, 0x07, 0xE4, 0x1F, 0x90, 0x7F, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFA, 0xF9, 0x05, 0x34, 0xF2,
- 0x14, 0x08, 0x00, 0x00, 0x10, 0x00
-};
-
-int main(void)
-{
- char c = 0;
- tomoyo_test_init();
-
- /* Test mount(). */
- {
- set_profile(3, "file::mount");
- show_prompt("mount('dev\\011name', '/', 'fs\\011name') ", 1);
- if (mount("dev\tname", "/", "fs\tname", 0, NULL) == EOF &&
- errno == EPERM)
- printf("OK: Permission denied.\n");
- else if (errno == ENODEV)
- printf("OK: No such device.\n");
- else
- printf("BUG: %s\n", strerror(errno));
- set_profile(1, "file::mount");
- show_prompt("mount('dev\\011name', '/', 'fs\\011name') ", 0);
- if (mount("dev\tname", "/", "fs\tname", 0, NULL) == EOF &&
- errno == ENOMEM)
- printf("OK: Out of memory.\n");
- else if (errno == ENODEV)
- printf("OK: No such device.\n");
- else
- printf("BUG: %s\n", strerror(errno));
- set_profile(3, "file::mount");
- show_prompt("mount('dev\\011name', '/', 'fs\\011name') ", 0);
- if (mount("dev\tname", "/", "fs\tname", 0, NULL) == EOF &&
- errno == ENOMEM)
- printf("OK: Out of memory.\n");
- else if (errno == ENODEV)
- printf("OK: No such device.\n");
- else
- printf("BUG: %s\n", strerror(errno));
- fprintf(domain_fp, "delete allow_mount dev\\011name / "
- "fs\\011name 0\n");
- show_prompt("mount('dev\\011name', '/', 'fs\\011name') ", 1);
- if (mount("dev\tname", "/", "fs\tname", 0, NULL) == EOF &&
- errno == EPERM)
- printf("OK: Permission denied.\n");
- else if (errno == ENODEV)
- printf("OK: No such device.\n");
- else
- printf("BUG: %s\n", strerror(errno));
- set_profile(1, "file::mount");
- show_prompt("mount(NULL, '/', 'tmpfs') ", 0);
- if (mount(NULL, "/", "tmpfs", 0, NULL))
- printf("BUG: %s\n", strerror(errno));
- else
- printf("OK: Success\n");
- set_profile(3, "file::mount");
- show_prompt("mount(NULL, '/', 'tmpfs') ", 0);
- if (mount(NULL, "/", "tmpfs", 0, NULL))
- printf("BUG: %s\n", strerror(errno));
- else
- printf("OK: Success\n");
- show_prompt("mount('anydev', '/', 'tmpfs') ", 0);
- if (mount("anydev", "/", "tmpfs", 0, NULL))
- printf("BUG: %s\n", strerror(errno));
- else
- printf("OK: Success\n");
- fprintf(domain_fp, "delete allow_mount <NULL> / tmpfs 0\n");
- fprintf(domain_fp, "allow_mount anydev / tmpfs 0\n");
- show_prompt("mount(NULL, '/', 'tmpfs') ", 0);
- if (mount(NULL, "/", "tmpfs", 0, NULL))
- printf("BUG: %s\n", strerror(errno));
- else
- printf("OK: Success\n");
- fprintf(domain_fp, "delete allow_mount anydev / tmpfs 0\n");
- set_profile(2, "file::mount");
- show_prompt("mount(NULL, NULL, 'tmpfs') ", 1);
- if (mount(NULL, NULL, "tmpfs", 0, NULL))
- printf("OK: %s\n", strerror(errno));
- else
- printf("BUG: Did not fail.\n");
- show_prompt("mount(NULL, NULL, NULL) ", 1);
- if (mount(NULL, NULL, NULL, 0, NULL))
- printf("OK: %s\n", strerror(errno));
- else
- printf("BUG: Did not fail.\n");
- show_prompt("mount('/', NULL, NULL) ", 1);
- if (mount("/", NULL, NULL, 0, NULL))
- printf("OK: %s\n", strerror(errno));
- else
- printf("BUG: Did not fail.\n");
- show_prompt("mount('/', NULL, 'tmpfs') ", 1);
- if (mount("/", NULL, "tmpfs", 0, NULL))
- printf("OK: %s\n", strerror(errno));
- else
- printf("BUG: Did not fail.\n");
- show_prompt("mount('/', '/', 'nonexistentfs') ", 1);
- if (mount("/", "/", "nonexistentfs", 0, NULL))
- printf("OK: %s\n", strerror(errno));
- else
- printf("BUG: Did not fail.\n");
- set_profile(0, "file::mount");
- }
-
- mkdir("/tmp/mount/", 0755);
- mkdir("/tmp/mount_bind/", 0755);
- mkdir("/tmp/mount_move/", 0755);
-
- /* Test mount(). */
- {
- static char buf[4096];
- char *dev_ram_path = realpath("/dev/ram0", NULL);
- if (!dev_ram_path)
- dev_ram_path = realpath("/dev/ram", NULL);
- if (!dev_ram_path) {
- dev_ram_path = "/dev/ram0";
- mknod(dev_ram_path, S_IFBLK, MKDEV(1, 0));
- }
- memset(buf, 0, sizeof(buf));
- {
- struct stat sbuf;
- FILE *fp = NULL;
- snprintf(buf, sizeof(buf) - 1, "zcat - > %s",
- dev_ram_path);
- if (lstat(dev_ram_path, &sbuf) == 0 &&
- S_ISBLK(sbuf.st_mode) && MAJOR(sbuf.st_rdev) == 1)
- fp = popen(buf, "w");
- if (fp) {
- if (fwrite(compressed_ext2_image_sample, 1,
- sizeof(compressed_ext2_image_sample),
- fp) !=
- sizeof(compressed_ext2_image_sample))
- err(1, "fwrite");
- pclose(fp);
- } else
- fprintf(stderr, "Can't write to %s .\n",
- dev_ram_path);
- }
- set_profile(3, "file::mount");
-
- /* Test standard case */
- show_prompt("mount('none', '/tmp/mount/', 'tmpfs') for "
- "'/tmp/mount/'", 1);
- if (mount("none", "/tmp/mount/", "tmpfs", 0, NULL) == EOF &&
- errno == EPERM)
- printf("OK: Permission denied.\n");
- else
- printf("BUG: %s\n", strerror(errno));
-
- /* Test device_name with pattern */
- snprintf(buf, sizeof(buf) - 1, "mount('%s', '/tmp/mount/', "
- "'ext2') for '%s\\*'", dev_ram_path, dev_ram_path);
- show_prompt(buf, 1);
- if (mount(dev_ram_path, "/tmp/mount/", "ext2", MS_RDONLY, NULL)
- == EOF && errno == EPERM)
- printf("OK: Permission denied.\n");
- else
- printf("BUG: %s\n", strerror(errno));
-
- /* Test dir_name with pattern */
- show_prompt("mount('none', '/tmp/mount/', 'tmpfs') for "
- "'/tmp/\\?\\?\\?\\?\\?/'", 1);
- if (mount("none", "/tmp/mount/", "tmpfs", 0, NULL) == EOF &&
- errno == EPERM)
- printf("OK: Permission denied.\n");
- else
- printf("BUG: %s\n", strerror(errno));
-
- /* Test standard case */
- fprintf(domain_fp, "allow_mount none /tmp/mount/ tmpfs 0\n");
- show_prompt("mount('none', '/tmp/mount/', 'tmpfs') for "
- "'/tmp/mount/'", 0);
- if (mount("none", "/tmp/mount/", "tmpfs", 0, NULL) == 0)
- printf("OK\n");
- else
- printf("FAILED: %s\n", strerror(errno));
- fprintf(domain_fp,
- "delete allow_mount none /tmp/mount/ tmpfs 0\n");
-
- /* Test device_name with pattern */
- fprintf(domain_fp, "allow_mount %s\\* /tmp/mount/ ext2 1\n",
- dev_ram_path);
- snprintf(buf, sizeof(buf) - 1, "mount('%s', '/tmp/mount/', "
- "'ext2') for '%s\\*'", dev_ram_path, dev_ram_path);
- show_prompt(buf, 0);
- if (mount(dev_ram_path, "/tmp/mount/", "ext2", MS_RDONLY, NULL)
- == 0)
- printf("OK\n");
- else
- printf("FAILED: %s\n", strerror(errno));
- fprintf(domain_fp, "delete allow_mount %s\\* "
- "/tmp/mount/ ext2 1\n", dev_ram_path);
-
- /* Test dir_name with pattern */
- fprintf(domain_fp,
- "allow_mount none /tmp/\\?\\?\\?\\?\\?/ tmpfs 0\n");
- show_prompt("mount('none', '/tmp/mount/', 'tmpfs') for "
- "'/tmp/\\?\\?\\?\\?\\?/'", 0);
- if (mount("none", "/tmp/mount/", "tmpfs", 0, NULL) == 0)
- printf("OK\n");
- else
- printf("FAILED: %s\n", strerror(errno));
- fprintf(domain_fp, "delete allow_mount none "
- "/tmp/\\?\\?\\?\\?\\?/ tmpfs 0\n");
-
- set_profile(0, "file::mount");
- while (umount("/tmp/mount/") == 0)
- c++; /* Dummy. */
- }
-
- /* Test mount(). */
- {
- mount2("none", "/tmp/mount/", "tmpfs");
- set_profile(3, "file::mount");
-
- /* Test remount case */
- show_prompt("mount('/tmp/mount/', MS_REMOUNT)", 1);
- if (mount("none", "/tmp/mount/", "tmpfs", MS_REMOUNT, NULL)
- == EOF && errno == EPERM)
- printf("OK: Permission denied.\n");
- else
- printf("BUG: %s\n", strerror(errno));
- show_prompt("mount('/tmp/mount/', MS_REMOUNT)", 1);
- if (mount(NULL, "/tmp/mount/", NULL, MS_REMOUNT, NULL) == EOF
- && errno == EPERM)
- printf("OK: Permission denied.\n");
- else
- printf("BUG: %s\n", strerror(errno));
- fprintf(domain_fp, "allow_mount something /tmp/mount/ "
- "--remount 0\n");
- show_prompt("mount('/tmp/mount/', MS_REMOUNT)", 0);
- if (mount(NULL, "/tmp/mount/", NULL, MS_REMOUNT, NULL))
- printf("BUG: %s\n", strerror(errno));
- else
- printf("OK: Success.\n");
- fprintf(domain_fp, "delete allow_mount something /tmp/mount/ "
- "--remount 0\n");
-
- /* Test bind case */
- show_prompt("mount('/tmp/mount/', '/tmp/mount_bind/', "
- "MS_BIND)", 1);
- if (mount("/tmp/mount/", "/tmp/mount_bind/", NULL, MS_BIND,
- NULL) == EOF && errno == EPERM)
- printf("OK: Permission denied.\n");
- else
- printf("BUG: %s\n", strerror(errno));
-
- /* Test move case */
- show_prompt("mount('/tmp/mount/', '/tmp/mount_move/', "
- "MS_MOVE)", 1);
- if (mount("/tmp/mount/", "/tmp/mount_move/", NULL, MS_MOVE,
- NULL) == EOF && errno == EPERM)
- printf("OK: Permission denied.\n");
- else
- printf("BUG: %s\n", strerror(errno));
-
- /* Test remount case */
- fprintf(domain_fp, "allow_mount any /tmp/mount/ --remount 0\n");
- show_prompt("mount('/tmp/mount/', MS_REMOUNT)", 0);
- if (mount("none", "/tmp/mount/", "tmpfs", MS_REMOUNT, NULL)
- == 0)
- printf("OK\n");
- else
- printf("FAILED: %s\n", strerror(errno));
- fprintf(domain_fp, "delete allow_mount any /tmp/mount/ "
- "--remount 0\n");
-
- /* Test bind case */
- fprintf(domain_fp,
- "allow_mount /tmp/mount/ /tmp/mount_bind/ --bind 0\n");
- show_prompt("mount('/tmp/mount/', '/tmp/mount_bind', MS_BIND)",
- 0);
- if (mount("/tmp/mount/", "/tmp/mount_bind/", NULL, MS_BIND,
- NULL) == 0)
- printf("OK\n");
- else
- printf("FAILED: %s\n", strerror(errno));
- set_profile(0, "file::mount");
- umount("/tmp/mount_bind/");
- fprintf(domain_fp, "delete allow_mount /tmp/mount/ "
- "/tmp/mount_bind/ --bind 0\n");
-
- /* Test move case */
- set_profile(3, "file::mount");
- fprintf(domain_fp, "allow_unmount /tmp/mount/\n");
- fprintf(domain_fp, "allow_mount /tmp/mount/ /tmp/mount_move/ "
- "--move 0\n");
- show_prompt("mount('/tmp/mount/', '/tmp/mount_move/', "
- "MS_MOVE)", 0);
- if (mount("/tmp/mount/", "/tmp/mount_move/", NULL, MS_MOVE,
- NULL) == 0)
- printf("OK\n");
- else
- printf("FAILED: %s\n", strerror(errno));
- set_profile(0, "file::mount");
- umount("/tmp/mount_move/");
- fprintf(domain_fp, "delete allow_unmount /tmp/mount/\n");
- fprintf(domain_fp, "delete allow_mount /tmp/mount/ "
- "/tmp/mount_move/ --move 0\n");
-
- while (umount("/tmp/mount/") == 0)
- c++; /* Dummy. */
- }
-
- /* Test umount(). */
- {
- /* Test standard case */
- fprintf(domain_fp, "allow_unmount /tmp/mount/\n");
-
- set_profile(0, "file::umount");
- mount2("none", "/tmp/mount/", "tmpfs");
- set_profile(3, "file::umount");
- show_prompt("umount('/tmp/mount/') for '/tmp/mount/'", 0);
- if (umount("/tmp/mount/") == 0)
- printf("OK\n");
- else
- printf("BUG: %s\n", strerror(errno));
- fprintf(domain_fp, "delete allow_unmount /tmp/mount/\n");
-
- set_profile(0, "file::umount");
-
- mount2("none", "/tmp/mount/", "tmpfs");
- set_profile(3, "file::umount");
- show_prompt("umount('/tmp/mount/') for '/tmp/mount/'", 1);
- if (umount("/tmp/mount/") == EOF && errno == EPERM)
- printf("OK: Permission denied.\n");
- else
- printf("FAILED: %s\n", strerror(errno));
-
- /* Test pattern */
- fprintf(domain_fp, "allow_unmount /tmp/\\?\\?\\?\\?\\?/\n");
- set_profile(0, "file::umount");
- mount2("none", "/tmp/mount/", "tmpfs");
- set_profile(3, "file::umount");
- show_prompt("umount('/tmp/mount/') for "
- "'/tmp/\\?\\?\\?\\?\\?/'", 1);
- if (umount("/tmp/mount/") == 0)
- printf("OK\n");
- else
- printf("BUG: %s\n", strerror(errno));
- fprintf(domain_fp,
- "delete allow_unmount /tmp/\\?\\?\\?\\?\\?/\n");
-
- set_profile(0, "file::umount");
- while (umount("/tmp/mount/") == 0)
- c++; /* Dummy. */
- }
-
- /* Test chroot(). */
- {
- set_profile(3, "file::chroot");
-
- /* Test standard case */
- fprintf(domain_fp, "allow_chroot /tmp/mount/\n");
- show_prompt("chroot('/tmp/mount/') for '/tmp/mount/'", 0);
- fflush(stdout);
- if (fork() == 0) {
- if (chroot("/tmp/mount/") == 0)
- printf("OK\n");
- else
- printf("FAILED: %s\n", strerror(errno));
- fflush(stdout);
- _exit(0);
- }
- wait(NULL);
- fprintf(domain_fp, "delete allow_chroot /tmp/mount/\n");
-
- show_prompt("chroot('/tmp/mount/') for '/tmp/mount/'", 1);
- fflush(stdout);
- if (fork() == 0) {
- if (chroot("/tmp/mount/") == EOF && errno == EPERM)
- printf("OK: Permission denied.\n");
- else
- printf("BUG: %s\n", strerror(errno));
- fflush(stdout);
- _exit(0);
- }
- wait(NULL);
-
- /* Test pattern */
- fprintf(domain_fp, "allow_chroot /tmp/\\?\\?\\?\\?\\?/\n");
- show_prompt("chroot('/tmp/mount/') for "
- "'/tmp/\\?\\?\\?\\?\\?/'", 0);
- fflush(stdout);
- if (fork() == 0) {
- if (chroot("/tmp/mount/") == 0)
- printf("OK\n");
- else
- printf("FAILED: %s\n", strerror(errno));
- fflush(stdout);
- _exit(0);
- }
- wait(NULL);
- fprintf(domain_fp,
- "delete allow_chroot /tmp/\\?\\?\\?\\?\\?/\n");
-
- set_profile(0, "file::chroot");
- }
-
- /* Test pivot_root(). */
- {
- int error;
- static char stack[8192];
- set_profile(3, "file::pivot_root");
- fprintf(domain_fp, "allow_pivot_root %s %s\n",
- pivot_root_dir, proc_policy_dir);
- snprintf(stack, 8191, "pivot_root('%s', '%s')", pivot_root_dir,
- proc_policy_dir);
- show_prompt(stack, 0);
- {
- const pid_t pid = ltp_clone_quick(CLONE_NEWNS, child,
- NULL);
- while (waitpid(pid, &error, __WALL) == EOF &&
- errno == EINTR)
- c++; /* Dummy. */
- }
- errno = WIFEXITED(error) ? WEXITSTATUS(error) : -1;
- if (errno == 0)
- printf("OK\n");
- else
- printf("FAILED: %s\n", strerror(errno));
-
- fprintf(domain_fp, "delete allow_pivot_root %s %s\n",
- pivot_root_dir, proc_policy_dir);
- snprintf(stack, 8191, "pivot_root('%s', '%s')", pivot_root_dir,
- proc_policy_dir);
- show_prompt(stack, 1);
- {
- const pid_t pid = ltp_clone_quick(CLONE_NEWNS, child,
- NULL);
- while (waitpid(pid, &error, __WALL) == EOF &&
- errno == EINTR)
- c++; /* Dummy. */
- }
- errno = WIFEXITED(error) ? WEXITSTATUS(error) : -1;
- if (errno == EPERM)
- printf("OK: Permission denied.\n");
- else
- printf("BUG: %s\n", strerror(errno));
-
- set_profile(2, "file::pivot_root");
- snprintf(stack, 8191, "pivot_root('%s', '%s')", pivot_root_dir,
- proc_policy_dir);
- show_prompt(stack, 0);
- {
- const pid_t pid = ltp_clone_quick(CLONE_NEWNS, child,
- NULL);
- while (waitpid(pid, &error, __WALL) == EOF &&
- errno == EINTR)
- c++; /* Dummy. */
- }
- errno = WIFEXITED(error) ? WEXITSTATUS(error) : -1;
- if (errno == 0)
- printf("OK\n");
- else
- printf("FAILED: %s\n", strerror(errno));
-
- set_profile(0, "file::pivot_root");
-
- }
-
- rmdir("/tmp/mount_move/");
- rmdir("/tmp/mount_bind/");
- rmdir("/tmp/mount/");
-
- clear_status();
- return 0;
-}
diff --git a/testcases/kernel/security/tomoyo/tomoyo_new_file_test.c b/testcases/kernel/security/tomoyo/tomoyo_new_file_test.c
deleted file mode 100644
index eb912d726..000000000
--- a/testcases/kernel/security/tomoyo/tomoyo_new_file_test.c
+++ /dev/null
@@ -1,627 +0,0 @@
-/******************************************************************************/
-/* 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 */
-/* */
-/******************************************************************************/
-/*
- * tomoyo_new_file_test.c
- *
- * Testing program for security/tomoyo/
- *
- * Copyright (C) 2005-2010 NTT DATA CORPORATION
- */
-#include "include.h"
-
-static const char *policy = "";
-
-static void show_result(int result, char should_success)
-{
- int error = errno;
- printf("%s : ", policy);
- if (should_success) {
- if (result != EOF)
- printf("OK\n");
- else
- printf("FAILED: %s\n", strerror(error));
- } else {
- if (result == EOF) {
- if (error == EPERM)
- printf("OK: Permission denied.\n");
- else
- printf("FAILED: %s\n", strerror(error));
- } else {
- printf("BUG: didn't fail.\n");
- }
- }
-}
-
-static void create2(const char *pathname)
-{
- set_profile(0, "file::create");
- set_profile(0, "file::open");
- close(creat(pathname, 0600));
- set_profile(3, "file::create");
- set_profile(3, "file::open");
- errno = 0;
-}
-
-static void mkdir2(const char *pathname)
-{
- set_profile(0, "file::mkdir");
- mkdir(pathname, 0600);
- set_profile(3, "file::mkdir");
- errno = 0;
-}
-
-static void unlink2(const char *pathname)
-{
- set_profile(0, "file::unlink");
- unlink(pathname);
- set_profile(3, "file::unlink");
- errno = 0;
-}
-
-static void rmdir2(const char *pathname)
-{
- set_profile(0, "file::rmdir");
- rmdir(pathname);
- set_profile(3, "file::rmdir");
- errno = 0;
-}
-
-static void mkfifo2(const char *pathname)
-{
- set_profile(0, "file::mkfifo");
- mkfifo(pathname, 0600);
- set_profile(3, "file::mkfifo");
- errno = 0;
-}
-
-static void stage_file_test(void)
-{
- const char buffer[] = "32768 61000";
- int pipe_fd[2] = { EOF, EOF };
- int error = 0;
- int fd;
- char pbuffer[1024];
- struct stat sbuf;
- struct sockaddr_un addr;
- struct ifreq ifreq;
- char *filename = "";
- set_profile(3, "file::execute");
- set_profile(3, "file::open");
- set_profile(3, "file::create");
- set_profile(3, "file::unlink");
- set_profile(3, "file::mkdir");
- set_profile(3, "file::rmdir");
- set_profile(3, "file::mkfifo");
- set_profile(3, "file::mksock");
- set_profile(3, "file::truncate");
- set_profile(3, "file::symlink");
- set_profile(3, "file::rewrite");
- set_profile(3, "file::mkblock");
- set_profile(3, "file::mkchar");
- set_profile(3, "file::link");
- set_profile(3, "file::rename");
- set_profile(3, "file::chmod");
- set_profile(3, "file::chown");
- set_profile(3, "file::chgrp");
- set_profile(3, "file::ioctl");
- set_profile(3, "file::chroot");
- set_profile(3, "file::mount");
- set_profile(3, "file::umount");
- set_profile(3, "file::pivot_root");
-
- policy = "allow_read /proc/sys/net/ipv4/ip_local_port_range";
- write_domain_policy(policy, 0);
- show_result(read_sysctl(TEST_SYSCTL_PATH, NULL, 0), 1);
- write_domain_policy(policy, 1);
- show_result(read_sysctl(TEST_SYSCTL_PATH, NULL, 0), 0);
-
- policy = "allow_write /proc/sys/net/ipv4/ip_local_port_range";
- write_domain_policy(policy, 0);
- show_result(write_sysctl(TEST_SYSCTL_PATH, buffer), 1);
- write_domain_policy(policy, 1);
- show_result(write_sysctl(TEST_SYSCTL_PATH, buffer), 0);
-
- policy = "allow_read/write /proc/sys/net/ipv4/ip_local_port_range";
- write_domain_policy(policy, 0);
- show_result(read_sysctl(TEST_SYSCTL_PATH, NULL, 0) &&
- write_sysctl(TEST_SYSCTL_PATH, buffer), 1);
- write_domain_policy(policy, 1);
- show_result(read_sysctl(TEST_SYSCTL_PATH, NULL, 0) &&
- write_sysctl(TEST_SYSCTL_PATH, buffer), 0);
-
- policy = "allow_read /bin/true";
- write_domain_policy(policy, 0);
- show_result(uselib("/bin/true"), 1);
- write_domain_policy(policy, 1);
- show_result(uselib("/bin/true"), 0);
-
- policy = "allow_execute /bin/true";
- write_domain_policy(policy, 0);
- fflush(stdout);
- fflush(stderr);
- if (pipe(pipe_fd) == -1)
- err(1, "pipe");
- if (fork() == 0) {
- execl("/bin/true", "/bin/true", NULL);
- if (write(pipe_fd[1], &errno, sizeof(errno)) == -1)
- err(1, "write");
- exit(0);
- }
- close(pipe_fd[1]);
- (void)read(pipe_fd[0], &error, sizeof(error));
- close(pipe_fd[0]);
- wait(NULL);
- errno = error;
- show_result(error ? EOF : 0, 1);
- write_domain_policy(policy, 1);
- fflush(stdout);
- fflush(stderr);
- if (pipe(pipe_fd) == -1)
- err(1, "pipe");
- if (fork() == 0) {
- execl("/bin/true", "/bin/true", NULL);
- if (write(pipe_fd[1], &errno, sizeof(errno)) == -1)
- err(1, "write");
- _exit(0);
- }
- close(pipe_fd[1]);
- (void)read(pipe_fd[0], &error, sizeof(error));
- close(pipe_fd[0]);
- wait(NULL);
- errno = error;
- show_result(errno ? EOF : 0, 0);
-
- policy = "allow_read /dev/null";
- write_domain_policy(policy, 0);
- fd = open("/dev/null", O_RDONLY);
- show_result(fd, 1);
- if (fd != EOF)
- close(fd);
- write_domain_policy(policy, 1);
- fd = open("/dev/null", O_RDONLY);
- show_result(fd, 0);
- if (fd != EOF)
- close(fd);
-
- policy = "allow_read /dev/null";
- write_domain_policy(policy, 0);
- fd = open("/dev/null", O_RDONLY);
- show_result(fd, 1);
- if (fd != EOF)
- close(fd);
- write_domain_policy(policy, 1);
- fd = open("/dev/null", O_RDONLY);
- show_result(fd, 0);
- if (fd != EOF)
- close(fd);
-
- policy = "allow_read /dev/null";
- write_domain_policy(policy, 0);
- fd = open("/dev/null", O_RDONLY);
- show_result(fd, 1);
- if (fd != EOF)
- close(fd);
- write_domain_policy(policy, 1);
- fd = open("/dev/null", O_RDONLY);
- show_result(fd, 0);
- if (fd != EOF)
- close(fd);
-
- policy = "allow_read /dev/null";
- write_domain_policy(policy, 0);
- fd = open("/dev/null", O_RDONLY);
- show_result(fd, 1);
- if (fd != EOF)
- close(fd);
- write_domain_policy(policy, 1);
- fd = open("/dev/null", O_RDONLY);
- show_result(fd, 0);
- if (fd != EOF)
- close(fd);
-
- set_profile(3, "file::mkfifo");
- policy = "allow_mkfifo /tmp/mknod_fifo_test 0644";
- write_domain_policy(policy, 0);
- filename = "/tmp/mknod_fifo_test";
- show_result(mknod(filename, S_IFIFO | 0644, 0), 1);
- write_domain_policy(policy, 1);
- unlink2(filename);
- show_result(mknod(filename, S_IFIFO | 0644, 0), 0);
-
- memset(pbuffer, 0, sizeof(pbuffer));
- memset(&sbuf, 0, sizeof(sbuf));
- filename = "/dev/null";
- stat(filename, &sbuf);
- snprintf(pbuffer, sizeof(pbuffer) - 1, "allow_write %s", filename);
- policy = pbuffer;
- write_domain_policy(policy, 0);
- fd = open(filename, O_WRONLY);
- show_result(fd, 1);
- if (fd != EOF)
- close(fd);
- write_domain_policy(policy, 1);
- fd = open(filename, O_WRONLY);
- show_result(fd, 0);
- if (fd != EOF)
- close(fd);
-
- policy = "allow_read/write /tmp/fifo";
- mkfifo2("/tmp/fifo");
- write_domain_policy(policy, 0);
- fd = open("/tmp/fifo", O_RDWR);
- show_result(fd, 1);
- if (fd != EOF)
- close(fd);
- write_domain_policy(policy, 1);
- fd = open("/tmp/fifo", O_RDWR);
- show_result(fd, 0);
- if (fd != EOF)
- close(fd);
-
- policy = "allow_read /dev/null";
- write_domain_policy(policy, 0);
- fd = open("/dev/null", O_RDONLY);
- show_result(fd, 1);
- if (fd != EOF)
- close(fd);
- write_domain_policy(policy, 1);
- fd = open("/dev/null", O_RDONLY);
- show_result(fd, 0);
- if (fd != EOF)
- close(fd);
-
- policy = "allow_write /dev/null";
- write_domain_policy(policy, 0);
- fd = open("/dev/null", O_WRONLY);
- show_result(fd, 1);
- if (fd != EOF)
- close(fd);
- write_domain_policy(policy, 1);
- fd = open("/dev/null", O_WRONLY);
- show_result(fd, 0);
- if (fd != EOF)
- close(fd);
-
- policy = "allow_read/write /dev/null";
- write_domain_policy(policy, 0);
- fd = open("/dev/null", O_RDWR);
- show_result(fd, 1);
- if (fd != EOF)
- close(fd);
- write_domain_policy(policy, 1);
- fd = open("/dev/null", O_RDWR);
- show_result(fd, 0);
- if (fd != EOF)
- close(fd);
-
- policy = "allow_create /tmp/open_test 0644";
- write_domain_policy(policy, 0);
- policy = "allow_write /tmp/open_test";
- write_domain_policy(policy, 0);
- fd = open("/tmp/open_test", O_WRONLY | O_CREAT | O_EXCL, 0644);
- show_result(fd, 1);
- if (fd != EOF)
- close(fd);
- unlink2("/tmp/open_test");
- write_domain_policy(policy, 1);
- fd = open("/tmp/open_test", O_WRONLY | O_CREAT | O_EXCL, 0644);
- show_result(fd, 0);
- if (fd != EOF)
- close(fd);
- unlink2("/tmp/open_test");
-
- policy = "allow_create /tmp/open_test 0644";
- write_domain_policy(policy, 1);
-
- policy = "allow_write /tmp/open_test";
- write_domain_policy(policy, 0);
- policy = "allow_create /tmp/open_test 0644";
- write_domain_policy(policy, 0);
- fd = open("/tmp/open_test", O_WRONLY | O_CREAT | O_EXCL, 0644);
- show_result(fd, 1);
- if (fd != EOF)
- close(fd);
- unlink2("/tmp/open_test");
- write_domain_policy(policy, 1);
- fd = open("/tmp/open_test", O_WRONLY | O_CREAT | O_EXCL, 0644);
- show_result(fd, 0);
- if (fd != EOF)
- close(fd);
- unlink2("/tmp/open_test");
- policy = "allow_write /tmp/open_test";
- write_domain_policy(policy, 1);
-
- filename = "/tmp/truncate_test";
- create2(filename);
-
- policy = "allow_truncate /tmp/truncate_test";
- write_domain_policy(policy, 0);
- policy = "allow_write /tmp/truncate_test";
- write_domain_policy(policy, 0);
- fd = open(filename, O_WRONLY | O_TRUNC);
- show_result(fd, 1);
- if (fd != EOF)
- close(fd);
- write_domain_policy(policy, 1);
- fd = open(filename, O_WRONLY | O_TRUNC);
- show_result(fd, 0);
- if (fd != EOF)
- close(fd);
- policy = "allow_truncate /tmp/truncate_test";
- write_domain_policy(policy, 1);
-
- policy = "allow_write /tmp/truncate_test";
- write_domain_policy(policy, 0);
- policy = "allow_truncate /tmp/truncate_test";
- write_domain_policy(policy, 0);
- fd = open(filename, O_WRONLY | O_TRUNC);
- show_result(fd, 1);
- if (fd != EOF)
- close(fd);
- write_domain_policy(policy, 1);
- fd = open(filename, O_WRONLY | O_TRUNC);
- show_result(fd, 0);
- if (fd != EOF)
- close(fd);
- policy = "allow_write /tmp/truncate_test";
- write_domain_policy(policy, 1);
-
- policy = "allow_truncate /tmp/truncate_test";
- write_domain_policy(policy, 0);
- show_result(truncate(filename, 0), 1);
- write_domain_policy(policy, 1);
- show_result(truncate(filename, 0), 0);
-
- policy = "allow_truncate /tmp/truncate_test";
- write_domain_policy(policy, 0);
- set_profile(0, "file::open");
- fd = open(filename, O_WRONLY);
- set_profile(3, "file::open");
- show_result(ftruncate(fd, 0), 1);
- write_domain_policy(policy, 1);
- show_result(ftruncate(fd, 0), 0);
- if (fd != EOF)
- close(fd);
-
- unlink2(filename);
-
- policy = "allow_create /tmp/mknod_reg_test 0644";
- write_domain_policy(policy, 0);
- filename = "/tmp/mknod_reg_test";
- show_result(mknod(filename, S_IFREG | 0644, 0), 1);
- write_domain_policy(policy, 1);
- unlink2(filename);
- show_result(mknod(filename, S_IFREG | 0644, 0), 0);
-
- policy = "allow_mkchar /tmp/mknod_chr_test 0644 1 3";
- write_domain_policy(policy, 0);
- filename = "/tmp/mknod_chr_test";
- show_result(mknod(filename, S_IFCHR | 0644, MKDEV(1, 3)), 1);
- write_domain_policy(policy, 1);
- unlink2(filename);
- show_result(mknod(filename, S_IFCHR | 0644, MKDEV(1, 3)), 0);
-
- policy = "allow_mkblock /tmp/mknod_blk_test 0644 1 0";
- write_domain_policy(policy, 0);
- filename = "/tmp/mknod_blk_test";
- show_result(mknod(filename, S_IFBLK | 0644, MKDEV(1, 0)), 1);
- write_domain_policy(policy, 1);
- unlink2(filename);
- show_result(mknod(filename, S_IFBLK | 0644, MKDEV(1, 0)), 0);
-
- policy = "allow_mkfifo /tmp/mknod_fifo_test 0644";
- write_domain_policy(policy, 0);
- filename = "/tmp/mknod_fifo_test";
- show_result(mknod(filename, S_IFIFO | 0644, 0), 1);
- write_domain_policy(policy, 1);
- unlink2(filename);
- show_result(mknod(filename, S_IFIFO | 0644, 0), 0);
-
- policy = "allow_mksock /tmp/mknod_sock_test 0644";
- write_domain_policy(policy, 0);
- filename = "/tmp/mknod_sock_test";
- show_result(mknod(filename, S_IFSOCK | 0644, 0), 1);
- write_domain_policy(policy, 1);
- unlink2(filename);
- show_result(mknod(filename, S_IFSOCK | 0644, 0), 0);
-
- policy = "allow_mkdir /tmp/mkdir_test/ 0600";
- write_domain_policy(policy, 0);
- filename = "/tmp/mkdir_test";
- show_result(mkdir(filename, 0600), 1);
- write_domain_policy(policy, 1);
- rmdir2(filename);
- show_result(mkdir(filename, 0600), 0);
-
- policy = "allow_rmdir /tmp/rmdir_test/";
- write_domain_policy(policy, 0);
- filename = "/tmp/rmdir_test";
- mkdir2(filename);
- show_result(rmdir(filename), 1);
- write_domain_policy(policy, 1);
- mkdir2(filename);
- show_result(rmdir(filename), 0);
- rmdir2(filename);
-
- policy = "allow_unlink /tmp/unlink_test";
- write_domain_policy(policy, 0);
- filename = "/tmp/unlink_test";
- create2(filename);
- show_result(unlink(filename), 1);
- write_domain_policy(policy, 1);
- create2(filename);
- show_result(unlink(filename), 0);
- unlink2(filename);
-
- policy = "allow_symlink /tmp/symlink_source_test";
- write_domain_policy(policy, 0);
- filename = "/tmp/symlink_source_test";
- show_result(symlink("/tmp/symlink_dest_test", filename), 1);
- write_domain_policy(policy, 1);
- unlink2(filename);
- show_result(symlink("/tmp/symlink_dest_test", filename), 0);
-
- policy = "allow_symlink /tmp/symlink_source_test";
- write_domain_policy(policy, 0);
- filename = "/tmp/symlink_source_test";
- show_result(symlink("/tmp/symlink_dest_test", filename), 1);
- write_domain_policy(policy, 1);
- unlink2(filename);
- show_result(symlink("/tmp/symlink_dest_test", filename), 0);
-
- policy = "allow_symlink /tmp/symlink_source_test";
- write_domain_policy(policy, 0);
- filename = "/tmp/symlink_source_test";
- show_result(symlink("/tmp/symlink_dest_test", filename), 1);
- write_domain_policy(policy, 1);
- unlink2(filename);
- show_result(symlink("/tmp/symlink_dest_test", filename), 0);
-
- policy = "allow_symlink /tmp/symlink_source_test";
- write_domain_policy(policy, 0);
- filename = "/tmp/symlink_source_test";
- show_result(symlink("/tmp/symlink_dest_test", filename), 1);
- write_domain_policy(policy, 1);
- unlink2(filename);
- show_result(symlink("/tmp/symlink_dest_test", filename), 0);
-
- policy = "allow_symlink /tmp/symlink_source_test";
- write_domain_policy(policy, 0);
- filename = "/tmp/symlink_source_test";
- show_result(symlink("/tmp/symlink_dest_test", filename), 1);
- write_domain_policy(policy, 1);
- unlink2(filename);
- show_result(symlink("/tmp/symlink_dest_test", filename), 0);
-
- policy = "allow_link /tmp/link_source_test /tmp/link_dest_test";
- write_domain_policy(policy, 0);
- filename = "/tmp/link_source_test";
- create2(filename);
- show_result(link(filename, "/tmp/link_dest_test"), 1);
- write_domain_policy(policy, 1);
- unlink2("/tmp/link_dest_test");
- show_result(link(filename, "/tmp/link_dest_test"), 0);
- unlink2(filename);
-
- policy = "allow_rename /tmp/rename_source_test /tmp/rename_dest_test";
- write_domain_policy(policy, 0);
- filename = "/tmp/rename_source_test";
- create2(filename);
- show_result(rename(filename, "/tmp/rename_dest_test"), 1);
- write_domain_policy(policy, 1);
- unlink2("/tmp/rename_dest_test");
- create2(filename);
- show_result(rename(filename, "/tmp/rename_dest_test"), 0);
- unlink2(filename);
-
- policy = "allow_mksock /tmp/socket_test 0755";
- write_domain_policy(policy, 0);
- filename = "/tmp/socket_test";
- memset(&addr, 0, sizeof(addr));
- addr.sun_family = AF_UNIX;
- strncpy(addr.sun_path, filename, sizeof(addr.sun_path) - 1);
- fd = socket(AF_UNIX, SOCK_STREAM, 0);
- show_result(bind(fd, (struct sockaddr *)&addr, sizeof(addr)), 1);
- if (fd != EOF)
- close(fd);
- write_domain_policy(policy, 1);
- unlink2(filename);
- fd = socket(AF_UNIX, SOCK_STREAM, 0);
- show_result(bind(fd, (struct sockaddr *)&addr, sizeof(addr)), 0);
- if (fd != EOF)
- close(fd);
-
- filename = "/tmp/rewrite_test";
- create2(filename);
- policy = "allow_read/write /tmp/rewrite_test";
- write_domain_policy(policy, 0);
- write_exception_policy("deny_rewrite /tmp/rewrite_test", 0);
- policy = "allow_truncate /tmp/rewrite_test";
- write_domain_policy(policy, 0);
-
- fd = open(filename, O_RDONLY);
- show_result(fd, 1);
- if (fd != EOF)
- close(fd);
-
- fd = open(filename, O_WRONLY | O_APPEND);
- show_result(fd, 1);
- if (fd != EOF)
- close(fd);
-
- fd = open(filename, O_WRONLY);
- show_result(fd, 0);
- if (fd != EOF)
- close(fd);
-
- fd = open(filename, O_WRONLY | O_TRUNC);
- show_result(fd, 0);
- if (fd != EOF)
- close(fd);
-
- fd = open(filename, O_WRONLY | O_TRUNC | O_APPEND);
- show_result(fd, 0);
- if (fd != EOF)
- close(fd);
-
- show_result(truncate(filename, 0), 0);
-
- set_profile(0, "file::open");
- fd = open(filename, O_WRONLY | O_APPEND);
- set_profile(3, "file::open");
- show_result(ftruncate(fd, 0), 0);
-
- show_result(fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) & ~O_APPEND), 0);
- if (fd != EOF)
- close(fd);
-
- write_domain_policy(policy, 1);
-
- policy = "allow_read/write /tmp/rewrite_test";
- write_domain_policy(policy, 1);
- write_exception_policy("deny_rewrite /tmp/rewrite_test", 1);
-
- unlink2(filename);
-
- policy = "allow_ioctl socket:[family=2:type=2:protocol=17] "
- "35122-35124";
- write_domain_policy(policy, 0);
- fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
- memset(&ifreq, 0, sizeof(ifreq));
- snprintf(ifreq.ifr_name, sizeof(ifreq.ifr_name) - 1, "lo");
- show_result(ioctl(fd, 35123, &ifreq), 1);
- write_domain_policy(policy, 1);
- policy = "allow_ioctl " "socket:[family=2:type=2:protocol=17] 0-35122";
- write_domain_policy(policy, 0);
- show_result(ioctl(fd, 35123, &ifreq), 0);
- write_domain_policy(policy, 1);
- if (fd != EOF)
- close(fd);
-}
-
-int main(void)
-{
- tomoyo_test_init();
- fprintf(domain_fp, "%s /bin/true\n", self_domain);
- fprintf(domain_fp, "use_profile 255\n");
- fprintf(domain_fp, "select pid=%u\n", pid);
- fprintf(profile_fp, "255-PREFERENCE::audit={ max_reject_log=1024 }\n");
- stage_file_test();
- fprintf(domain_fp, "use_profile 0\n");
- clear_status();
- return 0;
-}
diff --git a/testcases/kernel/security/tomoyo/tomoyo_new_test.c b/testcases/kernel/security/tomoyo/tomoyo_new_test.c
deleted file mode 100644
index a1ab259e5..000000000
--- a/testcases/kernel/security/tomoyo/tomoyo_new_test.c
+++ /dev/null
@@ -1,652 +0,0 @@
-/******************************************************************************/
-/* 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 */
-/* */
-/******************************************************************************/
-/*
- * tomoyo_new_test.c
- *
- * Testing program for security/tomoyo/
- *
- * Copyright (C) 2005-2010 NTT DATA CORPORATION
- */
-#include "include.h"
-
-static int result;
-static int error;
-
-static void show_result(const char *test, int should_success)
-{
- error = errno;
- printf("%s : ", test);
- if (should_success) {
- if (error == 0)
- printf("OK (%d)\n", result);
- else
- printf("FAILED: %s\n", strerror(error));
- } else {
- if (error == 0)
- printf("BUG: Didn't fail (%d)\n", result);
- else if (error == EPERM)
- printf("OK: permission denied\n");
- else
- printf("FAILED: %s\n", strerror(error));
- }
-}
-
-static void test_read_etc_fstab(void)
-{
- result = open("/etc/fstab", O_RDONLY);
-}
-
-static void test_write_dev_null(void)
-{
- result = open("/dev/null", O_WRONLY);
-}
-
-static void cleanup_file_open(void)
-{
- if (result != EOF)
- close(result);
-}
-
-static void test_mkdir_testdir(void)
-{
- result = mkdir("/tmp/testdir", 0755);
-}
-
-static void cleanup_mkdir_testdir(void)
-{
- rmdir("/tmp/testdir");
-}
-
-static void setup_mkdir_testdir(void)
-{
- mkdir("/tmp/testdir", 0755);
-}
-
-static void test_rmdir_testdir(void)
-{
- result = rmdir("/tmp/testdir");
-}
-
-static void setup_execute_bin_true(void)
-{
- fprintf(domain_fp, "%s /bin/true\n", self_domain);
- fprintf(domain_fp, "use_profile 0\n");
- fprintf(domain_fp, "select pid=%u\n", pid);
-}
-
-static void cleanup_execute_bin_true(void)
-{
- wait(NULL);
- fprintf(domain_fp, "delete %s /bin/true\n", self_domain);
- fprintf(domain_fp, "select pid=%u\n", pid);
-}
-
-static void test_execute_bin_true(void)
-{
- char *argv[] = { "/bin/true", NULL };
- char *envp[] = { "HOME=/", NULL };
- int pipe_fd[2] = { EOF, EOF };
- if (pipe(pipe_fd) == -1)
- err(1, "pipe");
- switch (fork()) {
- case 0:
- execve("/bin/true", argv, envp);
- error = errno;
- if (write(pipe_fd[1], &error, sizeof(error)) == -1)
- err(1, "write");
- _exit(0);
- break;
- case -1:
- error = ENOMEM;
- break;
- }
- close(pipe_fd[1]);
- (void)read(pipe_fd[0], &error, sizeof(error));
- close(pipe_fd[0]);
- result = error ? EOF : 0;
- errno = error;
-}
-
-static void test_chmod_dev_null(void)
-{
- result = chmod("/dev/null", 0666);
-}
-
-static void test_chown_dev_null(void)
-{
- result = chown("/dev/null", 0, -1);
-}
-
-static void test_chgrp_dev_null(void)
-{
- result = chown("/dev/null", -1, 0);
-}
-
-static void test_ioctl_dev_null(void)
-{
- int fd = open("/dev/null", O_RDWR);
- errno = 0;
- result = ioctl(fd, 0x5451, NULL);
- error = errno;
- close(fd);
- errno = error;
-}
-
-static void setup_chmod_group(void)
-{
- write_exception_policy("path_group CHMOD_TARGET /dev/null", 0);
- write_exception_policy("number_group CHMOD_MODES 0666", 0);
-}
-
-static void cleanup_chmod_group(void)
-{
- write_exception_policy("path_group CHMOD_TARGET /dev/null", 1);
- write_exception_policy("number_group CHMOD_MODES 0666", 1);
-}
-
-static void setup_chown_group(void)
-{
- write_exception_policy("path_group CHOWN_TARGET /dev/\\*", 0);
- write_exception_policy("number_group CHOWN_IDS 0x0-0xFFFE", 0);
-}
-
-static void cleanup_chown_group(void)
-{
- write_exception_policy("path_group CHOWN_TARGET /dev/\\*", 1);
- write_exception_policy("number_group CHOWN_IDS 0x0-0xFFFE", 1);
-}
-
-static void setup_ioctl_group(void)
-{
- write_exception_policy("path_group IOCTL_TARGET /dev/\\*", 0);
- write_exception_policy("number_group IOCTL_NUMBERS 0x5450-0x5452", 0);
-}
-
-static void cleanup_ioctl_group(void)
-{
- write_exception_policy("path_group IOCTL_TARGET /dev/\\*", 1);
- write_exception_policy("number_group IOCTL_NUMBERS 0x5450-0x5452", 1);
-}
-
-static void setup_open_group(void)
-{
- write_exception_policy("path_group READABLE /etc/\\*", 0);
- write_exception_policy("number_group READABLE_IDS 0-0xFFF", 0);
-}
-
-static void cleanup_open_group(void)
-{
- cleanup_file_open();
- write_exception_policy("path_group READABLE /etc/\\*", 1);
- write_exception_policy("number_group READABLE_IDS 0-0xFFF", 1);
-}
-
-static void test_file_open_0(void)
-{
- result = open("/tmp/testfile0", O_RDONLY, 0600);
-}
-
-static void test_file_open_1(void)
-{
- result = open("/tmp/testfile1", O_CREAT | O_RDONLY, 0600);
-}
-
-static void test_file_open_2(void)
-{
- result = open("/tmp/testfile2", O_TRUNC | O_RDONLY, 0600);
-}
-
-static void test_file_open_3(void)
-{
- result = open("/tmp/testfile3", O_TRUNC | O_CREAT | O_RDONLY, 0600);
-}
-
-static void test_file_open_4(void)
-{
- result = open("/tmp/testfile4", O_APPEND | O_RDONLY, 0600);
-}
-
-static void test_file_open_5(void)
-{
- result = open("/tmp/testfile5", O_APPEND | O_CREAT | O_RDONLY, 0600);
-}
-
-static void test_file_open_6(void)
-{
- result = open("/tmp/testfile6", O_APPEND | O_TRUNC | O_RDONLY, 0600);
-}
-
-static void test_file_open_7(void)
-{
- result = open("/tmp/testfile7",
- O_APPEND | O_TRUNC | O_CREAT | O_RDONLY, 0600);
-}
-
-static void test_file_open_8(void)
-{
- result = open("/tmp/testfile8", O_WRONLY, 0600);
-}
-
-static void test_file_open_9(void)
-{
- result = open("/tmp/testfile9", O_CREAT | O_WRONLY, 0600);
-}
-
-static void test_file_open_10(void)
-{
- result = open("/tmp/testfile10", O_TRUNC | O_WRONLY, 0600);
-}
-
-static void test_file_open_11(void)
-{
- result = open("/tmp/testfile11", O_TRUNC | O_CREAT | O_WRONLY, 0600);
-}
-
-static void test_file_open_12(void)
-{
- result = open("/tmp/testfile12", O_APPEND | O_WRONLY, 0600);
-}
-
-static void test_file_open_13(void)
-{
- result = open("/tmp/testfile13", O_APPEND | O_CREAT | O_WRONLY, 0600);
-}
-
-static void test_file_open_14(void)
-{
- result = open("/tmp/testfile14", O_APPEND | O_TRUNC | O_WRONLY, 0600);
-}
-
-static void test_file_open_15(void)
-{
- result = open("/tmp/testfile15",
- O_APPEND | O_TRUNC | O_CREAT | O_WRONLY, 0600);
-}
-
-static void test_file_open_16(void)
-{
- result = open("/tmp/testfile16", O_RDWR, 0600);
-}
-
-static void test_file_open_17(void)
-{
- result = open("/tmp/testfile17", O_CREAT | O_RDWR, 0600);
-}
-
-static void test_file_open_18(void)
-{
- result = open("/tmp/testfile18", O_TRUNC | O_RDWR, 0600);
-}
-
-static void test_file_open_19(void)
-{
- result = open("/tmp/testfile19", O_TRUNC | O_CREAT | O_RDWR, 0600);
-}
-
-static void test_file_open_20(void)
-{
- result = open("/tmp/testfile20", O_APPEND | O_RDWR, 0600);
-}
-
-static void test_file_open_21(void)
-{
- result = open("/tmp/testfile21", O_APPEND | O_CREAT | O_RDWR, 0600);
-}
-
-static void test_file_open_22(void)
-{
- result = open("/tmp/testfile22", O_APPEND | O_TRUNC | O_RDWR, 0600);
-}
-
-static void test_file_open_23(void)
-{
- result = open("/tmp/testfile23", O_APPEND | O_TRUNC | O_CREAT | O_RDWR,
- 0600);
-}
-
-static void setup_test_file(void)
-{
- int i;
- char buffer[32];
- buffer[31] = '\0';
- for (i = 0; i < 24; i += 2) {
- snprintf(buffer, sizeof(buffer) - 1, "/tmp/testfile%u", i);
- close(open(buffer, O_WRONLY | O_CREAT, 0600));
- }
- write_exception_policy("deny_rewrite /tmp/testfile\\$", 0);
-}
-
-static void setup_test_file_truncate(void)
-{
- setup_test_file();
- write_domain_policy("allow_truncate /tmp/testfile\\$", 0);
- set_profile(3, "file::truncate");
-}
-
-static void setup_all_test_file(void)
-{
- int i;
- char buffer[32];
- buffer[31] = '\0';
- for (i = 0; i < 24; i++) {
- snprintf(buffer, sizeof(buffer) - 1, "/tmp/testfile%u", i);
- close(open(buffer, O_WRONLY | O_CREAT, 0600));
- }
- write_exception_policy("deny_rewrite /tmp/testfile\\$", 0);
-}
-
-static void setup_all_test_file_truncate(void)
-{
- setup_all_test_file();
- write_domain_policy("allow_truncate /tmp/testfile\\$", 0);
- set_profile(3, "file::truncate");
-}
-
-static void cleanup_test_file(void)
-{
- int i;
- char buffer[32];
- buffer[31] = '\0';
- for (i = 0; i < 24; i++) {
- snprintf(buffer, sizeof(buffer) - 1, "/tmp/testfile%u", i);
- unlink(buffer);
- }
- write_exception_policy("deny_rewrite /tmp/testfile\\$", 1);
- cleanup_file_open();
-}
-
-static void cleanup_test_file_truncate(void)
-{
- cleanup_test_file();
- write_domain_policy("allow_truncate /tmp/testfile\\$", 1);
- set_profile(0, "file::truncate");
-}
-
-static struct test_struct {
- void (*do_setup) (void);
- void (*do_test) (void);
- void (*do_cleanup) (void);
- const char *name;
- const char *policy;
-} tests[] = {
- {
- NULL, test_read_etc_fstab, cleanup_file_open, "file::open",
- "allow_read /etc/fstab"}, {
- NULL, test_read_etc_fstab, cleanup_file_open, "file::open",
- "allow_read /etc/fstab"}, {
- NULL, test_read_etc_fstab, cleanup_file_open, "file::open",
- "allow_read /etc/fstab"}, {
- setup_open_group, test_read_etc_fstab, cleanup_open_group,
- "file::open", "allow_read @READABLE"}, {
- NULL, test_write_dev_null, cleanup_file_open, "file::open",
- "allow_write /dev/null"}, {
- NULL, test_write_dev_null, cleanup_file_open, "file::open",
- "allow_write /dev/null"}, {
- NULL, test_write_dev_null, cleanup_file_open, "file::open",
- "allow_write /dev/null"}, {
- cleanup_mkdir_testdir, test_mkdir_testdir,
- cleanup_mkdir_testdir, "file::mkdir",
- "allow_mkdir /tmp/testdir/ 0755"}, {
- cleanup_mkdir_testdir, test_mkdir_testdir,
- cleanup_mkdir_testdir, "file::mkdir",
- "allow_mkdir /tmp/testdir/ 0755"}, {
- cleanup_mkdir_testdir, test_mkdir_testdir,
- cleanup_mkdir_testdir, "file::mkdir",
- "allow_mkdir /tmp/testdir/ 0755"}, {
- setup_mkdir_testdir, test_rmdir_testdir, cleanup_mkdir_testdir,
- "file::rmdir", "allow_rmdir /tmp/testdir/"}, {
- setup_mkdir_testdir, test_rmdir_testdir, cleanup_mkdir_testdir,
- "file::rmdir", "allow_rmdir /tmp/testdir/"}, {
- setup_mkdir_testdir, test_rmdir_testdir, cleanup_mkdir_testdir,
- "file::rmdir", "allow_rmdir /tmp/testdir/"}, {
- setup_execute_bin_true, test_execute_bin_true,
- cleanup_execute_bin_true, "file::execute",
- "allow_execute /bin/true"}, {
- setup_execute_bin_true, test_execute_bin_true,
- cleanup_execute_bin_true, "file::execute",
- "allow_execute /bin/true"}, {
- setup_execute_bin_true, test_execute_bin_true,
- cleanup_execute_bin_true, "file::execute",
- "allow_execute /bin/true"}, {
- NULL, test_chmod_dev_null, NULL, "file::chmod",
- "allow_chmod /dev/null 0666"}, {
- NULL, test_chown_dev_null, NULL, "file::chown",
- "allow_chown /dev/null 0"}, {
- NULL, test_chgrp_dev_null, NULL, "file::chgrp",
- "allow_chgrp /dev/null 0"}, {
- NULL, test_ioctl_dev_null, NULL, "file::ioctl",
- "allow_ioctl /dev/null 0x5451"}, {
- setup_chmod_group, test_chmod_dev_null, cleanup_chmod_group,
- "file::chmod", "allow_chmod @CHMOD_TARGET @CHMOD_MODES"}, {
- setup_chown_group, test_chown_dev_null, cleanup_chown_group,
- "file::chown", "allow_chown @CHOWN_TARGET @CHOWN_IDS"}, {
- setup_chown_group, test_chgrp_dev_null, cleanup_chown_group,
- "file::chgrp", "allow_chgrp @CHOWN_TARGET @CHOWN_IDS"}, {
- setup_ioctl_group, test_ioctl_dev_null, cleanup_ioctl_group,
- "file::ioctl", "allow_ioctl @IOCTL_TARGET @IOCTL_NUMBERS"},
- {
- setup_test_file, test_file_open_0, cleanup_test_file,
- "file::open", "allow_read /tmp/testfile0"}, {
- setup_test_file, test_file_open_1, cleanup_test_file,
- "file::open", "allow_read /tmp/testfile1"}, {
- setup_test_file, test_file_open_1, cleanup_test_file,
- "file::create", "allow_create /tmp/testfile1 0600"}, {
- setup_test_file, test_file_open_2, cleanup_test_file,
- "file::open", "allow_read /tmp/testfile2"}, {
- setup_test_file, test_file_open_2, cleanup_test_file,
- "file::truncate", "allow_truncate /tmp/testfile2"}, {
- setup_test_file_truncate, test_file_open_2,
- cleanup_test_file_truncate, "file::rewrite",
- "allow_rewrite /tmp/testfile2"}, {
- setup_test_file, test_file_open_3, cleanup_test_file,
- "file::open", "allow_read /tmp/testfile3"}, {
- setup_test_file, test_file_open_3, cleanup_test_file,
- "file::create", "allow_create /tmp/testfile3 0600"}, {
- setup_test_file, test_file_open_4, cleanup_test_file,
- "file::open", "allow_read /tmp/testfile4"}, {
- setup_test_file, test_file_open_5, cleanup_test_file,
- "file::open", "allow_read /tmp/testfile5"}, {
- setup_test_file, test_file_open_5, cleanup_test_file,
- "file::create", "allow_create /tmp/testfile5 0600"}, {
- setup_test_file, test_file_open_6, cleanup_test_file,
- "file::open", "allow_read /tmp/testfile6"}, {
- setup_test_file, test_file_open_6, cleanup_test_file,
- "file::truncate", "allow_truncate /tmp/testfile6"}, {
- setup_test_file_truncate, test_file_open_6,
- cleanup_test_file_truncate, "file::rewrite",
- "allow_rewrite /tmp/testfile6"}, {
- setup_test_file, test_file_open_7, cleanup_test_file,
- "file::open", "allow_read /tmp/testfile7"}, {
- setup_test_file, test_file_open_7, cleanup_test_file,
- "file::create", "allow_create /tmp/testfile7 0600"}, {
- setup_test_file, test_file_open_8, cleanup_test_file,
- "file::open", "allow_write /tmp/testfile8"}, {
- setup_test_file, test_file_open_8, cleanup_test_file,
- "file::rewrite", "allow_rewrite /tmp/testfile8"}, {
- setup_test_file, test_file_open_9, cleanup_test_file,
- "file::open", "allow_write /tmp/testfile9"}, {
- setup_test_file, test_file_open_9, cleanup_test_file,
- "file::create", "allow_create /tmp/testfile9 0600"}, {
- setup_test_file, test_file_open_9, cleanup_test_file,
- "file::rewrite", "allow_rewrite /tmp/testfile9"}, {
- setup_test_file, test_file_open_10, cleanup_test_file,
- "file::open", "allow_write /tmp/testfile10"}, {
- setup_test_file, test_file_open_10, cleanup_test_file,
- "file::truncate", "allow_truncate /tmp/testfile10"}, {
- setup_test_file, test_file_open_10, cleanup_test_file,
- "file::rewrite", "allow_rewrite /tmp/testfile10"}, {
- setup_test_file, test_file_open_11, cleanup_test_file,
- "file::open", "allow_write /tmp/testfile11"}, {
- setup_test_file, test_file_open_11, cleanup_test_file,
- "file::create", "allow_create /tmp/testfile11 0600"}, {
- setup_test_file, test_file_open_11, cleanup_test_file,
- "file::rewrite", "allow_rewrite /tmp/testfile11"}, {
- setup_test_file, test_file_open_12, cleanup_test_file,
- "file::open", "allow_write /tmp/testfile12"}, {
- setup_test_file, test_file_open_13, cleanup_test_file,
- "file::open", "allow_write /tmp/testfile13"}, {
- setup_test_file, test_file_open_13, cleanup_test_file,
- "file::create", "allow_create /tmp/testfile13 0600"}, {
- setup_test_file, test_file_open_14, cleanup_test_file,
- "file::open", "allow_write /tmp/testfile14"}, {
- setup_test_file, test_file_open_14, cleanup_test_file,
- "file::truncate", "allow_truncate /tmp/testfile14"}, {
- setup_test_file_truncate, test_file_open_14,
- cleanup_test_file_truncate, "file::rewrite",
- "allow_rewrite /tmp/testfile14"}, {
- setup_test_file, test_file_open_15, cleanup_test_file,
- "file::open", "allow_write /tmp/testfile15"}, {
- setup_test_file, test_file_open_15, cleanup_test_file,
- "file::create", "allow_create /tmp/testfile15 0600"}, {
- setup_test_file, test_file_open_16, cleanup_test_file,
- "file::open", "allow_read/write /tmp/testfile16"}, {
- setup_test_file, test_file_open_16, cleanup_test_file,
- "file::rewrite", "allow_rewrite /tmp/testfile16"}, {
- setup_test_file, test_file_open_17, cleanup_test_file,
- "file::open", "allow_read/write /tmp/testfile17"}, {
- setup_test_file, test_file_open_17, cleanup_test_file,
- "file::create", "allow_create /tmp/testfile17 0600"}, {
- setup_test_file, test_file_open_17, cleanup_test_file,
- "file::rewrite", "allow_rewrite /tmp/testfile17"}, {
- setup_test_file, test_file_open_18, cleanup_test_file,
- "file::open", "allow_read/write /tmp/testfile18"}, {
- setup_test_file, test_file_open_18, cleanup_test_file,
- "file::truncate", "allow_truncate /tmp/testfile18"}, {
- setup_test_file, test_file_open_18, cleanup_test_file,
- "file::rewrite", "allow_rewrite /tmp/testfile18"}, {
- setup_test_file, test_file_open_19, cleanup_test_file,
- "file::open", "allow_read/write /tmp/testfile19"}, {
- setup_test_file, test_file_open_19, cleanup_test_file,
- "file::create", "allow_create /tmp/testfile19 0600"}, {
- setup_test_file, test_file_open_19, cleanup_test_file,
- "file::rewrite", "allow_rewrite /tmp/testfile19"}, {
- setup_test_file, test_file_open_20, cleanup_test_file,
- "file::open", "allow_read/write /tmp/testfile20"}, {
- setup_test_file, test_file_open_21, cleanup_test_file,
- "file::open", "allow_read/write /tmp/testfile21"}, {
- setup_test_file, test_file_open_21, cleanup_test_file,
- "file::create", "allow_create /tmp/testfile21 0600"}, {
- setup_test_file, test_file_open_22, cleanup_test_file,
- "file::open", "allow_read/write /tmp/testfile22"}, {
- setup_test_file, test_file_open_22, cleanup_test_file,
- "file::truncate", "allow_truncate /tmp/testfile22"}, {
- setup_test_file_truncate, test_file_open_22,
- cleanup_test_file_truncate, "file::rewrite",
- "allow_rewrite /tmp/testfile22"}, {
- setup_test_file, test_file_open_23, cleanup_test_file,
- "file::open", "allow_read/write /tmp/testfile23"}, {
- setup_test_file, test_file_open_23, cleanup_test_file,
- "file::create", "allow_create /tmp/testfile23 0600"}, {
- setup_all_test_file, test_file_open_0, cleanup_test_file,
- "file::open", "allow_read /tmp/testfile0"}, {
- setup_all_test_file, test_file_open_2, cleanup_test_file,
- "file::open", "allow_read /tmp/testfile2"}, {
- setup_all_test_file, test_file_open_2, cleanup_test_file,
- "file::truncate", "allow_truncate /tmp/testfile2"}, {
- setup_all_test_file_truncate, test_file_open_2,
- cleanup_test_file_truncate, "file::rewrite",
- "allow_rewrite /tmp/testfile2"}, {
- setup_all_test_file, test_file_open_4, cleanup_test_file,
- "file::open", "allow_read /tmp/testfile4"}, {
- setup_all_test_file, test_file_open_6, cleanup_test_file,
- "file::open", "allow_read /tmp/testfile6"}, {
- setup_all_test_file, test_file_open_6, cleanup_test_file,
- "file::truncate", "allow_truncate /tmp/testfile6"}, {
- setup_all_test_file_truncate, test_file_open_6,
- cleanup_test_file_truncate, "file::rewrite",
- "allow_rewrite /tmp/testfile6"}, {
- setup_all_test_file, test_file_open_8, cleanup_test_file,
- "file::open", "allow_write /tmp/testfile8"}, {
- setup_all_test_file, test_file_open_8, cleanup_test_file,
- "file::rewrite", "allow_rewrite /tmp/testfile8"}, {
- setup_all_test_file, test_file_open_10, cleanup_test_file,
- "file::open", "allow_write /tmp/testfile10"}, {
- setup_all_test_file, test_file_open_10, cleanup_test_file,
- "file::truncate", "allow_truncate /tmp/testfile10"}, {
- setup_all_test_file, test_file_open_10, cleanup_test_file,
- "file::rewrite", "allow_rewrite /tmp/testfile10"}, {
- setup_all_test_file, test_file_open_12, cleanup_test_file,
- "file::open", "allow_write /tmp/testfile12"}, {
- setup_all_test_file, test_file_open_14, cleanup_test_file,
- "file::open", "allow_write /tmp/testfile14"}, {
- setup_all_test_file, test_file_open_14, cleanup_test_file,
- "file::truncate", "allow_truncate /tmp/testfile14"}, {
- setup_all_test_file_truncate, test_file_open_14,
- cleanup_test_file_truncate, "file::rewrite",
- "allow_rewrite /tmp/testfile14"}, {
- setup_all_test_file, test_file_open_16, cleanup_test_file,
- "file::open", "allow_read/write /tmp/testfile16"}, {
- setup_all_test_file, test_file_open_16, cleanup_test_file,
- "file::rewrite", "allow_rewrite /tmp/testfile16"}, {
- setup_all_test_file, test_file_open_18, cleanup_test_file,
- "file::open", "allow_read/write /tmp/testfile18"}, {
- setup_all_test_file, test_file_open_18, cleanup_test_file,
- "file::truncate", "allow_truncate /tmp/testfile18"}, {
- setup_all_test_file, test_file_open_18, cleanup_test_file,
- "file::rewrite", "allow_rewrite /tmp/testfile18"}, {
- setup_all_test_file, test_file_open_20, cleanup_test_file,
- "file::open", "allow_read/write /tmp/testfile20"}, {
- setup_all_test_file, test_file_open_22, cleanup_test_file,
- "file::open", "allow_read/write /tmp/testfile22"}, {
- setup_all_test_file, test_file_open_22, cleanup_test_file,
- "file::truncate", "allow_truncate /tmp/testfile22"}, {
- setup_all_test_file_truncate, test_file_open_22,
- cleanup_test_file_truncate, "file::rewrite",
- "allow_rewrite /tmp/testfile22"}, {
- NULL}
-};
-
-int main(void)
-{
- int i;
- tomoyo_test_init();
- for (i = 0; tests[i].do_test; i++) {
- int trial;
- for (trial = 0; trial < 2; trial++) {
- int should_fail;
- for (should_fail = 0; should_fail < 2; should_fail++) {
- if (tests[i].do_setup)
- tests[i].do_setup();
- if (!should_fail)
- write_domain_policy(tests[i].policy, 0);
- set_profile(3, tests[i].name);
- tests[i].do_test();
- show_result(tests[i].policy, !should_fail);
- set_profile(0, tests[i].name);
- if (tests[i].do_cleanup)
- tests[i].do_cleanup();
- if (!should_fail)
- write_domain_policy(tests[i].policy, 1);
- }
- }
- }
- for (i = 0; tests[i].do_test; i++) {
- int mode;
- for (mode = 0; mode < 4; mode++) {
- if (tests[i].do_setup)
- tests[i].do_setup();
- set_profile(mode, tests[i].name);
- tests[i].do_test();
- show_result(tests[i].name, 1);
- set_profile(0, tests[i].name);
- if (tests[i].do_cleanup)
- tests[i].do_cleanup();
- }
- }
- fprintf(domain_fp, "delete %s\n", self_domain);
- return 0;
-}
diff --git a/testcases/kernel/security/tomoyo/tomoyo_policy_io_test.c b/testcases/kernel/security/tomoyo/tomoyo_policy_io_test.c
deleted file mode 100644
index b1897a0fc..000000000
--- a/testcases/kernel/security/tomoyo/tomoyo_policy_io_test.c
+++ /dev/null
@@ -1,195 +0,0 @@
-/******************************************************************************/
-/* 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 */
-/* */
-/******************************************************************************/
-/*
- * tomoyo_policy_io_test.c
- *
- * Testing program for security/tomoyo/
- *
- * Copyright (C) 2005-2010 NTT DATA CORPORATION
- */
-#include "include.h"
-
-static FILE *policy_fp = NULL;
-static const char *policy_file = "";
-
-static void try_io(const char *policy, const char should_success)
-{
- FILE *fp = fopen(policy_file, "r");
- char buffer[8192];
- int policy_found = 0;
- memset(buffer, 0, sizeof(buffer));
- printf("%s: ", policy);
- fprintf(policy_fp, "%s\n", policy);
- if (!fp) {
- printf("BUG: policy read failed\n");
- return;
- }
- while (fgets(buffer, sizeof(buffer) - 1, fp)) {
- char *cp = strchr(buffer, '\n');
- if (cp)
- *cp = '\0';
- if (!strcmp(buffer, policy)) {
- policy_found = 1;
- break;
- }
- }
- fclose(fp);
- if (should_success) {
- if (policy_found)
- printf("OK\n");
- else
- printf("BUG: policy write failed\n");
- } else {
- if (!policy_found)
- printf("OK : write rejected.\n");
- else
- printf("BUG: policy write not rejected.\n");
- }
- fprintf(policy_fp, "delete %s\n", policy);
-}
-
-static void stage_policy_io_test(void)
-{
- int i;
- policy_file = proc_policy_domain_policy;
- policy_fp = domain_fp;
- for (i = 0; i < 3; i++) {
- try_io("allow_chroot /", 1);
- try_io("allow_chroot ", 0);
- try_io("allow_chroot /mnt0/", 1);
- try_io("allow_chroot /var1/chroot2/", 1);
- try_io("allow_chroot /mnt0/", 1);
- try_io("allow_chroot /mnt0/", 1);
- try_io("allow_chroot /mnt0/", 1);
- try_io("allow_chroot /mnt\\?\\*/", 1);
- try_io("allow_chroot /mnt\\?\\*/", 1);
- try_io("allow_unmount /", 1);
- try_io("allow_unmount /sys1/", 1);
- try_io("allow_unmount /initrd2/", 1);
- try_io("allow_unmount /initrd/dev3/", 1);
- try_io("allow_unmount /initrd/\\*\\+/", 1);
- try_io("allow_unmount /initrd/\\@\\*/", 1);
- try_io("allow_unmount /initrd2/", 1);
- try_io("allow_pivot_root / /proc3/", 1);
- try_io("allow_pivot_root /sys5/ /proc3/", 1);
- try_io("allow_pivot_root /sys/", 0);
- try_io("allow_pivot_root *", 0);
- try_io("allow_pivot_root /sys5/ /proc3/", 1);
- try_io("allow_mount / / --bind 0xD", 1);
- try_io("allow_mount / / --move 0xF", 1);
- try_io("allow_mount / --remount", 0);
- try_io("allow_mount /", 0);
- try_io("allow_mount none /tmp/ tmpfs 0x1", 1);
- try_io("allow_mount none /tmp/ tmpfs", 0);
- try_io("allow_mount none /tmp/ nonexistent 0x0", 1);
- try_io("allow_mount none /proc/ proc 0x0", 1);
- try_io("allow_mount none /selinux/ selinuxfs 0x0", 1);
- try_io("allow_mount /proc/bus/usb /proc/bus/usb/ usbfs 0x0", 1);
- try_io("allow_mount none /dev/pts/ devpts 0x0", 1);
- try_io("allow_mount any / --remount 0xC00", 1);
- try_io("allow_mount /dev/sda1 /boot/ ext3 0xC00", 1);
- try_io("allow_mount none /dev/shm/ tmpfs 0x0", 1);
- try_io("allow_mount none /proc/sys/fs/binfmt_misc/ binfmt_misc "
- "0x0", 1);
- try_io("allow_mount none /proc/sys/fs/binfmt_misc/ binfmt_misc "
- "0x0 0x1", 0);
- try_io("allow_mount none /proc/sys/fs/binfmt_misc/ tmpfs "
- "binfmt_misc 0x0", 0);
- try_io("allow_mount /proc/bus/usb /proc/bus/usb/ usbfs 0x0", 1);
- }
- policy_file = proc_policy_exception_policy;
- policy_fp = exception_fp;
- for (i = 0; i < 3; i++) {
- try_io("allow_read /tmp/abc", 1);
- try_io("allow_read /tmp/abc\\*", 1);
- try_io("allow_read abc", 1);
- try_io("allow_read /tmp/abc/", 1);
- try_io("allow_read", 0);
- try_io("allow_read *", 1);
- try_io("file_pattern /\\*\\*\\*", 1);
- try_io("file_pattern /abc", 1);
- try_io("file_pattern /abc /def", 0);
- try_io("file_pattern abcdef", 1);
- try_io("path_group TEST /", 1);
- try_io("path_group TEST /boo", 1);
- try_io("path_group TEST /bar", 1);
- try_io("path_group TEST /\\*", 1);
- try_io("path_group TEST / /", 0);
- try_io("path_group TEST /boo", 1);
- try_io("path_group TEST /bar", 1);
- try_io("path_group TEST boo", 1);
- try_io("path_group TEST boo/", 1);
- try_io("path_group TEST /bar", 1);
- try_io("path_group TEST3 /\\*", 1);
- try_io("path_group TEST3 / /", 0);
- try_io("path_group TEST3 /boo", 1);
- try_io("path_group TEST3 /bar", 1);
- try_io("path_group TEST3 boo", 1);
- try_io("path_group TEST3 boo/", 1);
- try_io("deny_rewrite /", 1);
- try_io("deny_rewrite /foo", 1);
- try_io("deny_rewrite /\\*", 1);
- try_io("deny_rewrite /\\:", 0);
- try_io("deny_rewrite / /", 0);
- try_io("deny_rewrite @/TEST", 1);
- try_io("aggregator /boo/\\* /BOO", 1);
- try_io("aggregator /boo/\\* /BOO\\*", 0);
- try_io("aggregator /boo/\\*/ /BOO", 1);
- try_io("aggregator /boo/\\* /BOO/", 1);
- try_io("keep_domain <kernel>", 1);
- try_io("keep_domain <kernel> /sbin/init", 1);
- try_io("keep_domain <kernel> foo", 0);
- try_io("keep_domain <kernel> \\*", 0);
- try_io("keep_domain /ssh", 1);
- try_io("keep_domain /ssh /foo", 0);
- try_io("keep_domain /foo from <kernel>", 1);
- try_io("keep_domain /foo from <kernel> /sbin/init", 1);
- try_io("keep_domain from <kernel> /sbin/init", 0);
- try_io("keep_domain \\* from <kernel> /sbin/init", 0);
- try_io("no_keep_domain <kernel>", 1);
- try_io("no_keep_domain <kernel> /sbin/init", 1);
- try_io("no_keep_domain <kernel> foo", 0);
- try_io("no_keep_domain <kernel> \\*", 0);
- try_io("no_keep_domain /ssh", 1);
- try_io("no_keep_domain /ssh /foo", 0);
- try_io("no_keep_domain /foo from <kernel>", 1);
- try_io("no_keep_domain /foo from <kernel> /sbin/init", 1);
- try_io("no_keep_domain from <kernel> /sbin/init", 0);
- try_io("no_keep_domain \\* from <kernel> /sbin/init", 0);
- try_io("initialize_domain /foo", 1);
- try_io("initialize_domain /\\*", 1);
- try_io("initialize_domain /foo /bar", 0);
- try_io("initialize_domain /foo from /bar", 1);
- try_io("initialize_domain /foo from <kernel> /bar", 1);
- try_io("initialize_domain /\\* from <kernel>", 1);
- try_io("initialize_domain /foo from <kernel> \\*", 0);
- try_io("no_initialize_domain /foo", 1);
- try_io("no_initialize_domain /\\*", 1);
- try_io("no_initialize_domain /foo /bar", 0);
- try_io("no_initialize_domain /foo from /bar", 1);
- try_io("no_initialize_domain /foo from <kernel> /bar", 1);
- try_io("no_initialize_domain /\\* from <kernel>", 1);
- try_io("no_initialize_domain /foo from <kernel> \\*", 0);
- }
-}
-
-int main(void)
-{
- tomoyo_test_init();
- stage_policy_io_test();
- return 0;
-}
diff --git a/testcases/kernel/security/tomoyo/tomoyo_policy_memory_test.c b/testcases/kernel/security/tomoyo/tomoyo_policy_memory_test.c
deleted file mode 100644
index a6620ba30..000000000
--- a/testcases/kernel/security/tomoyo/tomoyo_policy_memory_test.c
+++ /dev/null
@@ -1,358 +0,0 @@
-/******************************************************************************/
-/* 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 */
-/* */
-/******************************************************************************/
-/*
- * tomoyo_policy_memory_test.c
- *
- * Testing program for security/tomoyo/
- *
- * Copyright (C) 2005-2010 NTT DATA CORPORATION
- */
-/*
- * Usage: Run this program using init= boot option.
- */
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/mount.h>
-
-static void BUG(const char *msg)
-{
- printf("%s", msg);
- fflush(stdout);
- while (1)
- sleep(100);
-}
-
-static const char *policy_file = NULL;
-static const char *policy = NULL;
-
-static void get_meminfo(unsigned int *policy_memory)
-{
- FILE *fp = fopen("/sys/kernel/security/tomoyo/meminfo", "r");
- if (!fp || fscanf(fp, "Policy: %u", policy_memory) != 1 || fclose(fp))
- BUG("BUG: Policy read error\n");
-}
-
-static void check_policy_common(const int found_expected, const int id)
-{
- FILE *fp = fopen(policy_file, "r");
- char buffer[8192];
- int policy_found = 0;
- memset(buffer, 0, sizeof(buffer));
- if (!fp)
- BUG("BUG: Policy read error\n");
- while (fgets(buffer, sizeof(buffer) - 1, fp)) {
- char *cp = strchr(buffer, '\n');
- if (cp)
- *cp = '\0';
- if (strcmp(buffer, policy))
- continue;
- policy_found = 1;
- break;
- }
- fclose(fp);
- if (policy_found != found_expected) {
- printf("BUG: Policy write error: %s %s at %d\n", policy,
- found_expected ? "not added" : "not deleted", id);
- BUG("");
- }
-}
-
-static inline void check_policy_written(FILE * fp, const int id)
-{
- fflush(fp);
- check_policy_common(1, id);
-}
-
-static inline void check_policy_deleted(FILE * fp, const int id)
-{
- fflush(fp);
- check_policy_common(0, id);
-}
-
-static const char *domain_testcases[] = {
- "allow_create /tmp/mknod_reg_test 0600",
- "allow_create /tmp/open_test 0600",
- "allow_create /tmp/open_test 0600",
- "allow_create /tmp/open_test 0600",
- "allow_execute /bin/true",
- "allow_execute /bin/true",
- "allow_execute /bin/true0",
- "allow_execute /bin/true1",
- "allow_execute /bin/true2",
- "allow_execute /bin/true3",
- "allow_execute /bin/true4",
- "allow_execute /bin/true5",
- "allow_execute /bin/true6",
- "allow_execute /bin/true7",
- "allow_execute /bin/true7",
- "allow_execute /bin/true7",
- "allow_execute /bin/true8",
- "allow_ioctl socket:[family=2:type=2:protocol=17] 0-35122",
- "allow_ioctl socket:[family=2:type=2:protocol=17] 35122-35124",
- "allow_link /tmp/link_source_test /tmp/link_dest_test",
- "allow_mkblock /tmp/mknod_blk_test 0600 1 0",
- "allow_mkchar /tmp/mknod_chr_test 0600 1 3",
- "allow_mkdir /tmp/mkdir_test/ 0755",
- "allow_mkfifo /tmp/mknod_fifo_test 0600",
- "allow_mkfifo /tmp/mknod_fifo_test 0600",
- "allow_mksock /tmp/mknod_sock_test 0600",
- "allow_mksock /tmp/socket_test 0600",
- "allow_read /bin/true",
- "allow_read /bin/true",
- "allow_read /dev/null",
- "allow_read /dev/null",
- "allow_read /dev/null",
- "allow_read /dev/null",
- "allow_read /dev/null",
- "allow_read /dev/null",
- "allow_read /foo",
- "allow_read /proc/sys/net/ipv4/ip_local_port_range",
- "allow_read /proc/sys/net/ipv4/ip_local_port_range",
- "allow_read/write /bar",
- "allow_read/write /dev/null",
- "allow_read/write /dev/null",
- "allow_read/write /proc/sys/net/ipv4/ip_local_port_range",
- "allow_read/write /proc/sys/net/ipv4/ip_local_port_range",
- "allow_read/write /tmp/fifo",
- "allow_read/write /tmp/fifo",
- "allow_read/write /tmp/rewrite_test",
- "allow_rename /tmp/rename_source_test /tmp/rename_dest_test",
- "allow_rmdir /tmp/rmdir_test/",
- "allow_symlink /symlink",
- "allow_symlink /symlink",
- "allow_symlink /symlink",
- "allow_symlink /symlink",
- "allow_symlink /tmp/symlink_source_test",
- "allow_symlink /tmp/symlink_source_test",
- "allow_symlink /tmp/symlink_source_test",
- "allow_symlink /tmp/symlink_source_test",
- "allow_symlink /tmp/symlink_source_test",
- "allow_truncate /tmp/rewrite_test",
- "allow_truncate /tmp/truncate_test",
- "allow_truncate /tmp/truncate_test",
- "allow_unlink /tmp/unlink_test",
- "allow_write /123",
- "allow_write /dev/null",
- "allow_write /dev/null",
- "allow_write /devfile",
- "allow_write /devfile",
- "allow_write /proc/sys/net/ipv4/ip_local_port_range",
- "allow_write /proc/sys/net/ipv4/ip_local_port_range",
- "allow_write /tmp/open_test",
- "allow_write /tmp/open_test",
- "allow_write /tmp/open_test",
- "allow_write /tmp/truncate_test",
- "allow_write /tmp/truncate_test",
- "allow_rewrite /tmp/rewrite_test",
- "allow_rewrite /tmp/rewrite_test",
- "allow_mount /dev/sda1 /mnt/sda1/ ext3 0x123",
- "allow_mount /dev/sda1 /mnt/sda1/ ext3 123",
- "allow_mount /dev/sda1 /mnt/sda1/ ext3 0123",
- "allow_mount /dev/sda1 /mnt/sda1/ ext3 0x123",
- "allow_mount /dev/sda1 /mnt/sda1/ ext3 123",
- "allow_mount /dev/sda1 /mnt/sda1/ ext3 0123",
- "allow_chroot /",
- "allow_chroot /",
- "allow_chroot /mnt/",
- "allow_pivot_root / /proc/",
- "allow_pivot_root /mnt/ /proc/mnt/",
- "allow_unmount /",
- "allow_unmount /proc/",
- NULL
-};
-
-static void domain_policy_test(const unsigned int before)
-{
- unsigned int after;
- int j;
- policy_file = "/sys/kernel/security/tomoyo/domain_policy";
- for (j = 0; domain_testcases[j]; j++) {
- int i;
- FILE *fp = fopen(policy_file, "w");
- if (!fp)
- BUG("BUG: Policy write error\n");
- fprintf(fp, "<kernel>\n");
- policy = domain_testcases[j];
- printf("Processing: %s\n", policy);
- for (i = 0; i < 100; i++) {
- fprintf(fp, "%s\n", policy);
- if (!i)
- check_policy_written(fp, 1);
- fprintf(fp, "delete %s\n", policy);
- }
- check_policy_deleted(fp, 1);
- for (i = 0; i < 100; i++)
- fprintf(fp, "%s\n", policy);
- check_policy_written(fp, 2);
- fprintf(fp, "delete %s\n", policy);
- check_policy_deleted(fp, 2);
- fclose(fp);
- for (i = 0; i < 30; i++) {
- usleep(100000);
- get_meminfo(&after);
- if (before == after)
- break;
- }
- if (before != after) {
- printf("Policy: %d\n", after - before);
- BUG("Policy read/write test: Fail\n");
- }
- }
- for (j = 0; j < 10; j++) {
- int i;
- FILE *fp = fopen(policy_file, "w");
- if (!fp)
- BUG("BUG: Policy write error\n");
- fprintf(fp, "<kernel> /sbin/init\n");
- for (i = 0; domain_testcases[i]; i++)
- fprintf(fp, "%s\n", domain_testcases[i]);
- fprintf(fp, "delete <kernel> /sbin/init\n");
- fclose(fp);
- for (i = 0; i < 50; i++) {
- usleep(100000);
- get_meminfo(&after);
- if (before == after)
- break;
- }
- if (before != after) {
- printf("Policy: %d\n", after - before);
- BUG("Policy read/write test: Fail\n");
- }
- }
-}
-
-static const char *exception_testcases[] = {
- "allow_read /tmp/mknod_reg_test",
- "allow_env HOME",
- "path_group PG1 /",
- "path_group PG2 /",
- "address_group AG3 0.0.0.0",
- "address_group AG3 1.2.3.4-5.6.7.8",
- "address_group AG3 f:ee:ddd:cccc:b:aa:999:8888",
- "address_group AG4 0:1:2:3:4:5:6:7-8:90:a00:b000:c00:d0:e:f000",
- "number_group NG1 1000",
- "number_group NG2 10-0x100000",
- "number_group NG3 01234567-0xABCDEF89",
- "deny_autobind 1024",
- "deny_autobind 32668-65535",
- "deny_autobind 0-1023",
- "initialize_domain /usr/sbin/sshd",
- "no_initialize_domain /usr/sbin/sshd",
- "initialize_domain /usr/sbin/sshd from /bin/bash",
- "no_initialize_domain /usr/sbin/sshd from /bin/bash",
- "initialize_domain /usr/sbin/sshd from "
- "<kernel> /bin/mingetty/bin/bash",
- "no_initialize_domain /usr/sbin/sshd from "
- "<kernel> /bin/mingetty/bin/bash",
- "keep_domain <kernel> /usr/sbin/sshd /bin/bash",
- "no_keep_domain <kernel> /usr/sbin/sshd /bin/bash",
- "keep_domain /bin/pwd from <kernel> /usr/sbin/sshd /bin/bash",
- "no_keep_domain /bin/pwd from <kernel> /usr/sbin/sshd /bin/bash",
- "keep_domain /bin/pwd from /bin/bash",
- "no_keep_domain /bin/pwd from /bin/bash",
- "file_pattern /proc/\\$/task/\\$/environ",
- "file_pattern /proc/\\$/task/\\$/auxv",
- "allow_read /etc/ld.so.cache",
- "allow_read /proc/meminfo",
- "allow_read /proc/sys/kernel/version",
- "allow_read /etc/localtime",
- "allow_read /proc/self/task/\\$/attr/current",
- "allow_read /proc/self/task/\\$/oom_score",
- "allow_read /proc/self/wchan",
- "allow_read /lib/ld-2.5.so",
- "file_pattern pipe:[\\$]",
- "file_pattern socket:[\\$]",
- "file_pattern /var/cache/logwatch/logwatch.\\*/",
- "file_pattern /var/cache/logwatch/logwatch.\\*/\\*",
- "deny_rewrite /var/log/\\*",
- "deny_rewrite /var/log/\\*/\\*",
- "aggregator /etc/rc.d/rc\\?.d/\\?\\+\\+smb /etc/rc.d/init.d/smb",
- "aggregator /etc/rc.d/rc\\?.d/\\?\\+\\+crond /etc/rc.d/init.d/crond",
- NULL
-};
-
-static void exception_policy_test(const unsigned int before)
-{
- unsigned int after;
- int j;
- policy_file = "/sys/kernel/security/tomoyo/exception_policy";
- for (j = 0; exception_testcases[j]; j++) {
- int i;
- FILE *fp = fopen(policy_file, "w");
- if (!fp)
- BUG("BUG: Policy write error\n");
- policy = exception_testcases[j];
- printf("Processing: %s\n", policy);
- for (i = 0; i < 100; i++) {
- fprintf(fp, "%s\n", policy);
- if (!i)
- check_policy_written(fp, 1);
- fprintf(fp, "delete %s\n", policy);
- }
- check_policy_deleted(fp, 1);
- for (i = 0; i < 100; i++)
- fprintf(fp, "%s\n", policy);
- check_policy_written(fp, 2);
- fprintf(fp, "delete %s\n", policy);
- check_policy_deleted(fp, 2);
- fclose(fp);
- for (i = 0; i < 30; i++) {
- usleep(100000);
- get_meminfo(&after);
- if (before == after)
- break;
- }
- if (before != after) {
- printf("Policy: %d\n", after - before);
- BUG("Policy read/write test: Fail\n");
- }
- }
- for (j = 0; j < 10; j++) {
- int i;
- FILE *fp = fopen(policy_file, "w");
- if (!fp)
- BUG("BUG: Policy write error\n");
- for (i = 0; exception_testcases[i]; i++)
- fprintf(fp, "%s\n", exception_testcases[i]);
- for (i = 0; exception_testcases[i]; i++)
- fprintf(fp, "delete %s\n", exception_testcases[i]);
- fclose(fp);
- for (i = 0; i < 50; i++) {
- usleep(100000);
- get_meminfo(&after);
- if (before == after)
- break;
- }
- if (before != after) {
- printf("Policy: %d\n", after - before);
- BUG("Policy read/write test: Fail\n");
- }
- }
-}
-
-int main(void)
-{
- unsigned int before;
- mount("/proc", "/proc/", "proc", 0, NULL);
- get_meminfo(&before);
- domain_policy_test(before);
- exception_policy_test(before);
- BUG("Policy read/write test: Success\n");
- return 0;
-}
diff --git a/testcases/kernel/security/tomoyo/tomoyo_rewrite_test.c b/testcases/kernel/security/tomoyo/tomoyo_rewrite_test.c
deleted file mode 100644
index 7bc22c39b..000000000
--- a/testcases/kernel/security/tomoyo/tomoyo_rewrite_test.c
+++ /dev/null
@@ -1,169 +0,0 @@
-/******************************************************************************/
-/* 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 */
-/* */
-/******************************************************************************/
-/*
- * tomoyo_rewrite_test.c
- *
- * Testing program for security/tomoyo/
- *
- * Copyright (C) 2005-2010 NTT DATA CORPORATION
- */
-#include "include.h"
-
-static int should_fail = 0;
-
-static void show_prompt(const char *str)
-{
- printf("Testing %35s: (%s) ", str,
- should_fail ? "must fail" : "must success");
- errno = 0;
-}
-
-static void show_result(int result)
-{
- if (should_fail) {
- if (result == EOF) {
- if (errno == EPERM)
- printf("OK: Permission denied.\n");
- else
- printf("BUG!\n");
- } else {
- printf("BUG!\n");
- }
- } else {
- if (result != EOF)
- printf("OK\n");
- else
- printf("BUG!\n");
- }
-}
-
-#define REWRITE_PATH "/tmp/rewrite_test"
-
-static void stage_rewrite_test(void)
-{
- int fd;
-
- /* Start up */
- write_domain_policy("allow_read/write " REWRITE_PATH, 0);
- write_domain_policy("allow_truncate " REWRITE_PATH, 0);
- write_domain_policy("allow_create " REWRITE_PATH " 0600", 0);
- write_domain_policy("allow_unlink " REWRITE_PATH, 0);
- write_exception_policy("deny_rewrite " REWRITE_PATH, 0);
- set_profile(3, "file::open");
- set_profile(3, "file::create");
- set_profile(3, "file::truncate");
- set_profile(3, "file::rewrite");
- set_profile(3, "file::unlink");
- close(open(REWRITE_PATH, O_WRONLY | O_APPEND | O_CREAT, 0600));
-
- /* Enforce mode */
- should_fail = 0;
-
- show_prompt("open(O_RDONLY)");
- fd = open(REWRITE_PATH, O_RDONLY);
- show_result(fd);
- close(fd);
-
- show_prompt("open(O_WRONLY | O_APPEND)");
- fd = open(REWRITE_PATH, O_WRONLY | O_APPEND);
- show_result(fd);
- close(fd);
-
- should_fail = 1;
- show_prompt("open(O_WRONLY)");
- fd = open(REWRITE_PATH, O_WRONLY);
- show_result(fd);
- close(fd);
-
- show_prompt("open(O_WRONLY | O_TRUNC)");
- fd = open(REWRITE_PATH, O_WRONLY | O_TRUNC);
- show_result(fd);
- close(fd);
-
- show_prompt("open(O_WRONLY | O_TRUNC | O_APPEND)");
- fd = open(REWRITE_PATH, O_WRONLY | O_TRUNC | O_APPEND);
- show_result(fd);
- close(fd);
-
- show_prompt("truncate()");
- show_result(truncate(REWRITE_PATH, 0));
-
- fd = open(REWRITE_PATH, O_WRONLY | O_APPEND);
- show_prompt("ftruncate()");
- show_result(ftruncate(fd, 0));
-
- show_prompt("fcntl(F_SETFL, ~O_APPEND)");
- show_result(fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) & ~O_APPEND));
- close(fd);
-
- /* Permissive mode */
- set_profile(2, "file::open");
- set_profile(2, "file::create");
- set_profile(2, "file::truncate");
- set_profile(2, "file::rewrite");
- set_profile(2, "file::unlink");
- should_fail = 0;
-
- show_prompt("open(O_RDONLY)");
- fd = open(REWRITE_PATH, O_RDONLY);
- show_result(fd);
- close(fd);
-
- show_prompt("open(O_WRONLY | O_APPEND)");
- fd = open(REWRITE_PATH, O_WRONLY | O_APPEND);
- show_result(fd);
- close(fd);
-
- show_prompt("open(O_WRONLY)");
- fd = open(REWRITE_PATH, O_WRONLY);
- show_result(fd);
- close(fd);
-
- show_prompt("open(O_WRONLY | O_TRUNC)");
- fd = open(REWRITE_PATH, O_WRONLY | O_TRUNC);
- show_result(fd);
- close(fd);
-
- show_prompt("open(O_WRONLY | O_TRUNC | O_APPEND)");
- fd = open(REWRITE_PATH, O_WRONLY | O_TRUNC | O_APPEND);
- show_result(fd);
- close(fd);
-
- show_prompt("truncate()");
- show_result(truncate(REWRITE_PATH, 0));
-
- fd = open(REWRITE_PATH, O_WRONLY | O_APPEND);
- show_prompt("ftruncate()");
- show_result(ftruncate(fd, 0));
-
- show_prompt("fcntl(F_SETFL, ~O_APPEND)");
- show_result(fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) & ~O_APPEND));
- close(fd);
-
- /* Clean up */
- unlink(REWRITE_PATH);
- write_exception_policy("deny_rewrite " REWRITE_PATH, 0);
- printf("\n\n");
-}
-
-int main(void)
-{
- tomoyo_test_init();
- stage_rewrite_test();
- clear_status();
- return 0;
-}
diff --git a/testcases/kernel/sound/snd_timer01.c b/testcases/kernel/sound/snd_timer01.c
index 123d1a2cb..310169b0f 100644
--- a/testcases/kernel/sound/snd_timer01.c
+++ b/testcases/kernel/sound/snd_timer01.c
@@ -8,7 +8,7 @@
*
* The test performs several ioctl() parallel with readv() on the same
* file descriptor to /dev/snd/timer. A buggy kernel will leak memory
- * to the process, which may contain information from the the kernel or
+ * to the process, which may contain information from the kernel or
* any other process on the system.
*
* The issue was fixed with
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/ipc/semaphore/sem02.c b/testcases/kernel/syscalls/ipc/semop/semop05.c
index 34b714bf0..34b714bf0 100644
--- a/testcases/kernel/ipc/semaphore/sem02.c
+++ b/testcases/kernel/syscalls/ipc/semop/semop05.c
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)
diff --git a/testcases/lib/.gitignore b/testcases/lib/.gitignore
index 34dea272d..e8afd06f3 100644
--- a/testcases/lib/.gitignore
+++ b/testcases/lib/.gitignore
@@ -3,17 +3,23 @@
/tst_check_kconfigs
/tst_checkpoint
/tst_device
+/tst_fsfreeze
/tst_getconf
/tst_get_free_pids
/tst_get_median
/tst_get_unused_port
+/tst_hexdump
/tst_kvcmp
+/tst_lockdown_enabled
/tst_net_iface_prefix
/tst_net_ip_prefix
/tst_net_vars
+/tst_ns_create
+/tst_ns_exec
+/tst_ns_ifmove
/tst_random
/tst_rod
+/tst_secureboot_enabled
/tst_sleep
/tst_supported_fs
-/tst_hexdump
/tst_timeout_kill
diff --git a/testcases/lib/Makefile b/testcases/lib/Makefile
index f4f8c8524..990b46089 100644
--- a/testcases/lib/Makefile
+++ b/testcases/lib/Makefile
@@ -12,6 +12,7 @@ MAKE_TARGETS := tst_sleep tst_random tst_checkpoint tst_rod tst_kvcmp\
tst_device tst_net_iface_prefix tst_net_ip_prefix tst_net_vars\
tst_getconf tst_supported_fs tst_check_drivers tst_get_unused_port\
tst_get_median tst_hexdump tst_get_free_pids tst_timeout_kill\
- tst_check_kconfigs tst_cgctl
+ tst_check_kconfigs tst_cgctl tst_fsfreeze tst_ns_create tst_ns_exec\
+ tst_ns_ifmove tst_lockdown_enabled tst_secureboot_enabled
include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/lib/tst_fsfreeze.c b/testcases/lib/tst_fsfreeze.c
new file mode 100644
index 000000000..4b0b12cba
--- /dev/null
+++ b/testcases/lib/tst_fsfreeze.c
@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2010 Hajime Taira <htaira@redhat.com>
+ * Masatake Yamato <yamato@redhat.com>
+ * Copyright (c) 2023 Petr Vorel <pvorel@suse.cz>
+ *
+ * Based on fsfreeze from util-linux.
+ */
+
+#include <linux/fs.h>
+#include <stdio.h>
+
+#define TST_NO_DEFAULT_MAIN
+#include "tst_test.h"
+#include "tst_safe_macros.h"
+
+static void help(void)
+{
+ printf("Freeze and unfreeze the device.\n");
+ printf("Usage: tst_fsfreeze device\n");
+}
+
+int main(int argc, char *argv[])
+{
+ int fd;
+
+ if (argc < 2) {
+ help();
+ return 1;
+ }
+
+ fd = SAFE_OPEN(argv[1], O_RDONLY);
+ SAFE_IOCTL(fd, FIFREEZE, 0);
+ SAFE_IOCTL(fd, FITHAW, 0);
+ SAFE_CLOSE(fd);
+
+ return 0;
+}
diff --git a/testcases/lib/tst_get_free_pids.c b/testcases/lib/tst_get_free_pids.c
index d7b68c620..370ec3e26 100644
--- a/testcases/lib/tst_get_free_pids.c
+++ b/testcases/lib/tst_get_free_pids.c
@@ -2,7 +2,7 @@
#define TST_NO_DEFAULT_MAIN
#include <stdio.h>
-#include <tst_test.h>
+#include "tst_test.h"
extern struct tst_test *tst_test;
diff --git a/testcases/lib/tst_kvcmp.c b/testcases/lib/tst_kvcmp.c
index 0f5793ef1..afc4b5ce3 100644
--- a/testcases/lib/tst_kvcmp.c
+++ b/testcases/lib/tst_kvcmp.c
@@ -7,7 +7,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <sys/utsname.h>
-#include <tst_test.h>
+#include "tst_test.h"
enum op {
EQ,
diff --git a/testcases/lib/tst_lockdown_enabled.c b/testcases/lib/tst_lockdown_enabled.c
new file mode 100644
index 000000000..30abe3e5e
--- /dev/null
+++ b/testcases/lib/tst_lockdown_enabled.c
@@ -0,0 +1,12 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2023 Petr Vorel <pvorel@suse.cz>
+ */
+
+#define TST_NO_DEFAULT_MAIN
+#include "tst_test.h"
+
+int main(void)
+{
+ return tst_lockdown_enabled() <= 0;
+}
diff --git a/testcases/lib/tst_net.sh b/testcases/lib/tst_net.sh
index e6bb09d81..6168db86b 100644
--- a/testcases/lib/tst_net.sh
+++ b/testcases/lib/tst_net.sh
@@ -1,7 +1,7 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (c) 2014-2017 Oracle and/or its affiliates. All Rights Reserved.
-# Copyright (c) 2016-2022 Petr Vorel <pvorel@suse.cz>
+# Copyright (c) 2016-2023 Petr Vorel <pvorel@suse.cz>
# Author: Alexey Kodanev <alexey.kodanev@oracle.com>
[ -n "$TST_LIB_NET_LOADED" ] && return 0
@@ -59,7 +59,7 @@ tst_net_remote_tmpdir()
tst_net_setup()
{
- [ "$TST_IPVER" = 6 ] && tst_net_require_ipv6
+ [ "$TST_IPV6" ] && tst_net_require_ipv6
tst_net_remote_tmpdir
[ -n "$TST_SETUP_CALLER" ] && $TST_SETUP_CALLER
@@ -73,52 +73,93 @@ tst_net_setup()
fi
}
-if [ "$TST_PARSE_ARGS_CALLER" = "$TST_PARSE_ARGS" ]; then
- tst_res TWARN "TST_PARSE_ARGS_CALLER same as TST_PARSE_ARGS, unset it ($TST_PARSE_ARGS)"
- unset TST_PARSE_ARGS_CALLER
-fi
-if [ "$TST_SETUP_CALLER" = "$TST_SETUP" ]; then
- tst_res TWARN "TST_SETUP_CALLER same as TST_SETUP, unset it ($TST_SETUP)"
- unset TST_SETUP_CALLER
-fi
-if [ "$TST_USAGE_CALLER" = "$TST_USAGE" ]; then
- tst_res TWARN "TST_USAGE_CALLER same as TST_USAGE, unset it ($TST_USAGE)"
- unset TST_USAGE_CALLER
-fi
-
-if [ -n "$TST_USE_LEGACY_API" ]; then
- tst_net_read_opts "$@"
-fi
-
# old vs. new API compatibility layer
tst_res_()
{
[ -z "$TST_USE_LEGACY_API" ] && tst_res $@ || tst_resm $@
}
+
tst_brk_()
{
[ -z "$TST_USE_LEGACY_API" ] && tst_brk $@ || tst_brkm $@
}
+# Detect IPv6 disabled via 1) CONFIG_IPV6=n or 2) ipv6.disable=1 kernel cmdline
+# parameter or 3) sysctl net.ipv6.conf.all.disable_ipv6=1 (disables IPv6 on all
+# interfaces (including both already created and later created).
+# $TST_NET_IPV6_ENABLED: 1 on IPv6 enabled, 0 on IPv6 disabled.
tst_net_detect_ipv6()
{
local type="${1:-lhost}"
local cmd='[ -f /proc/net/if_inet6 ]'
- local ret
+ local disabled iface ret
if [ "$type" = "lhost" ]; then
$cmd
else
tst_rhost_run -c "$cmd"
fi
- ret=$?
- if [ $ret -eq 0 ]; then
- TST_NET_IPV6_ENABLED=1
+ if [ $? -ne 0 ]; then
+ TST_NET_IPV6_ENABLED=0
+ tst_res_ TINFO "IPv6 disabled on $type via kernel command line or not compiled in"
+ return
+ fi
+
+ cmd='cat /proc/sys/net/ipv6/conf/all/disable_ipv6'
+ if [ "$type" = "lhost" ]; then
+ disabled=$($cmd)
+ else
+ disabled=$(tst_rhost_run -c "$cmd")
+ fi
+ if [ $disabled = 1 ]; then
+ tst_res_ TINFO "IPv6 disabled on $type net.ipv6.conf.all.disable_ipv6=1"
+ TST_NET_IPV6_ENABLED=0
+ return
+ fi
+
+ TST_NET_IPV6_ENABLED=1
+}
+
+# Detect IPv6 disabled on interface via sysctl
+# net.ipv6.conf.$iface.disable_ipv6=1.
+# $TST_NET_IPV6_ENABLED: 1 on IPv6 enabled, 0 on IPv6 disabled.
+# return: 0 on IPv6 enabled, 1 on IPv6 disabled.
+tst_net_detect_ipv6_iface()
+{
+ [ "$TST_NET_IPV6_ENABLED" = 1 ] || return 1
+
+ local iface="$1"
+ local type="${2:-lhost}"
+ local check="cat /proc/sys/net/ipv6/conf/$iface/disable_ipv6"
+ local disabled
+
+ if [ "$type" = "lhost" ]; then
+ disabled=$($check)
else
+ disabled=$(tst_rhost_run -c "$check")
+ fi
+ if [ $disabled = 1 ]; then
+ tst_res_ TINFO "IPv6 disabled on $type on $iface"
TST_NET_IPV6_ENABLED=0
- tst_res TINFO "IPv6 disabled on $type"
+ return 1
fi
+
+ return 0
+}
+
+# Detect IPv6 disabled on used interfaces.
+tst_net_check_ifaces_ipv6()
+{
+ local iface
+
+ for iface in $(tst_get_ifaces); do
+ tst_net_detect_ipv6_iface $iface || return
+ done
+
+ for iface in $(tst_get_ifaces rhost); do
+ tst_net_detect_ipv6_iface $iface rhost || return
+ done
}
tst_net_require_ipv6()
@@ -131,18 +172,18 @@ init_ltp_netspace()
local pid
if [ ! -f /var/run/netns/ltp_ns -a -z "$LTP_NETNS" ]; then
- tst_require_cmds ip ns_create ns_exec ns_ifmove
+ tst_require_cmds ip tst_ns_create tst_ns_exec tst_ns_ifmove
tst_require_root
tst_require_drivers veth
ROD ip link add name ltp_ns_veth1 type veth peer name ltp_ns_veth2
- pid="$(ROD ns_create net,mnt)"
+ pid="$(ROD tst_ns_create net,mnt)"
mkdir -p /var/run/netns
ROD ln -s /proc/$pid/ns/net /var/run/netns/ltp_ns
- ROD ns_exec $pid net,mnt mount --make-rprivate /sys
- ROD ns_exec $pid net,mnt mount -t sysfs none /sys
- ROD ns_ifmove ltp_ns_veth1 $pid
- ROD ns_exec $pid net,mnt ip link set lo up
+ ROD tst_ns_exec $pid net,mnt mount --make-rprivate /sys
+ ROD tst_ns_exec $pid net,mnt mount -t sysfs none /sys
+ ROD tst_ns_ifmove ltp_ns_veth1 $pid
+ ROD tst_ns_exec $pid net,mnt ip link set lo up
elif [ -n "$LTP_NETNS" ]; then
tst_res_ TINFO "using not default LTP netns: '$LTP_NETNS'"
fi
@@ -150,10 +191,8 @@ init_ltp_netspace()
LHOST_IFACES="${LHOST_IFACES:-ltp_ns_veth2}"
RHOST_IFACES="${RHOST_IFACES:-ltp_ns_veth1}"
- export TST_INIT_NETNS="no"
-
pid="$(echo $(readlink /var/run/netns/ltp_ns) | cut -f3 -d'/')"
- export LTP_NETNS="${LTP_NETNS:-ns_exec $pid net,mnt}"
+ export LTP_NETNS="${LTP_NETNS:-tst_ns_exec $pid net,mnt}"
tst_restore_ipaddr
tst_restore_ipaddr rhost
@@ -460,7 +499,7 @@ tst_ipaddr_un()
;;
m)
! tst_is_int "$OPTARG" || [ "$OPTARG" -lt 0 ]|| [ "$OPTARG" -gt $max_net_id ] && \
- tst_brk TBROK "tst_ipaddr_un: -m must be integer <0,$max_net_id> ($OPTARG)"
+ tst_brk_ TBROK "tst_ipaddr_un: -m must be integer <0,$max_net_id> ($OPTARG)"
[ "$OPTARG" -gt $max_net_id ] && \
tst_brk_ TBROK "tst_ipaddr_un: -m cannot be higher than $max_net_id ($OPTARG)"
max_host_id="$OPTARG"
@@ -481,16 +520,16 @@ tst_ipaddr_un()
! tst_is_int "$min_host_id" || ! tst_is_int "$max_host_id" || \
[ $min_host_id -lt 0 -o $min_host_id -gt $default_max ] || \
[ $max_host_id -lt 0 -o $max_host_id -gt $default_max ] && \
- tst_brk TBROK "tst_ipaddr_un: HOST_ID must be int in range <0,$default_max> ($min_host_id,$max_host_id)"
+ tst_brk_ TBROK "tst_ipaddr_un: HOST_ID must be int in range <0,$default_max> ($min_host_id,$max_host_id)"
! tst_is_int "$min_net_id" || ! tst_is_int "$max_net_id" || \
[ $min_net_id -lt 0 -o $min_net_id -gt $default_max ] || \
[ $max_net_id -lt 0 -o $max_net_id -gt $default_max ] && \
- tst_brk TBROK "tst_ipaddr_un: NET_ID must be int in range <0,$default_max> ($min_net_id,$max_net_id)"
+ tst_brk_ TBROK "tst_ipaddr_un: NET_ID must be int in range <0,$default_max> ($min_net_id,$max_net_id)"
[ $min_host_id -gt $max_host_id ] && \
- tst_brk TBROK "tst_ipaddr_un: max HOST_ID ($max_host_id) must be >= min HOST_ID ($min_host_id)"
+ tst_brk_ TBROK "tst_ipaddr_un: max HOST_ID ($max_host_id) must be >= min HOST_ID ($min_host_id)"
[ $min_net_id -gt $max_net_id ] && \
- tst_brk TBROK "tst_ipaddr_un: max NET_ID ($max_net_id) must be >= min NET_ID ($min_net_id)"
+ tst_brk_ TBROK "tst_ipaddr_un: max NET_ID ($max_net_id) must be >= min NET_ID ($min_net_id)"
# counter
host_range=$((max_host_id - min_host_id + 1))
@@ -533,7 +572,9 @@ tst_init_iface()
local type="${1:-lhost}"
local link_num="${2:-0}"
local iface="$(tst_iface $type $link_num)"
+
tst_res_ TINFO "initialize '$type' '$iface' interface"
+ tst_net_detect_ipv6_iface $iface $type
if [ "$type" = "lhost" ]; then
if ip xfrm state 1>/dev/null 2>&1; then
@@ -584,7 +625,7 @@ tst_add_ipaddr()
d) action="del" ;;
q) quiet=1 ;;
s) lsafe="ROD"; rsafe="-s" ;;
- *) tst_brk TBROK "tst_add_ipaddr: unknown option: $OPTARG" ;;
+ *) tst_brk_ TBROK "tst_add_ipaddr: unknown option: $OPTARG" ;;
esac
done
shift $((OPTIND - 1))
@@ -593,6 +634,8 @@ tst_add_ipaddr()
local link_num="${2:-0}"
local iface=$(tst_iface $type $link_num)
+ tst_net_detect_ipv6_iface $iface $type
+
if [ "$TST_IPV6" ]; then
dad="nodad"
[ "$type" = "lhost" ] && mask=$IPV6_LPREFIX || mask=$IPV6_RPREFIX
@@ -969,43 +1012,25 @@ tst_default_max_pkt()
echo "$((mtu + mtu / 10))"
}
-[ -n "$TST_USE_LEGACY_API" ] && . test.sh || . tst_test.sh
-
-# detect IPv6 support on lhost for tests which don't use test links
-tst_net_detect_ipv6
-
-[ -n "$TST_NET_SKIP_VARIABLE_INIT" ] && return 0
-
-# Management Link
-[ -z "$RHOST" ] && TST_USE_NETNS="yes"
-export RHOST="$RHOST"
-export PASSWD="${PASSWD:-}"
-# Don't use it in new tests, use tst_rhost_run() from tst_net.sh instead.
-export LTP_RSH="${LTP_RSH:-ssh -nq}"
-
-# Test Links
-# IPV{4,6}_{L,R}HOST can be set with or without prefix (e.g. IP or IP/prefix),
-# but if you use IP/prefix form, /prefix will be removed by tst_net_vars.
-IPV4_LHOST="${IPV4_LHOST:-10.0.0.2/24}"
-IPV4_RHOST="${IPV4_RHOST:-10.0.0.1/24}"
-IPV6_LHOST="${IPV6_LHOST:-fd00:1:1:1::2/64}"
-IPV6_RHOST="${IPV6_RHOST:-fd00:1:1:1::1/64}"
-
-# tst_net_ip_prefix
+# Setup LTP network.
+#
+# Used tools:
+# * tst_net_ip_prefix
# Strip prefix from IP address and save both If no prefix found sets
# default prefix.
-#
-# tst_net_iface_prefix reads prefix and interface from rtnetlink.
+# * tst_net_iface_prefix reads prefix and interface from rtnetlink.
# If nothing found sets default prefix value.
-#
-# tst_net_vars exports environment variables related to test links and
+# * tst_net_vars exports environment variables related to test links and
# networks that aren't reachable through the test links.
#
# For full list of exported environment variables see:
# tst_net_ip_prefix -h
# tst_net_iface_prefix -h
# tst_net_vars -h
-if [ -z "$_tst_net_parse_variables" ]; then
+tst_net_setup_network()
+{
+ tst_require_cmds tst_net_iface_prefix tst_net_ip_prefix tst_net_vars
+
eval $(tst_net_ip_prefix $IPV4_LHOST || echo "exit $?")
eval $(tst_net_ip_prefix -r $IPV4_RHOST || echo "exit $?")
@@ -1015,25 +1040,20 @@ if [ -z "$_tst_net_parse_variables" ]; then
eval $(tst_net_ip_prefix $IPV6_LHOST || echo "exit $?")
eval $(tst_net_ip_prefix -r $IPV6_RHOST || echo "exit $?")
fi
-fi
-[ -n "$TST_USE_NETNS" -a "$TST_INIT_NETNS" != "no" ] && init_ltp_netspace
+ tst_net_use_netns && init_ltp_netspace
-if [ -z "$_tst_net_parse_variables" ]; then
eval $(tst_net_iface_prefix $IPV4_LHOST || echo "exit $?")
eval $(tst_rhost_run -c 'tst_net_iface_prefix -r '$IPV4_RHOST \
|| echo "exit $?")
+ eval $(tst_net_vars $IPV4_LHOST/$IPV4_LPREFIX \
+ $IPV4_RHOST/$IPV4_RPREFIX || echo "exit $?")
if [ "$TST_NET_IPV6_ENABLED" = 1 ]; then
+ tst_net_check_ifaces_ipv6
eval $(tst_net_iface_prefix $IPV6_LHOST || echo "exit $?")
eval $(tst_rhost_run -c 'tst_net_iface_prefix -r '$IPV6_RHOST \
|| echo "exit $?")
- fi
-
- eval $(tst_net_vars $IPV4_LHOST/$IPV4_LPREFIX \
- $IPV4_RHOST/$IPV4_RPREFIX || echo "exit $?")
-
- if [ "$TST_NET_IPV6_ENABLED" = 1 ]; then
eval $(tst_net_vars $IPV6_LHOST/$IPV6_LPREFIX \
$IPV6_RHOST/$IPV6_RPREFIX || echo "exit $?")
fi
@@ -1043,9 +1063,56 @@ if [ -z "$_tst_net_parse_variables" ]; then
tst_res_ TINFO "$IPV4_LHOST/$IPV4_LPREFIX -- $IPV4_RHOST/$IPV4_RPREFIX"
tst_res_ TINFO "$IPV6_LHOST/$IPV6_LPREFIX -- $IPV6_RHOST/$IPV6_RPREFIX"
- export _tst_net_parse_variables="yes"
+ if [ -n "$TST_USE_LEGACY_API" ]; then
+ [ "$TST_IPV6" ] && tst_net_require_ipv6
+ tst_net_remote_tmpdir
+ fi
+}
+
+[ -n "$TST_USE_LEGACY_API" ] && . test.sh || . tst_test.sh
+
+if [ -n "$TST_USE_LEGACY_API" ]; then
+ tst_net_read_opts "$@"
+else
+ if [ "$TST_PARSE_ARGS_CALLER" = "$TST_PARSE_ARGS" ]; then
+ tst_res_ TWARN "TST_PARSE_ARGS_CALLER same as TST_PARSE_ARGS, unset it ($TST_PARSE_ARGS)"
+ unset TST_PARSE_ARGS_CALLER
+ fi
+ if [ "$TST_SETUP_CALLER" = "$TST_SETUP" ]; then
+ tst_res_ TWARN "TST_SETUP_CALLER same as TST_SETUP, unset it ($TST_SETUP)"
+ unset TST_SETUP_CALLER
+ fi
+ if [ "$TST_USAGE_CALLER" = "$TST_USAGE" ]; then
+ tst_res_ TWARN "TST_USAGE_CALLER same as TST_USAGE, unset it ($TST_USAGE)"
+ unset TST_USAGE_CALLER
+ fi
fi
+# detect IPv6 support on lhost for tests which don't use test links
+tst_net_detect_ipv6
+
+[ -n "$TST_NET_SKIP_VARIABLE_INIT" ] && return 0
+
+# Management Link
+[ -z "$RHOST" ] && TST_USE_NETNS="yes"
+export RHOST="$RHOST"
+export PASSWD="${PASSWD:-}"
+# Don't use it in new tests, use tst_rhost_run() from tst_net.sh instead.
+export LTP_RSH="${LTP_RSH:-ssh -nq}"
+
+# Test Links
+# IPV{4,6}_{L,R}HOST can be set with or without prefix (e.g. IP or IP/prefix),
+# but if you use IP/prefix form, /prefix will be removed by tst_net_vars.
+IPV4_LHOST="${IPV4_LHOST:-10.0.0.2/24}"
+IPV4_RHOST="${IPV4_RHOST:-10.0.0.1/24}"
+IPV6_LHOST="${IPV6_LHOST:-fd00:1:1:1::2/64}"
+IPV6_RHOST="${IPV6_RHOST:-fd00:1:1:1::1/64}"
+
+tst_net_setup_network
+
+# More information about network parameters can be found
+# in the following document: testcases/network/stress/README
+
export TST_NET_DATAROOT="$LTPROOT/testcases/bin/datafiles"
export TST_NETLOAD_CLN_REQUESTS="${TST_NETLOAD_CLN_REQUESTS:-10000}"
@@ -1090,13 +1157,6 @@ export RHOST_HWADDRS="${RHOST_HWADDRS:-$(tst_get_hwaddrs rhost)}"
export NS_ICMPV4_SENDER_DATA_MAXSIZE=1472
export NS_ICMPV6_SENDER_DATA_MAXSIZE=1452
-# More information about network parameters can be found
-# in the following document: testcases/network/stress/README
-
-if [ -n "$TST_USE_LEGACY_API" ]; then
- tst_net_remote_tmpdir
-fi
-
if [ -z "$TST_USE_LEGACY_API" ] && ! tst_cmd_available ping6; then
ping6()
{
diff --git a/testcases/kernel/containers/share/ns_common.h b/testcases/lib/tst_ns_common.h
index 813cd3388..358db5141 100644
--- a/testcases/kernel/containers/share/ns_common.h
+++ b/testcases/lib/tst_ns_common.h
@@ -3,8 +3,8 @@
* Copyright (c) Linux Test Project, 2015-2023
*/
-#ifndef __NS_COMMON_H__
-#define __NS_COMMON_H__
+#ifndef TST_NS_COMMON_H__
+#define TST_NS_COMMON_H__
#include <sched.h>
#include "lapi/sched.h"
@@ -39,4 +39,4 @@ static struct param *get_param(const char *name)
return NULL;
}
-#endif
+#endif /* TST_NS_COMMON_H__ */
diff --git a/testcases/lib/tst_ns_create.c b/testcases/lib/tst_ns_create.c
new file mode 100644
index 000000000..1c6258cd1
--- /dev/null
+++ b/testcases/lib/tst_ns_create.c
@@ -0,0 +1,92 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2015 Red Hat, Inc.
+ * Matus Marhefka <mmarhefk@redhat.com>
+ * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+ * Copyright (c) Linux Test Project, 2020-2023
+ */
+
+/*\
+ * [Description]
+ *
+ * Creates a child process in the new specified namespace(s), child is then
+ * daemonized and is running in the background. PID of the daemonized child
+ * process is printed on the stdout. As the new namespace(s) is(are) maintained
+ * by the daemonized child process it(they) can be removed by killing this
+ * process.
+ */
+
+#define TST_NO_DEFAULT_MAIN
+
+#include <stdio.h>
+#include <string.h>
+#include "tst_test.h"
+#include "tst_ns_common.h"
+
+extern struct tst_test *tst_test;
+
+static struct tst_test test = {
+ .forks_child = 1, /* Needed by SAFE_CLONE */
+};
+
+static void print_help(void)
+{
+ int i;
+
+ printf("usage: tst_ns_create <%s", params[0].name);
+
+ for (i = 1; params[i].name; i++)
+ printf("|,%s", params[i].name);
+
+ printf(">\n");
+}
+
+static void child_fn(void)
+{
+ int i;
+
+ SAFE_SETSID();
+ SAFE_CHDIR("/");
+
+ for (i = 0; i < SAFE_SYSCONF(_SC_OPEN_MAX); i++)
+ close(i);
+
+ printf("pausing child\n");
+ pause();
+}
+
+int main(int argc, char *argv[])
+{
+ struct tst_clone_args args = { 0, SIGCHLD };
+ char *token;
+ int pid;
+
+ if (argc < 2) {
+ print_help();
+ return 1;
+ }
+
+ tst_test = &test;
+
+ while ((token = strsep(&argv[1], ","))) {
+ struct param *p = get_param(token);
+
+ if (!p) {
+ printf("Unknown namespace: %s\n", token);
+ print_help();
+ return 1;
+ }
+
+ args.flags |= p->flag;
+ }
+
+ pid = SAFE_CLONE(&args);
+ if (!pid) {
+ child_fn();
+ return 0;
+ }
+
+ printf("%d", pid);
+
+ return 0;
+}
diff --git a/testcases/lib/tst_ns_exec.c b/testcases/lib/tst_ns_exec.c
new file mode 100644
index 000000000..66a4e69d3
--- /dev/null
+++ b/testcases/lib/tst_ns_exec.c
@@ -0,0 +1,115 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2015 Red Hat, Inc.
+ * Matus Marhefka <mmarhefk@redhat.com>
+ * Copyright (c) Linux Test Project, 2015-2023
+ * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * [Description]
+ *
+ * Enters the namespace(s) of a process specified by a PID and then executes
+ * the indicated program inside that namespace(s).
+ */
+
+#define TST_NO_DEFAULT_MAIN
+
+#include <stdio.h>
+#include <sys/wait.h>
+#include "tst_test.h"
+#include "tst_ns_common.h"
+
+extern struct tst_test *tst_test;
+
+static struct tst_test test = {
+ .forks_child = 1, /* Needed by SAFE_CLONE */
+};
+
+static int ns_fd[NS_TOTAL];
+static int ns_fds;
+
+static void print_help(void)
+{
+ int i;
+
+ printf("usage: tst_ns_exec <NS_PID> <%s", params[0].name);
+
+ for (i = 1; params[i].name; i++)
+ printf("|,%s", params[i].name);
+
+ printf("> <PROGRAM> [ARGS]\nSecond argument indicates the types"
+ " of a namespaces maintained by NS_PID\nand is specified"
+ " as a comma separated list.\n"
+ "Example: tst_ns_exec 1234 net,ipc ip a\n");
+}
+
+static void open_ns_fd(const char *pid, const char *ns)
+{
+ int fd;
+ char file_buf[64];
+
+ sprintf(file_buf, "%s/%s/ns/%s", PROC_PATH, pid, ns);
+
+ fd = SAFE_OPEN(file_buf, O_RDONLY);
+ ns_fd[ns_fds] = fd;
+
+ ++ns_fds;
+}
+
+static void close_ns_fd(void)
+{
+ int i;
+
+ for (i = 0; i < ns_fds; i++)
+ SAFE_CLOSE(ns_fd[i]);
+}
+
+int main(int argc, char *argv[])
+{
+ struct tst_clone_args args = { 0, SIGCHLD };
+ int i, status, pid;
+ char *token;
+
+ tst_test = &test;
+
+ if (argc < 4) {
+ print_help();
+ return 1;
+ }
+
+ memset(ns_fd, 0, sizeof(ns_fd));
+
+ while ((token = strsep(&argv[2], ","))) {
+ struct param *p = get_param(token);
+
+ if (!p) {
+ printf("Unknown namespace: %s\n", token);
+ print_help();
+ return 1;
+ }
+
+ open_ns_fd(argv[1], token);
+ }
+
+ if (!ns_fds) {
+ printf("no namespace entries in /proc/%s/ns/\n", argv[1]);
+ return 1;
+ }
+
+ for (i = 0; i < ns_fds; i++)
+ SAFE_SETNS(ns_fd[i], 0);
+
+ pid = SAFE_CLONE(&args);
+ if (!pid)
+ SAFE_EXECVP(argv[3], argv+3);
+
+ SAFE_WAITPID(pid, &status, 0);
+
+ close_ns_fd();
+
+ if (WIFEXITED(status))
+ return WEXITSTATUS(status);
+
+ return 0;
+}
diff --git a/testcases/lib/tst_ns_ifmove.c b/testcases/lib/tst_ns_ifmove.c
new file mode 100644
index 000000000..03531fc9b
--- /dev/null
+++ b/testcases/lib/tst_ns_ifmove.c
@@ -0,0 +1,92 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/* Copyright (c) 2015 Red Hat, Inc.
+ * Copyright (c) Linux Test Project, 2015-2022
+ * Copyright (c) 2023 Petr Vorel <pvorel@suse.cz>
+ * Written by Matus Marhefka <mmarhefk@redhat.com>
+ */
+
+/*\
+ * [Description]
+ *
+ * Moves a network interface to the namespace of a process specified by a PID.
+ */
+
+#include "config.h"
+
+#define TST_NO_DEFAULT_MAIN
+#include "tst_test.h"
+#include "tst_safe_macros.h"
+#include "tst_safe_net.h"
+
+#include <linux/if.h>
+#include <linux/rtnetlink.h>
+#include <net/ethernet.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef HAVE_DECL_IFLA_NET_NS_PID
+
+static struct {
+ struct nlmsghdr nh;
+ struct ifinfomsg ifi;
+ char attrbuf[512];
+} req;
+
+
+static int get_intf_index_from_name(const char *intf_name)
+{
+ struct ifreq ifr;
+ int sock_fd;
+
+ memset(&ifr, 0, sizeof(ifr));
+ strncpy(ifr.ifr_name, intf_name, sizeof(ifr.ifr_name) - 1);
+ ifr.ifr_name[sizeof(ifr.ifr_name)-1] = '\0';
+
+ sock_fd = SAFE_SOCKET(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
+
+ /* interface index */
+ SAFE_IOCTL(sock_fd, SIOCGIFINDEX, &ifr);
+ SAFE_CLOSE(sock_fd);
+
+ return ifr.ifr_ifindex;
+}
+
+int main(int argc, char **argv)
+{
+ struct rtattr *rta;
+ int intf_index, pid, rtnetlink_socket;
+
+ if (argc != 3) {
+ printf("tst_ns_ifmove <INTERFACE_NAME> <NAMESPACE_PID>\n");
+ return 1;
+ }
+
+ intf_index = get_intf_index_from_name(argv[1]);
+ pid = atoi(argv[2]);
+ rtnetlink_socket = SAFE_SOCKET(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
+
+ memset(&req, 0, sizeof(req));
+ req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
+ req.nh.nlmsg_flags = NLM_F_REQUEST;
+ req.nh.nlmsg_type = RTM_NEWLINK;
+ req.ifi.ifi_family = AF_UNSPEC;
+ req.ifi.ifi_index = intf_index;
+ req.ifi.ifi_change = 0xffffffff;
+ rta = (struct rtattr *)(((char *) &req) +
+ NLMSG_ALIGN(req.nh.nlmsg_len));
+ rta->rta_type = IFLA_NET_NS_PID;
+ rta->rta_len = RTA_LENGTH(sizeof(int));
+ req.nh.nlmsg_len = NLMSG_ALIGN(req.nh.nlmsg_len) +
+ RTA_LENGTH(sizeof(pid));
+ memcpy(RTA_DATA(rta), &pid, sizeof(pid));
+
+ SAFE_SEND(1, rtnetlink_socket, &req, req.nh.nlmsg_len, 0);
+ SAFE_CLOSE(rtnetlink_socket);
+
+ return 0;
+}
+
+#else
+ TST_TEST_TCONF("IFLA_NET_NS_PID not defined in linux/if_link.h");
+#endif
diff --git a/testcases/lib/tst_secureboot_enabled.c b/testcases/lib/tst_secureboot_enabled.c
new file mode 100644
index 000000000..dadc0413c
--- /dev/null
+++ b/testcases/lib/tst_secureboot_enabled.c
@@ -0,0 +1,12 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2023 Petr Vorel <pvorel@suse.cz>
+ */
+
+#define TST_NO_DEFAULT_MAIN
+#include "tst_test.h"
+
+int main(void)
+{
+ return tst_secureboot_enabled() <= 0;
+}
diff --git a/testcases/lib/tst_test.sh b/testcases/lib/tst_test.sh
index 3bd68a63a..b3f451a21 100644
--- a/testcases/lib/tst_test.sh
+++ b/testcases/lib/tst_test.sh
@@ -532,7 +532,7 @@ _tst_cleanup_timer()
{
if [ -n "$_tst_setup_timer_pid" ]; then
kill -TERM $_tst_setup_timer_pid 2>/dev/null
- # kill is succesful only on test timeout
+ # kill is successful only on test timeout
wait $_tst_setup_timer_pid 2>/dev/null || true
fi
}
@@ -682,7 +682,7 @@ tst_run()
CHECKPOINT_WAIT|CHECKPOINT_WAKE);;
CHECKPOINT_WAKE2|CHECKPOINT_WAKE_AND_WAIT);;
DEV_EXTRA_OPTS|DEV_FS_OPTS|FORMAT_DEVICE|MOUNT_DEVICE);;
- SKIP_FILESYSTEMS);;
+ SKIP_FILESYSTEMS|SKIP_IN_LOCKDOWN|SKIP_IN_SECUREBOOT);;
*) tst_res TWARN "Reserved variable TST_$_tst_i used!";;
esac
done
@@ -702,6 +702,14 @@ tst_run()
[ "$TST_NEEDS_ROOT" = 1 ] && tst_require_root
+ if [ "$TST_SKIP_IN_SECUREBOOT" = 1 ] && tst_secureboot_enabled; then
+ tst_brk TCONF "SecureBoot enabled, skipping test"
+ fi
+
+ if [ "$TST_SKIP_IN_LOCKDOWN" = 1 ] && tst_lockdown_enabled; then
+ tst_brk TCONF "Kernel is locked down, skipping test"
+ fi
+
[ "$TST_DISABLE_APPARMOR" = 1 ] && tst_disable_apparmor
[ "$TST_DISABLE_SELINUX" = 1 ] && tst_disable_selinux
@@ -726,6 +734,8 @@ tst_run()
fi
TST_TMPDIR=$(mktemp -d "$TMPDIR/LTP_$TST_ID.XXXXXXXXXX")
+ # remove possible trailing slash or double slashes from TMPDIR
+ TST_TMPDIR=$(echo "$TST_TMPDIR" | sed 's~/\+~/~g')
chmod 777 "$TST_TMPDIR"
diff --git a/testcases/network/iptables/iptables_lib.sh b/testcases/network/iptables/iptables_lib.sh
index ab76cbd41..767008869 100755
--- a/testcases/network/iptables/iptables_lib.sh
+++ b/testcases/network/iptables/iptables_lib.sh
@@ -22,7 +22,7 @@ NFRUN()
if [ "$use_iptables" = 1 ]; then
ip${TST_IPV6}tables $@
else
- $(ip${TST_IPV6}tables-translate $@ | sed 's,\\,,g')
+ $(ip${TST_IPV6}tables-translate $@ | sed "s/[\']//g")
fi
}
@@ -66,9 +66,9 @@ init()
cleanup()
{
if lsmod | grep -q "ip${TST_IPV6}_tables"; then
- NFTRUN -F -t filter > /dev/null 2>&1
- NFTRUN -F -t nat > /dev/null 2>&1
- NFTRUN -F -t mangle > /dev/null 2>&1
+ NFRUN -F -t filter > /dev/null 2>&1
+ NFRUN -F -t nat > /dev/null 2>&1
+ NFRUN -F -t mangle > /dev/null 2>&1
rmmod -v ipt_limit ipt_multiport ipt_LOG ipt_REJECT \
ip${TST_IPV6}table_mangle ip${TST_IPV6}table_nat ip_conntrack \
ip${TST_IPV6}table_filter ip${TST_IPV6}_tables nf_nat_ipv${TST_IPVER} nf_nat \
diff --git a/testcases/network/lib6/asapi_01.c b/testcases/network/lib6/asapi_01.c
index a34b8aee6..ac1de5418 100644
--- a/testcases/network/lib6/asapi_01.c
+++ b/testcases/network/lib6/asapi_01.c
@@ -33,7 +33,7 @@
#include "test.h"
#include "safe_macros.h"
-char *TCID = "asapi_04";
+char *TCID = "asapi_01";
static pid_t pid;
diff --git a/testcases/network/lib6/asapi_02.c b/testcases/network/lib6/asapi_02.c
index f8c30f1df..7808b2c3a 100644
--- a/testcases/network/lib6/asapi_02.c
+++ b/testcases/network/lib6/asapi_02.c
@@ -1,102 +1,98 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
- * Copyright (c) 2015 Fujitsu Ltd.
+ * Copyright (c) 2023 FUJITSU LIMITED. All rights reserved.
* Copyright (c) International Business Machines Corp., 2001
+ * Author: David L Stevens
+ */
+
+/*\
+ * [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 3 of the License, or
- * (at your option) any later version.
+ * Basic test for ICMP6_FILTER.
*
- * 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.
+ * For ICMP6_FILTER usage, refer to: https://man.openbsd.org/icmp6.
*
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * Because of the extra functionality of ICMPv6 in comparison to ICMPv4, a
+ * larger number of messages may be potentially received on an ICMPv6 socket.
+ * Input filters may therefore be used to restrict input to a subset of the
+ * incoming ICMPv6 messages so only interesting messages are returned by the
+ * recv(2) family of calls to an application.
+
+ * The icmp6_filter structure may be used to refine the input message set
+ * according to the ICMPv6 type. By default, all messages types are allowed
+ * on newly created raw ICMPv6 sockets. The following macros may be used to
+ * refine the input set, thus being tested:
*
- * Author: David L Stevens
+ * void ICMP6_FILTER_SETPASSALL(struct icmp6_filter *filterp)
+ * &ndash; Allow all incoming messages. filterp is modified to allow all message types.
+ *
+ * void ICMP6_FILTER_SETBLOCKALL(struct icmp6_filter *filterp)
+ * &ndash; Ignore all incoming messages. filterp is modified to ignore all message types.
+ *
+ * void ICMP6_FILTER_SETPASS(int, struct icmp6_filter *filterp)
+ * &ndash; Allow ICMPv6 messages with the given type. filterp is modified to allow such
+ * messages.
+ *
+ * void ICMP6_FILTER_SETBLOCK(int, struct icmp6_filter *filterp)
+ * &ndash; Ignore ICMPv6 messages with the given type. filterp is modified to ignore
+ * such messages.
+ *
+ * int ICMP6_FILTER_WILLPASS(int, const struct icmp6_filter *filterp)
+ * &ndash; Determine if the given filter will allow an ICMPv6 message of the given type.
+ *
+ * int ICMP6_FILTER_WILLBLOCK(int, const struct icmp6_filter *)
+ * &ndash; Determine if the given filter will ignore an ICMPv6 message of the given type.
+ *
+ * The getsockopt(2) and setsockopt(2) calls may be used to obtain and install
+ * the filter on ICMPv6 sockets at option level IPPROTO_ICMPV6 and name ICMP6_FILTER
+ * with a pointer to the icmp6_filter structure as the option value.
*/
-#include <stdio.h>
-#include <unistd.h>
-#include <errno.h>
-
-#include <sys/wait.h>
-#include <sys/socket.h>
-
-#include <netinet/in.h>
-#include <netinet/ip6.h>
#include <netinet/icmp6.h>
+#include "tst_test.h"
-#include "test.h"
-#include "safe_macros.h"
+static int sall = -1, sf = -1;
-char *TCID = "asapi_05";
-
-static void setup(void);
-
-static void icmp6_ft(void);
-
-int main(int argc, char *argv[])
-{
- int lc;
-
- tst_parse_opts(argc, argv, NULL, NULL);
-
- setup();
-
- for (lc = 0; TEST_LOOPING(lc); ++lc)
- icmp6_ft();
-
- tst_exit();
-}
-
-static void setup(void)
-{
- TEST_PAUSE;
- tst_require_root();
-}
-
-enum tt {
- T_WILLPASS,
- T_WILLBLOCK,
- T_SETPASS,
- T_SETBLOCK,
- T_SETPASSALL,
- T_SETBLOCKALL
+enum filter_macro {
+ FILTER_SETPASS,
+ FILTER_SETBLOCK,
+ FILTER_PASSALL,
+ FILTER_BLOCKALL,
+ FILTER_WILLBLOCK,
+ FILTER_WILLPASS
};
-static struct ftent {
- char *ft_tname; /* test name, for logging */
- unsigned char ft_sndtype; /* send type field */
- unsigned char ft_flttype; /* filter type field */
- enum tt ft_test; /* what macro to test */
- int ft_expected; /* packet should pass? */
-} ftab[] = {
- {"ICMP6_FILTER_SETPASS s 20 f 20", 20, 20, T_SETPASS, 1},
- {"ICMP6_FILTER_SETPASS s 20 f 21", 20, 21, T_SETPASS, 0},
- {"ICMP6_FILTER_SETBLOCK s 20 f 20", 20, 20, T_SETBLOCK, 0},
- {"ICMP6_FILTER_SETBLOCK s 20 f 21", 20, 21, T_SETBLOCK, 1},
- {"ICMP6_FILTER_PASSALL s 20", 20, 0, T_SETPASSALL, 1},
- {"ICMP6_FILTER_PASSALL s 20", 21, 0, T_SETPASSALL, 1},
- {"ICMP6_FILTER_BLOCKALL s 20", 20, 0, T_SETBLOCKALL, 0},
- {"ICMP6_FILTER_BLOCKALL s 20", 21, 0, T_SETBLOCKALL, 0},
- {"ICMP6_FILTER_WILLBLOCK s 20 f 21", 20, 21, T_WILLBLOCK, 0},
- {"ICMP6_FILTER_WILLBLOCK s 20 f 20", 20, 20, T_WILLBLOCK, 1},
- {"ICMP6_FILTER_WILLPASS s 20 f 21", 20, 21, T_WILLPASS, 0},
- {"ICMP6_FILTER_WILLPASS s 22 f 22", 22, 22, T_WILLPASS, 1},
+#define DESC(x, y, z) .tname = "ICMP6_" #x ", send type: " #y ", filter type: " \
+ #z, .send_type = y, .filter_type = z, .test_macro = x
+
+static struct tcase {
+ char *tname;
+ unsigned char send_type;
+ unsigned char filter_type;
+ enum filter_macro test_macro;
+ int pass_packet;
+} tcases[] = {
+ {DESC(FILTER_SETPASS, 20, 20), .pass_packet = 1},
+ {DESC(FILTER_SETPASS, 20, 21)},
+ {DESC(FILTER_SETBLOCK, 20, 20)},
+ {DESC(FILTER_SETBLOCK, 20, 21), .pass_packet = 1},
+ {DESC(FILTER_PASSALL, 20, 20), .pass_packet = 1},
+ {DESC(FILTER_PASSALL, 21, 0), .pass_packet = 1},
+ {DESC(FILTER_BLOCKALL, 20, 0)},
+ {DESC(FILTER_BLOCKALL, 21, 0)},
+ {DESC(FILTER_WILLBLOCK, 20, 21)},
+ {DESC(FILTER_WILLBLOCK, 20, 20), .pass_packet = 1},
+ {DESC(FILTER_WILLPASS, 20, 21)},
+ {DESC(FILTER_WILLPASS, 22, 22), .pass_packet = 1},
};
-#define FTCOUNT ARRAY_SIZE(ftab)
-
-static int ic6_send1(char *tname, unsigned char type)
+static void ic6_send(unsigned char type)
{
struct sockaddr_in6 sin6;
struct icmp6_hdr ic6;
int s;
- s = SAFE_SOCKET(NULL, AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
+ s = SAFE_SOCKET(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
memset(&ic6, 0, sizeof(ic6));
ic6.icmp6_type = type;
@@ -105,22 +101,15 @@ static int ic6_send1(char *tname, unsigned char type)
memset(&sin6, 0, sizeof(sin6));
sin6.sin6_family = AF_INET6;
sin6.sin6_addr = in6addr_loopback;
- if (sendto(s, &ic6, sizeof(ic6), 0, (struct sockaddr *)&sin6,
- sizeof(sin6)) == -1) {
- tst_resm(TBROK | TERRNO, "%s: sendto failed", tname);
- return 1;
- }
- return 0;
+ SAFE_SENDTO(0, s, &ic6, sizeof(ic6), 0, (struct sockaddr *)&sin6, sizeof(sin6));
}
-static int ic6_recv1(char *tname, int sall, int sf)
+static int ic6_recv(void)
{
fd_set readfds, readfds_saved;
struct timeval tv;
- int maxfd, nfds;
- int gotall, gotone;
- int cc;
- static unsigned char rbuf[2048];
+ int maxfd, nfds, gotall, gotone;
+ unsigned char rbuf[2048];
tv.tv_sec = 0;
tv.tv_usec = 250000;
@@ -133,129 +122,120 @@ static int ic6_recv1(char *tname, int sall, int sf)
memcpy(&readfds, &readfds_saved, sizeof(readfds));
gotall = gotone = 0;
- /*
- * Note: this relies on linux-specific behavior (select
- * updating tv with time elapsed)
- */
+
while (!gotall || !gotone) {
struct icmp6_hdr *pic6 = (struct icmp6_hdr *)rbuf;
nfds = select(maxfd + 1, &readfds, 0, 0, &tv);
if (nfds == 0)
- break; /* timed out */
+ break;
+
if (nfds < 0) {
if (errno == EINTR)
continue;
- tst_resm(TBROK | TERRNO, "%s: select failed", tname);
+ tst_brk(TBROK | TERRNO, "select failed");
}
+
if (FD_ISSET(sall, &readfds)) {
- cc = recv(sall, rbuf, sizeof(rbuf), 0);
- if (cc < 0) {
- tst_resm(TBROK | TERRNO,
- "%s: recv(sall, ..) failed", tname);
- return -1;
- }
- /* if packet check succeeds... */
+ SAFE_RECV(0, sall, rbuf, sizeof(rbuf), 0);
if (htonl(pic6->icmp6_data32[0]) == (uint32_t)getpid())
gotall = 1;
}
+
if (FD_ISSET(sf, &readfds)) {
- cc = recv(sf, rbuf, sizeof(rbuf), 0);
- if (cc < 0) {
- tst_resm(TBROK | TERRNO,
- "%s: recv(sf, ..) failed", tname);
- return -1;
- }
- /* if packet check succeeds... */
+ SAFE_RECV(0, sf, rbuf, sizeof(rbuf), 0);
if (htonl(pic6->icmp6_data32[0]) == (uint32_t)getpid())
gotone = 1;
}
memcpy(&readfds, &readfds_saved, sizeof(readfds));
}
+
if (!gotall) {
- tst_resm(TBROK, "%s: recv all timed out", tname);
+ tst_res(TFAIL, "recv all time out");
return -1;
}
+
if (gotone)
return 1;
+
return 0;
}
-/* functional tests */
-static void icmp6_ft(void)
+static void verify_icmp6_filter(unsigned int n)
{
+ struct tcase *tc = &tcases[n];
struct icmp6_filter i6f;
- int sall, sf;
- unsigned int i;
+ int rc;
+
+ tst_res(TINFO, "Testing %s", tc->tname);
+
+ switch (tc->test_macro) {
+ case FILTER_SETPASS:
+ ICMP6_FILTER_SETBLOCKALL(&i6f);
+ ICMP6_FILTER_SETPASS(tc->filter_type, &i6f);
+ break;
+ case FILTER_PASSALL:
+ ICMP6_FILTER_SETPASSALL(&i6f);
+ break;
+ case FILTER_SETBLOCK:
+ ICMP6_FILTER_SETPASSALL(&i6f);
+ ICMP6_FILTER_SETBLOCK(tc->filter_type, &i6f);
+ break;
+ case FILTER_BLOCKALL:
+ ICMP6_FILTER_SETBLOCKALL(&i6f);
+ break;
+ case FILTER_WILLBLOCK:
+ ICMP6_FILTER_SETPASSALL(&i6f);
+ ICMP6_FILTER_SETBLOCK(tc->filter_type, &i6f);
+ rc = ICMP6_FILTER_WILLBLOCK(tc->send_type, &i6f);
+ TST_EXP_EXPR(rc == tc->pass_packet, "%d (%d)", tc->pass_packet, rc);
+ return;
+ case FILTER_WILLPASS:
+ ICMP6_FILTER_SETBLOCKALL(&i6f);
+ ICMP6_FILTER_SETPASS(tc->filter_type, &i6f);
+ rc = ICMP6_FILTER_WILLPASS(tc->send_type, &i6f);
+ TST_EXP_EXPR(rc == tc->pass_packet, "%d (%d)", tc->pass_packet, rc);
+ return;
+ default:
+ tst_brk(TBROK, "unknown test type %d", tc->filter_type);
+ break;
+ }
- sall = SAFE_SOCKET(NULL, PF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
+ SAFE_SETSOCKOPT(sf, IPPROTO_ICMPV6, ICMP6_FILTER, &i6f, sizeof(i6f));
+ ic6_send(tc->send_type);
- ICMP6_FILTER_SETPASSALL(&i6f);
- if (setsockopt(sall, IPPROTO_ICMPV6, ICMP6_FILTER, &i6f,
- sizeof(i6f)) < 0) {
- tst_resm(TBROK | TERRNO,
- "setsockopt pass all ICMP6_FILTER failed");
- }
+ rc = ic6_recv();
+ if (rc < 0)
+ return;
- sf = SAFE_SOCKET(NULL, PF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
+ TST_EXP_EXPR(rc == tc->pass_packet, "%s packet type %d",
+ rc ? "pass" : "block", tc->send_type);
+}
- int rv;
+static void setup(void)
+{
+ struct icmp6_filter i6f;
- for (i = 0; i < FTCOUNT; ++i) {
+ sall = SAFE_SOCKET(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
+ ICMP6_FILTER_SETPASSALL(&i6f);
+ SAFE_SETSOCKOPT(sall, IPPROTO_ICMPV6, ICMP6_FILTER, &i6f, sizeof(i6f));
- rv = -1;
+ sf = SAFE_SOCKET(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
+}
- switch (ftab[i].ft_test) {
- case T_SETPASS:
- ICMP6_FILTER_SETBLOCKALL(&i6f);
- ICMP6_FILTER_SETPASS(ftab[i].ft_flttype, &i6f);
- break;
- case T_SETPASSALL:
- ICMP6_FILTER_SETPASSALL(&i6f);
- break;
- case T_SETBLOCK:
- ICMP6_FILTER_SETPASSALL(&i6f);
- ICMP6_FILTER_SETBLOCK(ftab[i].ft_flttype, &i6f);
- break;
- case T_SETBLOCKALL:
- ICMP6_FILTER_SETBLOCKALL(&i6f);
- break;
- case T_WILLBLOCK:
- ICMP6_FILTER_SETPASSALL(&i6f);
- ICMP6_FILTER_SETBLOCK(ftab[i].ft_flttype, &i6f);
- rv = ICMP6_FILTER_WILLBLOCK(ftab[i].ft_sndtype, &i6f);
- break;
- case T_WILLPASS:
- ICMP6_FILTER_SETBLOCKALL(&i6f);
- ICMP6_FILTER_SETPASS(ftab[i].ft_flttype, &i6f);
- rv = ICMP6_FILTER_WILLPASS(ftab[i].ft_sndtype, &i6f);
- break;
- default:
- tst_resm(TBROK, "%s: unknown test type %d",
- ftab[i].ft_tname, ftab[i].ft_test);
- continue;
- }
- if (ftab[i].ft_test != T_WILLBLOCK &&
- ftab[i].ft_test != T_WILLPASS) {
- if (setsockopt(sf, IPPROTO_ICMPV6, ICMP6_FILTER, &i6f,
- sizeof(i6f)) < 0) {
- tst_resm(TFAIL | TERRNO,
- "setsockopt ICMP6_FILTER");
- continue;
- }
- if (ic6_send1(ftab[i].ft_tname, ftab[i].ft_sndtype))
- continue;
- rv = ic6_recv1(ftab[i].ft_tname, sall, sf);
- } else {
- rv = -1;
- }
+static void cleanup(void)
+{
+ if (sall > -1)
+ SAFE_CLOSE(sall);
- if (rv < 0)
- continue;
- if (rv != ftab[i].ft_expected)
- tst_resm(TFAIL, "%s: rv %d != expected %d",
- ftab[i].ft_tname, rv, ftab[i].ft_expected);
- else
- tst_resm(TPASS, "%s", ftab[i].ft_tname);
- }
+ if (sf > -1)
+ SAFE_CLOSE(sf);
}
+
+static struct tst_test test = {
+ .needs_root = 1,
+ .setup = setup,
+ .cleanup = cleanup,
+ .test = verify_icmp6_filter,
+ .tcnt = ARRAY_SIZE(tcases)
+};
diff --git a/testcases/network/lib6/asapi_03.c b/testcases/network/lib6/asapi_03.c
index 2124ba7d9..87d050add 100644
--- a/testcases/network/lib6/asapi_03.c
+++ b/testcases/network/lib6/asapi_03.c
@@ -43,7 +43,7 @@
#include "test.h"
#include "safe_macros.h"
-char *TCID = "asapi_06";
+char *TCID = "asapi_03";
int TST_TOTAL = 1;
diff --git a/testcases/network/netstress/netstress.c b/testcases/network/netstress/netstress.c
index 6a888f2ee..fb6281cd0 100644
--- a/testcases/network/netstress/netstress.c
+++ b/testcases/network/netstress/netstress.c
@@ -384,6 +384,7 @@ void *client_fn(void *id)
inf.raddr_len = sizeof(inf.raddr);
inf.etime_cnt = 0;
+ inf.eshutdown_cnt = 0;
inf.timeout = wait_timeout;
inf.pmtu_err_cnt = 0;
diff --git a/testcases/network/nfs/nfs_stress/Makefile b/testcases/network/nfs/nfs_stress/Makefile
index 8cd095867..5b396dede 100644
--- a/testcases/network/nfs/nfs_stress/Makefile
+++ b/testcases/network/nfs/nfs_stress/Makefile
@@ -9,13 +9,6 @@ include $(top_srcdir)/include/mk/testcases.mk
nfs04_create_file: CPPFLAGS += -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
nfs05_make_tree: LDLIBS += -lpthread
-INSTALL_TARGETS := nfs_lib.sh \
- nfs01.sh \
- nfs02.sh \
- nfs03.sh \
- nfs04.sh \
- nfs05.sh \
- nfs06.sh \
- nfs07.sh
+INSTALL_TARGETS := *.sh
include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/network/nfs/nfs_stress/nfs03.sh b/testcases/network/nfs/nfs_stress/nfs03.sh
index e5f4de67c..e9ef5fb78 100755
--- a/testcases/network/nfs/nfs_stress/nfs03.sh
+++ b/testcases/network/nfs/nfs_stress/nfs03.sh
@@ -66,11 +66,13 @@ do_test()
cd ../dir1
wait $pid1
rm_files &
+ pid3=$!
tst_res TINFO "cd dir2 & removing files"
cd ../dir2
wait $pid2
rm_files
+ wait $pid3
tst_res TPASS "test done"
}
diff --git a/testcases/network/nfs/nfs_stress/nfs05.sh b/testcases/network/nfs/nfs_stress/nfs05.sh
index c18ef1ab4..760b585e4 100755
--- a/testcases/network/nfs/nfs_stress/nfs05.sh
+++ b/testcases/network/nfs/nfs_stress/nfs05.sh
@@ -8,9 +8,9 @@
#
# Created by: Robbie Williamson (robbiew@us.ibm.com)
-DIR_NUM=${DIR_NUM:-"10"}
-FILE_NUM=${FILE_NUM:-"30"}
-THREAD_NUM=${THREAD_NUM:-"8"}
+DIR_NUM=${DIR_NUM:-"5"}
+FILE_NUM=${FILE_NUM:-"20"}
+THREAD_NUM=${THREAD_NUM:-"5"}
TST_NEEDS_CMDS="make gcc"
TST_TESTFUNC="do_test"
diff --git a/testcases/network/nfs/nfs_stress/nfs06.sh b/testcases/network/nfs/nfs_stress/nfs06.sh
index d51f7dc82..560df05b1 100755
--- a/testcases/network/nfs/nfs_stress/nfs06.sh
+++ b/testcases/network/nfs/nfs_stress/nfs06.sh
@@ -11,7 +11,8 @@
TST_TESTFUNC="do_test"
TST_CLEANUP="do_cleanup"
-THREAD_NUM=${THREAD_NUM:-"2"}
+THREAD_NUM="${THREAD_NUM:-2}"
+OPERATION_NUM="${OPERATION_NUM:-1000}"
do_cleanup()
{
@@ -26,7 +27,7 @@ do_test()
local n=0
local pids
for i in $VERSION; do
- fsstress -l 1 -d $TST_TMPDIR/$i/$n -n 1000 -p $THREAD_NUM -r -c > /dev/null &
+ fsstress -l 1 -d $TST_TMPDIR/$i/$n -n $OPERATION_NUM -p $THREAD_NUM -r -c > /dev/null &
pids="$pids $!"
n=$(( n + 1 ))
done
diff --git a/testcases/network/nfs/nfs_stress/nfs08.sh b/testcases/network/nfs/nfs_stress/nfs08.sh
new file mode 100755
index 000000000..759b4e418
--- /dev/null
+++ b/testcases/network/nfs/nfs_stress/nfs08.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0-or-later
+# Copyright (c) 2023 Petr Vorel <pvorel@suse.cz>
+# Test for broken NFS cache invalidation for directories.
+# Kernel patch broke cache invalidation, which caused the second 'ls'
+# not shown '2'.
+# https://lore.kernel.org/linux-nfs/167649314509.15170.15885497881041431304@noble.neil.brown.name/
+# Based on reproducer from Neil Brown <neilb@suse.de>
+
+TST_TESTFUNC="do_test"
+
+do_test()
+{
+ tst_res TINFO "testing NFS cache invalidation for directories"
+
+ touch 1
+ EXPECT_PASS 'ls | grep 1'
+ touch 2
+ EXPECT_PASS 'ls | grep 2'
+}
+
+. nfs_lib.sh
+tst_run
diff --git a/testcases/network/nfs/nfs_stress/nfs_lib.sh b/testcases/network/nfs/nfs_stress/nfs_lib.sh
index af7d46a21..a996f7cc8 100644
--- a/testcases/network/nfs/nfs_stress/nfs_lib.sh
+++ b/testcases/network/nfs/nfs_stress/nfs_lib.sh
@@ -1,6 +1,6 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0-or-later
-# Copyright (c) Linux Test Project, 2016-2022
+# Copyright (c) Linux Test Project, 2016-2023
# Copyright (c) 2015-2018 Oracle and/or its affiliates. All Rights Reserved.
# Copyright (c) International Business Machines Corp., 2001
@@ -28,7 +28,10 @@ NFS_PARSE_ARGS_CALLER="$TST_PARSE_ARGS"
TST_OPTS="v:t:$TST_OPTS"
TST_PARSE_ARGS=nfs_parse_args
TST_USAGE=nfs_usage
-TST_NEEDS_TMPDIR=1
+TST_ALL_FILESYSTEMS=1
+TST_SKIP_FILESYSTEMS="exfat,ext2,ext3,fuse,ntfs,vfat,tmpfs"
+TST_MOUNT_DEVICE=1
+TST_FORMAT_DEVICE=1
TST_NEEDS_ROOT=1
TST_NEEDS_CMDS="$TST_NEEDS_CMDS mount exportfs mount.nfs"
TST_SETUP="${TST_SETUP:-nfs_setup}"
@@ -53,6 +56,24 @@ get_socket_type()
done
}
+# directory mounted by NFS client
+get_local_dir()
+{
+ local v="$1"
+ local n="$2"
+
+ echo "$TST_TMPDIR/$v/$n"
+}
+
+# directory on NFS server
+get_remote_dir()
+{
+ local v="$1"
+ local n="$2"
+
+ echo "$TST_MNTPOINT/$v/$n"
+}
+
nfs_get_remote_path()
{
local v
@@ -63,7 +84,7 @@ nfs_get_remote_path()
done
v=${1:-$v}
- echo "$TST_TMPDIR/$v/$type"
+ echo "$(get_remote_dir $v $type)"
}
nfs_server_udp_enabled()
@@ -78,8 +99,8 @@ nfs_server_udp_enabled()
nfs_setup_server()
{
-
- local fsid="$1"
+ local remote_dir="$1"
+ local fsid="$2"
local export_cmd="exportfs -i -o fsid=$fsid,no_root_squash,rw *:$remote_dir"
[ -z "$fsid" ] && tst_brk TBROK "empty fsid"
@@ -97,10 +118,14 @@ nfs_setup_server()
nfs_mount()
{
- local opts="$1"
+ local local_dir="$1"
+ local remote_dir="$2"
+ local opts="$3"
local host_type=rhost
local mount_dir
+ mkdir -p "$local_dir"
+
tst_net_use_netns && host_type=
if [ $TST_IPV6 ]; then
@@ -131,6 +156,8 @@ nfs_mount()
tst_brk TBROK "mount command failed"
fi
+
+ cd "$local_dir"
}
nfs_setup()
@@ -162,20 +189,14 @@ nfs_setup()
tst_brk TCONF "UDP support disabled on NFS server"
fi
- local_dir="$TST_TMPDIR/$i/$n"
- remote_dir="$TST_TMPDIR/$i/$type"
- mkdir -p $local_dir
-
- nfs_setup_server $(($$ + n))
-
- nfs_mount "-o proto=$type,vers=$i"
+ remote_dir="$(get_remote_dir $i $type)"
+ nfs_setup_server "$remote_dir" "$(($$ + n))"
+ local_dir="$(get_local_dir $i $n)"
+ tst_res TINFO "Mounting $local_dir"
+ nfs_mount "$local_dir" "$remote_dir" "-o proto=$type,vers=$i"
n=$(( n + 1 ))
done
-
- if [ "$n" -eq 1 ]; then
- cd ${VERSION}/0
- fi
}
nfs_cleanup()
@@ -190,17 +211,32 @@ nfs_cleanup()
local n=0
for i in $VERSION; do
- local_dir="$TST_TMPDIR/$i/$n"
- grep -q "$local_dir" /proc/mounts && umount $local_dir
+ local_dir="$(get_local_dir $i $n)"
+ if grep -q "$local_dir" /proc/mounts; then
+ tst_res TINFO "Unmounting $local_dir"
+ umount $local_dir
+ fi
n=$(( n + 1 ))
done
+ sleep 2
n=0
for i in $VERSION; do
type=$(get_socket_type $n)
- remote_dir="$TST_TMPDIR/$i/$type"
- tst_rhost_run -c "test -d $remote_dir && exportfs -u *:$remote_dir"
- tst_rhost_run -c "test -d $remote_dir && rm -rf $remote_dir"
+ remote_dir="$(get_remote_dir $i $type)"
+
+ if tst_net_use_netns; then
+ if test -d $remote_dir; then
+ exportfs -u *:$remote_dir
+ sleep 1
+ rm -rf $remote_dir
+ fi
+ else
+ tst_rhost_run -c "test -d $remote_dir && exportfs -u *:$remote_dir"
+ sleep 1
+ tst_rhost_run -c "test -d $remote_dir && rm -rf $remote_dir"
+ fi
+
n=$(( n + 1 ))
done
}
diff --git a/testcases/network/nfs/nfslock01/nfs_flock.c b/testcases/network/nfs/nfslock01/nfs_flock.c
index a7673c751..02f105b22 100644
--- a/testcases/network/nfs/nfslock01/nfs_flock.c
+++ b/testcases/network/nfs/nfslock01/nfs_flock.c
@@ -1,7 +1,17 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
+ * Copyright (c) Linux Test Project, 2001-2023
+ * Copyright (c) International Business Machines Corp., 2001
+ */
+
+/*\
+ * [Description]
+ *
* Program for testing file locking. The original data file consists of
* characters from 'A' to 'Z'. The data file after running this program
* would consist of lines with 1's in even lines and 0's in odd lines.
+ *
+ * Used in nfslock01.sh.
*/
#include "nfs_flock.h"
@@ -10,69 +20,91 @@
#include <stdlib.h>
#include <unistd.h>
-#define BYTES 64
-#define LINES 16384
-
int main(int argc, char **argv)
{
- int i, fd, mac;
+ int i, fd, mac, nchars, nlines;
int offset = 0;
char buf[BUFSIZ];
- if (argc != 3) {
- fprintf(stderr, "Usage: %s <mac num> <file name>\n", argv[0]);
+ if (argc != 5) {
+ fprintf(stderr, "Usage: %s <mac num> <file name> <nchars> <nlines>\n",
+ argv[0]);
exit(2);
}
- if ((fd = open(argv[2], O_RDWR)) < 0) {
+ fd = open(argv[2], O_RDWR);
+ if (fd < 0) {
perror("opening a file");
exit(1);
}
mac = atoi(argv[1]);
+ nchars = atoi(argv[3]);
+ nlines = atoi(argv[4]);
+
+ if (nchars > BUFSIZ) {
+ fprintf(stderr, "Exceeded the maximum limit of the buffer (%d)\n", BUFSIZ);
+ exit(3);
+ }
+
+ if (nchars < 1) {
+ fprintf(stderr, "<char/line> must be > 0\n");
+ exit(3);
+ }
+
+ if (nlines < 1) {
+ fprintf(stderr, "<lines> must be > 0\n");
+ exit(3);
+ }
/*
* Replace a line of characters by 1's if it is process one
- * else with 0's. Number of charcters in any line are BYTES-1,
+ * else with 0's. Number of charcters in any line are nchars-1,
* the last character being a newline character.
*/
- for (i = 0; i < BYTES - 1; i++) {
+ for (i = 0; i < nchars - 1; i++) {
if (mac == 1)
buf[i] = '1';
else
buf[i] = '0';
}
- buf[BYTES - 1] = '\n';
+ buf[nchars - 1] = '\n';
- for (i = 0; i < LINES; i++) {
+ for (i = 0; i < nlines; i++) {
if (mac == 1) { /* Set the offset to even lines */
if ((i % 2) == 0) {
if (i == 0)
offset = 0;
else
- offset += 2 * BYTES;
+ offset += 2 * nchars;
} else
continue;
} else { /* Set the offset to odd lines */
if ((i % 2) == 1) {
if (i == 1)
- offset = BYTES;
+ offset = nchars;
else
- offset += 2 * BYTES;
+ offset += 2 * nchars;
} else
continue;
}
- if (writeb_lock(fd, offset, SEEK_SET, BYTES) < 0)
- printf("failed in writeb_lock, Errno = %d", errno);
+ if (writeb_lock(fd, offset, SEEK_SET, nchars) < 0) {
+ fprintf(stderr, "failed in writeb_lock, errno = %d\n", errno);
+ exit(1);
+ }
lseek(fd, offset, SEEK_SET);
- /* write to the test file */
- write(fd, buf, BYTES);
+ if (write(fd, buf, nchars) < 0) {
+ fprintf(stderr, "failed to write buffer to test file, errno = %d\n", errno);
+ exit(1);
+ }
- if (unb_lock(fd, offset, SEEK_SET, BYTES) < 0)
- printf("failed in unb_lock, Errno = %d", errno);
+ if (unb_lock(fd, offset, SEEK_SET, nchars) < 0) {
+ fprintf(stderr, "failed in unb_lock, errno = %d\n", errno);
+ exit(1);
+ }
}
exit(0);
}
diff --git a/testcases/network/nfs/nfslock01/nfs_flock.h b/testcases/network/nfs/nfslock01/nfs_flock.h
index 09e3845f4..fba4a7f02 100644
--- a/testcases/network/nfs/nfslock01/nfs_flock.h
+++ b/testcases/network/nfs/nfslock01/nfs_flock.h
@@ -1,3 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) Linux Test Project, 2001-2009
+ * Copyright (c) International Business Machines Corp., 2001
+ */
+
#include <stdio.h>
#include <sys/stat.h>
#include <errno.h>
diff --git a/testcases/network/nfs/nfslock01/nfs_flock_dgen.c b/testcases/network/nfs/nfslock01/nfs_flock_dgen.c
index 2b33ca974..6ecdcdc4f 100644
--- a/testcases/network/nfs/nfslock01/nfs_flock_dgen.c
+++ b/testcases/network/nfs/nfslock01/nfs_flock_dgen.c
@@ -1,5 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
- * This program generates data for testing file locking
+ * Copyright (c) Linux Test Project, 2001-2023
+ * Copyright (c) International Business Machines Corp., 2001
+ */
+
+/*\
+ * [Description]
+ *
+ * Tool to generate data for testing file locking.
+ * Used in nfslock01.sh.
*/
#include <stdio.h>
@@ -13,32 +22,39 @@ int main(int argc, char **argv)
FILE *fp;
if (argc != 5) {
- printf
- ("usage: <nfs_flock_dgen> <file> <char/line> <lines> <ctype>\n");
+ fprintf(stderr, "usage: <nfs_flock_dgen> <file> <char/line> <lines> <ctype>\n");
exit(2);
}
fp = fopen(argv[1], "w");
nchars = atoi(argv[2]);
+ nlines = atoi(argv[3]);
+ ctype = atoi(argv[4]);
+
if (nchars > BUFSIZ) {
- printf("Exceeded the maximum limit of the buffer (%d)\n",
- BUFSIZ);
+ fprintf(stderr, "Exceeded the maximum limit of the buffer (%d)\n", BUFSIZ);
+ exit(3);
+ }
+
+ if (nchars < 1) {
+ fprintf(stderr, "<char/line> must be > 0\n");
+ exit(3);
+ }
+
+ if (nlines < 1) {
+ fprintf(stderr, "<lines> must be > 0\n");
exit(3);
}
- nlines = atoi(argv[3]);
- ctype = atoi(argv[4]);
k = 0;
for (i = 1; i <= nlines; i++) {
-
if (ctype)
c = ((i % 2) ? '1' : '0');
else
c = 'A' + k;
- for (j = 0; j < nchars; j++)
-
+ for (j = 0; j < nchars - 1; j++)
buf[j] = c;
fprintf(fp, "%s\n", buf);
@@ -53,5 +69,6 @@ int main(int argc, char **argv)
}
fclose(fp);
- return (0);
+
+ return 0;
}
diff --git a/testcases/network/nfs/nfslock01/nfs_flock_func.c b/testcases/network/nfs/nfslock01/nfs_flock_func.c
index 811136188..aee66f40b 100644
--- a/testcases/network/nfs/nfslock01/nfs_flock_func.c
+++ b/testcases/network/nfs/nfslock01/nfs_flock_func.c
@@ -1,3 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) Linux Test Project, 2001-2012
+ * Copyright (c) International Business Machines Corp., 2001
+ */
+
#include <stdlib.h>
#include <unistd.h>
diff --git a/testcases/network/nfs/nfslock01/nfslock01.sh b/testcases/network/nfs/nfslock01/nfslock01.sh
index fbcc3c00f..01d59ce85 100755
--- a/testcases/network/nfs/nfslock01/nfslock01.sh
+++ b/testcases/network/nfs/nfslock01/nfslock01.sh
@@ -1,6 +1,6 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0-or-later
-# Copyright (c) Linux Test Project, 2002-2022
+# Copyright (c) Linux Test Project, 2002-2023
# Copyright (c) 2016-2018 Oracle and/or its affiliates. All Rights Reserved.
# Copyright (c) International Business Machines Corp., 2001
#
@@ -13,19 +13,42 @@
TST_SETUP="do_setup"
TST_TESTFUNC="do_test"
+NCHARS=${NCHARS:-64}
+NLINES=${NLINES:-16384}
+
+generate_file()
+{
+ local file="$1"
+ local nchars="$2"
+ local nlines="$3"
+ local val="$4"
+ local exp_size="$((nchars*nlines))"
+ local size
+
+ ROD nfs_flock_dgen $file $nchars $nlines $val
+
+ size="$(wc -c $file | awk '{print $1}')"
+ if [ $size -ne $exp_size ]; then
+ tst_brk TBROK "could not create '$file' (size: $size, expected: $exp_size)"
+ fi
+}
+
do_setup()
{
- nfs_setup
+ if ! tst_is_int $NCHARS || [ $NCHARS -lt 1 ]; then
+ tst_res TBROK "NCHARS must be > 0"
+ fi
- tst_res TINFO "creating test files"
- ROD nfs_flock_dgen flock_data 63 16384 0
- ROD nfs_flock_dgen flock_odata 63 16384 1
+ if ! tst_is_int $NLINES || [ $NLINES -lt 1 ]; then
+ tst_res TBROK "NLINES must be > 0"
+ fi
+
+ nfs_setup
- [ "$(wc -c flock_data | awk '{print $1}')" -ne 1048576 ] && \
- tst_brk TBROK "could not create 'flock_data'"
+ tst_res TINFO "creating test files (chars: $NCHARS, lines: $NLINES)"
- [ "$(wc -c flock_odata | awk '{print $1}')" -ne 1048576 ] && \
- tst_brk TBROK "could not create 'flock_odata'"
+ generate_file flock_data $NCHARS $NLINES 0
+ generate_file flock_odata $NCHARS $NLINES 1
}
do_test()
@@ -36,9 +59,9 @@ do_test()
tst_res TINFO "locking 'flock_idata' file and writing data"
- nfs_flock 0 flock_idata &
+ nfs_flock 0 flock_idata $NCHARS $NLINES &
local pids=$!
- nfs_flock 1 flock_idata &
+ nfs_flock 1 flock_idata $NCHARS $NLINES &
pids="$pids $!"
tst_res TINFO "waiting for pids: $pids"
diff --git a/testcases/network/rpc/rpc-tirpc/tests_pack/rpc_suite/rpc/rpc_broadc_clnt_broadcast/rpc_clnt_broadcast.c b/testcases/network/rpc/rpc-tirpc/tests_pack/rpc_suite/rpc/rpc_broadc_clnt_broadcast/rpc_clnt_broadcast.c
index 5f024f113..80d5f045a 100644
--- a/testcases/network/rpc/rpc-tirpc/tests_pack/rpc_suite/rpc/rpc_broadc_clnt_broadcast/rpc_clnt_broadcast.c
+++ b/testcases/network/rpc/rpc-tirpc/tests_pack/rpc_suite/rpc/rpc_broadc_clnt_broadcast/rpc_clnt_broadcast.c
@@ -59,7 +59,8 @@ int main(int argn, char *argc[])
//Call broadcast routine
cs = clnt_broadcast(progNum, VERSNUM, PROCNUM,
(xdrproc_t) xdr_int, (char *)&varSnd,
- (xdrproc_t) xdr_int, (char *)&varRec, eachResult);
+ (xdrproc_t) xdr_int, (char *)&varRec,
+ (resultproc_t) eachResult);
test_status = (cs == RPC_SUCCESS) ? 0 : 1;
diff --git a/testcases/network/rpc/rpc-tirpc/tests_pack/rpc_suite/rpc/rpc_broadc_clnt_broadcast/rpc_clnt_broadcast_complex.c b/testcases/network/rpc/rpc-tirpc/tests_pack/rpc_suite/rpc/rpc_broadc_clnt_broadcast/rpc_clnt_broadcast_complex.c
index c6e55cd81..e1bb8fcc5 100644
--- a/testcases/network/rpc/rpc-tirpc/tests_pack/rpc_suite/rpc/rpc_broadc_clnt_broadcast/rpc_clnt_broadcast_complex.c
+++ b/testcases/network/rpc/rpc-tirpc/tests_pack/rpc_suite/rpc/rpc_broadc_clnt_broadcast/rpc_clnt_broadcast_complex.c
@@ -78,7 +78,8 @@ int main(int argn, char *argc[])
//Call broadcast routine
cs = clnt_broadcast(progNum, VERSNUM, PROCNUM,
(xdrproc_t) xdr_int, (char *)&varSnd,
- (xdrproc_t) xdr_int, (char *)&varRec, eachResult);
+ (xdrproc_t) xdr_int, (char *)&varRec,
+ (resultproc_t) eachResult);
if (currentAnswer == maxAnswer)
test_status = 0;
diff --git a/testcases/network/rpc/rpc-tirpc/tests_pack/rpc_suite/rpc/rpc_broadc_clnt_broadcast/rpc_clnt_broadcast_dataint.c b/testcases/network/rpc/rpc-tirpc/tests_pack/rpc_suite/rpc/rpc_broadc_clnt_broadcast/rpc_clnt_broadcast_dataint.c
index fdf1e31a2..e1f7bcb6a 100644
--- a/testcases/network/rpc/rpc-tirpc/tests_pack/rpc_suite/rpc/rpc_broadc_clnt_broadcast/rpc_clnt_broadcast_dataint.c
+++ b/testcases/network/rpc/rpc-tirpc/tests_pack/rpc_suite/rpc/rpc_broadc_clnt_broadcast/rpc_clnt_broadcast_dataint.c
@@ -72,7 +72,8 @@ int main(int argn, char *argc[])
clnt_broadcast(progNum, VERSNUM, INTPROCNUM,
(xdrproc_t) xdr_int, (char *)&intSnd,
- (xdrproc_t) xdr_int, (char *)&intRec, eachResult);
+ (xdrproc_t) xdr_int, (char *)&intRec,
+ (resultproc_t) eachResult);
if (intSnd != intRec)
test_status = 1;
@@ -84,7 +85,8 @@ int main(int argn, char *argc[])
clnt_broadcast(progNum, VERSNUM, INTPROCNUM,
(xdrproc_t) xdr_int, (char *)&intSnd,
- (xdrproc_t) xdr_int, (char *)&intRec, eachResult);
+ (xdrproc_t) xdr_int, (char *)&intRec,
+ (resultproc_t) eachResult);
if (intSnd != intRec)
test_status = 1;
@@ -96,7 +98,8 @@ int main(int argn, char *argc[])
clnt_broadcast(progNum, VERSNUM, LNGPROCNUM,
(xdrproc_t) xdr_long, (char *)&lngSnd,
- (xdrproc_t) xdr_long, (char *)&lngRec, eachResult);
+ (xdrproc_t) xdr_long, (char *)&lngRec,
+ (resultproc_t) eachResult);
if (lngSnd != lngRec)
test_status = 1;
@@ -108,7 +111,8 @@ int main(int argn, char *argc[])
clnt_broadcast(progNum, VERSNUM, LNGPROCNUM,
(xdrproc_t) xdr_double, (char *)&dblSnd,
- (xdrproc_t) xdr_double, (char *)&dblRec, eachResult);
+ (xdrproc_t) xdr_double, (char *)&dblRec,
+ (resultproc_t) eachResult);
if (dblSnd != dblRec)
test_status = 1;
@@ -121,7 +125,8 @@ int main(int argn, char *argc[])
clnt_broadcast(progNum, VERSNUM, LNGPROCNUM,
(xdrproc_t) xdr_wrapstring, (char *)&strSnd,
- (xdrproc_t) xdr_wrapstring, (char *)&strRec, eachResult);
+ (xdrproc_t) xdr_wrapstring, (char *)&strRec,
+ (resultproc_t) eachResult);
if (strcmp(strSnd, strRec))
test_status = 1;
diff --git a/testcases/network/rpc/rpc-tirpc/tests_pack/rpc_suite/rpc/rpc_broadc_clnt_broadcast/rpc_clnt_broadcast_performance.c b/testcases/network/rpc/rpc-tirpc/tests_pack/rpc_suite/rpc/rpc_broadc_clnt_broadcast/rpc_clnt_broadcast_performance.c
index 11ba64fab..d733e72ef 100644
--- a/testcases/network/rpc/rpc-tirpc/tests_pack/rpc_suite/rpc/rpc_broadc_clnt_broadcast/rpc_clnt_broadcast_performance.c
+++ b/testcases/network/rpc/rpc-tirpc/tests_pack/rpc_suite/rpc/rpc_broadc_clnt_broadcast/rpc_clnt_broadcast_performance.c
@@ -114,7 +114,7 @@ int main(int argn, char *argc[])
cs = clnt_broadcast(progNum, VERSNUM, PROCNUM,
(xdrproc_t) xdr_int, (char *)&varSnd,
(xdrproc_t) xdr_int, (char *)&varRec,
- eachResult);
+ (resultproc_t) eachResult);
if (cs != RPC_SUCCESS)
clnt_perrno(cs);
diff --git a/testcases/network/rpc/rpc-tirpc/tests_pack/rpc_suite/rpc/rpc_broadc_clnt_broadcast/rpc_clnt_broadcast_scalability.c b/testcases/network/rpc/rpc-tirpc/tests_pack/rpc_suite/rpc/rpc_broadc_clnt_broadcast/rpc_clnt_broadcast_scalability.c
index 57ea25349..4455c1173 100644
--- a/testcases/network/rpc/rpc-tirpc/tests_pack/rpc_suite/rpc/rpc_broadc_clnt_broadcast/rpc_clnt_broadcast_scalability.c
+++ b/testcases/network/rpc/rpc-tirpc/tests_pack/rpc_suite/rpc/rpc_broadc_clnt_broadcast/rpc_clnt_broadcast_scalability.c
@@ -114,7 +114,7 @@ int main(int argn, char *argc[])
cs = clnt_broadcast(progNum, VERSNUM, PROCNUM,
(xdrproc_t) xdr_int, (char *)&varSnd,
(xdrproc_t) xdr_int, (char *)&varRec,
- eachResult);
+ (resultproc_t) eachResult);
if (cs != RPC_SUCCESS)
clnt_perrno(cs);
diff --git a/testcases/network/rpc/rpc-tirpc/tests_pack/rpc_suite/rpc/rpc_broadc_clnt_broadcast/rpc_clnt_broadcast_stress.c b/testcases/network/rpc/rpc-tirpc/tests_pack/rpc_suite/rpc/rpc_broadc_clnt_broadcast/rpc_clnt_broadcast_stress.c
index d5d7d85d1..933305482 100644
--- a/testcases/network/rpc/rpc-tirpc/tests_pack/rpc_suite/rpc/rpc_broadc_clnt_broadcast/rpc_clnt_broadcast_stress.c
+++ b/testcases/network/rpc/rpc-tirpc/tests_pack/rpc_suite/rpc/rpc_broadc_clnt_broadcast/rpc_clnt_broadcast_stress.c
@@ -65,7 +65,7 @@ int main(int argn, char *argc[])
cs = clnt_broadcast(progNum, VERSNUM, PROCNUM,
(xdrproc_t) xdr_int, (char *)&varSnd,
(xdrproc_t) xdr_int, (char *)&varRec,
- eachResult);
+ (resultproc_t) eachResult);
if (cs == RPC_SUCCESS)
nbOk++;
}
diff --git a/testcases/network/rpc/rpc-tirpc/tests_pack/rpc_suite/rpc/rpc_regunreg_registerrpc/rpc_registerrpc.c b/testcases/network/rpc/rpc-tirpc/tests_pack/rpc_suite/rpc/rpc_regunreg_registerrpc/rpc_registerrpc.c
index 3becf4600..c6fb3e0f6 100644
--- a/testcases/network/rpc/rpc-tirpc/tests_pack/rpc_suite/rpc/rpc_regunreg_registerrpc/rpc_registerrpc.c
+++ b/testcases/network/rpc/rpc-tirpc/tests_pack/rpc_suite/rpc/rpc_regunreg_registerrpc/rpc_registerrpc.c
@@ -67,9 +67,8 @@ int main(int argn, char *argc[])
svcr = svcudp_create(RPC_ANYSOCK);
//call routine
- rslt =
- registerrpc(progNum, VERSNUM, PROCNUM, simplePing, xdr_int,
- xdr_int);
+ rslt = registerrpc(progNum, VERSNUM, PROCNUM, simplePing,
+ (xdrproc_t) xdr_int, (xdrproc_t) xdr_int);
if (run_mode) {
printf("SVC : %p\n", svcr);
diff --git a/testcases/network/sctp/sctp_big_chunk.c b/testcases/network/sctp/sctp_big_chunk.c
index a6a326ea2..467486846 100644
--- a/testcases/network/sctp/sctp_big_chunk.c
+++ b/testcases/network/sctp/sctp_big_chunk.c
@@ -1,9 +1,15 @@
// SPDX-License-Identifier: GPL-2.0-or-later
-/* Copyright (c) 2018 Oracle and/or its affiliates. All Rights Reserved.
+/*
+ * Copyright (c) 2018 Oracle and/or its affiliates. All Rights Reserved.
+ * Copyright (c) Linux Test Project, 2019-2023
+ */
+
+/*\
+ * [Description]
*
- * Regression test-case for the crash caused by over-sized SCTP chunk,
+ * Regression test for the crash caused by over-sized SCTP chunk,
* fixed by upstream commit 07f2c7ab6f8d ("sctp: verify size of a new
- * chunk in _sctp_make_chunk()")
+ * chunk in _sctp_make_chunk()").
*/
#include <stdlib.h>
@@ -34,6 +40,26 @@ static int addr_num = 3273;
static void setup_server(void)
{
+ const char hmac_algo_path[] = "/proc/sys/net/sctp/cookie_hmac_alg";
+ char hmac_algo[CHAR_MAX];
+ int hmac_algo_changed = 0;
+ int fd;
+
+ /* Disable md5 if fips is enabled. Set it to none */
+ if (tst_fips_enabled()) {
+ /* Load sctp module */
+ if (access(hmac_algo_path, F_OK) < 0) {
+ fd = SAFE_SOCKET(PF_INET, SOCK_STREAM, IPPROTO_SCTP);
+ SAFE_CLOSE(fd);
+ }
+
+ if (!access(hmac_algo_path, F_OK)) {
+ SAFE_FILE_SCANF(hmac_algo_path, "%s", hmac_algo);
+ SAFE_FILE_PRINTF(hmac_algo_path, "%s", "none");
+ hmac_algo_changed = 1;
+ }
+ }
+
loc.sin6_family = AF_INET6;
loc.sin6_addr = in6addr_loopback;
@@ -46,6 +72,9 @@ static void setup_server(void)
SAFE_LISTEN(sfd, 1);
srand(port);
+
+ if (hmac_algo_changed)
+ SAFE_FILE_PRINTF(hmac_algo_path, "%s", hmac_algo);
}
static void update_packet_field(size_t *off, void *buf, size_t buf_len)
diff --git a/testcases/network/sockets/vsock01.c b/testcases/network/sockets/vsock01.c
index 1e688df19..7be71a83b 100644
--- a/testcases/network/sockets/vsock01.c
+++ b/testcases/network/sockets/vsock01.c
@@ -8,10 +8,11 @@
*
* Reproducer of CVE-2021-26708
*
- * Based on POC https://github.com/jordan9001/vsock_poc
+ * Based on POC https://github.com/jordan9001/vsock_poc.
* Fuzzy Sync has been substituted for userfaultfd.
*
* Fixed by: c518adafa39f ("vsock: fix the race conditions in multi-transport support")
+ *
* Fixes: c0cfa2d8a788fcf4 ("vsock: add multi-transports support")
*
* Note that in many testing environments this will reproduce the race
diff --git a/testcases/network/stress/udp/multi-diffip/udp4-multi-diffip01 b/testcases/network/stress/udp/multi-diffip/udp4-multi-diffip01
index 92af9e438..c0d50efaf 100644
--- a/testcases/network/stress/udp/multi-diffip/udp4-multi-diffip01
+++ b/testcases/network/stress/udp/multi-diffip/udp4-multi-diffip01
@@ -230,7 +230,7 @@ while [ $ipaddr_pair_num -lt $IP_TOTAL_FOR_TCPIP ]; do
# Set IPv6 addresses to the interfaces
ip addr add ${lhost_addr}/${network_mask} dev $lhost_ifname
- if [ $ret -eq 2 ]; then
+ if [ $? -eq 2 ]; then
ip addr del ${lhost_addr}/${network_mask} dev $lhost_ifname 2>&1
ip addr add ${lhost_addr}/${network_mask} dev $lhost_ifname
fi
diff --git a/testcases/network/tcp_cmds/ipneigh/ipneigh01.sh b/testcases/network/tcp_cmds/ipneigh/ipneigh01.sh
index 644a1fb8d..e67ff5cc8 100755
--- a/testcases/network/tcp_cmds/ipneigh/ipneigh01.sh
+++ b/testcases/network/tcp_cmds/ipneigh/ipneigh01.sh
@@ -25,7 +25,7 @@ do_setup()
if [ -n "$TST_IPV6" ]; then
tst_brk TCONF "'arp' doesn't support IPv6"
fi
- SHOW_CMD="arp -a"
+ SHOW_CMD="arp -an"
DEL_CMD="ROD arp -d $(tst_ipaddr rhost) -i $(tst_iface)"
;;
*)
diff --git a/testcases/open_posix_testsuite/conformance/interfaces/aio_read/8-1.c b/testcases/open_posix_testsuite/conformance/interfaces/aio_read/8-1.c
index 8a6c024a9..e0fecd805 100644
--- a/testcases/open_posix_testsuite/conformance/interfaces/aio_read/8-1.c
+++ b/testcases/open_posix_testsuite/conformance/interfaces/aio_read/8-1.c
@@ -10,7 +10,7 @@
* assertion:
*
* The aio_read() function shall return the value -1 and set errno to
- * indicate error if the operation is not succesfully queued.
+ * indicate error if the operation is not successfully queued.
*
* method:
*
diff --git a/testcases/open_posix_testsuite/conformance/interfaces/aio_read/assertions.xml b/testcases/open_posix_testsuite/conformance/interfaces/aio_read/assertions.xml
index e23c6bcf6..ae2062221 100644
--- a/testcases/open_posix_testsuite/conformance/interfaces/aio_read/assertions.xml
+++ b/testcases/open_posix_testsuite/conformance/interfaces/aio_read/assertions.xml
@@ -28,7 +28,7 @@
</assertion>
<assertion id="8" tag="ref:XSH6TC2:4155:4155">
The aio_read() function shall return the value -1 and set errno to
- indicate error if the operation is not succesfully queued.
+ indicate error if the operation is not successfully queued.
</assertion>
<assertion id="9" tag="ref:XSH6TC2:4158:4159">
aio_read() shall fail with [EAGAIN] if:
@@ -46,16 +46,16 @@
value, or aio_nbytes is an invalid value.
</assertion>
<assertion id="12" tag="ref:XSH6TC2:4174:4174">
- The error status of a succesfully queued operation shall be:
+ The error status of a successfully queued operation shall be:
[EBADF] if the aio_fildes argument is not a valid file descriptor open for
reading.
</assertion>
<assertion id="13" tag="ref:XSH6TC2:4375:4376">
- The error status of a succesfully queued operation shall be:
+ The error status of a successfully queued operation shall be:
[ECANCELED] if The requested I/O was canceled before the I/O completed.
</assertion>
<assertion id="14" tag="ref:XSH6TC2:4177:4177">
- The error status of a succesfully queued operation shall be:
+ The error status of a successfully queued operation shall be:
[EINVAL] if aio_offset would be invalid, or aio_reqprio is not a valid
value, or aio_nbytes is an invalid value.
</assertion>
diff --git a/testcases/open_posix_testsuite/conformance/interfaces/aio_write/6-1.c b/testcases/open_posix_testsuite/conformance/interfaces/aio_write/6-1.c
index 2948552c4..60428ce27 100644
--- a/testcases/open_posix_testsuite/conformance/interfaces/aio_write/6-1.c
+++ b/testcases/open_posix_testsuite/conformance/interfaces/aio_write/6-1.c
@@ -10,7 +10,7 @@
* assertion:
*
* The aio_write() function shall return the value -1 and set errno to
- indicate error if the operation is not succesfully queued.
+ indicate error if the operation is not successfully queued.
*
* method:
*
@@ -18,7 +18,6 @@
* aiocb with invalid aio_reqprio
* - call aio_write
* - check aio_write return value
- *
*/
#include <stdio.h>
diff --git a/testcases/open_posix_testsuite/conformance/interfaces/aio_write/assertions.xml b/testcases/open_posix_testsuite/conformance/interfaces/aio_write/assertions.xml
index 86694021f..e00774c61 100644
--- a/testcases/open_posix_testsuite/conformance/interfaces/aio_write/assertions.xml
+++ b/testcases/open_posix_testsuite/conformance/interfaces/aio_write/assertions.xml
@@ -21,7 +21,7 @@
</assertion>
<assertion id="6" tag="ref:XSH6TC2:4348:4349">
The aio_write() function shall return the value -1 and set errno to
- indicate error if the operation is not succesfully queued.
+ indicate error if the operation is not successfully queued.
</assertion>
<assertion id="7" tag="ref:XSH6TC2:4352:4353">
aio_write() shall fail with [EAGAIN] if:
@@ -38,17 +38,17 @@
aio_nbytes is an invalid value.
</assertion>
<assertion id="10" tag="ref:XSH6TC2:4369:4369">
- The error status of a succesfully queued operation shall be:
+ The error status of a successfully queued operation shall be:
[EBADF] if the aio_fildes argument is not a valid file descriptor open for
writing.
</assertion>
<assertion id="11" tag="ref:XSH6TC2:4370:4370">
- The error status of a succesfully queued operation shall be:
+ The error status of a successfully queued operation shall be:
[EINVAL] if aio_offset would be invalid, or aio_reqprio is not a valid
value, or aio_nbytes is an invalid value.
</assertion>
<assertion id="12" tag="ref:XSH6TC2:4371:4372">
- The error status of a succesfully queued operation shall be:
+ The error status of a successfully queued operation shall be:
[ECANCELED] The requested I/O was canceled before the I/O completed.
</assertion>
<assertion id="13" tag="ref:XSH6TC2:4374:4376">
diff --git a/testcases/open_posix_testsuite/conformance/interfaces/fork/assertions.xml b/testcases/open_posix_testsuite/conformance/interfaces/fork/assertions.xml
index 48abbfbe8..64793fc3f 100644
--- a/testcases/open_posix_testsuite/conformance/interfaces/fork/assertions.xml
+++ b/testcases/open_posix_testsuite/conformance/interfaces/fork/assertions.xml
@@ -83,7 +83,7 @@
</assertion>
<assertion id="23" tag="ref:XSH6TC2:13060:13062">
fork() returns 0 to the child and the child PID to the parent process when
- succesful.
+ successful.
</assertion>
<assertion id="24" tag="ref:XSH6TC2:13063:13069">
fork() returns -1, errno is set to EAGAIN, and no child process
diff --git a/testcases/open_posix_testsuite/conformance/interfaces/lio_listio/13-1.c b/testcases/open_posix_testsuite/conformance/interfaces/lio_listio/13-1.c
index 33915a440..48754f815 100644
--- a/testcases/open_posix_testsuite/conformance/interfaces/lio_listio/13-1.c
+++ b/testcases/open_posix_testsuite/conformance/interfaces/lio_listio/13-1.c
@@ -10,7 +10,7 @@
* assertion:
*
* if mode is LIO_WAIT, lio_listio() shall return the value -1 and set
- * errno to indicate error if the operation is not succesfully queued.
+ * errno to indicate error if the operation is not successfully queued.
*
* method:
*
diff --git a/testcases/open_posix_testsuite/conformance/interfaces/lio_listio/assertions.xml b/testcases/open_posix_testsuite/conformance/interfaces/lio_listio/assertions.xml
index 8832fdd3c..5aaa78a18 100644
--- a/testcases/open_posix_testsuite/conformance/interfaces/lio_listio/assertions.xml
+++ b/testcases/open_posix_testsuite/conformance/interfaces/lio_listio/assertions.xml
@@ -36,7 +36,7 @@
</assertion>
<assertion id="11" tag="ref:XSH6TC2:23084:23085">
if mode is LIO_NOWAIT, lio_listio() shall return the value -1 and set
- errno to indicate error if the operation is not succesfully queued.
+ errno to indicate error if the operation is not successfully queued.
</assertion>
<assertion id="12" tag="ref:XSH6TC2:23086:23087">
if mode is LIO_WAIT, lio_listio() shall return the value zero when
diff --git a/testcases/open_posix_testsuite/conformance/interfaces/mmap/6-5.c b/testcases/open_posix_testsuite/conformance/interfaces/mmap/6-5.c
index 33c0575c5..a27c91e46 100644
--- a/testcases/open_posix_testsuite/conformance/interfaces/mmap/6-5.c
+++ b/testcases/open_posix_testsuite/conformance/interfaces/mmap/6-5.c
@@ -71,7 +71,7 @@ int main(void)
munmap(pa, size);
close(fd);
- printf("Succesfully mapped readonly file with "
+ printf("Successfully mapped readonly file with "
"PROT_WRITE, MAP_PRIVATE\n" "Test PASSED\n");
return PTS_PASS;
}
diff --git a/testcases/open_posix_testsuite/conformance/interfaces/pthread_attr_getinheritsched/assertions.xml b/testcases/open_posix_testsuite/conformance/interfaces/pthread_attr_getinheritsched/assertions.xml
index 9b2c14717..a15504bd6 100644
--- a/testcases/open_posix_testsuite/conformance/interfaces/pthread_attr_getinheritsched/assertions.xml
+++ b/testcases/open_posix_testsuite/conformance/interfaces/pthread_attr_getinheritsched/assertions.xml
@@ -4,7 +4,7 @@ pthread_attr_getinheritsched shall get the inheritsched attribute in the attr ar
PTHREAD_INHERIT_SCHED and PTHREAD_EXPLICIT_SCHED are valid value.
</assertion>
<assertion id="2" tag="ref:XSH6:31347:31347">
-If succesful, the pthread_attr_getinheritsched shall return zero.
+If successful, the pthread_attr_getinheritsched shall return zero.
</assertion>
<assertion id="3" tag="ref:XSH6:31348:31348">
If fail, the pthread_attr_getinheritsched shall return an error number.
diff --git a/testcases/open_posix_testsuite/conformance/interfaces/pthread_attr_getscope/assertions.xml b/testcases/open_posix_testsuite/conformance/interfaces/pthread_attr_getscope/assertions.xml
index c201c4449..f6733520c 100644
--- a/testcases/open_posix_testsuite/conformance/interfaces/pthread_attr_getscope/assertions.xml
+++ b/testcases/open_posix_testsuite/conformance/interfaces/pthread_attr_getscope/assertions.xml
@@ -4,7 +4,7 @@ pthread_attr_getscope shall get the inheritsched attribute in the attr argument
The contentionscope attribute may have the values PTHREAD_SCOPE_SYSTEM, signifying system scheduling contention scope, or PTHREAD_SCOPE_PROCESS, signifying process scheduling contention scope.
</assertion>
<assertion id="2" tag="ref:XSH6:31492:31492">
-If succesful, the pthread_attr_getscope shall return zero.
+If successful, the pthread_attr_getscope shall return zero.
</assertion>
<assertion id="3" tag="ref:XSH6:31493:31493">
If fail, the pthread_attr_getscope shall return an error number.
diff --git a/testcases/open_posix_testsuite/conformance/interfaces/pthread_cond_destroy/3-1.c b/testcases/open_posix_testsuite/conformance/interfaces/pthread_cond_destroy/3-1.c
index d07a199cb..a618e98c8 100644
--- a/testcases/open_posix_testsuite/conformance/interfaces/pthread_cond_destroy/3-1.c
+++ b/testcases/open_posix_testsuite/conformance/interfaces/pthread_cond_destroy/3-1.c
@@ -6,8 +6,7 @@
* source tree.
* Test that pthread_cond_destroy()
- * Upon succesful completion, it shall return a 0
- *
+ * Upon successful completion, it shall return 0.
*/
#include <pthread.h>
diff --git a/testcases/open_posix_testsuite/conformance/interfaces/pthread_cond_init/3-1.c b/testcases/open_posix_testsuite/conformance/interfaces/pthread_cond_init/3-1.c
index f0402648f..886d0f04b 100644
--- a/testcases/open_posix_testsuite/conformance/interfaces/pthread_cond_init/3-1.c
+++ b/testcases/open_posix_testsuite/conformance/interfaces/pthread_cond_init/3-1.c
@@ -6,8 +6,7 @@
* source tree.
* Test that pthread_cond_init()
- * Upon succesful completion, it shall return a 0
- *
+ * Upon successful completion, it shall return 0.
*/
#include <pthread.h>
diff --git a/testcases/open_posix_testsuite/conformance/interfaces/pthread_detach/3-1.c b/testcases/open_posix_testsuite/conformance/interfaces/pthread_detach/3-1.c
index 4217afa4b..80cd2ad96 100644
--- a/testcases/open_posix_testsuite/conformance/interfaces/pthread_detach/3-1.c
+++ b/testcases/open_posix_testsuite/conformance/interfaces/pthread_detach/3-1.c
@@ -6,14 +6,12 @@
* source tree.
* Test that pthread_detach()
- *
- * Upon succesful completion, it shall return a 0;
+ * Upon successful completion, it shall return 0.
*
* STEPS:
* 1.Create a joinable thread
* 2.Detach that thread
* 3.Check the return value
- *
*/
#include <pthread.h>
diff --git a/testcases/open_posix_testsuite/conformance/interfaces/pthread_mutex_destroy/3-1.c b/testcases/open_posix_testsuite/conformance/interfaces/pthread_mutex_destroy/3-1.c
index 9ce4ca105..a8b032c53 100644
--- a/testcases/open_posix_testsuite/conformance/interfaces/pthread_mutex_destroy/3-1.c
+++ b/testcases/open_posix_testsuite/conformance/interfaces/pthread_mutex_destroy/3-1.c
@@ -6,8 +6,7 @@
* source tree.
* Test that pthread_mutex_destroy()
- * Upon succesful completion, it shall return a 0
- *
+ * Upon successful completion, it shall return 0.
*/
#include <pthread.h>
diff --git a/testcases/open_posix_testsuite/conformance/interfaces/pthread_mutex_init/4-1.c b/testcases/open_posix_testsuite/conformance/interfaces/pthread_mutex_init/4-1.c
index d7b4f204e..1df6e5af2 100644
--- a/testcases/open_posix_testsuite/conformance/interfaces/pthread_mutex_init/4-1.c
+++ b/testcases/open_posix_testsuite/conformance/interfaces/pthread_mutex_init/4-1.c
@@ -6,8 +6,7 @@
* source tree.
* Test that pthread_mutex_init()
- * Upon succesful completion, it shall return a 0
- *
+ * Upon successful completion, it shall return 0.
*/
#include <pthread.h>
diff --git a/testcases/open_posix_testsuite/conformance/interfaces/pthread_mutex_lock/2-1.c b/testcases/open_posix_testsuite/conformance/interfaces/pthread_mutex_lock/2-1.c
index 7e8827c4a..a8123ba58 100644
--- a/testcases/open_posix_testsuite/conformance/interfaces/pthread_mutex_lock/2-1.c
+++ b/testcases/open_posix_testsuite/conformance/interfaces/pthread_mutex_lock/2-1.c
@@ -6,8 +6,7 @@
* source tree.
* Test that pthread_mutex_lock()
- * Upon succesful completion, it shall return a 0
- *
+ * Upon successful completion, it shall return 0.
*/
#include <pthread.h>
diff --git a/testcases/open_posix_testsuite/conformance/interfaces/pthread_mutex_trylock/3-1.c b/testcases/open_posix_testsuite/conformance/interfaces/pthread_mutex_trylock/3-1.c
index 32151322d..ea81f99ca 100644
--- a/testcases/open_posix_testsuite/conformance/interfaces/pthread_mutex_trylock/3-1.c
+++ b/testcases/open_posix_testsuite/conformance/interfaces/pthread_mutex_trylock/3-1.c
@@ -6,8 +6,7 @@
* source tree.
* Test that pthread_mutex_trylock()
- * Upon succesful completion, it shall return a 0
- *
+ * Upon successful completion, it shall return 0.
*/
#include <pthread.h>
diff --git a/testcases/open_posix_testsuite/conformance/interfaces/pthread_mutex_unlock/3-1.c b/testcases/open_posix_testsuite/conformance/interfaces/pthread_mutex_unlock/3-1.c
index 4053388be..cb0ae72b6 100644
--- a/testcases/open_posix_testsuite/conformance/interfaces/pthread_mutex_unlock/3-1.c
+++ b/testcases/open_posix_testsuite/conformance/interfaces/pthread_mutex_unlock/3-1.c
@@ -6,8 +6,7 @@
* source tree.
* Test that pthread_mutex_unlock()
- * Upon succesful completion, it shall return zero
- *
+ * Upon successful completion, it shall return zero
*/
#include <pthread.h>
diff --git a/testcases/open_posix_testsuite/conformance/interfaces/pthread_sigmask/5-1.c b/testcases/open_posix_testsuite/conformance/interfaces/pthread_sigmask/5-1.c
index 63f6721c8..12f522e1f 100644
--- a/testcases/open_posix_testsuite/conformance/interfaces/pthread_sigmask/5-1.c
+++ b/testcases/open_posix_testsuite/conformance/interfaces/pthread_sigmask/5-1.c
@@ -5,7 +5,7 @@
* of this license, see the COPYING file at the top level of this
* source tree.
-The resulting set shall be the the signal set pointed to by set
+The resulting set shall be the signal set pointed to by set
Steps:
1. Have main create a new thread and wait for its termination.
diff --git a/testcases/open_posix_testsuite/conformance/interfaces/raise/2-1.c b/testcases/open_posix_testsuite/conformance/interfaces/raise/2-1.c
index 1dfee2efe..005f46a4b 100644
--- a/testcases/open_posix_testsuite/conformance/interfaces/raise/2-1.c
+++ b/testcases/open_posix_testsuite/conformance/interfaces/raise/2-1.c
@@ -5,7 +5,7 @@
* of this license, see the COPYING file at the top level of this
* source tree.
- * Test that the the raise() function does not return until after the
+ * Test that the raise() function does not return until after the
* signal handler it calls returns.
* This test is only performed on one signal. All other signals are
* considered to be in the same equivalence class.
diff --git a/testcases/open_posix_testsuite/conformance/interfaces/sched_setparam/2-1.c b/testcases/open_posix_testsuite/conformance/interfaces/sched_setparam/2-1.c
index fb19ff6a4..ee106c677 100644
--- a/testcases/open_posix_testsuite/conformance/interfaces/sched_setparam/2-1.c
+++ b/testcases/open_posix_testsuite/conformance/interfaces/sched_setparam/2-1.c
@@ -24,10 +24,10 @@
* 5. Both children and father increment a counter in a basic loop.
* 6. The father send SIGTERM to the last child and get its counter. If child
* counter is reasonably lower than the fathers one, the test is
- * succesfull.
+ * successful.
* 7. The father kill all other children.
- *
*/
+
#include "affinity.h"
#include <sched.h>
diff --git a/testcases/open_posix_testsuite/conformance/interfaces/sched_setparam/2-2.c b/testcases/open_posix_testsuite/conformance/interfaces/sched_setparam/2-2.c
index 6c68120c3..c81ffd374 100644
--- a/testcases/open_posix_testsuite/conformance/interfaces/sched_setparam/2-2.c
+++ b/testcases/open_posix_testsuite/conformance/interfaces/sched_setparam/2-2.c
@@ -24,9 +24,8 @@
* 5. Both children and father increment a counter in a basic loop.
* 6. The father send SIGTERM to the last child and get its counter. If child
* counter is reasonably lower than the fathers one, the test is
- * succesfull.
+ * successful.
* 7. The father kill all other children.
- *
*/
#include "affinity.h"
diff --git a/testcases/open_posix_testsuite/conformance/interfaces/sigqueue/assertions.xml b/testcases/open_posix_testsuite/conformance/interfaces/sigqueue/assertions.xml
index 37b96641b..86fc1d544 100644
--- a/testcases/open_posix_testsuite/conformance/interfaces/sigqueue/assertions.xml
+++ b/testcases/open_posix_testsuite/conformance/interfaces/sigqueue/assertions.xml
@@ -5,7 +5,7 @@
</assertion>
<assertion id="2" tag="ref:XSH6:42291:42293 pt:RTS">
Error checking is performed but no signal is actually sent, if signo is zero (the null signal).
- Using the null signal can be used to check the the validity of pid.
+ Using the null signal can be used to check the validity of pid.
</assertion>
<assertion id="3" tag="ref:XSH6:42294:42295 pt:RTS">
For a process to have permission to queue a signal to another process
diff --git a/testcases/realtime/func/matrix_mult/matrix_mult.c b/testcases/realtime/func/matrix_mult/matrix_mult.c
index e2a55628a..c32092344 100644
--- a/testcases/realtime/func/matrix_mult/matrix_mult.c
+++ b/testcases/realtime/func/matrix_mult/matrix_mult.c
@@ -100,7 +100,7 @@ static void matrix_mult(struct matrices *matrices)
matrix_init(matrices->A, matrices->B);
for (i = 0; i < MATRIX_SIZE; i++) {
- int i_m = MATRIX_SIZE - i;
+ int i_m = MATRIX_SIZE - i - 1;
for (j = 0; j < MATRIX_SIZE; j++) {
double sum = matrices->A[i_m][j] * matrices->B[j][i];
for (k = 0; k < MATRIX_SIZE; k++)
diff --git a/testcases/realtime/tools/ftqviz.py b/testcases/realtime/tools/ftqviz.py
index 5ac094cbd..f56d41aa6 100644
--- a/testcases/realtime/tools/ftqviz.py
+++ b/testcases/realtime/tools/ftqviz.py
@@ -45,7 +45,7 @@ def smooth(x, wlen):
# generate the smoothed signal
y = convolve(w/w.sum(), s, mode='same')
- # recenter the the smoothed signal over the originals (slide along x)
+ # recenter the smoothed signal over the originals (slide along x)
y1 = y[wlen-1:-wlen+1]
return y1