From 9f81e8a10941168b88b4855a2bc753c6f5919f9d Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Sat, 30 Jan 2021 08:53:55 -0700 Subject: [PATCH] Don't leak memory for duplicate command options. The last option wins but we also now warn about the duplicate. Found locally using libfuzzer/oss-fuzz. --- plugins/sudoers/ldap_util.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/plugins/sudoers/ldap_util.c b/plugins/sudoers/ldap_util.c index fd308674d..4629c818f 100644 --- a/plugins/sudoers/ldap_util.c +++ b/plugins/sudoers/ldap_util.c @@ -525,26 +525,60 @@ sudo_ldap_role_to_priv(const char *cn, void *hosts, void *runasusers, op = sudo_ldap_parse_option(opt, &var, &val); if (strcmp(var, "command_timeout") == 0 && val != NULL) { + if (cmndspec->timeout != UNSPEC) { + sudo_warnx(U_("duplicate sudoOption: %s%s%s"), var, + op == '+' ? "+=" : op == '-' ? "-=" : "=", val); + } cmndspec->timeout = parse_timeout(val); } else if (strcmp(var, "runchroot") == 0 && val != NULL) { + if (cmndspec->runchroot != NULL) { + free(cmndspec->runchroot); + sudo_warnx(U_("duplicate sudoOption: %s%s%s"), var, + op == '+' ? "+=" : op == '-' ? "-=" : "=", val); + } if ((cmndspec->runchroot = strdup(val)) == NULL) break; } else if (strcmp(var, "runcwd") == 0 && val != NULL) { + if (cmndspec->runcwd != NULL) { + free(cmndspec->runcwd); + sudo_warnx(U_("duplicate sudoOption: %s%s%s"), var, + op == '+' ? "+=" : op == '-' ? "-=" : "=", val); + } if ((cmndspec->runcwd = strdup(val)) == NULL) break; #ifdef HAVE_SELINUX } else if (strcmp(var, "role") == 0 && val != NULL) { + if (cmndspec->role != NULL) { + free(cmndspec->role); + sudo_warnx(U_("duplicate sudoOption: %s%s%s"), var, + op == '+' ? "+=" : op == '-' ? "-=" : "=", val); + } if ((cmndspec->role = strdup(val)) == NULL) break; } else if (strcmp(var, "type") == 0 && val != NULL) { + if (cmndspec->type != NULL) { + free(cmndspec->type); + sudo_warnx(U_("duplicate sudoOption: %s%s%s"), var, + op == '+' ? "+=" : op == '-' ? "-=" : "=", val); + } if ((cmndspec->type = strdup(val)) == NULL) break; #endif /* HAVE_SELINUX */ #ifdef HAVE_PRIV_SET } else if (strcmp(var, "privs") == 0 && val != NULL) { + if (cmndspec->privs != NULL) { + free(cmndspec->privs); + sudo_warnx(U_("duplicate sudoOption: %s%s%s"), var, + op == '+' ? "+=" : op == '-' ? "-=" : "=", val); + } if ((cmndspec->privs = strdup(val)) == NULL) break; } else if (strcmp(var, "limitprivs") == 0 && val != NULL) { + if (cmndspec->limitprivs != NULL) { + free(cmndspec->limitprivs); + sudo_warnx(U_("duplicate sudoOption: %s%s%s"), var, + op == '+' ? "+=" : op == '-' ? "-=" : "=", val); + } if ((cmndspec->limitprivs = strdup(val)) == NULL) break; #endif /* HAVE_PRIV_SET */