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;
}
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);
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++;
hdr.version = 0;
hdr.type = cmd;
- hdr.seq = seq;
- hdr.peer = peer;
+ hdr.seq = cpu_to_be16(seq);
+ hdr.peer = cpu_to_be32(peer);
if (!msg) {
blob_buf_init(&b, 0);
return ret;
}
-static int recv_retry(int fd, struct iovec *iov, bool wait, int *recv_fd)
+static int recv_retry(struct ubus_context *ctx, struct iovec *iov, bool wait, int *recv_fd)
{
- int bytes, total = 0;
- 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;
if (bytes < 0) {
bytes = 0;
- if (uloop_cancelled)
- return 0;
if (errno == EINTR)
continue;
return 0;
if (recv_fd)
- *recv_fd = fd_buf.fd;
+ *recv_fd = *pfd;
recv_fd = NULL;
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);
return false;
ctx->msgbuf.data = ptr;
+ ctx->msgbuf_data_len = len;
return true;
}
int r;
/* receive header + start attribute */
- r = recv_retry(ctx->sock.fd, &iov, false, recv_fd);
+ r = recv_retry(ctx, &iov, false, recv_fd);
if (r <= 0) {
if (r < 0)
ctx->sock.eof = true;
return false;
}
+ hdrbuf.hdr.seq = be16_to_cpu(hdrbuf.hdr.seq);
+ hdrbuf.hdr.peer = be32_to_cpu(hdrbuf.hdr.peer);
+
if (!ubus_validate_hdr(&hdrbuf.hdr))
return false;
iov.iov_base = (char *)ctx->msgbuf.data + sizeof(hdrbuf.data);
iov.iov_len = blob_len(ctx->msgbuf.data);
if (iov.iov_len > 0 &&
- recv_retry(ctx->sock.fd, &iov, true, NULL) <= 0)
+ recv_retry(ctx, &iov, true, NULL) <= 0)
return false;
return true;
while (get_next_msg(ctx, &recv_fd)) {
ubus_process_msg(ctx, &ctx->msgbuf, recv_fd);
- if (uloop_cancelled)
+ if (uloop_cancelling() || ctx->cancel_poll)
break;
}
.events = POLLIN | POLLERR,
};
+ ctx->cancel_poll = false;
poll(&pfd, 1, timeout ? timeout : -1);
ubus_handle_data(&ctx->sock, ULOOP_READ);
}
close(ctx->sock.fd);
}
+ ctx->sock.eof = false;
+ ctx->sock.error = false;
ctx->sock.fd = usock(USOCK_UNIX, path, NULL);
if (ctx->sock.fd < 0)
return UBUS_STATUS_CONNECTION_FAILED;
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;