Commit be286bafe1f4069094865264f29805854c5788bf

Authored by Oliver Hartkopp
Committed by Marc Kleine-Budde
1 parent d904d3edcb

can: gw: add a variable limit for CAN frame routings

To prevent a possible misconfiguration (e.g. circular CAN frame routings)
limit the number of routings of a single CAN frame to a small variable value.

The limit can be specified by the module parameter 'max_hops' (1..6).
The default value is 1 (one hop), according to the original can-gw behaviour.

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>

Showing 1 changed file with 40 additions and 16 deletions Side-by-side Diff

... ... @@ -42,6 +42,7 @@
42 42 #include <linux/module.h>
43 43 #include <linux/init.h>
44 44 #include <linux/types.h>
  45 +#include <linux/kernel.h>
45 46 #include <linux/list.h>
46 47 #include <linux/spinlock.h>
47 48 #include <linux/rcupdate.h>
48 49  
49 50  
... ... @@ -58,15 +59,26 @@
58 59 #include <net/net_namespace.h>
59 60 #include <net/sock.h>
60 61  
61   -#define CAN_GW_VERSION "20101209"
62   -static __initconst const char banner[] =
63   - KERN_INFO "can: netlink gateway (rev " CAN_GW_VERSION ")\n";
  62 +#define CAN_GW_VERSION "20130117"
  63 +#define CAN_GW_NAME "can-gw"
64 64  
65 65 MODULE_DESCRIPTION("PF_CAN netlink gateway");
66 66 MODULE_LICENSE("Dual BSD/GPL");
67 67 MODULE_AUTHOR("Oliver Hartkopp <oliver.hartkopp@volkswagen.de>");
68   -MODULE_ALIAS("can-gw");
  68 +MODULE_ALIAS(CAN_GW_NAME);
69 69  
  70 +#define CGW_MIN_HOPS 1
  71 +#define CGW_MAX_HOPS 6
  72 +#define CGW_DEFAULT_HOPS 1
  73 +
  74 +static unsigned int max_hops __read_mostly = CGW_DEFAULT_HOPS;
  75 +module_param(max_hops, uint, S_IRUGO);
  76 +MODULE_PARM_DESC(max_hops,
  77 + "maximum " CAN_GW_NAME " routing hops for CAN frames "
  78 + "(valid values: " __stringify(CGW_MIN_HOPS) "-"
  79 + __stringify(CGW_MAX_HOPS) " hops, "
  80 + "default: " __stringify(CGW_DEFAULT_HOPS) ")");
  81 +
70 82 static HLIST_HEAD(cgw_list);
71 83 static struct notifier_block notifier;
72 84  
... ... @@ -339,8 +351,23 @@
339 351 struct sk_buff *nskb;
340 352 int modidx = 0;
341 353  
342   - /* do not handle already routed frames - see comment below */
343   - if (skb_mac_header_was_set(skb))
  354 + /*
  355 + * Do not handle CAN frames routed more than 'max_hops' times.
  356 + * In general we should never catch this delimiter which is intended
  357 + * to cover a misconfiguration protection (e.g. circular CAN routes).
  358 + *
  359 + * The Controller Area Network controllers only accept CAN frames with
  360 + * correct CRCs - which are not visible in the controller registers.
  361 + * According to skbuff.h documentation the csum_start element for IP
  362 + * checksums is undefined/unsued when ip_summed == CHECKSUM_UNNECESSARY.
  363 + * Only CAN skbs can be processed here which already have this property.
  364 + */
  365 +
  366 +#define cgw_hops(skb) ((skb)->csum_start)
  367 +
  368 + BUG_ON(skb->ip_summed != CHECKSUM_UNNECESSARY);
  369 +
  370 + if (cgw_hops(skb) >= max_hops)
344 371 return;
345 372  
346 373 if (!(gwj->dst.dev->flags & IFF_UP)) {
... ... @@ -371,15 +398,8 @@
371 398 return;
372 399 }
373 400  
374   - /*
375   - * Mark routed frames by setting some mac header length which is
376   - * not relevant for the CAN frames located in the skb->data section.
377   - *
378   - * As dev->header_ops is not set in CAN netdevices no one is ever
379   - * accessing the various header offsets in the CAN skbuffs anyway.
380   - * E.g. using the packet socket to read CAN frames is still working.
381   - */
382   - skb_set_mac_header(nskb, 8);
  401 + /* put the incremented hop counter in the cloned skb */
  402 + cgw_hops(nskb) = cgw_hops(skb) + 1;
383 403 nskb->dev = gwj->dst.dev;
384 404  
385 405 /* pointer to modifiable CAN frame */
... ... @@ -903,7 +923,11 @@
903 923  
904 924 static __init int cgw_module_init(void)
905 925 {
906   - printk(banner);
  926 + /* sanitize given module parameter */
  927 + max_hops = clamp_t(unsigned int, max_hops, CGW_MIN_HOPS, CGW_MAX_HOPS);
  928 +
  929 + pr_info("can: netlink gateway (rev " CAN_GW_VERSION ") max_hops=%d\n",
  930 + max_hops);
907 931  
908 932 cgw_cache = kmem_cache_create("can_gw", sizeof(struct cgw_job),
909 933 0, 0, NULL);