Clear next field when returnining list elements in queue.c

The ipa-otpd code occasionally removes elements from one queue,
inspects and modifies them, and then inserts them into
another (possibly identical, possibly different) queue.  When the next
pointer isn't cleared, this can result in element membership in both
queues, leading to double frees, or even self-referential elements,
causing infinite loops at traversal time.

Rather than eliminating the pattern, make it safe by clearing the next
field any time an element enters or exits a queue.

Related https://pagure.io/freeipa/issue/7262

Reviewed-By: Florence Blanc-Renaud <frenaud@redhat.com>
This commit is contained in:
Robbie Harwood 2018-08-22 15:32:16 -04:00 committed by Florence Blanc-Renaud
parent 90203fb044
commit fe650087b0

View File

@ -111,6 +111,8 @@ void otpd_queue_push(struct otpd_queue *q, struct otpd_queue_item *item)
q->head = q->tail = item;
else
q->tail = q->tail->next = item;
item->next = NULL;
}
void otpd_queue_push_head(struct otpd_queue *q, struct otpd_queue_item *item)
@ -118,6 +120,8 @@ void otpd_queue_push_head(struct otpd_queue *q, struct otpd_queue_item *item)
if (item == NULL)
return;
item->next = NULL;
if (q->head == NULL)
q->tail = q->head = item;
else {
@ -145,6 +149,8 @@ struct otpd_queue_item *otpd_queue_pop(struct otpd_queue *q)
if (q->head == NULL)
q->tail = NULL;
if (item != NULL)
item->next = NULL;
return item;
}
@ -160,6 +166,7 @@ struct otpd_queue_item *otpd_queue_pop_msgid(struct otpd_queue *q, int msgid)
*prev = item->next;
if (q->head == NULL)
q->tail = NULL;
item->next = NULL;
return item;
}
}