When the initial exec permission check on the executable path fails,
concatenate the command line with spaces and use the resulting string
as lookup path for a second exec permission check.
This allows for exec acls similar to this example:
"file": {
"/usr/bin/program --flag --option=1 arg *": [ "exec" ]
}
The example above would allow executing `/usr/bin/program` with the
arguments `--flag`, `--option=1` and `arg` in exactly this order,
followed by any number of optional arguments as denoted by the
asterisk.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
/* limit of regular files and command output data */
#define RPC_FILE_MAX_SIZE (4096 * 64)
/* 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; \
#define ustream_for_each_read_buffer(stream, ptr, len) \
for (ptr = ustream_get_read_buf(stream, &len); \
ptr != NULL && len > 0; \
static struct blob_buf buf;
static char *canonpath;
static struct blob_buf buf;
static char *canonpath;
+static char cmdstr[RPC_CMDLINE_MAX_SIZE];
struct blob_attr *cur;
uint8_t arglen;
struct blob_attr *cur;
uint8_t arglen;
- char *executable, **args, **tmp;
+ char *executable, **args, **tmp, *p;
struct rpc_file_exec_context *c;
struct rpc_file_exec_context *c;
return UBUS_STATUS_UNKNOWN_ERROR;
if (!rpc_file_access(sid, executable, "exec"))
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;
+ }