Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

xfrm: Add possibility to set the default to block if we have no policy

As the default we assume the traffic to pass, if we have no
matching IPsec policy. With this patch, we have a possibility to
change this default from allow to block. It can be configured
via netlink. Each direction (input/output/forward) can be
configured separately. With the default to block configuered,
we need allow policies for all packet flows we accept.
We do not use default policy lookup for the loopback device.

v1->v2
- fix compiling when XFRM is disabled
- Reported-by: kernel test robot <lkp@intel.com>

Co-developed-by: Christian Langrock <christian.langrock@secunet.com>
Signed-off-by: Christian Langrock <christian.langrock@secunet.com>
Co-developed-by: Antony Antony <antony.antony@secunet.com>
Signed-off-by: Antony Antony <antony.antony@secunet.com>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>

+115 -6
+7
include/net/netns/xfrm.h
··· 65 65 u32 sysctl_aevent_rseqth; 66 66 int sysctl_larval_drop; 67 67 u32 sysctl_acq_expires; 68 + 69 + u8 policy_default; 70 + #define XFRM_POL_DEFAULT_IN 1 71 + #define XFRM_POL_DEFAULT_OUT 2 72 + #define XFRM_POL_DEFAULT_FWD 4 73 + #define XFRM_POL_DEFAULT_MASK 7 74 + 68 75 #ifdef CONFIG_SYSCTL 69 76 struct ctl_table_header *sysctl_hdr; 70 77 #endif
+30 -6
include/net/xfrm.h
··· 1075 1075 } 1076 1076 1077 1077 #ifdef CONFIG_XFRM 1078 + static inline bool 1079 + xfrm_default_allow(struct net *net, int dir) 1080 + { 1081 + u8 def = net->xfrm.policy_default; 1082 + 1083 + switch (dir) { 1084 + case XFRM_POLICY_IN: 1085 + return def & XFRM_POL_DEFAULT_IN ? false : true; 1086 + case XFRM_POLICY_OUT: 1087 + return def & XFRM_POL_DEFAULT_OUT ? false : true; 1088 + case XFRM_POLICY_FWD: 1089 + return def & XFRM_POL_DEFAULT_FWD ? false : true; 1090 + } 1091 + return false; 1092 + } 1093 + 1078 1094 int __xfrm_policy_check(struct sock *, int dir, struct sk_buff *skb, 1079 1095 unsigned short family); 1080 1096 ··· 1104 1088 if (sk && sk->sk_policy[XFRM_POLICY_IN]) 1105 1089 return __xfrm_policy_check(sk, ndir, skb, family); 1106 1090 1107 - return (!net->xfrm.policy_count[dir] && !secpath_exists(skb)) || 1108 - (skb_dst(skb) && (skb_dst(skb)->flags & DST_NOPOLICY)) || 1109 - __xfrm_policy_check(sk, ndir, skb, family); 1091 + if (xfrm_default_allow(net, dir)) 1092 + return (!net->xfrm.policy_count[dir] && !secpath_exists(skb)) || 1093 + (skb_dst(skb) && (skb_dst(skb)->flags & DST_NOPOLICY)) || 1094 + __xfrm_policy_check(sk, ndir, skb, family); 1095 + else 1096 + return (skb_dst(skb) && (skb_dst(skb)->flags & DST_NOPOLICY)) || 1097 + __xfrm_policy_check(sk, ndir, skb, family); 1110 1098 } 1111 1099 1112 1100 static inline int xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, unsigned short family) ··· 1162 1142 { 1163 1143 struct net *net = dev_net(skb->dev); 1164 1144 1165 - return !net->xfrm.policy_count[XFRM_POLICY_OUT] || 1166 - (skb_dst(skb)->flags & DST_NOXFRM) || 1167 - __xfrm_route_forward(skb, family); 1145 + if (xfrm_default_allow(net, XFRM_POLICY_FWD)) 1146 + return !net->xfrm.policy_count[XFRM_POLICY_OUT] || 1147 + (skb_dst(skb)->flags & DST_NOXFRM) || 1148 + __xfrm_route_forward(skb, family); 1149 + else 1150 + return (skb_dst(skb)->flags & DST_NOXFRM) || 1151 + __xfrm_route_forward(skb, family); 1168 1152 } 1169 1153 1170 1154 static inline int xfrm4_route_forward(struct sk_buff *skb)
+10
include/uapi/linux/xfrm.h
··· 213 213 XFRM_MSG_GETSPDINFO, 214 214 #define XFRM_MSG_GETSPDINFO XFRM_MSG_GETSPDINFO 215 215 216 + XFRM_MSG_SETDEFAULT, 217 + #define XFRM_MSG_SETDEFAULT XFRM_MSG_SETDEFAULT 218 + XFRM_MSG_GETDEFAULT, 219 + #define XFRM_MSG_GETDEFAULT XFRM_MSG_GETDEFAULT 220 + 216 221 XFRM_MSG_MAPPING, 217 222 #define XFRM_MSG_MAPPING XFRM_MSG_MAPPING 218 223 __XFRM_MSG_MAX ··· 512 507 }; 513 508 #define XFRM_OFFLOAD_IPV6 1 514 509 #define XFRM_OFFLOAD_INBOUND 2 510 + 511 + struct xfrm_userpolicy_default { 512 + __u8 dirmask; 513 + __u8 action; 514 + }; 515 515 516 516 #ifndef __KERNEL__ 517 517 /* backwards compatibility for userspace */
+16
net/xfrm/xfrm_policy.c
··· 3165 3165 return dst; 3166 3166 3167 3167 nopol: 3168 + if (!(dst_orig->dev->flags & IFF_LOOPBACK) && 3169 + !xfrm_default_allow(net, dir)) { 3170 + err = -EPERM; 3171 + goto error; 3172 + } 3168 3173 if (!(flags & XFRM_LOOKUP_ICMP)) { 3169 3174 dst = dst_orig; 3170 3175 goto ok; ··· 3558 3553 } 3559 3554 3560 3555 if (!pol) { 3556 + if (!xfrm_default_allow(net, dir)) { 3557 + XFRM_INC_STATS(net, LINUX_MIB_XFRMINNOPOLS); 3558 + return 0; 3559 + } 3560 + 3561 3561 if (sp && secpath_has_nontransport(sp, 0, &xerr_idx)) { 3562 3562 xfrm_secpath_reject(xerr_idx, skb, &fl); 3563 3563 XFRM_INC_STATS(net, LINUX_MIB_XFRMINNOPOLS); ··· 3617 3607 tpp[ti++] = &pols[pi]->xfrm_vec[i]; 3618 3608 } 3619 3609 xfrm_nr = ti; 3610 + 3611 + if (!xfrm_default_allow(net, dir) && !xfrm_nr) { 3612 + XFRM_INC_STATS(net, LINUX_MIB_XFRMINNOSTATES); 3613 + goto reject; 3614 + } 3615 + 3620 3616 if (npols > 1) { 3621 3617 xfrm_tmpl_sort(stp, tpp, xfrm_nr, family); 3622 3618 tpp = stp;
+52
net/xfrm/xfrm_user.c
··· 1961 1961 return skb; 1962 1962 } 1963 1963 1964 + static int xfrm_set_default(struct sk_buff *skb, struct nlmsghdr *nlh, 1965 + struct nlattr **attrs) 1966 + { 1967 + struct net *net = sock_net(skb->sk); 1968 + struct xfrm_userpolicy_default *up = nlmsg_data(nlh); 1969 + u8 dirmask = (1 << up->dirmask) & XFRM_POL_DEFAULT_MASK; 1970 + u8 old_default = net->xfrm.policy_default; 1971 + 1972 + net->xfrm.policy_default = (old_default & (0xff ^ dirmask)) 1973 + | (up->action << up->dirmask); 1974 + 1975 + rt_genid_bump_all(net); 1976 + 1977 + return 0; 1978 + } 1979 + 1980 + static int xfrm_get_default(struct sk_buff *skb, struct nlmsghdr *nlh, 1981 + struct nlattr **attrs) 1982 + { 1983 + struct sk_buff *r_skb; 1984 + struct nlmsghdr *r_nlh; 1985 + struct net *net = sock_net(skb->sk); 1986 + struct xfrm_userpolicy_default *r_up, *up; 1987 + int len = NLMSG_ALIGN(sizeof(struct xfrm_userpolicy_default)); 1988 + u32 portid = NETLINK_CB(skb).portid; 1989 + u32 seq = nlh->nlmsg_seq; 1990 + 1991 + up = nlmsg_data(nlh); 1992 + 1993 + r_skb = nlmsg_new(len, GFP_ATOMIC); 1994 + if (!r_skb) 1995 + return -ENOMEM; 1996 + 1997 + r_nlh = nlmsg_put(r_skb, portid, seq, XFRM_MSG_GETDEFAULT, sizeof(*r_up), 0); 1998 + if (!r_nlh) { 1999 + kfree_skb(r_skb); 2000 + return -EMSGSIZE; 2001 + } 2002 + 2003 + r_up = nlmsg_data(r_nlh); 2004 + 2005 + r_up->action = ((net->xfrm.policy_default & (1 << up->dirmask)) >> up->dirmask); 2006 + r_up->dirmask = up->dirmask; 2007 + nlmsg_end(r_skb, r_nlh); 2008 + 2009 + return nlmsg_unicast(net->xfrm.nlsk, r_skb, portid); 2010 + } 2011 + 1964 2012 static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, 1965 2013 struct nlattr **attrs) 1966 2014 { ··· 2712 2664 [XFRM_MSG_GETSADINFO - XFRM_MSG_BASE] = sizeof(u32), 2713 2665 [XFRM_MSG_NEWSPDINFO - XFRM_MSG_BASE] = sizeof(u32), 2714 2666 [XFRM_MSG_GETSPDINFO - XFRM_MSG_BASE] = sizeof(u32), 2667 + [XFRM_MSG_SETDEFAULT - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_default), 2668 + [XFRM_MSG_GETDEFAULT - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_default), 2715 2669 }; 2716 2670 EXPORT_SYMBOL_GPL(xfrm_msg_min); 2717 2671 ··· 2793 2743 .nla_pol = xfrma_spd_policy, 2794 2744 .nla_max = XFRMA_SPD_MAX }, 2795 2745 [XFRM_MSG_GETSPDINFO - XFRM_MSG_BASE] = { .doit = xfrm_get_spdinfo }, 2746 + [XFRM_MSG_SETDEFAULT - XFRM_MSG_BASE] = { .doit = xfrm_set_default }, 2747 + [XFRM_MSG_GETDEFAULT - XFRM_MSG_BASE] = { .doit = xfrm_get_default }, 2796 2748 }; 2797 2749 2798 2750 static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh,