| From 17a6afea452029afa79f50c78ea36baac1607cec Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Tue, 18 Jan 2022 16:00:14 -0800 |
| Subject: xfrm: Fix xfrm migrate issues when address family changes |
| |
| From: Yan Yan <evitayan@google.com> |
| |
| [ Upstream commit e03c3bba351f99ad932e8f06baa9da1afc418e02 ] |
| |
| xfrm_migrate cannot handle address family change of an xfrm_state. |
| The symptons are the xfrm_state will be migrated to a wrong address, |
| and sending as well as receiving packets wil be broken. |
| |
| This commit fixes it by breaking the original xfrm_state_clone |
| method into two steps so as to update the props.family before |
| running xfrm_init_state. As the result, xfrm_state's inner mode, |
| outer mode, type and IP header length in xfrm_state_migrate can |
| be updated with the new address family. |
| |
| Tested with additions to Android's kernel unit test suite: |
| https://android-review.googlesource.com/c/kernel/tests/+/1885354 |
| |
| Signed-off-by: Yan Yan <evitayan@google.com> |
| Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| net/xfrm/xfrm_state.c | 8 +++++--- |
| 1 file changed, 5 insertions(+), 3 deletions(-) |
| |
| diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c |
| index 0fd67d1acbfb..cf147e1837a9 100644 |
| --- a/net/xfrm/xfrm_state.c |
| +++ b/net/xfrm/xfrm_state.c |
| @@ -1442,9 +1442,6 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig, |
| memcpy(&x->mark, &orig->mark, sizeof(x->mark)); |
| memcpy(&x->props.smark, &orig->props.smark, sizeof(x->props.smark)); |
| |
| - if (xfrm_init_state(x) < 0) |
| - goto error; |
| - |
| x->props.flags = orig->props.flags; |
| x->props.extra_flags = orig->props.extra_flags; |
| |
| @@ -1528,6 +1525,11 @@ struct xfrm_state *xfrm_state_migrate(struct xfrm_state *x, |
| if (!xc) |
| return NULL; |
| |
| + xc->props.family = m->new_family; |
| + |
| + if (xfrm_init_state(xc) < 0) |
| + goto error; |
| + |
| memcpy(&xc->id.daddr, &m->new_daddr, sizeof(xc->id.daddr)); |
| memcpy(&xc->props.saddr, &m->new_saddr, sizeof(xc->props.saddr)); |
| |
| -- |
| 2.34.1 |
| |