| From ed17b8d377eaf6b4a01d46942b4c647378a79bdd Mon Sep 17 00:00:00 2001 |
| From: Xin Long <lucien.xin@gmail.com> |
| Date: Mon, 25 May 2020 13:53:37 +0800 |
| Subject: xfrm: fix a warning in xfrm_policy_insert_list |
| |
| From: Xin Long <lucien.xin@gmail.com> |
| |
| commit ed17b8d377eaf6b4a01d46942b4c647378a79bdd upstream. |
| |
| This waring can be triggered simply by: |
| |
| # ip xfrm policy update src 192.168.1.1/24 dst 192.168.1.2/24 dir in \ |
| priority 1 mark 0 mask 0x10 #[1] |
| # ip xfrm policy update src 192.168.1.1/24 dst 192.168.1.2/24 dir in \ |
| priority 2 mark 0 mask 0x1 #[2] |
| # ip xfrm policy update src 192.168.1.1/24 dst 192.168.1.2/24 dir in \ |
| priority 2 mark 0 mask 0x10 #[3] |
| |
| Then dmesg shows: |
| |
| [ ] WARNING: CPU: 1 PID: 7265 at net/xfrm/xfrm_policy.c:1548 |
| [ ] RIP: 0010:xfrm_policy_insert_list+0x2f2/0x1030 |
| [ ] Call Trace: |
| [ ] xfrm_policy_inexact_insert+0x85/0xe50 |
| [ ] xfrm_policy_insert+0x4ba/0x680 |
| [ ] xfrm_add_policy+0x246/0x4d0 |
| [ ] xfrm_user_rcv_msg+0x331/0x5c0 |
| [ ] netlink_rcv_skb+0x121/0x350 |
| [ ] xfrm_netlink_rcv+0x66/0x80 |
| [ ] netlink_unicast+0x439/0x630 |
| [ ] netlink_sendmsg+0x714/0xbf0 |
| [ ] sock_sendmsg+0xe2/0x110 |
| |
| The issue was introduced by Commit 7cb8a93968e3 ("xfrm: Allow inserting |
| policies with matching mark and different priorities"). After that, the |
| policies [1] and [2] would be able to be added with different priorities. |
| |
| However, policy [3] will actually match both [1] and [2]. Policy [1] |
| was matched due to the 1st 'return true' in xfrm_policy_mark_match(), |
| and policy [2] was matched due to the 2nd 'return true' in there. It |
| caused WARN_ON() in xfrm_policy_insert_list(). |
| |
| This patch is to fix it by only (the same value and priority) as the |
| same policy in xfrm_policy_mark_match(). |
| |
| Thanks to Yuehaibing, we could make this fix better. |
| |
| v1->v2: |
| - check policy->mark.v == pol->mark.v only without mask. |
| |
| Fixes: 7cb8a93968e3 ("xfrm: Allow inserting policies with matching mark and different priorities") |
| Reported-by: Xiumei Mu <xmu@redhat.com> |
| Signed-off-by: Xin Long <lucien.xin@gmail.com> |
| Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| net/xfrm/xfrm_policy.c | 7 +------ |
| 1 file changed, 1 insertion(+), 6 deletions(-) |
| |
| --- a/net/xfrm/xfrm_policy.c |
| +++ b/net/xfrm/xfrm_policy.c |
| @@ -722,12 +722,7 @@ static void xfrm_policy_requeue(struct x |
| static bool xfrm_policy_mark_match(struct xfrm_policy *policy, |
| struct xfrm_policy *pol) |
| { |
| - u32 mark = policy->mark.v & policy->mark.m; |
| - |
| - if (policy->mark.v == pol->mark.v && policy->mark.m == pol->mark.m) |
| - return true; |
| - |
| - if ((mark & pol->mark.m) == pol->mark.v && |
| + if (policy->mark.v == pol->mark.v && |
| policy->priority == pol->priority) |
| return true; |
| |