Add reference counting to debug register/deregister.

Fixes a potential problem when an instance is re-registered.
This commit is contained in:
Todd C. Miller
2019-12-03 20:03:19 -07:00
parent 7c782edf53
commit 3ab29e29bb

View File

@@ -106,6 +106,7 @@ struct sudo_debug_instance {
const char *const *subsystems; const char *const *subsystems;
const unsigned int *subsystem_ids; const unsigned int *subsystem_ids;
unsigned int max_subsystem; unsigned int max_subsystem;
unsigned int refcnt;
struct sudo_debug_output_list outputs; struct sudo_debug_output_list outputs;
}; };
@@ -328,6 +329,7 @@ sudo_debug_register_v1(const char *program, const char *const subsystems[],
instance->subsystems = subsystems; instance->subsystems = subsystems;
instance->subsystem_ids = ids; instance->subsystem_ids = ids;
instance->max_subsystem = max_id; instance->max_subsystem = max_id;
instance->refcnt = 1;
SLIST_INIT(&instance->outputs); SLIST_INIT(&instance->outputs);
sudo_debug_instances[idx] = instance; sudo_debug_instances[idx] = instance;
if (idx != free_idx) if (idx != free_idx)
@@ -340,6 +342,7 @@ sudo_debug_register_v1(const char *program, const char *const subsystems[],
for (i = 0; subsystems[i] != NULL; i++) for (i = 0; subsystems[i] != NULL; i++)
ids[i] = instance->subsystem_ids[i]; ids[i] = instance->subsystem_ids[i];
} }
instance->refcnt++;
} }
TAILQ_FOREACH(debug_file, debug_files, entries) { TAILQ_FOREACH(debug_file, debug_files, entries) {
@@ -364,6 +367,7 @@ sudo_debug_register_v1(const char *program, const char *const subsystems[],
/* /*
* De-register the specified instance from the debug subsystem * De-register the specified instance from the debug subsystem
* and free up any associated data structures. * and free up any associated data structures.
* Returns the number of remaining references for the instance or -1 on error.
*/ */
int int
sudo_debug_deregister_v1(int idx) sudo_debug_deregister_v1(int idx)
@@ -383,7 +387,10 @@ sudo_debug_deregister_v1(int idx)
instance = sudo_debug_instances[idx]; instance = sudo_debug_instances[idx];
if (instance == NULL) if (instance == NULL)
return -1; /* already deregistered */ return -1; /* already deregistered */
if (--instance->refcnt != 0)
return instance->refcnt; /* ref held by other caller */
/* Free up instance data, note that subsystems[] is owned by caller. */ /* Free up instance data, note that subsystems[] is owned by caller. */
sudo_debug_instances[idx] = NULL; sudo_debug_instances[idx] = NULL;