1 /*
2 * This file is part of semtimedop* strace tests.
3 *
4 * Copyright (c) 2016-2021 The strace developers.
5 * All rights reserved.
6 *
7 * SPDX-License-Identifier: GPL-2.0-or-later
8 */
9
10 #include <sys/ipc.h>
11 #include <sys/sem.h>
12 #include <stdint.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <unistd.h>
16 #include "kernel_timespec.h"
17
18 #define XLAT_MACROS_ONLY
19 # include "xlat/semop_flags.h"
20 #undef XLAT_MACROS_ONLY
21
22 static long
23 k_semtimedop_imp(const kernel_ulong_t semid,
24 const kernel_ulong_t sops,
25 const kernel_ulong_t nsops,
26 const kernel_ulong_t timeout);
27
28 static const char *errstr;
29
30 static long
31 k_semtimedop(const unsigned int semid,
32 void *const sops,
33 const size_t nsops,
34 const void *const timeout)
35 {
36 static const kernel_ulong_t fill = (kernel_ulong_t) 0xdefaced0defacedULL;
37 static const kernel_ulong_t k_1 = (kernel_ulong_t) -1;
38 const kernel_ulong_t k_semid = semid | (fill & (k_1 - -1U));
39 const kernel_ulong_t k_sops = f8ill_ptr_to_kulong(sops);
40 const kernel_ulong_t k_nsops = nsops | (fill & (k_1 - (size_t) -1));
41 const kernel_ulong_t k_timeout = f8ill_ptr_to_kulong(timeout);
42 const long rc = k_semtimedop_imp(k_semid, k_sops, k_nsops, k_timeout);
43 errstr = sprintrc(rc);
44 return rc;
45 }
46
47 static int id = -1;
48
49 static void
50 cleanup(void)
51 {
52 semctl(id, 0, IPC_RMID, 0);
53 id = -1;
54 }
55
56 int
57 main(void)
58 {
59 static const int bogus_semid = 0xfdb97531;
60 static void * const bogus_sops = (void *) -1UL;
61 static const size_t bogus_nsops = (size_t) 0xdefaceddeadbeefULL;
62
63 TAIL_ALLOC_OBJECT_CONST_PTR(semtimedop_timespec_t, ts);
64
65 id = semget(IPC_PRIVATE, 1, 0600);
66 if (id < 0)
67 perror_msg_and_skip("semget");
68 atexit(cleanup);
69
70 union {
71 int val;
72 void *buf;
73 } sem_union = { .val = 0 };
74 if (semctl(id, 0, SETVAL, sem_union) == -1)
75 perror_msg_and_skip("semctl");
76
77 TAIL_ALLOC_OBJECT_CONST_PTR(struct sembuf, sem_b);
78 TAIL_ALLOC_OBJECT_CONST_PTR(struct sembuf, sem_b2);
79
80 k_semtimedop(bogus_semid, NULL, bogus_nsops, NULL);
81 printf("%s(%d, NULL, %u, NULL) = %s\n",
82 SYSCALL_NAME, bogus_semid, (unsigned) bogus_nsops, errstr);
83
84 k_semtimedop(bogus_semid, bogus_sops, 1, NULL);
85 printf("%s(%d, %p, %u, NULL) = %s\n",
86 SYSCALL_NAME, bogus_semid, bogus_sops, 1, errstr);
87
88 sem_b->sem_num = 0;
89 sem_b->sem_op = 1;
90 sem_b->sem_flg = SEM_UNDO;
91
92 sem_b2->sem_num = 0xface;
93 sem_b2->sem_op = 0xf00d;
94 sem_b2->sem_flg = 0xbeef;
95
96 k_semtimedop(bogus_semid, sem_b2, 2, NULL);
97 printf("%s(%d, [{sem_num=%hu, sem_op=%hd, sem_flg=%s%s%#hx}"
98 ", ... /* %p */], %u, NULL) = %s\n",
99 SYSCALL_NAME, bogus_semid, sem_b2->sem_num, sem_b2->sem_op,
100 sem_b2->sem_flg & SEM_UNDO ? "SEM_UNDO|" : "",
101 sem_b2->sem_flg & IPC_NOWAIT ? "IPC_NOWAIT|" : "",
102 (short) (sem_b2->sem_flg & ~(SEM_UNDO | IPC_NOWAIT)),
103 sem_b2 + 1, 2, errstr);
104
105 if (k_semtimedop(id, sem_b, 1, NULL))
106 perror_msg_and_skip(SYSCALL_NAME ", 1");
107 printf("%s(%d, [{sem_num=0, sem_op=1, sem_flg=SEM_UNDO}], 1, NULL) = 0\n", SYSCALL_NAME, id);
108
109 sem_b->sem_op = -1;
110 if (k_semtimedop(id, sem_b, 1, NULL))
111 perror_msg_and_skip(SYSCALL_NAME ", -1");
112 printf("%s(%d, [{sem_num=0, sem_op=-1, sem_flg=SEM_UNDO}], 1, NULL) = 0\n", SYSCALL_NAME, id);
113
114 k_semtimedop(bogus_semid, NULL, bogus_nsops, NULL);
115 printf("%s(%d, NULL, %u, NULL) = %s\n",
116 SYSCALL_NAME, bogus_semid, (unsigned) bogus_nsops, errstr);
117
118 k_semtimedop(id, sem_b + 1, 1, ts + 1);
119 printf("%s(%d, %p, 1, %p) = %s\n",
120 SYSCALL_NAME, id, sem_b + 1, ts + 1, errstr);
121
122 ts->tv_sec = 1;
123 ts->tv_nsec = 123456789;
124 k_semtimedop(bogus_semid, sem_b2, 2, ts);
125 printf("%s(%d, [{sem_num=%hu, sem_op=%hd, sem_flg=%s%s%#hx}"
126 ", ... /* %p */], %u, {tv_sec=%lld, tv_nsec=%llu}) = %s\n",
127 SYSCALL_NAME, bogus_semid, sem_b2->sem_num, sem_b2->sem_op,
128 sem_b2->sem_flg & SEM_UNDO ? "SEM_UNDO|" : "",
129 sem_b2->sem_flg & IPC_NOWAIT ? "IPC_NOWAIT|" : "",
130 (short) (sem_b2->sem_flg & ~(SEM_UNDO | IPC_NOWAIT)),
131 sem_b2 + 1, 2,
132 (long long) ts->tv_sec, zero_extend_signed_to_ull(ts->tv_nsec),
133 errstr);
134
135 sem_b->sem_op = 1;
136 if (k_semtimedop(id, sem_b, 1, NULL))
137 perror_msg_and_skip(SYSCALL_NAME ", 1");
138 printf("%s(%d, [{sem_num=0, sem_op=1, sem_flg=SEM_UNDO}], 1, NULL) = 0\n", SYSCALL_NAME, id);
139
140 sem_b->sem_op = -1;
141 if (k_semtimedop(id, sem_b, 1, ts))
142 perror_msg_and_skip(SYSCALL_NAME ", -1");
143 printf("%s(%d, [{sem_num=0, sem_op=-1, sem_flg=SEM_UNDO}], 1"
144 ", {tv_sec=%lld, tv_nsec=%llu}) = 0\n",
145 SYSCALL_NAME, id,
146 (long long) ts->tv_sec, zero_extend_signed_to_ull(ts->tv_nsec));
147
148 sem_b->sem_op = 1;
149 ts->tv_sec = 0xdeadbeefU;
150 ts->tv_nsec = 0xfacefeedU;
151 k_semtimedop(id, sem_b, 1, ts);
152 printf("%s(%d, [{sem_num=0, sem_op=1, sem_flg=SEM_UNDO}], 1"
153 ", {tv_sec=%lld, tv_nsec=%llu}) = %s\n",
154 SYSCALL_NAME, id, (long long) ts->tv_sec,
155 zero_extend_signed_to_ull(ts->tv_nsec), errstr);
156
157 sem_b->sem_op = -1;
158 ts->tv_sec = (typeof(ts->tv_sec)) 0xcafef00ddeadbeefLL;
159 ts->tv_nsec = (typeof(ts->tv_nsec)) 0xbadc0dedfacefeedLL;
160 k_semtimedop(id, sem_b, 1, ts);
161 printf("%s(%d, [{sem_num=0, sem_op=-1, sem_flg=SEM_UNDO}], 1"
162 ", {tv_sec=%lld, tv_nsec=%llu}) = %s\n",
163 SYSCALL_NAME, id, (long long) ts->tv_sec,
164 zero_extend_signed_to_ull(ts->tv_nsec), errstr);
165
166 puts("+++ exited with 0 +++");
167 return 0;
168 }