summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaiki Ueno <ueno@gnu.org>2021-11-14 16:39:29 +0100
committerDaiki Ueno <ueno@gnu.org>2021-11-17 07:38:35 +0100
commitbcffed047f7a228cf99028eb2b8249e5a02eb2e6 (patch)
tree555eba78c10de55b63ee5d41a338309828faa9ff
parent14dd5bbe4a6f8482e69a2c0ffba4fa258c9b236e (diff)
downloadgnutls-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.c27
-rw-r--r--lib/locks.h14
-rw-r--r--lib/priority.c180
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;
}