Commit f8d858e6 authored by Nicolas Dichtel's avatar Nicolas Dichtel Committed by Steffen Klassert

xfrm: make user policy API complete

>From a userland POV, this API was based on some magic values:
 - dirmask and action were bitfields but meaning of bits
   (XFRM_POL_DEFAULT_*) are not exported;
 - action is confusing, if a bit is set, does it mean drop or accept?

Let's try to simplify this uapi by using explicit field and macros.

Fixes: 2d151d39 ("xfrm: Add possibility to set the default to block if we have no policy")
Signed-off-by: default avatarNicolas Dichtel <nicolas.dichtel@6wind.com>
Signed-off-by: default avatarSteffen Klassert <steffen.klassert@secunet.com>
parent 844f7eaa
...@@ -514,9 +514,12 @@ struct xfrm_user_offload { ...@@ -514,9 +514,12 @@ struct xfrm_user_offload {
#define XFRM_OFFLOAD_INBOUND 2 #define XFRM_OFFLOAD_INBOUND 2
struct xfrm_userpolicy_default { struct xfrm_userpolicy_default {
#define XFRM_USERPOLICY_DIRMASK_MAX (sizeof(__u8) * 8) #define XFRM_USERPOLICY_UNSPEC 0
__u8 dirmask; #define XFRM_USERPOLICY_BLOCK 1
__u8 action; #define XFRM_USERPOLICY_ACCEPT 2
__u8 in;
__u8 fwd;
__u8 out;
}; };
#ifndef __KERNEL__ #ifndef __KERNEL__
......
...@@ -1966,16 +1966,21 @@ static int xfrm_set_default(struct sk_buff *skb, struct nlmsghdr *nlh, ...@@ -1966,16 +1966,21 @@ static int xfrm_set_default(struct sk_buff *skb, struct nlmsghdr *nlh,
{ {
struct net *net = sock_net(skb->sk); struct net *net = sock_net(skb->sk);
struct xfrm_userpolicy_default *up = nlmsg_data(nlh); struct xfrm_userpolicy_default *up = nlmsg_data(nlh);
u8 dirmask;
u8 old_default = net->xfrm.policy_default;
if (up->dirmask >= XFRM_USERPOLICY_DIRMASK_MAX) if (up->in == XFRM_USERPOLICY_BLOCK)
return -EINVAL; net->xfrm.policy_default |= XFRM_POL_DEFAULT_IN;
else if (up->in == XFRM_USERPOLICY_ACCEPT)
net->xfrm.policy_default &= ~XFRM_POL_DEFAULT_IN;
dirmask = (1 << up->dirmask) & XFRM_POL_DEFAULT_MASK; if (up->fwd == XFRM_USERPOLICY_BLOCK)
net->xfrm.policy_default |= XFRM_POL_DEFAULT_FWD;
else if (up->fwd == XFRM_USERPOLICY_ACCEPT)
net->xfrm.policy_default &= ~XFRM_POL_DEFAULT_FWD;
net->xfrm.policy_default = (old_default & (0xff ^ dirmask)) if (up->out == XFRM_USERPOLICY_BLOCK)
| (up->action << up->dirmask); net->xfrm.policy_default |= XFRM_POL_DEFAULT_OUT;
else if (up->out == XFRM_USERPOLICY_ACCEPT)
net->xfrm.policy_default &= ~XFRM_POL_DEFAULT_OUT;
rt_genid_bump_all(net); rt_genid_bump_all(net);
...@@ -1988,13 +1993,11 @@ static int xfrm_get_default(struct sk_buff *skb, struct nlmsghdr *nlh, ...@@ -1988,13 +1993,11 @@ static int xfrm_get_default(struct sk_buff *skb, struct nlmsghdr *nlh,
struct sk_buff *r_skb; struct sk_buff *r_skb;
struct nlmsghdr *r_nlh; struct nlmsghdr *r_nlh;
struct net *net = sock_net(skb->sk); struct net *net = sock_net(skb->sk);
struct xfrm_userpolicy_default *r_up, *up; struct xfrm_userpolicy_default *r_up;
int len = NLMSG_ALIGN(sizeof(struct xfrm_userpolicy_default)); int len = NLMSG_ALIGN(sizeof(struct xfrm_userpolicy_default));
u32 portid = NETLINK_CB(skb).portid; u32 portid = NETLINK_CB(skb).portid;
u32 seq = nlh->nlmsg_seq; u32 seq = nlh->nlmsg_seq;
up = nlmsg_data(nlh);
r_skb = nlmsg_new(len, GFP_ATOMIC); r_skb = nlmsg_new(len, GFP_ATOMIC);
if (!r_skb) if (!r_skb)
return -ENOMEM; return -ENOMEM;
...@@ -2005,15 +2008,14 @@ static int xfrm_get_default(struct sk_buff *skb, struct nlmsghdr *nlh, ...@@ -2005,15 +2008,14 @@ static int xfrm_get_default(struct sk_buff *skb, struct nlmsghdr *nlh,
return -EMSGSIZE; return -EMSGSIZE;
} }
if (up->dirmask >= XFRM_USERPOLICY_DIRMASK_MAX) {
kfree_skb(r_skb);
return -EINVAL;
}
r_up = nlmsg_data(r_nlh); r_up = nlmsg_data(r_nlh);
r_up->action = ((net->xfrm.policy_default & (1 << up->dirmask)) >> up->dirmask); r_up->in = net->xfrm.policy_default & XFRM_POL_DEFAULT_IN ?
r_up->dirmask = up->dirmask; XFRM_USERPOLICY_BLOCK : XFRM_USERPOLICY_ACCEPT;
r_up->fwd = net->xfrm.policy_default & XFRM_POL_DEFAULT_FWD ?
XFRM_USERPOLICY_BLOCK : XFRM_USERPOLICY_ACCEPT;
r_up->out = net->xfrm.policy_default & XFRM_POL_DEFAULT_OUT ?
XFRM_USERPOLICY_BLOCK : XFRM_USERPOLICY_ACCEPT;
nlmsg_end(r_skb, r_nlh); nlmsg_end(r_skb, r_nlh);
return nlmsg_unicast(net->xfrm.nlsk, r_skb, portid); return nlmsg_unicast(net->xfrm.nlsk, r_skb, portid);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment