Revert "xfrm: rework default policy structure"

This reverts commit 0d2e9d8000 which is
b58b1f563ab78955d37e9e43e02790a85c66ac05 commit upstream.

It breaks the Android kernel ABI and if this really needs to be added to
Android, it must come back in a format in the future that does not break
the abi.

Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
Change-Id: I0a8403a202b21cda7f856ea143c5b01b78346078
This commit is contained in:
Greg Kroah-Hartman
2022-06-24 10:01:45 +02:00
parent ece9c2a70f
commit 42dadcf0a8
4 changed files with 61 additions and 42 deletions

View File

@@ -66,7 +66,11 @@ struct netns_xfrm {
int sysctl_larval_drop; int sysctl_larval_drop;
u32 sysctl_acq_expires; u32 sysctl_acq_expires;
u8 policy_default[XFRM_POLICY_MAX]; u8 policy_default;
#define XFRM_POL_DEFAULT_IN 1
#define XFRM_POL_DEFAULT_OUT 2
#define XFRM_POL_DEFAULT_FWD 4
#define XFRM_POL_DEFAULT_MASK 7
#ifdef CONFIG_SYSCTL #ifdef CONFIG_SYSCTL
struct ctl_table_header *sysctl_hdr; struct ctl_table_header *sysctl_hdr;

View File

@@ -1083,18 +1083,25 @@ xfrm_state_addr_cmp(const struct xfrm_tmpl *tmpl, const struct xfrm_state *x, un
} }
#ifdef CONFIG_XFRM #ifdef CONFIG_XFRM
int __xfrm_policy_check(struct sock *, int dir, struct sk_buff *skb, static inline bool
unsigned short family); xfrm_default_allow(struct net *net, int dir)
static inline bool __xfrm_check_nopolicy(struct net *net, struct sk_buff *skb,
int dir)
{ {
if (!net->xfrm.policy_count[dir] && !secpath_exists(skb)) u8 def = net->xfrm.policy_default;
return net->xfrm.policy_default[dir] == XFRM_USERPOLICY_ACCEPT;
switch (dir) {
case XFRM_POLICY_IN:
return def & XFRM_POL_DEFAULT_IN ? false : true;
case XFRM_POLICY_OUT:
return def & XFRM_POL_DEFAULT_OUT ? false : true;
case XFRM_POLICY_FWD:
return def & XFRM_POL_DEFAULT_FWD ? false : true;
}
return false; return false;
} }
int __xfrm_policy_check(struct sock *, int dir, struct sk_buff *skb,
unsigned short family);
static inline int __xfrm_policy_check2(struct sock *sk, int dir, static inline int __xfrm_policy_check2(struct sock *sk, int dir,
struct sk_buff *skb, struct sk_buff *skb,
unsigned int family, int reverse) unsigned int family, int reverse)
@@ -1105,9 +1112,13 @@ static inline int __xfrm_policy_check2(struct sock *sk, int dir,
if (sk && sk->sk_policy[XFRM_POLICY_IN]) if (sk && sk->sk_policy[XFRM_POLICY_IN])
return __xfrm_policy_check(sk, ndir, skb, family); return __xfrm_policy_check(sk, ndir, skb, family);
return __xfrm_check_nopolicy(net, skb, dir) || if (xfrm_default_allow(net, dir))
return (!net->xfrm.policy_count[dir] && !secpath_exists(skb)) ||
(skb_dst(skb) && (skb_dst(skb)->flags & DST_NOPOLICY)) || (skb_dst(skb) && (skb_dst(skb)->flags & DST_NOPOLICY)) ||
__xfrm_policy_check(sk, ndir, skb, family); __xfrm_policy_check(sk, ndir, skb, family);
else
return (skb_dst(skb) && (skb_dst(skb)->flags & DST_NOPOLICY)) ||
__xfrm_policy_check(sk, ndir, skb, family);
} }
static inline int xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, unsigned short family) static inline int xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, unsigned short family)
@@ -1159,10 +1170,11 @@ static inline int xfrm_route_forward(struct sk_buff *skb, unsigned short family)
{ {
struct net *net = dev_net(skb->dev); struct net *net = dev_net(skb->dev);
if (!net->xfrm.policy_count[XFRM_POLICY_OUT] && if (xfrm_default_allow(net, XFRM_POLICY_OUT))
net->xfrm.policy_default[XFRM_POLICY_OUT] == XFRM_USERPOLICY_ACCEPT) return !net->xfrm.policy_count[XFRM_POLICY_OUT] ||
return true; (skb_dst(skb)->flags & DST_NOXFRM) ||
__xfrm_route_forward(skb, family);
else
return (skb_dst(skb)->flags & DST_NOXFRM) || return (skb_dst(skb)->flags & DST_NOXFRM) ||
__xfrm_route_forward(skb, family); __xfrm_route_forward(skb, family);
} }

View File

