Skip to content

Commit f4446d5

Browse files
committed
privsep: Ensure we recv for real after a successful recv MSG_PEEK
Adjust the code flow so that the same errors would be caught after the final recv. This ensures we read what is really meant for us and not something silly. Should fix #555.
1 parent 385ff24 commit f4446d5

File tree

1 file changed

+18
-14
lines changed

1 file changed

+18
-14
lines changed

src/privsep-root.c

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ ps_root_readerrorcb(struct psr_ctx *psr_ctx)
8686
{ .iov_base = psr_error, .iov_len = sizeof(*psr_error) },
8787
{ .iov_base = NULL, .iov_len = 0 },
8888
};
89+
struct msghdr msg = { .msg_iov = iov, .msg_iovlen = __arraycount(iov) };
8990
ssize_t len;
9091

9192
#define PSR_ERROR(e) \
@@ -98,37 +99,40 @@ ps_root_readerrorcb(struct psr_ctx *psr_ctx)
9899
if (eloop_waitfd(fd) == -1)
99100
PSR_ERROR(errno);
100101

101-
len = recv(fd, psr_error, sizeof(*psr_error), MSG_PEEK);
102+
len = recvmsg(fd, &msg, MSG_PEEK | MSG_WAITALL);
102103
if (len == -1)
103104
PSR_ERROR(errno);
104105
else if ((size_t)len < sizeof(*psr_error))
105-
PSR_ERROR(EINVAL);
106+
goto recv;
106107

107-
if (psr_error->psr_datalen > SSIZE_MAX)
108-
PSR_ERROR(ENOBUFS);
109108
if (psr_ctx->psr_usemdata &&
110109
psr_error->psr_datalen > psr_ctx->psr_mdatalen)
111110
{
112111
void *d = realloc(psr_ctx->psr_mdata, psr_error->psr_datalen);
113-
if (d == NULL)
114-
PSR_ERROR(errno);
115-
psr_ctx->psr_mdata = d;
116-
psr_ctx->psr_mdatalen = psr_error->psr_datalen;
112+
113+
if (d != NULL) {
114+
psr_ctx->psr_mdata = d;
115+
psr_ctx->psr_mdatalen = psr_error->psr_datalen;
116+
}
117117
}
118118
if (psr_error->psr_datalen != 0) {
119-
if (psr_ctx->psr_usemdata)
119+
if (psr_ctx->psr_usemdata) {
120120
iov[1].iov_base = psr_ctx->psr_mdata;
121-
else {
122-
if (psr_error->psr_datalen > psr_ctx->psr_datalen)
123-
PSR_ERROR(ENOBUFS);
121+
iov[1].iov_len = psr_ctx->psr_mdatalen;
122+
} else {
124123
iov[1].iov_base = psr_ctx->psr_data;
124+
iov[1].iov_len = psr_ctx->psr_datalen;
125125
}
126-
iov[1].iov_len = psr_error->psr_datalen;
127126
}
128127

129-
len = readv(fd, iov, __arraycount(iov));
128+
recv:
129+
len = recvmsg(fd, &msg, MSG_WAITALL);
130130
if (len == -1)
131131
PSR_ERROR(errno);
132+
else if ((size_t)len < sizeof(*psr_error))
133+
PSR_ERROR(EINVAL);
134+
else if (msg.msg_flags & MSG_TRUNC)
135+
PSR_ERROR(ENOBUFS);
132136
else if ((size_t)len != sizeof(*psr_error) + psr_error->psr_datalen)
133137
PSR_ERROR(EINVAL);
134138
return len;

0 commit comments

Comments
 (0)