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.
This commit is contained in:
Todd C. Miller
2014-05-12 11:45:17 -06:00
parent 2e3fbaa2c5
commit ffb07443c3
3 changed files with 37 additions and 0 deletions

View File

@@ -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)
{

View File

@@ -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);

View File

@@ -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);