commit b566cb9e84b095289a1c662e953218c9a7d1f77d Author: Nick Mathewson nickm@torproject.org Date: Tue Jul 14 10:18:52 2015 -0400
Make file-reading and key-reading preserve errno
This is an important part of #16582. --- src/common/crypto_curve25519.c | 21 ++++++++++++++++----- src/common/util.c | 5 +++++ 2 files changed, 21 insertions(+), 5 deletions(-)
diff --git a/src/common/crypto_curve25519.c b/src/common/crypto_curve25519.c index 80b0d88..113ac89 100644 --- a/src/common/crypto_curve25519.c +++ b/src/common/crypto_curve25519.c @@ -201,7 +201,7 @@ crypto_write_tagged_contents_to_file(const char *fname, * <b>data_out_len</b>-byte buffer in <b>data_out</b>. Check that the * typestring matches <b>typestring</b>; store the tag into a newly allocated * string in <b>tag_out</b>. Return -1 on failure, and the number of bytes of - * data on success. */ + * data on success. Preserves the errno from reading the file. */ ssize_t crypto_read_tagged_contents_from_file(const char *fname, const char *typestring, @@ -214,27 +214,36 @@ crypto_read_tagged_contents_from_file(const char *fname, struct stat st; ssize_t r = -1; size_t st_size = 0; + int saved_errno = 0;
*tag_out = NULL; st.st_size = 0; content = read_file_to_str(fname, RFTS_BIN|RFTS_IGNORE_MISSING, &st); - if (! content) + if (! content) { + saved_errno = errno; goto end; - if (st.st_size < 32 || st.st_size > 32 + data_out_len) + } + if (st.st_size < 32 || st.st_size > 32 + data_out_len) { + saved_errno = EINVAL; goto end; + } st_size = (size_t)st.st_size;
memcpy(prefix, content, 32); prefix[32] = 0; /* Check type, extract tag. */ if (strcmpstart(prefix, "== ") || strcmpend(prefix, " ==") || - ! tor_mem_is_zero(prefix+strlen(prefix), 32-strlen(prefix))) + ! tor_mem_is_zero(prefix+strlen(prefix), 32-strlen(prefix))) { + saved_errno = EINVAL; goto end; + }
if (strcmpstart(prefix+3, typestring) || 3+strlen(typestring) >= 32 || - strcmpstart(prefix+3+strlen(typestring), ": ")) + strcmpstart(prefix+3+strlen(typestring), ": ")) { + saved_errno = EINVAL; goto end; + }
*tag_out = tor_strndup(prefix+5+strlen(typestring), strlen(prefix)-8-strlen(typestring)); @@ -246,6 +255,8 @@ crypto_read_tagged_contents_from_file(const char *fname, if (content) memwipe(content, 0, st_size); tor_free(content); + if (saved_errno) + errno = saved_errno; return r; }
diff --git a/src/common/util.c b/src/common/util.c index 4490150..a140057 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -2571,7 +2571,9 @@ read_file_to_str_until_eof(int fd, size_t max_bytes_to_read, size_t *sz_out) string = tor_realloc(string, string_max); r = read(fd, string + pos, string_max - pos - 1); if (r < 0) { + int save_errno = errno; tor_free(string); + errno = save_errno; return NULL; }
@@ -2639,11 +2641,14 @@ read_file_to_str(const char *filename, int flags, struct stat *stat_out) if (S_ISFIFO(statbuf.st_mode)) { size_t sz = 0; string = read_file_to_str_until_eof(fd, FIFO_READ_MAX, &sz); + int save_errno = errno; if (string && stat_out) { statbuf.st_size = sz; memcpy(stat_out, &statbuf, sizeof(struct stat)); } close(fd); + if (!string) + errno = save_errno; return string; } #endif