@@ -3167,7 +3167,7 @@ ok:
nopol: nopol:
if (!(dst_orig->dev->flags & IFF_LOOPBACK) && if (!(dst_orig->dev->flags & IFF_LOOPBACK) &&
net->xfrm.policy_default[dir] == XFRM_USERPOLICY_BLOCK) { !xfrm_default_allow(net, dir)) {
err = -EPERM; err = -EPERM;
goto error; goto error;
} }
@@ -3618,7 +3618,7 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
} }
if (!pol) { if (!pol) {
if (net->xfrm.policy_default[dir] == XFRM_USERPOLICY_BLOCK) { if (!xfrm_default_allow(net, dir)) {
XFRM_INC_STATS(net, LINUX_MIB_XFRMINNOPOLS); XFRM_INC_STATS(net, LINUX_MIB_XFRMINNOPOLS);
return 0; return 0;
} }
@@ -3678,8 +3678,7 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
} }
xfrm_nr = ti; xfrm_nr = ti;
if (net->xfrm.policy_default[dir] == XFRM_USERPOLICY_BLOCK && if (!xfrm_default_allow(net, dir) && !xfrm_nr) {
!xfrm_nr) {
XFRM_INC_STATS(net, LINUX_MIB_XFRMINNOSTATES); XFRM_INC_STATS(net, LINUX_MIB_XFRMINNOSTATES);
goto reject; goto reject;
} }
@@ -4167,9 +4166,6 @@ static int __net_init xfrm_net_init(struct net *net)
spin_lock_init(&net->xfrm.xfrm_state_lock); spin_lock_init(&net->xfrm.xfrm_state_lock);
spin_lock_init(&net->xfrm.xfrm_policy_lock); spin_lock_init(&net->xfrm.xfrm_policy_lock);
mutex_init(&net->xfrm.xfrm_cfg_mutex); mutex_init(&net->xfrm.xfrm_cfg_mutex);
net->xfrm.policy_default[XFRM_POLICY_IN] = XFRM_USERPOLICY_ACCEPT;
net->xfrm.policy_default[XFRM_POLICY_FWD] = XFRM_USERPOLICY_ACCEPT;
net->xfrm.policy_default[XFRM_POLICY_OUT] = XFRM_USERPOLICY_ACCEPT;
rv = xfrm_statistics_init(net); rv = xfrm_statistics_init(net);
if (rv < 0) if (rv < 0)

View File

@@ -1919,35 +1919,38 @@ static int xfrm_notify_userpolicy(struct net *net)
} }
up = nlmsg_data(nlh); up = nlmsg_data(nlh);
up->in = net->xfrm.policy_default[XFRM_POLICY_IN]; up->in = net->xfrm.policy_default & XFRM_POL_DEFAULT_IN ?
up->fwd = net->xfrm.policy_default[XFRM_POLICY_FWD]; XFRM_USERPOLICY_BLOCK : XFRM_USERPOLICY_ACCEPT;
up->out = net->xfrm.policy_default[XFRM_POLICY_OUT]; up->fwd = net->xfrm.policy_default & XFRM_POL_DEFAULT_FWD ?
XFRM_USERPOLICY_BLOCK : XFRM_USERPOLICY_ACCEPT;
up->out = net->xfrm.policy_default & XFRM_POL_DEFAULT_OUT ?
XFRM_USERPOLICY_BLOCK : XFRM_USERPOLICY_ACCEPT;
nlmsg_end(skb, nlh); nlmsg_end(skb, nlh);
return xfrm_nlmsg_multicast(net, skb, 0, XFRMNLGRP_POLICY); return xfrm_nlmsg_multicast(net, skb, 0, XFRMNLGRP_POLICY);
} }
static bool xfrm_userpolicy_is_valid(__u8 policy)
{
return policy == XFRM_USERPOLICY_BLOCK ||
policy == XFRM_USERPOLICY_ACCEPT;
}
static int xfrm_set_default(struct sk_buff *skb, struct nlmsghdr *nlh, static int xfrm_set_default(struct sk_buff *skb, struct nlmsghdr *nlh,
struct nlattr **attrs) struct nlattr **attrs)
{ {
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);
if (xfrm_userpolicy_is_valid(up->in)) if (up->in == XFRM_USERPOLICY_BLOCK)
net->xfrm.policy_default[XFRM_POLICY_IN] = up->in; net->xfrm.policy_default |= XFRM_POL_DEFAULT_IN;
else if (up->in == XFRM_USERPOLICY_ACCEPT)
net->xfrm.policy_default &= ~XFRM_POL_DEFAULT_IN;
if (xfrm_userpolicy_is_valid(up->fwd)) if (up->fwd == XFRM_USERPOLICY_BLOCK)
net->xfrm.policy_default[XFRM_POLICY_FWD] = up->fwd; net->xfrm.policy_default |= XFRM_POL_DEFAULT_FWD;
else if (up->fwd == XFRM_USERPOLICY_ACCEPT)
net->xfrm.policy_default &= ~XFRM_POL_DEFAULT_FWD;
if (xfrm_userpolicy_is_valid(up->out)) if (up->out == XFRM_USERPOLICY_BLOCK)
net->xfrm.policy_default[XFRM_POLICY_OUT] = up->out; 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);
@@ -1977,9 +1980,13 @@ static int xfrm_get_default(struct sk_buff *skb, struct nlmsghdr *nlh,
} }
r_up = nlmsg_data(r_nlh); r_up = nlmsg_data(r_nlh);
r_up->in = net->xfrm.policy_default[XFRM_POLICY_IN];
r_up->fwd = net->xfrm.policy_default[XFRM_POLICY_FWD]; r_up->in = net->xfrm.policy_default & XFRM_POL_DEFAULT_IN ?
r_up->out = net->xfrm.policy_default[XFRM_POLICY_OUT]; 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);