Ejemplo n.º 1
0
int main(int ac, char **av)
{
	int lc, pid;

	tst_parse_opts(ac, av, NULL, NULL);

	setup();

#ifdef UCLINUX
	maybe_run_child(&dochild, "sdd", filename, &recstart, &reclen);
#endif

	for (lc = 0; TEST_LOOPING(lc); lc++) {
		sprintf(filename, MOUNT_DIR"%s.%d.%d\n", TCID, getpid(), lc);

		if (tst_fill_file(filename, 0, 1024, 8)) {
			tst_brkm(TBROK, cleanup,
			         "Failed to create test file '%s'", filename);
		}

		SAFE_CHMOD(cleanup, filename, 02666);

		reclen = RECLEN;
		/*
		 * want at least RECLEN bytes BEFORE AND AFTER the
		 * record lock.
		 */
		recstart = RECLEN + rand() % (len - 3 * RECLEN);

		if ((pid = FORK_OR_VFORK()) < 0)
			tst_brkm(TBROK | TERRNO, cleanup, "fork() failed");

		if (pid == 0) {
#ifdef UCLINUX
			if (self_exec(av[0], "sdd", filename, recstart,
			              reclen) < -1) {
				tst_brkm(TBROK, cleanup, "self_exec() failed");
			}
#else
			dochild();
#endif
		}

		doparent();
	}

	cleanup();
	tst_exit();
}
Ejemplo n.º 2
0
static BOOL chat_with_program(char *passwordprogram,char *name,char *chatsequence, BOOL as_root)
{
  char *slavedev;
  int master;
  pid_t pid, wpid;
  int wstat;
  BOOL chstat = False;    

  /* allocate a pseudo-terminal device */
  if ((master = findpty (&slavedev)) < 0) {
    DEBUG(3,("Cannot Allocate pty for password change: %s\n",name));
    return(False);
  }

  /*
   * We need to temporarily stop CatchChild from eating
   * SIGCLD signals as it also eats the exit status code. JRA.
   */

  CatchChildLeaveStatus();

#ifdef __uClinux__
  /* Hmmm, need to check this one further... */
  DEBUG(0,("%s(%d): vfork()ing\n",__FILE__,__LINE__));
  if ((pid = vfork()) < 0) {
#else
  if ((pid = fork()) < 0) {
#endif
    DEBUG(3,("Cannot fork() child for password change: %s\n",name));
    close(master);
    CatchChild();
    return(False);
  }

  /* we now have a pty */
  if (pid > 0){			/* This is the parent process */
    if ((chstat = talktochild(master, chatsequence)) == False) {
      DEBUG(3,("Child failed to change password: %s\n",name));
      kill(pid, SIGKILL); /* be sure to end this process */
    }

	while((wpid = sys_waitpid(pid, &wstat, 0)) < 0) {
      if(errno == EINTR) {
        errno = 0;
        continue;
      }
	  break;
    }

    if (wpid < 0) {
      DEBUG(3,("The process is no longer waiting!\n\n"));
      close(master);
      CatchChild();
      return(False);
    }

    /*
     * Go back to ignoring children.
     */
    CatchChild();

    close(master);

    if (pid != wpid) {
      DEBUG(3,("We were waiting for the wrong process ID\n"));	
      return(False);
    }
    if (WIFEXITED(wstat) == 0) {
      DEBUG(3,("The process exited while we were waiting\n"));
      return(False);
    }
    if (WEXITSTATUS(wstat) != 0) {
      DEBUG(3,("The status of the process exiting was %d\n", wstat));
      return(False);
    }
    
  } else {
    /* CHILD */

    /*
     * Lose any oplock capabilities.
     */
    set_process_capability(KERNEL_OPLOCK_CAPABILITY, False);
    set_inherited_process_capability(KERNEL_OPLOCK_CAPABILITY, False);

    /* make sure it doesn't freeze */
    alarm(20);

    if (as_root)
      become_root(False);
    DEBUG(3,("Dochild for user %s (uid=%d,gid=%d)\n",name,(int)getuid(),(int)getgid()));
    chstat = dochild(master, slavedev, name, passwordprogram, as_root);

	/*
	 * The child should never return from dochild() ....
	 */

	DEBUG(0,("chat_with_program: Error: dochild() returned %d\n", chstat ));
	exit(1);
  }

  if (chstat)
    DEBUG(3,("Password change %ssuccessful for user %s\n", (chstat?"":"un"), name));
  return (chstat);
}


BOOL chgpasswd(char *name,char *oldpass,char *newpass, BOOL as_root)
{
  pstring passwordprogram;
  pstring chatsequence;
  size_t i;
  size_t len;

  strlower(name); 
  DEBUG(3,("Password change for user: %s\n",name));

#if DEBUG_PASSWORD
  DEBUG(100,("Passwords: old=%s new=%s\n",oldpass,newpass)); 
#endif

  /* Take the passed information and test it for minimum criteria */
  /* Minimum password length */
  if (strlen(newpass) < lp_min_passwd_length()) /* too short, must be at least MINPASSWDLENGTH */ 
    {
      DEBUG(0,("Password Change: user %s, New password is shorter than minimum password length = %d\n",
            name, lp_min_passwd_length()));
      return (False);		/* inform the user */
    }
  
  /* Password is same as old password */
  if (strcmp(oldpass,newpass) == 0) /* don't allow same password */
    {
      DEBUG(2,("Password Change: %s, New password is same as old\n",name)); /* log the attempt */
      return (False);		/* inform the user */
    }

  pstrcpy(passwordprogram,lp_passwd_program());
  pstrcpy(chatsequence,lp_passwd_chat());

  if (!*chatsequence) {
    DEBUG(2,("Null chat sequence - no password changing\n"));
    return(False);
  }

  if (!*passwordprogram) {
    DEBUG(2,("Null password program - no password changing\n"));
    return(False);
  }

  /* 
   * Check the old and new passwords don't contain any control
   * characters.
   */

  len = strlen(oldpass); 
  for(i = 0; i < len; i++) {
    if (iscntrl((int)oldpass[i])) {
      DEBUG(0,("chat_with_program: oldpass contains control characters (disallowed).\n"));
      return False;
    }
  }

  len = strlen(newpass);
  for(i = 0; i < len; i++) {
    if (iscntrl((int)newpass[i])) {
      DEBUG(0,("chat_with_program: newpass contains control characters (disallowed).\n"));
      return False;
    }
  }

  pstring_sub(passwordprogram,"%u",name);
  /* note that we do NOT substitute the %o and %n in the password program
     as this would open up a security hole where the user could use
     a new password containing shell escape characters */

  pstring_sub(chatsequence,"%u",name);
  all_string_sub(chatsequence,"%o",oldpass,sizeof(pstring));
  all_string_sub(chatsequence,"%n",newpass,sizeof(pstring));
  return(chat_with_program(passwordprogram,name,chatsequence, as_root));
}
Ejemplo n.º 3
0
static BOOL chat_with_program(char *passwordprogram,char *name,char *chatsequence, BOOL as_root)
{
  char *slavedev;
  int master;
  pid_t pid, wpid;
  int wstat;
  BOOL chstat = False;    

  /* allocate a pseudo-terminal device */
  if ((master = findpty (&slavedev)) < 0) {
    DEBUG(3,("Cannot Allocate pty for password change: %s\n",name));
    return(False);
  }

  /*
   * We need to temporarily stop CatchChild from eating
   * SIGCLD signals as it also eats the exit status code. JRA.
   */

  CatchChildLeaveStatus();

  if ((pid = fork()) < 0) {
    DEBUG(3,("Cannot fork() child for password change: %s\n",name));
    close(master);
    CatchChild();
    return(False);
  }

  /* we now have a pty */
  if (pid > 0){			/* This is the parent process */
    if ((chstat = talktochild(master, chatsequence)) == False) {
      DEBUG(3,("Child failed to change password: %s\n",name));
      kill(pid, SIGKILL); /* be sure to end this process */
    }

	while((wpid = sys_waitpid(pid, &wstat, 0)) < 0) {
      if(errno == EINTR) {
        errno = 0;
        continue;
      }
	  break;
    }

    if (wpid < 0) {
      DEBUG(3,("The process is no longer waiting!\n\n"));
      close(master);
      CatchChild();
      return(False);
    }

    /*
     * Go back to ignoring children.
     */
    CatchChild();

    close(master);

    if (pid != wpid) {
      DEBUG(3,("We were waiting for the wrong process ID\n"));	
      return(False);
    }
    if (WIFEXITED(wstat) == 0) {
      DEBUG(3,("The process exited while we were waiting\n"));
      return(False);
    }
    if (WEXITSTATUS(wstat) != 0) {
      DEBUG(3,("The status of the process exiting was %d\n", wstat));
      return(False);
    }
    
  } else {
    /* CHILD */

    /*
     * Lose any oplock capabilities.
     */
    set_process_capability(KERNEL_OPLOCK_CAPABILITY, False);
    set_inherited_process_capability(KERNEL_OPLOCK_CAPABILITY, False);

    /* make sure it doesn't freeze */
    alarm(20);

    if (as_root)
      become_root(False);
    DEBUG(3,("Dochild for user %s (uid=%d,gid=%d)\n",name,(int)getuid(),(int)getgid()));
    chstat = dochild(master, slavedev, name, passwordprogram, as_root);

	/*
	 * The child should never return from dochild() ....
	 */

	DEBUG(0,("chat_with_program: Error: dochild() returned %d\n", chstat ));
	exit(1);
  }

  if (chstat)
    DEBUG(3,("Password change %ssuccessful for user %s\n", (chstat?"":"un"), name));
  return (chstat);
}
Ejemplo n.º 4
0
int run_test(int file_flag, int file_mode, int start, int end)
{
	int child_count;
	int child;
	int nexited;
	int status, expect_stat;
	int i, fail = 0;

	/* loop through all test cases */
	for (test = start; test < end; test++) {
		/* open a temp file to lock */
		fd = open(tmpname, file_flag, file_mode);
		if (fd < 0) {
			tst_brkm(TBROK, cleanup, "open failed");
		 }

		/* write some dummy data to the file */
		(void)write(fd, FILEDATA, 10);

		/* Initialize first parent lock structure */
		thiscase = &testcases[test];
		thislock = &thiscase->parent_a;

		/* set the initial parent lock on the file */
		if ((fcntl(fd, F_SETLK, thislock)) < 0) {
			tst_resm(TFAIL, "First parent lock failed");
			tst_resm(TFAIL, "Test case %d, errno = %d", test + 1,
				 errno);
			unlink(tmpname);
			return 1;
		}

		/* Initialize second parent lock structure */
		thislock = &thiscase->parent_b;

		if ((thislock->type) != IGNORED) {	/*SKIPVAL */
			/* set the second parent lock */
			if ((fcntl(fd, F_SETLK, thislock)) < 0) {
				tst_resm(TFAIL, "Second parent lock failed");
				tst_resm(TFAIL, "Test case %d, errno = %d",
					 test + 1, errno);
				unlink(tmpname);
				return 1;
			}
		}

		/* Initialize first child lock structure */
		thislock = &thiscase->child_a;

		/* Initialize child counter and flags */
		alarm_flag = parent_flag = 0;
		child_flag1 = child_flag2 = 0;
		child_count = 0;

		/* spawn child processes */
		for (i = 0; i < 2; i++) {
			if (thislock->type != IGNORED) {
				if ((child = FORK_OR_VFORK()) == 0) {
#ifdef UCLINUX
					if (self_exec(argv0, "ddddd", i, parent,
						      test, thislock, fd) < 0) {
						perror("self_exec failed");
						return 1;
					}
#else
					dochild(i);
#endif
				}
				if (child < 0) {
					perror("Fork failed");
					return 1;
				}
				child_count++;
				child_pid[i] = child;
				flag[i] = thislock->flag;
			}
			/* Initialize second child lock structure */
			thislock = &thiscase->child_b;
		}
		/* parent process */

		/*
		 * Wait for children to signal they are ready. Set a timeout
		 * just in case they don't signal at all.
		 */
		alarm(TIME_OUT);

		while (!alarm_flag
		       && (child_flag1 + child_flag2 != child_count)) {
			pause();
		}

		/*
		 * Turn off alarm and unmask signals
		 */
		alarm((unsigned)0);

		if (child_flag1 + child_flag2 != child_count) {
			tst_resm(TFAIL, "Test case %d: kids didn't signal",
				 test + 1);
			fail = 1;
		}
		child_flag1 = child_flag2 = alarm_flag = 0;

		thislock = &thiscase->parent_c;

		/* set the third parent lock on the file */
		if ((fcntl(fd, F_SETLK, thislock)) < 0) {
			tst_resm(TFAIL, "Third parent lock failed");
			tst_resm(TFAIL, "Test case %d, errno = %d",
				 test + 1, errno);
			unlink(tmpname);
			return 1;
		}

		/* Initialize fourth parent lock structure */
		thislock = &thiscase->parent_d;

		if ((thislock->type) != IGNORED) {	/*SKIPVAL */
			/* set the fourth parent lock */
			if ((fcntl(fd, F_SETLK, thislock)) < 0) {
				tst_resm(TINFO, "Fourth parent lock failed");
				tst_resm(TINFO, "Test case %d, errno = %d",
					 test + 1, errno);
				unlink(tmpname);
				return 1;
			}
		}

		/*
		 * Wait for children to exit, or for timeout to occur.
		 * Timeouts are expected for testcases where kids are
		 * 'WILLBLOCK', In that case, send kids a wakeup interrupt
		 * and wait again for them. If a second timeout occurs, then
		 * something is wrong.
		 */
		alarm_flag = nexited = 0;
		while (nexited < child_count) {
			alarm(TIME_OUT);
			child = wait(&status);
			alarm(0);

			if (child == -1) {
				if (errno != EINTR || alarm_flag != 1) {
					/*
					 * Some error other than a timeout,
					 * or else this is the second
					 * timeout. Both cases are errors.
					 */
					break;
				}

				/*
				 * Expected timeout case. Signal kids then
				 * go back and wait again
				 */
				child_sig(SIGUSR1, child_count);
				continue;
			}

			for (i = 0; i < child_count; i++)
				if (child == child_pid[i])
					break;
			if (i == child_count) {
				/*
				 * Ignore unexpected kid, it could be a
				 * leftover from a previous iteration that
				 * timed out.
				 */
				continue;
			}

			/* Found the right kid, check his status */
			nexited++;

			expect_stat = (flag[i] == NOBLOCK) ? 0 : 1;

			if (!WIFEXITED(status)
			    || WEXITSTATUS(status) != expect_stat) {
				/* got unexpected exit status from kid */
				tst_resm(TFAIL, "Test case %d: child %d %s "
					 "or got bad status (x%x)", test + 1,
					 i, (flag[i] == NOBLOCK) ?
					 "BLOCKED unexpectedly" :
					 "failed to BLOCK", status);
				fail = 1;
			}
		}

		if (nexited != child_count) {
			tst_resm(TFAIL, "Test case %d, caught %d expected %d "
				 "children", test + 1, nexited, child_count);
			child_sig(SIGKILL, nexited);
			fail = 1;
		}
		close(fd);
	}
	unlink(tmpname);
	if (fail) {
		return 1;
	} else {
		return 0;
	}
	return 0;
}
Ejemplo n.º 5
0
void dochild_uc()
{
	dochild(kid_uc);
}
Ejemplo n.º 6
0
int main(int ac, char **av)
{
	int fd, i;
	int tlen = 0;
	struct sigaction act;
	int lc;
	char *msg;
	struct statvfs fs;

	/*
	 * parse standard options
	 */
	if ((msg = parse_opts(ac, av, NULL, NULL)) != NULL) {
		tst_resm(TBROK, "OPTION PARSING ERROR - %s", msg);
		tst_exit();

	}
#ifdef UCLINUX
	maybe_run_child(&dochild, "dddd", filename, &recstart, &reclen, &ppid);
#endif

	local_flag = PASSED;
	tst_tmpdir();
	if (statvfs(".", &fs) == -1) {
		tst_resm(TFAIL | TERRNO, "statvfs failed");
		tst_rmdir();
		tst_exit();
	}
	if ((fs.f_flag & MS_MANDLOCK) == 0) {
		tst_resm(TCONF,
			 "The filesystem where /tmp is mounted does"
			 " not support mandatory locks. Cannot run this test.");
		tst_rmdir();
		tst_exit();

	}
	for (lc = 0; TEST_LOOPING(lc); lc++) {
		setvbuf(stdin, 0, _IOLBF, BUFSIZ);
		setvbuf(stdout, 0, _IOLBF, BUFSIZ);
		setvbuf(stderr, 0, _IOLBF, BUFSIZ);
		ppid = getpid();
		srand(ppid);
		sigemptyset(&set);
		act.sa_handler = (void (*)())usr1hndlr;
		act.sa_mask = set;
		act.sa_flags = 0;
		if (sigaction(SIGUSR1, &act, 0)) {
			tst_resm(TBROK, "Sigaction for SIGUSR1 failed");
			tst_rmdir();
			tst_exit();
		}		/* end if */
		if (sigaddset(&set, SIGUSR1)) {
			tst_resm(TBROK, "sigaddset for SIGUSR1 failed");
			tst_rmdir();
			tst_exit();
		}
		if (sigprocmask(SIG_SETMASK, &set, 0)) {
			tst_resm(TBROK, "sigprocmask for SIGUSR1 failed");
			tst_rmdir();
			tst_exit();
		}
		for (i = 0; i < iterations; i++) {
			sprintf(filename, "%s.%d.%d\n", progname, ppid, i);
			if ((fd = open(filename, O_CREAT | O_RDWR, 02666)) < 0) {
				tst_resm(TBROK,
					 "parent error opening/creating %s",
					 filename);
				cleanup();
			}	/* end if */
			if (chown(filename, geteuid(), getegid()) == -1) {
				tst_resm(TBROK, "parent error chowning %s",
					 filename);
				cleanup();
			}	/* end if */
			if (chmod(filename, 02666) == -1) {
				tst_resm(TBROK, "parent error chmoding %s",
					 filename);
				cleanup();
			}	/* end if */
			do {
				if (write(fd, buffer, BUFSIZE) < 0) {
					tst_resm(TBROK,
						 "parent write failed to %s",
						 filename);
					cleanup();
				}
				tlen += BUFSIZE;
			} while (tlen < len);
			close(fd);
			reclen = RECLEN;
			/*
			 * want at least RECLEN bytes BEFORE AND AFTER the
			 * record lock.
			 */
			recstart = RECLEN + rand() % (len - 3 * RECLEN);

			if (sync_pipe_create(sync_pipes, PIPE_NAME) == -1)
				tst_brkm(TBROK, cleanup,
					 "sync_pipe_create failed");

			if ((cpid = FORK_OR_VFORK()) < 0) {
				unlink(filename);
				tst_resm(TINFO,
					 "System resource may be too low, fork() malloc()"
					 " etc are likely to fail.");
				tst_resm(TBROK,
					 "Test broken due to inability of fork.");
				tst_rmdir();
				tst_exit();
			}

			if (cpid == 0) {
#ifdef UCLINUX
				if (self_exec
				    (av[0], "dddd", filename, recstart, reclen,
				     ppid) < -1) {
					unlink(filename);
					tst_resm(TBROK, "self_exec failed.");
					tst_rmdir();
					tst_exit();
				}
#else
				dochild();
#endif
				/* never returns */
			}

			if (sync_pipe_wait(sync_pipes) == -1)
				tst_brkm(TBROK, cleanup,
					 "sync_pipe_wait failed");

			if (sync_pipe_close(sync_pipes, PIPE_NAME) == -1)
				tst_brkm(TBROK, cleanup,
					 "sync_pipe_close failed");

			doparent();
			/* child should already be dead */
			unlink(filename);
		}
		if (local_flag == PASSED)
			tst_resm(TPASS, "Test passed.");
		else
			tst_resm(TFAIL, "Test failed.");

		tst_rmdir();
		tst_exit();
	}			/* end for */
	tst_exit();
}