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) { if (len == 0) {
struct stat stat; struct stat stat;
if (lstat(path, &stat) == -1) if (lstat(path, &stat) == -1)
return WHYF_perror("lstat(%s)", path); return WHYF_perror("lstat(%s)", alloca_str_toprint(path));
return stat.st_size; return stat.st_size + 1; // allow for terminating nul
} }
ssize_t nr = readlink(path, buf, len); ssize_t nr = readlink(path, buf, len);
if (nr == -1) 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) 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'; buf[nr] = '\0';
return nr; 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 * 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, * an ERROR and returns -1. Otherwise, returns the number of bytes read,
* including the terminating nul, ie, returns what readlink(2) returns plus * 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 * one. If the 'len' argument is given as zero, then ignores 'buf' and returns
* bytes that would be read, by calling lstat(2) instead of readlink(2), plus * the number of bytes that would be read, by calling lstat(2) instead of
* one for the terminating nul. Beware of the following race condition: a * readlink(2), plus one for the terminating nul. Beware of the following race
* symbolic link may be altered between calling the lstat(2) and readlink(2), * condition: a symbolic link may be altered between calling the lstat(2) and
* so the following apparently overflow-proof code may still fail from a buffer * readlink(2), so the following apparently overflow-proof code may still fail
* overflow in the second call to read_symlink(): * from a buffer overflow in the second call to read_symlink():
* *
* char *readlink_malloc(const char *path) { * char *readlink_malloc(const char *path) {
* ssize_t len = read_symlink(path, NULL, 0); * ssize_t len = read_symlink(path, NULL, 0);