14Srgrimes/* $NetBSD: t_msgsnd.c,v 1.3 2017/01/13 20:44:45 christos Exp $ */ 2122295Speter 3549Srgrimes/*- 44Srgrimes * Copyright (c) 2011 The NetBSD Foundation, Inc. 54Srgrimes * All rights reserved. 64Srgrimes * 74Srgrimes * This code is derived from software contributed to The NetBSD Foundation 84Srgrimes * by Jukka Ruohonen. 94Srgrimes * 104Srgrimes * Redistribution and use in source and binary forms, with or without 114Srgrimes * modification, are permitted provided that the following conditions 124Srgrimes * are met: 134Srgrimes * 1. Redistributions of source code must retain the above copyright 144Srgrimes * notice, this list of conditions and the following disclaimer. 154Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 164Srgrimes * notice, this list of conditions and the following disclaimer in the 174Srgrimes * documentation and/or other materials provided with the distribution. 184Srgrimes * 194Srgrimes * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 204Srgrimes * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 214Srgrimes * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 224Srgrimes * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 234Srgrimes * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 244Srgrimes * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 254Srgrimes * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 264Srgrimes * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 274Srgrimes * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 284Srgrimes * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 294Srgrimes * POSSIBILITY OF SUCH DAMAGE. 304Srgrimes */ 314Srgrimes#include <sys/cdefs.h> 324Srgrimes__RCSID("$NetBSD: t_msgsnd.c,v 1.3 2017/01/13 20:44:45 christos Exp $"); 334Srgrimes 344Srgrimes#include <sys/msg.h> 354Srgrimes#include <sys/stat.h> 364Srgrimes#include <sys/sysctl.h> 374Srgrimes#include <sys/wait.h> 38123180Speter 394Srgrimes#include <atf-c.h> 4071261Speter#include <errno.h> 41118031Sobrien#include <limits.h> 42118031Sobrien#include <pwd.h> 43118031Sobrien#include <signal.h> 4436605Sbde#include <stdio.h> 45122849Speter#include <stdlib.h> 4652150Smarcel#include <string.h> 4731544Sjmg#include <sysexits.h> 4813228Swollman#include <time.h> 4936605Sbde#include <unistd.h> 5036605Sbde 5171785Speter#define MSG_KEY 1234 52118235Speter#define MSG_MTYPE_1 0x41 5328976Sbde#define MSG_MTYPE_2 0x42 54222853Savg#define MSG_MTYPE_3 0x43 5514825Swollman 56250840Smarcelstruct msg { 57178471Sjeff long mtype; 58211924Srpaulo char buf[3]; 594Srgrimes}; 601549Srgrimes 61141378Snjlstatic void clean(void); 621549Srgrimes 63141237Snjlstatic void 64141237Snjlclean(void) 65141237Snjl{ 66141237Snjl int id; 67141378Snjl 68141237Snjl if ((id = msgget(MSG_KEY, 0)) != -1) 69270344Semaste (void)msgctl(id, IPC_RMID, 0); 70141237Snjl} 71141378Snjl 72102561SjakeATF_TC_WITH_CLEANUP(msgsnd_block); 73131941SmarcelATF_TC_HEAD(msgsnd_block, tc) 741549Srgrimes{ 7565557Sjasone atf_tc_set_md_var(tc, "descr", "Test that msgsnd(2) blocks"); 7640089Smsmith atf_tc_set_md_var(tc, "timeout", "10"); 7774912Sjhb} 7854188Sluoqi 79238310SjhbATF_TC_BODY(msgsnd_block, tc) 80141378Snjl{ 8167357Sjhb struct msg msg = { MSG_MTYPE_1, { 'a', 'b', 'c' } }; 8276440Sjhb int id, sta; 83141378Snjl pid_t pid; 841549Srgrimes 85248084Sattilio id = msgget(MSG_KEY, IPC_CREAT | 0600); 86104964Sjeff ATF_REQUIRE(id != -1); 87141237Snjl 88219473Sjkim pid = fork(); 89219473Sjkim ATF_REQUIRE(pid >= 0); 90219473Sjkim 91209613Sjhb if (pid == 0) { 92141378Snjl 932254Ssos /* 94141237Snjl * Enqueue messages until some limit (e.g. the maximum 9590776Sdeischen * number of messages in the queue or the maximum number 9612662Sdg * of bytes in the queue) is reached. After this the call 974Srgrimes * should block when the IPC_NOWAIT is not set. 982056Swollman */ 99141378Snjl for (;;) { 1002056Swollman 1012056Swollman#ifdef __FreeBSD__ 10212662Sdg if (msgsnd(id, &msg, sizeof(msg.buf), 0) < 0) 103141378Snjl#else 1049507Sdg if (msgsnd(id, &msg, sizeof(struct msg), 0) < 0) 105141378Snjl#endif 1064Srgrimes _exit(EXIT_FAILURE); 107133903Speter } 108133903Speter } 109133903Speter 110133903Speter (void)sleep(2); 111195410Sjhb (void)kill(pid, SIGKILL); 112195410Sjhb (void)wait(&sta); 113133903Speter 1147090Sbde if (WIFEXITED(sta) != 0 || WIFSIGNALED(sta) == 0) 1152772Swollman atf_tc_fail("msgsnd(2) did not block"); 1162772Swollman 117141378Snjl ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0); 1182056Swollman} 11964592Sjhb 120122849SpeterATF_TC_CLEANUP(msgsnd_block, tc) 121214630Sjhb{ 1227090Sbde clean(); 123141378Snjl} 124222853Savg 125135691SpeterATF_TC_WITH_CLEANUP(msgsnd_count); 126141378SnjlATF_TC_HEAD(msgsnd_count, tc) 12785449Sjhb{ 128141378Snjl atf_tc_set_md_var(tc, "descr", 129141378Snjl "Test that msgsnd(2) increments the amount of " 130141378Snjl "message in the queue, as given by msgctl(2)"); 13114825Swollman atf_tc_set_md_var(tc, "timeout", "10"); 13214825Swollman} 13314825Swollman 134114349SpeterATF_TC_BODY(msgsnd_count, tc) 135122849Speter{ 136122849Speter struct msg msg = { MSG_MTYPE_1, { 'a', 'b', 'c' } }; 137122849Speter struct msqid_ds ds; 138250840Smarcel size_t i = 0; 139250840Smarcel int id, rv; 140250840Smarcel 141556Srgrimes id = msgget(MSG_KEY, IPC_CREAT | 0600); 142163267Sjhb ATF_REQUIRE(id != -1); 143204309Sattilio 144163267Sjhb for (;;) { 145152651Sjhb 146163267Sjhb errno = 0; 147122849Speter#ifdef __FreeBSD__ 148122849Speter rv = msgsnd(id, &msg, sizeof(msg.buf), IPC_NOWAIT); 14947642Sdfr#else 1504Srgrimes rv = msgsnd(id, &msg, sizeof(struct msg), IPC_NOWAIT); 151122930Speter#endif 152122930Speter 153122930Speter if (rv == 0) { 154115431Speter i++; 15510358Sjulian continue; 15624112Skato } 157114349Speter 15824112Skato if (rv == -1 && errno == EAGAIN) 15913085Sdg break; 16061220Sbde 16161220Sbde atf_tc_fail("failed to enqueue a message"); 16261220Sbde } 16392770Salfred 164230426Skib (void)memset(&ds, 0, sizeof(struct msqid_ds)); 165230426Skib (void)msgctl(id, IPC_STAT, &ds); 166230426Skib 167230426Skib if (ds.msg_qnum != i) 168177253Srwatson atf_tc_fail("incorrect message count"); 16910358Sjulian 170220090Salc ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0); 171220090Salc} 172220090Salc 173220090SalcATF_TC_CLEANUP(msgsnd_count, tc) 174220090Salc{ 175131941Smarcel clean(); 176131941Smarcel} 177131941Smarcel 178131941SmarcelATF_TC_WITH_CLEANUP(msgsnd_err); 179202897SalcATF_TC_HEAD(msgsnd_err, tc) 180202897Salc{ 181174557Srpaulo atf_tc_set_md_var(tc, "descr", "Test errors from msgsnd(2)"); 182174557Srpaulo} 183174557Srpaulo 184174557SrpauloATF_TC_BODY(msgsnd_err, tc) 185190620Skib{ 186556Srgrimes struct msg msg = { MSG_MTYPE_1, { 'a', 'b', 'c' } }; 18715392Sphk int id; 18812623Sphk 189102600Speter id = msgget(MSG_KEY, IPC_CREAT | 0600); 190142866Sobrien ATF_REQUIRE(id != -1); 1914Srgrimes 192170253Salc errno = 0; 193170253Salc 194170253Salc ATF_REQUIRE_ERRNO(EFAULT, msgsnd(id, (void *)-1, 195170253Salc#ifdef __FreeBSD__ 196170253Salc sizeof(msg.buf), IPC_NOWAIT) == -1); 197170253Salc#else 198170253Salc sizeof(struct msg), IPC_NOWAIT) == -1); 199974Sdg#endif 200162112Sjhb 201162112Sjhb errno = 0; 202162112Sjhb 2039578Sdg ATF_REQUIRE_ERRNO(EINVAL, msgsnd(-1, &msg, 204147671Speter#ifdef __FreeBSD__ 205147671Speter sizeof(msg.buf), IPC_NOWAIT) == -1); 2069578Sdg#else 20782127Sdillon sizeof(struct msg), IPC_NOWAIT) == -1); 20882127Sdillon#endif 20964529Speter 210122849Speter errno = 0; 211556Srgrimes 212122849Speter ATF_REQUIRE_ERRNO(EINVAL, msgsnd(-1, &msg, 213122849Speter SSIZE_MAX, IPC_NOWAIT) == -1); 21488322Sjhb 21565557Sjasone errno = 0; 216238310Sjhb msg.mtype = 0; 217238310Sjhb 218190620Skib ATF_REQUIRE_ERRNO(EINVAL, msgsnd(id, &msg, 219190620Skib#ifdef __FreeBSD__ 220261275Sjhb sizeof(msg.buf), IPC_NOWAIT) == -1); 221261275Sjhb#else 22210358Sjulian sizeof(struct msg), IPC_NOWAIT) == -1); 22311390Sbde#endif 22411390Sbde 2254Srgrimes ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0); 226190599Sjkim} 227174557Srpaulo 228174557SrpauloATF_TC_CLEANUP(msgsnd_err, tc) 2294Srgrimes{ 230174557Srpaulo clean(); 231174557Srpaulo} 232174557Srpaulo 233174557SrpauloATF_TC_WITH_CLEANUP(msgsnd_nonblock); 234174557SrpauloATF_TC_HEAD(msgsnd_nonblock, tc) 235174557Srpaulo{ 236174557Srpaulo atf_tc_set_md_var(tc, "descr", "Test msgsnd(2) with IPC_NOWAIT"); 237174557Srpaulo atf_tc_set_md_var(tc, "timeout", "10"); 238174557Srpaulo} 239195907Srpaulo 240196033SedATF_TC_BODY(msgsnd_nonblock, tc) 241271541Spfg{ 242195907Srpaulo struct msg msg = { MSG_MTYPE_1, { 'a', 'b', 'c' } }; 243195907Srpaulo int id, rv, sta; 244196390Sed pid_t pid; 245271541Spfg 246195907Srpaulo id = msgget(MSG_KEY, IPC_CREAT | 0600); 247174557Srpaulo ATF_REQUIRE(id != -1); 248174557Srpaulo 249174557Srpaulo pid = fork(); 250174557Srpaulo ATF_REQUIRE(pid >= 0); 251174557Srpaulo 252174557Srpaulo if (pid == 0) { 253174557Srpaulo 254174557Srpaulo for (;;) { 255174557Srpaulo 2564Srgrimes errno = 0; 2574Srgrimes#ifdef __FreeBSD__ 2582014Swollman rv = msgsnd(id, &msg, sizeof(msg.buf), IPC_NOWAIT); 25924112Skato#else 26024112Skato rv = msgsnd(id, &msg, sizeof(struct msg), IPC_NOWAIT); 26117014Swollman#endif 26217014Swollman 26317014Swollman if (rv == -1 && errno == EAGAIN) 264196412Sjkim _exit(EXIT_SUCCESS); 265196412Sjkim } 266196412Sjkim } 267196412Sjkim 268196412Sjkim (void)wait(&sta); 269190599Sjkim 270190599Sjkim if (WIFEXITED(sta) == 0 || WIFSIGNALED(sta) != 0) 271196412Sjkim atf_tc_fail("msgsnd(2) blocked with IPC_NOWAIT"); 272190599Sjkim 273196412Sjkim ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0); 274196412Sjkim} 275196412Sjkim 276196412SjkimATF_TC_CLEANUP(msgsnd_nonblock, tc) 277258996Sroyger{ 278196412Sjkim clean(); 2799578Sdg} 2809578Sdg 2819578SdgATF_TC_WITH_CLEANUP(msgsnd_perm); 28229109SdgATF_TC_HEAD(msgsnd_perm, tc) 28329109Sdg{ 2844Srgrimes atf_tc_set_md_var(tc, "descr", "Test permissions with msgsnd(2)"); 28529109Sdg atf_tc_set_md_var(tc, "require.user", "root"); 28629109Sdg} 287112569Sjake 2889578SdgATF_TC_BODY(msgsnd_perm, tc) 289112569Sjake{ 290112569Sjake struct msg msg = { MSG_MTYPE_1, { 'a', 'b', 'c' } }; 291112569Sjake struct passwd *pw; 292112569Sjake int id, sta; 293112569Sjake pid_t pid; 294112569Sjake uid_t uid; 2959578Sdg 2969578Sdg pw = getpwnam("nobody"); 2979578Sdg id = msgget(MSG_KEY, IPC_CREAT | 0600); 29882127Sdillon 29982127Sdillon ATF_REQUIRE(id != -1); 300190599Sjkim ATF_REQUIRE(pw != NULL); 301170170Sattilio 302170170Sattilio uid = pw->pw_uid; 3031298Sdg ATF_REQUIRE(uid != 0); 30428808Speter 30528808Speter pid = fork(); 30628808Speter ATF_REQUIRE(pid >= 0); 30728808Speter 30828808Speter if (pid == 0) { 30928808Speter 31064529Speter /* 3114Srgrimes * Try to enqueue a message to the queue 3124Srgrimes * created by root as RW for owner only. 3134Srgrimes */ 3144Srgrimes if (setuid(uid) != 0) 3154Srgrimes _exit(EX_OSERR); 3164Srgrimes 317190620Skib id = msgget(MSG_KEY, 0); 3184Srgrimes 3194Srgrimes if (id == -1) 3204Srgrimes _exit(EX_OSERR); 3214Srgrimes 3224Srgrimes errno = 0; 32351792Smarcel 324151316Sdavidxu#ifdef __FreeBSD__ 32551792Smarcel if (msgsnd(id, &msg, sizeof(msg.buf), IPC_NOWAIT) == 0) 326105950Speter#else 327216634Sjkim if (msgsnd(id, &msg, sizeof(struct msg), IPC_NOWAIT) == 0) 32861220Sbde#endif 32983366Sjulian _exit(EXIT_FAILURE); 33061220Sbde 331107521Sdeischen if (errno != EACCES) 33251792Smarcel _exit(EXIT_FAILURE); 333230426Skib 334230426Skib _exit(EXIT_SUCCESS); 335156694Speter } 33652140Sluoqi 33751792Smarcel (void)wait(&sta); 33883366Sjulian 339216634Sjkim if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS) { 34083366Sjulian 34183163Sjhb if (errno == EX_OSERR) 342151316Sdavidxu atf_tc_fail("system call failed"); 34361220Sbde 344114983Sjhb atf_tc_fail("UID %u enqueued message to root's queue", uid); 34583366Sjulian } 346114349Speter 34751792Smarcel ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0); 348230426Skib} 349230426Skib 350230426SkibATF_TC_CLEANUP(msgsnd_perm, tc) 351230426Skib{ 352230426Skib clean(); 353230426Skib} 354230426Skib 355230426SkibATF_TP_ADD_TCS(tp) 35661220Sbde{ 35761220Sbde 35851792Smarcel ATF_TP_ADD_TC(tp, msgsnd_block); 359124092Sdavidxu ATF_TP_ADD_TC(tp, msgsnd_count); 360124092Sdavidxu ATF_TP_ADD_TC(tp, msgsnd_err); 36169379Smarcel ATF_TP_ADD_TC(tp, msgsnd_nonblock); 36269379Smarcel ATF_TP_ADD_TC(tp, msgsnd_perm); 363114951Speter 364103407Smini return atf_no_error(); 365230426Skib} 366103407Smini