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