Fix bug in read_symlink(), improve logging

This commit is contained in:
Andrew Bettison 2014-05-05 18:12:25 +09:30
parent f606daebc6
commit 18c89b4b98
2 changed files with 10 additions and 10 deletions

8
os.c
View File

@ -171,14 +171,14 @@ ssize_t read_symlink(const char *path, char *buf, size_t len)
if (len == 0) {
struct stat stat;
if (lstat(path, &stat) == -1)
return WHYF_perror("lstat(%s)", path);
return stat.st_size;
return WHYF_perror("lstat(%s)", alloca_str_toprint(path));
return stat.st_size + 1; // allow for terminating nul
}
ssize_t nr = readlink(path, buf, len);
if (nr == -1)
return WHYF_perror("readlink(%s,%p,%zu)", path, buf, len);
return WHYF_perror("readlink(%s,%p,%zu)", alloca_str_toprint(path), buf, len);
if ((size_t)nr >= len)
return WHYF("buffer overrun from readlink(%s, len=%zu)", path, len);
return WHYF("buffer overrun from readlink(%s, len=%zu)", alloca_str_toprint(path), len);
buf[nr] = '\0';
return nr;
}

12
os.h
View File

@ -133,12 +133,12 @@ int urandombytes(unsigned char *buf, size_t len);
* content and the terminating nul. If readlink(2) returns an error, then logs
* an ERROR and returns -1. Otherwise, returns the number of bytes read,
* including the terminating nul, ie, returns what readlink(2) returns plus
* one. If the 'len' argument is given as zero, then returns the number of
* bytes that would be read, by calling lstat(2) instead of readlink(2), plus
* one for the terminating nul. Beware of the following race condition: a
* symbolic link may be altered between calling the lstat(2) and readlink(2),
* so the following apparently overflow-proof code may still fail from a buffer
* overflow in the second call to read_symlink():
* one. If the 'len' argument is given as zero, then ignores 'buf' and returns
* the number of bytes that would be read, by calling lstat(2) instead of
* readlink(2), plus one for the terminating nul. Beware of the following race
* condition: a symbolic link may be altered between calling the lstat(2) and
* readlink(2), so the following apparently overflow-proof code may still fail
* from a buffer overflow in the second call to read_symlink():
*
* char *readlink_malloc(const char *path) {
* ssize_t len = read_symlink(path, NULL, 0);