strace/tests/semop.c

137 lines
3.8 KiB
C
Raw Normal View History

#include "tests.h"
#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "xlat.h"
#include "xlat/semop_flags.h"
union semun {
int val;
struct semid_ds *buf;
unsigned short *array;
struct seminfo *__buf;
};
static int id = -1;
static void
cleanup(void)
{
semctl(id, 0, IPC_RMID, 0);
id = -1;
}
int
main(void)
{
static const int bogus_semid = 0xfdb97531;
static void * const bogus_sops = (void *) -1L;
static const size_t bogus_nsops = (size_t) 0xdefaceddeadbeefULL;
TAIL_ALLOC_OBJECT_CONST_PTR(struct timespec, ts);
int rc;
id = semget(IPC_PRIVATE, 1, 0600);
if (id < 0)
perror_msg_and_skip("semget");
atexit(cleanup);
union semun sem_union = { .val = 0 };
if (semctl(id, 0, SETVAL, sem_union) == -1)
perror_msg_and_skip("semctl");
TAIL_ALLOC_OBJECT_CONST_PTR(struct sembuf, sem_b);
TAIL_ALLOC_OBJECT_CONST_PTR(struct sembuf, sem_b2);
rc = semop(bogus_semid, NULL, bogus_nsops);
printf("semop(%d, NULL, %u) = %s\n",
bogus_semid, (unsigned) bogus_nsops, sprintrc(rc));
rc = semop(bogus_semid, bogus_sops, 1);
printf("semop(%d, %p, %u) = %s\n",
bogus_semid, bogus_sops, 1, sprintrc(rc));
sem_b->sem_num = 0;
sem_b->sem_op = 1;
sem_b->sem_flg = SEM_UNDO;
sem_b2->sem_num = 0xface;
sem_b2->sem_op = 0xf00d;
sem_b2->sem_flg = 0xbeef;
rc = semop(bogus_semid, sem_b2, 2);
print_array: enhance printing of unfetchable object addresses When umoven_func invocation fails to fetch data, it prints the faulty address. If this happens to a subsequent umoven_func invocation, the printed address may be undistinguishable from a valid data printed by print_func, e.g. when the data is printed in a numeric form like [0x1, 0x2, 0x3, 0xdefaced]. Fix this source of confusion by moving the printing of the faulty address from umoven_func to print_array itself. This change renames umoven_func to tfetch_mem_func and changes its semantics, so that - tfetch_mem_func never prints anything; - tfetch_mem_func returns true if the fetch succeeded, and false otherwise. * defs.h (print_array): Replace umoven_func argument with tfetch_mem_func. * util.c (print_array): Replace umoven_func argument with tfetch_mem_func, document expected tfetch_mem_func return value semantics. When tfetch_mem_func returns false, print either addr or "... /* addr */" depending on the context (inside the array or not). * bpf.c (print_ebpf_prog, print_bpf_prog_info, BEGIN_BPF_CMD_DECODER(BPF_PROG_QUERY)): Replace umoven_or_printaddr argument of print_array with tfetch_mem. * bpf_filter.c (print_bpf_fprog): Likewise. * btrfs.c (btrfs_print_logical_ino_container, btrfs_print_ino_path_container, btrfs_print_qgroup_inherit, btrfs_ioctl): Likewise. * dm.c (dm_decode_dm_target_deps): Likewise. * epoll.c (epoll_wait_common): Likewise. * file_ioctl.c (file_ioctl): Likewise. * ipc_sem.c (tprint_sembuf_array): Likewise. * kexec.c (print_kexec_segments): Likewise. * mem.c (SYS_FUNC(subpage_prot)): Likewise. * net.c (print_getsockopt): Likewise. * netlink.c (decode_nlmsgerr_attr_cookie): Likewise. * netlink_netlink_diag.c (decode_netlink_diag_groups): Likewise. * netlink_packet_diag.c (decode_packet_diag_mclist): Likewise. * netlink_unix_diag.c (decode_unix_diag_inode): Likewise. * nlattr.c (decode_nla_meminfo): Likewise. * numa.c (print_nodemask, SYS_FUNC(move_pages), * perf_ioctl.c (perf_ioctl_query_bpf): Likewise. * poll.c (decode_poll_entering): Likewise. * printsiginfo.c (print_siginfo_array): Likewise. * rtnl_tc.c (decode_tca_stab_data): Likewise. * sock.c (decode_ifconf): Likewise. * uid.c (print_groups): Likewise. * io.c (SYS_FUNC(io_submit), SYS_FUNC(io_getevents)): Replace umoven_or_printaddr argument of print_array with tfetch_mem. (tprint_iov_upto): Replace umoven_or_printaddr_ignore_syserror with tfetch_mem_ignore_syserror. * v4l2.c (print_v4l2_format_fmt): Replace umoven_or_printaddr argument of print_array with tfetch_mem. (print_v4l2_ext_controls): Replace umoven_or_printaddr_ignore_syserror with tfetch_mem_ignore_syserror. * mmsghdr.c (fetch_struct_mmsghdr_or_printaddr): Rename to fetch_struct_mmsghdr_for_print, do not print address, return bool. (decode_mmsgvec): Replace fetch_struct_mmsghdr_or_printaddr with fetch_struct_mmsghdr_for_print. * tests/aio.c (main): Update expected output. * tests/bpf.c (print_BPF_PROG_QUERY_attr5): Likewise. * tests/ioctl_perf-success.c (main): Likewise. * tests/ioctl_v4l2.c (main): Update expected output. * tests/kexec_load.c (main): Likewise. * tests/mmsg_name.c (test_mmsg_name): Update expected output. * tests/move_pages.c (print_page_array, print_node_array): Likewise. * tests/poll.c (print_pollfd_array_entering): Likewise. * tests/preadv-pwritev.c (main): Likewise. * tests/preadv2-pwritev2.c (dumpio): Likewise. * tests/process_vm_readv_writev.c (print_iov): Likewise. * tests/pwritev.c (print_iovec): Likewise. * tests/readv.c (main): Likewise. * tests/seccomp-filter-v.c * tests/semop.c (main): Likewise. * tests/set_mempolicy.c (print_nodes): Likewise. * tests/setgroups.c (main): Likewise. * tests/test_nlattr.h (print_nlattr) Likewise. Co-Authored-by: Eugene Syromyatnikov <evgsyr@gmail.com>
2018-05-29 01:15:19 +00:00
printf("semop(%d, [{%hu, %hd, %s%s%#hx}, ... /* %p */], %u) = %s\n",
bogus_semid, sem_b2->sem_num, sem_b2->sem_op,
sem_b2->sem_flg & SEM_UNDO ? "SEM_UNDO|" : "",
sem_b2->sem_flg & IPC_NOWAIT ? "IPC_NOWAIT|" : "",
(short) (sem_b2->sem_flg & ~(SEM_UNDO | IPC_NOWAIT)),
sem_b2 + 1, 2, sprintrc(rc));
if (semop(id, sem_b, 1))
perror_msg_and_skip("semop, 1");
printf("semop(%d, [{0, 1, SEM_UNDO}], 1) = 0\n", id);
sem_b->sem_op = -1;
if (semop(id, sem_b, 1))
perror_msg_and_skip("semop, -1");
printf("semop(%d, [{0, -1, SEM_UNDO}], 1) = 0\n", id);
rc = semtimedop(bogus_semid, NULL, bogus_nsops, NULL);
printf("semtimedop(%d, NULL, %u, NULL) = %s\n",
bogus_semid, (unsigned) bogus_nsops, sprintrc(rc));
rc = semtimedop(id, sem_b + 1, 1, ts + 1);
printf("semtimedop(%d, %p, 1, %p) = %s\n",
id, sem_b + 1, ts + 1, sprintrc(rc));
ts->tv_sec = 1;
ts->tv_nsec = 123456789;
rc = semtimedop(bogus_semid, sem_b2, 2, ts);
print_array: enhance printing of unfetchable object addresses When umoven_func invocation fails to fetch data, it prints the faulty address. If this happens to a subsequent umoven_func invocation, the printed address may be undistinguishable from a valid data printed by print_func, e.g. when the data is printed in a numeric form like [0x1, 0x2, 0x3, 0xdefaced]. Fix this source of confusion by moving the printing of the faulty address from umoven_func to print_array itself. This change renames umoven_func to tfetch_mem_func and changes its semantics, so that - tfetch_mem_func never prints anything; - tfetch_mem_func returns true if the fetch succeeded, and false otherwise. * defs.h (print_array): Replace umoven_func argument with tfetch_mem_func. * util.c (print_array): Replace umoven_func argument with tfetch_mem_func, document expected tfetch_mem_func return value semantics. When tfetch_mem_func returns false, print either addr or "... /* addr */" depending on the context (inside the array or not). * bpf.c (print_ebpf_prog, print_bpf_prog_info, BEGIN_BPF_CMD_DECODER(BPF_PROG_QUERY)): Replace umoven_or_printaddr argument of print_array with tfetch_mem. * bpf_filter.c (print_bpf_fprog): Likewise. * btrfs.c (btrfs_print_logical_ino_container, btrfs_print_ino_path_container, btrfs_print_qgroup_inherit, btrfs_ioctl): Likewise. * dm.c (dm_decode_dm_target_deps): Likewise. * epoll.c (epoll_wait_common): Likewise. * file_ioctl.c (file_ioctl): Likewise. * ipc_sem.c (tprint_sembuf_array): Likewise. * kexec.c (print_kexec_segments): Likewise. * mem.c (SYS_FUNC(subpage_prot)): Likewise. * net.c (print_getsockopt): Likewise. * netlink.c (decode_nlmsgerr_attr_cookie): Likewise. * netlink_netlink_diag.c (decode_netlink_diag_groups): Likewise. * netlink_packet_diag.c (decode_packet_diag_mclist): Likewise. * netlink_unix_diag.c (decode_unix_diag_inode): Likewise. * nlattr.c (decode_nla_meminfo): Likewise. * numa.c (print_nodemask, SYS_FUNC(move_pages), * perf_ioctl.c (perf_ioctl_query_bpf): Likewise. * poll.c (decode_poll_entering): Likewise. * printsiginfo.c (print_siginfo_array): Likewise. * rtnl_tc.c (decode_tca_stab_data): Likewise. * sock.c (decode_ifconf): Likewise. * uid.c (print_groups): Likewise. * io.c (SYS_FUNC(io_submit), SYS_FUNC(io_getevents)): Replace umoven_or_printaddr argument of print_array with tfetch_mem. (tprint_iov_upto): Replace umoven_or_printaddr_ignore_syserror with tfetch_mem_ignore_syserror. * v4l2.c (print_v4l2_format_fmt): Replace umoven_or_printaddr argument of print_array with tfetch_mem. (print_v4l2_ext_controls): Replace umoven_or_printaddr_ignore_syserror with tfetch_mem_ignore_syserror. * mmsghdr.c (fetch_struct_mmsghdr_or_printaddr): Rename to fetch_struct_mmsghdr_for_print, do not print address, return bool. (decode_mmsgvec): Replace fetch_struct_mmsghdr_or_printaddr with fetch_struct_mmsghdr_for_print. * tests/aio.c (main): Update expected output. * tests/bpf.c (print_BPF_PROG_QUERY_attr5): Likewise. * tests/ioctl_perf-success.c (main): Likewise. * tests/ioctl_v4l2.c (main): Update expected output. * tests/kexec_load.c (main): Likewise. * tests/mmsg_name.c (test_mmsg_name): Update expected output. * tests/move_pages.c (print_page_array, print_node_array): Likewise. * tests/poll.c (print_pollfd_array_entering): Likewise. * tests/preadv-pwritev.c (main): Likewise. * tests/preadv2-pwritev2.c (dumpio): Likewise. * tests/process_vm_readv_writev.c (print_iov): Likewise. * tests/pwritev.c (print_iovec): Likewise. * tests/readv.c (main): Likewise. * tests/seccomp-filter-v.c * tests/semop.c (main): Likewise. * tests/set_mempolicy.c (print_nodes): Likewise. * tests/setgroups.c (main): Likewise. * tests/test_nlattr.h (print_nlattr) Likewise. Co-Authored-by: Eugene Syromyatnikov <evgsyr@gmail.com>
2018-05-29 01:15:19 +00:00
printf("semtimedop(%d, [{%hu, %hd, %s%s%#hx}, ... /* %p */], %u"
Print microseconds/nanoseconds as non-negative Negative micro/nanoseconds values are treated as invalid by kernel anyway, and in one case (timespec_valid in include/linux/time.h) it is even checked by conversion to unsigned long. * print_timespec.c (timespec_fmt): Change tv_sec format to %lld and tv_nsec format to %llu. (print_timespec_t): Cast tv_sec to long long and process tv_nsec with zero_extend_signed_to_ull. (sprint_timespec): Likewise. * print_timeval.c (timeval_fmt): Change tv_sec format to %lld and tv_usec format to %llu. (print_timeval_t): Cast tv_sec to long long and process tv_nsec with zero_extend_signed_to_ull. (sprint_timeval, print_timeval32_t, sprint_timeval32): Likewise. * defs.h (TIMESPEC_TEXT_BUFSIZE): Update. * tests/adjtimex.c (main): Change tv_sec printing format to %lld, cast it to long long; change tv_usec printing format to %llu, process it with zero_extend_signed_to_ull. * tests/clock_nanosleep.c (main): Change tv_sec printing format to %lld, cast it to long long; change tv_nsec printing format to %llu, process it with zero_extend_signed_to_ull. * tests/clock_xettime.c (main): Likewise. * tests/futex.c (main): Likewise. * tests/futimesat.c (print_tv): Likewise. * tests/getrusage.c (invoke_print): Likewise. * tests/mq_sendrecv.c (do_send, do_recv, main): Likewise. * tests/nanosleep.c (main): Likewise. * tests/pselect6.c (main): Likewise. * tests/restart_syscall.c (main): Likewise. * tests/rt_sigtimedwait.c (iterate, main): Likewise. * tests/sched_rr_get_interval.c (main): Likewise. * tests/semop.c (main): Likewise. * tests/timer_xettime.c (main): Likewise. * tests/timerfd_xettime.c (main): Likewise. * tests/waitid.c (main): Likewise. * tests/xetitimer.c (main): Likewise. * tests/xettimeofday.c (main): Likewise. * tests/xselect.c (main): Likewise. * tests/xutimes.c (print_tv): Likewise. * tests/wait4.c (sprint_rusage): Likewise. * tests/waitid.c (sprint_rusage): Likewise. * tests/utimensat.c (print_ts): Likewise. (main): Add check for higher bits of tv_sec/tv_nsec. Co-authored-by: Dmitry V. Levin <ldv@altlinux.org>
2017-04-23 05:57:03 +02:00
", {tv_sec=%lld, tv_nsec=%llu}) = %s\n",
bogus_semid, sem_b2->sem_num, sem_b2->sem_op,
sem_b2->sem_flg & SEM_UNDO ? "SEM_UNDO|" : "",
sem_b2->sem_flg & IPC_NOWAIT ? "IPC_NOWAIT|" : "",
(short) (sem_b2->sem_flg & ~(SEM_UNDO | IPC_NOWAIT)),
sem_b2 + 1, 2,
Print microseconds/nanoseconds as non-negative Negative micro/nanoseconds values are treated as invalid by kernel anyway, and in one case (timespec_valid in include/linux/time.h) it is even checked by conversion to unsigned long. * print_timespec.c (timespec_fmt): Change tv_sec format to %lld and tv_nsec format to %llu. (print_timespec_t): Cast tv_sec to long long and process tv_nsec with zero_extend_signed_to_ull. (sprint_timespec): Likewise. * print_timeval.c (timeval_fmt): Change tv_sec format to %lld and tv_usec format to %llu. (print_timeval_t): Cast tv_sec to long long and process tv_nsec with zero_extend_signed_to_ull. (sprint_timeval, print_timeval32_t, sprint_timeval32): Likewise. * defs.h (TIMESPEC_TEXT_BUFSIZE): Update. * tests/adjtimex.c (main): Change tv_sec printing format to %lld, cast it to long long; change tv_usec printing format to %llu, process it with zero_extend_signed_to_ull. * tests/clock_nanosleep.c (main): Change tv_sec printing format to %lld, cast it to long long; change tv_nsec printing format to %llu, process it with zero_extend_signed_to_ull. * tests/clock_xettime.c (main): Likewise. * tests/futex.c (main): Likewise. * tests/futimesat.c (print_tv): Likewise. * tests/getrusage.c (invoke_print): Likewise. * tests/mq_sendrecv.c (do_send, do_recv, main): Likewise. * tests/nanosleep.c (main): Likewise. * tests/pselect6.c (main): Likewise. * tests/restart_syscall.c (main): Likewise. * tests/rt_sigtimedwait.c (iterate, main): Likewise. * tests/sched_rr_get_interval.c (main): Likewise. * tests/semop.c (main): Likewise. * tests/timer_xettime.c (main): Likewise. * tests/timerfd_xettime.c (main): Likewise. * tests/waitid.c (main): Likewise. * tests/xetitimer.c (main): Likewise. * tests/xettimeofday.c (main): Likewise. * tests/xselect.c (main): Likewise. * tests/xutimes.c (print_tv): Likewise. * tests/wait4.c (sprint_rusage): Likewise. * tests/waitid.c (sprint_rusage): Likewise. * tests/utimensat.c (print_ts): Likewise. (main): Add check for higher bits of tv_sec/tv_nsec. Co-authored-by: Dmitry V. Levin <ldv@altlinux.org>
2017-04-23 05:57:03 +02:00
(long long) ts->tv_sec, zero_extend_signed_to_ull(ts->tv_nsec),
sprintrc(rc));
sem_b->sem_op = 1;
if (semtimedop(id, sem_b, 1, NULL))
perror_msg_and_skip("semtimedop, 1");
printf("semtimedop(%d, [{0, 1, SEM_UNDO}], 1, NULL) = 0\n", id);
sem_b->sem_op = -1;
if (semtimedop(id, sem_b, 1, ts))
perror_msg_and_skip("semtimedop, -1");
Print microseconds/nanoseconds as non-negative Negative micro/nanoseconds values are treated as invalid by kernel anyway, and in one case (timespec_valid in include/linux/time.h) it is even checked by conversion to unsigned long. * print_timespec.c (timespec_fmt): Change tv_sec format to %lld and tv_nsec format to %llu. (print_timespec_t): Cast tv_sec to long long and process tv_nsec with zero_extend_signed_to_ull. (sprint_timespec): Likewise. * print_timeval.c (timeval_fmt): Change tv_sec format to %lld and tv_usec format to %llu. (print_timeval_t): Cast tv_sec to long long and process tv_nsec with zero_extend_signed_to_ull. (sprint_timeval, print_timeval32_t, sprint_timeval32): Likewise. * defs.h (TIMESPEC_TEXT_BUFSIZE): Update. * tests/adjtimex.c (main): Change tv_sec printing format to %lld, cast it to long long; change tv_usec printing format to %llu, process it with zero_extend_signed_to_ull. * tests/clock_nanosleep.c (main): Change tv_sec printing format to %lld, cast it to long long; change tv_nsec printing format to %llu, process it with zero_extend_signed_to_ull. * tests/clock_xettime.c (main): Likewise. * tests/futex.c (main): Likewise. * tests/futimesat.c (print_tv): Likewise. * tests/getrusage.c (invoke_print): Likewise. * tests/mq_sendrecv.c (do_send, do_recv, main): Likewise. * tests/nanosleep.c (main): Likewise. * tests/pselect6.c (main): Likewise. * tests/restart_syscall.c (main): Likewise. * tests/rt_sigtimedwait.c (iterate, main): Likewise. * tests/sched_rr_get_interval.c (main): Likewise. * tests/semop.c (main): Likewise. * tests/timer_xettime.c (main): Likewise. * tests/timerfd_xettime.c (main): Likewise. * tests/waitid.c (main): Likewise. * tests/xetitimer.c (main): Likewise. * tests/xettimeofday.c (main): Likewise. * tests/xselect.c (main): Likewise. * tests/xutimes.c (print_tv): Likewise. * tests/wait4.c (sprint_rusage): Likewise. * tests/waitid.c (sprint_rusage): Likewise. * tests/utimensat.c (print_ts): Likewise. (main): Add check for higher bits of tv_sec/tv_nsec. Co-authored-by: Dmitry V. Levin <ldv@altlinux.org>
2017-04-23 05:57:03 +02:00
printf("semtimedop(%d, [{0, -1, SEM_UNDO}], 1"
", {tv_sec=%lld, tv_nsec=%llu}) = 0\n", id,
(long long) ts->tv_sec, zero_extend_signed_to_ull(ts->tv_nsec));
sem_b->sem_op = 1;
ts->tv_sec = 0xdeadbeefU;
ts->tv_nsec = 0xfacefeedU;
rc = semtimedop(id, sem_b, 1, ts);
printf("semtimedop(%d, [{0, 1, SEM_UNDO}], 1"
", {tv_sec=%lld, tv_nsec=%llu}) = %s\n",
id, (long long) ts->tv_sec,
zero_extend_signed_to_ull(ts->tv_nsec), sprintrc(rc));
sem_b->sem_op = -1;
ts->tv_sec = (time_t) 0xcafef00ddeadbeefLL;
ts->tv_nsec = (long) 0xbadc0dedfacefeedLL;
rc = semtimedop(id, sem_b, 1, ts);
printf("semtimedop(%d, [{0, -1, SEM_UNDO}], 1"
", {tv_sec=%lld, tv_nsec=%llu}) = %s\n",
id, (long long) ts->tv_sec,
zero_extend_signed_to_ull(ts->tv_nsec), sprintrc(rc));
puts("+++ exited with 0 +++");
return 0;
}