lua: avoid truncation of large numeric values
[oweals/ubus.git] / libubus-io.c
index 887e88c1b48b30a7c0a8d456dd022059c8aace2e..3561ac462eb960fbbd828d9100d0656f101131cb 100644 (file)
@@ -43,9 +43,9 @@ static const struct blob_attr_info ubus_policy[UBUS_ATTR_MAX] = {
 
 static struct blob_attr *attrbuf[UBUS_ATTR_MAX];
 
-__hidden struct blob_attr **ubus_parse_msg(struct blob_attr *msg)
+__hidden struct blob_attr **ubus_parse_msg(struct blob_attr *msg, size_t len)
 {
-       blob_parse(msg, attrbuf, ubus_policy, UBUS_ATTR_MAX);
+       blob_parse_untrusted(msg, len, attrbuf, ubus_policy, UBUS_ATTR_MAX);
        return attrbuf;
 }
 
@@ -59,32 +59,33 @@ static void wait_data(int fd, bool write)
 
 static int writev_retry(int fd, struct iovec *iov, int iov_len, int sock_fd)
 {
-       static struct {
-               struct cmsghdr h;
-               int fd;
-       } fd_buf = {
-               .h = {
-                       .cmsg_len = sizeof(fd_buf),
-                       .cmsg_level = SOL_SOCKET,
-                       .cmsg_type = SCM_RIGHTS,
-               }
-       };
-       struct msghdr msghdr = {
-               .msg_iov = iov,
-               .msg_iovlen = iov_len,
-               .msg_control = &fd_buf,
-               .msg_controllen = sizeof(fd_buf),
-       };
+       uint8_t fd_buf[CMSG_SPACE(sizeof(int))] = { 0 };
+       struct msghdr msghdr = { 0 };
+       struct cmsghdr *cmsg;
        int len = 0;
+       int *pfd;
+
+       msghdr.msg_iov = iov,
+       msghdr.msg_iovlen = iov_len,
+       msghdr.msg_control = fd_buf;
+       msghdr.msg_controllen = sizeof(fd_buf);
+
+       cmsg = CMSG_FIRSTHDR(&msghdr);
+       cmsg->cmsg_type = SCM_RIGHTS;
+       cmsg->cmsg_level = SOL_SOCKET;
+       cmsg->cmsg_len = CMSG_LEN(sizeof(int));
+
+       pfd = (int *) CMSG_DATA(cmsg);
+       msghdr.msg_controllen = cmsg->cmsg_len;
 
        do {
-               int cur_len;
+               ssize_t cur_len;
 
                if (sock_fd < 0) {
                        msghdr.msg_control = NULL;
                        msghdr.msg_controllen = 0;
                } else {
-                       fd_buf.fd = sock_fd;
+                       *pfd = sock_fd;
                }
 
                cur_len = sendmsg(fd, &msghdr, 0);
@@ -105,7 +106,7 @@ static int writev_retry(int fd, struct iovec *iov, int iov_len, int sock_fd)
                        sock_fd = -1;
 
                len += cur_len;
-               while (cur_len >= iov->iov_len) {
+               while (cur_len >= (ssize_t) iov->iov_len) {
                        cur_len -= iov->iov_len;
                        iov_len--;
                        iov++;
@@ -156,36 +157,38 @@ int __hidden ubus_send_msg(struct ubus_context *ctx, uint32_t seq,
 
 static int recv_retry(struct ubus_context *ctx, struct iovec *iov, bool wait, int *recv_fd)
 {
-       int bytes, total = 0;
-       int fd = ctx->sock.fd;
-       static struct {
-               struct cmsghdr h;
-               int fd;
-       } fd_buf = {
-               .h = {
-                       .cmsg_type = SCM_RIGHTS,
-                       .cmsg_level = SOL_SOCKET,
-                       .cmsg_len = sizeof(fd_buf),
-               },
-       };
-       struct msghdr msghdr = {
-               .msg_iov = iov,
-               .msg_iovlen = 1,
-       };
+       uint8_t fd_buf[CMSG_SPACE(sizeof(int))] = { 0 };
+       struct msghdr msghdr = { 0 };
+       struct cmsghdr *cmsg;
+       int total = 0;
+       int bytes;
+       int *pfd;
+       int fd;
 
-       while (iov->iov_len > 0) {
-               if (wait)
-                       wait_data(fd, false);
+       fd = ctx->sock.fd;
+
+       msghdr.msg_iov = iov,
+       msghdr.msg_iovlen = 1,
+       msghdr.msg_control = fd_buf;
+       msghdr.msg_controllen = sizeof(fd_buf);
+
+       cmsg = CMSG_FIRSTHDR(&msghdr);
+       cmsg->cmsg_type = SCM_RIGHTS;
+       cmsg->cmsg_level = SOL_SOCKET;
+       cmsg->cmsg_len = CMSG_LEN(sizeof(int));
 
+       pfd = (int *) CMSG_DATA(cmsg);
+
+       while (iov->iov_len > 0) {
                if (recv_fd) {
-                       msghdr.msg_control = &fd_buf;
-                       msghdr.msg_controllen = sizeof(fd_buf);
+                       msghdr.msg_control = fd_buf;
+                       msghdr.msg_controllen = cmsg->cmsg_len;
                } else {
                        msghdr.msg_control = NULL;
                        msghdr.msg_controllen = 0;
                }
 
-               fd_buf.fd = -1;
+               *pfd = -1;
                bytes = recvmsg(fd, &msghdr, 0);
                if (!bytes)
                        return -1;
@@ -202,7 +205,7 @@ static int recv_retry(struct ubus_context *ctx, struct iovec *iov, bool wait, in
                        return 0;
 
                if (recv_fd)
-                       *recv_fd = fd_buf.fd;
+                       *recv_fd = *pfd;
 
                recv_fd = NULL;
 
@@ -210,12 +213,15 @@ static int recv_retry(struct ubus_context *ctx, struct iovec *iov, bool wait, in
                iov->iov_len -= bytes;
                iov->iov_base += bytes;
                total += bytes;
+
+               if (iov->iov_len > 0)
+                       wait_data(fd, false);
        }
 
        return total;
 }
 
-static bool ubus_validate_hdr(struct ubus_msghdr *hdr)
+bool ubus_validate_hdr(struct ubus_msghdr *hdr)
 {
        struct blob_attr *data = (struct blob_attr *) (hdr + 1);
 
@@ -392,7 +398,7 @@ int ubus_reconnect(struct ubus_context *ctx, const char *path)
                goto out_close;
 
        memcpy(buf, &hdr.data, sizeof(hdr.data));
-       if (read(ctx->sock.fd, blob_data(buf), blob_len(buf)) != blob_len(buf))
+       if (read(ctx->sock.fd, blob_data(buf), blob_len(buf)) != (ssize_t) blob_len(buf))
                goto out_free;
 
        ctx->local_id = hdr.hdr.peer;