Commit 620512af authored by Herbert Xu's avatar Herbert Xu Committed by Linus Torvalds

[NET]: Fix CMSG validation checks wrt. signedness.

Noticed by Georgi Guninski.
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 4c20da44
......@@ -90,6 +90,10 @@ struct cmsghdr {
(struct cmsghdr *)(ctl) : \
(struct cmsghdr *)NULL)
#define CMSG_FIRSTHDR(msg) __CMSG_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen)
#define CMSG_OK(mhdr, cmsg) ((cmsg)->cmsg_len >= sizeof(struct cmsghdr) && \
(cmsg)->cmsg_len <= (unsigned long) \
((mhdr)->msg_controllen - \
((char *)(cmsg) - (char *)(mhdr)->msg_control)))
/*
* This mess will go away with glibc
......
......@@ -127,9 +127,7 @@ int __scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie *p)
for too short ancillary data object at all! Oops.
OK, let's add it...
*/
if (cmsg->cmsg_len < sizeof(struct cmsghdr) ||
(unsigned long)(((char*)cmsg - (char*)msg->msg_control)
+ cmsg->cmsg_len) > msg->msg_controllen)
if (!CMSG_OK(msg, cmsg))
goto error;
if (cmsg->cmsg_level != SOL_SOCKET)
......
......@@ -146,11 +146,8 @@ int ip_cmsg_send(struct msghdr *msg, struct ipcm_cookie *ipc)
struct cmsghdr *cmsg;
for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) {
if (cmsg->cmsg_len < sizeof(struct cmsghdr) ||
(unsigned long)(((char*)cmsg - (char*)msg->msg_control)
+ cmsg->cmsg_len) > msg->msg_controllen) {
if (!CMSG_OK(msg, cmsg))
return -EINVAL;
}
if (cmsg->cmsg_level != SOL_IP)
continue;
switch (cmsg->cmsg_type) {
......
......@@ -427,9 +427,7 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl,
int addr_type;
struct net_device *dev = NULL;
if (cmsg->cmsg_len < sizeof(struct cmsghdr) ||
(unsigned long)(((char*)cmsg - (char*)msg->msg_control)
+ cmsg->cmsg_len) > msg->msg_controllen) {
if (!CMSG_OK(msg, cmsg)) {
err = -EINVAL;
goto exit_f;
}
......
......@@ -4098,12 +4098,8 @@ SCTP_STATIC int sctp_msghdr_parse(const struct msghdr *msg,
for (cmsg = CMSG_FIRSTHDR(msg);
cmsg != NULL;
cmsg = CMSG_NXTHDR((struct msghdr*)msg, cmsg)) {
/* Check for minimum length. The SCM code has this check. */
if (cmsg->cmsg_len < sizeof(struct cmsghdr) ||
(unsigned long)(((char*)cmsg - (char*)msg->msg_control)
+ cmsg->cmsg_len) > msg->msg_controllen) {
if (!CMSG_OK(msg, cmsg))
return -EINVAL;
}
/* Should we parse this header or ignore? */
if (cmsg->cmsg_level != IPPROTO_SCTP)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment