From b566cb9e84b095289a1c662e953218c9a7d1f77d Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Tue, 14 Jul 2015 10:18:52 -0400 Subject: [PATCH] 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 80b0d88952..113ac89df7 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, * data_out_len-byte buffer in data_out. Check that the * typestring matches typestring; store the tag into a newly allocated * string in tag_out. 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 449015054f..a140057dea 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 -- 2.11.4.GIT