1 /* $NetBSD: t_msgctl.c,v 1.3 2011/11/11 05:06:01 jruoho Exp $ */
4 * Copyright (c) 2011 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
31 #include <sys/cdefs.h>
32 __RCSID("$NetBSD: t_msgctl.c,v 1.3 2011/11/11 05:06:01 jruoho Exp $");
36 #include <sys/sysctl.h>
49 #define MSG_KEY 12345689
50 #define MSG_MTYPE_1 0x41
57 static void clean(void);
64 if ((id
= msgget(MSG_KEY
, 0)) != -1)
65 (void)msgctl(id
, IPC_RMID
, 0);
68 ATF_TC_WITH_CLEANUP(msgctl_err
);
69 ATF_TC_HEAD(msgctl_err
, tc
)
71 atf_tc_set_md_var(tc
, "descr", "Test errors from msgctl(2)");
74 ATF_TC_BODY(msgctl_err
, tc
)
76 const int cmd
[] = { IPC_STAT
, IPC_SET
, IPC_RMID
};
77 struct msqid_ds msgds
;
81 (void)memset(&msgds
, 0, sizeof(struct msqid_ds
));
83 id
= msgget(MSG_KEY
, IPC_CREAT
| 0600);
84 ATF_REQUIRE(id
!= -1);
87 ATF_REQUIRE_ERRNO(EINVAL
, msgctl(id
, INT_MAX
, &msgds
) == -1);
90 ATF_REQUIRE_ERRNO(EFAULT
, msgctl(id
, IPC_STAT
, (void *)-1) == -1);
92 for (i
= 0; i
< __arraycount(cmd
); i
++) {
94 ATF_REQUIRE_ERRNO(EINVAL
, msgctl(-1, cmd
[i
], &msgds
) == -1);
97 ATF_REQUIRE(msgctl(id
, IPC_RMID
, 0) == 0);
100 ATF_TC_CLEANUP(msgctl_err
, tc
)
105 ATF_TC_WITH_CLEANUP(msgctl_perm
);
106 ATF_TC_HEAD(msgctl_perm
, tc
)
108 atf_tc_set_md_var(tc
, "descr", "Test permissions with msgctl(2)");
109 atf_tc_set_md_var(tc
, "require.user", "root");
112 ATF_TC_BODY(msgctl_perm
, tc
)
114 struct msqid_ds msgds
;
120 (void)memset(&msgds
, 0, sizeof(struct msqid_ds
));
122 pw
= getpwnam("nobody");
123 id
= msgget(MSG_KEY
, IPC_CREAT
| 0600);
125 ATF_REQUIRE(id
!= -1);
126 ATF_REQUIRE(pw
!= NULL
);
127 ATF_REQUIRE(msgctl(id
, IPC_STAT
, &msgds
) == 0);
130 ATF_REQUIRE(pid
>= 0);
134 if (setuid(pw
->pw_uid
) != 0)
137 msgds
.msg_perm
.uid
= getuid();
138 msgds
.msg_perm
.gid
= getgid();
142 if (msgctl(id
, IPC_SET
, &msgds
) == 0)
148 (void)memset(&msgds
, 0, sizeof(struct msqid_ds
));
150 if (msgctl(id
, IPC_STAT
, &msgds
) != 0)
153 msgds
.msg_qbytes
= 1;
155 if (msgctl(id
, IPC_SET
, &msgds
) == 0)
166 if (WIFEXITED(sta
) == 0) {
168 if (WEXITSTATUS(sta
) == EX_OSERR
)
169 atf_tc_fail("system call failed");
171 if (WEXITSTATUS(sta
) == EXIT_FAILURE
)
172 atf_tc_fail("UID %u manipulated root's "
173 "message queue", pw
->pw_uid
);
176 ATF_REQUIRE(msgctl(id
, IPC_RMID
, 0) == 0);
179 ATF_TC_CLEANUP(msgctl_perm
, tc
)
184 ATF_TC_WITH_CLEANUP(msgctl_pid
);
185 ATF_TC_HEAD(msgctl_pid
, tc
)
187 atf_tc_set_md_var(tc
, "descr", "Test that PIDs are updated");
190 ATF_TC_BODY(msgctl_pid
, tc
)
192 struct msg msg
= { MSG_MTYPE_1
, { 'a', 'b', 'c' } };
193 struct msqid_ds msgds
;
197 id
= msgget(MSG_KEY
, IPC_CREAT
| 0600);
198 ATF_REQUIRE(id
!= -1);
201 ATF_REQUIRE(pid
>= 0);
205 (void)msgsnd(id
, &msg
, sizeof(struct msg
), IPC_NOWAIT
);
212 (void)memset(&msgds
, 0, sizeof(struct msqid_ds
));
214 ATF_REQUIRE(msgctl(id
, IPC_STAT
, &msgds
) == 0);
216 if (pid
!= msgds
.msg_lspid
)
217 atf_tc_fail("the PID of last msgsnd(2) was not updated");
220 ATF_REQUIRE(pid
>= 0);
224 (void)msgrcv(id
, &msg
,
225 sizeof(struct msg
), MSG_MTYPE_1
, IPC_NOWAIT
);
232 (void)memset(&msgds
, 0, sizeof(struct msqid_ds
));
234 ATF_REQUIRE(msgctl(id
, IPC_STAT
, &msgds
) == 0);
236 if (pid
!= msgds
.msg_lrpid
)
237 atf_tc_fail("the PID of last msgrcv(2) was not updated");
239 ATF_REQUIRE(msgctl(id
, IPC_RMID
, 0) == 0);
242 ATF_TC_CLEANUP(msgctl_pid
, tc
)
247 ATF_TC_WITH_CLEANUP(msgctl_set
);
248 ATF_TC_HEAD(msgctl_set
, tc
)
250 atf_tc_set_md_var(tc
, "descr", "Test msgctl(2) with IPC_SET");
251 atf_tc_set_md_var(tc
, "require.user", "root");
254 ATF_TC_BODY(msgctl_set
, tc
)
256 struct msqid_ds msgds
;
260 (void)memset(&msgds
, 0, sizeof(struct msqid_ds
));
262 pw
= getpwnam("nobody");
263 id
= msgget(MSG_KEY
, IPC_CREAT
| 0600);
265 ATF_REQUIRE(id
!= -1);
266 ATF_REQUIRE(pw
!= NULL
);
267 ATF_REQUIRE(msgctl(id
, IPC_STAT
, &msgds
) == 0);
269 msgds
.msg_perm
.uid
= pw
->pw_uid
;
271 if (msgctl(id
, IPC_SET
, &msgds
) != 0)
272 atf_tc_fail("root failed to change the UID of message queue");
274 msgds
.msg_perm
.uid
= getuid();
275 msgds
.msg_perm
.gid
= pw
->pw_gid
;
277 if (msgctl(id
, IPC_SET
, &msgds
) != 0)
278 atf_tc_fail("root failed to change the GID of message queue");
281 * Note: setting the qbytes to zero fails even as root.
283 msgds
.msg_qbytes
= 1;
284 msgds
.msg_perm
.gid
= getgid();
286 if (msgctl(id
, IPC_SET
, &msgds
) != 0)
287 atf_tc_fail("root failed to change qbytes of message queue");
289 ATF_REQUIRE(msgctl(id
, IPC_RMID
, 0) == 0);
292 ATF_TC_CLEANUP(msgctl_set
, tc
)
297 ATF_TC_WITH_CLEANUP(msgctl_time
);
298 ATF_TC_HEAD(msgctl_time
, tc
)
300 atf_tc_set_md_var(tc
, "descr", "Test that access times are updated");
303 ATF_TC_BODY(msgctl_time
, tc
)
305 struct msg msg
= { MSG_MTYPE_1
, { 'a', 'b', 'c' } };
306 struct msqid_ds msgds
;
310 id
= msgget(MSG_KEY
, IPC_CREAT
| 0600);
311 ATF_REQUIRE(id
!= -1);
315 (void)memset(&msgds
, 0, sizeof(struct msqid_ds
));
316 (void)msgsnd(id
, &msg
, sizeof(struct msg
), IPC_NOWAIT
);
317 (void)msgctl(id
, IPC_STAT
, &msgds
);
319 if (abs(t
- msgds
.msg_stime
) > 1)
320 atf_tc_fail("time of last msgsnd(2) was not updated");
322 if (msgds
.msg_rtime
!= 0)
323 atf_tc_fail("time of last msgrcv(2) was updated incorrectly");
327 (void)memset(&msgds
, 0, sizeof(struct msqid_ds
));
328 (void)msgrcv(id
, &msg
, sizeof(struct msg
), MSG_MTYPE_1
, IPC_NOWAIT
);
329 (void)msgctl(id
, IPC_STAT
, &msgds
);
331 if (abs(t
- msgds
.msg_rtime
) > 1)
332 atf_tc_fail("time of last msgrcv(2) was not updated");
335 * Note: this is non-zero even after the memset(3).
337 if (msgds
.msg_stime
== 0)
338 atf_tc_fail("time of last msgsnd(2) was updated incorrectly");
340 ATF_REQUIRE(msgctl(id
, IPC_RMID
, 0) == 0);
343 ATF_TC_CLEANUP(msgctl_time
, tc
)
351 ATF_TP_ADD_TC(tp
, msgctl_err
);
352 ATF_TP_ADD_TC(tp
, msgctl_perm
);
353 ATF_TP_ADD_TC(tp
, msgctl_pid
);
354 ATF_TP_ADD_TC(tp
, msgctl_set
);
355 ATF_TP_ADD_TC(tp
, msgctl_time
);
357 return atf_no_error();