netdev
[Top] [All Lists]

ipv6 UDP MSG_MORE oops fix

To: yoshfuji@xxxxxxxxxxxxxx
Subject: ipv6 UDP MSG_MORE oops fix
From: "David S. Miller" <davem@xxxxxxxxxx>
Date: Thu, 7 Aug 2003 22:34:21 -0700
Cc: kuznet@xxxxxxxxxxxxx, netdev@xxxxxxxxxxx
Sender: netdev-bounce@xxxxxxxxxxx
Yoshfuji-san, I found the MSG_MORE udp bug.

If "np->pending" is true, we call ip_dst_store() with uninitialized
dst, it could be any kind of garbage.  This is dereferenced and we
crash.

If np->pending, we have some 'dst' stored into the socket already.
So no need to relookup dst or anything like that.

This is the fix I am using, on top of Miyazawa-san's ah6_input
and authentication error patches.

# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
#                  ChangeSet    1.1167  -> 1.1168 
#       net/ipv6/ip6_output.c   1.40    -> 1.41   
#             net/ipv6/raw.c    1.38    -> 1.39   
#             net/ipv6/udp.c    1.45    -> 1.46   
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 03/08/07      davem@xxxxxxxxxxxxxx    1.1168
# [IPV6]: Make sure errors propagate properly in {udp,raw} sendmsg.
# --------------------------------------------
#
diff -Nru a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
--- a/net/ipv6/ip6_output.c     Thu Aug  7 22:34:06 2003
+++ b/net/ipv6/ip6_output.c     Thu Aug  7 22:34:06 2003
@@ -209,7 +209,6 @@
        int seg_len = skb->len;
        int hlimit;
        u32 mtu;
-       int err = 0;
 
        if (opt) {
                int head_room;
diff -Nru a/net/ipv6/raw.c b/net/ipv6/raw.c
--- a/net/ipv6/raw.c    Thu Aug  7 22:34:06 2003
+++ b/net/ipv6/raw.c    Thu Aug  7 22:34:06 2003
@@ -659,7 +659,7 @@
                fl.oif = np->mcast_oif;
 
        dst = ip6_dst_lookup(sk, &fl);
-       if (dst->error)
+       if ((err = dst->error))
                goto out;
 
        if (hlimit < 0) {
diff -Nru a/net/ipv6/udp.c b/net/ipv6/udp.c
--- a/net/ipv6/udp.c    Thu Aug  7 22:34:06 2003
+++ b/net/ipv6/udp.c    Thu Aug  7 22:34:06 2003
@@ -811,8 +811,10 @@
                 * The socket lock must be held while it's corked.
                 */
                lock_sock(sk);
-               if (likely(up->pending))
+               if (likely(up->pending)) {
+                       dst = NULL;
                        goto do_append_data;
+               }
                release_sock(sk);
        }
        ulen += sizeof(struct udphdr);
@@ -929,7 +931,7 @@
                fl.oif = np->mcast_oif;
 
        dst = ip6_dst_lookup(sk, &fl);
-       if (dst->error)
+       if ((err = dst->error))
                goto out;
 
        if (hlimit < 0) {
@@ -968,9 +970,10 @@
        else if (!corkreq)
                err = udp_v6_push_pending_frames(sk, up);
 
-       ip6_dst_store(sk, dst,
-                     !ipv6_addr_cmp(&fl.fl6_dst, &np->daddr) ?
-                     &np->daddr : NULL);
+       if (dst)
+               ip6_dst_store(sk, dst,
+                             !ipv6_addr_cmp(&fl.fl6_dst, &np->daddr) ?
+                             &np->daddr : NULL);
        if (err > 0)
                err = np->recverr ? net_xmit_errno(err) : 0;
        release_sock(sk);

<Prev in Thread] Current Thread [Next in Thread>