Skip to content

Commit

Permalink
net: validate HWTSTAMP ioctl parameters
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Richard Cochran authored and David S. Miller committed Oct 19, 2011
1 parent 850a545 commit 4dc360c
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 2 deletions.
4 changes: 2 additions & 2 deletions include/linux/net_tstamp.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ struct hwtstamp_config {
};

/* possible values for hwtstamp_config->tx_type */
enum {
enum hwtstamp_tx_types {
/*
* No outgoing packet will need hardware time stamping;
* should a packet arrive which asks for it, no hardware
Expand All @@ -72,7 +72,7 @@ enum {
};

/* possible values for hwtstamp_config->rx_filter */
enum {
enum hwtstamp_rx_filters {
/* time stamp no incoming packet at all */
HWTSTAMP_FILTER_NONE,

Expand Down
58 changes: 58 additions & 0 deletions net/core/dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@
#include <linux/if_tunnel.h>
#include <linux/if_pppox.h>
#include <linux/ppp_defs.h>
#include <linux/net_tstamp.h>

#include "net-sysfs.h"

Expand Down Expand Up @@ -1477,6 +1478,57 @@ static inline void net_timestamp_check(struct sk_buff *skb)
__net_timestamp(skb);
}

static int net_hwtstamp_validate(struct ifreq *ifr)
{
struct hwtstamp_config cfg;
enum hwtstamp_tx_types tx_type;
enum hwtstamp_rx_filters rx_filter;
int tx_type_valid = 0;
int rx_filter_valid = 0;

if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg)))
return -EFAULT;

if (cfg.flags) /* reserved for future extensions */
return -EINVAL;

tx_type = cfg.tx_type;
rx_filter = cfg.rx_filter;

switch (tx_type) {
case HWTSTAMP_TX_OFF:
case HWTSTAMP_TX_ON:
case HWTSTAMP_TX_ONESTEP_SYNC:
tx_type_valid = 1;
break;
}

switch (rx_filter) {
case HWTSTAMP_FILTER_NONE:
case HWTSTAMP_FILTER_ALL:
case HWTSTAMP_FILTER_SOME:
case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
case HWTSTAMP_FILTER_PTP_V2_EVENT:
case HWTSTAMP_FILTER_PTP_V2_SYNC:
case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
rx_filter_valid = 1;
break;
}

if (!tx_type_valid || !rx_filter_valid)
return -ERANGE;

return 0;
}

static inline bool is_skb_forwardable(struct net_device *dev,
struct sk_buff *skb)
{
Expand Down Expand Up @@ -4921,6 +4973,12 @@ static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd)
ifr->ifr_newname[IFNAMSIZ-1] = '\0';
return dev_change_name(dev, ifr->ifr_newname);

case SIOCSHWTSTAMP:
err = net_hwtstamp_validate(ifr);
if (err)
return err;
/* fall through */

/*
* Unknown or private ioctl
*/
Expand Down

0 comments on commit 4dc360c

Please sign in to comment.