sys: use "Auto-Installed" field for packagelist
[project/rpcd.git] / file.c
diff --git a/file.c b/file.c
index b78c54f5131f8446ad32e8c69b9f10a66d05b6c7..1e5b2f4106f8fd3456e79eac8d9bfa83446d456d 100644 (file)
--- a/file.c
+++ b/file.c
 #include <rpcd/plugin.h>
 
 /* limit of sys & proc files */
-#define RPC_FILE_MIN_SIZE              (128)
+#define RPC_FILE_MIN_SIZE              (4096)
 
 /* 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,10 +805,13 @@ 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;
 
+       if (sid && env)
+               return UBUS_STATUS_PERMISSION_DENIED;
+
        cmd = rpc_file_exec_lookup(cmd);
 
        if (!cmd)
@@ -816,20 +823,45 @@ 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 = 2;
+               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))
+                               return UBUS_STATUS_PERMISSION_DENIED;
+
+                       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));
 
        if (!c)
                return UBUS_STATUS_UNKNOWN_ERROR;
 
-       if (pipe(opipe) || pipe(epipe))
-               return rpc_errno_status();
+       if (pipe(opipe))
+               goto fail_opipe;
+
+       if (pipe(epipe))
+               goto fail_epipe;
 
        switch ((pid = fork()))
        {
        case -1:
-               return rpc_errno_status();
+               goto fail_fork;
 
        case 0:
                uloop_done();
@@ -921,6 +953,18 @@ rpc_file_exec_run(const char *cmd, const struct blob_attr *sid,
        }
 
        return UBUS_STATUS_OK;
+
+fail_fork:
+       close(epipe[0]);
+       close(epipe[1]);
+
+fail_epipe:
+       close(opipe[0]);
+       close(opipe[1]);
+
+fail_opipe:
+       free(c);
+       return rpc_errno_status();
 }
 
 static int
@@ -955,7 +999,7 @@ rpc_file_api_init(const struct rpc_daemon_ops *o, struct ubus_context *ctx)
        };
 
        static struct ubus_object_type file_type =
-               UBUS_OBJECT_TYPE("luci-rpc-file", file_methods);
+               UBUS_OBJECT_TYPE("rpcd-plugin-file", file_methods);
 
        static struct ubus_object obj = {
                .name = "file",