diff --git a/file.c b/file.c index 4ed2e5c..bd7af56 100644 --- a/file.c +++ b/file.c @@ -43,6 +43,9 @@ /* limit of regular files and command output data */ #define RPC_FILE_MAX_SIZE (4096 * 64) +/* limit of command line length for exec acl checks */ +#define RPC_CMDLINE_MAX_SIZE (1024) + #define ustream_for_each_read_buffer(stream, ptr, len) \ for (ptr = ustream_get_read_buf(stream, &len); \ ptr != NULL && len > 0; \ @@ -71,6 +74,7 @@ struct rpc_file_exec_context { static struct blob_buf buf; static char *canonpath; +static char cmdstr[RPC_CMDLINE_MAX_SIZE]; enum { RPC_F_R_PATH, @@ -801,7 +805,7 @@ rpc_file_exec_run(const char *cmd, const struct blob_attr *sid, struct blob_attr *cur; uint8_t arglen; - char *executable, **args, **tmp; + char *executable, **args, **tmp, *p; struct rpc_file_exec_context *c; @@ -816,7 +820,29 @@ rpc_file_exec_run(const char *cmd, const struct blob_attr *sid, return UBUS_STATUS_UNKNOWN_ERROR; if (!rpc_file_access(sid, executable, "exec")) - return UBUS_STATUS_PERMISSION_DENIED; + { + if (arg == NULL || strlen(executable) >= sizeof(cmdstr)) + return UBUS_STATUS_PERMISSION_DENIED; + + arglen = 0; + p = cmdstr + sprintf(cmdstr, "%s", executable); + + blobmsg_for_each_attr(cur, arg, rem) + { + if (blobmsg_type(cur) != BLOBMSG_TYPE_STRING) + continue; + + if (arglen == 255 || + p + blobmsg_data_len(cur) >= cmdstr + sizeof(cmdstr)) + break; + + p += sprintf(p, " %s", blobmsg_get_string(cur)); + arglen++; + } + + if (!rpc_file_access(sid, cmdstr, "exec")) + return UBUS_STATUS_PERMISSION_DENIED; + } c = malloc(sizeof(*c));