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

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