Commit 578f3932 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

Steffen Klassert says:

====================
pull request (net): ipsec 2021-10-07

1) Fix a sysbot reported shift-out-of-bounds in xfrm_get_default.
   From Pavel Skripkin.

2) Fix XFRM_MSG_MAPPING ABI breakage. The new XFRM_MSG_MAPPING
   messages were accidentally not paced at the end.
   Fix by Eugene Syromiatnikov.

3) Fix the uapi for the default policy, use explicit field and macros
   and make it accessible to userland.
   From Nicolas Dichtel.

4) Fix a missing rcu lock in xfrm_notify_userpolicy().
   From Nicolas Dichtel.

Please pull or let me know if there are problems.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 65f280bb 93ec1320
...@@ -213,13 +213,13 @@ enum { ...@@ -213,13 +213,13 @@ enum {
XFRM_MSG_GETSPDINFO, XFRM_MSG_GETSPDINFO,
#define XFRM_MSG_GETSPDINFO XFRM_MSG_GETSPDINFO #define XFRM_MSG_GETSPDINFO XFRM_MSG_GETSPDINFO
XFRM_MSG_MAPPING,
#define XFRM_MSG_MAPPING XFRM_MSG_MAPPING
XFRM_MSG_SETDEFAULT, XFRM_MSG_SETDEFAULT,
#define XFRM_MSG_SETDEFAULT XFRM_MSG_SETDEFAULT #define XFRM_MSG_SETDEFAULT XFRM_MSG_SETDEFAULT
XFRM_MSG_GETDEFAULT, XFRM_MSG_GETDEFAULT,
#define XFRM_MSG_GETDEFAULT XFRM_MSG_GETDEFAULT #define XFRM_MSG_GETDEFAULT XFRM_MSG_GETDEFAULT
XFRM_MSG_MAPPING,
#define XFRM_MSG_MAPPING XFRM_MSG_MAPPING
__XFRM_MSG_MAX __XFRM_MSG_MAX
}; };
#define XFRM_MSG_MAX (__XFRM_MSG_MAX - 1) #define XFRM_MSG_MAX (__XFRM_MSG_MAX - 1)
...@@ -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__
......
...@@ -1961,24 +1961,65 @@ static struct sk_buff *xfrm_policy_netlink(struct sk_buff *in_skb, ...@@ -1961,24 +1961,65 @@ static struct sk_buff *xfrm_policy_netlink(struct sk_buff *in_skb,
return skb; return skb;
} }
static int xfrm_notify_userpolicy(struct net *net)
{
struct xfrm_userpolicy_default *up;
int len = NLMSG_ALIGN(sizeof(*up));
struct nlmsghdr *nlh;
struct sk_buff *skb;
int err;
skb = nlmsg_new(len, GFP_ATOMIC);
if (skb == NULL)
return -ENOMEM;
nlh = nlmsg_put(skb, 0, 0, XFRM_MSG_GETDEFAULT, sizeof(*up), 0);
if (nlh == NULL) {
kfree_skb(skb);
return -EMSGSIZE;
}
up = nlmsg_data(nlh);
up->in = net->xfrm.policy_default & XFRM_POL_DEFAULT_IN ?
XFRM_USERPOLICY_BLOCK : XFRM_USERPOLICY_ACCEPT;
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);
rcu_read_lock();
err = xfrm_nlmsg_multicast(net, skb, 0, XFRMNLGRP_POLICY);
rcu_read_unlock();
return err;
}
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);
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);
xfrm_notify_userpolicy(net);
return 0; return 0;
} }
...@@ -1988,13 +2029,11 @@ static int xfrm_get_default(struct sk_buff *skb, struct nlmsghdr *nlh, ...@@ -1988,13 +2029,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;
...@@ -2007,8 +2046,12 @@ static int xfrm_get_default(struct sk_buff *skb, struct nlmsghdr *nlh, ...@@ -2007,8 +2046,12 @@ 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->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);
......
...@@ -126,6 +126,8 @@ static const struct nlmsg_perm nlmsg_xfrm_perms[] = ...@@ -126,6 +126,8 @@ static const struct nlmsg_perm nlmsg_xfrm_perms[] =
{ XFRM_MSG_NEWSPDINFO, NETLINK_XFRM_SOCKET__NLMSG_WRITE }, { XFRM_MSG_NEWSPDINFO, NETLINK_XFRM_SOCKET__NLMSG_WRITE },
{ XFRM_MSG_GETSPDINFO, NETLINK_XFRM_SOCKET__NLMSG_READ }, { XFRM_MSG_GETSPDINFO, NETLINK_XFRM_SOCKET__NLMSG_READ },
{ XFRM_MSG_MAPPING, NETLINK_XFRM_SOCKET__NLMSG_READ }, { XFRM_MSG_MAPPING, NETLINK_XFRM_SOCKET__NLMSG_READ },
{ XFRM_MSG_SETDEFAULT, NETLINK_XFRM_SOCKET__NLMSG_WRITE },
{ XFRM_MSG_GETDEFAULT, NETLINK_XFRM_SOCKET__NLMSG_READ },
}; };
static const struct nlmsg_perm nlmsg_audit_perms[] = static const struct nlmsg_perm nlmsg_audit_perms[] =
...@@ -189,7 +191,7 @@ int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm) ...@@ -189,7 +191,7 @@ int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm)
* structures at the top of this file with the new mappings * structures at the top of this file with the new mappings
* before updating the BUILD_BUG_ON() macro! * before updating the BUILD_BUG_ON() macro!
*/ */
BUILD_BUG_ON(XFRM_MSG_MAX != XFRM_MSG_MAPPING); BUILD_BUG_ON(XFRM_MSG_MAX != XFRM_MSG_GETDEFAULT);
err = nlmsg_perm(nlmsg_type, perm, nlmsg_xfrm_perms, err = nlmsg_perm(nlmsg_type, perm, nlmsg_xfrm_perms,
sizeof(nlmsg_xfrm_perms)); sizeof(nlmsg_xfrm_perms));
break; break;
......
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