Message ID | 20240522073044.33519-1-rzats@paloaltonetworks.com (mailing list archive) |
---|---|
State | Accepted |
Commit | e8021b94b0412c37bcc79027c2e382086b6ce449 |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | [net,v2] enic: Validate length of nl attributes in enic_set_vf_port | expand |
Hello: This patch was applied to netdev/net.git (main) by Paolo Abeni <pabeni@redhat.com>: On Wed, 22 May 2024 10:30:44 +0300 you wrote: > 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. > > [...] 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!
On Wed, 22 May 2024 10:30:44 +0300 Roded Zats <rzats@paloaltonetworks.com> wrote: > 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. > > Fixes: f8bd909183ac ("net: Add ndo_{set|get}_vf_port support for enic dynamic vnics") > Signed-off-by: Roded Zats <rzats@paloaltonetworks.com> > --- > drivers/net/ethernet/cisco/enic/enic_main.c | 12 ++++++++++++ > 1 file changed, 12 insertions(+) > > diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c > index f604119efc80..5f26fc3ad655 100644 > --- a/drivers/net/ethernet/cisco/enic/enic_main.c > +++ b/drivers/net/ethernet/cisco/enic/enic_main.c > @@ -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.
diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c index f604119efc80..5f26fc3ad655 100644 --- a/drivers/net/ethernet/cisco/enic/enic_main.c +++ b/drivers/net/ethernet/cisco/enic/enic_main.c @@ -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);
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. Fixes: f8bd909183ac ("net: Add ndo_{set|get}_vf_port support for enic dynamic vnics") Signed-off-by: Roded Zats <rzats@paloaltonetworks.com> --- drivers/net/ethernet/cisco/enic/enic_main.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)