[tor-commits] [tor/master] Add a CFLG_IMMUTABLE flag to mark a field as unchangeable.

teor at torproject.org teor at torproject.org
Tue Nov 5 04:28:52 UTC 2019


commit 2a2c7049b8b7e6c95f495df2cd9788a47b6e835c
Author: Nick Mathewson <nickm at torproject.org>
Date:   Wed Oct 30 15:00:53 2019 -0400

    Add a CFLG_IMMUTABLE flag to mark a field as unchangeable.
---
 src/lib/conf/conftypes.h  |  5 +++++
 src/lib/confmgt/confmgt.c | 45 +++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 48 insertions(+), 2 deletions(-)

diff --git a/src/lib/conf/conftypes.h b/src/lib/conf/conftypes.h
index 69a5f79bf..d4e2ea218 100644
--- a/src/lib/conf/conftypes.h
+++ b/src/lib/conf/conftypes.h
@@ -178,6 +178,11 @@ typedef struct struct_magic_decl_t {
  * however, setting them appends to their old value.
  */
 #define CFLG_NOREPLACE    (1u<<5)
+/**
+ * Flag to indicate that an option or type cannot be changed while Tor is
+ * running.
+ **/
+#define CFLG_IMMUTABLE (1u<<6)
 
 /**
  * A group of flags that should be set on all obsolete options and types.
diff --git a/src/lib/confmgt/confmgt.c b/src/lib/confmgt/confmgt.c
index 1218a63ae..137bb2137 100644
--- a/src/lib/confmgt/confmgt.c
+++ b/src/lib/confmgt/confmgt.c
@@ -1154,6 +1154,41 @@ config_init(const config_mgr_t *mgr, void *options)
 }
 
 /**
+ * Helper for config_validate_single: see whether any immutable option
+ * has changed between old_options and new_options.
+ *
+ * On success return 0; on failure set *msg_out to a newly allocated
+ * string explaining what is wrong, and return -1.
+ */
+static int
+config_check_immutable_flags(const config_format_t *fmt,
+                             const void *old_options,
+                             const void *new_options,
+                             char **msg_out)
+{
+  tor_assert(fmt);
+  tor_assert(new_options);
+  if (BUG(! old_options))
+    return 0;
+
+  unsigned i;
+  for (i = 0; fmt->vars[i].member.name; ++i) {
+    const config_var_t *v = &fmt->vars[i];
+    if (! config_var_has_flag(v, CFLG_IMMUTABLE))
+      continue;
+
+    if (! struct_var_eq(old_options, new_options, &v->member)) {
+      tor_asprintf(msg_out,
+                   "While Tor is running, changing %s is not allowed",
+                   v->member.name);
+      return -1;
+    }
+  }
+
+  return 0;
+}
+
+/**
  * Normalize and validate a single object `options` within a configuration
  * suite, according to its format.  `options` may be modified as appropriate
  * in order to set ancillary data.  If `old_options` is provided, make sure
@@ -1189,10 +1224,16 @@ config_validate_single(const config_format_t *fmt,
     }
   }
 
-  if (fmt->check_transition_fn && old_options) {
-    if (fmt->check_transition_fn(old_options, options, msg_out) < 0) {
+  if (old_options) {
+    if (config_check_immutable_flags(fmt, old_options, options, msg_out) < 0) {
       return VSTAT_TRANSITION_ERR;
     }
+
+    if (fmt->check_transition_fn) {
+      if (fmt->check_transition_fn(old_options, options, msg_out) < 0) {
+        return VSTAT_TRANSITION_ERR;
+      }
+    }
   }
 
   if (fmt->post_normalize_fn) {





More information about the tor-commits mailing list