execve 到我刚刚写的文件——“文本文件忙”

Ara*_*dur 0 c linux execve

下面的 C 程序的预期行为是将其自己的可执行文件复制到一个新的随机命名的文件,然后执行该文件,令人作呕。这应该创建很多很多可执行文件的副本。这显然是一个糟糕的想法,但这仍然是我正在尝试做的事情。

#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;
}
Run Code Online (Sandbox Code Playgroud)

相反,输出如下:

Hello from ./execTest
execve: Text file busy
Run Code Online (Sandbox Code Playgroud)

我认为文本文件“忙”,因为./execTest仍在访问它......但我确实关闭了该文件的文件流。我做错了什么?

asv*_*kau 5

手册页mkstemp

   On success, these functions return the file descriptor of the
   temporary file.
Run Code Online (Sandbox Code Playgroud)

您丢弃由 返回给您的文件描述符mkstemp,从而有效地泄漏了它。可能它是一个可写文件描述符,因此会导致execve失败ETXTBSY(当有可写文件描述符打开时会发生这种情况)。您可以尝试close()一下返回值mkstemp并看看是否可以改善行为?

反馈的一般要点:在使用 C 语言编码时,您应该养成查看返回值的习惯。未能观察其含义和错误状态通常表明存在错误。