mirror of https://gitee.com/openkylin/linux.git
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>
This commit is contained in:
parent
f30be4d53c
commit
af9eed5bbf
|
@ -57,6 +57,14 @@ struct sockaddr_ieee802154 {
|
||||||
/* get/setsockopt */
|
/* get/setsockopt */
|
||||||
#define SOL_IEEE802154 0
|
#define SOL_IEEE802154 0
|
||||||
|
|
||||||
#define WPAN_WANTACK 0
|
#define WPAN_WANTACK 0
|
||||||
|
#define WPAN_SECURITY 1
|
||||||
|
#define WPAN_SECURITY_LEVEL 2
|
||||||
|
|
||||||
|
#define WPAN_SECURITY_DEFAULT 0
|
||||||
|
#define WPAN_SECURITY_OFF 1
|
||||||
|
#define WPAN_SECURITY_ON 2
|
||||||
|
|
||||||
|
#define WPAN_SECURITY_LEVEL_DEFAULT (-1)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
* Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
|
* Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <linux/capability.h>
|
||||||
#include <linux/net.h>
|
#include <linux/net.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/if_arp.h>
|
#include <linux/if_arp.h>
|
||||||
|
@ -47,6 +48,10 @@ struct dgram_sock {
|
||||||
unsigned int bound:1;
|
unsigned int bound:1;
|
||||||
unsigned int connected:1;
|
unsigned int connected:1;
|
||||||
unsigned int want_ack:1;
|
unsigned int want_ack:1;
|
||||||
|
unsigned int secen:1;
|
||||||
|
unsigned int secen_override:1;
|
||||||
|
unsigned int seclevel:3;
|
||||||
|
unsigned int seclevel_override:1;
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline struct dgram_sock *dgram_sk(const struct sock *sk)
|
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,
|
||||||
dst_addr = ro->dst_addr;
|
dst_addr = ro->dst_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cb->secen = ro->secen;
|
||||||
|
cb->secen_override = ro->secen_override;
|
||||||
|
cb->seclevel = ro->seclevel;
|
||||||
|
cb->seclevel_override = ro->seclevel_override;
|
||||||
|
|
||||||
err = dev_hard_header(skb, dev, ETH_P_IEEE802154, &dst_addr,
|
err = dev_hard_header(skb, dev, ETH_P_IEEE802154, &dst_addr,
|
||||||
ro->bound ? &ro->src_addr : NULL, size);
|
ro->bound ? &ro->src_addr : NULL, size);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
|
@ -427,6 +437,20 @@ static int dgram_getsockopt(struct sock *sk, int level, int optname,
|
||||||
case WPAN_WANTACK:
|
case WPAN_WANTACK:
|
||||||
val = ro->want_ack;
|
val = ro->want_ack;
|
||||||
break;
|
break;
|
||||||
|
case WPAN_SECURITY:
|
||||||
|
if (!ro->secen_override)
|
||||||
|
val = WPAN_SECURITY_DEFAULT;
|
||||||
|
else if (ro->secen)
|
||||||
|
val = WPAN_SECURITY_ON;
|
||||||
|
else
|
||||||
|
val = WPAN_SECURITY_OFF;
|
||||||
|
break;
|
||||||
|
case WPAN_SECURITY_LEVEL:
|
||||||
|
if (!ro->seclevel_override)
|
||||||
|
val = WPAN_SECURITY_LEVEL_DEFAULT;
|
||||||
|
else
|
||||||
|
val = ro->seclevel;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return -ENOPROTOOPT;
|
return -ENOPROTOOPT;
|
||||||
}
|
}
|
||||||
|
@ -442,6 +466,7 @@ static int dgram_setsockopt(struct sock *sk, int level, int optname,
|
||||||
char __user *optval, unsigned int optlen)
|
char __user *optval, unsigned int optlen)
|
||||||
{
|
{
|
||||||
struct dgram_sock *ro = dgram_sk(sk);
|
struct dgram_sock *ro = dgram_sk(sk);
|
||||||
|
struct net *net = sock_net(sk);
|
||||||
int val;
|
int val;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
|
@ -457,6 +482,47 @@ static int dgram_setsockopt(struct sock *sk, int level, int optname,
|
||||||
case WPAN_WANTACK:
|
case WPAN_WANTACK:
|
||||||
ro->want_ack = !!val;
|
ro->want_ack = !!val;
|
||||||
break;
|
break;
|
||||||
|
case WPAN_SECURITY:
|
||||||
|
if (!ns_capable(net->user_ns, CAP_NET_ADMIN) &&
|
||||||
|
!ns_capable(net->user_ns, CAP_NET_RAW)) {
|
||||||
|
err = -EPERM;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (val) {
|
||||||
|
case WPAN_SECURITY_DEFAULT:
|
||||||
|
ro->secen_override = 0;
|
||||||
|
break;
|
||||||
|
case WPAN_SECURITY_ON:
|
||||||
|
ro->secen_override = 1;
|
||||||
|
ro->secen = 1;
|
||||||
|
break;
|
||||||
|
case WPAN_SECURITY_OFF:
|
||||||
|
ro->secen_override = 1;
|
||||||
|
ro->secen = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
err = -EINVAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WPAN_SECURITY_LEVEL:
|
||||||
|
if (!ns_capable(net->user_ns, CAP_NET_ADMIN) &&
|
||||||
|
!ns_capable(net->user_ns, CAP_NET_RAW)) {
|
||||||
|
err = -EPERM;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (val < WPAN_SECURITY_LEVEL_DEFAULT ||
|
||||||
|
val > IEEE802154_SCF_SECLEVEL_ENC_MIC128) {
|
||||||
|
err = -EINVAL;
|
||||||
|
} else if (val == WPAN_SECURITY_LEVEL_DEFAULT) {
|
||||||
|
ro->seclevel_override = 0;
|
||||||
|
} else {
|
||||||
|
ro->seclevel_override = 1;
|
||||||
|
ro->seclevel = val;
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
err = -ENOPROTOOPT;
|
err = -ENOPROTOOPT;
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in New Issue