0

The intended behavior of the C program below is to copy its own executable file to a new randomly-named file, then execve that file, ad nauseum. This should create many, many copies of the executable. This is obviously a terrible idea, but it is nevertheless what I am trying to do.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>

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

  /* Obtain name of current executable */
  const char* binName = argv[0];

  /* Print message */
  printf("Hello from %s!\n", binName);

  /* Create name of new executable */
  char newBinName[] = "tmpXXXXXX";
  mkstemp(newBinName);

  /* Determine size of current executable */
  struct stat st;
  stat(binName, &st);
  const int binSize = st.st_size;

  /* Copy current executable to memory */
  char* binData = (char*) malloc(sizeof(char) * binSize);
  FILE* binFile = fopen(binName, "rb");
  fread(binData, sizeof(char), binSize, binFile);
  fclose(binFile);

  /* Write executable in memory to new file */
  binFile = fopen(newBinName, "wb");
  fwrite(binData, sizeof(char), binSize, binFile);
  fclose(binFile);

  /* Make new file executable */
  chmod(newBinName, S_IRUSR | S_IWUSR |S_IXUSR);

  /* Run new file executable */
  execve(
    newBinName,
    (char*[]) {
      newBinName,
      NULL
    },
    NULL);

  /* If this code runs, then there has been an error. */
  perror("execve");

  return EXIT_FAILURE;
}

Instead, though, the following is output:

Hello from ./execTest
execve: Text file busy

I presume that the text file is "busy" because ./execTest is still accessing it... but I do close the file stream to that file. What is it that I'm doing wrong?

Arandur
  • 727
  • 6
  • 19

1 Answers1

4

From the manpage of mkstemp:

   On success, these functions return the file descriptor of the
   temporary file.

You discard the file descriptor returned to you by mkstemp, effectively leaking it. Probably it is a writable file descriptor and thus will cause execve to fail with ETXTBSY (which occurs when there are writable fds open). Can you try close() on the return value of mkstemp and see if that improves the behavior?

General point of feedback: When coding in C you should be in the habit of looking at return values. Failure to observe their meaning and error status is often indicative of a bug.

asveikau
  • 39,039
  • 2
  • 53
  • 68
  • Oh, bloody... yes, that was exactly it, thank you. I'm a C++ programmer; I'm still fumbling a bit with the C stuff. – Arandur Feb 20 '15 at 22:18