670-ipv6-allow-rejecting-with-source-address-failed-policy.patch 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. --- a/include/net/netns/ipv6.h
  2. +++ b/include/net/netns/ipv6.h
  3. @@ -55,6 +55,7 @@ struct netns_ipv6 {
  4. unsigned long ip6_rt_last_gc;
  5. #ifdef CONFIG_IPV6_MULTIPLE_TABLES
  6. struct rt6_info *ip6_prohibit_entry;
  7. + struct rt6_info *ip6_failed_policy_entry;
  8. struct rt6_info *ip6_blk_hole_entry;
  9. struct fib6_table *fib6_local_tbl;
  10. struct fib_rules_ops *fib6_rules_ops;
  11. --- a/include/uapi/linux/fib_rules.h
  12. +++ b/include/uapi/linux/fib_rules.h
  13. @@ -64,6 +64,10 @@ enum {
  14. FR_ACT_BLACKHOLE, /* Drop without notification */
  15. FR_ACT_UNREACHABLE, /* Drop with ENETUNREACH */
  16. FR_ACT_PROHIBIT, /* Drop with EACCES */
  17. + FR_ACT_RES9,
  18. + FR_ACT_RES10,
  19. + FR_ACT_RES11,
  20. + FR_ACT_FAILED_POLICY, /* Drop with EPERM */
  21. __FR_ACT_MAX,
  22. };
  23. --- a/include/uapi/linux/rtnetlink.h
  24. +++ b/include/uapi/linux/rtnetlink.h
  25. @@ -203,6 +203,7 @@ enum {
  26. RTN_THROW, /* Not in this table */
  27. RTN_NAT, /* Translate this address */
  28. RTN_XRESOLVE, /* Use external resolver */
  29. + RTN_FAILED_POLICY, /* Failed ingress/egress policy */
  30. __RTN_MAX
  31. };
  32. --- a/net/ipv4/fib_rules.c
  33. +++ b/net/ipv4/fib_rules.c
  34. @@ -84,6 +84,10 @@ static int fib4_rule_action(struct fib_r
  35. err = -EACCES;
  36. goto errout;
  37. + case FR_ACT_FAILED_POLICY:
  38. + err = -EPERM;
  39. + goto errout;
  40. +
  41. case FR_ACT_BLACKHOLE:
  42. default:
  43. err = -EINVAL;
  44. --- a/net/ipv4/fib_semantics.c
  45. +++ b/net/ipv4/fib_semantics.c
  46. @@ -138,6 +138,10 @@ const struct fib_prop fib_props[RTN_MAX
  47. .error = -EINVAL,
  48. .scope = RT_SCOPE_NOWHERE,
  49. },
  50. + [RTN_FAILED_POLICY] = {
  51. + .error = -EPERM,
  52. + .scope = RT_SCOPE_UNIVERSE,
  53. + },
  54. };
  55. static void rt_fibinfo_free(struct rtable __rcu **rtp)
  56. --- a/net/ipv4/fib_trie.c
  57. +++ b/net/ipv4/fib_trie.c
  58. @@ -2331,6 +2331,7 @@ static const char *const rtn_type_names[
  59. [RTN_THROW] = "THROW",
  60. [RTN_NAT] = "NAT",
  61. [RTN_XRESOLVE] = "XRESOLVE",
  62. + [RTN_FAILED_POLICY] = "FAILED_POLICY",
  63. };
  64. static inline const char *rtn_type(char *buf, size_t len, unsigned int t)
  65. --- a/net/ipv4/ipmr.c
  66. +++ b/net/ipv4/ipmr.c
  67. @@ -181,6 +181,7 @@ static int ipmr_rule_action(struct fib_r
  68. case FR_ACT_UNREACHABLE:
  69. return -ENETUNREACH;
  70. case FR_ACT_PROHIBIT:
  71. + case FR_ACT_FAILED_POLICY:
  72. return -EACCES;
  73. case FR_ACT_BLACKHOLE:
  74. default:
  75. --- a/net/ipv6/fib6_rules.c
  76. +++ b/net/ipv6/fib6_rules.c
  77. @@ -69,6 +69,9 @@ static int fib6_rule_action(struct fib_r
  78. case FR_ACT_PROHIBIT:
  79. rt = net->ipv6.ip6_prohibit_entry;
  80. goto discard_pkt;
  81. + case FR_ACT_FAILED_POLICY:
  82. + rt = net->ipv6.ip6_failed_policy_entry;
  83. + goto discard_pkt;
  84. }
  85. table = fib6_get_table(net, rule->table);
  86. --- a/net/ipv6/ip6mr.c
  87. +++ b/net/ipv6/ip6mr.c
  88. @@ -166,6 +166,8 @@ static int ip6mr_rule_action(struct fib_
  89. return -ENETUNREACH;
  90. case FR_ACT_PROHIBIT:
  91. return -EACCES;
  92. + case FR_ACT_FAILED_POLICY:
  93. + return -EPERM;
  94. case FR_ACT_BLACKHOLE:
  95. default:
  96. return -EINVAL;
  97. --- a/net/ipv6/route.c
  98. +++ b/net/ipv6/route.c
  99. @@ -251,6 +251,24 @@ static const struct rt6_info ip6_prohibi
  100. .rt6i_ref = ATOMIC_INIT(1),
  101. };
  102. +static int ip6_pkt_failed_policy(struct sk_buff *skb);
  103. +static int ip6_pkt_failed_policy_out(struct sk_buff *skb);
  104. +
  105. +static const struct rt6_info ip6_failed_policy_entry_template = {
  106. + .dst = {
  107. + .__refcnt = ATOMIC_INIT(1),
  108. + .__use = 1,
  109. + .obsolete = DST_OBSOLETE_FORCE_CHK,
  110. + .error = -EPERM,
  111. + .input = ip6_pkt_failed_policy,
  112. + .output = ip6_pkt_failed_policy_out,
  113. + },
  114. + .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP),
  115. + .rt6i_protocol = RTPROT_KERNEL,
  116. + .rt6i_metric = ~(u32) 0,
  117. + .rt6i_ref = ATOMIC_INIT(1),
  118. +};
  119. +
  120. static const struct rt6_info ip6_blk_hole_entry_template = {
  121. .dst = {
  122. .__refcnt = ATOMIC_INIT(1),
  123. @@ -1508,6 +1526,9 @@ int ip6_route_add(struct fib6_config *cf
  124. case RTN_THROW:
  125. rt->dst.error = -EAGAIN;
  126. break;
  127. + case RTN_FAILED_POLICY:
  128. + rt->dst.error = -EPERM;
  129. + break;
  130. default:
  131. rt->dst.error = -ENETUNREACH;
  132. break;
  133. @@ -2087,6 +2108,17 @@ static int ip6_pkt_prohibit_out(struct s
  134. return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED, IPSTATS_MIB_OUTNOROUTES);
  135. }
  136. +static int ip6_pkt_failed_policy(struct sk_buff *skb)
  137. +{
  138. + return ip6_pkt_drop(skb, ICMPV6_POLICY_FAIL, IPSTATS_MIB_INNOROUTES);
  139. +}
  140. +
  141. +static int ip6_pkt_failed_policy_out(struct sk_buff *skb)
  142. +{
  143. + skb->dev = skb_dst(skb)->dev;
  144. + return ip6_pkt_drop(skb, ICMPV6_POLICY_FAIL, IPSTATS_MIB_OUTNOROUTES);
  145. +}
  146. +
  147. #endif
  148. /*
  149. @@ -2293,7 +2325,8 @@ static int rtm_to_fib6_config(struct sk_
  150. if (rtm->rtm_type == RTN_UNREACHABLE ||
  151. rtm->rtm_type == RTN_BLACKHOLE ||
  152. rtm->rtm_type == RTN_PROHIBIT ||
  153. - rtm->rtm_type == RTN_THROW)
  154. + rtm->rtm_type == RTN_THROW ||
  155. + rtm->rtm_type == RTN_FAILED_POLICY)
  156. cfg->fc_flags |= RTF_REJECT;
  157. if (rtm->rtm_type == RTN_LOCAL)
  158. @@ -2495,6 +2528,9 @@ static int rt6_fill_node(struct net *net
  159. case -EACCES:
  160. rtm->rtm_type = RTN_PROHIBIT;
  161. break;
  162. + case -EPERM:
  163. + rtm->rtm_type = RTN_FAILED_POLICY;
  164. + break;
  165. case -EAGAIN:
  166. rtm->rtm_type = RTN_THROW;
  167. break;
  168. @@ -2745,6 +2781,8 @@ static int ip6_route_dev_notify(struct n
  169. #ifdef CONFIG_IPV6_MULTIPLE_TABLES
  170. net->ipv6.ip6_prohibit_entry->dst.dev = dev;
  171. net->ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(dev);
  172. + net->ipv6.ip6_failed_policy_entry->dst.dev = dev;
  173. + net->ipv6.ip6_failed_policy_entry->rt6i_idev = in6_dev_get(dev);
  174. net->ipv6.ip6_blk_hole_entry->dst.dev = dev;
  175. net->ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(dev);
  176. #endif
  177. @@ -3005,6 +3043,17 @@ static int __net_init ip6_route_net_init
  178. net->ipv6.ip6_blk_hole_entry->dst.ops = &net->ipv6.ip6_dst_ops;
  179. dst_init_metrics(&net->ipv6.ip6_blk_hole_entry->dst,
  180. ip6_template_metrics, true);
  181. +
  182. + net->ipv6.ip6_failed_policy_entry =
  183. + kmemdup(&ip6_failed_policy_entry_template,
  184. + sizeof(*net->ipv6.ip6_failed_policy_entry), GFP_KERNEL);
  185. + if (!net->ipv6.ip6_failed_policy_entry)
  186. + goto out_ip6_blk_hole_entry;
  187. + net->ipv6.ip6_failed_policy_entry->dst.path =
  188. + (struct dst_entry *)net->ipv6.ip6_failed_policy_entry;
  189. + net->ipv6.ip6_failed_policy_entry->dst.ops = &net->ipv6.ip6_dst_ops;
  190. + dst_init_metrics(&net->ipv6.ip6_failed_policy_entry->dst,
  191. + ip6_template_metrics, true);
  192. #endif
  193. net->ipv6.sysctl.flush_delay = 0;
  194. @@ -3023,6 +3072,8 @@ out:
  195. return ret;
  196. #ifdef CONFIG_IPV6_MULTIPLE_TABLES
  197. +out_ip6_blk_hole_entry:
  198. + kfree(net->ipv6.ip6_blk_hole_entry);
  199. out_ip6_prohibit_entry:
  200. kfree(net->ipv6.ip6_prohibit_entry);
  201. out_ip6_null_entry:
  202. @@ -3040,6 +3091,7 @@ static void __net_exit ip6_route_net_exi
  203. #ifdef CONFIG_IPV6_MULTIPLE_TABLES
  204. kfree(net->ipv6.ip6_prohibit_entry);
  205. kfree(net->ipv6.ip6_blk_hole_entry);
  206. + kfree(net->ipv6.ip6_failed_policy_entry);
  207. #endif
  208. dst_entries_destroy(&net->ipv6.ip6_dst_ops);
  209. }
  210. @@ -3136,6 +3188,9 @@ int __init ip6_route_init(void)
  211. init_net.ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
  212. init_net.ipv6.ip6_blk_hole_entry->dst.dev = init_net.loopback_dev;
  213. init_net.ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
  214. + init_net.ipv6.ip6_failed_policy_entry->dst.dev = init_net.loopback_dev;
  215. + init_net.ipv6.ip6_failed_policy_entry->rt6i_idev =
  216. + in6_dev_get(init_net.loopback_dev);
  217. #endif
  218. ret = fib6_init();
  219. if (ret)