diff options
author | Daiki Ueno <ueno@gnu.org> | 2020-05-26 10:22:37 +0200 |
---|---|---|
committer | Daiki Ueno <ueno@gnu.org> | 2020-05-27 14:14:37 +0200 |
commit | a2080f6506701d8d9ca5111d628607a6a8013f61 (patch) | |
tree | 21f5bc6031441e9c34718eeadbe5f6160a8a56e0 /lib/read-file.c | |
parent | e4a38aadac2e90c6dfb317d0845746c200cf6697 (diff) | |
download | gnulib-a2080f6506701d8d9ca5111d628607a6a8013f61.tar.gz |
read-file: add RF_SENSITIVE flag
* lib/read-file.h (RF_SENSITIVE): New define.
* lib/read-file.c (fread_file, read_file): Take into account of
RF_SENSITIVE flag.
* modules/read-file (Depends-on): Add explicit_bzero.
This adds an alternative behavior of those functions to explicitly
clear the internal memory block when it becomes unused. This is
useful for reading sensitive information from a file.
Diffstat (limited to 'lib/read-file.c')
-rw-r--r-- | lib/read-file.c | 57 |
1 files changed, 50 insertions, 7 deletions
diff --git a/lib/read-file.c b/lib/read-file.c index 904f1c9018..36780cc157 100644 --- a/lib/read-file.c +++ b/lib/read-file.c @@ -31,6 +31,9 @@ /* Get malloc, realloc, free. */ #include <stdlib.h> +/* Get explicit_bzero, memcpy. */ +#include <string.h> + /* Get errno. */ #include <errno.h> @@ -38,9 +41,12 @@ and set *LENGTH to the length of the string. The string is zero-terminated, but the terminating zero byte is not counted in *LENGTH. On errors, *LENGTH is undefined, errno preserves the - values set by system functions (if any), and NULL is returned. */ + values set by system functions (if any), and NULL is returned. + + If the RF_SENSITIVE flag is set in FLAGS, the memory buffer + internally allocated will be cleared upon failure. */ char * -fread_file (FILE *stream, int flags _GL_UNUSED, size_t *length) +fread_file (FILE *stream, int flags, size_t *length) { char *buf = NULL; size_t alloc = BUFSIZ; @@ -94,9 +100,25 @@ fread_file (FILE *stream, int flags _GL_UNUSED, size_t *length) /* Shrink the allocated memory if possible. */ if (size < alloc - 1) { - char *smaller_buf = realloc (buf, size + 1); - if (smaller_buf != NULL) - buf = smaller_buf; + if (flags & RF_SENSITIVE) + { + char *smaller_buf = malloc (size + 1); + if (smaller_buf == NULL) + explicit_bzero (buf + size, alloc - size); + else + { + memcpy (smaller_buf, buf, size); + explicit_bzero (buf, alloc); + free (buf); + buf = smaller_buf; + } + } + else + { + char *smaller_buf = realloc (buf, size + 1); + if (smaller_buf != NULL) + buf = smaller_buf; + } } buf[size] = '\0'; @@ -106,6 +128,7 @@ fread_file (FILE *stream, int flags _GL_UNUSED, size_t *length) { char *new_buf; + size_t save_alloc = alloc; if (alloc == PTRDIFF_MAX) { @@ -118,7 +141,21 @@ fread_file (FILE *stream, int flags _GL_UNUSED, size_t *length) else alloc = PTRDIFF_MAX; - if (!(new_buf = realloc (buf, alloc))) + if (flags & RF_SENSITIVE) + { + new_buf = malloc (alloc); + if (!new_buf) + { + /* BUF should be cleared below after the loop. */ + save_errno = errno; + break; + } + memcpy (new_buf, buf, save_alloc); + explicit_bzero (buf, save_alloc); + free (buf); + buf = new_buf; + } + else if (!(new_buf = realloc (buf, alloc))) { save_errno = errno; break; @@ -128,6 +165,9 @@ fread_file (FILE *stream, int flags _GL_UNUSED, size_t *length) } } + if (flags & RF_SENSITIVE) + explicit_bzero (buf, alloc); + free (buf); errno = save_errno; return NULL; @@ -142,7 +182,8 @@ fread_file (FILE *stream, int flags _GL_UNUSED, size_t *length) any), and NULL is returned. If the RF_BINARY flag is set in FLAGS, the file is opened in binary - mode. */ + mode. If the RF_SENSITIVE flag is set in FLAGS, the memory buffer + internally allocated will be cleared upon failure. */ char * read_file (const char *filename, int flags, size_t *length) { @@ -163,6 +204,8 @@ read_file (const char *filename, int flags, size_t *length) if (out) { save_errno = errno; + if (flags & RF_SENSITIVE) + explicit_bzero (out, *length); free (out); } errno = save_errno; |