summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaiki Ueno <ueno@gnu.org>2020-05-26 10:22:37 +0200
committerDaiki Ueno <ueno@gnu.org>2020-05-27 14:14:37 +0200
commita2080f6506701d8d9ca5111d628607a6a8013f61 (patch)
tree21f5bc6031441e9c34718eeadbe5f6160a8a56e0
parente4a38aadac2e90c6dfb317d0845746c200cf6697 (diff)
downloadgnulib-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.
-rw-r--r--ChangeLog11
-rw-r--r--lib/read-file.c57
-rw-r--r--lib/read-file.h3
-rw-r--r--modules/read-file1
-rw-r--r--tests/test-read-file.c2
5 files changed, 67 insertions, 7 deletions
diff --git a/ChangeLog b/ChangeLog
index 291fd0788b..4b51128a21 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,16 @@
2020-05-27 Daiki Ueno <ueno@gnu.org>
+ 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.
+
+2020-05-27 Daiki Ueno <ueno@gnu.org>
+
read-file: add flags to modify reading behavior
* lib/read-file.h (RF_BINARY): New define.
(fread_file, read_file): Take FLAGS argument.
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;
diff --git a/lib/read-file.h b/lib/read-file.h
index 7ff82ca77d..c2454ef689 100644
--- a/lib/read-file.h
+++ b/lib/read-file.h
@@ -27,6 +27,9 @@
/* Indicate that the file is treated as binary. */
#define RF_BINARY 0x1
+/* Indicate that the file content contains sensitive information. */
+#define RF_SENSITIVE 0x2
+
extern char *fread_file (FILE * stream, int flags, size_t * length);
extern char *read_file (const char *filename, int flags, size_t * length);
diff --git a/modules/read-file b/modules/read-file
index a6e7faf0a8..5d2be5bbf4 100644
--- a/modules/read-file
+++ b/modules/read-file
@@ -7,6 +7,7 @@ lib/read-file.c
m4/read-file.m4
Depends-on:
+explicit_bzero
fopen-gnu
fstat
ftello
diff --git a/tests/test-read-file.c b/tests/test-read-file.c
index 84b9049940..b37f875b22 100644
--- a/tests/test-read-file.c
+++ b/tests/test-read-file.c
@@ -117,6 +117,8 @@ main (void)
{
ASSERT (!test_read_file (0));
ASSERT (!test_read_file (RF_BINARY));
+ ASSERT (!test_read_file (RF_SENSITIVE));
+ ASSERT (!test_read_file (RF_BINARY | RF_SENSITIVE));
return 0;
}