diff -urp v4.19/linux/Documentation/networking/ip-sysctl.txt linux/Documentation/networking/ip-sysctl.txt
--- v4.19/linux/Documentation/networking/ip-sysctl.txt	2018-10-28 11:32:19.000000000 +0200
+++ linux/Documentation/networking/ip-sysctl.txt	2018-10-28 11:33:50.498630730 +0200
@@ -1053,6 +1053,19 @@ forwarding - BOOLEAN
 	Enable IP forwarding on this interface.  This controls whether packets
 	received _on_ this interface can be forwarded.
 
+forward_shared - BOOLEAN
+	Integer value determines if a source validation should allow
+	forwarding of packets with local source address. 1 means yes,
+	0 means no. By default the flag is disabled and such packets
+	are not forwarded.
+ 
+	If you enable this flag on internal network, the router will forward
+	packets from internal hosts with shared IP addresses no matter how
+	the rp_filter is set. This flag is activated only if it is
+	enabled both in specific device section and in "all" section.
+
+	The forward_shared value could be ignored when rp_filter is set to 0.
+
 mc_forwarding - BOOLEAN
 	Do multicast routing. The kernel needs to be compiled with CONFIG_MROUTE
 	and a multicast routing daemon is required.
diff -urp v4.19/linux/include/linux/inetdevice.h linux/include/linux/inetdevice.h
--- v4.19/linux/include/linux/inetdevice.h	2018-10-28 11:32:19.000000000 +0200
+++ linux/include/linux/inetdevice.h	2018-10-28 11:33:50.498630730 +0200
@@ -98,6 +98,7 @@ static inline void ipv4_devconf_setall(s
 #define IN_DEV_SRC_VMARK(in_dev)    	IN_DEV_ORCONF((in_dev), SRC_VMARK)
 #define IN_DEV_SOURCE_ROUTE(in_dev)	IN_DEV_ANDCONF((in_dev), \
 						       ACCEPT_SOURCE_ROUTE)
+#define IN_DEV_FORWARD_SHARED(in_dev)	IN_DEV_ANDCONF((in_dev), FORWARD_SHARED)
 #define IN_DEV_ACCEPT_LOCAL(in_dev)	IN_DEV_ORCONF((in_dev), ACCEPT_LOCAL)
 #define IN_DEV_BOOTP_RELAY(in_dev)	IN_DEV_ANDCONF((in_dev), BOOTP_RELAY)
 
diff -urp v4.19/linux/include/net/ip_fib.h linux/include/net/ip_fib.h
--- v4.19/linux/include/net/ip_fib.h	2018-10-28 11:32:19.000000000 +0200
+++ linux/include/net/ip_fib.h	2018-10-28 11:33:50.498630730 +0200
@@ -375,7 +375,7 @@ void ip_fib_init(void);
 __be32 fib_compute_spec_dst(struct sk_buff *skb);
 int fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst,
 			u8 tos, int oif, struct net_device *dev,
-			struct in_device *idev, u32 *itag);
+			struct in_device *idev, u32 *itag, int our);
 #ifdef CONFIG_IP_ROUTE_CLASSID
 static inline int fib_num_tclassid_users(struct net *net)
 {
diff -urp v4.19/linux/include/uapi/linux/ip.h linux/include/uapi/linux/ip.h
--- v4.19/linux/include/uapi/linux/ip.h	2018-10-28 11:32:19.000000000 +0200
+++ linux/include/uapi/linux/ip.h	2018-10-28 11:34:14.237326011 +0200
@@ -169,6 +169,7 @@ enum
 	IPV4_DEVCONF_DROP_UNICAST_IN_L2_MULTICAST,
 	IPV4_DEVCONF_DROP_GRATUITOUS_ARP,
 	IPV4_DEVCONF_BC_FORWARDING,
+	IPV4_DEVCONF_FORWARD_SHARED,
 	__IPV4_DEVCONF_MAX
 };
 
