...
Code Block | ||
---|---|---|
| ||
char buf[2561024]; ssize_t len = readlink("/usr/bin/perl", buf, sizeof(buf)); buf[len] = '\0'; |
A simple (but An incorrect ) solution to this problem is to try to make buf
large enough that it can always hold the result:
Code Block | ||
---|---|---|
| ||
long symlink_max; size_t bufsize; char buf[PATH_MAX+1]; ssize_t *buf; ssize_t len; errno = 0; if ((symlink_max = pathconf("/usr/bin/", _PC_SYMLINK_MAX)) == -1 && errno != 0) { /* handle error condition */ } if (symlink_max == -1) bufsize = 10000; else bufsize = symlink_max+1; if ((buf = (char *)malloc(bufsize)) == NULL) { /* handle error condition */ } len = readlink("/usr/bin/perl", buf, sizeof(bufbufsize)); buf[len] = '\0'; |
This modification incorrectly assumes that PATH_MAX
represents the longest possible path for a file in the filesystem. (PATH_MAX
only bounds the longest possible relative path that can be passed to the kernel in a single call.) On most Unix and Linux systems, there is no easily-determined maximum length for a file paththe symbolic link cannot be longer than the value of SYMLINK_MAX returned by pathconf()
. However, the value returned by pathconf()
is out-of-date by the time readlink()
is called, and so the off-by-one buffer overflow risk is still present because in between the two calls the location of /usr/bin/perl
could change to a file system with a larger SYMLINK_MAX value. Also, if SYMLINK_MAX is indeterminate (that is, if pathconf()
returned -1 without setting errno
), the code uses an arbitrary large buffer size (10000) that it hopes will be sufficient, but there is a small chance that readlink()
could return exactly this size.
An additional issue is that readlink()
can return -1
if it fails, causing an off-by-one underflow.
...
Code Block | ||
---|---|---|
| ||
enum { BUFFERSIZE = 2561024 }; char buf[BUFFERSIZE]; ssize_t len; if ((len = readlink("/usr/bin/perl", buf, sizeof(buf)-1)) != -1) buf[len] = '\0'; else { /* handle error condition */ } |
...