Skip to content

Commit

Permalink
Enable write protection on a per-module list basis
Browse files Browse the repository at this point in the history
  • Loading branch information
arr2036 committed May 14, 2024
1 parent cccb2c4 commit db7b3ff
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 19 deletions.
4 changes: 3 additions & 1 deletion src/lib/io/master.c
Original file line number Diff line number Diff line change
Expand Up @@ -2702,8 +2702,10 @@ static int mod_instantiate(module_inst_ctx_t const *mctx)
* Create a list of client modules.
*
* FIXME - Probably only want to do this for connected sockets?
*
* FIXME - We probably want write protect enabled?
*/
inst->clients = module_list_alloc(inst, &module_list_type_thread_local, "clients");
inst->clients = module_list_alloc(inst, &module_list_type_thread_local, "clients", false);
module_list_mask_set(inst->clients, MODULE_INSTANCE_BOOTSTRAPPED);

return 0;
Expand Down
24 changes: 12 additions & 12 deletions src/lib/server/module.c
Original file line number Diff line number Diff line change
Expand Up @@ -622,16 +622,14 @@ void module_list_debug(module_list_t const *ml)
static inline CC_HINT(always_inline)
int module_data_protect(module_instance_t *mi, module_data_pool_t *pool)
{
if (pool->start == NULL) return 0; /* noop */
if ((pool->start == NULL) || !mi->ml->write_protect) return 0; /* noop */

DEBUG3("Protecting data %s %p-%p", mi->name, pool->start, (uint8_t *)pool->start + pool->len);

#if 0
if (unlikely(mprotect(pool->start, pool->len, PROT_READ) < 0)) {
fr_strerror_printf("Protecting \"%s\" module data failed: %s", mi->name, fr_syserror(errno));
return -1;
}
#endif

return 0;
}
Expand All @@ -646,16 +644,14 @@ int module_data_protect(module_instance_t *mi, module_data_pool_t *pool)
static inline CC_HINT(always_inline)
int module_data_unprotect(module_instance_t const *mi, module_data_pool_t const *pool)
{
if (pool->start == NULL) return 0; /* noop */
if ((pool->start == NULL) || !mi->ml->write_protect) return 0; /* noop */

DEBUG3("Unprotecting data %s %p-%p", mi->name, pool->start, (uint8_t *)pool->start + pool->len);

#if 0
if (unlikely(mprotect(pool->start, pool->len, PROT_READ | PROT_WRITE) < 0)) {
fr_strerror_printf("Unprotecting \"%s\" data failed: %s", mi->name, fr_syserror(errno));
return -1;
}
#endif

return 0;
}
Expand Down Expand Up @@ -1747,14 +1743,17 @@ void module_list_mask_set(module_list_t *ml, module_instance_state_t mask)
* If the list is freed all module instance data will be freed.
* If no more instances of the module exist the module be unloaded.
*
* @param[in] ctx To allocate the list in.
* @param[in] type of the list. Controls whether this is a global
* module list, or a per-thread list containing
* variants of an existing module.
* @param[in] name of the list. Used for debugging.
* @param[in] ctx To allocate the list in.
* @param[in] type of the list. Controls whether this is a global
* module list, or a per-thread list containing
* variants of an existing module.
* @param[in] name of the list. Used for debugging.
* @param[in] write_protect Whether to write protect the module data
* after instantiation and bootstrapping.
* @return A new module list.
*/
module_list_t *module_list_alloc(TALLOC_CTX *ctx, module_list_type_t const *type, char const *name)
module_list_t *module_list_alloc(TALLOC_CTX *ctx, module_list_type_t const *type,
char const *name, bool write_protect)
{
module_list_t *ml;

Expand All @@ -1778,6 +1777,7 @@ module_list_t *module_list_alloc(TALLOC_CTX *ctx, module_list_type_t const *type
talloc_free(ml);
return NULL;
}
ml->write_protect = write_protect;

return ml;
}
Expand Down
17 changes: 14 additions & 3 deletions src/lib/server/module.h
Original file line number Diff line number Diff line change
Expand Up @@ -331,8 +331,13 @@ typedef module_thread_instance_t *(*module_list_thread_data_get_t)(module_instan

/** A list of modules
*
* This allows modules to be instantiated and freed in phases,
* i.e. proto modules before rlm modules.
* This used to be a global structure, but was move to a struct.
*
* Module lists allow collections of modules to be created. The module lists themselves can be configured
* to be thread-local or global, with optional runtime write protection.
*
* Thread-local module lists are used for dynamic modules, i.e. those created at runtime, where as the
* global module lists are used for backend modules, listeners, and process state machines.
*/
struct module_list_s
{
Expand All @@ -344,6 +349,11 @@ struct module_list_s
fr_rb_tree_t *data_tree; //!< Modules indexed by data.
fr_heap_t *inst_heap; //!< Heap of module instances.

bool write_protect; //!< If true, pages containing module boot or
///< instance data will be write protected after
///< bootstrapping and instantiation is complete,
///< to prevent accidental modification.

/** @name Callbacks to manage thread-specific data
*
* In "child" lists, which are only operating in a single thread, we don't need
Expand Down Expand Up @@ -491,7 +501,8 @@ bool module_instance_skip_thread_instantiate(module_instance_t *mi);
void module_list_mask_set(module_list_t *ml, module_instance_state_t mask);
/** @} */

module_list_t *module_list_alloc(TALLOC_CTX *ctx, module_list_type_t const *type, char const *name)
module_list_t *module_list_alloc(TALLOC_CTX *ctx, module_list_type_t const *type,
char const *name, bool write_protect)
CC_HINT(nonnull(2,3)) CC_HINT(warn_unused_result);

void modules_init(char const *lib_dir);
Expand Down
2 changes: 1 addition & 1 deletion src/lib/server/module_rlm.c
Original file line number Diff line number Diff line change
Expand Up @@ -1170,7 +1170,7 @@ static int _modules_rlm_free_atexit(UNUSED void *uctx)
*/
int modules_rlm_init(void)
{
MEM(rlm_modules = module_list_alloc(NULL, &module_list_type_global, "rlm"));
MEM(rlm_modules = module_list_alloc(NULL, &module_list_type_global, "rlm", true));
MEM(module_rlm_virtual_name_tree = fr_rb_inline_alloc(NULL, module_rlm_virtual_t, name_node,
module_rlm_virtual_name_cmp, NULL));
fr_atexit_global(_modules_rlm_free_atexit, NULL);
Expand Down
10 changes: 8 additions & 2 deletions src/lib/server/virtual_servers.c
Original file line number Diff line number Diff line change
Expand Up @@ -1626,8 +1626,14 @@ int virtual_servers_init(void)
return -1;
}

MEM(process_modules = module_list_alloc(NULL, &module_list_type_global, "process"));
MEM(proto_modules = module_list_alloc(NULL, &module_list_type_global, "protocol"));
MEM(process_modules = module_list_alloc(NULL, &module_list_type_global, "process", true));

/*
* FIXME - We should be able to turn on write protection,
* but there are too many proto modules that hang things
* off of their instance data.
*/
MEM(proto_modules = module_list_alloc(NULL, &module_list_type_global, "protocol", false));
MEM(listen_addr_root = fr_rb_inline_alloc(NULL, fr_listen_t, virtual_server_node, listen_addr_cmp, NULL));
MEM(server_section_name_tree = fr_rb_alloc(NULL, server_section_name_cmp, NULL));

Expand Down

0 comments on commit db7b3ff

Please sign in to comment.