Vulnerability: net/bridge/br_mdb.c in the Linux kernel before 3.8.4 does not initialize certain structures, which allows local users to obtain sensitive information from kernel memory via a crafted application.
Vulnerability ID: CVE-2013-2636
CWE: CWE-399
Severity score: 2.9
Project: https://github.com/torvalds/linux
Published: 2013-03-22
File: net/bridge/br_mdb.c
Commit message: bridge: fix mdb info leaks

The bridging code discloses heap and stack bytes via the RTM_GETMDB
netlink interface and via the notify messages send to group RTNLGRP_MDB
afer a successful add/del.

Fix both cases by initializing all unset members/padding bytes with
memset(0).

Cc: Stephen Hemminger <stephen@networkplumber.org>
Signed-off-by: Mathias Krause <minipli@googlemail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Commit author: Mathias Krause

Vulnerable version (before fix):
 static int br_mdb_fill_info(struct sk_buff *skb, struct netlink_callback *cb, 				port = p->port; 				if (port) { 					struct br_mdb_entry e; 					e.ifindex = port->dev->ifindex; 					e.state = p->state; 					if (p->addr.proto == htons(ETH_P_IP)) static int br_mdb_dump(struct sk_buff *skb, struct netlink_callback *cb) 				break;  			bpm = nlmsg_data(nlh); 			bpm->ifindex = dev->ifindex; 			if (br_mdb_fill_info(skb, cb, dev) < 0) 				goto out; static int nlmsg_populate_mdb_fill(struct sk_buff *skb, 		return -EMSGSIZE;  	bpm = nlmsg_data(nlh); 	bpm->family  = AF_BRIDGE; 	bpm->ifindex = dev->ifindex; 	nest = nla_nest_start(skb, MDBA_MDB); void br_mdb_notify(struct net_device *dev, struct net_bridge_port *port, { 	struct br_mdb_entry entry;  	entry.ifindex = port->dev->ifindex; 	entry.addr.proto = group->proto; 	entry.addr.u.ip4 = group->u.ip4;

Fixed version (after fix):
 static int br_mdb_fill_info(struct sk_buff *skb, struct netlink_callback *cb, 				port = p->port; 				if (port) { 					struct br_mdb_entry e; 					memset(&e, 0, sizeof(e)); 					e.ifindex = port->dev->ifindex; 					e.state = p->state; 					if (p->addr.proto == htons(ETH_P_IP)) static int br_mdb_dump(struct sk_buff *skb, struct netlink_callback *cb) 				break;  			bpm = nlmsg_data(nlh); 			memset(bpm, 0, sizeof(*bpm)); 			bpm->ifindex = dev->ifindex; 			if (br_mdb_fill_info(skb, cb, dev) < 0) 				goto out; static int nlmsg_populate_mdb_fill(struct sk_buff *skb, 		return -EMSGSIZE;  	bpm = nlmsg_data(nlh); 	memset(bpm, 0, sizeof(*bpm)); 	bpm->family  = AF_BRIDGE; 	bpm->ifindex = dev->ifindex; 	nest = nla_nest_start(skb, MDBA_MDB); void br_mdb_notify(struct net_device *dev, struct net_bridge_port *port, { 	struct br_mdb_entry entry;  	memset(&entry, 0, sizeof(entry)); 	entry.ifindex = port->dev->ifindex; 	entry.addr.proto = group->proto; 	entry.addr.u.ip4 = group->u.ip4;

Patch:
patch: @@ -80,6 +80,7 @@ static int br_mdb_fill_info(struct sk_buff *skb, struct netlink_callback *cb,
 				port = p->port;
 				if (port) {
 					struct br_mdb_entry e;
+					memset(&e, 0, sizeof(e));
 					e.ifindex = port->dev->ifindex;
 					e.state = p->state;
 					if (p->addr.proto == htons(ETH_P_IP))
@@ -136,6 +137,7 @@ static int br_mdb_dump(struct sk_buff *skb, struct netlink_callback *cb)
 				break;
 
 			bpm = nlmsg_data(nlh);
+			memset(bpm, 0, sizeof(*bpm));
 			bpm->ifindex = dev->ifindex;
 			if (br_mdb_fill_info(skb, cb, dev) < 0)
 				goto out;
@@ -171,6 +173,7 @@ static int nlmsg_populate_mdb_fill(struct sk_buff *skb,
 		return -EMSGSIZE;
 
 	bpm = nlmsg_data(nlh);
+	memset(bpm, 0, sizeof(*bpm));
 	bpm->family  = AF_BRIDGE;
 	bpm->ifindex = dev->ifindex;
 	nest = nla_nest_start(skb, MDBA_MDB);
@@ -228,6 +231,7 @@ void br_mdb_notify(struct net_device *dev, struct net_bridge_port *port,
 {
 	struct br_mdb_entry entry;
 
+	memset(&entry, 0, sizeof(entry));
 	entry.ifindex = port->dev->ifindex;
 	entry.addr.proto = group->proto;
 	entry.addr.u.ip4 = group->u.ip4;
path: net/bridge/br_mdb.c