From 5d2bf09ec594d97eb9284b8c721dbfe10b81a6f6 Mon Sep 17 00:00:00 2001 From: Jordan Miner Date: Sat, 24 Mar 2018 20:30:07 -0500 Subject: [PATCH] uci: fix a potential use-after-free in uci_set() When calling uci_set() to update an option, if ptr->o != NULL and ptr->option == NULL, then uci_expand_ptr() will set ptr->option to ptr->o->e.name (or the caller could set ptr->option to that value). In this case, the option will be freed just before calling uci_alloc_option() with ptr->option, which was just freed. Signed-off-by: Jordan Miner Signed-off-by: Hans Dedecker --- list.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/list.c b/list.c index abb202f..25aec56 100644 --- a/list.c +++ b/list.c @@ -699,11 +699,15 @@ int uci_set(struct uci_context *ctx, struct uci_ptr *ptr) ptr->s = uci_alloc_section(ptr->p, ptr->value, ptr->section); ptr->last = &ptr->s->e; } else if (ptr->o && ptr->option) { /* update option */ + struct uci_option *o; + if ((ptr->o->type == UCI_TYPE_STRING) && !strcmp(ptr->o->v.string, ptr->value)) return 0; - uci_free_option(ptr->o); + + o = ptr->o; ptr->o = uci_alloc_option(ptr->s, ptr->option, ptr->value); + uci_free_option(o); ptr->last = &ptr->o->e; } else if (ptr->s && ptr->section) { /* update section */ char *s = uci_strdup(ctx, ptr->value); -- 2.25.1