mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-09-18 22:14:16 +00:00
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
6 changed files with 122 additions and 9 deletions
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
#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,
|
||||||
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)
|
||||||
{
|
{
|
||||||
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 {
|
||||||
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 {
|
||||||
#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,
|
||||||
|
|
||||||
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)
|
||||||
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 @@ ok:
|
||||||
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,
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
||||||
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,
|
||||||
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] = {
|
||||||
[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 {
|
||||||
.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,
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue