aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2009-06-23 21:34:49 -0400
committerDavid S. Miller <davem@davemloft.net>2009-07-15 11:53:37 -0400
commit4f45b2cd4e78b5e49d7d41548345b879d3fdfeae (patch)
treea93bd6d6b40e0271bb0e2e4ab775e2e68bc041e8
parentb333b3d22822cf9b295990866798e9239c9dee72 (diff)
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>
-rw-r--r--net/wireless/wext.c114
1 files changed, 57 insertions, 57 deletions
diff --git a/net/wireless/wext.c b/net/wireless/wext.c
index db8351a5a87d..ee35e6422f1f 100644
--- a/net/wireless/wext.c
+++ b/net/wireless/wext.c
@@ -1300,22 +1300,15 @@ static void wireless_nlevent_process(struct work_struct *work)
1300 1300
1301static DECLARE_WORK(wireless_nlevent_work, wireless_nlevent_process); 1301static DECLARE_WORK(wireless_nlevent_work, wireless_nlevent_process);
1302 1302
1303/* ---------------------------------------------------------------- */ 1303static struct nlmsghdr *rtnetlink_ifinfo_prep(struct net_device *dev,
1304/* 1304 struct sk_buff *skb)
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 */
1310static int rtnetlink_fill_iwinfo(struct sk_buff *skb, struct net_device *dev,
1311 int type, char *event, int event_len)
1312{ 1305{
1313 struct ifinfomsg *r; 1306 struct ifinfomsg *r;
1314 struct nlmsghdr *nlh; 1307 struct nlmsghdr *nlh;
1315 1308
1316 nlh = nlmsg_put(skb, 0, 0, type, sizeof(*r), 0); 1309 nlh = nlmsg_put(skb, 0, 0, RTM_NEWLINK, sizeof(*r), 0);
1317 if (nlh == NULL) 1310 if (!nlh)
1318 return -EMSGSIZE; 1311 return NULL;
1319 1312
1320 r = nlmsg_data(nlh); 1313 r = nlmsg_data(nlh);
1321 r->ifi_family = AF_UNSPEC; 1314 r->ifi_family = AF_UNSPEC;
@@ -1326,45 +1319,14 @@ static int rtnetlink_fill_iwinfo(struct sk_buff *skb, struct net_device *dev,
1326 r->ifi_change = 0; /* Wireless changes don't affect those flags */ 1319 r->ifi_change = 0; /* Wireless changes don't affect those flags */
1327 1320
1328 NLA_PUT_STRING(skb, IFLA_IFNAME, dev->name); 1321 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);
1333 1322
1334nla_put_failure: 1323 return nlh;
1324 nla_put_failure:
1335 nlmsg_cancel(skb, nlh); 1325 nlmsg_cancel(skb, nlh);
1336 return -EMSGSIZE; 1326 return NULL;
1337} 1327}
1338 1328
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 */
1346static 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;
1354 1329
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/* ---------------------------------------------------------------- */
1368/* 1330/*
1369 * Main event dispatcher. Called from other parts and drivers. 1331 * Main event dispatcher. Called from other parts and drivers.
1370 * Send the event on the appropriate channels. 1332 * Send the event on the appropriate channels.
@@ -1383,6 +1345,9 @@ void wireless_send_event(struct net_device * dev,
1383 int wrqu_off = 0; /* Offset in wrqu */ 1345 int wrqu_off = 0; /* Offset in wrqu */
1384 /* Don't "optimise" the following variable, it will crash */ 1346 /* Don't "optimise" the following variable, it will crash */
1385 unsigned cmd_index; /* *MUST* be unsigned */ 1347 unsigned cmd_index; /* *MUST* be unsigned */
1348 struct sk_buff *skb;
1349 struct nlmsghdr *nlh;
1350 struct nlattr *nla;
1386 1351
1387 /* Get the description of the Event */ 1352 /* Get the description of the Event */
1388 if (cmd <= SIOCIWLAST) { 1353 if (cmd <= SIOCIWLAST) {
@@ -1430,25 +1395,60 @@ void wireless_send_event(struct net_device * dev,
1430 hdr_len = event_type_size[descr->header_type]; 1395 hdr_len = event_type_size[descr->header_type];
1431 event_len = hdr_len + extra_len; 1396 event_len = hdr_len + extra_len;
1432 1397
1433 /* Create temporary buffer to hold the event */ 1398 /*
1434 event = kmalloc(event_len, GFP_ATOMIC); 1399 * The problem for 64/32 bit.
1435 if (event == NULL) 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);
1436 return; 1436 return;
1437 }
1438 event = nla_data(nla);
1437 1439
1438 /* Fill event */ 1440 /* Fill event - first clear to avoid data leaking */
1441 memset(event, 0, hdr_len);
1439 event->len = event_len; 1442 event->len = event_len;
1440 event->cmd = cmd; 1443 event->cmd = cmd;
1441 memcpy(&event->u, ((char *) wrqu) + wrqu_off, hdr_len - IW_EV_LCP_LEN); 1444 memcpy(&event->u, ((char *) wrqu) + wrqu_off, hdr_len - IW_EV_LCP_LEN);
1442 if (extra) 1445 if (extra_len)
1443 memcpy(((char *) event) + hdr_len, extra, extra_len); 1446 memcpy(((char *) event) + hdr_len, extra, extra_len);
1444 1447
1445 /* Send via the RtNetlink event channel */ 1448 nlmsg_end(skb, nlh);
1446 rtmsg_iwinfo(dev, (char *) event, event_len);
1447
1448 /* Cleanup */
1449 kfree(event);
1450 1449
1451 return; /* Always success, I guess ;-) */ 1450 skb_queue_tail(&dev_net(dev)->wext_nlevents, skb);
1451 schedule_work(&wireless_nlevent_work);
1452} 1452}
1453EXPORT_SYMBOL(wireless_send_event); 1453EXPORT_SYMBOL(wireless_send_event);
1454 1454