0

I'm trying to create a c program that takes an executable and its arguments and runs them using execve, and then does some other stuff that shouldn't matter. The problem I'm having is that execve won't work when calling it on an exectuable assembly file. I think the problem is with my path because I can get the unix shell commands to work, but I can't get executables in the current directory (using ./spy ./executableName where spy is the name of my c program) to run. Here's the code:

#include <stdio.h>
#include <stdlib.h>
#include <sys/user.h>
#include <sys/reg.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/ptrace.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>

extern char **environ;

int main(int argc, char* const argv[]) {
    pid_t pid;
    char filename[50];
    char* arglist[argc];
    int i = 1,count = 0;
    int status;

    strcpy(filename, "/bin/");
    strcat(filename,argv[1]);
    for(i = 1; i< argc; i++)
        arglist[i-1] = argv[i];
    arglist[argc-1] = 0;
    arglist[0] = filename;
    if (argc == 1) {
        fprintf(stderr,"usage : %s <prog> ...\n",argv[0]);
        return -1;
    }
    pid = fork();
    if(pid == 0) {
        ptrace(PTRACE_TRACEME, 0, NULL, NULL);
        if(execve(filename, arglist, 0) < 0)
            fprintf(stdout,"Invalid file.");
    }
    else {
        while(1) {
            waitpid(pid,&status,0);
            if (WIFEXITED(status))
                break;
            ptrace(PTRACE_SINGLESTEP, pid,NULL, NULL);
            count++;
        }
    }
    return 0;
}
zaloo
  • 879
  • 3
  • 13
  • 27
  • Welcome to Stack Overflow. Please read the [About] page soon. Can you run the executable assembly file from the shell? If not, the problem is in the executable assembly file. If so, you should also be able to execute it from your code. Can you run other programs (such as `ls`) from your program? When it comes down to it, every program (shell, `ls`, you name it) is produced from assembler code. – Jonathan Leffler Sep 07 '13 at 21:03
  • From the source you posted it looks as if you were always prefixing the name passed as parameter with `/bin/`. So if the file isn't in `/bin/` it can not be found, nor run. – alk Sep 07 '13 at 21:05
  • Thanks for the welcome! I've been able to run the executable assembly files, and I can run ls and other programs like cd and grep from my program. I think the issue is solely about my file path or environment variables, but I've been banging my head against the wall for a while and can't figure it out. Also @ alk, I've tried not prefixing it with /bin/. When i do that, neither file runs. I know that's not the right method, but I'm just confused with how to handle program location in the file system with execve. What do you think I should do? – zaloo Sep 07 '13 at 21:11

1 Answers1

1

From the source you posted it looks as if you were always prefixing the name passed as parameter with /bin/. So if the file isn't in /bin/ it can not be found, nor run.

Just change these two lines:

strcpy(filename, "/bin/");
strcat(filename,argv[1]);

to be:

strcpy(filename,argv[1]);

Note that having applied this modification the program to be run needs to be specified with its full path.

So to run ls you need to do specfify /bin/ls as parameter to the program.


Some other comments:

So avoid buffer a overflow for long path/file names change:

char filename[50];

to be:

char filename[PATH_MAX];

To get more detailed information on why an execve() might have failed change:

if(execve(filename, arglist, 0) < 0)
  fprintf(stdout,"Invalid file.");

to be:

if(execve(filename, arglist, (char*) 0) < 0)
  perror("execve() failed");

To detect a possible failure of forking do change:

pid = fork();

to become:

if (-1 == (pid = fork())) then
{
  perror("fork() failed");
}
else
alk
  • 69,737
  • 10
  • 105
  • 255
  • I made all the changes you listed (except PATHMAX, what should I import to get that variable), but I'm still getting a failure. This is similar to an earlier version I had, but I like the more descriptive error messages. I'm now getting an error from the perror("execve() failed"); line that says execve() failed: No such file or directory. Also, my code is now failing (expectedly) on ls, cd and grep now. I'm not hardcoding in the /bin/ prefix so that makes sense. – zaloo Sep 07 '13 at 21:37
  • @user2756569: Sry, that's been a typo, it's `PATH_MAX`. You need to specify the program to run **including** their path. Please see the **note** on this in my answer. – alk Sep 07 '13 at 21:58