| From c7f4151fb053b0d0691d8f10d7e3690265d28889 Mon Sep 17 00:00:00 2001 |
| From: Lukasz Nowak <lnowak@tycoint.com> |
| Date: Wed, 26 Oct 2016 18:13:02 +0100 |
| Subject: [PATCH] stats: Fix bad file descriptor initialisation |
| |
| Stats file code initialises its file descriptor field to 0. But 0 is |
| a valid fd value. -1 should be used instead. This causes problems |
| when an error happens before a stats file is open (e.g. mkdir |
| fails). The clean-up procedure, stats_free() calls close(fd). When fd |
| is 0, this first closes stdin, and then any files/sockets which |
| received fd=0, re-used by the OS. |
| |
| Fixed several instances of bad file descriptor field handling, in case |
| of errors. |
| |
| The bug results with connman freezing if there is no read/write storage |
| directory available, and there are multiple active interfaces |
| (fd=0 gets re-used for sockets in that case). |
| |
| The patch was imported from the Connman git repository |
| (git://git.kernel.org/pub/scm/network/connman) as of commit id |
| c7f4151fb053b0d0691d8f10d7e3690265d28889. |
| |
| Upstream-Status: Accepted |
| Signed-off-by: Lukasz Nowak <lnowak@tycoint.com> |
| --- |
| src/stats.c | 15 +++++++++++++++ |
| src/util.c | 4 ++-- |
| 2 files changed, 17 insertions(+), 2 deletions(-) |
| |
| diff --git a/src/stats.c b/src/stats.c |
| index 26343b1..c3ca738 100644 |
| --- a/src/stats.c |
| +++ b/src/stats.c |
| @@ -378,6 +378,7 @@ static int stats_file_setup(struct stats_file *file) |
| strerror(errno), file->name); |
| |
| TFR(close(file->fd)); |
| + file->fd = -1; |
| g_free(file->name); |
| file->name = NULL; |
| |
| @@ -393,6 +394,7 @@ static int stats_file_setup(struct stats_file *file) |
| err = stats_file_remap(file, size); |
| if (err < 0) { |
| TFR(close(file->fd)); |
| + file->fd = -1; |
| g_free(file->name); |
| file->name = NULL; |
| |
| @@ -649,6 +651,13 @@ static int stats_file_history_update(struct stats_file *data_file) |
| bzero(history_file, sizeof(struct stats_file)); |
| bzero(temp_file, sizeof(struct stats_file)); |
| |
| + /* |
| + * 0 is a valid file descriptor - fd needs to be initialized |
| + * to -1 to handle errors correctly |
| + */ |
| + history_file->fd = -1; |
| + temp_file->fd = -1; |
| + |
| err = stats_open(history_file, data_file->history_name); |
| if (err < 0) |
| return err; |
| @@ -682,6 +691,12 @@ int __connman_stats_service_register(struct connman_service *service) |
| if (!file) |
| return -ENOMEM; |
| |
| + /* |
| + * 0 is a valid file descriptor - fd needs to be initialized |
| + * to -1 to handle errors correctly |
| + */ |
| + file->fd = -1; |
| + |
| g_hash_table_insert(stats_hash, service, file); |
| } else { |
| return -EALREADY; |
| diff --git a/src/util.c b/src/util.c |
| index e6532c8..732d451 100644 |
| --- a/src/util.c |
| +++ b/src/util.c |
| @@ -63,7 +63,7 @@ int __connman_util_init(void) |
| { |
| int r = 0; |
| |
| - if (f > 0) |
| + if (f >= 0) |
| return 0; |
| |
| f = open(URANDOM, O_RDONLY); |
| @@ -86,7 +86,7 @@ int __connman_util_init(void) |
| |
| void __connman_util_cleanup(void) |
| { |
| - if (f > 0) |
| + if (f >= 0) |
| close(f); |
| |
| f = -1; |
| -- |
| 2.7.4 |
| |