Hi Cygwin community,

I am currently facing a problem with the combination of setuid/execv on a 
Cygwin/Windows 7.

Here is the description of my configuration :
* Cygwin 1.7.17
* Windows 7 Pro (64 bits) - Service Pack 1
* Compilation (no option) and execution of a sample program using an admin 
account having the following privileges :
  - SeCreateTokenPrivilege
  - SeAssignPrimaryTokenPrivilege
  - SeTcbPrivilege
  - SeIncreaseQuotaPrivilege
  - SeRestorePrivilege
  - SeServiceLogonRight
  - SeBatchLogonRight

See attachment for the source code of the program.

An exemple of the observed output is the following :

  Parent / My child is 2380
  setuid returns 0
  Child exited with status 32512 and word 2380
  exited, status=127

The file /tmp/test.touched has not been created.

When executing the same code on an older configuration (Cygwin 1.5.25 / Windows 
XP Pro 2002 SP 2), the program runs correctly and produces the following output 
:

  Parent / My child is 1616
  setuid returns 0
  Child exited with status 6912 and word 1616
  exited, status=27

The file /tmp/test.touched has effectively been created.

Thanks for your help,
Laurent COCAULT
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>

int main(int argc, char** argv)
{

  /*************/
  /* FORK/EXEC */
  /*************/

  int status = 0;
  pid_t w = 0;
  
  /* Create the pipe */
  int pipe_script[2];
  if (pipe(pipe_script)==-1) {
    /* Pipe failed */
    printf("Pipe failed\n");
  }
  
  /* Fork the process */
  pid_t pid = fork();

  if (pid < 0) {

    /* Fork failed */
    printf("Fork failed\n");

  } else if (pid == 0) {

    /* Child, close the output pipe and connect standard input */
    dup2(pipe_script[0], 0);
    close(pipe_script[0]);
    close(pipe_script[1]);

    /**********/
    /* SETUID */
    /**********/
    printf("setuid returns %d\n", setuid(1012)); /* Change the UID */

    /* Execute a bash shell */
    char* args[1];
    args[0] = NULL;
    status = execv("/bin/bash", args);
                
    /* Should not be here */
    printf("Exec failed : %d\n", status);

  } else {

    /* Parent, close input pipe */
    printf("Parent / My child is %d\n", pid);
    close(pipe_script[0]);
                
    /* Pass two commands to child shell */
    const char* cmd1 = "touch /tmp/test.touched\n";
    const char* cmd2 = "exit 27\n";
    write(pipe_script[1], cmd1, strlen(cmd1));
    write(pipe_script[1], cmd2, strlen(cmd2));

    /* Wait for child to exit */
    w = waitpid(pid, &status, 0);
    if (w == -1) {
      perror("waitpid");
      exit(EXIT_FAILURE);
    }
    printf("Child exited with status %d and word %d\n", status, w);
    
    /* Decode child exit code */
    if (WIFEXITED(status)) {
      printf("exited, status=%d\n", WEXITSTATUS(status));
    } else if (WIFSIGNALED(status)) {
      printf("killed by signal %d\n", WTERMSIG(status));
    } else if (WIFSTOPPED(status)) {
      printf("stopped by signal %d\n", WSTOPSIG(status));
    }

  }

  return status;

}
--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

Reply via email to