From: Greg KH <gre...@linuxfoundation.org>

3.4-stable review patch.  If anyone has any objections, please let me know.

------------------


From: Paul Moore <pmo...@redhat.com>

[ Upstream commit 89d7ae34cdda4195809a5a987f697a517a2a3177 ]

As reported by Alan Cox, and verified by Lin Ming, when a user
attempts to add a CIPSO option to a socket using the CIPSO_V4_TAG_LOCAL
tag the kernel dies a terrible death when it attempts to follow a NULL
pointer (the skb argument to cipso_v4_validate() is NULL when called via
the setsockopt() syscall).

This patch fixes this by first checking to ensure that the skb is
non-NULL before using it to find the incoming network interface.  In
the unlikely case where the skb is NULL and the user attempts to add
a CIPSO option with the _TAG_LOCAL tag we return an error as this is
not something we want to allow.

A simple reproducer, kindly supplied by Lin Ming, although you must
have the CIPSO DOI #3 configure on the system first or you will be
caught early in cipso_v4_validate():

        #include <sys/types.h>
        #include <sys/socket.h>
        #include <linux/ip.h>
        #include <linux/in.h>
        #include <string.h>

        struct local_tag {
                char type;
                char length;
                char info[4];
        };

        struct cipso {
                char type;
                char length;
                char doi[4];
                struct local_tag local;
        };

        int main(int argc, char **argv)
        {
                int sockfd;
                struct cipso cipso = {
                        .type = IPOPT_CIPSO,
                        .length = sizeof(struct cipso),
                        .local = {
                                .type = 128,
                                .length = sizeof(struct local_tag),
                        },
                };

                memset(cipso.doi, 0, 4);
                cipso.doi[3] = 3;

                sockfd = socket(AF_INET, SOCK_DGRAM, 0);
                #define SOL_IP 0
                setsockopt(sockfd, SOL_IP, IP_OPTIONS,
                        &cipso, sizeof(struct cipso));

                return 0;
        }

CC: Lin Ming <m...@ss.pku.edu.cn>
Reported-by: Alan Cox <a...@lxorguk.ukuu.org.uk>
Signed-off-by: Paul Moore <pmo...@redhat.com>
Signed-off-by: David S. Miller <da...@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gre...@linuxfoundation.org>
---
 net/ipv4/cipso_ipv4.c |    6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

--- a/net/ipv4/cipso_ipv4.c
+++ b/net/ipv4/cipso_ipv4.c
@@ -1725,8 +1725,10 @@ int cipso_v4_validate(const struct sk_bu
                case CIPSO_V4_TAG_LOCAL:
                        /* This is a non-standard tag that we only allow for
                         * local connections, so if the incoming interface is
-                        * not the loopback device drop the packet. */
-                       if (!(skb->dev->flags & IFF_LOOPBACK)) {
+                        * not the loopback device drop the packet. Further,
+                        * there is no legitimate reason for setting this from
+                        * userspace so reject it if skb is NULL. */
+                       if (skb == NULL || !(skb->dev->flags & IFF_LOOPBACK)) {
                                err_offset = opt_iter;
                                goto validate_return_locked;
                        }


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to