]> granicus.if.org Git - sudo/commitdiff
Simple garbage collection (really a to-be-freed list) for the sudoers
authorTodd C. Miller <Todd.Miller@courtesan.com>
Thu, 28 Jan 2016 21:53:48 +0000 (14:53 -0700)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Thu, 28 Jan 2016 21:53:48 +0000 (14:53 -0700)
plugin.  Almost identical to what sudo.c uses.  Currenly only the
environment strings are collected at exit time which is enough to
quiet address sanitizer's leak detector.

MANIFEST
plugins/sudoers/Makefile.in
plugins/sudoers/env.c
plugins/sudoers/gc.c [new file with mode: 0644]
plugins/sudoers/sudoers.h

index a27e2c76a3be2b615e35746e884f55ba8a2afe9c..1e82b5130897c3c37fc063e1cf0997f1dd3039b1 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -259,6 +259,7 @@ plugins/sudoers/defaults.h
 plugins/sudoers/editor.c
 plugins/sudoers/env.c
 plugins/sudoers/find_path.c
+plugins/sudoers/gc.c
 plugins/sudoers/getdate.c
 plugins/sudoers/getdate.y
 plugins/sudoers/getspwuid.c
index 04aba2e1d6d363ed1a300f318db0572db8329583..17cdbc0491ab7315dabc548c6f7737f2557af656 100644 (file)
@@ -151,7 +151,7 @@ LIBPARSESUDOERS_OBJS = alias.lo audit.lo base64.lo defaults.lo hexchar.lo \
                       toke_util.lo
 
 SUDOERS_OBJS = $(AUTH_OBJS) boottime.lo check.lo editor.lo env.lo find_path.lo \
-              goodpath.lo group_plugin.lo interfaces.lo iolog.lo \
+              gc.lo goodpath.lo group_plugin.lo interfaces.lo iolog.lo \
               iolog_path.lo locale.lo logging.lo logwrap.lo parse.lo \
               policy.lo prompt.lo set_perms.lo sudo_nss.lo sudoers.lo \
               timestamp.lo @SUDOERS_OBJS@
@@ -666,6 +666,14 @@ fwtk.lo: $(authdir)/fwtk.c $(devdir)/def_data.h $(incdir)/compat/stdbool.h \
          $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
          $(top_builddir)/config.h $(top_builddir)/pathnames.h
        $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(authdir)/fwtk.c
+gc.lo: $(srcdir)/gc.c $(devdir)/def_data.h $(incdir)/compat/stdbool.h \
+       $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+       $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+       $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+       $(srcdir)/logging.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+       $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+       $(top_builddir)/pathnames.h
+       $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/gc.c
 getdate.o: $(devdir)/getdate.c $(incdir)/sudo_compat.h $(top_builddir)/config.h
        $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(devdir)/getdate.c
 getspwuid.lo: $(srcdir)/getspwuid.c $(devdir)/def_data.h \
index a50ac813230769c98c7c329e4fabcd899c1bdb3e..b0097f2412d8b90a3894a44439ca7bc52d625048 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2005, 2007-2015
+ * Copyright (c) 2000-2005, 2007-2016
  *     Todd C. Miller <Todd.Miller@courtesan.com>
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -412,6 +412,8 @@ sudo_setenv2(const char *var, const char *val, bool dupcheck, bool overwrite)
     }
     if (rval == -1)
        free(estring);
+    else
+       sudoers_gc_add(GC_PTR, estring);
     debug_return_int(rval);
 }
 
@@ -468,6 +470,8 @@ sudo_setenv_nodebug(const char *var, const char *val, int overwrite)
 done:
     if (rval == -1)
        free(estring);
+    else
+       sudoers_gc_add(GC_PTR, estring);
     return rval;
 }
 
@@ -972,6 +976,7 @@ rebuild_env(void)
                free(cp);
                goto bad;
            }
