return false;
 }
 
+static inline bool __xfrm_check_dev_nopolicy(struct sk_buff *skb,
+                                            int dir, unsigned short family)
+{
+       if (dir != XFRM_POLICY_OUT && family == AF_INET) {
+               /* same dst may be used for traffic originating from
+                * devices with different policy settings.
+                */
+               return IPCB(skb)->flags & IPSKB_NOPOLICY;
+       }
+       return skb_dst(skb) && (skb_dst(skb)->flags & DST_NOPOLICY);
+}
+
 static inline int __xfrm_policy_check2(struct sock *sk, int dir,
                                       struct sk_buff *skb,
                                       unsigned int family, int reverse)
                return __xfrm_policy_check(sk, ndir, skb, family);
 
        return __xfrm_check_nopolicy(net, skb, dir) ||
-              (skb_dst(skb) && (skb_dst(skb)->flags & DST_NOPOLICY)) ||
+              __xfrm_check_dev_nopolicy(skb, dir, family) ||
               __xfrm_policy_check(sk, ndir, skb, family);
 }
 
 
        struct in_device *in_dev = __in_dev_get_rcu(dev);
        unsigned int flags = RTCF_MULTICAST;
        struct rtable *rth;
+       bool no_policy;
        u32 itag = 0;
        int err;
 
        if (our)
                flags |= RTCF_LOCAL;
 
+       no_policy = IN_DEV_ORCONF(in_dev, NOPOLICY);
+       if (no_policy)
+               IPCB(skb)->flags |= IPSKB_NOPOLICY;
+
        rth = rt_dst_alloc(dev_net(dev)->loopback_dev, flags, RTN_MULTICAST,
-                          IN_DEV_ORCONF(in_dev, NOPOLICY), false);
+                          no_policy, false);
        if (!rth)
                return -ENOBUFS;
 
        struct rtable *rth;
        int err;
        struct in_device *out_dev;
-       bool do_cache;
+       bool do_cache, no_policy;
        u32 itag = 0;
 
        /* get a working reference to the output device */
                }
        }
 
+       no_policy = IN_DEV_ORCONF(in_dev, NOPOLICY);
+       if (no_policy)
+               IPCB(skb)->flags |= IPSKB_NOPOLICY;
+
        fnhe = find_exception(nhc, daddr);
        if (do_cache) {
                if (fnhe)
                }
        }
 
-       rth = rt_dst_alloc(out_dev->dev, 0, res->type,
-                          IN_DEV_ORCONF(in_dev, NOPOLICY),
+       rth = rt_dst_alloc(out_dev->dev, 0, res->type, no_policy,
                           IN_DEV_ORCONF(out_dev, NOXFRM));
        if (!rth) {
                err = -ENOBUFS;
        struct rtable   *rth;
        struct flowi4   fl4;
        bool do_cache = true;
+       bool no_policy;
 
        /* IP on this device is disabled. */
 
        RT_CACHE_STAT_INC(in_brd);
 
 local_input:
+       no_policy = IN_DEV_ORCONF(in_dev, NOPOLICY);
+       if (no_policy)
+               IPCB(skb)->flags |= IPSKB_NOPOLICY;
+
        do_cache &= res->fi && !itag;
        if (do_cache) {
                struct fib_nh_common *nhc = FIB_RES_NHC(*res);
 
        rth = rt_dst_alloc(ip_rt_get_dev(net, res),
                           flags | RTCF_LOCAL, res->type,
-                          IN_DEV_ORCONF(in_dev, NOPOLICY), false);
+                          no_policy, false);
        if (!rth)
                goto e_nobufs;