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

net: validate HWTSTAMP ioctl parameters

This patch adds a sanity check on the values provided by user space for
the hardware time stamping configuration. If the values lie outside of
the absolute limits, then the ioctl request will be denied.

Signed-off-by: Richard Cochran <richard.cochran@omicron.at>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Richard Cochran and committed by
David S. Miller
4dc360c5 850a545b

+60 -2
+2 -2
include/linux/net_tstamp.h
··· 45 45 }; 46 46 47 47 /* possible values for hwtstamp_config->tx_type */ 48 - enum { 48 + enum hwtstamp_tx_types { 49 49 /* 50 50 * No outgoing packet will need hardware time stamping; 51 51 * should a packet arrive which asks for it, no hardware ··· 72 72 }; 73 73 74 74 /* possible values for hwtstamp_config->rx_filter */ 75 - enum { 75 + enum hwtstamp_rx_filters { 76 76 /* time stamp no incoming packet at all */ 77 77 HWTSTAMP_FILTER_NONE, 78 78
+58
net/core/dev.c
··· 136 136 #include <linux/if_tunnel.h> 137 137 #include <linux/if_pppox.h> 138 138 #include <linux/ppp_defs.h> 139 + #include <linux/net_tstamp.h> 139 140 140 141 #include "net-sysfs.h" 141 142 ··· 1476 1475 { 1477 1476 if (!skb->tstamp.tv64 && atomic_read(&netstamp_needed)) 1478 1477 __net_timestamp(skb); 1478 + } 1479 + 1480 + static int net_hwtstamp_validate(struct ifreq *ifr) 1481 + { 1482 + struct hwtstamp_config cfg; 1483 + enum hwtstamp_tx_types tx_type; 1484 + enum hwtstamp_rx_filters rx_filter; 1485 + int tx_type_valid = 0; 1486 + int rx_filter_valid = 0; 1487 + 1488 + if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg))) 1489 + return -EFAULT; 1490 + 1491 + if (cfg.flags) /* reserved for future extensions */ 1492 + return -EINVAL; 1493 + 1494 + tx_type = cfg.tx_type; 1495 + rx_filter = cfg.rx_filter; 1496 + 1497 + switch (tx_type) { 1498 + case HWTSTAMP_TX_OFF: 1499 + case HWTSTAMP_TX_ON: 1500 + case HWTSTAMP_TX_ONESTEP_SYNC: 1501 + tx_type_valid = 1; 1502 + break; 1503 + } 1504 + 1505 + switch (rx_filter) { 1506 + case HWTSTAMP_FILTER_NONE: 1507 + case HWTSTAMP_FILTER_ALL: 1508 + case HWTSTAMP_FILTER_SOME: 1509 + case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: 1510 + case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: 1511 + case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: 1512 + case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: 1513 + case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: 1514 + case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: 1515 + case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: 1516 + case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: 1517 + case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: 1518 + case HWTSTAMP_FILTER_PTP_V2_EVENT: 1519 + case HWTSTAMP_FILTER_PTP_V2_SYNC: 1520 + case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: 1521 + rx_filter_valid = 1; 1522 + break; 1523 + } 1524 + 1525 + if (!tx_type_valid || !rx_filter_valid) 1526 + return -ERANGE; 1527 + 1528 + return 0; 1479 1529 } 1480 1530 1481 1531 static inline bool is_skb_forwardable(struct net_device *dev, ··· 4972 4920 case SIOCSIFNAME: 4973 4921 ifr->ifr_newname[IFNAMSIZ-1] = '\0'; 4974 4922 return dev_change_name(dev, ifr->ifr_newname); 4923 + 4924 + case SIOCSHWTSTAMP: 4925 + err = net_hwtstamp_validate(ifr); 4926 + if (err) 4927 + return err; 4928 + /* fall through */ 4975 4929 4976 4930 /* 4977 4931 * Unknown or private ioctl