diff -urp v4.19/linux/net/ipv4/devinet.c linux/net/ipv4/devinet.c
--- v4.19/linux/net/ipv4/devinet.c	2018-10-28 11:32:19.000000000 +0200
+++ linux/net/ipv4/devinet.c	2018-10-28 11:33:50.499630718 +0200
@@ -2278,6 +2278,7 @@ static struct devinet_sysctl_table {
 		DEVINET_SYSCTL_RW_ENTRY(SEND_REDIRECTS, "send_redirects"),
 		DEVINET_SYSCTL_RW_ENTRY(ACCEPT_SOURCE_ROUTE,
 					"accept_source_route"),
+		DEVINET_SYSCTL_RW_ENTRY(FORWARD_SHARED, "forward_shared"),
 		DEVINET_SYSCTL_RW_ENTRY(ACCEPT_LOCAL, "accept_local"),
 		DEVINET_SYSCTL_RW_ENTRY(SRC_VMARK, "src_valid_mark"),
 		DEVINET_SYSCTL_RW_ENTRY(PROXY_ARP, "proxy_arp"),
diff -urp v4.19/linux/net/ipv4/fib_frontend.c linux/net/ipv4/fib_frontend.c
--- v4.19/linux/net/ipv4/fib_frontend.c	2018-10-28 11:32:19.000000000 +0200
+++ linux/net/ipv4/fib_frontend.c	2018-10-28 11:33:50.500630705 +0200
@@ -325,13 +325,15 @@ __be32 fib_compute_spec_dst(struct sk_bu
  */
 static int __fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst,
 				 u8 tos, int oif, struct net_device *dev,
-				 int rpf, struct in_device *idev, u32 *itag)
+				 int rpf, struct in_device *idev, u32 *itag,
+				 int our)
 {
 	struct net *net = dev_net(dev);
 	struct flow_keys flkeys;
 	int ret, no_addr;
 	struct fib_result res;
 	struct flowi4 fl4;
+	int fwdsh;
 	bool dev_match;
 
 	fl4.flowi4_oif = 0;
@@ -348,6 +350,7 @@ static int __fib_validate_source(struct
 
 	no_addr = idev->ifa_list == NULL;
 
+	fwdsh = IN_DEV_FORWARD_SHARED(idev);
 	fl4.flowi4_mark = IN_DEV_SRC_VMARK(idev) ? skb->mark : 0;
 	if (!fib4_rules_early_flow_dissect(net, skb, &fl4, &flkeys)) {
 		fl4.flowi4_proto = 0;
@@ -357,7 +360,12 @@ static int __fib_validate_source(struct
 
 	if (fib_lookup(net, &fl4, &res, 0))
 		goto last_resort;
-	if (res.type != RTN_UNICAST &&
+	if (fwdsh) {
+		fwdsh = (res.type == RTN_LOCAL && !our);
+		if (fwdsh)
+			rpf = 0;
+	}
+	if (res.type != RTN_UNICAST && !fwdsh &&
 	    (res.type != RTN_LOCAL || !IN_DEV_ACCEPT_LOCAL(idev)))
 		goto e_inval;
 	fib_combine_itag(itag, &res);
@@ -388,6 +396,8 @@ static int __fib_validate_source(struct
 	if (rpf == 1)
 		goto e_rpf;
 	fl4.flowi4_oif = dev->ifindex;
+	if (fwdsh)
+		fl4.flowi4_iif = LOOPBACK_IFINDEX;
 
 	ret = 0;
 	if (fib_lookup(net, &fl4, &res, FIB_LOOKUP_IGNORE_LINKSTATE) == 0) {
@@ -411,7 +421,7 @@ e_rpf:
 /* Ignore rp_filter for packets protected by IPsec. */
 int fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst,
 			u8 tos, int oif, struct net_device *dev,
-			struct in_device *idev, u32 *itag)
+			struct in_device *idev, u32 *itag, int our)
 {
 	int r = secpath_exists(skb) ? 0 : IN_DEV_RPFILTER(idev);
 	struct net *net = dev_net(dev);
@@ -436,7 +446,8 @@ ok:
 	}
 
 full_check:
-	return __fib_validate_source(skb, src, dst, tos, oif, dev, r, idev, itag);
+	return __fib_validate_source(skb, src, dst, tos, oif, dev, r, idev,
+				     itag, our);
 }
 
 static inline __be32 sk_extract_addr(struct sockaddr *addr)
diff -urp v4.19/linux/net/ipv4/route.c linux/net/ipv4/route.c
--- v4.19/linux/net/ipv4/route.c	2018-10-28 11:32:19.000000000 +0200
+++ linux/net/ipv4/route.c	2018-10-28 11:33:50.501630692 +0200
@@ -1623,7 +1623,7 @@ int ip_mc_validate_source(struct sk_buff
 			return -EINVAL;
 	} else {
 		err = fib_validate_source(skb, saddr, 0, tos, 0, dev,
-					  in_dev, itag);
+					  in_dev, itag, 1);
 		if (err < 0)
 			return err;
 	}
@@ -1715,7 +1715,7 @@ static int __mkroute_input(struct sk_buf
 	}
 
 	err = fib_validate_source(skb, saddr, daddr, tos, FIB_RES_OIF(*res),
-				  in_dev->dev, in_dev, &itag);
+				  in_dev->dev, in_dev, &itag, 0);
 	if (err < 0) {
 		ip_handle_martian_source(in_dev->dev, in_dev, skb, daddr,
 					 saddr);
@@ -2005,7 +2005,7 @@ static int ip_route_input_slow(struct sk
 
 	if (res->type == RTN_LOCAL) {
 		err = fib_validate_source(skb, saddr, daddr, tos,
-					  0, dev, in_dev, &itag);
+					  0, dev, in_dev, &itag, 1);
 		if (err < 0)
 			goto martian_source;
 		goto local_input;
@@ -2028,7 +2028,7 @@ brd_input:
 
 	if (!ipv4_is_zeronet(saddr)) {
 		err = fib_validate_source(skb, saddr, 0, tos, 0, dev,
-					  in_dev, &itag);
+					  in_dev, &itag, 1);
 		if (err < 0)
 			goto martian_source;
 	}
