Skip to content

Commit

Permalink
hs: Rescan the main loop event list if the service map changes
Browse files Browse the repository at this point in the history
Because ADD_ONION/DEL_ONION can modify the global service map (both for v2 and
v3), we need to rescan the event list so we either enable or disable the HS
service main loop event.

Fixees #25939

Signed-off-by: David Goulet <dgoulet@torproject.org>
  • Loading branch information
dgoulet-tor committed Apr 27, 2018
1 parent 3ab017b commit f7633c1
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 3 deletions.
28 changes: 28 additions & 0 deletions src/or/hs_service.c
Expand Up @@ -80,6 +80,7 @@ static smartlist_t *hs_service_staging_list;
* reupload if needed */
static int consider_republishing_hs_descriptors = 0;

/* Static declaration. */
static void set_descriptor_revision_counter(hs_descriptor_t *hs_desc);
static void move_descriptors(hs_service_t *src, hs_service_t *dst);

Expand Down Expand Up @@ -152,6 +153,12 @@ register_service(hs_service_ht *map, hs_service_t *service)
}
/* Taking ownership of the object at this point. */
HT_INSERT(hs_service_ht, map, service);

/* If we just modified the global map, we notify. */
if (map == hs_service_map) {
hs_service_map_has_changed();
}

return 0;
}

Expand All @@ -178,6 +185,11 @@ remove_service(hs_service_ht *map, hs_service_t *service)
"while removing service %s",
escaped(service->config.directory_path));
}

/* If we just modified the global map, we notify. */
if (map == hs_service_map) {
hs_service_map_has_changed();
}
}

/* Set the default values for a service configuration object <b>c</b>. */
Expand Down Expand Up @@ -916,6 +928,11 @@ register_all_services(void)
smartlist_clear(hs_service_staging_list);
service_free_all();
hs_service_map = new_service_map;
/* We've just register services into the new map and now we've replaced the
* global map with it so we have to notify that the change happened. When
* registering a service, the notify is only triggered if the destination
* map is the global map for which in here it was not. */
hs_service_map_has_changed();
}

/* Write the onion address of a given service to the given filename fname_ in
Expand Down Expand Up @@ -2936,6 +2953,17 @@ service_add_fnames_to_list(const hs_service_t *service, smartlist_t *list)
/* Public API */
/* ========== */

/* This is called everytime the service map (v2 or v3) changes that is if an
* element is added or removed. */
void
hs_service_map_has_changed(void)
{
/* If we now have services where previously we had not, we need to enable
* the HS service main loop event. If we changed to having no services, we
* need to disable the event. */
rescan_periodic_events(get_options());
}

/* Upload an encoded descriptor in encoded_desc of the given version. This
* descriptor is for the service identity_pk and blinded_pk used to setup the
* directory connection identifier. It is uploaded to the directory hsdir_rs
Expand Down
1 change: 1 addition & 0 deletions src/or/hs_service.h
Expand Up @@ -260,6 +260,7 @@ void hs_service_lists_fnames_for_sandbox(smartlist_t *file_list,
int hs_service_set_conn_addr_port(const origin_circuit_t *circ,
edge_connection_t *conn);

void hs_service_map_has_changed(void);
void hs_service_dir_info_changed(void);
void hs_service_run_scheduled_events(time_t now);
void hs_service_circuit_has_opened(origin_circuit_t *circ);
Expand Down
11 changes: 11 additions & 0 deletions src/or/rendservice.c
Expand Up @@ -348,6 +348,13 @@ rend_add_service(smartlist_t *service_list, rend_service_t *service)
/* The service passed all the checks */
tor_assert(s_list);
smartlist_add(s_list, service);

/* Notify that our global service list has changed only if this new service
* went into our global list. If not, when we move service from the staging
* list to the new list, a notify is triggered. */
if (s_list == rend_service_list) {
hs_service_map_has_changed();
}
return 0;
}

Expand Down Expand Up @@ -609,6 +616,8 @@ rend_service_prune_list_impl_(void)
circuit_mark_for_close(TO_CIRCUIT(ocirc), END_CIRC_REASON_FINISHED);
}
smartlist_free(surviving_services);
/* Notify that our global service list has changed. */
hs_service_map_has_changed();
}

/* Try to prune our main service list using the temporary one that we just
Expand Down Expand Up @@ -958,6 +967,8 @@ rend_service_del_ephemeral(const char *service_id)
}
} SMARTLIST_FOREACH_END(circ);
smartlist_remove(rend_service_list, s);
/* Notify that we just removed a service from our global list. */
hs_service_map_has_changed();
rend_service_free(s);

log_debug(LD_CONFIG, "Removed ephemeral Onion Service: %s", service_id);
Expand Down
12 changes: 9 additions & 3 deletions src/test/test_periodic_event.c
Expand Up @@ -69,7 +69,7 @@ test_pe_initialize(void *arg)
static void
test_pe_launch(void *arg)
{
hs_service_t service;
hs_service_t service, *to_remove = NULL;
or_options_t *options;

(void) arg;
Expand Down Expand Up @@ -152,15 +152,21 @@ test_pe_launch(void *arg)
options->V3AuthoritativeDir = 1; options->BridgeAuthoritativeDir = 1;
register_dummy_hidden_service(&service);
periodic_events_on_new_options(options);
/* Remove it now so the hs_free_all() doesn't try to free stack memory. */
remove_service(get_hs_service_map(), &service);
/* Note down the reference because we need to remove this service from the
* global list before the hs_free_all() call so it doesn't try to free
* memory on the stack. Furthermore, we can't remove it now else it will
* trigger a rescan of the event disabling the HS service event. */
to_remove = &service;

for (int i = 0; periodic_events[i].name; ++i) {
periodic_event_item_t *item = &periodic_events[i];
tt_int_op(periodic_event_is_enabled(item), OP_EQ, 1);
}

done:
if (to_remove) {
remove_service(get_hs_service_map(), to_remove);
}
hs_free_all();
}

Expand Down

0 comments on commit f7633c1

Please sign in to comment.