Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Johannes Berg and committed by
David S. Miller
4f45b2cd b333b3d2

+57 -57
+57 -57
net/wireless/wext.c
··· 1300 1300 1301 1301 static DECLARE_WORK(wireless_nlevent_work, wireless_nlevent_process); 1302 1302 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) 1312 1305 { 1313 1306 struct ifinfomsg *r; 1314 1307 struct nlmsghdr *nlh; 1315 1308 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; 1319 1312 1320 1313 r = nlmsg_data(nlh); 1321 1314 r->ifi_family = AF_UNSPEC; ··· 1319 1326 r->ifi_change = 0; /* Wireless changes don't affect those flags */ 1320 1327 1321 1328 NLA_PUT_STRING(skb, IFLA_IFNAME, dev->name); 1322 - /* Add the wireless events in the netlink packet */ 1323 - NLA_PUT(skb, IFLA_WIRELESS, event_len, event); 1324 1329 1325 - return nlmsg_end(skb, nlh); 1326 - 1327 - nla_put_failure: 1330 + return nlh; 1331 + nla_put_failure: 1328 1332 nlmsg_cancel(skb, nlh); 1329 - return -EMSGSIZE; 1333 + return NULL; 1330 1334 } 1331 1335 1332 - /* ---------------------------------------------------------------- */ 1333 - /* 1334 - * Create and broadcast and send it on the standard rtnetlink socket 1335 - * This is a pure clone rtmsg_ifinfo() in net/core/rtnetlink.c 1336 - * Andrzej Krzysztofowicz mandated that I used a IFLA_XXX field 1337 - * within a RTM_NEWLINK event. 1338 - */ 1339 - static void rtmsg_iwinfo(struct net_device *dev, char *event, int event_len) 1340 - { 1341 - struct sk_buff *skb; 1342 - int err; 1343 1336 1344 - skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC); 1345 - if (!skb) 1346 - return; 1347 - 1348 - err = rtnetlink_fill_iwinfo(skb, dev, RTM_NEWLINK, event, event_len); 1349 - if (err < 0) { 1350 - WARN_ON(err == -EMSGSIZE); 1351 - kfree_skb(skb); 1352 - return; 1353 - } 1354 - 1355 - NETLINK_CB(skb).dst_group = RTNLGRP_LINK; 1356 - skb_queue_tail(&dev_net(dev)->wext_nlevents, skb); 1357 - schedule_work(&wireless_nlevent_work); 1358 - } 1359 - 1360 - /* ---------------------------------------------------------------- */ 1361 1337 /* 1362 1338 * Main event dispatcher. Called from other parts and drivers. 1363 1339 * Send the event on the appropriate channels. ··· 1345 1383 int wrqu_off = 0; /* Offset in wrqu */ 1346 1384 /* Don't "optimise" the following variable, it will crash */ 1347 1385 unsigned cmd_index; /* *MUST* be unsigned */ 1386 + struct sk_buff *skb; 1387 + struct nlmsghdr *nlh; 1388 + struct nlattr *nla; 1348 1389 1349 1390 /* Get the description of the Event */ 1350 1391 if (cmd <= SIOCIWLAST) { ··· 1395 1430 hdr_len = event_type_size[descr->header_type]; 1396 1431 event_len = hdr_len + extra_len; 1397 1432 1398 - /* Create temporary buffer to hold the event */ 1399 - event = kmalloc(event_len, GFP_ATOMIC); 1400 - if (event == NULL) 1433 + /* 1434 + * The problem for 64/32 bit. 1435 + * 1436 + * On 64-bit, a regular event is laid out as follows: 1437 + * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 1438 + * | event.len | event.cmd | p a d d i n g | 1439 + * | wrqu data ... (with the correct size) | 1440 + * 1441 + * This padding exists because we manipulate event->u, 1442 + * and 'event' is not packed. 1443 + * 1444 + * An iw_point event is laid out like this instead: 1445 + * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 1446 + * | event.len | event.cmd | p a d d i n g | 1447 + * | iwpnt.len | iwpnt.flg | p a d d i n g | 1448 + * | extra data ... 1449 + * 1450 + * The second padding exists because struct iw_point is extended, 1451 + * but this depends on the platform... 1452 + * 1453 + * On 32-bit, all the padding shouldn't be there. 1454 + */ 1455 + 1456 + skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC); 1457 + if (!skb) 1401 1458 return; 1402 1459 1403 - /* Fill event */ 1460 + /* Send via the RtNetlink event channel */ 1461 + nlh = rtnetlink_ifinfo_prep(dev, skb); 1462 + if (WARN_ON(!nlh)) { 1463 + kfree_skb(skb); 1464 + return; 1465 + } 1466 + 1467 + /* Add the wireless events in the netlink packet */ 1468 + nla = nla_reserve(skb, IFLA_WIRELESS, event_len); 1469 + if (!nla) { 1470 + kfree_skb(skb); 1471 + return; 1472 + } 1473 + event = nla_data(nla); 1474 + 1475 + /* Fill event - first clear to avoid data leaking */ 1476 + memset(event, 0, hdr_len); 1404 1477 event->len = event_len; 1405 1478 event->cmd = cmd; 1406 1479 memcpy(&event->u, ((char *) wrqu) + wrqu_off, hdr_len - IW_EV_LCP_LEN); 1407 - if (extra) 1480 + if (extra_len) 1408 1481 memcpy(((char *) event) + hdr_len, extra, extra_len); 1409 1482 1410 - /* Send via the RtNetlink event channel */ 1411 - rtmsg_iwinfo(dev, (char *) event, event_len); 1483 + nlmsg_end(skb, nlh); 1412 1484 1413 - /* Cleanup */ 1414 - kfree(event); 1415 - 1416 - return; /* Always success, I guess ;-) */ 1485 + skb_queue_tail(&dev_net(dev)->wext_nlevents, skb); 1486 + schedule_work(&wireless_nlevent_work); 1417 1487 } 1418 1488 EXPORT_SYMBOL(wireless_send_event); 1419 1489