From ffb07443c36f9a9cc74e091fff5f747408f00baa Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Mon, 12 May 2014 11:45:17 -0600 Subject: [PATCH] Do not allow the same callback function to be registered more that once in fatal_callback_register(). Add fatal_callback_deregister() to deregister a callback. --- common/fatal.c | 33 +++++++++++++++++++++++++++++++++ include/fatal.h | 1 + plugins/sudoers/policy.c | 3 +++ 3 files changed, 37 insertions(+) diff --git a/common/fatal.c b/common/fatal.c index aae23dab9..48012897a 100644 --- a/common/fatal.c +++ b/common/fatal.c @@ -168,11 +168,21 @@ _warning(int use_errno, const char *fmt, va_list ap) errno = serrno; } +/* + * Register a callback to be run when fatal()/fatalx() is called. + */ int fatal_callback_register(void (*func)(void)) { struct sudo_fatal_callback *cb; + /* Do not register the same callback twice. */ + SLIST_FOREACH(cb, &callbacks, entries) { + if (func == cb->func) + return -1; /* dupe! */ + } + + /* Allocate and insert new callback. */ cb = malloc(sizeof(*cb)); if (cb == NULL) return -1; @@ -182,6 +192,29 @@ fatal_callback_register(void (*func)(void)) return 0; } +/* + * Deregister a fatal()/fatalx() callback. + */ +int +fatal_callback_deregister(void (*func)(void)) +{ + struct sudo_fatal_callback *cb, **prev; + + /* Search for callback and remove if found, dupes are not allowed. */ + SLIST_FOREACH_PREVPTR(cb, prev, &callbacks, entries) { + if (cb->func == func) { + if (cb == SLIST_FIRST(&callbacks)) + SLIST_REMOVE_HEAD(&callbacks, entries); + else + SLIST_REMOVE_AFTER(*prev, entries); + free(cb); + return 0; + } + } + + return -1; +} + void fatal_disable_setjmp(void) { diff --git a/include/fatal.h b/include/fatal.h index 9963b0f78..907a6259e 100644 --- a/include/fatal.h +++ b/include/fatal.h @@ -119,6 +119,7 @@ extern int (*sudo_printf)(int msg_type, const char *fmt, ...); extern sigjmp_buf fatal_jmp; +int fatal_callback_deregister(void (*func)(void)); int fatal_callback_register(void (*func)(void)); char *warning_gettext(const char *msgid) __format_arg(1); void fatal_disable_setjmp(void); diff --git a/plugins/sudoers/policy.c b/plugins/sudoers/policy.c index e9a801d0e..73f7fa50e 100644 --- a/plugins/sudoers/policy.c +++ b/plugins/sudoers/policy.c @@ -576,6 +576,9 @@ sudoers_policy_close(int exit_status, int error_code) if (ISSET(sudo_mode, MODE_RUN|MODE_EDIT)) (void)sudo_auth_end_session(runas_pw); + /* Deregister the callback for fatal()/fatalx(). */ + fatal_callback_deregister(sudoers_cleanup); + /* Free remaining references to password and group entries. */ /* XXX - move cleanup to function in sudoers.c */ sudo_pw_delref(sudo_user.pw);