| From 7c76ecd9c99b6e9a771d813ab1aa7fa428b3ade1 Mon Sep 17 00:00:00 2001 |
| From: Leon Romanovsky <leonro@nvidia.com> |
| Date: Tue, 8 Feb 2022 16:14:32 +0200 |
| Subject: xfrm: enforce validity of offload input flags |
| |
| From: Leon Romanovsky <leonro@nvidia.com> |
| |
| commit 7c76ecd9c99b6e9a771d813ab1aa7fa428b3ade1 upstream. |
| |
| struct xfrm_user_offload has flags variable that received user input, |
| but kernel didn't check if valid bits were provided. It caused a situation |
| where not sanitized input was forwarded directly to the drivers. |
| |
| For example, XFRM_OFFLOAD_IPV6 define that was exposed, was used by |
| strongswan, but not implemented in the kernel at all. |
| |
| As a solution, check and sanitize input flags to forward |
| XFRM_OFFLOAD_INBOUND to the drivers. |
| |
| Fixes: d77e38e612a0 ("xfrm: Add an IPsec hardware offloading API") |
| Signed-off-by: Leon Romanovsky <leonro@nvidia.com> |
| Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| include/uapi/linux/xfrm.h | 6 ++++++ |
| net/xfrm/xfrm_device.c | 6 +++++- |
| 2 files changed, 11 insertions(+), 1 deletion(-) |
| |
| --- a/include/uapi/linux/xfrm.h |
| +++ b/include/uapi/linux/xfrm.h |
| @@ -504,6 +504,12 @@ struct xfrm_user_offload { |
| int ifindex; |
| __u8 flags; |
| }; |
| +/* This flag was exposed without any kernel code that supporting it. |
| + * Unfortunately, strongswan has the code that uses sets this flag, |
| + * which makes impossible to reuse this bit. |
| + * |
| + * So leave it here to make sure that it won't be reused by mistake. |
| + */ |
| #define XFRM_OFFLOAD_IPV6 1 |
| #define XFRM_OFFLOAD_INBOUND 2 |
| |
| --- a/net/xfrm/xfrm_device.c |
| +++ b/net/xfrm/xfrm_device.c |
| @@ -206,6 +206,9 @@ int xfrm_dev_state_add(struct net *net, |
| if (x->encap || x->tfcpad) |
| return -EINVAL; |
| |
| + if (xuo->flags & ~(XFRM_OFFLOAD_IPV6 | XFRM_OFFLOAD_INBOUND)) |
| + return -EINVAL; |
| + |
| dev = dev_get_by_index(net, xuo->ifindex); |
| if (!dev) { |
| if (!(xuo->flags & XFRM_OFFLOAD_INBOUND)) { |
| @@ -243,7 +246,8 @@ int xfrm_dev_state_add(struct net *net, |
| |
| xso->dev = dev; |
| xso->num_exthdrs = 1; |
| - xso->flags = xuo->flags; |
| + /* Don't forward bit that is not implemented */ |
| + xso->flags = xuo->flags & ~XFRM_OFFLOAD_IPV6; |
| |
| err = dev->xfrmdev_ops->xdo_dev_state_add(x); |
| if (err) { |