summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJo-Philipp Wich <jo@mein.io>2019-12-10 16:49:55 +0100
committerJo-Philipp Wich <jo@mein.io>2019-12-11 09:13:05 +0100
commitaaa08366e6384d9933a405d1218b03c1b167f9e5 (patch)
treef347d01e181d45ce28adb2291ba90fb9c2ef8297
parent77ad0de09247b9bdce50f4cecf3e5beb5636f57f (diff)
downloadrpcd-aaa08366e6384d9933a405d1218b03c1b167f9e5.tar.gz
file: extend exec acl checks to commands with arguments
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>
-rw-r--r--file.c30
1 files changed, 28 insertions, 2 deletions
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));