3-1.c revision e9410dfd93b8e415ecbe3f7e09a085462b27836e
1/* 2* Copyright (c) 2005, Bull S.A.. All rights reserved. 3* Created by: Sebastien Decugis 4 5* This program is free software; you can redistribute it and/or modify it 6* under the terms of version 2 of the GNU General Public License as 7* published by the Free Software Foundation. 8* 9* This program is distributed in the hope that it would be useful, but 10* WITHOUT ANY WARRANTY; without even the implied warranty of 11* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12* 13* You should have received a copy of the GNU General Public License along 14* with this program; if not, write the Free Software Foundation, Inc., 59 15* Temple Place - Suite 330, Boston MA 02111-1307, USA. 16 17 18* This sample test aims to check the following assertion: 19* 20* sem_unlink will return -1 and set errno to EACCESS if the process has not 21* priviledge to unlink the sem. 22 23* The steps are: 24* -> open a semaphore with 0744 mask 25* -> fork 26* -> change child uid 27* -> child attempts to unlink the semaphore. It should fail. 28* -> join the child 29* -> sem_unlink (should be OK) 30 31* The test fails if the child process is able to unlink the semaphore. 32 33*/ 34 35/* We are testing conformance to IEEE Std 1003.1, 2003 Edition */ 36#define _POSIX_C_SOURCE 200112L 37 38/* Some of the routines are XSI extensions */ 39#define _XOPEN_SOURCE 600 40 41/******************************************************************************/ 42/*************************** standard includes ********************************/ 43/******************************************************************************/ 44#include <pthread.h> 45#include <stdarg.h> 46#include <stdio.h> 47#include <stdlib.h> 48#include <string.h> 49#include <unistd.h> 50 51#include <pwd.h> 52#include <semaphore.h> 53#include <errno.h> 54#include <fcntl.h> 55#include <sys/wait.h> 56 57/******************************************************************************/ 58/*************************** Test framework *******************************/ 59/******************************************************************************/ 60#include "testfrmw.h" 61#include "testfrmw.c" 62/* This header is responsible for defining the following macros: 63 * UNRESOLVED(ret, descr); 64 * where descr is a description of the error and ret is an int 65 * (error code for example) 66 * FAILED(descr); 67 * where descr is a short text saying why the test has failed. 68 * PASSED(); 69 * No parameter. 70 * 71 * Both three macros shall terminate the calling process. 72 * The testcase shall not terminate in any other maneer. 73 * 74 * The other file defines the functions 75 * void output_init() 76 * void output(char * string, ...) 77 * 78 * Those may be used to output information. 79 */ 80 81/******************************************************************************/ 82/**************************** Configuration ***********************************/ 83/******************************************************************************/ 84#ifndef VERBOSE 85#define VERBOSE 1 86#endif 87 88#define SEM_NAME "/sem_unlink_3_1" 89 90/******************************************************************************/ 91/*************************** Test case ***********************************/ 92/******************************************************************************/ 93 94/* Set the euid of this process to a non-root uid */ 95/* (from ../sem_open/3-1.c) */ 96int set_nonroot() 97{ 98 99 struct passwd * pw; 100 setpwent(); 101 /* search for the first user which is non root */ 102 103 while (( pw = getpwent()) != NULL) 104 if (strcmp(pw->pw_name, "root") ) 105 break; 106 107 endpwent(); 108 109 if (pw == NULL) 110 { 111 output("There is no other user than current and root.\n"); 112 return 1; 113 } 114 115 if (seteuid(pw->pw_uid) != 0) 116 { 117 if (errno == EPERM) 118 { 119 output("You don't have permission to change your UID.\n"); 120 return 1; 121 } 122 123 perror("An error occurs when calling seteuid()"); 124 return 1; 125 } 126 127 output("Testing with user '%s' (uid: %d)\n", 128 pw->pw_name, (int) geteuid()); 129 return 0; 130} 131 132 133 134 135/* The main test function. */ 136int main(int argc, char * argv[]) 137{ 138 int ret, status; 139 pid_t ch, ctl; 140 sem_t * sem; 141 142 /* Initialize output */ 143 output_init(); 144 145 /* Create the semaphore */ 146 sem = sem_open(SEM_NAME, O_CREAT | O_EXCL, 0744, 1); 147 148 if ((sem == SEM_FAILED) && (errno == EEXIST) ) 149 { 150 sem_unlink(SEM_NAME); 151 sem = sem_open(SEM_NAME, O_CREAT | O_EXCL, 0744, 1); 152 } 153 154 if (sem == SEM_FAILED) 155 { 156 UNRESOLVED(errno, "Failed to create the semaphore"); 157 } 158 159 /* fork */ 160 ch = fork(); 161 162 if (ch == (pid_t) - 1) 163 { 164 UNRESOLVED(errno, "Failed to fork"); 165 } 166 167 if (ch == (pid_t) 0) /* child */ 168 { 169 /* connect to the semaphore */ 170 sem = sem_open(SEM_NAME, 0); 171 172 if (sem == SEM_FAILED) 173 { 174 output("Failed to connect to the semaphore, error %d: %s\n", errno, strerror(errno) ); 175 exit(1); 176 } 177 178 /* change euid */ 179 ret = set_nonroot(); 180 181 if (ret) 182 { 183 output("Changing euid failed\n"); 184 exit (1); 185 } 186 187 /* try and unlink, it should fail */ 188 ret = sem_unlink(SEM_NAME); 189 190 if (ret == 0) 191 { 192 output("sem_unlink did not fail in child"); 193 exit(2); 194 } 195 196 if (errno != EACCES) 197 { 198 output("sem_unlink failed with unexpected error %d: %s\n", errno, strerror(errno) ); 199 exit(2); 200 } 201 202 /* Ok, child is done. */ 203 exit(0); 204 } 205 206 /* Parent waits for the child to finish */ 207 ctl = waitpid(ch, &status, 0); 208 209 if (ctl != ch) 210 { 211 UNRESOLVED(errno, "Waitpid returned the wrong PID"); 212 } 213 214 if (!WIFEXITED(status) ) 215 { 216 FAILED("Child exited abnormally"); 217 } 218 219 if (WEXITSTATUS(status) == 1) 220 { 221 UNRESOLVED(0, "An error occured in child"); 222 } 223 224 if (WEXITSTATUS(status) == 2) 225 { 226 FAILED("Test failed in child"); 227 } 228 229 if (WEXITSTATUS(status) != 0) 230 { 231 UNRESOLVED(0, "Unexpected return value from child"); 232 } 233 234 /* Unlink */ 235 ret = sem_unlink(SEM_NAME); 236 237 if (ret != 0) 238 { 239 UNRESOLVED(errno, "Failed to unlink the semaphore"); 240 } 241 242 /* Test passed */ 243#if VERBOSE > 0 244 output("Test passed\n"); 245 246#endif 247 PASSED; 248} 249 250 251