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