过滤execve环境的正确方法

时间:2018-05-19 14:24:49

标签: c environment-variables ld-preload execve

我正在尝试编写一个LD_PRELOAD能够阻止进程从此变量中删除进程的库(以确保子进程继承它)。 到目前为止,我成功地包裹了putenvsetenvclearenv,但execve给了我一些问题。

到目前为止我的代码:

int (*real_execve)(const char *filename, char *const argv[], char *const envp[]);
int execve(const char *filename, char *const argv[], char *const envp[]){
  real_execve = dlsym(RTLD_NEXT,"execve");
  char *path = getenv("LD_PRELOAD");
  fprintf(stderr, "INTERCEPTED execve, env:\n");
  int i;
  for(i=0;envp[i]!=NULL;i++);
  char *nenvp[i+1];
  nenvp[i]=NULL;
  for(i=0;envp[i]!=NULL;i++){
    char *string = envp[i];
    char *buf = malloc((strlen(string)+1)*sizeof(char));
    strcpy(buf,string);
    char *name = strtok(buf,"=");
    char *value = strtok(NULL,"=");
    if(0==strcmp(name,"LD_PRELOAD")){
      fprintf(stderr,"  FIXING '%s'\n",string);
      char * nstring = malloc((strlen(name)+strlen(path)+strlen(value)+3)*sizeof(char));
      strcpy(nstring,name);
      strcat(nstring,"=");
      strcat(nstring,path);
      strcat(nstring,":");
      strcat(nstring,value);
      nenvp[i]=nstring;
      fprintf(stderr,"    TO  '%s'\n",nenvp[i]);
      free(string);
    }else{
      nenvp[i]=envp[i];
      fprintf(stderr,"  LEFT  '%s'\n",nenvp[i]);
    }
    free(buf);
  }
  fprintf(stderr, "  CALLING %s\n", filename);
  return real_execve(filename,argv,nenvp);
}

我遇到了两个问题:

  • 记录如下内容:

    FIXING 'LD_PRELOAD=/usr/$LIB/libstdc++.so.6 /usr/$LIB/libgcc_s.so.1 /usr/$LIB/libxcb.so.1'
      TO  'LD_PRELOAD=/usr/$LIB/libstdc++.so.6 /usr/$LIB/libgcc_s.so.1 /usr/$LIB/libxcb.so.1:/usr/$LIB/libstdc++.so.6 /usr/$LIB/libgcc_s.so.1 /usr/$LIB/libxcb.so.1'
    

    而不是预期的自我前路,所以我想我不知何故搞砸了strtok。

  • 我收到很多错误:

    Error in 'sh': munmap_chunk(): invalid pointer: 0x00007fff3888af4a

    对我而言,听起来我可能会解放太多,但我找不到罪魁祸首。

我希望这听起来不像是“嘿为我解决这个问题”的帖子,但是我在这里碰壁,任何帮助都会非常感激。

2 个答案:

答案 0 :(得分:2)

您不能假设envp中的单个字符串已分配malloc,因此free(string)可能是未定义的行为。实际上不可能用完全空的堆调用exec*,并且无论如何都会替换整个图像,因此不值得担心。

您的第二次strtok来电应提供NULL作为其第一个参数。有关说明和示例,请参阅man strtok

答案 1 :(得分:1)

直接这样做:

  • 使用保存新env / var / s所需的大小创建 new 指针数组
  • strdup()从旧数组到新数组所需的所有元素。
  • 根据需要添加新内容。
  • 确保数组中的最后一个指针是NULL
  • 将新指针数组传递给原始execve()

修改或甚至(尝试)旧环境的free()条目。