diff options
author | Daiki Ueno <ueno@gnu.org> | 2021-11-14 16:39:29 +0100 |
---|---|---|
committer | Daiki Ueno <ueno@gnu.org> | 2021-11-17 07:38:35 +0100 |
commit | bcffed047f7a228cf99028eb2b8249e5a02eb2e6 (patch) | |
tree | 555eba78c10de55b63ee5d41a338309828faa9ff | |
parent | 14dd5bbe4a6f8482e69a2c0ffba4fa258c9b236e (diff) | |
download | gnutls-bcffed047f7a228cf99028eb2b8249e5a02eb2e6.tar.gz |
locks: rework rwlock primitives
Remove GNUTLS_STATIC_RWLOCK_*LOCK macros and respect return values of
rwlock primitives.
Signed-off-by: Daiki Ueno <ueno@gnu.org>
-rw-r--r-- | lib/locks.c | 27 | ||||
-rw-r--r-- | lib/locks.h | 14 | ||||
-rw-r--r-- | lib/priority.c | 180 |
3 files changed, 142 insertions, 79 deletions
diff --git a/lib/locks.c b/lib/locks.c index 67f4e1b329..3c05e4d988 100644 --- a/lib/locks.c +++ b/lib/locks.c @@ -90,3 +90,30 @@ gnutls_static_mutex_unlock(gnutls_static_mutex_t lock) } return 0; } + +int +gnutls_rwlock_rdlock(gnutls_rwlock_t rwlock) +{ + if (unlikely(glthread_rwlock_rdlock(rwlock))) { + return gnutls_assert_val(GNUTLS_E_LOCKING_ERROR); + } + return 0; +} + +int +gnutls_rwlock_wrlock(gnutls_rwlock_t rwlock) +{ + if (unlikely(glthread_rwlock_wrlock(rwlock))) { + return gnutls_assert_val(GNUTLS_E_LOCKING_ERROR); + } + return 0; +} + +int +gnutls_rwlock_unlock(gnutls_rwlock_t rwlock) +{ + if (unlikely(glthread_rwlock_unlock(rwlock))) { + return gnutls_assert_val(GNUTLS_E_LOCKING_ERROR); + } + return 0; +} diff --git a/lib/locks.h b/lib/locks.h index 99bf083fd1..b48d2e702b 100644 --- a/lib/locks.h +++ b/lib/locks.h @@ -43,9 +43,15 @@ typedef gl_lock_t *gnutls_static_mutex_t; int gnutls_static_mutex_lock(gnutls_static_mutex_t lock); int gnutls_static_mutex_unlock(gnutls_static_mutex_t lock); -#define GNUTLS_STATIC_RWLOCK(rwlock) gl_rwlock_define_initialized(static, rwlock) -#define GNUTLS_STATIC_RWLOCK_RDLOCK gl_rwlock_rdlock -#define GNUTLS_STATIC_RWLOCK_WRLOCK gl_rwlock_wrlock -#define GNUTLS_STATIC_RWLOCK_UNLOCK gl_rwlock_unlock +/* Unlike static mutexes, static rwlocks can be locked/unlocked with + * the functions defined below, because there is no way to replace + * those functions. + */ +#define GNUTLS_RWLOCK(rwlock) gl_rwlock_define_initialized(static, rwlock) +typedef gl_rwlock_t *gnutls_rwlock_t; + +int gnutls_rwlock_rdlock(gnutls_rwlock_t rwlock); +int gnutls_rwlock_wrlock(gnutls_rwlock_t rwlock); +int gnutls_rwlock_unlock(gnutls_rwlock_t rwlock); #endif /* GNUTLS_LIB_LOCKS_H */ diff --git a/lib/priority.c b/lib/priority.c index e45c6aa11d..2851d51474 100644 --- a/lib/priority.c +++ b/lib/priority.c @@ -1012,7 +1012,7 @@ struct cfg { }; /* Lock for reading and writing system_wide_config */ -GNUTLS_STATIC_RWLOCK(system_wide_config_rwlock); +GNUTLS_RWLOCK(system_wide_config_rwlock); static struct cfg system_wide_config; static unsigned fail_on_invalid_config = 0; @@ -1308,13 +1308,17 @@ static int cfg_ini_handler(void *_ctx, const char *section, const char *name, co return 1; } -static void _gnutls_update_system_priorities(void) +static int _gnutls_update_system_priorities(void) { - int ret = 0; + int ret, err = 0; struct stat sb; FILE *fp; - GNUTLS_STATIC_RWLOCK_RDLOCK(system_wide_config_rwlock); + ret = gnutls_rwlock_rdlock(&system_wide_config_rwlock); + if (ret < 0) { + return gnutls_assert_val(ret); + } + if (stat(system_priority_file, &sb) < 0) { _gnutls_debug_log("cfg: unable to access: %s: %d\n", system_priority_file, errno); @@ -1328,9 +1332,12 @@ static void _gnutls_update_system_priorities(void) goto out; } - GNUTLS_STATIC_RWLOCK_UNLOCK(system_wide_config_rwlock); + (void)gnutls_rwlock_unlock(&system_wide_config_rwlock); - GNUTLS_STATIC_RWLOCK_WRLOCK(system_wide_config_rwlock); + ret = gnutls_rwlock_wrlock(&system_wide_config_rwlock); + if (ret < 0) { + return gnutls_assert_val(ret); + } /* Another thread has successfully updated the system wide config (with * the same modification time as checked above), while upgrading to @@ -1350,11 +1357,11 @@ static void _gnutls_update_system_priorities(void) system_priority_file, errno); goto out; } - ret = ini_parse_file(fp, cfg_ini_handler, NULL); + err = ini_parse_file(fp, cfg_ini_handler, NULL); fclose(fp); - if (ret != 0) { + if (err) { _gnutls_debug_log("cfg: unable to parse: %s: %d\n", - system_priority_file, ret); + system_priority_file, err); goto out; } @@ -1366,16 +1373,19 @@ static void _gnutls_update_system_priorities(void) system_priority_last_mod = sb.st_mtime; out: - GNUTLS_STATIC_RWLOCK_UNLOCK(system_wide_config_rwlock); + (void)gnutls_rwlock_unlock(&system_wide_config_rwlock); - if (ret != 0 && fail_on_invalid_config) { + if (err && fail_on_invalid_config) { exit(1); } + + return ret; } void _gnutls_load_system_priorities(void) { const char *p; + int ret; p = secure_getenv("GNUTLS_SYSTEM_PRIORITY_FILE"); if (p != NULL) @@ -1385,7 +1395,11 @@ void _gnutls_load_system_priorities(void) if (p != NULL && p[0] == '1' && p[1] == 0) fail_on_invalid_config = 1; - _gnutls_update_system_priorities(); + ret = _gnutls_update_system_priorities(); + if (ret < 0) { + _gnutls_debug_log("failed to update system priorities: %s\n", + gnutls_strerror(ret)); + } } void _gnutls_unload_system_priorities(void) @@ -1423,88 +1437,101 @@ char *_gnutls_resolve_priorities(const char* priorities) { const char *p = priorities; char *additional = NULL; - char *ret = NULL; + char *resolved = NULL; const char *ss, *ss_next; unsigned ss_len, ss_next_len; size_t n, n2 = 0; + int ret; - while (c_isspace(*p)) + while (c_isspace(*p)) { p++; + } - if (*p == '@') { - ss = p+1; - additional = strchr(ss, ':'); - if (additional != NULL) { - additional++; - } + /* Cannot reduce further. */ + if (*p != '@') { + return gnutls_strdup(p); + } - /* Always try to refresh the cached data, to - * allow it to be updated without restarting - * all applications - */ - _gnutls_update_system_priorities(); - - do { - ss_next = strchr(ss, ','); - if (ss_next != NULL) { - if (additional && ss_next > additional) - ss_next = NULL; - else - ss_next++; - } + ss = p+1; + additional = strchr(ss, ':'); + if (additional) { + additional++; + } + + /* Always try to refresh the cached data, to allow it to be + * updated without restarting all applications. + */ + ret = _gnutls_update_system_priorities(); + if (ret < 0) { + _gnutls_debug_log("failed to update system priorities: %s\n", + gnutls_strerror(ret)); + } - if (ss_next) { - ss_len = ss_next - ss - 1; - ss_next_len = additional - ss_next - 1; - } else if (additional) { - ss_len = additional - ss - 1; - ss_next_len = 0; + do { + ss_next = strchr(ss, ','); + if (ss_next) { + if (additional && ss_next > additional) { + ss_next = NULL; } else { - ss_len = strlen(ss); - ss_next_len = 0; + ss_next++; } + } + + if (ss_next) { + ss_len = ss_next - ss - 1; + ss_next_len = additional - ss_next - 1; + } else if (additional) { + ss_len = additional - ss - 1; + ss_next_len = 0; + } else { + ss_len = strlen(ss); + ss_next_len = 0; + } - GNUTLS_STATIC_RWLOCK_RDLOCK(system_wide_config_rwlock); - p = _name_val_array_value(system_wide_config.priority_strings, ss, ss_len); + ret = gnutls_rwlock_rdlock(&system_wide_config_rwlock); + if (ret < 0) { + _gnutls_debug_log("cannot read system priority strings: %s\n", + gnutls_strerror(ret)); + break; + } - _gnutls_debug_log("resolved '%.*s' to '%s', next '%.*s'\n", - ss_len, ss, S(p), ss_next_len, S(ss_next)); + p = _name_val_array_value(system_wide_config.priority_strings, + ss, ss_len); - if (p) { - n = strlen(p); - if (additional) { - n2 = strlen(additional); - } + _gnutls_debug_log("resolved '%.*s' to '%s', next '%.*s'\n", + ss_len, ss, S(p), ss_next_len, S(ss_next)); - ret = gnutls_malloc(n+n2+1+1); - if (ret) { - memcpy(ret, p, n); - if (additional != NULL) { - ret[n] = ':'; - memcpy(&ret[n+1], additional, n2); - ret[n+n2+1] = 0; - } else { - ret[n] = 0; - } + if (p) { + n = strlen(p); + if (additional) { + n2 = strlen(additional); + } + + resolved = gnutls_malloc(n+n2+1+1); + if (resolved) { + memcpy(resolved, p, n); + if (additional) { + resolved[n] = ':'; + memcpy(&resolved[n+1], additional, n2); + resolved[n+n2+1] = 0; + } else { + resolved[n] = 0; } } - GNUTLS_STATIC_RWLOCK_UNLOCK(system_wide_config_rwlock); + } - ss = ss_next; - } while (ss && ret == NULL); + (void)gnutls_rwlock_unlock(&system_wide_config_rwlock); - if (ret == NULL) { - _gnutls_debug_log("unable to resolve %s\n", priorities); - } - } else { - return gnutls_strdup(p); - } + ss = ss_next; + } while (ss && !resolved); - if (ret != NULL) { - _gnutls_debug_log("selected priority string: %s\n", ret); + if (resolved) { + _gnutls_debug_log("selected priority string: %s\n", resolved); + } else { + _gnutls_debug_log("unable to resolve %s\n", priorities); } - return ret; + return resolved; } static void add_ec(gnutls_priority_t priority_cache) @@ -1572,7 +1599,10 @@ static int set_ciphersuite_list(gnutls_priority_t priority_cache) /* The following requires a lock so there are no inconsistencies in the * members of system_wide_config loaded from the config file. */ - GNUTLS_STATIC_RWLOCK_RDLOCK(system_wide_config_rwlock); + ret = gnutls_rwlock_rdlock(&system_wide_config_rwlock); + if (ret < 0) { + return gnutls_assert_val(ret); + } /* disable key exchanges which are globally disabled */ z = 0; @@ -1853,7 +1883,7 @@ static int set_ciphersuite_list(gnutls_priority_t priority_cache) } out: - GNUTLS_STATIC_RWLOCK_UNLOCK(system_wide_config_rwlock); + gnutls_rwlock_unlock(&system_wide_config_rwlock); return ret; } |