enic: Validate length of nl attributes in enic_set_vf_port
Subsystems (3)
A message that is not in the archive (sent off-list or not yet received): [email protected]
PATCH 1/1 enic: Validate length of nl attributes in enic_set_vf_port
enic_set_vf_port assumes that the nl attribute IFLA_PORT_PROFILE is of length PORT_PROFILE_MAX and that the nl attributes IFLA_PORT_INSTANCE_UUID, IFLA_PORT_HOST_UUID are of length PORT_UUID_MAX. These attributes are validated (in the function do_setlink in rtnetlink.c) using the nla_policy ifla_port_policy. The policy defines IFLA_PORT_PROFILE as NLA_STRING, IFLA_PORT_INSTANCE_UUID as NLA_BINARY and IFLA_PORT_HOST_UUID as NLA_STRING. That means that the length validation using the policy is for the max size of the attributes and not on exact size so the length of these attributes might be less than the sizes that enic_set_vf_port expects. This might cause an out of bands
read access in the memcpys of the data of these
attributes in enic_set_vf_port.
--- drivers/net/ethernet/cisco/enic/enic_main.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
drivers/net/ethernet/cisco/enic/enic_main.c +12 -0
@@ -1117,18 +1117,30 @@ static int enic_set_vf_port(struct net_device *netdev, int vf, pp->request =nla_get_u8 (port[IFLA_PORT_REQUEST ]);if (port[IFLA_PORT_PROFILE ]) { +if (nla_len (port[IFLA_PORT_PROFILE ]) !=PORT_PROFILE_MAX ) { +memcpy (pp, &prev_pp,sizeof (*pp)); +return -EOPNOTSUPP ; + } pp->set |=ENIC_SET_NAME ;memcpy (pp->name,nla_data (port[IFLA_PORT_PROFILE ]),PORT_PROFILE_MAX ); }if (port[IFLA_PORT_INSTANCE_UUID ]) { +if (nla_len (port[IFLA_PORT_INSTANCE_UUID ]) !=PORT_UUID_MAX ) { +memcpy (pp, &prev_pp,sizeof (*pp)); +return -EOPNOTSUPP ; + } pp->set |=ENIC_SET_INSTANCE ;memcpy (pp->instance_uuid,nla_data (port[IFLA_PORT_INSTANCE_UUID ]),PORT_UUID_MAX ); }if (port[IFLA_PORT_HOST_UUID ]) { +if (nla_len (port[IFLA_PORT_HOST_UUID ]) !=PORT_UUID_MAX ) { +memcpy (pp, &prev_pp,sizeof (*pp)); +return -EOPNOTSUPP ; + } pp->set |=ENIC_SET_HOST ;memcpy (pp->host_uuid,nla_data (port[IFLA_PORT_HOST_UUID ]),PORT_UUID_MAX );
Signature · 1 line
2.39.3 (Apple Git-146)
Paolo Abeni
maintainerQuoted 24 lines · Roded Zats
enic_set_vf_portassumes that the nl attributeIFLA_PORT_PROFILEis of lengthPORT_PROFILE_MAXand that the nl attributesIFLA_PORT_INSTANCE_UUID,IFLA_PORT_HOST_UUIDare of lengthPORT_UUID_MAX. These attributes are validated (in the functiondo_setlinkinrtnetlink.c) using thenla_policyifla_port_policy. The policy definesIFLA_PORT_PROFILEasNLA_STRING,IFLA_PORT_INSTANCE_UUIDasNLA_BINARYandIFLA_PORT_HOST_UUIDasNLA_STRING. That means that the length validation using the policy is for the max size of the attributes and not on exact size so the length of these attributes might be less than the sizes thatenic_set_vf_portexpects. This might cause an out of bands
read access in the memcpys of the data of these
attributes inenic_set_vf_port.Fixes f8bd909183ac ("net: Add ndo_{set|get}_vf_port support for enic dynamic vnics")Signed-off-by Roded Zats <[email protected]>--- drivers/net/ethernet/cisco/enic/enic_main.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)drivers/net/ethernet/cisco/enic/enic_main.c +0
-0
drivers/net/ethernet/cisco/enic/enic_main.c static int enic_set_vf_port(struct net_device *netdev, int vf, · line 1122
Quoted 6 lines
drivers/net/ethernet/cisco/enic/enic_main.c +3
-0@@ -1117,18 +1117,30 @@ static int enic_set_vf_port(struct net_device *netdev, int vf, pp->request =nla_get_u8 (port[IFLA_PORT_REQUEST ]);if (port[IFLA_PORT_PROFILE ]) { +if (nla_len (port[IFLA_PORT_PROFILE ]) !=PORT_PROFILE_MAX ) { +memcpy (pp, &prev_pp,sizeof (*pp)); +return -EOPNOTSUPP ;
I think -EOPNOTSUPP is misleading here (and below), -EINVAL should be appropriate.
Thanks,
Paolo
PATCH v2 1/1 enic: Validate length of nl attributes in enic_set_vf_port
enic_set_vf_port assumes that the nl attribute IFLA_PORT_PROFILE is of length PORT_PROFILE_MAX and that the nl attributes IFLA_PORT_INSTANCE_UUID, IFLA_PORT_HOST_UUID are of length PORT_UUID_MAX. These attributes are validated (in the function do_setlink in rtnetlink.c) using the nla_policy ifla_port_policy. The policy defines IFLA_PORT_PROFILE as NLA_STRING, IFLA_PORT_INSTANCE_UUID as NLA_BINARY and IFLA_PORT_HOST_UUID as NLA_STRING. That means that the length validation using the policy is for the max size of the attributes and not on exact size so the length of these attributes might be less than the sizes that enic_set_vf_port expects. This might cause an out of bands
read access in the memcpys of the data of these
attributes in enic_set_vf_port.
--- drivers/net/ethernet/cisco/enic/enic_main.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
drivers/net/ethernet/cisco/enic/enic_main.c +12 -0
@@ -1117,18 +1117,30 @@ static int enic_set_vf_port(struct net_device *netdev, int vf, pp->request =nla_get_u8 (port[IFLA_PORT_REQUEST ]);if (port[IFLA_PORT_PROFILE ]) { +if (nla_len (port[IFLA_PORT_PROFILE ]) !=PORT_PROFILE_MAX ) { +memcpy (pp, &prev_pp,sizeof (*pp)); +return -EINVAL ; + } pp->set |=ENIC_SET_NAME ;memcpy (pp->name,nla_data (port[IFLA_PORT_PROFILE ]),PORT_PROFILE_MAX ); }if (port[IFLA_PORT_INSTANCE_UUID ]) { +if (nla_len (port[IFLA_PORT_INSTANCE_UUID ]) !=PORT_UUID_MAX ) { +memcpy (pp, &prev_pp,sizeof (*pp)); +return -EINVAL ; + } pp->set |=ENIC_SET_INSTANCE ;memcpy (pp->instance_uuid,nla_data (port[IFLA_PORT_INSTANCE_UUID ]),PORT_UUID_MAX ); }if (port[IFLA_PORT_HOST_UUID ]) { +if (nla_len (port[IFLA_PORT_HOST_UUID ]) !=PORT_UUID_MAX ) { +memcpy (pp, &prev_pp,sizeof (*pp)); +return -EINVAL ; + } pp->set |=ENIC_SET_HOST ;memcpy (pp->host_uuid,nla_data (port[IFLA_PORT_HOST_UUID ]),PORT_UUID_MAX );
Signature · 1 line
2.39.3 (Apple Git-146)
This patch was applied to netdev/net.git (main) by Paolo Abeni <[email protected]>:
Hello:
This patch was applied to netdev/net.git (main)
by Paolo Abeni <[email protected]>:
Quoted 13 lines · On Wed, 22 May 2024 10:30:44 +0300 you wrote:
enic_set_vf_portassumes that the nl attributeIFLA_PORT_PROFILEis of lengthPORT_PROFILE_MAXand that the nl attributesIFLA_PORT_INSTANCE_UUID,IFLA_PORT_HOST_UUIDare of lengthPORT_UUID_MAX. These attributes are validated (in the functiondo_setlinkinrtnetlink.c) using thenla_policyifla_port_policy. The policy definesIFLA_PORT_PROFILEasNLA_STRING,IFLA_PORT_INSTANCE_UUIDasNLA_BINARYandIFLA_PORT_HOST_UUIDasNLA_STRING. That means that the length validation using the policy is for the max size of the attributes and not on exact size so the length of these attributes might be less than the sizes thatenic_set_vf_portexpects. This might cause an out of bands
read access in the memcpys of the data of these
attributes inenic_set_vf_port.
Quoted 1 line
[...]
Here is the summary with links:
- [net,v2] enic: Validate length of nl attributes in enic_set_vf_port
https://git.kernel.org/netdev/net/c/e8021b94b041
You are awesome, thank you!
Signature · 2 lines
Deet-doot-dot, I am a bot. https://korg.docs.kernel.org/patchwork/pwbot.html
Quoted 24 lines · On Wed, 22 May 2024 10:30:44 +0300 Roded Zats <[email protected]>…
enic_set_vf_portassumes that the nl attributeIFLA_PORT_PROFILEis of lengthPORT_PROFILE_MAXand that the nl attributesIFLA_PORT_INSTANCE_UUID,IFLA_PORT_HOST_UUIDare of lengthPORT_UUID_MAX. These attributes are validated (in the functiondo_setlinkinrtnetlink.c) using thenla_policyifla_port_policy. The policy definesIFLA_PORT_PROFILEasNLA_STRING,IFLA_PORT_INSTANCE_UUIDasNLA_BINARYandIFLA_PORT_HOST_UUIDasNLA_STRING. That means that the length validation using the policy is for the max size of the attributes and not on exact size so the length of these attributes might be less than the sizes thatenic_set_vf_portexpects. This might cause an out of bands
read access in the memcpys of the data of these
attributes inenic_set_vf_port.Fixes f8bd909183ac ("net: Add ndo_{set|get}_vf_port support for enic dynamic vnics")Signed-off-by Roded Zats <[email protected]>--- drivers/net/ethernet/cisco/enic/enic_main.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)drivers/net/ethernet/cisco/enic/enic_main.c +0
-0
drivers/net/ethernet/cisco/enic/enic_main.c static int enic_set_vf_port(struct net_device *netdev, int vf, · line 1123
Quoted 7 lines
drivers/net/ethernet/cisco/enic/enic_main.c +4
-0@@ -1117,18 +1117,30 @@ static int enic_set_vf_port(struct net_device *netdev, int vf, pp->request =nla_get_u8 (port[IFLA_PORT_REQUEST ]);if (port[IFLA_PORT_PROFILE ]) { +if (nla_len (port[IFLA_PORT_PROFILE ]) !=PORT_PROFILE_MAX ) { +memcpy (pp, &prev_pp,sizeof (*pp)); +return -EINVAL ; + }
If you have multiple error conditions with the same unwind, the common design pattern in Linux is to use a goto error at end of function.