Fix handling of duplicate policy and I/O plugins.

The warning message said the later I/O plugin was ignored but it
actually overwrote the existing one instead.
The first registered plugin of the same name now is used, as was intended.
Specifying more than one policy plugin is no longer a fatal error;
this allows the admin to fix the situation.
This commit is contained in:
Todd C. Miller
2020-01-14 13:53:52 -07:00
parent c592470dbd
commit 9c5c79194d

View File

@@ -171,11 +171,12 @@ sudo_load_plugin(struct plugin_container *policy_plugin,
struct generic_plugin *plugin; struct generic_plugin *plugin;
char path[PATH_MAX]; char path[PATH_MAX];
void *handle = NULL; void *handle = NULL;
bool ret = false;
debug_decl(sudo_load_plugin, SUDO_DEBUG_PLUGIN); debug_decl(sudo_load_plugin, SUDO_DEBUG_PLUGIN);
/* Sanity check plugin and fill in path */ /* Sanity check plugin and fill in path */
if (!sudo_check_plugin(info, path, sizeof(path))) if (!sudo_check_plugin(info, path, sizeof(path)))
goto bad; goto done;
/* Open plugin and map in symbol */ /* Open plugin and map in symbol */
handle = sudo_dso_load(path, SUDO_DSO_LAZY|SUDO_DSO_GLOBAL); handle = sudo_dso_load(path, SUDO_DSO_LAZY|SUDO_DSO_GLOBAL);
@@ -185,21 +186,21 @@ sudo_load_plugin(struct plugin_container *policy_plugin,
_PATH_SUDO_CONF, info->lineno, info->symbol_name); _PATH_SUDO_CONF, info->lineno, info->symbol_name);
sudo_warnx(U_("unable to load %s: %s"), path, sudo_warnx(U_("unable to load %s: %s"), path,
errstr ? errstr : "unknown error"); errstr ? errstr : "unknown error");
goto bad; goto done;
} }
plugin = sudo_dso_findsym(handle, info->symbol_name); plugin = sudo_dso_findsym(handle, info->symbol_name);
if (!plugin) { if (!plugin) {
sudo_warnx(U_("error in %s, line %d while loading plugin \"%s\""), sudo_warnx(U_("error in %s, line %d while loading plugin \"%s\""),
_PATH_SUDO_CONF, info->lineno, info->symbol_name); _PATH_SUDO_CONF, info->lineno, info->symbol_name);
sudo_warnx(U_("unable to find symbol \"%s\" in %s"), info->symbol_name, path); sudo_warnx(U_("unable to find symbol \"%s\" in %s"), info->symbol_name, path);
goto bad; goto done;
} }
if (plugin->type != SUDO_POLICY_PLUGIN && plugin->type != SUDO_IO_PLUGIN) { if (plugin->type != SUDO_POLICY_PLUGIN && plugin->type != SUDO_IO_PLUGIN) {
sudo_warnx(U_("error in %s, line %d while loading plugin \"%s\""), sudo_warnx(U_("error in %s, line %d while loading plugin \"%s\""),
_PATH_SUDO_CONF, info->lineno, info->symbol_name); _PATH_SUDO_CONF, info->lineno, info->symbol_name);
sudo_warnx(U_("unknown policy type %d found in %s"), plugin->type, path); sudo_warnx(U_("unknown policy type %d found in %s"), plugin->type, path);
goto bad; goto done;
} }
if (SUDO_API_VERSION_GET_MAJOR(plugin->version) != SUDO_API_VERSION_MAJOR) { if (SUDO_API_VERSION_GET_MAJOR(plugin->version) != SUDO_API_VERSION_MAJOR) {
sudo_warnx(U_("error in %s, line %d while loading plugin \"%s\""), sudo_warnx(U_("error in %s, line %d while loading plugin \"%s\""),
@@ -207,26 +208,28 @@ sudo_load_plugin(struct plugin_container *policy_plugin,
sudo_warnx(U_("incompatible plugin major version %d (expected %d) found in %s"), sudo_warnx(U_("incompatible plugin major version %d (expected %d) found in %s"),
SUDO_API_VERSION_GET_MAJOR(plugin->version), SUDO_API_VERSION_GET_MAJOR(plugin->version),
SUDO_API_VERSION_MAJOR, path); SUDO_API_VERSION_MAJOR, path);
goto bad; goto done;
} }
if (plugin->type == SUDO_POLICY_PLUGIN) { if (plugin->type == SUDO_POLICY_PLUGIN) {
if (policy_plugin->handle != NULL) { if (policy_plugin->handle != NULL) {
/* Ignore duplicate entries. */ /* Ignore duplicate entries. */
if (strcmp(policy_plugin->name, info->symbol_name) != 0) { if (strcmp(policy_plugin->name, info->symbol_name) == 0) {
sudo_warnx(U_("ignoring duplicate policy plugin \"%s\" in %s, line %d"),
info->symbol_name, _PATH_SUDO_CONF, info->lineno);
} else {
sudo_warnx(U_("ignoring policy plugin \"%s\" in %s, line %d"), sudo_warnx(U_("ignoring policy plugin \"%s\" in %s, line %d"),
info->symbol_name, _PATH_SUDO_CONF, info->lineno); info->symbol_name, _PATH_SUDO_CONF, info->lineno);
sudo_warnx(U_("only a single policy plugin may be specified")); sudo_warnx(U_("only a single policy plugin may be specified"));
goto bad; goto done;
} }
sudo_warnx(U_("ignoring duplicate policy plugin \"%s\" in %s, line %d"), ret = true;
info->symbol_name, _PATH_SUDO_CONF, info->lineno); goto done;
goto bad;
} }
policy_plugin->handle = handle; policy_plugin->handle = handle;
policy_plugin->path = strdup(path); policy_plugin->path = strdup(path);
if (policy_plugin->path == NULL) { if (policy_plugin->path == NULL) {
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory")); sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
goto bad; goto done;
} }
policy_plugin->name = info->symbol_name; policy_plugin->name = info->symbol_name;
policy_plugin->options = info->options; policy_plugin->options = info->options;
@@ -239,15 +242,15 @@ sudo_load_plugin(struct plugin_container *policy_plugin,
if (strcmp(container->name, info->symbol_name) == 0) { if (strcmp(container->name, info->symbol_name) == 0) {
sudo_warnx(U_("ignoring duplicate I/O plugin \"%s\" in %s, line %d"), sudo_warnx(U_("ignoring duplicate I/O plugin \"%s\" in %s, line %d"),
info->symbol_name, _PATH_SUDO_CONF, info->lineno); info->symbol_name, _PATH_SUDO_CONF, info->lineno);
sudo_dso_unload(handle); ret = true;
handle = NULL; goto done;
break;
} }
} }
container = calloc(1, sizeof(*container)); container = calloc(1, sizeof(*container));
if (container == NULL || (container->path = strdup(path)) == NULL) { if (container == NULL || (container->path = strdup(path)) == NULL) {
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory")); sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
goto bad; free(container);
goto done;
} }
container->handle = handle; container->handle = handle;
container->name = info->symbol_name; container->name = info->symbol_name;
@@ -261,13 +264,14 @@ sudo_load_plugin(struct plugin_container *policy_plugin,
/* Zero out info strings that we now own (see above). */ /* Zero out info strings that we now own (see above). */
info->symbol_name = NULL; info->symbol_name = NULL;
info->options = NULL; info->options = NULL;
handle = NULL;
debug_return_bool(true); ret = true;
bad:
free(container); done:
if (handle != NULL) if (handle != NULL)
sudo_dso_unload(handle); sudo_dso_unload(handle);
debug_return_bool(false); debug_return_bool(ret);
} }
static void static void