Skip to content

Commit 4f45b2c

Browse files
jmbergdavem330
authored andcommitted
wext: optimise, comment and fix event sending
The current function for sending events first allocates the event stream buffer, and then an skb to copy the event stream into. This can be done in one go. Also, the current function leaks kernel data to userspace in a 4 uninitialised bytes, initialise those explicitly. Finally also add a few useful comments, as opposed to the current comments. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent b333b3d commit 4f45b2c

File tree

1 file changed

+57
-57
lines changed

1 file changed

+57
-57
lines changed

net/wireless/wext.c

Lines changed: 57 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1300,22 +1300,15 @@ static void wireless_nlevent_process(struct work_struct *work)
13001300

13011301
static DECLARE_WORK(wireless_nlevent_work, wireless_nlevent_process);
13021302

1303-
/* ---------------------------------------------------------------- */
1304-
/*
1305-
* Fill a rtnetlink message with our event data.
1306-
* Note that we propage only the specified event and don't dump the
1307-
* current wireless config. Dumping the wireless config is far too
1308-
* expensive (for each parameter, the driver need to query the hardware).
1309-
*/
1310-
static int rtnetlink_fill_iwinfo(struct sk_buff *skb, struct net_device *dev,
1311-
int type, char *event, int event_len)
1303+
static struct nlmsghdr *rtnetlink_ifinfo_prep(struct net_device *dev,
1304+
struct sk_buff *skb)
13121305
{
13131306
struct ifinfomsg *r;
13141307
struct nlmsghdr *nlh;
13151308

1316-
nlh = nlmsg_put(skb, 0, 0, type, sizeof(*r), 0);
1317-
if (nlh == NULL)
1318-
return -EMSGSIZE;
1309+
nlh = nlmsg_put(skb, 0, 0, RTM_NEWLINK, sizeof(*r), 0);
1310+
if (!nlh)
1311+
return NULL;
13191312

13201313
r = nlmsg_data(nlh);
13211314
r->ifi_family = AF_UNSPEC;
@@ -1326,45 +1319,14 @@ static int rtnetlink_fill_iwinfo(struct sk_buff *skb, struct net_device *dev,
13261319
r->ifi_change = 0; /* Wireless changes don't affect those flags */
13271320

13281321
NLA_PUT_STRING(skb, IFLA_IFNAME, dev->name);
1329-
/* Add the wireless events in the netlink packet */
1330-
NLA_PUT(skb, IFLA_WIRELESS, event_len, event);
1331-
1332-
return nlmsg_end(skb, nlh);
13331322

1334-
nla_put_failure:
1323+
return nlh;
1324+
nla_put_failure:
13351325
nlmsg_cancel(skb, nlh);
1336-
return -EMSGSIZE;
1326+
return NULL;
13371327
}
13381328

1339-
/* ---------------------------------------------------------------- */
1340-
/*
1341-
* Create and broadcast and send it on the standard rtnetlink socket
1342-
* This is a pure clone rtmsg_ifinfo() in net/core/rtnetlink.c
1343-
* Andrzej Krzysztofowicz mandated that I used a IFLA_XXX field
1344-
* within a RTM_NEWLINK event.
1345-
*/
1346-
static void rtmsg_iwinfo(struct net_device *dev, char *event, int event_len)
1347-
{
1348-
struct sk_buff *skb;
1349-
int err;
1350-
1351-
skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
1352-
if (!skb)
1353-
return;
13541329

1355-
err = rtnetlink_fill_iwinfo(skb, dev, RTM_NEWLINK, event, event_len);
1356-
if (err < 0) {
1357-
WARN_ON(err == -EMSGSIZE);
1358-
kfree_skb(skb);
1359-
return;
1360-
}
1361-
1362-
NETLINK_CB(skb).dst_group = RTNLGRP_LINK;
1363-
skb_queue_tail(&dev_net(dev)->wext_nlevents, skb);
1364-
schedule_work(&wireless_nlevent_work);
1365-
}
1366-
1367-
/* ---------------------------------------------------------------- */
13681330
/*
13691331
* Main event dispatcher. Called from other parts and drivers.
13701332
* Send the event on the appropriate channels.
@@ -1383,6 +1345,9 @@ void wireless_send_event(struct net_device * dev,
13831345
int wrqu_off = 0; /* Offset in wrqu */
13841346
/* Don't "optimise" the following variable, it will crash */
13851347
unsigned cmd_index; /* *MUST* be unsigned */
1348+
struct sk_buff *skb;
1349+
struct nlmsghdr *nlh;
1350+
struct nlattr *nla;
13861351

13871352
/* Get the description of the Event */
13881353
if (cmd <= SIOCIWLAST) {
@@ -1430,25 +1395,60 @@ void wireless_send_event(struct net_device * dev,
14301395
hdr_len = event_type_size[descr->header_type];
14311396
event_len = hdr_len + extra_len;
14321397

1433-
/* Create temporary buffer to hold the event */
1434-
event = kmalloc(event_len, GFP_ATOMIC);
1435-
if (event == NULL)
1398+
/*
1399+
* The problem for 64/32 bit.
1400+
*
1401+
* On 64-bit, a regular event is laid out as follows:
1402+
* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
1403+
* | event.len | event.cmd | p a d d i n g |
1404+
* | wrqu data ... (with the correct size) |
1405+
*
1406+
* This padding exists because we manipulate event->u,
1407+
* and 'event' is not packed.
1408+
*
1409+
* An iw_point event is laid out like this instead:
1410+
* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
1411+
* | event.len | event.cmd | p a d d i n g |
1412+
* | iwpnt.len | iwpnt.flg | p a d d i n g |
1413+
* | extra data ...
1414+
*
1415+
* The second padding exists because struct iw_point is extended,
1416+
* but this depends on the platform...
1417+
*
1418+
* On 32-bit, all the padding shouldn't be there.
1419+
*/
1420+
1421+
skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
1422+
if (!skb)
1423+
return;
1424+
1425+
/* Send via the RtNetlink event channel */
1426+
nlh = rtnetlink_ifinfo_prep(dev, skb);
1427+
if (WARN_ON(!nlh)) {
1428+
kfree_skb(skb);
1429+
return;
1430+
}
1431+
1432+
/* Add the wireless events in the netlink packet */
1433+
nla = nla_reserve(skb, IFLA_WIRELESS, event_len);
1434+
if (!nla) {
1435+
kfree_skb(skb);
14361436
return;
1437+
}
1438+
event = nla_data(nla);
14371439

1438-
/* Fill event */
1440+
/* Fill event - first clear to avoid data leaking */
1441+
memset(event, 0, hdr_len);
14391442
event->len = event_len;
14401443
event->cmd = cmd;
14411444
memcpy(&event->u, ((char *) wrqu) + wrqu_off, hdr_len - IW_EV_LCP_LEN);
1442-
if (extra)
1445+
if (extra_len)
14431446
memcpy(((char *) event) + hdr_len, extra, extra_len);
14441447

1445-
/* Send via the RtNetlink event channel */
1446-
rtmsg_iwinfo(dev, (char *) event, event_len);
1447-
1448-
/* Cleanup */
1449-
kfree(event);
1448+
nlmsg_end(skb, nlh);
14501449

1451-
return; /* Always success, I guess ;-) */
1450+
skb_queue_tail(&dev_net(dev)->wext_nlevents, skb);
1451+
schedule_work(&wireless_nlevent_work);
14521452
}
14531453
EXPORT_SYMBOL(wireless_send_event);
14541454

0 commit comments

Comments
 (0)