1f08c3bdfSopenharmony_ci/* 2f08c3bdfSopenharmony_ci * 3f08c3bdfSopenharmony_ci * Copyright (c) International Business Machines Corp., 2001 4f08c3bdfSopenharmony_ci * 5f08c3bdfSopenharmony_ci * This program is free software; you can redistribute it and/or modify 6f08c3bdfSopenharmony_ci * it under the terms of the GNU General Public License as published by 7f08c3bdfSopenharmony_ci * the Free Software Foundation; either version 2 of the License, or 8f08c3bdfSopenharmony_ci * (at your option) any later version. 9f08c3bdfSopenharmony_ci * 10f08c3bdfSopenharmony_ci * This program is distributed in the hope that it will be useful, 11f08c3bdfSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 12f08c3bdfSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 13f08c3bdfSopenharmony_ci * the GNU General Public License for more details. 14f08c3bdfSopenharmony_ci * 15f08c3bdfSopenharmony_ci * You should have received a copy of the GNU General Public License 16f08c3bdfSopenharmony_ci * along with this program; if not, write to the Free Software 17f08c3bdfSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18f08c3bdfSopenharmony_ci */ 19f08c3bdfSopenharmony_ci 20f08c3bdfSopenharmony_ci/* 21f08c3bdfSopenharmony_ci * Name: vfork01 22f08c3bdfSopenharmony_ci * 23f08c3bdfSopenharmony_ci * Test Description: 24f08c3bdfSopenharmony_ci * Fork a process using vfork() and verify that, the attribute values like 25f08c3bdfSopenharmony_ci * euid, ruid, suid, egid, rgid, sgid, umask, inode and device number of 26f08c3bdfSopenharmony_ci * root and current working directories are same as that of the parent 27f08c3bdfSopenharmony_ci * process. 28f08c3bdfSopenharmony_ci * $ 29f08c3bdfSopenharmony_ci * Expected Result: 30f08c3bdfSopenharmony_ci * The attribute values like euid, ruid, suid, egid, rgid, sgid, umask, inode 31f08c3bdfSopenharmony_ci * and device number of root and current working directory of the parent and 32f08c3bdfSopenharmony_ci * child processes should be equal. 33f08c3bdfSopenharmony_ci * 34f08c3bdfSopenharmony_ci * Algorithm: 35f08c3bdfSopenharmony_ci * Setup: 36f08c3bdfSopenharmony_ci * Setup signal handling. 37f08c3bdfSopenharmony_ci * Pause for SIGUSR1 if option specified. 38f08c3bdfSopenharmony_ci * 39f08c3bdfSopenharmony_ci * Test: 40f08c3bdfSopenharmony_ci * Loop if the proper options are given. 41f08c3bdfSopenharmony_ci * Execute system call 42f08c3bdfSopenharmony_ci * Check return code, if system call failed (return=-1) 43f08c3bdfSopenharmony_ci * Log the errno and Issue a FAIL message. 44f08c3bdfSopenharmony_ci * Otherwise, 45f08c3bdfSopenharmony_ci * Verify the Functionality of system call 46f08c3bdfSopenharmony_ci * if successful, 47f08c3bdfSopenharmony_ci * Issue Functionality-Pass message. 48f08c3bdfSopenharmony_ci * Otherwise, 49f08c3bdfSopenharmony_ci * Issue Functionality-Fail message. 50f08c3bdfSopenharmony_ci * Cleanup: 51f08c3bdfSopenharmony_ci * Print errno log and/or timing stats if options given 52f08c3bdfSopenharmony_ci * 53f08c3bdfSopenharmony_ci * Usage: <for command-line> 54f08c3bdfSopenharmony_ci * vfork01 [-c n] [-e] [-f] [-i n] [-I x] [-p x] [-t] 55f08c3bdfSopenharmony_ci * where, -c n : Run n copies concurrently. 56f08c3bdfSopenharmony_ci * -e : Turn on errno logging. 57f08c3bdfSopenharmony_ci * -f : Turn off functionality Testing. 58f08c3bdfSopenharmony_ci * -i n : Execute test n times. 59f08c3bdfSopenharmony_ci * -I x : Execute test for x seconds. 60f08c3bdfSopenharmony_ci * -P x : Pause for x seconds between iterations. 61f08c3bdfSopenharmony_ci * -t : Turn on syscall timing. 62f08c3bdfSopenharmony_ci * 63f08c3bdfSopenharmony_ci * History 64f08c3bdfSopenharmony_ci * 07/2001 John George 65f08c3bdfSopenharmony_ci * -Ported 66f08c3bdfSopenharmony_ci * 67f08c3bdfSopenharmony_ci * Restrictions: 68f08c3bdfSopenharmony_ci * None. 69f08c3bdfSopenharmony_ci * 70f08c3bdfSopenharmony_ci */ 71f08c3bdfSopenharmony_ci 72f08c3bdfSopenharmony_ci#define _GNU_SOURCE 1 73f08c3bdfSopenharmony_ci#include <stdio.h> 74f08c3bdfSopenharmony_ci#include <sys/types.h> 75f08c3bdfSopenharmony_ci#include <errno.h> 76f08c3bdfSopenharmony_ci#include <unistd.h> 77f08c3bdfSopenharmony_ci#include <fcntl.h> 78f08c3bdfSopenharmony_ci#include <string.h> 79f08c3bdfSopenharmony_ci#include <signal.h> 80f08c3bdfSopenharmony_ci#include <unistd.h> 81f08c3bdfSopenharmony_ci#include <sys/stat.h> 82f08c3bdfSopenharmony_ci#include <sys/wait.h> 83f08c3bdfSopenharmony_ci 84f08c3bdfSopenharmony_ci#include "test.h" 85f08c3bdfSopenharmony_ci 86f08c3bdfSopenharmony_cichar *TCID = "vfork01"; 87f08c3bdfSopenharmony_ciint TST_TOTAL = 1; 88f08c3bdfSopenharmony_ci 89f08c3bdfSopenharmony_ci/* Variables to hold parent/child eff/real/saved uid/gid values */ 90f08c3bdfSopenharmony_ciuid_t Peuid, Ceuid, Csuid, Psuid, Pruid, Cruid; 91f08c3bdfSopenharmony_cigid_t Pegid, Cegid, Psgid, Csgid, Prgid, Crgid; 92f08c3bdfSopenharmony_cimode_t Pumask, Cumask; 93f08c3bdfSopenharmony_ci 94f08c3bdfSopenharmony_cichar *Pcwd, *Ccwd; /* 95f08c3bdfSopenharmony_ci * pathname of working directory of 96f08c3bdfSopenharmony_ci * child/parent process. 97f08c3bdfSopenharmony_ci */ 98f08c3bdfSopenharmony_ci/* stat structure to hold directory/inode information for parent/child */ 99f08c3bdfSopenharmony_cistruct stat StatPbuf; 100f08c3bdfSopenharmony_cistruct stat StatCbuf; 101f08c3bdfSopenharmony_cistruct stat Stat_cwd_Pbuf; 102f08c3bdfSopenharmony_cistruct stat Stat_cwd_Cbuf; 103f08c3bdfSopenharmony_ci 104f08c3bdfSopenharmony_civoid setup(); /* Main setup function of test */ 105f08c3bdfSopenharmony_civoid cleanup(); /* cleanup function for the test */ 106f08c3bdfSopenharmony_ci 107f08c3bdfSopenharmony_ciint main(int ac, char **av) 108f08c3bdfSopenharmony_ci{ 109f08c3bdfSopenharmony_ci int lc; 110f08c3bdfSopenharmony_ci pid_t cpid; /* process id of the child process */ 111f08c3bdfSopenharmony_ci int exit_status; /* exit status of child process */ 112f08c3bdfSopenharmony_ci 113f08c3bdfSopenharmony_ci tst_parse_opts(ac, av, NULL, NULL); 114f08c3bdfSopenharmony_ci 115f08c3bdfSopenharmony_ci setup(); 116f08c3bdfSopenharmony_ci 117f08c3bdfSopenharmony_ci for (lc = 0; TEST_LOOPING(lc); lc++) { 118f08c3bdfSopenharmony_ci 119f08c3bdfSopenharmony_ci tst_count = 0; 120f08c3bdfSopenharmony_ci 121f08c3bdfSopenharmony_ci /* 122f08c3bdfSopenharmony_ci * Call vfork(2) to create a child process without 123f08c3bdfSopenharmony_ci * fully copying the address space of parent. 124f08c3bdfSopenharmony_ci */ 125f08c3bdfSopenharmony_ci TEST(vfork()); 126f08c3bdfSopenharmony_ci 127f08c3bdfSopenharmony_ci if ((cpid = TEST_RETURN) == -1) { 128f08c3bdfSopenharmony_ci tst_resm(TFAIL, "vfork() Failed, errno=%d : %s", 129f08c3bdfSopenharmony_ci TEST_ERRNO, strerror(TEST_ERRNO)); 130f08c3bdfSopenharmony_ci } else if (cpid == 0) { /* Child process */ 131f08c3bdfSopenharmony_ci /* 132f08c3bdfSopenharmony_ci * Get the euid, ruid, egid, rgid, umask value 133f08c3bdfSopenharmony_ci * and the current working directory of the 134f08c3bdfSopenharmony_ci * child process 135f08c3bdfSopenharmony_ci */ 136f08c3bdfSopenharmony_ci if (getresuid(&Cruid, &Ceuid, &Csuid) < 0) { 137f08c3bdfSopenharmony_ci tst_resm(TFAIL, "getresuid() fails to " 138f08c3bdfSopenharmony_ci "get real/eff./saved uid of " 139f08c3bdfSopenharmony_ci "child process"); 140f08c3bdfSopenharmony_ci _exit(1); 141f08c3bdfSopenharmony_ci } 142f08c3bdfSopenharmony_ci 143f08c3bdfSopenharmony_ci if (getresgid(&Crgid, &Cegid, &Csgid) < 0) { 144f08c3bdfSopenharmony_ci tst_resm(TFAIL, "getresgid() fails to " 145f08c3bdfSopenharmony_ci "get real/eff./saved gid of " 146f08c3bdfSopenharmony_ci "child process"); 147f08c3bdfSopenharmony_ci _exit(1); 148f08c3bdfSopenharmony_ci } 149f08c3bdfSopenharmony_ci 150f08c3bdfSopenharmony_ci /* 151f08c3bdfSopenharmony_ci * Get the file mode creation mask value of 152f08c3bdfSopenharmony_ci * child process by setting value zero and 153f08c3bdfSopenharmony_ci * restore the previous mask value. 154f08c3bdfSopenharmony_ci */ 155f08c3bdfSopenharmony_ci Cumask = umask(0); 156f08c3bdfSopenharmony_ci 157f08c3bdfSopenharmony_ci /* 158f08c3bdfSopenharmony_ci * Restore the process mask of child to 159f08c3bdfSopenharmony_ci * previous value. 160f08c3bdfSopenharmony_ci */ 161f08c3bdfSopenharmony_ci umask(Cumask); 162f08c3bdfSopenharmony_ci 163f08c3bdfSopenharmony_ci /* 164f08c3bdfSopenharmony_ci * Get the pathname of current working 165f08c3bdfSopenharmony_ci * directory for the child process. 166f08c3bdfSopenharmony_ci */ 167f08c3bdfSopenharmony_ci if ((Ccwd = (char *)getcwd(NULL, 168f08c3bdfSopenharmony_ci BUFSIZ)) == NULL) { 169f08c3bdfSopenharmony_ci tst_resm(TFAIL, "getcwd failed for the " 170f08c3bdfSopenharmony_ci "child process"); 171f08c3bdfSopenharmony_ci _exit(1); 172f08c3bdfSopenharmony_ci } 173f08c3bdfSopenharmony_ci 174f08c3bdfSopenharmony_ci /* 175f08c3bdfSopenharmony_ci * Get the device number and the inode 176f08c3bdfSopenharmony_ci * number of "/" directory for the child 177f08c3bdfSopenharmony_ci * process. 178f08c3bdfSopenharmony_ci */ 179f08c3bdfSopenharmony_ci if (stat("/", &StatCbuf) < 0) { 180f08c3bdfSopenharmony_ci tst_resm(TFAIL, "stat(2) failed to get " 181f08c3bdfSopenharmony_ci "info. of'/' in the child " 182f08c3bdfSopenharmony_ci "process"); 183f08c3bdfSopenharmony_ci _exit(1); 184f08c3bdfSopenharmony_ci } 185f08c3bdfSopenharmony_ci 186f08c3bdfSopenharmony_ci /* 187f08c3bdfSopenharmony_ci * Get the device/inode number of "." 188f08c3bdfSopenharmony_ci * (working directory) for the child process. 189f08c3bdfSopenharmony_ci */ 190f08c3bdfSopenharmony_ci if (stat(Ccwd, &Stat_cwd_Cbuf) < 0) { 191f08c3bdfSopenharmony_ci tst_resm(TFAIL, "stat(2) failed to get " 192f08c3bdfSopenharmony_ci "info. of working irectory in " 193f08c3bdfSopenharmony_ci "the child"); 194f08c3bdfSopenharmony_ci _exit(1); 195f08c3bdfSopenharmony_ci } 196f08c3bdfSopenharmony_ci 197f08c3bdfSopenharmony_ci /* Now, do the actual comparision */ 198f08c3bdfSopenharmony_ci if (Peuid != Ceuid || Pegid != Cegid || 199f08c3bdfSopenharmony_ci Psuid != Csuid || Psgid != Csgid || 200f08c3bdfSopenharmony_ci Pruid != Cruid || Prgid != Crgid || 201f08c3bdfSopenharmony_ci Pumask != Cumask) { 202f08c3bdfSopenharmony_ci tst_resm(TFAIL, "Attribute values of " 203f08c3bdfSopenharmony_ci "parent and child don't match"); 204f08c3bdfSopenharmony_ci _exit(1); 205f08c3bdfSopenharmony_ci } else { 206f08c3bdfSopenharmony_ci tst_resm(TINFO, "Attribute values of " 207f08c3bdfSopenharmony_ci "parent and child match"); 208f08c3bdfSopenharmony_ci } 209f08c3bdfSopenharmony_ci 210f08c3bdfSopenharmony_ci /* Check for the same working directories */ 211f08c3bdfSopenharmony_ci if (strcmp(Pcwd, Ccwd) != 0) { 212f08c3bdfSopenharmony_ci tst_resm(TFAIL, "Working directories " 213f08c3bdfSopenharmony_ci "of parent and child don't " 214f08c3bdfSopenharmony_ci "match"); 215f08c3bdfSopenharmony_ci _exit(1); 216f08c3bdfSopenharmony_ci } else { 217f08c3bdfSopenharmony_ci tst_resm(TINFO, "Working directories " 218f08c3bdfSopenharmony_ci "of parent and child match"); 219f08c3bdfSopenharmony_ci } 220f08c3bdfSopenharmony_ci 221f08c3bdfSopenharmony_ci /* 222f08c3bdfSopenharmony_ci * Check for the same device/inode number of 223f08c3bdfSopenharmony_ci * '/' directory. 224f08c3bdfSopenharmony_ci */ 225f08c3bdfSopenharmony_ci if ((StatPbuf.st_ino != StatCbuf.st_ino) || 226f08c3bdfSopenharmony_ci (StatPbuf.st_dev != StatCbuf.st_dev)) { 227f08c3bdfSopenharmony_ci tst_resm(TFAIL, "Device/inode number " 228f08c3bdfSopenharmony_ci "of parent and childs '/' " 229f08c3bdfSopenharmony_ci " don't match"); 230f08c3bdfSopenharmony_ci _exit(1); 231f08c3bdfSopenharmony_ci } else { 232f08c3bdfSopenharmony_ci tst_resm(TINFO, "Device/inode number " 233f08c3bdfSopenharmony_ci "of parent and childs '/' " 234f08c3bdfSopenharmony_ci "match"); 235f08c3bdfSopenharmony_ci } 236f08c3bdfSopenharmony_ci 237f08c3bdfSopenharmony_ci /* 238f08c3bdfSopenharmony_ci * Check for the same device and inode number 239f08c3bdfSopenharmony_ci * of "." (current working directory. 240f08c3bdfSopenharmony_ci */ 241f08c3bdfSopenharmony_ci if ((Stat_cwd_Pbuf.st_ino != 242f08c3bdfSopenharmony_ci Stat_cwd_Cbuf.st_ino) || 243f08c3bdfSopenharmony_ci (Stat_cwd_Pbuf.st_dev != 244f08c3bdfSopenharmony_ci Stat_cwd_Cbuf.st_dev)) { 245f08c3bdfSopenharmony_ci tst_resm(TFAIL, "Device/inode number " 246f08c3bdfSopenharmony_ci "of parent and childs '.' " 247f08c3bdfSopenharmony_ci "don't match"); 248f08c3bdfSopenharmony_ci _exit(1); 249f08c3bdfSopenharmony_ci } else { 250f08c3bdfSopenharmony_ci tst_resm(TINFO, "Device/inode number " 251f08c3bdfSopenharmony_ci "of parent and childs '.' " 252f08c3bdfSopenharmony_ci "don't match"); 253f08c3bdfSopenharmony_ci } 254f08c3bdfSopenharmony_ci 255f08c3bdfSopenharmony_ci /* 256f08c3bdfSopenharmony_ci * Exit with normal exit code if everything 257f08c3bdfSopenharmony_ci * fine 258f08c3bdfSopenharmony_ci */ 259f08c3bdfSopenharmony_ci _exit(0); 260f08c3bdfSopenharmony_ci 261f08c3bdfSopenharmony_ci } else { /* parent process */ 262f08c3bdfSopenharmony_ci /* 263f08c3bdfSopenharmony_ci * Let the parent process wait till child completes 264f08c3bdfSopenharmony_ci * its execution. 265f08c3bdfSopenharmony_ci */ 266f08c3bdfSopenharmony_ci wait(&exit_status); 267f08c3bdfSopenharmony_ci 268f08c3bdfSopenharmony_ci /* Check for the exit status of child process */ 269f08c3bdfSopenharmony_ci if (WEXITSTATUS(exit_status) == 0) { 270f08c3bdfSopenharmony_ci tst_resm(TPASS, "Call of vfork() successful"); 271f08c3bdfSopenharmony_ci } else if (WEXITSTATUS(exit_status) == 1) { 272f08c3bdfSopenharmony_ci tst_resm(TFAIL, 273f08c3bdfSopenharmony_ci "Child process exited abnormally"); 274f08c3bdfSopenharmony_ci } 275f08c3bdfSopenharmony_ci } 276f08c3bdfSopenharmony_ci tst_count++; /* incr. TEST_LOOP counter */ 277f08c3bdfSopenharmony_ci } 278f08c3bdfSopenharmony_ci 279f08c3bdfSopenharmony_ci cleanup(); 280f08c3bdfSopenharmony_ci tst_exit(); 281f08c3bdfSopenharmony_ci} 282f08c3bdfSopenharmony_ci 283f08c3bdfSopenharmony_ci/* 284f08c3bdfSopenharmony_ci * void 285f08c3bdfSopenharmony_ci * setup() - performs all ONE TIME setup for this test. 286f08c3bdfSopenharmony_ci * This function gets real/effective/saved uid/gid, umask, the device/inode 287f08c3bdfSopenharmony_ci * number of '/' and current working directory for the parent process. 288f08c3bdfSopenharmony_ci */ 289f08c3bdfSopenharmony_civoid setup(void) 290f08c3bdfSopenharmony_ci{ 291f08c3bdfSopenharmony_ci 292f08c3bdfSopenharmony_ci tst_sig(FORK, DEF_HANDLER, cleanup); 293f08c3bdfSopenharmony_ci 294f08c3bdfSopenharmony_ci TEST_PAUSE; 295f08c3bdfSopenharmony_ci 296f08c3bdfSopenharmony_ci /* 297f08c3bdfSopenharmony_ci * Get the euid, ruid, egid, rgid, umask value 298f08c3bdfSopenharmony_ci * and the current working directory of the parent process. 299f08c3bdfSopenharmony_ci */ 300f08c3bdfSopenharmony_ci if (getresuid(&Pruid, &Peuid, &Psuid) < 0) { 301f08c3bdfSopenharmony_ci tst_brkm(TFAIL, cleanup, "getresuid() fails to get " 302f08c3bdfSopenharmony_ci "real/eff./saved uid of parent"); 303f08c3bdfSopenharmony_ci } 304f08c3bdfSopenharmony_ci 305f08c3bdfSopenharmony_ci if (getresgid(&Prgid, &Pegid, &Psgid) < 0) { 306f08c3bdfSopenharmony_ci tst_brkm(TFAIL, cleanup, "getresgid() fails to get " 307f08c3bdfSopenharmony_ci "real/eff./saved gid of parent"); 308f08c3bdfSopenharmony_ci } 309f08c3bdfSopenharmony_ci 310f08c3bdfSopenharmony_ci /* Get the process file mode creation mask by setting value 0 */ 311f08c3bdfSopenharmony_ci Pumask = umask(0); 312f08c3bdfSopenharmony_ci umask(Pumask); /* 313f08c3bdfSopenharmony_ci * Restore the mask value of the 314f08c3bdfSopenharmony_ci * process. 315f08c3bdfSopenharmony_ci */ 316f08c3bdfSopenharmony_ci /* 317f08c3bdfSopenharmony_ci * Get the pathname of current working directory of the parent 318f08c3bdfSopenharmony_ci * process. 319f08c3bdfSopenharmony_ci */ 320f08c3bdfSopenharmony_ci if ((Pcwd = (char *)getcwd(NULL, BUFSIZ)) == NULL) { 321f08c3bdfSopenharmony_ci tst_brkm(TFAIL, cleanup, 322f08c3bdfSopenharmony_ci "getcwd failed for the parent process"); 323f08c3bdfSopenharmony_ci } 324f08c3bdfSopenharmony_ci 325f08c3bdfSopenharmony_ci /* 326f08c3bdfSopenharmony_ci * Get the device and inode number of root directory for the 327f08c3bdfSopenharmony_ci * parent process. 328f08c3bdfSopenharmony_ci */ 329f08c3bdfSopenharmony_ci if (stat("/", &StatPbuf) == -1) { 330f08c3bdfSopenharmony_ci tst_brkm(TFAIL, cleanup, "stat(2) failed to get info. of '/' " 331f08c3bdfSopenharmony_ci "in parent process"); 332f08c3bdfSopenharmony_ci } 333f08c3bdfSopenharmony_ci 334f08c3bdfSopenharmony_ci /* 335f08c3bdfSopenharmony_ci * Get the device number and the inode number of "." (current- 336f08c3bdfSopenharmony_ci * working directory) for the parent process. 337f08c3bdfSopenharmony_ci */ 338f08c3bdfSopenharmony_ci if (stat(Pcwd, &Stat_cwd_Pbuf) < 0) { 339f08c3bdfSopenharmony_ci tst_brkm(TFAIL, cleanup, "stat(2) failed to get info. of " 340f08c3bdfSopenharmony_ci "working directory in parent process"); 341f08c3bdfSopenharmony_ci } 342f08c3bdfSopenharmony_ci} 343f08c3bdfSopenharmony_ci 344f08c3bdfSopenharmony_ci/* 345f08c3bdfSopenharmony_ci * void 346f08c3bdfSopenharmony_ci * cleanup() - performs all ONE TIME cleanup for this test at 347f08c3bdfSopenharmony_ci * completion or premature exit. 348f08c3bdfSopenharmony_ci */ 349f08c3bdfSopenharmony_civoid cleanup(void) 350f08c3bdfSopenharmony_ci{ 351f08c3bdfSopenharmony_ci 352f08c3bdfSopenharmony_ci} 353