All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ben Pfaff <blp@nicira.com>
To: Jamal Hadi Salim <hadi@cyberus.ca>
Cc: netdev@vger.kernel.org
Subject: tc: RTM_GETQDISC causes kernel OOPS
Date: Fri, 21 May 2010 15:42:43 -0700	[thread overview]
Message-ID: <20100521224243.GD10247@nicira.com> (raw)

Hi.  While working on some library code for working with qdiscs and
classes I came upon a kernel OOPS.  Originally I came across it with a
2.6.26 kernel, but I can also reproduce it with unmodified v2.6.34 from
kernel.org.

At the end of this mail I'm appending both an example of the OOPS and a
simple test program that reliably reproduces the problem for me when I
invoke it with "lo" as argument.  The program does not need to be run as
root.

After the OOPS, a lot of networking and other system functions stop
working, so it seems to me a serious issue.

The null pointer dereference that causes the OOPS is the dereference of
the return value of qdisc_dev() in tc_fill_qdisc() in
net/sched/sch_api.c line 1163:

    1161	tcm->tcm__pad1 = 0;
    1162	tcm->tcm__pad2 = 0;
    1163	tcm->tcm_ifindex = qdisc_dev(q)->ifindex;
    1164	tcm->tcm_parent = clid;
    1165	tcm->tcm_handle = q->handle;

I am pretty sure about that, because if I add "WARN_ON(!qdisc_dev(q));"
just before line 1163 then that warning triggers.

Thanks,

Ben.

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

