uci: reject invalid section and option names
The invoked libuci functions do not reliably check their arguments, causing malformed section and option names to end up in the delta file, letting the uci cli and other components to segfault when processung such invalid entries. In order to prevent that, manually test received values before passing them on to libuci. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
This commit is contained in:
parent
820621952d
commit
51980c687b
1 changed files with 74 additions and 0 deletions
74
uci.c
74
uci.c
|
@ -181,6 +181,60 @@ static const struct blobmsg_policy rpc_uci_rollback_policy[__RPC_B_MAX] = {
|
|||
.type = BLOBMSG_TYPE_STRING },
|
||||
};
|
||||
|
||||
/*
|
||||
* Validate a uci name
|
||||
*/
|
||||
static bool
|
||||
rpc_uci_verify_str(const char *name, bool extended, bool type)
|
||||
{
|
||||
const char *c;
|
||||
char *e;
|
||||
|
||||
if (!name || !*name)
|
||||
return false;
|
||||
|
||||
if (extended && *name != '@')
|
||||
extended = false;
|
||||
|
||||
for (c = name + extended; *c; c++)
|
||||
if (!isalnum(*c) && *c != '_' && ((!type && !extended) || *c != '-'))
|
||||
break;
|
||||
|
||||
if (extended) {
|
||||
if (*c != '[')
|
||||
return false;
|
||||
|
||||
strtol(++c, &e, 10);
|
||||
|
||||
return (e > c && *e == ']' && *(e+1) == 0);
|
||||
}
|
||||
|
||||
return (*c == 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check that string is a valid, shell compatible uci name
|
||||
*/
|
||||
static bool rpc_uci_verify_name(const char *name) {
|
||||
return rpc_uci_verify_str(name, false, false);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check that string is a valid section type name
|
||||
*/
|
||||
static bool rpc_uci_verify_type(const char *type) {
|
||||
return rpc_uci_verify_str(type, false, true);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check that the string is a valid section id, optionally in extended
|
||||
* lookup notation
|
||||
*/
|
||||
static bool rpc_uci_verify_section(const char *section) {
|
||||
return rpc_uci_verify_str(section, true, false);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Turn uci error state into ubus return code
|
||||
*/
|
||||
|
@ -644,6 +698,13 @@ rpc_uci_add(struct ubus_context *ctx, struct ubus_object *obj,
|
|||
if (!rpc_uci_write_access(tb[RPC_A_SESSION], tb[RPC_A_CONFIG]))
|
||||
return UBUS_STATUS_PERMISSION_DENIED;
|
||||
|
||||
if (!rpc_uci_verify_type(blobmsg_data(tb[RPC_A_TYPE])))
|
||||
return UBUS_STATUS_INVALID_ARGUMENT;
|
||||
|
||||
if (tb[RPC_A_NAME] &&
|
||||
!rpc_uci_verify_name(blobmsg_data(tb[RPC_A_NAME])))
|
||||
return UBUS_STATUS_INVALID_ARGUMENT;
|
||||
|
||||
ptr.package = blobmsg_data(tb[RPC_A_CONFIG]);
|
||||
|
||||
if (uci_load(cursor, ptr.package, &p))
|
||||
|
@ -676,6 +737,9 @@ rpc_uci_add(struct ubus_context *ctx, struct ubus_object *obj,
|
|||
ptr.o = NULL;
|
||||
ptr.option = blobmsg_name(cur);
|
||||
|
||||
if (!rpc_uci_verify_name(ptr.option))
|
||||
continue;
|
||||
|
||||
if (rpc_uci_lookup(&ptr) || !ptr.s)
|
||||
continue;
|
||||
|
||||
|
@ -726,6 +790,9 @@ rpc_uci_merge_set(struct blob_attr *opt, struct uci_ptr *ptr)
|
|||
ptr->option = blobmsg_name(opt);
|
||||
ptr->value = NULL;
|
||||
|
||||
if (!rpc_uci_verify_name(ptr->option))
|
||||
return;
|
||||
|
||||
if (rpc_uci_lookup(ptr) || !ptr->s)
|
||||
return;
|
||||
|
||||
|
@ -774,6 +841,10 @@ rpc_uci_set(struct ubus_context *ctx, struct ubus_object *obj,
|
|||
if (!rpc_uci_write_access(tb[RPC_S_SESSION], tb[RPC_S_CONFIG]))
|
||||
return UBUS_STATUS_PERMISSION_DENIED;
|
||||
|
||||
if (tb[RPC_S_SECTION] &&
|
||||
!rpc_uci_verify_section(blobmsg_data(tb[RPC_S_SECTION])))
|
||||
return UBUS_STATUS_INVALID_ARGUMENT;
|
||||
|
||||
ptr.package = blobmsg_data(tb[RPC_S_CONFIG]);
|
||||
|
||||
if (uci_load(cursor, ptr.package, &p))
|
||||
|
@ -937,6 +1008,9 @@ rpc_uci_rename(struct ubus_context *ctx, struct ubus_object *obj,
|
|||
ptr.section = blobmsg_data(tb[RPC_R_SECTION]);
|
||||
ptr.value = blobmsg_data(tb[RPC_R_NAME]);
|
||||
|
||||
if (!rpc_uci_verify_name(ptr.value))
|
||||
return UBUS_STATUS_INVALID_ARGUMENT;
|
||||
|
||||
if (tb[RPC_R_OPTION])
|
||||
ptr.option = blobmsg_data(tb[RPC_R_OPTION]);
|
||||
|
||||
|
|
Loading…
Reference in a new issue