Commit fe50893a authored by David S. Miller's avatar David S. Miller

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: default avatarDavid S. Miller <davem@davemloft.net>
parents a5504093 5d8dbb7f
...@@ -65,6 +65,13 @@ struct netns_xfrm { ...@@ -65,6 +65,13 @@ struct netns_xfrm {
u32 sysctl_aevent_rseqth; u32 sysctl_aevent_rseqth;
int sysctl_larval_drop; int sysctl_larval_drop;
u32 sysctl_acq_expires; 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 #ifdef CONFIG_SYSCTL
struct ctl_table_header *sysctl_hdr; struct ctl_table_header *sysctl_hdr;
#endif #endif
......
...@@ -1075,6 +1075,22 @@ xfrm_state_addr_cmp(const struct xfrm_tmpl *tmpl, const struct xfrm_state *x, un ...@@ -1075,6 +1075,22 @@ xfrm_state_addr_cmp(const struct xfrm_tmpl *tmpl, const struct xfrm_state *x, un
} }
#ifdef CONFIG_XFRM #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, int __xfrm_policy_check(struct sock *, int dir, struct sk_buff *skb,
unsigned short family); unsigned short family);
...@@ -1088,9 +1104,13 @@ static inline int __xfrm_policy_check2(struct sock *sk, int dir, ...@@ -1088,9 +1104,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 (!net->xfrm.policy_count[dir] && !secpath_exists(skb)) || if (xfrm_default_allow(net, dir))
(skb_dst(skb) && (skb_dst(skb)->flags & DST_NOPOLICY)) || return (!net->xfrm.policy_count[dir] && !secpath_exists(skb)) ||
__xfrm_policy_check(sk, ndir, skb, family); (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) 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) ...@@ -1142,9 +1162,13 @@ 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);
return !net->xfrm.policy_count[XFRM_POLICY_OUT] || if (xfrm_default_allow(net, XFRM_POLICY_FWD))
(skb_dst(skb)->flags & DST_NOXFRM) || return !net->xfrm.policy_count[XFRM_POLICY_OUT] ||
__xfrm_route_forward(skb, family); (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) static inline int xfrm4_route_forward(struct sk_buff *skb)
......
...@@ -213,6 +213,11 @@ enum { ...@@ -213,6 +213,11 @@ enum {
XFRM_MSG_GETSPDINFO, XFRM_MSG_GETSPDINFO,
#define XFRM_MSG_GETSPDINFO 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, XFRM_MSG_MAPPING,
#define XFRM_MSG_MAPPING XFRM_MSG_MAPPING #define XFRM_MSG_MAPPING XFRM_MSG_MAPPING
__XFRM_MSG_MAX __XFRM_MSG_MAX
...@@ -508,6 +513,12 @@ struct xfrm_user_offload { ...@@ -508,6 +513,12 @@ struct xfrm_user_offload {
#define XFRM_OFFLOAD_IPV6 1 #define XFRM_OFFLOAD_IPV6 1
#define XFRM_OFFLOAD_INBOUND 2 #define XFRM_OFFLOAD_INBOUND 2
struct xfrm_userpolicy_default {
#define XFRM_USERPOLICY_DIRMASK_MAX (sizeof(__u8) * 8)
__u8 dirmask;
__u8 action;
};
#ifndef __KERNEL__ #ifndef __KERNEL__
/* backwards compatibility for userspace */ /* backwards compatibility for userspace */
#define XFRMGRP_ACQUIRE 1 #define XFRMGRP_ACQUIRE 1
......
...@@ -97,7 +97,6 @@ static inline struct scatterlist *esp_req_sg(struct crypto_aead *aead, ...@@ -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) 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; struct crypto_aead *aead = x->data;
int extralen = 0; int extralen = 0;
u8 *iv; u8 *iv;
...@@ -105,9 +104,8 @@ static void esp_ssg_unref(struct xfrm_state *x, void *tmp) ...@@ -105,9 +104,8 @@ static void esp_ssg_unref(struct xfrm_state *x, void *tmp)
struct scatterlist *sg; struct scatterlist *sg;
if (x->props.flags & XFRM_STATE_ESN) 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); iv = esp_tmp_iv(aead, tmp, extralen);
req = esp_tmp_req(aead, iv); req = esp_tmp_req(aead, iv);
......
...@@ -3157,6 +3157,11 @@ struct dst_entry *xfrm_lookup_with_ifid(struct net *net, ...@@ -3157,6 +3157,11 @@ struct dst_entry *xfrm_lookup_with_ifid(struct net *net,
return dst; return dst;
nopol: nopol:
if (!(dst_orig->dev->flags & IFF_LOOPBACK) &&
!xfrm_default_allow(net, dir)) {
err = -EPERM;
goto error;
}
if (!(flags & XFRM_LOOKUP_ICMP)) { if (!(flags & XFRM_LOOKUP_ICMP)) {
dst = dst_orig; dst = dst_orig;
goto ok; goto ok;
...@@ -3545,6 +3550,11 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, ...@@ -3545,6 +3550,11 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
} }
if (!pol) { 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)) { if (sp && secpath_has_nontransport(sp, 0, &xerr_idx)) {
xfrm_secpath_reject(xerr_idx, skb, &fl); xfrm_secpath_reject(xerr_idx, skb, &fl);
XFRM_INC_STATS(net, LINUX_MIB_XFRMINNOPOLS); XFRM_INC_STATS(net, LINUX_MIB_XFRMINNOPOLS);
...@@ -3599,6 +3609,12 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, ...@@ -3599,6 +3609,12 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
tpp[ti++] = &pols[pi]->xfrm_vec[i]; tpp[ti++] = &pols[pi]->xfrm_vec[i];
} }
xfrm_nr = ti; xfrm_nr = ti;
if (!xfrm_default_allow(net, dir) && !xfrm_nr) {
XFRM_INC_STATS(net, LINUX_MIB_XFRMINNOSTATES);
goto reject;
}
if (npols > 1) { if (npols > 1) {
xfrm_tmpl_sort(stp, tpp, xfrm_nr, family); xfrm_tmpl_sort(stp, tpp, xfrm_nr, family);
tpp = stp; tpp = stp;
......
...@@ -1961,6 +1961,59 @@ static struct sk_buff *xfrm_policy_netlink(struct sk_buff *in_skb, ...@@ -1961,6 +1961,59 @@ static struct sk_buff *xfrm_policy_netlink(struct sk_buff *in_skb,
return 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, static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
struct nlattr **attrs) struct nlattr **attrs)
{ {
...@@ -2664,6 +2717,8 @@ const int xfrm_msg_min[XFRM_NR_MSGTYPES] = { ...@@ -2664,6 +2717,8 @@ const int xfrm_msg_min[XFRM_NR_MSGTYPES] = {
[XFRM_MSG_GETSADINFO - XFRM_MSG_BASE] = sizeof(u32), [XFRM_MSG_GETSADINFO - XFRM_MSG_BASE] = sizeof(u32),
[XFRM_MSG_NEWSPDINFO - XFRM_MSG_BASE] = sizeof(u32), [XFRM_MSG_NEWSPDINFO - XFRM_MSG_BASE] = sizeof(u32),
[XFRM_MSG_GETSPDINFO - 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); EXPORT_SYMBOL_GPL(xfrm_msg_min);
...@@ -2743,6 +2798,8 @@ static const struct xfrm_link { ...@@ -2743,6 +2798,8 @@ static const struct xfrm_link {
.nla_pol = xfrma_spd_policy, .nla_pol = xfrma_spd_policy,
.nla_max = XFRMA_SPD_MAX }, .nla_max = XFRMA_SPD_MAX },
[XFRM_MSG_GETSPDINFO - XFRM_MSG_BASE] = { .doit = xfrm_get_spdinfo }, [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, static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh,
......
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