From: Todd C. Miller Date: Tue, 22 Oct 2013 15:08:38 +0000 (-0600) Subject: Add "headless" tail queues and use them in place of the semi-circular X-Git-Tag: SUDO_1_8_9^2~156 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b38d253e9845409e2bd21a863a92f665991449ec;p=sudo Add "headless" tail queues and use them in place of the semi-circular lists in sudoers. Once the headless tail queue is built up it is converted to a normal TAILQ. This removes the last consumer of list.c and list.h so those can now be removed. --- diff --git a/MANIFEST b/MANIFEST index 2248ad338..c29d8f4d7 100644 --- a/MANIFEST +++ b/MANIFEST @@ -20,7 +20,6 @@ common/fileops.c common/fmt_string.c common/gidlist.c common/lbuf.c -common/list.c common/regress/sudo_conf/conf_test.c common/regress/sudo_conf/test1.in common/regress/sudo_conf/test1.out.ok @@ -47,6 +46,7 @@ common/regress/sudo_parseln/test5.in common/regress/sudo_parseln/test5.out.ok common/regress/sudo_parseln/test6.in common/regress/sudo_parseln/test6.out.ok +common/regress/tailq/hltq_test.c common/secure_path.c common/setgroups.c common/sudo_conf.c @@ -145,7 +145,6 @@ include/fatal.h include/fileops.h include/gettext.h include/lbuf.h -include/list.h include/missing.h include/queue.h include/secure_path.h diff --git a/common/Makefile.in b/common/Makefile.in index cdbc5b990..7b4caaf01 100644 --- a/common/Makefile.in +++ b/common/Makefile.in @@ -55,7 +55,7 @@ SSP_CFLAGS = @SSP_CFLAGS@ SSP_LDFLAGS = @SSP_LDFLAGS@ # Regression tests -TEST_PROGS = conf_test parseln_test +TEST_PROGS = conf_test parseln_test hltq_test TEST_LIBS = @LIBS@ @LIBINTL@ ../compat/libreplace.la TEST_LDFLAGS = @LDFLAGS@ @@ -67,7 +67,7 @@ DEFS = @OSDEFS@ -D_PATH_SUDO_CONF=\"$(sysconfdir)/sudo.conf\" SHELL = @SHELL@ LTOBJS = alloc.lo atobool.lo atoid.lo event.lo fatal.lo fileops.lo \ - fmt_string.lo gidlist.lo lbuf.lo list.lo secure_path.lo \ + fmt_string.lo gidlist.lo lbuf.lo secure_path.lo \ setgroups.lo sudo_conf.lo sudo_debug.lo sudo_printf.lo term.lo \ ttysize.lo @COMMON_OBJS@ @@ -75,6 +75,8 @@ PARSELN_TEST_OBJS = parseln_test.lo CONF_TEST_OBJS = conf_test.lo +HLTQ_TEST_OBJS = hltq_test.lo + all: libcommon.la Makefile: $(srcdir)/Makefile.in @@ -94,6 +96,9 @@ conf_test: $(CONF_TEST_OBJS) libcommon.la parseln_test: $(PARSELN_TEST_OBJS) libcommon.la $(LIBTOOL) --mode=link $(CC) -o $@ $(PARSELN_TEST_OBJS) libcommon.la $(PIE_LDFLAGS) $(SSP_LDFLAGS) $(TEST_LDFLAGS) $(TEST_LIBS) +hltq_test: $(HLTQ_TEST_OBJS) libcommon.la + $(LIBTOOL) --mode=link $(CC) -o $@ $(HLTQ_TEST_OBJS) libcommon.la $(PIE_LDFLAGS) $(SSP_LDFLAGS) $(TEST_LDFLAGS) $(TEST_LIBS) + pre-install: install: @@ -113,6 +118,12 @@ uninstall: check: $(TEST_PROGS) @if test X"$(cross_compiling)" != X"yes"; then \ passed=0; failed=0; total=0; \ + total=1; \ + if ./hltq_test; then \ + passed=`expr $$passed + 1`; \ + else \ + failed=`expr $$failed + 1`; \ + fi; \ for dir in sudo_conf sudo_parseln; do \ mkdir -p regress/$$dir; \ for t in $(srcdir)/regress/$$dir/*.in; do \ @@ -203,13 +214,14 @@ gidlist.lo: $(srcdir)/gidlist.c $(top_builddir)/config.h $(incdir)/gettext.h \ $(incdir)/missing.h $(incdir)/alloc.h $(incdir)/fatal.h \ $(incdir)/sudo_debug.h $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/gidlist.c +hltq_test.lo: $(srcdir)/regress/tailq/hltq_test.c $(top_builddir)/config.h \ + $(top_srcdir)/compat/stdbool.h $(incdir)/missing.h \ + $(incdir)/fatal.h $(incdir)/queue.h + $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/regress/tailq/hltq_test.c lbuf.lo: $(srcdir)/lbuf.c $(top_builddir)/config.h $(incdir)/missing.h \ $(incdir)/alloc.h $(incdir)/fatal.h $(incdir)/lbuf.h \ $(incdir)/sudo_debug.h $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/lbuf.c -list.lo: $(srcdir)/list.c $(top_builddir)/config.h $(incdir)/missing.h \ - $(incdir)/list.h $(incdir)/fatal.h - $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/list.c parseln_test.lo: $(srcdir)/regress/sudo_parseln/parseln_test.c \ $(top_builddir)/config.h $(top_srcdir)/compat/stdbool.h \ $(incdir)/missing.h $(incdir)/fileops.h diff --git a/common/list.c b/common/list.c deleted file mode 100644 index dce6489ab..000000000 --- a/common/list.c +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (c) 2007-2008, 2010-2012 Todd C. Miller - * - * 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. - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include - -#include -#include -#ifdef STDC_HEADERS -# include -# include -#else -# ifdef HAVE_STDLIB_H -# include -# endif -#endif /* STDC_HEADERS */ - -#include "missing.h" -#include "list.h" -#ifdef DEBUG -# include "fatal.h" -#endif - -struct list_proto { - struct list_proto *prev; - struct list_proto *next; -}; - -struct list_head_proto { - struct list_proto *first; - struct list_proto *last; -}; - -/* - * Pop the last element off the end of vh. - * Returns the popped element. - */ -void * -tq_pop(void *vh) -{ - struct list_head_proto *h = (struct list_head_proto *)vh; - void *last = NULL; - - if (!tq_empty(h)) { - last = (void *)h->last; - if (h->first == h->last) { - h->first = NULL; - h->last = NULL; - } else { - h->last = h->last->prev; - h->last->next = NULL; - } - } - return last; -} - -/* - * Convert from a semi-circle queue to normal doubly-linked list - * with a head node. - */ -void -list2tq(void *vh, void *vl) -{ - struct list_head_proto *h = (struct list_head_proto *)vh; - struct list_proto *l = (struct list_proto *)vl; - - if (l != NULL) { -#ifdef DEBUG - if (l->prev == NULL) { - warningx_nodebug("list2tq called with non-semicircular list"); - abort(); - } -#endif - h->first = l; - h->last = l->prev; /* l->prev points to the last member of l */ - l->prev = NULL; /* zero last ptr now that we have a head */ - } else { - h->first = NULL; - h->last = NULL; - } -} - -/* - * Append one queue (or single entry) to another using the - * circular properties of the prev pointer to simplify the logic. - */ -void -list_append(void *vl1, void *vl2) -{ - struct list_proto *l1 = (struct list_proto *)vl1; - struct list_proto *l2 = (struct list_proto *)vl2; - void *tail = l2->prev; - - l1->prev->next = l2; - l2->prev = l1->prev; - l1->prev = tail; -} - -/* - * Append the list of entries to the head node and convert - * from a semi-circle queue to normal doubly-linked list. - */ -void -tq_append(void *vh, void *vl) -{ - struct list_head_proto *h = (struct list_head_proto *)vh; - struct list_proto *l = (struct list_proto *)vl; - void *tail = l->prev; - - if (h->first == NULL) - h->first = l; - else - h->last->next = l; - l->prev = h->last; - h->last = tail; -} - -/* - * Remove element from the tail_queue - */ -void -tq_remove(void *vh, void *vl) -{ - struct list_head_proto *h = (struct list_head_proto *)vh; - struct list_proto *l = (struct list_proto *)vl; - - if (h->first == l && h->last == l) { - /* Single element in the list. */ - h->first = NULL; - h->last = NULL; - } else { - /* At least two elements in the list. */ - if (h->first == l) { - h->first = l->next; - h->first->prev = h->first; - } else if (h->last == l) { - h->last = l->prev; - h->last->next = NULL; - } else { - l->prev->next = l->next; - l->next->prev = l->prev; - } - } -} diff --git a/common/regress/tailq/hltq_test.c b/common/regress/tailq/hltq_test.c new file mode 100644 index 000000000..7897a6675 --- /dev/null +++ b/common/regress/tailq/hltq_test.c @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2013 Todd C. Miller + * + * 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 + +#include +#include +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif /* STDC_HEADERS */ +#ifdef HAVE_STRING_H +# if defined(HAVE_MEMORY_H) && !defined(STDC_HEADERS) +# include +# endif +# include +#endif /* HAVE_STRING_H */ +#ifdef HAVE_STRINGS_H +# include +#endif /* HAVE_STRINGS_H */ +#ifdef HAVE_STDBOOL_H +# include +#else +# include "compat/stdbool.h" +#endif + +#include "missing.h" +#include "fatal.h" +#include "queue.h" + +__dso_public int main(int argc, char *argv[]); + +/* + * Note: HLTQ_ENTRY is intentionally in the middle of the struct + * to catch bad assumptions in the PREV/NEXT macros. + */ +struct test_data { + int a; + HLTQ_ENTRY(test_data) entries; + char b; +}; + +TAILQ_HEAD(test_data_list, test_data); + +/* + * Simple tests for headless tail queue macros. + */ +int +main(int argc, char *argv[]) +{ + struct test_data d1, d2, d3; + struct test_data *hltq; + struct test_data_list tq; + int errors = 0; + + /* + * Initialize three data elements and concatenate them in order. + */ + HLTQ_INIT(&d1, entries); + d1.a = 1; + d1.b = 'a'; + if (HLTQ_FIRST(&d1) != &d1) { + warningx_nodebug("FAIL: HLTQ_FIRST(1 entry) doesn't return first element: got %p, expected %p", HLTQ_FIRST(&d1), &d1); + errors++; + } + if (HLTQ_LAST(&d1, test_data, entries) != &d1) { + warningx_nodebug("FAIL: HLTQ_LAST(1 entry) doesn't return first element: got %p, expected %p", HLTQ_LAST(&d1, test_data, entries), &d1); + errors++; + } + if (HLTQ_PREV(&d1, test_data, entries) != NULL) { + warningx_nodebug("FAIL: HLTQ_PREV(1 entry) doesn't return NULL: got %p", HLTQ_PREV(&d1, test_data, entries)); + errors++; + } + + HLTQ_INIT(&d2, entries); + d2.a = 2; + d2.b = 'b'; + + HLTQ_INIT(&d3, entries); + d3.a = 3; + d3.b = 'c'; + + HLTQ_CONCAT(&d1, &d2, entries); + HLTQ_CONCAT(&d1, &d3, entries); + hltq = &d1; + + /* + * Verify that HLTQ_FIRST, HLTQ_LAST, HLTQ_NEXT, HLTQ_PREV + * work as expected. + */ + if (HLTQ_FIRST(hltq) != &d1) { + warningx_nodebug("FAIL: HLTQ_FIRST(3 entries) doesn't return first element: got %p, expected %p", HLTQ_FIRST(hltq), &d1); + errors++; + } + if (HLTQ_LAST(hltq, test_data, entries) != &d3) { + warningx_nodebug("FAIL: HLTQ_LAST(3 entries) doesn't return third element: got %p, expected %p", HLTQ_LAST(hltq, test_data, entries), &d3); + errors++; + } + + if (HLTQ_NEXT(&d1, entries) != &d2) { + warningx_nodebug("FAIL: HLTQ_NEXT(&d1) doesn't return &d2: got %p, expected %p", HLTQ_NEXT(&d1, entries), &d2); + errors++; + } + if (HLTQ_NEXT(&d2, entries) != &d3) { + warningx_nodebug("FAIL: HLTQ_NEXT(&d2) doesn't return &d3: got %p, expected %p", HLTQ_NEXT(&d2, entries), &d3); + errors++; + } + if (HLTQ_NEXT(&d3, entries) != NULL) { + warningx_nodebug("FAIL: HLTQ_NEXT(&d3) doesn't return NULL: got %p", HLTQ_NEXT(&d3, entries)); + errors++; + } + + if (HLTQ_PREV(&d1, test_data, entries) != NULL) { + warningx_nodebug("FAIL: HLTQ_PREV(&d1) doesn't return NULL: got %p", HLTQ_PREV(&d1, test_data, entries)); + errors++; + } + if (HLTQ_PREV(&d2, test_data, entries) != &d1) { + warningx_nodebug("FAIL: HLTQ_PREV(&d2) doesn't return &d1: got %p, expected %p", HLTQ_PREV(&d2, test_data, entries), &d1); + errors++; + } + if (HLTQ_PREV(&d3, test_data, entries) != &d2) { + warningx_nodebug("FAIL: HLTQ_PREV(&d3) doesn't return &d2: got %p, expected %p", HLTQ_PREV(&d3, test_data, entries), &d2); + errors++; + } + + /* Test conversion to TAILQ. */ + HLTQ_TO_TAILQ(&tq, hltq, entries); + + if (TAILQ_FIRST(&tq) != &d1) { + warningx_nodebug("FAIL: TAILQ_FIRST(&tq) doesn't return first element: got %p, expected %p", TAILQ_FIRST(&tq), &d1); + errors++; + } + if (TAILQ_LAST(&tq, test_data_list) != &d3) { + warningx_nodebug("FAIL: TAILQ_LAST(&tq) doesn't return third element: got %p, expected %p", TAILQ_LAST(&tq, test_data_list), &d3); + errors++; + } + + if (TAILQ_NEXT(&d1, entries) != &d2) { + warningx_nodebug("FAIL: TAILQ_NEXT(&d1) doesn't return &d2: got %p, expected %p", TAILQ_NEXT(&d1, entries), &d2); + errors++; + } + if (TAILQ_NEXT(&d2, entries) != &d3) { + warningx_nodebug("FAIL: TAILQ_NEXT(&d2) doesn't return &d3: got %p, expected %p", TAILQ_NEXT(&d2, entries), &d3); + errors++; + } + if (TAILQ_NEXT(&d3, entries) != NULL) { + warningx_nodebug("FAIL: TAILQ_NEXT(&d3) doesn't return NULL: got %p", TAILQ_NEXT(&d3, entries)); + errors++; + } + + if (TAILQ_PREV(&d1, test_data_list, entries) != NULL) { + warningx_nodebug("FAIL: TAILQ_PREV(&d1) doesn't return NULL: got %p", TAILQ_PREV(&d1, test_data_list, entries)); + errors++; + } + if (TAILQ_PREV(&d2, test_data_list, entries) != &d1) { + warningx_nodebug("FAIL: TAILQ_PREV(&d2) doesn't return &d1: got %p, expected %p", TAILQ_PREV(&d2, test_data_list, entries), &d1); + errors++; + } + if (TAILQ_PREV(&d3, test_data_list, entries) != &d2) { + warningx_nodebug("FAIL: TAILQ_PREV(&d3) doesn't return &d2: got %p, expected %p", TAILQ_PREV(&d3, test_data_list, entries), &d2); + errors++; + } + + exit(errors); +} + +/* STUB */ +void +warning_set_locale(void) +{ + return; +} + +/* STUB */ +void +warning_restore_locale(void) +{ + return; +} diff --git a/include/list.h b/include/list.h deleted file mode 100644 index 1055e227a..000000000 --- a/include/list.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2007, 2010 Todd C. Miller - * - * 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. - */ - -#ifndef _SUDO_LIST_H -#define _SUDO_LIST_H - -/* - * Convenience macro for declaring a list head. - */ -#define TQ_DECLARE(n) \ -struct n##_list { \ - struct n *first; \ - struct n *last; \ -}; - -/* - * Foreach loops: forward and reverse - */ -#undef tq_foreach_fwd -#define tq_foreach_fwd(h, v) \ - for ((v) = (h)->first; (v) != NULL; (v) = (v)->next) - -#undef tq_foreach_rev -#define tq_foreach_rev(h, v) \ - for ((v) = (h)->last; (v) != NULL; (v) = (v)->prev) - -/* - * Init a list head. - */ -#undef tq_init -#define tq_init(h) do { \ - (h)->first = NULL; \ - (h)->last = NULL; \ -} while (0) - -/* - * Simple macros to avoid exposing first/last and prev/next. - */ -#undef tq_empty -#define tq_empty(h) ((h)->first == NULL) - -#undef tq_first -#define tq_first(h) ((h)->first) - -#undef tq_last -#define tq_last(h) ((h)->last) - -#undef list_next -#define list_next(e) ((e)->next) - -#undef list_prev -#define list_prev(e) ((e)->prev) - -/* - * Prototypes for list.c - */ -void *tq_pop(void *); -void tq_append(void *, void *); -void tq_remove(void *, void *); -void list_append(void *, void *); -void list2tq(void *, void *); - -#endif /* _SUDO_LIST_H */ diff --git a/include/queue.h b/include/queue.h index de4ef162a..9392c674d 100644 --- a/include/queue.h +++ b/include/queue.h @@ -72,6 +72,13 @@ * after an existing element, at the head of the list, or at the end of * the list. A tail queue may be traversed in either direction. * + * A headless tail queue lacks a head structure, The first element acts + * as a de facto list head. It uses the same entry struct as a regular + * tail queue for easy conversion from headless to headful. + * It is capable of concatenating queues as well as individual elements. + * Traversing in reverse is more expensive due to lack of a list head. + * Note: elements must be initialized before use. + * * For details on the use of these macros, see the queue(3) manual page. * * @@ -712,4 +719,88 @@ struct { \ (head2)->tqh_last = &(head2)->tqh_first; \ } while (0) +/* + * Headless Tail queue definitions. + */ +#undef HLTQ_ENTRY +#define HLTQ_ENTRY(type) TAILQ_ENTRY(type) + +#undef HLTQ_INIT +#define HLTQ_INIT(entry, field) do { \ + (entry)->field.tqe_next = NULL; \ + (entry)->field.tqe_prev = &(entry)->field.tqe_next; \ +} while (0) + +#undef HLTQ_INITIALIZER +#define HLTQ_INITIALIZER(entry, field) \ + { NULL, &(entry)->field.tqe_next } + +#undef HLTQ_FIRST +#define HLTQ_FIRST(elm) (elm) + +#undef HLTQ_END +#define HLTQ_END(elm) NULL + +#undef HLTQ_NEXT +#define HLTQ_NEXT(elm, field) ((elm)->field.tqe_next) + +#undef HLTQ_LAST +#define HLTQ_LAST(elm, type, field) \ + ((elm)->field.tqe_next == NULL ? (elm) : \ + __containerof((elm)->field.tqe_prev, struct type, field.tqe_next)) + +#undef HLTQ_PREV +#define HLTQ_PREV(elm, type, field) \ + (*(elm)->field.tqe_prev == NULL ? NULL : \ + __containerof((elm)->field.tqe_prev, struct type, field.tqe_next)) + +#undef HLTQ_FOREACH +#define HLTQ_FOREACH(var, head, field) \ + for ((var) = HLTQ_FIRST(head); \ + (var) != HLTQ_END(head); \ + (var) = HLTQ_NEXT(var, field)) + +#undef HLTQ_FOREACH_SAFE +#define HLTQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = HLTQ_FIRST(head); \ + (var) != HLTQ_END(head) && \ + ((tvar) = HLTQ_NEXT(var, field), 1); \ + (var) = (tvar)) + +#undef HLTQ_FOREACH_REVERSE +#define HLTQ_FOREACH_REVERSE(var, head, headname, field) \ + for ((var) = HLTQ_LAST(head, headname); \ + (var) != HLTQ_END(head); \ + (var) = HLTQ_PREV(var, headname, field)) + +#undef HLTQ_FOREACH_REVERSE_SAFE +#define HLTQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \ + for ((var) = HLTQ_LAST(head, headname); \ + (var) != HLTQ_END(head) && \ + ((tvar) = HLTQ_PREV(var, headname, field), 1); \ + (var) = (tvar)) + +/* Concatenate queue2 to the end of queue1. */ +#undef HLTQ_CONCAT +#define HLTQ_CONCAT(queue1, queue2, field) do { \ + (queue2)->field.tqe_prev = (queue1)->field.tqe_prev; \ + *(queue1)->field.tqe_prev = (queue2); \ + (queue1)->field.tqe_prev = &(queue2)->field.tqe_next; \ +} while (0) + +/* Convert a headless tailq to a headful one. */ +#define HLTQ_TO_TAILQ(head, hl, field) do { \ + (head)->tqh_first = (hl); \ + (head)->tqh_last = (hl)->field.tqe_prev; \ + (hl)->field.tqe_prev = &(head)->tqh_first; \ +} while (0) + +/* Concatenate a headless tail queue to the end of a regular tail queue. */ +#define TAILQ_CONCAT_HLTQ(head, hl, field) do { \ + void *last = (hl)->field.tqe_prev; \ + (hl)->field.tqe_prev = (head)->tqh_last; \ + *(head)->tqh_last = (hl); \ + (head)->tqh_last = last; \ +} while (0) + #endif /* !_SUDO_QUEUE_H_ */ diff --git a/plugins/sudoers/Makefile.in b/plugins/sudoers/Makefile.in index 08d4ef352..f861dcafd 100644 --- a/plugins/sudoers/Makefile.in +++ b/plugins/sudoers/Makefile.in @@ -450,8 +450,7 @@ alias.lo: $(srcdir)/alias.c $(top_builddir)/config.h $(srcdir)/sudoers.h \ $(incdir)/queue.h $(incdir)/fileops.h $(srcdir)/defaults.h \ $(devdir)/def_data.h $(srcdir)/logging.h $(srcdir)/sudo_nss.h \ $(incdir)/sudo_plugin.h $(incdir)/sudo_debug.h $(incdir)/gettext.h \ - $(srcdir)/parse.h $(incdir)/list.h $(srcdir)/redblack.h \ - $(devdir)/gram.h + $(srcdir)/parse.h $(srcdir)/redblack.h $(devdir)/gram.h $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/alias.c audit.lo: $(srcdir)/audit.c $(top_builddir)/config.h \ $(top_srcdir)/compat/stdbool.h $(incdir)/missing.h \ @@ -491,7 +490,7 @@ check_addr.o: $(srcdir)/regress/parser/check_addr.c $(top_builddir)/config.h \ $(incdir)/fileops.h $(srcdir)/defaults.h $(devdir)/def_data.h \ $(srcdir)/logging.h $(srcdir)/sudo_nss.h $(incdir)/sudo_plugin.h \ $(incdir)/sudo_debug.h $(incdir)/gettext.h $(srcdir)/parse.h \ - $(incdir)/list.h $(srcdir)/interfaces.h + $(srcdir)/interfaces.h $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/regress/parser/check_addr.c check_base64.o: $(srcdir)/regress/parser/check_base64.c \ $(top_builddir)/config.h $(incdir)/missing.h @@ -501,8 +500,8 @@ check_digest.o: $(srcdir)/regress/parser/check_digest.c \ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/regress/parser/check_digest.c check_fill.o: $(srcdir)/regress/parser/check_fill.c $(top_builddir)/config.h \ $(top_srcdir)/compat/stdbool.h $(incdir)/missing.h \ - $(incdir)/list.h $(srcdir)/parse.h $(incdir)/list.h \ - $(srcdir)/toke.h $(incdir)/sudo_plugin.h $(devdir)/gram.h + $(incdir)/queue.h $(srcdir)/parse.h $(srcdir)/toke.h \ + $(incdir)/sudo_plugin.h $(devdir)/gram.h $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/regress/parser/check_fill.c check_iolog_path.o: $(srcdir)/regress/iolog_path/check_iolog_path.c \ $(top_builddir)/config.h $(srcdir)/sudoers.h \ @@ -534,8 +533,8 @@ defaults.lo: $(srcdir)/defaults.c $(top_builddir)/config.h $(srcdir)/sudoers.h \ $(incdir)/queue.h $(incdir)/fileops.h $(srcdir)/defaults.h \ $(devdir)/def_data.h $(srcdir)/logging.h $(srcdir)/sudo_nss.h \ $(incdir)/sudo_plugin.h $(incdir)/sudo_debug.h \ - $(incdir)/gettext.h $(srcdir)/parse.h $(incdir)/list.h \ - $(devdir)/gram.h $(devdir)/def_data.c + $(incdir)/gettext.h $(srcdir)/parse.h $(devdir)/gram.h \ + $(devdir)/def_data.c $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/defaults.c env.lo: $(srcdir)/env.c $(top_builddir)/config.h $(srcdir)/sudoers.h \ $(top_srcdir)/compat/stdbool.h $(top_builddir)/pathnames.h \ @@ -585,7 +584,7 @@ gram.lo: $(devdir)/gram.c $(top_builddir)/config.h $(top_builddir)/config.h \ $(incdir)/alloc.h $(incdir)/queue.h $(incdir)/fileops.h \ $(srcdir)/defaults.h $(devdir)/def_data.h $(srcdir)/logging.h \ $(srcdir)/sudo_nss.h $(incdir)/sudo_plugin.h $(incdir)/sudo_debug.h \ - $(incdir)/gettext.h $(srcdir)/parse.h $(incdir)/list.h $(srcdir)/toke.h + $(incdir)/gettext.h $(srcdir)/parse.h $(srcdir)/toke.h $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(devdir)/gram.c group_plugin.lo: $(srcdir)/group_plugin.c $(top_builddir)/config.h \ $(top_srcdir)/compat/dlfcn.h $(srcdir)/sudoers.h \ @@ -643,7 +642,7 @@ ldap.lo: $(srcdir)/ldap.c $(top_builddir)/config.h \ $(incdir)/queue.h $(incdir)/fileops.h $(srcdir)/defaults.h \ $(devdir)/def_data.h $(srcdir)/logging.h $(srcdir)/sudo_nss.h \ $(incdir)/sudo_plugin.h $(incdir)/sudo_debug.h $(incdir)/gettext.h \ - $(srcdir)/parse.h $(incdir)/list.h $(incdir)/lbuf.h + $(srcdir)/parse.h $(incdir)/lbuf.h $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/ldap.c linux_audit.lo: $(srcdir)/linux_audit.c $(top_builddir)/config.h \ $(incdir)/missing.h $(incdir)/fatal.h $(incdir)/alloc.h \ @@ -678,8 +677,8 @@ match.lo: $(srcdir)/match.c $(top_builddir)/config.h \ $(incdir)/alloc.h $(incdir)/queue.h $(incdir)/fileops.h \ $(srcdir)/defaults.h $(devdir)/def_data.h $(srcdir)/logging.h \ $(srcdir)/sudo_nss.h $(incdir)/sudo_plugin.h $(incdir)/sudo_debug.h \ - $(incdir)/gettext.h $(srcdir)/parse.h $(incdir)/list.h \ - $(srcdir)/sha2.h $(devdir)/gram.h + $(incdir)/gettext.h $(srcdir)/parse.h $(srcdir)/sha2.h \ + $(devdir)/gram.h $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/match.c match_addr.lo: $(srcdir)/match_addr.c $(top_builddir)/config.h \ $(srcdir)/sudoers.h $(top_srcdir)/compat/stdbool.h \ @@ -708,7 +707,7 @@ parse.lo: $(srcdir)/parse.c $(top_builddir)/config.h $(srcdir)/sudoers.h \ $(incdir)/queue.h $(incdir)/fileops.h $(srcdir)/defaults.h \ $(devdir)/def_data.h $(srcdir)/logging.h $(srcdir)/sudo_nss.h \ $(incdir)/sudo_plugin.h $(incdir)/sudo_debug.h $(incdir)/gettext.h \ - $(srcdir)/parse.h $(incdir)/list.h $(incdir)/lbuf.h $(devdir)/gram.h + $(srcdir)/parse.h $(incdir)/lbuf.h $(devdir)/gram.h $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/parse.c passwd.lo: $(authdir)/passwd.c $(top_builddir)/config.h $(srcdir)/sudoers.h \ $(top_srcdir)/compat/stdbool.h $(top_builddir)/pathnames.h \ @@ -805,8 +804,7 @@ sssd.lo: $(srcdir)/sssd.c $(top_builddir)/config.h \ $(incdir)/queue.h $(incdir)/fileops.h $(srcdir)/defaults.h \ $(devdir)/def_data.h $(srcdir)/logging.h $(srcdir)/sudo_nss.h \ $(incdir)/sudo_plugin.h $(incdir)/sudo_debug.h $(incdir)/gettext.h \ - $(srcdir)/parse.h $(incdir)/list.h $(incdir)/lbuf.h \ - $(incdir)/sudo_debug.h + $(srcdir)/parse.h $(incdir)/lbuf.h $(incdir)/sudo_debug.h $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/sssd.c sudo_auth.lo: $(authdir)/sudo_auth.c $(top_builddir)/config.h \ $(srcdir)/sudoers.h $(top_srcdir)/compat/stdbool.h \ @@ -853,8 +851,8 @@ testsudoers.o: $(srcdir)/testsudoers.c $(top_builddir)/config.h \ $(devdir)/def_data.h $(srcdir)/logging.h $(srcdir)/sudo_nss.h \ $(incdir)/sudo_plugin.h $(incdir)/sudo_debug.h \ $(incdir)/gettext.h $(srcdir)/interfaces.h $(srcdir)/parse.h \ - $(incdir)/list.h $(incdir)/sudo_conf.h $(incdir)/queue.h \ - $(incdir)/secure_path.h $(devdir)/gram.h + $(incdir)/sudo_conf.h $(incdir)/queue.h $(incdir)/secure_path.h \ + $(devdir)/gram.h $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/testsudoers.c timestamp.lo: $(srcdir)/timestamp.c $(top_builddir)/config.h \ $(srcdir)/sudoers.h $(top_srcdir)/compat/stdbool.h \ @@ -872,8 +870,8 @@ toke.lo: $(devdir)/toke.c $(top_builddir)/config.h $(top_builddir)/config.h \ $(incdir)/alloc.h $(incdir)/queue.h $(incdir)/fileops.h \ $(srcdir)/defaults.h $(devdir)/def_data.h $(srcdir)/logging.h \ $(srcdir)/sudo_nss.h $(incdir)/sudo_plugin.h $(incdir)/sudo_debug.h \ - $(incdir)/gettext.h $(srcdir)/parse.h $(incdir)/list.h \ - $(srcdir)/toke.h $(devdir)/gram.h $(incdir)/lbuf.h $(srcdir)/sha2.h \ + $(incdir)/gettext.h $(srcdir)/parse.h $(srcdir)/toke.h \ + $(devdir)/gram.h $(incdir)/lbuf.h $(srcdir)/sha2.h \ $(incdir)/secure_path.h $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(devdir)/toke.c toke_util.lo: $(srcdir)/toke_util.c $(top_builddir)/config.h \ @@ -883,7 +881,7 @@ toke_util.lo: $(srcdir)/toke_util.c $(top_builddir)/config.h \ $(incdir)/fileops.h $(srcdir)/defaults.h $(devdir)/def_data.h \ $(srcdir)/logging.h $(srcdir)/sudo_nss.h $(incdir)/sudo_plugin.h \ $(incdir)/sudo_debug.h $(incdir)/gettext.h $(srcdir)/parse.h \ - $(incdir)/list.h $(srcdir)/toke.h $(devdir)/gram.h + $(srcdir)/toke.h $(devdir)/gram.h $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/toke_util.c toke_util.o: toke_util.lo tsgetgrpw.o: $(srcdir)/tsgetgrpw.c $(top_builddir)/config.h \ @@ -902,7 +900,7 @@ visudo.o: $(srcdir)/visudo.c $(top_builddir)/config.h \ $(incdir)/queue.h $(incdir)/fileops.h $(srcdir)/defaults.h \ $(devdir)/def_data.h $(srcdir)/logging.h $(srcdir)/sudo_nss.h \ $(incdir)/sudo_plugin.h $(incdir)/sudo_debug.h $(incdir)/gettext.h \ - $(srcdir)/parse.h $(incdir)/list.h $(srcdir)/redblack.h \ - $(incdir)/gettext.h $(srcdir)/sudoers_version.h \ - $(incdir)/sudo_conf.h $(incdir)/queue.h $(devdir)/gram.h + $(srcdir)/parse.h $(srcdir)/redblack.h $(incdir)/gettext.h \ + $(srcdir)/sudoers_version.h $(incdir)/sudo_conf.h $(incdir)/queue.h \ + $(devdir)/gram.h $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/visudo.c diff --git a/plugins/sudoers/alias.c b/plugins/sudoers/alias.c index ccedd0347..0c1fc7183 100644 --- a/plugins/sudoers/alias.c +++ b/plugins/sudoers/alias.c @@ -131,7 +131,7 @@ alias_add(char *name, int type, struct member *members) a->name = name; a->type = type; /* a->used = false; */ - list2tq(&a->members, members); + HLTQ_TO_TAILQ(&a->members, members, entries); if (rbinsert(aliases, a)) { snprintf(errbuf, sizeof(errbuf), N_("Alias `%s' already defined"), name); alias_free(a); @@ -176,8 +176,7 @@ alias_free(void *v) debug_decl(alias_free, SUDO_DEBUG_ALIAS) efree(a->name); - for (m = a->members.first; m != NULL; m = next) { - next = m->next; + TAILQ_FOREACH_SAFE(m, &a->members, entries, next) { if (m->type == COMMAND) { c = (struct sudo_command *) m->name; efree(c->cmnd); diff --git a/plugins/sudoers/defaults.c b/plugins/sudoers/defaults.c index 249e0e999..37d9de4d1 100644 --- a/plugins/sudoers/defaults.c +++ b/plugins/sudoers/defaults.c @@ -502,7 +502,7 @@ update_defaults(int what) bool rc = true; debug_decl(update_defaults, SUDO_DEBUG_DEFAULTS) - tq_foreach_fwd(&defaults, def) { + TAILQ_FOREACH(def, &defaults, entries) { switch (def->type) { case DEFAULTS: if (ISSET(what, SETDEF_GENERIC) && @@ -513,7 +513,7 @@ update_defaults(int what) #if 1 if (ISSET(what, SETDEF_USER)) { int m; - m = userlist_matches(sudo_user.pw, &def->binding); + m = userlist_matches(sudo_user.pw, def->binding); if (m == ALLOW) { if (!set_default(def->var, def->val, def->op)) rc = false; @@ -521,26 +521,26 @@ update_defaults(int what) } #else if (ISSET(what, SETDEF_USER) && - userlist_matches(sudo_user.pw, &def->binding) == ALLOW && + userlist_matches(sudo_user.pw, def->binding) == ALLOW && !set_default(def->var, def->val, def->op)) rc = false; #endif break; case DEFAULTS_RUNAS: if (ISSET(what, SETDEF_RUNAS) && - runaslist_matches(&def->binding, NULL, NULL, NULL) == ALLOW && + runaslist_matches(def->binding, NULL, NULL, NULL) == ALLOW && !set_default(def->var, def->val, def->op)) rc = false; break; case DEFAULTS_HOST: if (ISSET(what, SETDEF_HOST) && - hostlist_matches(&def->binding) == ALLOW && + hostlist_matches(def->binding) == ALLOW && !set_default(def->var, def->val, def->op)) rc = false; break; case DEFAULTS_CMND: if (ISSET(what, SETDEF_CMND) && - cmndlist_matches(&def->binding) == ALLOW && + cmndlist_matches(def->binding) == ALLOW && !set_default(def->var, def->val, def->op)) rc = false; break; @@ -561,7 +561,7 @@ check_defaults(int what, bool quiet) bool rc = true; debug_decl(check_defaults, SUDO_DEBUG_DEFAULTS) - tq_foreach_fwd(&defaults, def) { + TAILQ_FOREACH(def, &defaults, entries) { switch (def->type) { case DEFAULTS: if (!ISSET(what, SETDEF_GENERIC)) diff --git a/plugins/sudoers/gram.c b/plugins/sudoers/gram.c index 46e15bea2..3fe555075 100644 --- a/plugins/sudoers/gram.c +++ b/plugins/sudoers/gram.c @@ -117,8 +117,8 @@ bool parse_error = false; int errorlineno = -1; char *errorfile = NULL; -struct defaults_list defaults; -struct userspec_list userspecs; +struct defaults_list defaults = TAILQ_HEAD_INITIALIZER(defaults); +struct userspec_list userspecs = TAILQ_HEAD_INITIALIZER(userspecs); /* * Local protoypes @@ -699,7 +699,7 @@ short *yyss; short *yysslim; YYSTYPE *yyvs; int yystacksize; -#line 681 "gram.y" +#line 688 "gram.y" void sudoerserror(const char *s) { @@ -741,11 +741,10 @@ new_default(char *var, char *val, int op) d = ecalloc(1, sizeof(struct defaults)); d->var = var; d->val = val; - tq_init(&d->binding); /* d->type = 0; */ d->op = op; - d->prev = d; - /* d->next = NULL; */ + /* d->binding = NULL */ + HLTQ_INIT(d, entries); debug_return_ptr(d); } @@ -759,8 +758,7 @@ new_member(char *name, int type) m = ecalloc(1, sizeof(struct member)); m->name = name; m->type = type; - m->prev = m; - /* m->next = NULL; */ + HLTQ_INIT(m, entries); debug_return_ptr(m); } @@ -787,30 +785,34 @@ static void add_defaults(int type, struct member *bmem, struct defaults *defs) { struct defaults *d; - struct member_list binding; + struct member_list *binding; debug_decl(add_defaults, SUDO_DEBUG_PARSER) /* - * We can only call list2tq once on bmem as it will zero - * out the prev pointer when it consumes bmem. + * We use a single binding for each entry in defs. */ - list2tq(&binding, bmem); + binding = emalloc(sizeof(*binding)); + if (bmem != NULL) + HLTQ_TO_TAILQ(binding, bmem, entries); + else + TAILQ_INIT(binding); /* * Set type and binding (who it applies to) for new entries. + * Then add to the global defaults list. */ - for (d = defs; d != NULL; d = d->next) { + HLTQ_FOREACH(d, defs, entries) { d->type = type; d->binding = binding; } - tq_append(&defaults, defs); + TAILQ_CONCAT_HLTQ(&defaults, defs, entries); debug_return; } /* * Allocate a new struct userspec, populate it, and insert it at the - * and of the userspecs list. + * end of the userspecs list. */ static void add_userspec(struct member *members, struct privilege *privs) @@ -819,11 +821,9 @@ add_userspec(struct member *members, struct privilege *privs) debug_decl(add_userspec, SUDO_DEBUG_PARSER) u = ecalloc(1, sizeof(*u)); - list2tq(&u->users, members); - list2tq(&u->privileges, privs); - u->prev = u; - /* u->next = NULL; */ - tq_append(&userspecs, u); + HLTQ_TO_TAILQ(&u->users, members, entries); + HLTQ_TO_TAILQ(&u->privileges, privs, entries); + TAILQ_INSERT_TAIL(&userspecs, u, entries); debug_return; } @@ -835,21 +835,24 @@ add_userspec(struct member *members, struct privilege *privs) void init_parser(const char *path, bool quiet) { + struct member_list *binding; + struct member *m; struct defaults *d; - struct member *m, *binding; struct userspec *us; struct privilege *priv; struct cmndspec *cs; struct sudo_command *c; debug_decl(init_parser, SUDO_DEBUG_PARSER) - while ((us = tq_pop(&userspecs)) != NULL) { - while ((m = tq_pop(&us->users)) != NULL) { + while ((us = TAILQ_FIRST(&userspecs)) != NULL) { + TAILQ_REMOVE(&userspecs, us, entries); + while ((m = TAILQ_FIRST(&us->users)) != NULL) { + TAILQ_REMOVE(&us->users, m, entries); efree(m->name); efree(m); } - while ((priv = tq_pop(&us->privileges)) != NULL) { - struct member *runasuser = NULL, *runasgroup = NULL; + while ((priv = TAILQ_FIRST(&us->privileges)) != NULL) { + struct member_list *runasuserlist = NULL, *runasgrouplist = NULL; #ifdef HAVE_SELINUX char *role = NULL, *type = NULL; #endif /* HAVE_SELINUX */ @@ -857,11 +860,14 @@ init_parser(const char *path, bool quiet) char *privs = NULL, *limitprivs = NULL; #endif /* HAVE_PRIV_SET */ - while ((m = tq_pop(&priv->hostlist)) != NULL) { + TAILQ_REMOVE(&us->privileges, priv, entries); + while ((m = TAILQ_FIRST(&priv->hostlist)) != NULL) { + TAILQ_REMOVE(&priv->hostlist, m, entries); efree(m->name); efree(m); } - while ((cs = tq_pop(&priv->cmndlist)) != NULL) { + while ((cs = TAILQ_FIRST(&priv->cmndlist)) != NULL) { + TAILQ_REMOVE(&priv->cmndlist, cs, entries); #ifdef HAVE_SELINUX /* Only free the first instance of a role/type. */ if (cs->role != role) { @@ -884,19 +890,24 @@ init_parser(const char *path, bool quiet) efree(cs->limitprivs); } #endif /* HAVE_PRIV_SET */ - if (tq_last(&cs->runasuserlist) != runasuser) { - runasuser = tq_last(&cs->runasuserlist); - while ((m = tq_pop(&cs->runasuserlist)) != NULL) { + /* Only free the first instance of runas user/group lists. */ + if (cs->runasuserlist && cs->runasuserlist != runasuserlist) { + runasuserlist = cs->runasuserlist; + while ((m = TAILQ_FIRST(runasuserlist)) != NULL) { + TAILQ_REMOVE(runasuserlist, m, entries); efree(m->name); efree(m); } + efree(runasuserlist); } - if (tq_last(&cs->runasgrouplist) != runasgroup) { - runasgroup = tq_last(&cs->runasgrouplist); - while ((m = tq_pop(&cs->runasgrouplist)) != NULL) { + if (cs->runasgrouplist && cs->runasgrouplist != runasgrouplist) { + runasgrouplist = cs->runasgrouplist; + while ((m = TAILQ_FIRST(runasgrouplist)) != NULL) { + TAILQ_REMOVE(runasgrouplist, m, entries); efree(m->name); efree(m); } + efree(runasgrouplist); } if (cs->cmnd->type == COMMAND) { c = (struct sudo_command *) cs->cmnd->name; @@ -911,13 +922,15 @@ init_parser(const char *path, bool quiet) } efree(us); } - tq_init(&userspecs); + TAILQ_INIT(&userspecs); binding = NULL; - while ((d = tq_pop(&defaults)) != NULL) { - if (tq_last(&d->binding) != binding) { - binding = tq_last(&d->binding); - while ((m = tq_pop(&d->binding)) != NULL) { + while ((d = TAILQ_FIRST(&defaults)) != NULL) { + TAILQ_REMOVE(&defaults, d, entries); + if (d->binding != binding) { + binding = d->binding; + while ((m = TAILQ_FIRST(d->binding)) != NULL) { + TAILQ_REMOVE(d->binding, m, entries); if (m->type == COMMAND) { c = (struct sudo_command *) m->name; efree(c->cmnd); @@ -926,12 +939,13 @@ init_parser(const char *path, bool quiet) efree(m->name); efree(m); } + efree(d->binding); } efree(d->var); efree(d->val); efree(d); } - tq_init(&defaults); + TAILQ_INIT(&defaults); init_aliases(); @@ -947,7 +961,7 @@ init_parser(const char *path, bool quiet) debug_return; } -#line 898 "gram.c" +#line 912 "gram.c" /* allocate initial stack or double stack size, up to YYMAXDEPTH */ #if defined(__cplusplus) || defined(__STDC__) static int yygrowstack(void) @@ -1228,7 +1242,7 @@ break; case 18: #line 232 "gram.y" { - list_append(yyvsp[-2].defaults, yyvsp[0].defaults); + HLTQ_CONCAT(yyvsp[-2].defaults, yyvsp[0].defaults, entries); yyval.defaults = yyvsp[-2].defaults; } break; @@ -1265,7 +1279,7 @@ break; case 25: #line 256 "gram.y" { - list_append(yyvsp[-2].privilege, yyvsp[0].privilege); + HLTQ_CONCAT(yyvsp[-2].privilege, yyvsp[0].privilege, entries); yyval.privilege = yyvsp[-2].privilege; } break; @@ -1273,108 +1287,116 @@ case 26: #line 262 "gram.y" { struct privilege *p = ecalloc(1, sizeof(*p)); - list2tq(&p->hostlist, yyvsp[-2].member); - list2tq(&p->cmndlist, yyvsp[0].cmndspec); - p->prev = p; - /* p->next = NULL; */ + HLTQ_TO_TAILQ(&p->hostlist, yyvsp[-2].member, entries); + HLTQ_TO_TAILQ(&p->cmndlist, yyvsp[0].cmndspec, entries); + HLTQ_INIT(p, entries); yyval.privilege = p; } break; case 27: -#line 272 "gram.y" +#line 271 "gram.y" { yyval.member = yyvsp[0].member; yyval.member->negated = false; } break; case 28: -#line 276 "gram.y" +#line 275 "gram.y" { yyval.member = yyvsp[0].member; yyval.member->negated = true; } break; case 29: -#line 282 "gram.y" +#line 281 "gram.y" { yyval.member = new_member(yyvsp[0].string, ALIAS); } break; case 30: -#line 285 "gram.y" +#line 284 "gram.y" { yyval.member = new_member(NULL, ALL); } break; case 31: -#line 288 "gram.y" +#line 287 "gram.y" { yyval.member = new_member(yyvsp[0].string, NETGROUP); } break; case 32: -#line 291 "gram.y" +#line 290 "gram.y" { yyval.member = new_member(yyvsp[0].string, NTWKADDR); } break; case 33: -#line 294 "gram.y" +#line 293 "gram.y" { yyval.member = new_member(yyvsp[0].string, WORD); } break; case 35: -#line 300 "gram.y" +#line 299 "gram.y" { - list_append(yyvsp[-2].cmndspec, yyvsp[0].cmndspec); + struct cmndspec *prev; + prev = HLTQ_LAST(yyvsp[-2].cmndspec, cmndspec, entries); + HLTQ_CONCAT(yyvsp[-2].cmndspec, yyvsp[0].cmndspec, entries); #ifdef HAVE_SELINUX /* propagate role and type */ if (yyvsp[0].cmndspec->role == NULL) - yyvsp[0].cmndspec->role = yyvsp[0].cmndspec->prev->role; + yyvsp[0].cmndspec->role = prev->role; if (yyvsp[0].cmndspec->type == NULL) - yyvsp[0].cmndspec->type = yyvsp[0].cmndspec->prev->type; + yyvsp[0].cmndspec->type = prev->type; #endif /* HAVE_SELINUX */ #ifdef HAVE_PRIV_SET /* propagate privs & limitprivs */ if (yyvsp[0].cmndspec->privs == NULL) - yyvsp[0].cmndspec->privs = yyvsp[0].cmndspec->prev->privs; + yyvsp[0].cmndspec->privs = prev->privs; if (yyvsp[0].cmndspec->limitprivs == NULL) - yyvsp[0].cmndspec->limitprivs = yyvsp[0].cmndspec->prev->limitprivs; + yyvsp[0].cmndspec->limitprivs = prev->limitprivs; #endif /* HAVE_PRIV_SET */ /* propagate tags and runas list */ if (yyvsp[0].cmndspec->tags.nopasswd == UNSPEC) - yyvsp[0].cmndspec->tags.nopasswd = yyvsp[0].cmndspec->prev->tags.nopasswd; + yyvsp[0].cmndspec->tags.nopasswd = prev->tags.nopasswd; if (yyvsp[0].cmndspec->tags.noexec == UNSPEC) - yyvsp[0].cmndspec->tags.noexec = yyvsp[0].cmndspec->prev->tags.noexec; + yyvsp[0].cmndspec->tags.noexec = prev->tags.noexec; if (yyvsp[0].cmndspec->tags.setenv == UNSPEC && - yyvsp[0].cmndspec->prev->tags.setenv != IMPLIED) - yyvsp[0].cmndspec->tags.setenv = yyvsp[0].cmndspec->prev->tags.setenv; + prev->tags.setenv != IMPLIED) + yyvsp[0].cmndspec->tags.setenv = prev->tags.setenv; if (yyvsp[0].cmndspec->tags.log_input == UNSPEC) - yyvsp[0].cmndspec->tags.log_input = yyvsp[0].cmndspec->prev->tags.log_input; + yyvsp[0].cmndspec->tags.log_input = prev->tags.log_input; if (yyvsp[0].cmndspec->tags.log_output == UNSPEC) - yyvsp[0].cmndspec->tags.log_output = yyvsp[0].cmndspec->prev->tags.log_output; - if ((tq_empty(&yyvsp[0].cmndspec->runasuserlist) && - tq_empty(&yyvsp[0].cmndspec->runasgrouplist)) && - (!tq_empty(&yyvsp[0].cmndspec->prev->runasuserlist) || - !tq_empty(&yyvsp[0].cmndspec->prev->runasgrouplist))) { - yyvsp[0].cmndspec->runasuserlist = yyvsp[0].cmndspec->prev->runasuserlist; - yyvsp[0].cmndspec->runasgrouplist = yyvsp[0].cmndspec->prev->runasgrouplist; + yyvsp[0].cmndspec->tags.log_output = prev->tags.log_output; + if ((yyvsp[0].cmndspec->runasuserlist == NULL && + yyvsp[0].cmndspec->runasgrouplist == NULL) && + (prev->runasuserlist != NULL || + prev->runasgrouplist != NULL)) { + yyvsp[0].cmndspec->runasuserlist = prev->runasuserlist; + yyvsp[0].cmndspec->runasgrouplist = prev->runasgrouplist; } yyval.cmndspec = yyvsp[-2].cmndspec; } break; case 36: -#line 339 "gram.y" +#line 340 "gram.y" { struct cmndspec *cs = ecalloc(1, sizeof(*cs)); if (yyvsp[-4].runas != NULL) { - list2tq(&cs->runasuserlist, yyvsp[-4].runas->runasusers); - list2tq(&cs->runasgrouplist, yyvsp[-4].runas->runasgroups); + if (yyvsp[-4].runas->runasusers != NULL) { + cs->runasuserlist = + emalloc(sizeof(*cs->runasuserlist)); + HLTQ_TO_TAILQ(cs->runasuserlist, + yyvsp[-4].runas->runasusers, entries); + } + if (yyvsp[-4].runas->runasgroups != NULL) { + cs->runasgrouplist = + emalloc(sizeof(*cs->runasgrouplist)); + HLTQ_TO_TAILQ(cs->runasgrouplist, + yyvsp[-4].runas->runasgroups, entries); + } efree(yyvsp[-4].runas); - } else { - tq_init(&cs->runasuserlist); - tq_init(&cs->runasgrouplist); } #ifdef HAVE_SELINUX cs->role = yyvsp[-3].seinfo.role; @@ -1386,8 +1408,7 @@ case 36: #endif cs->tags = yyvsp[-1].tag; cs->cmnd = yyvsp[0].member; - cs->prev = cs; - cs->next = NULL; + HLTQ_INIT(cs, entries); /* sudo "ALL" implies the SETENV tag */ if (cs->cmnd->type == ALL && !cs->cmnd->negated && cs->tags.setenv == UNSPEC) @@ -1396,37 +1417,37 @@ case 36: } break; case 37: -#line 369 "gram.y" +#line 376 "gram.y" { yyval.digest = new_digest(SUDO_DIGEST_SHA224, yyvsp[0].string); } break; case 38: -#line 372 "gram.y" +#line 379 "gram.y" { yyval.digest = new_digest(SUDO_DIGEST_SHA256, yyvsp[0].string); } break; case 39: -#line 375 "gram.y" +#line 382 "gram.y" { yyval.digest = new_digest(SUDO_DIGEST_SHA384, yyvsp[0].string); } break; case 40: -#line 378 "gram.y" +#line 385 "gram.y" { yyval.digest = new_digest(SUDO_DIGEST_SHA512, yyvsp[0].string); } break; case 41: -#line 383 "gram.y" +#line 390 "gram.y" { yyval.member = yyvsp[0].member; } break; case 42: -#line 386 "gram.y" +#line 393 "gram.y" { /* XXX - yuck */ struct sudo_command *c = (struct sudo_command *)(yyvsp[0].member->name); @@ -1435,127 +1456,127 @@ case 42: } break; case 43: -#line 394 "gram.y" +#line 401 "gram.y" { yyval.member = yyvsp[0].member; yyval.member->negated = false; } break; case 44: -#line 398 "gram.y" +#line 405 "gram.y" { yyval.member = yyvsp[0].member; yyval.member->negated = true; } break; case 45: -#line 404 "gram.y" +#line 411 "gram.y" { yyval.string = yyvsp[0].string; } break; case 46: -#line 409 "gram.y" +#line 416 "gram.y" { yyval.string = yyvsp[0].string; } break; case 47: -#line 414 "gram.y" +#line 421 "gram.y" { yyval.seinfo.role = NULL; yyval.seinfo.type = NULL; } break; case 48: -#line 418 "gram.y" +#line 425 "gram.y" { yyval.seinfo.role = yyvsp[0].string; yyval.seinfo.type = NULL; } break; case 49: -#line 422 "gram.y" +#line 429 "gram.y" { yyval.seinfo.type = yyvsp[0].string; yyval.seinfo.role = NULL; } break; case 50: -#line 426 "gram.y" +#line 433 "gram.y" { yyval.seinfo.role = yyvsp[-1].string; yyval.seinfo.type = yyvsp[0].string; } break; case 51: -#line 430 "gram.y" +#line 437 "gram.y" { yyval.seinfo.type = yyvsp[-1].string; yyval.seinfo.role = yyvsp[0].string; } break; case 52: -#line 436 "gram.y" +#line 443 "gram.y" { yyval.string = yyvsp[0].string; } break; case 53: -#line 440 "gram.y" +#line 447 "gram.y" { yyval.string = yyvsp[0].string; } break; case 54: -#line 445 "gram.y" +#line 452 "gram.y" { yyval.privinfo.privs = NULL; yyval.privinfo.limitprivs = NULL; } break; case 55: -#line 449 "gram.y" +#line 456 "gram.y" { yyval.privinfo.privs = yyvsp[0].string; yyval.privinfo.limitprivs = NULL; } break; case 56: -#line 453 "gram.y" +#line 460 "gram.y" { yyval.privinfo.privs = NULL; yyval.privinfo.limitprivs = yyvsp[0].string; } break; case 57: -#line 457 "gram.y" +#line 464 "gram.y" { yyval.privinfo.privs = yyvsp[-1].string; yyval.privinfo.limitprivs = yyvsp[0].string; } break; case 58: -#line 461 "gram.y" +#line 468 "gram.y" { yyval.privinfo.limitprivs = yyvsp[-1].string; yyval.privinfo.privs = yyvsp[0].string; } break; case 59: -#line 467 "gram.y" +#line 474 "gram.y" { yyval.runas = NULL; } break; case 60: -#line 470 "gram.y" +#line 477 "gram.y" { yyval.runas = yyvsp[-1].runas; } break; case 61: -#line 475 "gram.y" +#line 482 "gram.y" { yyval.runas = ecalloc(1, sizeof(struct runascontainer)); yyval.runas->runasusers = new_member(NULL, MYSELF); @@ -1563,7 +1584,7 @@ case 61: } break; case 62: -#line 480 "gram.y" +#line 487 "gram.y" { yyval.runas = ecalloc(1, sizeof(struct runascontainer)); yyval.runas->runasusers = yyvsp[0].member; @@ -1571,7 +1592,7 @@ case 62: } break; case 63: -#line 485 "gram.y" +#line 492 "gram.y" { yyval.runas = ecalloc(1, sizeof(struct runascontainer)); yyval.runas->runasusers = yyvsp[-2].member; @@ -1579,7 +1600,7 @@ case 63: } break; case 64: -#line 490 "gram.y" +#line 497 "gram.y" { yyval.runas = ecalloc(1, sizeof(struct runascontainer)); /* $$->runasusers = NULL; */ @@ -1587,7 +1608,7 @@ case 64: } break; case 65: -#line 495 "gram.y" +#line 502 "gram.y" { yyval.runas = ecalloc(1, sizeof(struct runascontainer)); yyval.runas->runasusers = new_member(NULL, MYSELF); @@ -1595,86 +1616,86 @@ case 65: } break; case 66: -#line 502 "gram.y" +#line 509 "gram.y" { yyval.tag.nopasswd = yyval.tag.noexec = yyval.tag.setenv = yyval.tag.log_input = yyval.tag.log_output = UNSPEC; } break; case 67: -#line 506 "gram.y" +#line 513 "gram.y" { yyval.tag.nopasswd = true; } break; case 68: -#line 509 "gram.y" +#line 516 "gram.y" { yyval.tag.nopasswd = false; } break; case 69: -#line 512 "gram.y" +#line 519 "gram.y" { yyval.tag.noexec = true; } break; case 70: -#line 515 "gram.y" +#line 522 "gram.y" { yyval.tag.noexec = false; } break; case 71: -#line 518 "gram.y" +#line 525 "gram.y" { yyval.tag.setenv = true; } break; case 72: -#line 521 "gram.y" +#line 528 "gram.y" { yyval.tag.setenv = false; } break; case 73: -#line 524 "gram.y" +#line 531 "gram.y" { yyval.tag.log_input = true; } break; case 74: -#line 527 "gram.y" +#line 534 "gram.y" { yyval.tag.log_input = false; } break; case 75: -#line 530 "gram.y" +#line 537 "gram.y" { yyval.tag.log_output = true; } break; case 76: -#line 533 "gram.y" +#line 540 "gram.y" { yyval.tag.log_output = false; } break; case 77: -#line 538 "gram.y" +#line 545 "gram.y" { yyval.member = new_member(NULL, ALL); } break; case 78: -#line 541 "gram.y" +#line 548 "gram.y" { yyval.member = new_member(yyvsp[0].string, ALIAS); } break; case 79: -#line 544 "gram.y" +#line 551 "gram.y" { struct sudo_command *c = ecalloc(1, sizeof(*c)); c->cmnd = yyvsp[0].command.cmnd; @@ -1683,7 +1704,7 @@ case 79: } break; case 82: -#line 556 "gram.y" +#line 563 "gram.y" { char *s; if ((s = alias_add(yyvsp[-2].string, HOSTALIAS, yyvsp[0].member)) != NULL) { @@ -1693,14 +1714,14 @@ case 82: } break; case 84: -#line 566 "gram.y" +#line 573 "gram.y" { - list_append(yyvsp[-2].member, yyvsp[0].member); + HLTQ_CONCAT(yyvsp[-2].member, yyvsp[0].member, entries); yyval.member = yyvsp[-2].member; } break; case 87: -#line 576 "gram.y" +#line 583 "gram.y" { char *s; if ((s = alias_add(yyvsp[-2].string, CMNDALIAS, yyvsp[0].member)) != NULL) { @@ -1710,14 +1731,14 @@ case 87: } break; case 89: -#line 586 "gram.y" +#line 593 "gram.y" { - list_append(yyvsp[-2].member, yyvsp[0].member); + HLTQ_CONCAT(yyvsp[-2].member, yyvsp[0].member, entries); yyval.member = yyvsp[-2].member; } break; case 92: -#line 596 "gram.y" +#line 603 "gram.y" { char *s; if ((s = alias_add(yyvsp[-2].string, RUNASALIAS, yyvsp[0].member)) != NULL) { @@ -1727,7 +1748,7 @@ case 92: } break; case 95: -#line 609 "gram.y" +#line 616 "gram.y" { char *s; if ((s = alias_add(yyvsp[-2].string, USERALIAS, yyvsp[0].member)) != NULL) { @@ -1737,96 +1758,96 @@ case 95: } break; case 97: -#line 619 "gram.y" +#line 626 "gram.y" { - list_append(yyvsp[-2].member, yyvsp[0].member); + HLTQ_CONCAT(yyvsp[-2].member, yyvsp[0].member, entries); yyval.member = yyvsp[-2].member; } break; case 98: -#line 625 "gram.y" +#line 632 "gram.y" { yyval.member = yyvsp[0].member; yyval.member->negated = false; } break; case 99: -#line 629 "gram.y" +#line 636 "gram.y" { yyval.member = yyvsp[0].member; yyval.member->negated = true; } break; case 100: -#line 635 "gram.y" +#line 642 "gram.y" { yyval.member = new_member(yyvsp[0].string, ALIAS); } break; case 101: -#line 638 "gram.y" +#line 645 "gram.y" { yyval.member = new_member(NULL, ALL); } break; case 102: -#line 641 "gram.y" +#line 648 "gram.y" { yyval.member = new_member(yyvsp[0].string, NETGROUP); } break; case 103: -#line 644 "gram.y" +#line 651 "gram.y" { yyval.member = new_member(yyvsp[0].string, USERGROUP); } break; case 104: -#line 647 "gram.y" +#line 654 "gram.y" { yyval.member = new_member(yyvsp[0].string, WORD); } break; case 106: -#line 653 "gram.y" +#line 660 "gram.y" { - list_append(yyvsp[-2].member, yyvsp[0].member); + HLTQ_CONCAT(yyvsp[-2].member, yyvsp[0].member, entries); yyval.member = yyvsp[-2].member; } break; case 107: -#line 659 "gram.y" +#line 666 "gram.y" { yyval.member = yyvsp[0].member; yyval.member->negated = false; } break; case 108: -#line 663 "gram.y" +#line 670 "gram.y" { yyval.member = yyvsp[0].member; yyval.member->negated = true; } break; case 109: -#line 669 "gram.y" +#line 676 "gram.y" { yyval.member = new_member(yyvsp[0].string, ALIAS); } break; case 110: -#line 672 "gram.y" +#line 679 "gram.y" { yyval.member = new_member(NULL, ALL); } break; case 111: -#line 675 "gram.y" +#line 682 "gram.y" { yyval.member = new_member(yyvsp[0].string, WORD); } break; -#line 1777 "gram.c" +#line 1798 "gram.c" } yyssp -= yym; yystate = *yyssp; diff --git a/plugins/sudoers/gram.y b/plugins/sudoers/gram.y index 0642802b5..6b4212ce4 100644 --- a/plugins/sudoers/gram.y +++ b/plugins/sudoers/gram.y @@ -79,8 +79,8 @@ bool parse_error = false; int errorlineno = -1; char *errorfile = NULL; -struct defaults_list defaults; -struct userspec_list userspecs; +struct defaults_list defaults = TAILQ_HEAD_INITIALIZER(defaults); +struct userspec_list userspecs = TAILQ_HEAD_INITIALIZER(userspecs); /* * Local protoypes @@ -230,7 +230,7 @@ entry : COMMENT { defaults_list : defaults_entry | defaults_list ',' defaults_entry { - list_append($1, $3); + HLTQ_CONCAT($1, $3, entries); $$ = $1; } ; @@ -254,17 +254,16 @@ defaults_entry : DEFVAR { privileges : privilege | privileges ':' privilege { - list_append($1, $3); + HLTQ_CONCAT($1, $3, entries); $$ = $1; } ; privilege : hostlist '=' cmndspeclist { struct privilege *p = ecalloc(1, sizeof(*p)); - list2tq(&p->hostlist, $1); - list2tq(&p->cmndlist, $3); - p->prev = p; - /* p->next = NULL; */ + HLTQ_TO_TAILQ(&p->hostlist, $1, entries); + HLTQ_TO_TAILQ(&p->cmndlist, $3, entries); + HLTQ_INIT(p, entries); $$ = p; } ; @@ -298,39 +297,41 @@ host : ALIAS { cmndspeclist : cmndspec | cmndspeclist ',' cmndspec { - list_append($1, $3); + struct cmndspec *prev; + prev = HLTQ_LAST($1, cmndspec, entries); + HLTQ_CONCAT($1, $3, entries); #ifdef HAVE_SELINUX /* propagate role and type */ if ($3->role == NULL) - $3->role = $3->prev->role; + $3->role = prev->role; if ($3->type == NULL) - $3->type = $3->prev->type; + $3->type = prev->type; #endif /* HAVE_SELINUX */ #ifdef HAVE_PRIV_SET /* propagate privs & limitprivs */ if ($3->privs == NULL) - $3->privs = $3->prev->privs; + $3->privs = prev->privs; if ($3->limitprivs == NULL) - $3->limitprivs = $3->prev->limitprivs; + $3->limitprivs = prev->limitprivs; #endif /* HAVE_PRIV_SET */ /* propagate tags and runas list */ if ($3->tags.nopasswd == UNSPEC) - $3->tags.nopasswd = $3->prev->tags.nopasswd; + $3->tags.nopasswd = prev->tags.nopasswd; if ($3->tags.noexec == UNSPEC) - $3->tags.noexec = $3->prev->tags.noexec; + $3->tags.noexec = prev->tags.noexec; if ($3->tags.setenv == UNSPEC && - $3->prev->tags.setenv != IMPLIED) - $3->tags.setenv = $3->prev->tags.setenv; + prev->tags.setenv != IMPLIED) + $3->tags.setenv = prev->tags.setenv; if ($3->tags.log_input == UNSPEC) - $3->tags.log_input = $3->prev->tags.log_input; + $3->tags.log_input = prev->tags.log_input; if ($3->tags.log_output == UNSPEC) - $3->tags.log_output = $3->prev->tags.log_output; - if ((tq_empty(&$3->runasuserlist) && - tq_empty(&$3->runasgrouplist)) && - (!tq_empty(&$3->prev->runasuserlist) || - !tq_empty(&$3->prev->runasgrouplist))) { - $3->runasuserlist = $3->prev->runasuserlist; - $3->runasgrouplist = $3->prev->runasgrouplist; + $3->tags.log_output = prev->tags.log_output; + if (($3->runasuserlist == NULL && + $3->runasgrouplist == NULL) && + (prev->runasuserlist != NULL || + prev->runasgrouplist != NULL)) { + $3->runasuserlist = prev->runasuserlist; + $3->runasgrouplist = prev->runasgrouplist; } $$ = $1; } @@ -339,12 +340,19 @@ cmndspeclist : cmndspec cmndspec : runasspec selinux solarisprivs cmndtag digcmnd { struct cmndspec *cs = ecalloc(1, sizeof(*cs)); if ($1 != NULL) { - list2tq(&cs->runasuserlist, $1->runasusers); - list2tq(&cs->runasgrouplist, $1->runasgroups); + if ($1->runasusers != NULL) { + cs->runasuserlist = + emalloc(sizeof(*cs->runasuserlist)); + HLTQ_TO_TAILQ(cs->runasuserlist, + $1->runasusers, entries); + } + if ($1->runasgroups != NULL) { + cs->runasgrouplist = + emalloc(sizeof(*cs->runasgrouplist)); + HLTQ_TO_TAILQ(cs->runasgrouplist, + $1->runasgroups, entries); + } efree($1); - } else { - tq_init(&cs->runasuserlist); - tq_init(&cs->runasgrouplist); } #ifdef HAVE_SELINUX cs->role = $2.role; @@ -356,8 +364,7 @@ cmndspec : runasspec selinux solarisprivs cmndtag digcmnd { #endif cs->tags = $4; cs->cmnd = $5; - cs->prev = cs; - cs->next = NULL; + HLTQ_INIT(cs, entries); /* sudo "ALL" implies the SETENV tag */ if (cs->cmnd->type == ALL && !cs->cmnd->negated && cs->tags.setenv == UNSPEC) @@ -564,7 +571,7 @@ hostalias : ALIAS '=' hostlist { hostlist : ophost | hostlist ',' ophost { - list_append($1, $3); + HLTQ_CONCAT($1, $3, entries); $$ = $1; } ; @@ -584,7 +591,7 @@ cmndalias : ALIAS '=' cmndlist { cmndlist : digcmnd | cmndlist ',' digcmnd { - list_append($1, $3); + HLTQ_CONCAT($1, $3, entries); $$ = $1; } ; @@ -617,7 +624,7 @@ useralias : ALIAS '=' userlist { userlist : opuser | userlist ',' opuser { - list_append($1, $3); + HLTQ_CONCAT($1, $3, entries); $$ = $1; } ; @@ -651,7 +658,7 @@ user : ALIAS { grouplist : opgroup | grouplist ',' opgroup { - list_append($1, $3); + HLTQ_CONCAT($1, $3, entries); $$ = $1; } ; @@ -719,11 +726,10 @@ new_default(char *var, char *val, int op) d = ecalloc(1, sizeof(struct defaults)); d->var = var; d->val = val; - tq_init(&d->binding); /* d->type = 0; */ d->op = op; - d->prev = d; - /* d->next = NULL; */ + /* d->binding = NULL */ + HLTQ_INIT(d, entries); debug_return_ptr(d); } @@ -737,8 +743,7 @@ new_member(char *name, int type) m = ecalloc(1, sizeof(struct member)); m->name = name; m->type = type; - m->prev = m; - /* m->next = NULL; */ + HLTQ_INIT(m, entries); debug_return_ptr(m); } @@ -765,30 +770,34 @@ static void add_defaults(int type, struct member *bmem, struct defaults *defs) { struct defaults *d; - struct member_list binding; + struct member_list *binding; debug_decl(add_defaults, SUDO_DEBUG_PARSER) /* - * We can only call list2tq once on bmem as it will zero - * out the prev pointer when it consumes bmem. + * We use a single binding for each entry in defs. */ - list2tq(&binding, bmem); + binding = emalloc(sizeof(*binding)); + if (bmem != NULL) + HLTQ_TO_TAILQ(binding, bmem, entries); + else + TAILQ_INIT(binding); /* * Set type and binding (who it applies to) for new entries. + * Then add to the global defaults list. */ - for (d = defs; d != NULL; d = d->next) { + HLTQ_FOREACH(d, defs, entries) { d->type = type; d->binding = binding; } - tq_append(&defaults, defs); + TAILQ_CONCAT_HLTQ(&defaults, defs, entries); debug_return; } /* * Allocate a new struct userspec, populate it, and insert it at the - * and of the userspecs list. + * end of the userspecs list. */ static void add_userspec(struct member *members, struct privilege *privs) @@ -797,11 +806,9 @@ add_userspec(struct member *members, struct privilege *privs) debug_decl(add_userspec, SUDO_DEBUG_PARSER) u = ecalloc(1, sizeof(*u)); - list2tq(&u->users, members); - list2tq(&u->privileges, privs); - u->prev = u; - /* u->next = NULL; */ - tq_append(&userspecs, u); + HLTQ_TO_TAILQ(&u->users, members, entries); + HLTQ_TO_TAILQ(&u->privileges, privs, entries); + TAILQ_INSERT_TAIL(&userspecs, u, entries); debug_return; } @@ -813,21 +820,24 @@ add_userspec(struct member *members, struct privilege *privs) void init_parser(const char *path, bool quiet) { + struct member_list *binding; + struct member *m; struct defaults *d; - struct member *m, *binding; struct userspec *us; struct privilege *priv; struct cmndspec *cs; struct sudo_command *c; debug_decl(init_parser, SUDO_DEBUG_PARSER) - while ((us = tq_pop(&userspecs)) != NULL) { - while ((m = tq_pop(&us->users)) != NULL) { + while ((us = TAILQ_FIRST(&userspecs)) != NULL) { + TAILQ_REMOVE(&userspecs, us, entries); + while ((m = TAILQ_FIRST(&us->users)) != NULL) { + TAILQ_REMOVE(&us->users, m, entries); efree(m->name); efree(m); } - while ((priv = tq_pop(&us->privileges)) != NULL) { - struct member *runasuser = NULL, *runasgroup = NULL; + while ((priv = TAILQ_FIRST(&us->privileges)) != NULL) { + struct member_list *runasuserlist = NULL, *runasgrouplist = NULL; #ifdef HAVE_SELINUX char *role = NULL, *type = NULL; #endif /* HAVE_SELINUX */ @@ -835,11 +845,14 @@ init_parser(const char *path, bool quiet) char *privs = NULL, *limitprivs = NULL; #endif /* HAVE_PRIV_SET */ - while ((m = tq_pop(&priv->hostlist)) != NULL) { + TAILQ_REMOVE(&us->privileges, priv, entries); + while ((m = TAILQ_FIRST(&priv->hostlist)) != NULL) { + TAILQ_REMOVE(&priv->hostlist, m, entries); efree(m->name); efree(m); } - while ((cs = tq_pop(&priv->cmndlist)) != NULL) { + while ((cs = TAILQ_FIRST(&priv->cmndlist)) != NULL) { + TAILQ_REMOVE(&priv->cmndlist, cs, entries); #ifdef HAVE_SELINUX /* Only free the first instance of a role/type. */ if (cs->role != role) { @@ -862,19 +875,24 @@ init_parser(const char *path, bool quiet) efree(cs->limitprivs); } #endif /* HAVE_PRIV_SET */ - if (tq_last(&cs->runasuserlist) != runasuser) { - runasuser = tq_last(&cs->runasuserlist); - while ((m = tq_pop(&cs->runasuserlist)) != NULL) { + /* Only free the first instance of runas user/group lists. */ + if (cs->runasuserlist && cs->runasuserlist != runasuserlist) { + runasuserlist = cs->runasuserlist; + while ((m = TAILQ_FIRST(runasuserlist)) != NULL) { + TAILQ_REMOVE(runasuserlist, m, entries); efree(m->name); efree(m); } + efree(runasuserlist); } - if (tq_last(&cs->runasgrouplist) != runasgroup) { - runasgroup = tq_last(&cs->runasgrouplist); - while ((m = tq_pop(&cs->runasgrouplist)) != NULL) { + if (cs->runasgrouplist && cs->runasgrouplist != runasgrouplist) { + runasgrouplist = cs->runasgrouplist; + while ((m = TAILQ_FIRST(runasgrouplist)) != NULL) { + TAILQ_REMOVE(runasgrouplist, m, entries); efree(m->name); efree(m); } + efree(runasgrouplist); } if (cs->cmnd->type == COMMAND) { c = (struct sudo_command *) cs->cmnd->name; @@ -889,13 +907,15 @@ init_parser(const char *path, bool quiet) } efree(us); } - tq_init(&userspecs); + TAILQ_INIT(&userspecs); binding = NULL; - while ((d = tq_pop(&defaults)) != NULL) { - if (tq_last(&d->binding) != binding) { - binding = tq_last(&d->binding); - while ((m = tq_pop(&d->binding)) != NULL) { + while ((d = TAILQ_FIRST(&defaults)) != NULL) { + TAILQ_REMOVE(&defaults, d, entries); + if (d->binding != binding) { + binding = d->binding; + while ((m = TAILQ_FIRST(d->binding)) != NULL) { + TAILQ_REMOVE(d->binding, m, entries); if (m->type == COMMAND) { c = (struct sudo_command *) m->name; efree(c->cmnd); @@ -904,12 +924,13 @@ init_parser(const char *path, bool quiet) efree(m->name); efree(m); } + efree(d->binding); } efree(d->var); efree(d->val); efree(d); } - tq_init(&defaults); + TAILQ_INIT(&defaults); init_aliases(); diff --git a/plugins/sudoers/match.c b/plugins/sudoers/match.c index dd7f8bc24..1e7892e53 100644 --- a/plugins/sudoers/match.c +++ b/plugins/sudoers/match.c @@ -91,7 +91,7 @@ #include "sha2.h" #include -static struct member_list empty; +static struct member_list empty = TAILQ_HEAD_INITIALIZER(empty); static bool command_matches_dir(char *, size_t); #ifndef SUDOERS_NAME_MATCH @@ -117,7 +117,7 @@ userlist_matches(struct passwd *pw, struct member_list *list) int rval, matched = UNSPEC; debug_decl(userlist_matches, SUDO_DEBUG_MATCH) - tq_foreach_rev(list, m) { + TAILQ_FOREACH_REVERSE(m, list, member_list, entries) { switch (m->type) { case ALL: matched = !m->negated; @@ -169,46 +169,48 @@ runaslist_matches(struct member_list *user_list, if (runas_pw != NULL) { /* If no runas user or runas group listed in sudoers, use default. */ - if (tq_empty(user_list) && tq_empty(group_list)) + if (user_list == NULL && group_list == NULL) debug_return_int(userpw_matches(def_runas_default, runas_pw->pw_name, runas_pw)); - tq_foreach_rev(user_list, m) { - switch (m->type) { - case ALL: - user_matched = !m->negated; - break; - case NETGROUP: - if (netgr_matches(m->name, NULL, NULL, runas_pw->pw_name)) - user_matched = !m->negated; - break; - case USERGROUP: - if (usergr_matches(m->name, runas_pw->pw_name, runas_pw)) + if (user_list != NULL) { + TAILQ_FOREACH_REVERSE(m, user_list, member_list, entries) { + switch (m->type) { + case ALL: user_matched = !m->negated; - break; - case ALIAS: - if ((a = alias_get(m->name, RUNASALIAS)) != NULL) { - rval = runaslist_matches(&a->members, &empty, - matching_user, NULL); - if (rval != UNSPEC) - user_matched = m->negated ? !rval : rval; - alias_put(a); break; - } - /* FALLTHROUGH */ - case WORD: - if (userpw_matches(m->name, runas_pw->pw_name, runas_pw)) - user_matched = !m->negated; - break; - case MYSELF: - if (!ISSET(sudo_user.flags, RUNAS_USER_SPECIFIED) || - strcmp(user_name, runas_pw->pw_name) == 0) - user_matched = !m->negated; + case NETGROUP: + if (netgr_matches(m->name, NULL, NULL, runas_pw->pw_name)) + user_matched = !m->negated; + break; + case USERGROUP: + if (usergr_matches(m->name, runas_pw->pw_name, runas_pw)) + user_matched = !m->negated; + break; + case ALIAS: + if ((a = alias_get(m->name, RUNASALIAS)) != NULL) { + rval = runaslist_matches(&a->members, &empty, + matching_user, NULL); + if (rval != UNSPEC) + user_matched = m->negated ? !rval : rval; + alias_put(a); + break; + } + /* FALLTHROUGH */ + case WORD: + if (userpw_matches(m->name, runas_pw->pw_name, runas_pw)) + user_matched = !m->negated; + break; + case MYSELF: + if (!ISSET(sudo_user.flags, RUNAS_USER_SPECIFIED) || + strcmp(user_name, runas_pw->pw_name) == 0) + user_matched = !m->negated; + break; + } + if (user_matched != UNSPEC) { + if (matching_user != NULL && m->type != ALIAS) + *matching_user = m; break; - } - if (user_matched != UNSPEC) { - if (matching_user != NULL && m->type != ALIAS) - *matching_user = m; - break; + } } } } @@ -218,30 +220,32 @@ runaslist_matches(struct member_list *user_list, if (runas_pw == NULL || strcmp(runas_pw->pw_name, user_name) == 0) user_matched = ALLOW; /* only changing group */ } - tq_foreach_rev(group_list, m) { - switch (m->type) { - case ALL: - group_matched = !m->negated; - break; - case ALIAS: - if ((a = alias_get(m->name, RUNASALIAS)) != NULL) { - rval = runaslist_matches(&empty, &a->members, - NULL, matching_group); - if (rval != UNSPEC) - group_matched = m->negated ? !rval : rval; - alias_put(a); - break; - } - /* FALLTHROUGH */ - case WORD: - if (group_matches(m->name, runas_gr)) + if (group_list != NULL) { + TAILQ_FOREACH_REVERSE(m, group_list, member_list, entries) { + switch (m->type) { + case ALL: group_matched = !m->negated; + break; + case ALIAS: + if ((a = alias_get(m->name, RUNASALIAS)) != NULL) { + rval = runaslist_matches(&empty, &a->members, + NULL, matching_group); + if (rval != UNSPEC) + group_matched = m->negated ? !rval : rval; + alias_put(a); + break; + } + /* FALLTHROUGH */ + case WORD: + if (group_matches(m->name, runas_gr)) + group_matched = !m->negated; + break; + } + if (group_matched != UNSPEC) { + if (matching_group != NULL && m->type != ALIAS) + *matching_group = m; break; - } - if (group_matched != UNSPEC) { - if (matching_group != NULL && m->type != ALIAS) - *matching_group = m; - break; + } } } if (group_matched == UNSPEC) { @@ -269,7 +273,7 @@ hostlist_matches(struct member_list *list) int rval, matched = UNSPEC; debug_decl(hostlist_matches, SUDO_DEBUG_MATCH) - tq_foreach_rev(list, m) { + TAILQ_FOREACH_REVERSE(m, list, member_list, entries) { switch (m->type) { case ALL: matched = !m->negated; @@ -313,7 +317,7 @@ cmndlist_matches(struct member_list *list) int matched = UNSPEC; debug_decl(cmndlist_matches, SUDO_DEBUG_MATCH) - tq_foreach_rev(list, m) { + TAILQ_FOREACH_REVERSE(m, list, member_list, entries) { matched = cmnd_matches(m); if (matched != UNSPEC) break; diff --git a/plugins/sudoers/parse.c b/plugins/sudoers/parse.c index f91e41308..4daf9ab54 100644 --- a/plugins/sudoers/parse.c +++ b/plugins/sudoers/parse.c @@ -181,13 +181,13 @@ sudo_file_lookup(struct sudo_nss *nss, int validated, int pwflag) CLR(validated, FLAG_NO_USER); CLR(validated, FLAG_NO_HOST); match = DENY; - tq_foreach_fwd(&userspecs, us) { + TAILQ_FOREACH(us, &userspecs, entries) { if (userlist_matches(sudo_user.pw, &us->users) != ALLOW) continue; - tq_foreach_fwd(&us->privileges, priv) { + TAILQ_FOREACH(priv, &us->privileges, entries) { if (hostlist_matches(&priv->hostlist) != ALLOW) continue; - tq_foreach_fwd(&priv->cmndlist, cs) { + TAILQ_FOREACH(cs, &priv->cmndlist, entries) { /* Only check the command when listing another user. */ if (user_uid == 0 || list_pw == NULL || user_uid == list_pw->pw_uid || @@ -215,20 +215,20 @@ sudo_file_lookup(struct sudo_nss *nss, int validated, int pwflag) set_perms(PERM_RUNAS); match = UNSPEC; - tq_foreach_rev(&userspecs, us) { + TAILQ_FOREACH_REVERSE(us, &userspecs, userspec_list, entries) { if (userlist_matches(sudo_user.pw, &us->users) != ALLOW) continue; CLR(validated, FLAG_NO_USER); - tq_foreach_rev(&us->privileges, priv) { + TAILQ_FOREACH_REVERSE(priv, &us->privileges, privilege_list, entries) { host_match = hostlist_matches(&priv->hostlist); if (host_match == ALLOW) CLR(validated, FLAG_NO_HOST); else continue; - tq_foreach_rev(&priv->cmndlist, cs) { + TAILQ_FOREACH_REVERSE(cs, &priv->cmndlist, cmndspec_list, entries) { matching_user = NULL; - runas_match = runaslist_matches(&cs->runasuserlist, - &cs->runasgrouplist, &matching_user, NULL); + runas_match = runaslist_matches(cs->runasuserlist, + cs->runasgrouplist, &matching_user, NULL); if (runas_match == ALLOW) { cmnd_match = cmnd_matches(cs->cmnd); if (cmnd_match != UNSPEC) { @@ -340,10 +340,8 @@ sudo_file_append_cmnd(struct cmndspec *cs, struct cmndtag *tags, #define RUNAS_CHANGED(cs1, cs2) \ (cs1 == NULL || cs2 == NULL || \ - cs1->runasuserlist.first != cs2->runasuserlist.first || \ - cs1->runasuserlist.last != cs2->runasuserlist.last || \ - cs1->runasgrouplist.first != cs2->runasgrouplist.first || \ - cs1->runasgrouplist.last != cs2->runasgrouplist.last) + cs1->runasuserlist != cs2->runasuserlist || \ + cs1->runasgrouplist != cs2->runasgrouplist) static int sudo_file_display_priv_short(struct passwd *pw, struct userspec *us, @@ -362,30 +360,30 @@ sudo_file_display_priv_short(struct passwd *pw, struct userspec *us, tags.nopasswd = UNSPEC; tags.log_input = UNSPEC; tags.log_output = UNSPEC; - tq_foreach_fwd(&us->privileges, priv) { + TAILQ_FOREACH(priv, &us->privileges, entries) { if (hostlist_matches(&priv->hostlist) != ALLOW) continue; prev_cs = NULL; - tq_foreach_fwd(&priv->cmndlist, cs) { + TAILQ_FOREACH(cs, &priv->cmndlist, entries) { if (RUNAS_CHANGED(cs, prev_cs)) { - if (cs != tq_first(&priv->cmndlist)) + if (cs != TAILQ_FIRST(&priv->cmndlist)) lbuf_append(lbuf, "\n"); lbuf_append(lbuf, " ("); - if (!tq_empty(&cs->runasuserlist)) { - tq_foreach_fwd(&cs->runasuserlist, m) { - if (m != tq_first(&cs->runasuserlist)) + if (cs->runasuserlist != NULL) { + TAILQ_FOREACH(m, cs->runasuserlist, entries) { + if (m != TAILQ_FIRST(cs->runasuserlist)) lbuf_append(lbuf, ", "); print_member(lbuf, m, RUNASALIAS); } - } else if (tq_empty(&cs->runasgrouplist)) { + } else if (cs->runasgrouplist == NULL) { lbuf_append(lbuf, "%s", def_runas_default); } else { lbuf_append(lbuf, "%s", pw->pw_name); } - if (!tq_empty(&cs->runasgrouplist)) { + if (cs->runasgrouplist != NULL) { lbuf_append(lbuf, " : "); - tq_foreach_fwd(&cs->runasgrouplist, m) { - if (m != tq_first(&cs->runasgrouplist)) + TAILQ_FOREACH(m, cs->runasgrouplist, entries) { + if (m != TAILQ_FIRST(cs->runasgrouplist)) lbuf_append(lbuf, ", "); print_member(lbuf, m, RUNASALIAS); } @@ -396,7 +394,7 @@ sudo_file_display_priv_short(struct passwd *pw, struct userspec *us, tags.nopasswd = UNSPEC; tags.log_input = UNSPEC; tags.log_output = UNSPEC; - } else if (cs != tq_first(&priv->cmndlist)) { + } else if (cs != TAILQ_FIRST(&priv->cmndlist)) { lbuf_append(lbuf, ", "); } sudo_file_append_cmnd(cs, &tags, lbuf); @@ -452,30 +450,30 @@ sudo_file_display_priv_long(struct passwd *pw, struct userspec *us, int nfound = 0, olen; debug_decl(sudo_file_display_priv_long, SUDO_DEBUG_NSS) - tq_foreach_fwd(&us->privileges, priv) { + TAILQ_FOREACH(priv, &us->privileges, entries) { if (hostlist_matches(&priv->hostlist) != ALLOW) continue; prev_cs = NULL; - tq_foreach_fwd(&priv->cmndlist, cs) { + TAILQ_FOREACH(cs, &priv->cmndlist, entries) { if (new_long_entry(cs, prev_cs)) { lbuf_append(lbuf, _("\nSudoers entry:\n")); lbuf_append(lbuf, _(" RunAsUsers: ")); - if (!tq_empty(&cs->runasuserlist)) { - tq_foreach_fwd(&cs->runasuserlist, m) { - if (m != tq_first(&cs->runasuserlist)) + if (cs->runasuserlist != NULL) { + TAILQ_FOREACH(m, cs->runasuserlist, entries) { + if (m != TAILQ_FIRST(cs->runasuserlist)) lbuf_append(lbuf, ", "); print_member(lbuf, m, RUNASALIAS); } - } else if (tq_empty(&cs->runasgrouplist)) { + } else if (cs->runasgrouplist == NULL) { lbuf_append(lbuf, "%s", def_runas_default); } else { lbuf_append(lbuf, "%s", pw->pw_name); } lbuf_append(lbuf, "\n"); - if (!tq_empty(&cs->runasgrouplist)) { + if (cs->runasgrouplist != NULL) { lbuf_append(lbuf, _(" RunAsGroups: ")); - tq_foreach_fwd(&cs->runasgrouplist, m) { - if (m != tq_first(&cs->runasgrouplist)) + TAILQ_FOREACH(m, cs->runasgrouplist, entries) { + if (m != TAILQ_FIRST(cs->runasgrouplist)) lbuf_append(lbuf, ", "); print_member(lbuf, m, RUNASALIAS); } @@ -534,7 +532,7 @@ sudo_file_display_privs(struct sudo_nss *nss, struct passwd *pw, if (nss->handle == NULL) goto done; - tq_foreach_fwd(&userspecs, us) { + TAILQ_FOREACH(us, &userspecs, entries) { if (userlist_matches(pw, &us->users) != ALLOW) continue; @@ -567,14 +565,14 @@ sudo_file_display_defaults(struct sudo_nss *nss, struct passwd *pw, else prefix = ", "; - tq_foreach_fwd(&defaults, d) { + TAILQ_FOREACH(d, &defaults, entries) { switch (d->type) { case DEFAULTS_HOST: - if (hostlist_matches(&d->binding) != ALLOW) + if (hostlist_matches(d->binding) != ALLOW) continue; break; case DEFAULTS_USER: - if (userlist_matches(pw, &d->binding) != ALLOW) + if (userlist_matches(pw, d->binding) != ALLOW) continue; break; case DEFAULTS_RUNAS: @@ -624,7 +622,8 @@ static int display_bound_defaults(int dtype, struct lbuf *lbuf) { struct defaults *d; - struct member *m, *binding = NULL; + struct member_list *binding = NULL; + struct member *m; char *dsep; int atype, nfound = 0; debug_decl(display_bound_defaults, SUDO_DEBUG_NSS) @@ -649,18 +648,18 @@ display_bound_defaults(int dtype, struct lbuf *lbuf) default: debug_return_int(-1); } - tq_foreach_fwd(&defaults, d) { + TAILQ_FOREACH(d, &defaults, entries) { if (d->type != dtype) continue; nfound++; - if (binding != tq_first(&d->binding)) { - binding = tq_first(&d->binding); + if (binding != d->binding) { + binding = d->binding; if (nfound != 1) lbuf_append(lbuf, "\n"); lbuf_append(lbuf, " Defaults%s", dsep); - for (m = binding; m != NULL; m = m->next) { - if (m != binding) + TAILQ_FOREACH(m, binding, entries) { + if (m != TAILQ_FIRST(binding)) lbuf_append(lbuf, ","); print_member(lbuf, m, atype); lbuf_append(lbuf, " "); @@ -692,17 +691,17 @@ sudo_file_display_cmnd(struct sudo_nss *nss, struct passwd *pw) goto done; match = NULL; - tq_foreach_rev(&userspecs, us) { + TAILQ_FOREACH_REVERSE(us, &userspecs, userspec_list, entries) { if (userlist_matches(pw, &us->users) != ALLOW) continue; - tq_foreach_rev(&us->privileges, priv) { + TAILQ_FOREACH_REVERSE(priv, &us->privileges, privilege_list, entries) { host_match = hostlist_matches(&priv->hostlist); if (host_match != ALLOW) continue; - tq_foreach_rev(&priv->cmndlist, cs) { - runas_match = runaslist_matches(&cs->runasuserlist, - &cs->runasgrouplist, NULL, NULL); + TAILQ_FOREACH_REVERSE(cs, &priv->cmndlist, cmndspec_list, entries) { + runas_match = runaslist_matches(cs->runasuserlist, + cs->runasgrouplist, NULL, NULL); if (runas_match == ALLOW) { cmnd_match = cmnd_matches(cs->cmnd); if (cmnd_match != UNSPEC) { @@ -754,8 +753,8 @@ _print_member(struct lbuf *lbuf, char *name, int type, int negated, break; case ALIAS: if ((a = alias_get(name, alias_type)) != NULL) { - tq_foreach_fwd(&a->members, m) { - if (m != tq_first(&a->members)) + TAILQ_FOREACH(m, &a->members, entries) { + if (m != TAILQ_FIRST(&a->members)) lbuf_append(lbuf, "%s", separator); _print_member(lbuf, m->name, m->type, negated ? !m->negated : m->negated, separator, diff --git a/plugins/sudoers/parse.h b/plugins/sudoers/parse.h index b396da52d..62bb8acbc 100644 --- a/plugins/sudoers/parse.h +++ b/plugins/sudoers/parse.h @@ -18,8 +18,6 @@ #ifndef _SUDOERS_PARSE_H #define _SUDOERS_PARSE_H -#include "list.h" /* XXX */ - #undef UNSPEC #define UNSPEC -1 #undef DENY @@ -86,31 +84,30 @@ struct solaris_privs_info { * modelled after the yacc grammar. * * Other than the alias struct, which is stored in a red-black tree, - * the data structure used is basically a doubly-linked tail queue without - * a separate head struct--the first entry acts as the head where the prev - * pointer does double duty as the tail pointer. This makes it possible - * to trivally append sub-lists. In addition, the prev pointer is always - * valid (even if it points to itself). Unlike a circle queue, the next - * pointer of the last entry is NULL and does not point back to the head. - * - * Note that each list struct must contain a "prev" and "next" pointer as - * the first two members of the struct (in that order). + * the data structure used is a doubly-linked tail queue. While sudoers + * is being parsed, a headless tail queue is used where the first entry + * acts as the head and the prev pointer does double duty as the tail pointer. + * This makes it possible to trivally append sub-lists. In addition, the prev + * pointer is always valid (even if it points to itself). Unlike a circle + * queue, the next pointer of the last entry is NULL and does not point back + * to the head. When the tail queue is finalized, it is converted to a + * normal BSD tail queue. */ /* * Tail queue list head structure. */ -TQ_DECLARE(defaults) -TQ_DECLARE(userspec) -TQ_DECLARE(member) -TQ_DECLARE(privilege) -TQ_DECLARE(cmndspec) +TAILQ_HEAD(defaults_list, defaults); +TAILQ_HEAD(userspec_list, userspec); +TAILQ_HEAD(member_list, member); +TAILQ_HEAD(privilege_list, privilege); +TAILQ_HEAD(cmndspec_list, cmndspec); /* * Structure describing a user specification and list thereof. */ struct userspec { - struct userspec *prev, *next; + TAILQ_ENTRY(userspec) entries; struct member_list users; /* list of users */ struct privilege_list privileges; /* list of privileges */ }; @@ -119,7 +116,7 @@ struct userspec { * Structure describing a privilege specification. */ struct privilege { - struct privilege *prev, *next; + TAILQ_ENTRY(privilege) entries; struct member_list hostlist; /* list of hosts */ struct cmndspec_list cmndlist; /* list of Cmnd_Specs */ }; @@ -128,9 +125,9 @@ struct privilege { * Structure describing a linked list of Cmnd_Specs. */ struct cmndspec { - struct cmndspec *prev, *next; - struct member_list runasuserlist; /* list of runas users */ - struct member_list runasgrouplist; /* list of runas groups */ + TAILQ_ENTRY(cmndspec) entries; + struct member_list *runasuserlist; /* list of runas users */ + struct member_list *runasgrouplist; /* list of runas groups */ struct member *cmnd; /* command to allow/deny */ char *digest; /* optional command digest */ struct cmndtag tags; /* tag specificaion */ @@ -146,7 +143,7 @@ struct cmndspec { * Generic structure to hold users, hosts, commands. */ struct member { - struct member *prev, *next; + TAILQ_ENTRY(member) entries; char *name; /* member name */ short type; /* type (see gram.h) */ short negated; /* negated via '!'? */ @@ -172,10 +169,10 @@ struct alias { * Structure describing a Defaults entry and a list thereof. */ struct defaults { - struct defaults *prev, *next; + TAILQ_ENTRY(defaults) entries; char *var; /* variable name */ char *val; /* variable value */ - struct member_list binding; /* user/host/runas binding */ + struct member_list *binding; /* user/host/runas binding */ int type; /* DEFAULTS{,_USER,_RUNAS,_HOST} */ int op; /* true, false, '+', '-' */ }; diff --git a/plugins/sudoers/regress/parser/check_fill.c b/plugins/sudoers/regress/parser/check_fill.c index 5fc96d726..6ff807628 100644 --- a/plugins/sudoers/regress/parser/check_fill.c +++ b/plugins/sudoers/regress/parser/check_fill.c @@ -43,7 +43,7 @@ #define SUDO_ERROR_WRAP 0 #include "missing.h" -#include "list.h" +#include "queue.h" #include "parse.h" #include "toke.h" #include "sudo_plugin.h" diff --git a/plugins/sudoers/testsudoers.c b/plugins/sudoers/testsudoers.c index 6ee46726c..88d9f4e1d 100644 --- a/plugins/sudoers/testsudoers.c +++ b/plugins/sudoers/testsudoers.c @@ -304,19 +304,19 @@ main(int argc, char *argv[]) /* This loop must match the one in sudo_file_lookup() */ printf("\nEntries for user %s:\n", user_name); match = UNSPEC; - tq_foreach_rev(&userspecs, us) { + TAILQ_FOREACH_REVERSE(us, &userspecs, userspec_list, entries) { if (userlist_matches(sudo_user.pw, &us->users) != ALLOW) continue; - tq_foreach_rev(&us->privileges, priv) { + TAILQ_FOREACH_REVERSE(priv, &us->privileges, privilege_list, entries) { putchar('\n'); - print_privilege(priv); /* XXX */ + print_privilege(priv); putchar('\n'); host_match = hostlist_matches(&priv->hostlist); if (host_match == ALLOW) { puts("\thost matched"); - tq_foreach_rev(&priv->cmndlist, cs) { - runas_match = runaslist_matches(&cs->runasuserlist, - &cs->runasgrouplist, NULL, NULL); + TAILQ_FOREACH_REVERSE(cs, &priv->cmndlist, cmndspec_list, entries) { + runas_match = runaslist_matches(cs->runasuserlist, + cs->runasgrouplist, NULL, NULL); if (runas_match == ALLOW) { puts("\trunas matched"); cmnd_match = cmnd_matches(cs->cmnd); @@ -342,6 +342,8 @@ main(int argc, char *argv[]) */ exitcode = parse_error ? 1 : (match == ALLOW ? 0 : match + 3); done: + sudo_endpwent(); + sudo_endgrent(); sudo_debug_exit_int(__func__, __FILE__, __LINE__, sudo_debug_subsys, exitcode); exit(exitcode); } @@ -492,7 +494,7 @@ print_defaults(void) struct member *m; debug_decl(print_member, SUDO_DEBUG_UTIL) - tq_foreach_fwd(&defaults, d) { + TAILQ_FOREACH(d, &defaults, entries) { (void) fputs("Defaults", stdout); switch (d->type) { case DEFAULTS_HOST: @@ -508,8 +510,8 @@ print_defaults(void) putchar('!'); break; } - tq_foreach_fwd(&d->binding, m) { - if (m != tq_first(&d->binding)) + TAILQ_FOREACH(m, d->binding, entries) { + if (m != TAILQ_FIRST(d->binding)) putchar(','); print_member(m); } @@ -545,8 +547,8 @@ print_alias(void *v1, void *v2) (void) printf("Runas_Alias\t%s = ", a->name); break; } - tq_foreach_fwd(&a->members, m) { - if (m != tq_first(&a->members)) + TAILQ_FOREACH(m, &a->members, entries) { + if (m != TAILQ_FIRST(&a->members)) fputs(", ", stdout); if (m->type == COMMAND) { c = (struct sudo_command *) m->name; @@ -567,66 +569,61 @@ print_privilege(struct privilege *priv) { struct cmndspec *cs; struct member *m; - struct privilege *p; struct cmndtag tags; debug_decl(print_privilege, SUDO_DEBUG_UTIL) - for (p = priv; p != NULL; p = p->next) { - if (p != priv) - fputs(" : ", stdout); - tq_foreach_fwd(&p->hostlist, m) { - if (m != tq_first(&p->hostlist)) - fputs(", ", stdout); - print_member(m); - } - fputs(" = ", stdout); - tags.nopasswd = UNSPEC; - tags.noexec = UNSPEC; - tq_foreach_fwd(&p->cmndlist, cs) { - if (cs != tq_first(&p->cmndlist)) - fputs(", ", stdout); - if (!tq_empty(&cs->runasuserlist) || !tq_empty(&cs->runasgrouplist)) { - fputs("(", stdout); - if (!tq_empty(&cs->runasuserlist)) { - tq_foreach_fwd(&cs->runasuserlist, m) { - if (m != tq_first(&cs->runasuserlist)) - fputs(", ", stdout); - print_member(m); - } - } else if (tq_empty(&cs->runasgrouplist)) { - fputs(def_runas_default, stdout); - } else { - fputs(sudo_user.pw->pw_name, stdout); - } - if (!tq_empty(&cs->runasgrouplist)) { - fputs(" : ", stdout); - tq_foreach_fwd(&cs->runasgrouplist, m) { - if (m != tq_first(&cs->runasgrouplist)) - fputs(", ", stdout); - print_member(m); - } + TAILQ_FOREACH(m, &priv->hostlist, entries) { + if (m != TAILQ_FIRST(&priv->hostlist)) + fputs(", ", stdout); + print_member(m); + } + fputs(" = ", stdout); + tags.nopasswd = UNSPEC; + tags.noexec = UNSPEC; + TAILQ_FOREACH(cs, &priv->cmndlist, entries) { + if (cs != TAILQ_FIRST(&priv->cmndlist)) + fputs(", ", stdout); + if (cs->runasuserlist != NULL || cs->runasgrouplist != NULL) { + fputs("(", stdout); + if (cs->runasuserlist != NULL) { + TAILQ_FOREACH(m, cs->runasuserlist, entries) { + if (m != TAILQ_FIRST(cs->runasuserlist)) + fputs(", ", stdout); + print_member(m); + } + } else if (cs->runasgrouplist == NULL) { + fputs(def_runas_default, stdout); + } else { + fputs(sudo_user.pw->pw_name, stdout); + } + if (cs->runasgrouplist != NULL) { + fputs(" : ", stdout); + TAILQ_FOREACH(m, cs->runasgrouplist, entries) { + if (m != TAILQ_FIRST(cs->runasgrouplist)) + fputs(", ", stdout); + print_member(m); } - fputs(") ", stdout); } + fputs(") ", stdout); + } #ifdef HAVE_SELINUX - if (cs->role) - printf("ROLE=%s ", cs->role); - if (cs->type) - printf("TYPE=%s ", cs->type); + if (cs->role) + printf("ROLE=%s ", cs->role); + if (cs->type) + printf("TYPE=%s ", cs->type); #endif /* HAVE_SELINUX */ #ifdef HAVE_PRIV_SET - if (cs->privs) - printf("PRIVS=%s ", cs->privs); - if (cs->limitprivs) - printf("LIMITPRIVS=%s ", cs->limitprivs); + if (cs->privs) + printf("PRIVS=%s ", cs->privs); + if (cs->limitprivs) + printf("LIMITPRIVS=%s ", cs->limitprivs); #endif /* HAVE_PRIV_SET */ - if (cs->tags.nopasswd != UNSPEC && cs->tags.nopasswd != tags.nopasswd) - printf("%sPASSWD: ", cs->tags.nopasswd ? "NO" : ""); - if (cs->tags.noexec != UNSPEC && cs->tags.noexec != tags.noexec) - printf("%sEXEC: ", cs->tags.noexec ? "NO" : ""); - print_member(cs->cmnd); - memcpy(&tags, &cs->tags, sizeof(tags)); - } + if (cs->tags.nopasswd != UNSPEC && cs->tags.nopasswd != tags.nopasswd) + printf("%sPASSWD: ", cs->tags.nopasswd ? "NO" : ""); + if (cs->tags.noexec != UNSPEC && cs->tags.noexec != tags.noexec) + printf("%sEXEC: ", cs->tags.noexec ? "NO" : ""); + print_member(cs->cmnd); + memcpy(&tags, &cs->tags, sizeof(tags)); } debug_return; } @@ -636,16 +633,21 @@ print_userspecs(void) { struct member *m; struct userspec *us; + struct privilege *priv; debug_decl(print_userspecs, SUDO_DEBUG_UTIL) - tq_foreach_fwd(&userspecs, us) { - tq_foreach_fwd(&us->users, m) { - if (m != tq_first(&us->users)) + TAILQ_FOREACH(us, &userspecs, entries) { + TAILQ_FOREACH(m, &us->users, entries) { + if (m != TAILQ_FIRST(&us->users)) fputs(", ", stdout); print_member(m); } putchar('\t'); - print_privilege(us->privileges.first); /* XXX */ + TAILQ_FOREACH(priv, &us->privileges, entries) { + if (priv != TAILQ_FIRST(&us->privileges)) + fputs(" : ", stdout); + print_privilege(priv); + } putchar('\n'); } debug_return; diff --git a/plugins/sudoers/visudo.c b/plugins/sudoers/visudo.c index 5228083c2..e7c3997ea 100644 --- a/plugins/sudoers/visudo.c +++ b/plugins/sudoers/visudo.c @@ -1085,7 +1085,7 @@ alias_remove_recursive(char *name, int type) debug_decl(alias_remove_recursive, SUDO_DEBUG_ALIAS) if ((a = alias_remove(name, type)) != NULL) { - tq_foreach_fwd(&a->members, m) { + TAILQ_FOREACH(m, &a->members, entries) { if (m->type == ALIAS) { if (!alias_remove_recursive(m->name, type)) rval = false; @@ -1106,7 +1106,7 @@ check_alias(char *name, int type, int strict, int quiet) if ((a = alias_get(name, type)) != NULL) { /* check alias contents */ - tq_foreach_fwd(&a->members, m) { + TAILQ_FOREACH(m, &a->members, entries) { if (m->type == ALIAS) errors += check_alias(m->name, type, strict, quiet); } @@ -1143,7 +1143,7 @@ static int check_aliases(bool strict, bool quiet) { struct cmndspec *cs; - struct member *m, *binding; + struct member *m; struct privilege *priv; struct userspec *us; struct defaults *d; @@ -1153,22 +1153,31 @@ check_aliases(bool strict, bool quiet) alias_freelist = rbcreate(alias_compare); /* Forward check. */ - tq_foreach_fwd(&userspecs, us) { - tq_foreach_fwd(&us->users, m) { + TAILQ_FOREACH(us, &userspecs, entries) { + TAILQ_FOREACH(m, &us->users, entries) { if (m->type == ALIAS) { errors += check_alias(m->name, USERALIAS, strict, quiet); } } - tq_foreach_fwd(&us->privileges, priv) { - tq_foreach_fwd(&priv->hostlist, m) { + TAILQ_FOREACH(priv, &us->privileges, entries) { + TAILQ_FOREACH(m, &priv->hostlist, entries) { if (m->type == ALIAS) { errors += check_alias(m->name, HOSTALIAS, strict, quiet); } } - tq_foreach_fwd(&priv->cmndlist, cs) { - tq_foreach_fwd(&cs->runasuserlist, m) { - if (m->type == ALIAS) { - errors += check_alias(m->name, RUNASALIAS, strict, quiet); + TAILQ_FOREACH(cs, &priv->cmndlist, entries) { + if (cs->runasuserlist != NULL) { + TAILQ_FOREACH(m, cs->runasuserlist, entries) { + if (m->type == ALIAS) { + errors += check_alias(m->name, RUNASALIAS, strict, quiet); + } + } + } + if (cs->runasgrouplist != NULL) { + TAILQ_FOREACH(m, cs->runasgrouplist, entries) { + if (m->type == ALIAS) { + errors += check_alias(m->name, RUNASALIAS, strict, quiet); + } } } if ((m = cs->cmnd)->type == ALIAS) { @@ -1179,31 +1188,35 @@ check_aliases(bool strict, bool quiet) } /* Reverse check (destructive) */ - tq_foreach_fwd(&userspecs, us) { - tq_foreach_fwd(&us->users, m) { + TAILQ_FOREACH(us, &userspecs, entries) { + TAILQ_FOREACH(m, &us->users, entries) { if (m->type == ALIAS) { if (!alias_remove_recursive(m->name, USERALIAS)) errors++; } } - tq_foreach_fwd(&us->privileges, priv) { - tq_foreach_fwd(&priv->hostlist, m) { + TAILQ_FOREACH(priv, &us->privileges, entries) { + TAILQ_FOREACH(m, &priv->hostlist, entries) { if (m->type == ALIAS) { if (!alias_remove_recursive(m->name, HOSTALIAS)) errors++; } } - tq_foreach_fwd(&priv->cmndlist, cs) { - tq_foreach_fwd(&cs->runasuserlist, m) { - if (m->type == ALIAS) { - if (!alias_remove_recursive(m->name, RUNASALIAS)) - errors++; + TAILQ_FOREACH(cs, &priv->cmndlist, entries) { + if (cs->runasuserlist != NULL) { + TAILQ_FOREACH(m, cs->runasuserlist, entries) { + if (m->type == ALIAS) { + if (!alias_remove_recursive(m->name, RUNASALIAS)) + errors++; + } } } - tq_foreach_fwd(&cs->runasgrouplist, m) { - if (m->type == ALIAS) { - if (!alias_remove_recursive(m->name, RUNASALIAS)) - errors++; + if (cs->runasgrouplist != NULL) { + TAILQ_FOREACH(m, cs->runasgrouplist, entries) { + if (m->type == ALIAS) { + if (!alias_remove_recursive(m->name, RUNASALIAS)) + errors++; + } } } if ((m = cs->cmnd)->type == ALIAS) { @@ -1213,7 +1226,7 @@ check_aliases(bool strict, bool quiet) } } } - tq_foreach_fwd(&defaults, d) { + TAILQ_FOREACH(d, &defaults, entries) { switch (d->type) { case DEFAULTS_HOST: atype = HOSTALIAS; @@ -1230,12 +1243,10 @@ check_aliases(bool strict, bool quiet) default: continue; /* not an alias */ } - tq_foreach_fwd(&d->binding, binding) { - for (m = binding; m != NULL; m = m->next) { - if (m->type == ALIAS) { - if (!alias_remove_recursive(m->name, atype)) - errors++; - } + TAILQ_FOREACH(m, d->binding, entries) { + if (m->type == ALIAS) { + if (!alias_remove_recursive(m->name, atype)) + errors++; } } }