BUG: unable to handle kernel NULL pointer dereference at 00000050
IP: [<c12280c0>] tc_fill_qdisc+0x68/0x1e5
*pde = 00000000 
Oops: 0000 [#1] SMP 
last sysfs file: 
Modules linked in:

Pid: 600, comm: qdisc Not tainted 2.6.34 #16 /
EIP: 0060:[<c12280c0>] EFLAGS: 00010282 CPU: 0
EIP is at tc_fill_qdisc+0x68/0x1e5
EAX: 00000000 EBX: ffffffff ECX: 00000000 EDX: c7222070
ESI: c14576e0 EDI: c7115200 EBP: c7239ca0 ESP: c7239c3c
 DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068
Process qdisc (pid: 600, ti=c7239000 task=c720b700 task.ti=c7239000)
Stack:
 00000024 00000014 00000000 c14323a0 c7222060 c7222060 c10a7abd 00001030
<0> 000000d0 c7222060 000000d0 c1228329 000000d0 00000fc4 000000d0 c7115200
<0> 000000d0 00000ec0 c7239cac c12104b1 00000ec0 c1457a98 c7115200 00000258
Call Trace:
 [<c10a7abd>] ? __kmalloc_track_caller+0x122/0x131
 [<c1228329>] ? qdisc_notify+0x2a/0xc8
 [<c12104b1>] ? __alloc_skb+0x4e/0x115
 [<c122838a>] ? qdisc_notify+0x8b/0xc8
 [<c12287ea>] ? tc_get_qdisc+0x143/0x15d
 [<c12286a7>] ? tc_get_qdisc+0x0/0x15d
 [<c1220c28>] ? rtnetlink_rcv_msg+0x195/0x1af
 [<c1220a93>] ? rtnetlink_rcv_msg+0x0/0x1af
 [<c12329e2>] ? netlink_rcv_skb+0x30/0x75
 [<c1220a8b>] ? rtnetlink_rcv+0x1e/0x26
 [<c123281b>] ? netlink_unicast+0xc4/0x11a
 [<c1232eda>] ? netlink_sendmsg+0x223/0x230
 [<c120978c>] ? sock_sendmsg+0xa8/0xbf
 [<c10514fc>] ? print_lock_contention_bug+0x14/0xd7
 [<c101ebe4>] ? __wake_up+0x15/0x3b
 [<c101ebe4>] ? __wake_up+0x15/0x3b
 [<c101ec00>] ? __wake_up+0x31/0x3b
 [<c10acda4>] ? fget_light+0x2d/0xaf
 [<c109488d>] ? might_fault+0x47/0x81
 [<c120acf9>] ? sys_sendto+0xa4/0xc0
 [<c116b82c>] ? _copy_from_user+0x2e/0x108
 [<c120ad92>] ? sys_connect+0x63/0x6e
 [<c120ad2d>] ? sys_send+0x18/0x1a
 [<c120aedb>] ? sys_socketcall+0xd4/0x1a5
 [<c12ca931>] ? syscall_call+0x7/0xb
Code: 50 8b 55 08 89 f8 6a 14 ff 75 14 e8 49 fa ff ff 89 c2 83 c2 10 89 45 ac c6 42 01 00 66 c7 42 02 00 00 c6 40 10 00 8b 46 40 8b 00 <8b> 40 50 89 5a 0c 89 42 04 8b 46 20 89 42 08 8b 46 28 89 42 10 
EIP: [<c12280c0>] tc_fill_qdisc+0x68/0x1e5 SS:ESP 0068:c7239c3c
CR2: 0000000000000050
---[ end trace 6fb85bbc66de8f42 ]---

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

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#include <linux/rtnetlink.h>
#include <linux/pkt_sched.h>
#include <net/if.h>

int
main(int argc, char *argv[])
{
    struct {
        struct nlmsghdr nlmsg;
        struct tcmsg tcmsg;
    } msg;

    struct sockaddr_nl local, remote;
    int ifindex;
    int fd;

    if (argc != 2) {
        fprintf(stderr,
                "usage: %s <netdev>\n"
                "where <netdev> is a network device, e.g. \"lo\"\n",
                argv[0]);
        return EXIT_FAILURE;
    }

    /* Get ifindex. */
    ifindex = if_nametoindex(argv[1]);
    if (!ifindex) {
        fprintf(stderr, "no network device named \"%s\"", argv[1]);
        return EXIT_FAILURE;
    }

    /* Make rtnetlink socket. */
    fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
    if (fd < 0) {
        perror("socket");
        return EXIT_FAILURE;
    }

    /* Bind local address as our selected pid. */
    memset(&local, 0, sizeof local);
    local.nl_family = AF_NETLINK;
    local.nl_pid = getpid();
    if (bind(fd, (struct sockaddr *) &local, sizeof local) < 0) {
        perror("bind");
        return EXIT_FAILURE;
    }

    /* Bind remote address as the kernel (pid 0). */
    memset(&remote, 0, sizeof remote);
    remote.nl_family = AF_NETLINK;
    remote.nl_pid = 0;
    if (connect(fd, (struct sockaddr *) &remote, sizeof remote) < 0) {
        perror("connect");
        return EXIT_FAILURE;
    }

    /* Send "get" request. */
    memset(&msg, 0, sizeof msg);
    msg.nlmsg.nlmsg_len = sizeof msg;
    msg.nlmsg.nlmsg_type = RTM_GETQDISC;
    msg.nlmsg.nlmsg_flags = NLM_F_REQUEST | NLM_F_ECHO | NLM_F_ACK;
    msg.nlmsg.nlmsg_seq = 1;
    msg.nlmsg.nlmsg_pid = getpid();
    msg.tcmsg.tcm_family = AF_UNSPEC;
    msg.tcmsg.tcm_ifindex = ifindex;
    msg.tcmsg.tcm_handle = 0;
    msg.tcmsg.tcm_parent = TC_H_ROOT;
    if (send(fd, &msg, sizeof msg, 0) < 0) {
        perror("send");
        return EXIT_FAILURE;
    }

    return 0;
}

             reply	other threads:[~2010-05-21 23:13 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-05-21 22:42 Ben Pfaff [this message]
2010-05-22  7:18 ` tc: RTM_GETQDISC causes kernel OOPS Eric Dumazet
2010-05-22  9:51   ` Patrick McHardy
2010-05-22 12:31     ` jamal
2010-05-23  6:37       ` [PATCH] net_sched: Fix qdisc_notify() Eric Dumazet
2010-05-24  6:11         ` David Miller

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20100521224243.GD10247@nicira.com \
    --to=blp@nicira.com \
    --cc=hadi@cyberus.ca \
    --cc=netdev@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.