uci: manually clear uci_ptr flags after uci_delete() operations

This is required to avoid potential use-after-free errors through the
uci_set()->uci_delete()->uci_expand_ptr() call chain when passing
zero-length strings as values.

Ref: https://bugs.openwrt.org/index.php?do=details&task_id=3528
Suggested-by: olegio170 <olegios170@gmail.com>
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
This commit is contained in:
Jo-Philipp Wich 2020-12-23 19:06:12 +01:00
parent ea7f4717f8
commit d3f2041f43

6
uci.c
View file

@ -831,8 +831,10 @@ rpc_uci_merge_set(struct blob_attr *opt, struct uci_ptr *ptr)
if (blobmsg_type(opt) == BLOBMSG_TYPE_ARRAY) if (blobmsg_type(opt) == BLOBMSG_TYPE_ARRAY)
{ {
if (ptr->o) if (ptr->o) {
uci_delete(cursor, ptr); uci_delete(cursor, ptr);
ptr->flags = 0;
}
rv = UBUS_STATUS_INVALID_ARGUMENT; rv = UBUS_STATUS_INVALID_ARGUMENT;
@ -850,6 +852,7 @@ rpc_uci_merge_set(struct blob_attr *opt, struct uci_ptr *ptr)
else if (ptr->o && ptr->o->type == UCI_TYPE_LIST) else if (ptr->o && ptr->o->type == UCI_TYPE_LIST)
{ {
uci_delete(cursor, ptr); uci_delete(cursor, ptr);
ptr->flags = 0;
if (!rpc_uci_format_blob(opt, &ptr->value)) if (!rpc_uci_format_blob(opt, &ptr->value))
return UBUS_STATUS_INVALID_ARGUMENT; return UBUS_STATUS_INVALID_ARGUMENT;
@ -981,6 +984,7 @@ rpc_uci_merge_delete(struct blob_attr *opt, struct uci_ptr *ptr)
continue; continue;
uci_delete(cursor, ptr); uci_delete(cursor, ptr);
ptr->flags = 0;
rv = 0; rv = 0;
} }