forked from Minki/linux
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/
ipsec-next Steffen Klassert says: ==================== pull request (net-next): ipsec-next 2021-08-27 1) Remove an unneeded extra variable in esp4 esp_ssg_unref. From Corey Minyard. 2) Add a configuration option to change the default behaviour to block traffic if there is no matching policy. Joint work with Christian Langrock and Antony Antony. 3) Fix a shift-out-of-bounce bug reported from syzbot. From Pavel Skripkin. Please pull or let me know if there are problems. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
fe50893aa8
@ -65,6 +65,13 @@ struct netns_xfrm {
|
||||
u32 sysctl_aevent_rseqth;
|
||||
int sysctl_larval_drop;
|
||||
u32 sysctl_acq_expires;
|
||||
|
||||
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
|
||||
struct ctl_table_header *sysctl_hdr;
|
||||
#endif
|
||||
|
@ -1075,6 +1075,22 @@ xfrm_state_addr_cmp(const struct xfrm_tmpl *tmpl, const struct xfrm_state *x, un
|
||||
}
|
||||
|
||||
#ifdef CONFIG_XFRM
|
||||
static inline bool
|
||||
xfrm_default_allow(struct net *net, int dir)
|
||||
{
|
||||
u8 def = net->xfrm.policy_default;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
int __xfrm_policy_check(struct sock *, int dir, struct sk_buff *skb,
|
||||
unsigned short family);
|
||||
|
||||
@ -1088,9 +1104,13 @@ static inline int __xfrm_policy_check2(struct sock *sk, int dir,
|
||||
if (sk && sk->sk_policy[XFRM_POLICY_IN])
|
||||
return __xfrm_policy_check(sk, ndir, skb, family);
|
||||
|
||||
return (!net->xfrm.policy_count[dir] && !secpath_exists(skb)) ||
|
||||
(skb_dst(skb) && (skb_dst(skb)->flags & DST_NOPOLICY)) ||
|
||||
__xfrm_policy_check(sk, ndir, skb, family);
|
||||
if (xfrm_default_allow(net, dir))
|
||||
return (!net->xfrm.policy_count[dir] && !secpath_exists(skb)) ||
|
||||
(skb_dst(skb) && (skb_dst(skb)->flags & DST_NOPOLICY)) ||
|
||||
__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)
|
||||
@ -1142,9 +1162,13 @@ static inline int xfrm_route_forward(struct sk_buff *skb, unsigned short family)
|
||||
{
|
||||
struct net *net = dev_net(skb->dev);
|
||||
|
||||
return !net->xfrm.policy_count[XFRM_POLICY_OUT] ||
|
||||
(skb_dst(skb)->flags & DST_NOXFRM) ||
|
||||
__xfrm_route_forward(skb, family);
|
||||
if (xfrm_default_allow(net, XFRM_POLICY_FWD))
|
||||
return !net->xfrm.policy_count[XFRM_POLICY_OUT] ||
|
||||
(skb_dst(skb)->flags & DST_NOXFRM) ||
|
||||
__xfrm_route_forward(skb, family);
|
||||
else
|
||||
return (skb_dst(skb)->flags & DST_NOXFRM) ||
|
||||
__xfrm_route_forward(skb, family);
|
||||
}
|
||||
|
||||
static inline int xfrm4_route_forward(struct sk_buff *skb)
|
||||
|
@ -213,6 +213,11 @@ enum {
|
||||
XFRM_MSG_GETSPDINFO,
|
||||
#define XFRM_MSG_GETSPDINFO XFRM_MSG_GETSPDINFO
|
||||
|
||||
XFRM_MSG_SETDEFAULT,
|
||||
#define XFRM_MSG_SETDEFAULT XFRM_MSG_SETDEFAULT
|
||||
XFRM_MSG_GETDEFAULT,
|
||||
#define XFRM_MSG_GETDEFAULT XFRM_MSG_GETDEFAULT
|
||||
|
||||
XFRM_MSG_MAPPING,
|
||||
#define XFRM_MSG_MAPPING XFRM_MSG_MAPPING
|
||||
__XFRM_MSG_MAX
|
||||
@ -508,6 +513,12 @@ struct xfrm_user_offload {
|
||||
#define XFRM_OFFLOAD_IPV6 1
|
||||
#define XFRM_OFFLOAD_INBOUND 2
|
||||
|
||||
struct xfrm_userpolicy_default {
|
||||
#define XFRM_USERPOLICY_DIRMASK_MAX (sizeof(__u8) * 8)
|
||||
__u8 dirmask;
|
||||
__u8 action;
|
||||
};
|
||||
|
||||
#ifndef __KERNEL__
|
||||
/* backwards compatibility for userspace */
|
||||
#define XFRMGRP_ACQUIRE 1
|
||||
|
@ -97,7 +97,6 @@ static inline struct scatterlist *esp_req_sg(struct crypto_aead *aead,
|
||||
|
||||
static void esp_ssg_unref(struct xfrm_state *x, void *tmp)
|
||||
{
|
||||
struct esp_output_extra *extra = esp_tmp_extra(tmp);
|
||||
struct crypto_aead *aead = x->data;
|
||||
int extralen = 0;
|
||||
u8 *iv;
|
||||
@ -105,9 +104,8 @@ static void esp_ssg_unref(struct xfrm_state *x, void *tmp)
|
||||
struct scatterlist *sg;
|
||||
|
||||
if (x->props.flags & XFRM_STATE_ESN)
|
||||
extralen += sizeof(*extra);
|
||||
extralen += sizeof(struct esp_output_extra);
|
||||
|
||||
extra = esp_tmp_extra(tmp);
|
||||
iv = esp_tmp_iv(aead, tmp, extralen);
|
||||
req = esp_tmp_req(aead, iv);
|
||||
|
||||
|
@ -3157,6 +3157,11 @@ ok:
|
||||
return dst;
|
||||
|
||||
nopol:
|
||||
if (!(dst_orig->dev->flags & IFF_LOOPBACK) &&
|
||||
!xfrm_default_allow(net, dir)) {
|
||||
err = -EPERM;
|
||||
goto error;
|
||||
}
|
||||
if (!(flags & XFRM_LOOKUP_ICMP)) {
|
||||
dst = dst_orig;
|
||||
goto ok;
|
||||
@ -3545,6 +3550,11 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
|
||||
}
|
||||
|
||||
if (!pol) {
|
||||
if (!xfrm_default_allow(net, dir)) {
|
||||
XFRM_INC_STATS(net, LINUX_MIB_XFRMINNOPOLS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sp && secpath_has_nontransport(sp, 0, &xerr_idx)) {
|
||||
xfrm_secpath_reject(xerr_idx, skb, &fl);
|
||||
XFRM_INC_STATS(net, LINUX_MIB_XFRMINNOPOLS);
|
||||
@ -3599,6 +3609,12 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
|
||||
tpp[ti++] = &pols[pi]->xfrm_vec[i];
|
||||
}
|
||||
xfrm_nr = ti;
|
||||
|
||||
if (!xfrm_default_allow(net, dir) && !xfrm_nr) {
|
||||
XFRM_INC_STATS(net, LINUX_MIB_XFRMINNOSTATES);
|
||||
goto reject;
|
||||
}
|
||||
|
||||
if (npols > 1) {
|
||||
xfrm_tmpl_sort(stp, tpp, xfrm_nr, family);
|
||||
tpp = stp;
|
||||
|
@ -1961,6 +1961,59 @@ static struct sk_buff *xfrm_policy_netlink(struct sk_buff *in_skb,
|
||||
return skb;
|
||||
}
|
||||
|
||||
static int xfrm_set_default(struct sk_buff *skb, struct nlmsghdr *nlh,
|
||||
struct nlattr **attrs)
|
||||
{
|
||||
struct net *net = sock_net(skb->sk);
|
||||
struct xfrm_userpolicy_default *up = nlmsg_data(nlh);
|
||||
u8 dirmask;
|
||||
u8 old_default = net->xfrm.policy_default;
|
||||
|
||||
if (up->dirmask >= XFRM_USERPOLICY_DIRMASK_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
dirmask = (1 << up->dirmask) & XFRM_POL_DEFAULT_MASK;
|
||||
|
||||
net->xfrm.policy_default = (old_default & (0xff ^ dirmask))
|
||||
| (up->action << up->dirmask);
|
||||
|
||||
rt_genid_bump_all(net);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xfrm_get_default(struct sk_buff *skb, struct nlmsghdr *nlh,
|
||||
struct nlattr **attrs)
|
||||
{
|
||||
struct sk_buff *r_skb;
|
||||
struct nlmsghdr *r_nlh;
|
||||
struct net *net = sock_net(skb->sk);
|
||||
struct xfrm_userpolicy_default *r_up, *up;
|
||||
int len = NLMSG_ALIGN(sizeof(struct xfrm_userpolicy_default));
|
||||
u32 portid = NETLINK_CB(skb).portid;
|
||||
u32 seq = nlh->nlmsg_seq;
|
||||
|
||||
up = nlmsg_data(nlh);
|
||||
|
||||
r_skb = nlmsg_new(len, GFP_ATOMIC);
|
||||
if (!r_skb)
|
||||
return -ENOMEM;
|
||||
|
||||
r_nlh = nlmsg_put(r_skb, portid, seq, XFRM_MSG_GETDEFAULT, sizeof(*r_up), 0);
|
||||
if (!r_nlh) {
|
||||
kfree_skb(r_skb);
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
r_up = nlmsg_data(r_nlh);
|
||||
|
||||
r_up->action = ((net->xfrm.policy_default & (1 << up->dirmask)) >> up->dirmask);
|
||||
r_up->dirmask = up->dirmask;
|
||||
nlmsg_end(r_skb, r_nlh);
|
||||
|
||||
return nlmsg_unicast(net->xfrm.nlsk, r_skb, portid);
|
||||
}
|
||||
|
||||
static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
|
||||
struct nlattr **attrs)
|
||||
{
|
||||
@ -2664,6 +2717,8 @@ const int xfrm_msg_min[XFRM_NR_MSGTYPES] = {
|
||||
[XFRM_MSG_GETSADINFO - XFRM_MSG_BASE] = sizeof(u32),
|
||||
[XFRM_MSG_NEWSPDINFO - XFRM_MSG_BASE] = sizeof(u32),
|
||||
[XFRM_MSG_GETSPDINFO - XFRM_MSG_BASE] = sizeof(u32),
|
||||
[XFRM_MSG_SETDEFAULT - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_default),
|
||||
[XFRM_MSG_GETDEFAULT - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_default),
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(xfrm_msg_min);
|
||||
|
||||
@ -2743,6 +2798,8 @@ static const struct xfrm_link {
|
||||
.nla_pol = xfrma_spd_policy,
|
||||
.nla_max = XFRMA_SPD_MAX },
|
||||
[XFRM_MSG_GETSPDINFO - XFRM_MSG_BASE] = { .doit = xfrm_get_spdinfo },
|
||||
[XFRM_MSG_SETDEFAULT - XFRM_MSG_BASE] = { .doit = xfrm_set_default },
|
||||
[XFRM_MSG_GETDEFAULT - XFRM_MSG_BASE] = { .doit = xfrm_get_default },
|
||||
};
|
||||
|
||||
static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh,
|
||||
|
Loading…
Reference in New Issue
Block a user