Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1669cb98 authored by David S. Miller's avatar David S. Miller
Browse files


Steffen Klassert says:

====================
pull request (net-next): ipsec-next 2013-12-19

1) Use the user supplied policy index instead of a generated one
   if present. From Fan Du.

2) Make xfrm migration namespace aware. From Fan Du.

3) Make the xfrm state and policy locks namespace aware. From Fan Du.

4) Remove ancient sleeping when the SA is in acquire state,
   we now queue packets to the policy instead. This replaces the
   sleeping code.

5) Remove FLOWI_FLAG_CAN_SLEEP. This was used to notify xfrm about the
   posibility to sleep. The sleeping code is gone, so remove it.

6) Check user specified spi for IPComp. Thr spi for IPcomp is only
   16 bit wide, so check for a valid value. From Fan Du.

7) Export verify_userspi_info to check for valid user supplied spi ranges
   with pfkey and netlink. From Fan Du.

8) RFC3173 states that if the total size of a compressed payload and the IPComp
   header is not smaller than the size of the original payload, the IP datagram
   must be sent in the original non-compressed form. These packets are dropped
   by the inbound policy check because they are not transformed. Document the need
   to set 'level use' for IPcomp to receive such packets anyway. From Fan Du.

Please pull or let me know if there are problems.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents cb4eae3d b3c6efbc
Loading
Loading
Loading
Loading
+38 −0
Original line number Diff line number Diff line

Here documents known IPsec corner cases which need to be keep in mind when
deploy various IPsec configuration in real world production environment.

1. IPcomp: Small IP packet won't get compressed at sender, and failed on
	   policy check on receiver.

Quote from RFC3173:
2.2. Non-Expansion Policy

   If the total size of a compressed payload and the IPComp header, as
   defined in section 3, is not smaller than the size of the original
   payload, the IP datagram MUST be sent in the original non-compressed
   form.  To clarify: If an IP datagram is sent non-compressed, no

   IPComp header is added to the datagram.  This policy ensures saving
   the decompression processing cycles and avoiding incurring IP
   datagram fragmentation when the expanded datagram is larger than the
   MTU.

   Small IP datagrams are likely to expand as a result of compression.
   Therefore, a numeric threshold should be applied before compression,
   where IP datagrams of size smaller than the threshold are sent in the
   original form without attempting compression.  The numeric threshold
   is implementation dependent.

Current IPComp implementation is indeed by the book, while as in practice
when sending non-compressed packet to the peer(whether or not packet len
is smaller than the threshold or the compressed len is large than original
packet len), the packet is dropped when checking the policy as this packet
matches the selector but not coming from any XFRM layer, i.e., with no
security path. Such naked packet will not eventually make it to upper layer.
The result is much more wired to the user when ping peer with different
payload length.

One workaround is try to set "level use" for each policy if user observed
above scenario. The consequence of doing so is small packet(uncompressed)
will skip policy checking on receiver side.
+1 −2
Original line number Diff line number Diff line
@@ -20,8 +20,7 @@ struct flowi_common {
	__u8	flowic_proto;
	__u8	flowic_flags;
#define FLOWI_FLAG_ANYSRC		0x01
#define FLOWI_FLAG_CAN_SLEEP		0x02
#define FLOWI_FLAG_KNOWN_NH		0x04
#define FLOWI_FLAG_KNOWN_NH		0x02
	__u32	flowic_secid;
};

+2 −4
Original line number Diff line number Diff line
@@ -718,11 +718,9 @@ void ip6_flush_pending_frames(struct sock *sk);

int ip6_dst_lookup(struct sock *sk, struct dst_entry **dst, struct flowi6 *fl6);
struct dst_entry *ip6_dst_lookup_flow(struct sock *sk, struct flowi6 *fl6,
				      const struct in6_addr *final_dst,
				      bool can_sleep);
				      const struct in6_addr *final_dst);
struct dst_entry *ip6_sk_dst_lookup_flow(struct sock *sk, struct flowi6 *fl6,
					 const struct in6_addr *final_dst,
					 bool can_sleep);
					 const struct in6_addr *final_dst);
struct dst_entry *ip6_blackhole_route(struct net *net,
				      struct dst_entry *orig_dst);

+4 −2
Original line number Diff line number Diff line
@@ -33,8 +33,6 @@ struct netns_xfrm {
	struct hlist_head	state_gc_list;
	struct work_struct	state_gc_work;

	wait_queue_head_t	km_waitq;

	struct list_head	policy_all;
	struct hlist_head	*policy_byidx;
	unsigned int		policy_idx_hmask;
@@ -59,6 +57,10 @@ struct netns_xfrm {
#if IS_ENABLED(CONFIG_IPV6)
	struct dst_ops		xfrm6_dst_ops;
#endif
	spinlock_t xfrm_state_lock;
	spinlock_t xfrm_policy_sk_bundle_lock;
	rwlock_t xfrm_policy_lock;
	struct mutex xfrm_cfg_mutex;
};

#endif
+3 −5
Original line number Diff line number Diff line
@@ -239,14 +239,12 @@ static inline char rt_tos2priority(u8 tos)
static inline void ip_route_connect_init(struct flowi4 *fl4, __be32 dst, __be32 src,
					 u32 tos, int oif, u8 protocol,
					 __be16 sport, __be16 dport,
					 struct sock *sk, bool can_sleep)
					 struct sock *sk)
{
	__u8 flow_flags = 0;

	if (inet_sk(sk)->transparent)
		flow_flags |= FLOWI_FLAG_ANYSRC;
	if (can_sleep)
		flow_flags |= FLOWI_FLAG_CAN_SLEEP;

	flowi4_init_output(fl4, oif, sk->sk_mark, tos, RT_SCOPE_UNIVERSE,
			   protocol, flow_flags, dst, src, dport, sport);
@@ -256,13 +254,13 @@ static inline struct rtable *ip_route_connect(struct flowi4 *fl4,
					      __be32 dst, __be32 src, u32 tos,
					      int oif, u8 protocol,
					      __be16 sport, __be16 dport,
					      struct sock *sk, bool can_sleep)
					      struct sock *sk)
{
	struct net *net = sock_net(sk);
	struct rtable *rt;

	ip_route_connect_init(fl4, dst, src, tos, oif, protocol,
			      sport, dport, sk, can_sleep);
			      sport, dport, sk);

	if (!dst || !src) {
		rt = __ip_route_output_key(net, fl4);
Loading