commit 2cfa7e0fc0a8e6563598014d5dd3e3b8fcc45f32
parent 742dbae978d53ffc8ec039dedd0748cbf676d39c
Author: Nick Mathewson <nickm@torproject.org>
Date: Wed, 19 Mar 2025 16:37:06 +0000
Merge branch 'happy-sandbox' into 'main'
Make sandbox work with family id keys.
Closes #41022
See merge request tpo/core/tor!864
Diffstat:
4 files changed, 95 insertions(+), 21 deletions(-)
diff --git a/doc/man/tor.1.txt b/doc/man/tor.1.txt
@@ -2498,6 +2498,9 @@ is non-zero):
But for now, relay families should configure
both this option _and_ MyFamily, so older clients
will still recognize the relays' family membership.
+ +
+ (Note that if the seccomp2 Sandbox feature is enabled,
+ it is not possible to change the key filenames while Tor is running.)
[[Nickname]] **Nickname** __name__::
Set the server's nickname to \'name'. Nicknames must be between 1 and 19
diff --git a/src/app/main/main.c b/src/app/main/main.c
@@ -957,6 +957,17 @@ sandbox_init_filter(void)
OPEN("/etc/hosts");
OPEN("/proc/meminfo");
+ {
+ smartlist_t *family_id_files =
+ list_family_key_files(options, options->KeyDirectory);
+
+ SMARTLIST_FOREACH(family_id_files, const char *, fn,
+ OPEN(fn));
+
+ SMARTLIST_FOREACH(family_id_files, char *, cp, tor_free(cp));
+ smartlist_free(family_id_files);
+ }
+
if (options->BridgeAuthoritativeDir)
OPEN_DATADIR_SUFFIX("networkstatus-bridges", ".tmp");
diff --git a/src/feature/relay/routerkeys.c b/src/feature/relay/routerkeys.c
@@ -730,6 +730,68 @@ family_key_is_present(const ed25519_public_key_t *id)
*/
#define FAMILY_KEY_FILE_TAG "fmly-id"
+/** Return a list of all the possible family-key files in `keydir`.
+ * Return NULL on error.
+ *
+ * (Unlike list_family_key_files, this function does not use a cached
+ * list when the seccomp2 sandbox is enabled.) */
+static smartlist_t *
+list_family_key_files_impl(const char *keydir)
+{
+ smartlist_t *files = tor_listdir(keydir);
+ smartlist_t *result = smartlist_new();
+
+ if (!files) {
+ log_warn(LD_OR, "Unable to list contents of directory %s", keydir);
+ goto err;
+ }
+
+ SMARTLIST_FOREACH_BEGIN(files, const char *, fn) {
+ if (!is_family_key_fname(fn))
+ continue;
+
+ smartlist_add_asprintf(result, "%s%s%s", keydir, PATH_SEPARATOR, fn);
+ } SMARTLIST_FOREACH_END(fn);
+
+ goto done;
+ err:
+ SMARTLIST_FOREACH(result, char *, cp, tor_free(cp));
+ smartlist_free(result); // sets result to NULL.
+ done:
+ SMARTLIST_FOREACH(files, char *, cp, tor_free(cp));
+ smartlist_free(files);
+
+ return result;
+}
+
+/**
+ * A list of files returned by list_family_key_files_impl.
+ * Used when the seccomp2 sandbox is enabled.
+ */
+static smartlist_t *cached_family_key_file_list = NULL;
+
+/** Return a list of all the possible family-key files in `keydir`.
+ * Return NULL on error.
+ */
+smartlist_t *
+list_family_key_files(const or_options_t *options,
+ const char *keydir)
+{
+ if (options->Sandbox) {
+ if (!cached_family_key_file_list)
+ cached_family_key_file_list = list_family_key_files_impl(keydir);
+ if (!cached_family_key_file_list)
+ return NULL;
+
+ smartlist_t *result = smartlist_new();
+ SMARTLIST_FOREACH(cached_family_key_file_list, char *, fn,
+ smartlist_add_strdup(result, fn));
+ return result;
+ }
+
+ return list_family_key_files_impl(keydir);
+}
+
/**
* Look for all the family keys in `keydir`, load them into
* family_id_keys.
@@ -741,38 +803,31 @@ load_family_id_keys_impl(const or_options_t *options,
if (BUG(!options) || BUG(!keydir))
return -1;
- smartlist_t *files = tor_listdir(keydir);
+ smartlist_t *key_files = list_family_key_files(options, keydir);
smartlist_t *new_keys = NULL;
ed25519_keypair_t *kp_tmp = NULL;
- char *fn_tmp = NULL;
char *tag_tmp = NULL;
int r = -1;
- if (files == NULL) {
- log_warn(LD_OR, "Unable to list contents of directory %s", keydir);
- goto end;
+ if (key_files == NULL) {
+ goto end; // already warned.
}
new_keys = smartlist_new();
- SMARTLIST_FOREACH_BEGIN(files, const char *, fn) {
- if (!is_family_key_fname(fn))
- continue;
-
- tor_asprintf(&fn_tmp, "%s%s%s", keydir, PATH_SEPARATOR, fn);
-
+ SMARTLIST_FOREACH_BEGIN(key_files, const char *, fn) {
kp_tmp = tor_malloc_zero(sizeof(*kp_tmp));
// TODO: If we ever allow cert provisioning here,
// use ed_key_init_from_file() instead.
- if (ed25519_seckey_read_from_file(&kp_tmp->seckey, &tag_tmp, fn_tmp) < 0) {
- log_warn(LD_OR, "%s was not an ed25519 secret key.", fn_tmp);
+ if (ed25519_seckey_read_from_file(&kp_tmp->seckey, &tag_tmp, fn) < 0) {
+ log_warn(LD_OR, "%s was not an ed25519 secret key.", fn);
goto end;
}
if (0 != strcmp(tag_tmp, FAMILY_KEY_FILE_TAG)) {
- log_warn(LD_OR, "%s was not a family ID key.", fn_tmp);
+ log_warn(LD_OR, "%s was not a family ID key.", fn);
goto end;
}
if (ed25519_public_key_generate(&kp_tmp->pubkey, &kp_tmp->seckey) < 0) {
- log_warn(LD_OR, "Unable to generate public key for %s", fn_tmp);
+ log_warn(LD_OR, "Unable to generate public key for %s", fn);
goto end;
}
@@ -782,10 +837,9 @@ load_family_id_keys_impl(const or_options_t *options,
} else {
log_warn(LD_OR, "Found secret family key in %s "
"with unexpected FamilyID %s",
- fn_tmp, ed25519_fmt(&kp_tmp->pubkey));
+ fn, ed25519_fmt(&kp_tmp->pubkey));
}
- tor_free(fn_tmp);
tor_free(tag_tmp);
} SMARTLIST_FOREACH_END(fn);
@@ -793,16 +847,15 @@ load_family_id_keys_impl(const or_options_t *options,
new_keys = NULL; // prevent double-free
r = 0;
end:
- if (files) {
- SMARTLIST_FOREACH(files, char *, cp, tor_free(cp));
- smartlist_free(files);
+ if (key_files) {
+ SMARTLIST_FOREACH(key_files, char *, cp, tor_free(cp));
+ smartlist_free(key_files);
}
if (new_keys) {
SMARTLIST_FOREACH(new_keys, ed25519_keypair_t *, kp,
ed25519_keypair_free(kp));
smartlist_free(new_keys);
}
- tor_free(fn_tmp);
tor_free(tag_tmp);
ed25519_keypair_free(kp_tmp);
return r;
@@ -1030,6 +1083,11 @@ routerkeys_free_all(void)
tor_cert_free(auth_key_cert);
tor_free(rsa_ed_crosscert);
+ if (cached_family_key_file_list) {
+ SMARTLIST_FOREACH(cached_family_key_file_list, char *, cp, tor_free(cp));
+ smartlist_free(cached_family_key_file_list);
+ }
+
master_identity_key = master_signing_key = NULL;
current_auth_key = NULL;
signing_key_cert = link_cert_cert = auth_key_cert = NULL;
diff --git a/src/feature/relay/routerkeys.h b/src/feature/relay/routerkeys.h
@@ -21,6 +21,8 @@ const ed25519_keypair_t *get_current_auth_keypair(void);
const struct tor_cert_st *get_current_link_cert_cert(void);
const struct tor_cert_st *get_current_auth_key_cert(void);
+smartlist_t *list_family_key_files(const or_options_t *options,
+ const char *keydir);
const smartlist_t *get_current_family_id_keys(void);
void get_master_rsa_crosscert(const uint8_t **cert_out,