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 { ...@@ -90,6 +90,10 @@ struct cmsghdr {
(struct cmsghdr *)(ctl) : \ (struct cmsghdr *)(ctl) : \
(struct cmsghdr *)NULL) (struct cmsghdr *)NULL)
#define CMSG_FIRSTHDR(msg) __CMSG_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen) #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 * This mess will go away with glibc
......
...@@ -127,9 +127,7 @@ int __scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie *p) ...@@ -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. for too short ancillary data object at all! Oops.
OK, let's add it... OK, let's add it...
*/ */
if (cmsg->cmsg_len < sizeof(struct cmsghdr) || if (!CMSG_OK(msg, cmsg))
(unsigned long)(((char*)cmsg - (char*)msg->msg_control)
+ cmsg->cmsg_len) > msg->msg_controllen)
goto error; goto error;
if (cmsg->cmsg_level != SOL_SOCKET) if (cmsg->cmsg_level != SOL_SOCKET)
......
...@@ -146,11 +146,8 @@ int ip_cmsg_send(struct msghdr *msg, struct ipcm_cookie *ipc) ...@@ -146,11 +146,8 @@ int ip_cmsg_send(struct msghdr *msg, struct ipcm_cookie *ipc)
struct cmsghdr *cmsg; struct cmsghdr *cmsg;
for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) { for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) {
if (cmsg->cmsg_len < sizeof(struct cmsghdr) || if (!CMSG_OK(msg, cmsg))
(unsigned long)(((char*)cmsg - (char*)msg->msg_control)
+ cmsg->cmsg_len) > msg->msg_controllen) {
return -EINVAL; return -EINVAL;
}
if (cmsg->cmsg_level != SOL_IP) if (cmsg->cmsg_level != SOL_IP)
continue; continue;
switch (cmsg->cmsg_type) { switch (cmsg->cmsg_type) {
......
...@@ -427,9 +427,7 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl, ...@@ -427,9 +427,7 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl,
int addr_type; int addr_type;
struct net_device *dev = NULL; struct net_device *dev = NULL;
if (cmsg->cmsg_len < sizeof(struct cmsghdr) || if (!CMSG_OK(msg, cmsg)) {
(unsigned long)(((char*)cmsg - (char*)msg->msg_control)
+ cmsg->cmsg_len) > msg->msg_controllen) {
err = -EINVAL; err = -EINVAL;
goto exit_f; goto exit_f;
} }
......
...@@ -4098,12 +4098,8 @@ SCTP_STATIC int sctp_msghdr_parse(const struct msghdr *msg, ...@@ -4098,12 +4098,8 @@ SCTP_STATIC int sctp_msghdr_parse(const struct msghdr *msg,
for (cmsg = CMSG_FIRSTHDR(msg); for (cmsg = CMSG_FIRSTHDR(msg);
cmsg != NULL; cmsg != NULL;
cmsg = CMSG_NXTHDR((struct msghdr*)msg, cmsg)) { cmsg = CMSG_NXTHDR((struct msghdr*)msg, cmsg)) {
/* Check for minimum length. The SCM code has this check. */ if (!CMSG_OK(msg, cmsg))
if (cmsg->cmsg_len < sizeof(struct cmsghdr) ||
(unsigned long)(((char*)cmsg - (char*)msg->msg_control)
+ cmsg->cmsg_len) > msg->msg_controllen) {
return -EINVAL; return -EINVAL;
}
/* Should we parse this header or ignore? */ /* Should we parse this header or ignore? */
if (cmsg->cmsg_level != IPPROTO_SCTP) 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