diff options
author | Phoebe Buckheister <phoebe.buckheister@itwm.fraunhofer.de> | 2014-05-16 11:46:41 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-05-16 17:23:41 -0400 |
commit | af9eed5bbf0fb4e398081e79a707545dcca5ebda (patch) | |
tree | 9692f6122fa3b281cc89410bad98d796bfa1eace /net/ieee802154 | |
parent | f30be4d53cada48598dab0983866ae4b16af46dc (diff) |
ieee802154: add dgram sockopts for security control
Allow datagram sockets to override the security settings of the device
they send from on a per-socket basis. Requires CAP_NET_ADMIN or
CAP_NET_RAW, since raw sockets can send arbitrary packets anyway.
Signed-off-by: Phoebe Buckheister <phoebe.buckheister@itwm.fraunhofer.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ieee802154')
-rw-r--r-- | net/ieee802154/dgram.c | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/net/ieee802154/dgram.c b/net/ieee802154/dgram.c index 76c77256a56e..4f0ed8780194 100644 --- a/net/ieee802154/dgram.c +++ b/net/ieee802154/dgram.c | |||
@@ -21,6 +21,7 @@ | |||
21 | * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> | 21 | * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> |
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include <linux/capability.h> | ||
24 | #include <linux/net.h> | 25 | #include <linux/net.h> |
25 | #include <linux/module.h> | 26 | #include <linux/module.h> |
26 | #include <linux/if_arp.h> | 27 | #include <linux/if_arp.h> |
@@ -47,6 +48,10 @@ struct dgram_sock { | |||
47 | unsigned int bound:1; | 48 | unsigned int bound:1; |
48 | unsigned int connected:1; | 49 | unsigned int connected:1; |
49 | unsigned int want_ack:1; | 50 | unsigned int want_ack:1; |
51 | unsigned int secen:1; | ||
52 | unsigned int secen_override:1; | ||
53 | unsigned int seclevel:3; | ||
54 | unsigned int seclevel_override:1; | ||
50 | }; | 55 | }; |
51 | 56 | ||
52 | static inline struct dgram_sock *dgram_sk(const struct sock *sk) | 57 | static inline struct dgram_sock *dgram_sk(const struct sock *sk) |
@@ -264,6 +269,11 @@ static int dgram_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
264 | dst_addr = ro->dst_addr; | 269 | dst_addr = ro->dst_addr; |
265 | } | 270 | } |
266 | 271 | ||
272 | cb->secen = ro->secen; | ||
273 | cb->secen_override = ro->secen_override; | ||
274 | cb->seclevel = ro->seclevel; | ||
275 | cb->seclevel_override = ro->seclevel_override; | ||
276 | |||
267 | err = dev_hard_header(skb, dev, ETH_P_IEEE802154, &dst_addr, | 277 | err = dev_hard_header(skb, dev, ETH_P_IEEE802154, &dst_addr, |
268 | ro->bound ? &ro->src_addr : NULL, size); | 278 | ro->bound ? &ro->src_addr : NULL, size); |
269 | if (err < 0) | 279 | if (err < 0) |
@@ -427,6 +437,20 @@ static int dgram_getsockopt(struct sock *sk, int level, int optname, | |||
427 | case WPAN_WANTACK: | 437 | case WPAN_WANTACK: |
428 | val = ro->want_ack; | 438 | val = ro->want_ack; |
429 | break; | 439 | break; |
440 | case WPAN_SECURITY: | ||
441 | if (!ro->secen_override) | ||
442 | val = WPAN_SECURITY_DEFAULT; | ||
443 | else if (ro->secen) | ||
444 | val = WPAN_SECURITY_ON; | ||
445 | else | ||
446 | val = WPAN_SECURITY_OFF; | ||
447 | break; | ||
448 | case WPAN_SECURITY_LEVEL: | ||
449 | if (!ro->seclevel_override) | ||
450 | val = WPAN_SECURITY_LEVEL_DEFAULT; | ||
451 | else | ||
452 | val = ro->seclevel; | ||
453 | break; | ||
430 | default: | 454 | default: |
431 | return -ENOPROTOOPT; | 455 | return -ENOPROTOOPT; |
432 | } | 456 | } |
@@ -442,6 +466,7 @@ static int dgram_setsockopt(struct sock *sk, int level, int optname, | |||
442 | char __user *optval, unsigned int optlen) | 466 | char __user *optval, unsigned int optlen) |
443 | { | 467 | { |
444 | struct dgram_sock *ro = dgram_sk(sk); | 468 | struct dgram_sock *ro = dgram_sk(sk); |
469 | struct net *net = sock_net(sk); | ||
445 | int val; | 470 | int val; |
446 | int err = 0; | 471 | int err = 0; |
447 | 472 | ||
@@ -457,6 +482,47 @@ static int dgram_setsockopt(struct sock *sk, int level, int optname, | |||
457 | case WPAN_WANTACK: | 482 | case WPAN_WANTACK: |
458 | ro->want_ack = !!val; | 483 | ro->want_ack = !!val; |
459 | break; | 484 | break; |
485 | case WPAN_SECURITY: | ||
486 | if (!ns_capable(net->user_ns, CAP_NET_ADMIN) && | ||
487 | !ns_capable(net->user_ns, CAP_NET_RAW)) { | ||
488 | err = -EPERM; | ||
489 | break; | ||
490 | } | ||
491 | |||
492 | switch (val) { | ||
493 | case WPAN_SECURITY_DEFAULT: | ||
494 | ro->secen_override = 0; | ||
495 | break; | ||
496 | case WPAN_SECURITY_ON: | ||
497 | ro->secen_override = 1; | ||
498 | ro->secen = 1; | ||
499 | break; | ||
500 | case WPAN_SECURITY_OFF: | ||
501 | ro->secen_override = 1; | ||
502 | ro->secen = 0; | ||
503 | break; | ||
504 | default: | ||
505 | err = -EINVAL; | ||
506 | break; | ||
507 | } | ||
508 | break; | ||
509 | case WPAN_SECURITY_LEVEL: | ||
510 | if (!ns_capable(net->user_ns, CAP_NET_ADMIN) && | ||
511 | !ns_capable(net->user_ns, CAP_NET_RAW)) { | ||
512 | err = -EPERM; | ||
513 | break; | ||
514 | } | ||
515 | |||
516 | if (val < WPAN_SECURITY_LEVEL_DEFAULT || | ||
517 | val > IEEE802154_SCF_SECLEVEL_ENC_MIC128) { | ||
518 | err = -EINVAL; | ||
519 | } else if (val == WPAN_SECURITY_LEVEL_DEFAULT) { | ||
520 | ro->seclevel_override = 0; | ||
521 | } else { | ||
522 | ro->seclevel_override = 1; | ||
523 | ro->seclevel = val; | ||
524 | } | ||
525 | break; | ||
460 | default: | 526 | default: |
461 | err = -ENOPROTOOPT; | 527 | err = -ENOPROTOOPT; |
462 | break; | 528 | break; |