+           sudoers_gc_add(GC_PTR, cp);
        }
     } else {
        /*
@@ -1060,6 +1065,7 @@ rebuild_env(void)
            free(cp);
            goto bad;
        }
+       sudoers_gc_add(GC_PTR, cp);
     } else {
        CHECK_SETENV2("SUDO_COMMAND", user_cmnd, true, true);
     }
@@ -1217,6 +1223,7 @@ read_env_file(const char *path, int overwrite)
        memcpy(cp, var, var_len + 1); /* includes '=' */
        memcpy(cp + var_len + 1, val, val_len + 1); /* includes NUL */
 
+       sudoers_gc_add(GC_PTR, cp);
        if (sudo_putenv(cp, true, overwrite) == -1) {
            /* XXX - no undo on failure */
            rval = false;
diff --git a/plugins/sudoers/gc.c b/plugins/sudoers/gc.c
new file mode 100644 (file)
index 0000000..eeb8279
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2016 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "sudoers.h"
+
+struct sudoers_gc_entry {
+    SLIST_ENTRY(sudoers_gc_entry) entries;
+    enum sudoers_gc_types type;
+    union {
+       char **vec;
+       void *ptr;
+    } u;
+};
+SLIST_HEAD(sudoers_gc_list, sudoers_gc_entry);
+#ifdef NO_LEAKS
+static struct sudoers_gc_list sudoers_gc_list =
+    SLIST_HEAD_INITIALIZER(sudoers_gc_list);
+#endif
+
+bool
+sudoers_gc_add(enum sudoers_gc_types type, void *v)
+{
+#ifdef NO_LEAKS
+    struct sudoers_gc_entry *gc;
+    debug_decl(sudoers_gc_add, SUDOERS_DEBUG_UTIL)
+
+    if (v == NULL)
+       debug_return_bool(false);
+
+    gc = calloc(1, sizeof(*gc));
+    if (gc == NULL) {
+       sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+       debug_return_bool(false);
+    }
+    switch (type) {
+    case GC_PTR:
+       gc->u.ptr = v;
+       break;
+    case GC_VECTOR:
+       gc->u.vec = v;
+       break;
+    default:
+       free(gc);
+       sudo_warnx("unexpected garbage type %d", type);
+       debug_return_bool(false);
+    }
+    gc->type = type;
+    SLIST_INSERT_HEAD(&sudoers_gc_list, gc, entries);
+    debug_return_bool(true);
+#else
+    return true;
+#endif /* NO_LEAKS */
+}
+
+bool
+sudoers_gc_remove(enum sudoers_gc_types type, void *v)
+{
+#ifdef NO_LEAKS
+    struct sudoers_gc_entry *gc, *prev = NULL;
+    debug_decl(sudoers_gc_remove, SUDOERS_DEBUG_UTIL)
+
+    SLIST_FOREACH(gc, &sudoers_gc_list, entries) {
+       switch (gc->type) {
+       case GC_PTR:
+           if (gc->u.ptr == v)
+               goto found;
+           break;
+       case GC_VECTOR:
+           if (gc->u.vec == v)
+               goto found;
+           break;
+       default:
+           sudo_warnx("unexpected garbage type %d in %p", gc->type, gc);
+       }
+       prev = gc;
+    }
+    return false;
+found:
+    if (prev != NULL)
+       SLIST_REMOVE_HEAD(&sudoers_gc_list, entries);
+    else
+       SLIST_REMOVE_AFTER(prev, entries);
+    return true;
+#else
+    return false;
+#endif /* NO_LEAKS */
+}
+
+#ifdef NO_LEAKS
+static void
+sudoers_gc_run(void)
+{
+    struct sudoers_gc_entry *gc;
+    char **cur;
+    debug_decl(sudoers_gc_run, SUDOERS_DEBUG_UTIL)
+
+    /* Collect garbage. */
+    while ((gc = SLIST_FIRST(&sudoers_gc_list))) {
+       SLIST_REMOVE_HEAD(&sudoers_gc_list, entries);
+       switch (gc->type) {
+       case GC_PTR:
+           free(gc->u.ptr);
+           free(gc);
+           break;
+       case GC_VECTOR:
+           for (cur = gc->u.vec; *cur != NULL; cur++)
+               free(*cur);
+           free(gc->u.vec);
+           free(gc);
+           break;
+       default:
+           sudo_warnx("unexpected garbage type %d", gc->type);
+       }
+    }
+
+    debug_return;
+}
+#endif /* NO_LEAKS */
+
+void
+sudoers_gc_init(void)
+{
+#ifdef NO_LEAKS
+    atexit(sudoers_gc_run);
+#endif
+}
index 6d4769688547fc68cdb61ae64fa46b259a6b4167..7fda0505099942f275d2756ba6978c0ecf75d3ce 100644 (file)
@@ -377,4 +377,14 @@ extern const char *path_plugin_dir;
 char *resolve_editor(const char *ed, size_t edlen, int nfiles, char **files,
     int *argc_out, char ***argv_out, char * const *whitelist);
 
+/* gc.c */
+enum sudoers_gc_types {
+    GC_UNKNOWN,
+    GC_VECTOR,
+    GC_PTR
+};
+bool sudoers_gc_add(enum sudoers_gc_types type, void *ptr);
+bool sudoers_gc_remove(enum sudoers_gc_types type, void *ptr);
+void sudoers_gc_init(void);
+
 #endif /* SUDOERS_SUDOERS_H */