relying on PATH_MAX can cause overflow

vik*_*ria 2 c linux security x86 buffer-overflow

as you know PATH_MAX is value use to indicate the max size of an environment variable (in this case PATH variable), but it's not topically the case in most cases take a look at this code that is used to copy the environment variable into an array of size PATH_MAX

  char env[PATH_MAX]; 
  strcpy(path, getenv("PATH"));
Run Code Online (Sandbox Code Playgroud)

if you can see it can overflow so easily, one would say use strncpy so you can avoid overflow, but if you use it and the PATH is large then MAX_PATH we will not be able to get the PATH env variable complete and that make me thinking, how I could get the PATH env variable with the assumption that should be no overflow nor loss of data

Pet*_*des 5

通常,如果您根本需要复制一个未知长度的字符串,请使用strncpy复制到具有大小限制的固定大小的缓冲区中(但是请注意,如果字符串太长,则不终止该字符串会带来不便的行为)。

或用于strdup分配副本。


如您所知PATH_MAX,值是用来指示环境变量(在这种情况下为PATH变量)的最大大小

不,不是;与$PATH环境无关!!

它是单个文件系统路径名的最大长度。例如/foo/bar/verylongdirectoryname/x/y.txt,保证最大PATH_MAX长度。否则,您可能无法使用绝对路径读取它,而不得不将chdir插入该树并使用相对路径。

PATH环境只是一个扁带就像任何其他的环境变量; 内核不会将它们裁剪为固定长度。或当然不设上限PATH_MAX

我如何在不应该​​溢出也不丢失数据的前提下获取PATH env变量

嗯,您已经拥有了getenv("PATH")。这将返回一个指向进程内存空间中现有字符串的指针。它在静态存储中有效;您不需要复制它,以后的调用getenv也不会破坏指针。(在Linux上,ENV瓦尔在堆栈以上的argv在进程启动上。CRT启动代码,任何事情之前运行移动堆栈指针存储指向它们在全球envp哪里getenv以后可以找到它。)

如果要为一个env var 复制缓冲区,以便可以加长缓冲区或在不更改原始缓冲区的情况下对其进行修改,最简单的选择是strdup(3)from<string.h>来分配副本。 (POSIX 2008,以及之前的BSD,GNU C和之前的各种其他系统)。或strndup设置要复制的字节数的限制。

GNU C甚至有一个基于alloca的版本,而不是基于malloc的版本,以防您想要便宜的自动存储临时版本。


PATH_MAX

PATH_MAX例如在POSIX函数中是相关的,例如getwd(3)您提供缓冲区但没有长度限制的地方。(但实际上,您应该char *getcwd(char *buf, size_t size)改用它;参见与相同的链接getwd。手册页还说:

请注意,在某些系统上,PATH_MAX 可能不是编译时常量。此外,其值可能取决于文件系统,请参见pathconf(3)。


Linux readdir(3)手册页没有这么说,但是 struct dirent成员 char d_name[256]; /* Null-terminated filename */的大小是这样专门确定的,因为PATH_MAX=255。(或者更准确地说,由于readdir的大小限制,PATH_MAX为255)。


此外,类似chdir(2)或的系统调用open(2)在超过PATH_MAXENAMETOOLONG)的路径上也会失败:

ENAMETOOLONG
路径名或路径名的组成部分太长。

readlink(2)采用缓冲区大小,因此不需要限制链接目标的长度;它仅在您提供的路径中提到ENAMETOOLONG作为可能的错误,而不是链接名称。


即使在现代Linux上,单个文件名的255个字节也是一个硬限制。但是IIRC确实选择允许更长的路径名(具有多个目录组件)。POSIX规范在长路径上不需要错误open(),因此OS可以提供​​相当小的PATH_MAX,但在可能的情况下仍然可以在较长的路径上工作。