Commit d49baa7e authored by Eric Biggers's avatar Eric Biggers Committed by David S. Miller

net/smc: check for missing nlattrs in SMC_PNETID messages

It's possible to crash the kernel in several different ways by sending
messages to the SMC_PNETID generic netlink family that are missing the
expected attributes:

- Missing SMC_PNETID_NAME => null pointer dereference when comparing
  names.
- Missing SMC_PNETID_ETHNAME => null pointer dereference accessing
  smc_pnetentry::ndev.
- Missing SMC_PNETID_IBNAME => null pointer dereference accessing
  smc_pnetentry::smcibdev.
- Missing SMC_PNETID_IBPORT => out of bounds array access to
  smc_ib_device::pattr[-1].

Fix it by validating that all expected attributes are present and that
SMC_PNETID_IBPORT is nonzero.

Reported-by: syzbot+5cd61039dc9b8bfa6e47@syzkaller.appspotmail.com
Fixes: 6812baab ("smc: establish pnet table management")
Cc: <stable@vger.kernel.org> # v4.11+
Signed-off-by: default avatarEric Biggers <ebiggers@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 57f6f99f
...@@ -245,40 +245,45 @@ static struct smc_ib_device *smc_pnet_find_ib(char *ib_name) ...@@ -245,40 +245,45 @@ static struct smc_ib_device *smc_pnet_find_ib(char *ib_name)
static int smc_pnet_fill_entry(struct net *net, struct smc_pnetentry *pnetelem, static int smc_pnet_fill_entry(struct net *net, struct smc_pnetentry *pnetelem,
struct nlattr *tb[]) struct nlattr *tb[])
{ {
char *string, *ibname = NULL; char *string, *ibname;
int rc = 0; int rc;
memset(pnetelem, 0, sizeof(*pnetelem)); memset(pnetelem, 0, sizeof(*pnetelem));
INIT_LIST_HEAD(&pnetelem->list); INIT_LIST_HEAD(&pnetelem->list);
if (tb[SMC_PNETID_NAME]) {
string = (char *)nla_data(tb[SMC_PNETID_NAME]); rc = -EINVAL;
if (!smc_pnetid_valid(string, pnetelem->pnet_name)) { if (!tb[SMC_PNETID_NAME])
rc = -EINVAL; goto error;
goto error; string = (char *)nla_data(tb[SMC_PNETID_NAME]);
} if (!smc_pnetid_valid(string, pnetelem->pnet_name))
} goto error;
if (tb[SMC_PNETID_ETHNAME]) {
string = (char *)nla_data(tb[SMC_PNETID_ETHNAME]); rc = -EINVAL;
pnetelem->ndev = dev_get_by_name(net, string); if (!tb[SMC_PNETID_ETHNAME])
if (!pnetelem->ndev) goto error;
return -ENOENT; rc = -ENOENT;
} string = (char *)nla_data(tb[SMC_PNETID_ETHNAME]);
if (tb[SMC_PNETID_IBNAME]) { pnetelem->ndev = dev_get_by_name(net, string);
ibname = (char *)nla_data(tb[SMC_PNETID_IBNAME]); if (!pnetelem->ndev)
ibname = strim(ibname); goto error;
pnetelem->smcibdev = smc_pnet_find_ib(ibname);
if (!pnetelem->smcibdev) { rc = -EINVAL;
rc = -ENOENT; if (!tb[SMC_PNETID_IBNAME])
goto error; goto error;
} rc = -ENOENT;
} ibname = (char *)nla_data(tb[SMC_PNETID_IBNAME]);
if (tb[SMC_PNETID_IBPORT]) { ibname = strim(ibname);
pnetelem->ib_port = nla_get_u8(tb[SMC_PNETID_IBPORT]); pnetelem->smcibdev = smc_pnet_find_ib(ibname);
if (pnetelem->ib_port > SMC_MAX_PORTS) { if (!pnetelem->smcibdev)
rc = -EINVAL; goto error;
goto error;
} rc = -EINVAL;
} if (!tb[SMC_PNETID_IBPORT])
goto error;
pnetelem->ib_port = nla_get_u8(tb[SMC_PNETID_IBPORT]);
if (pnetelem->ib_port < 1 || pnetelem->ib_port > SMC_MAX_PORTS)
goto error;
return 0; return 0;
error: error:
...@@ -307,6 +312,8 @@ static int smc_pnet_get(struct sk_buff *skb, struct genl_info *info) ...@@ -307,6 +312,8 @@ static int smc_pnet_get(struct sk_buff *skb, struct genl_info *info)
void *hdr; void *hdr;
int rc; int rc;
if (!info->attrs[SMC_PNETID_NAME])
return -EINVAL;
pnetelem = smc_pnet_find_pnetid( pnetelem = smc_pnet_find_pnetid(
(char *)nla_data(info->attrs[SMC_PNETID_NAME])); (char *)nla_data(info->attrs[SMC_PNETID_NAME]));
if (!pnetelem) if (!pnetelem)
...@@ -359,6 +366,8 @@ static int smc_pnet_add(struct sk_buff *skb, struct genl_info *info) ...@@ -359,6 +366,8 @@ static int smc_pnet_add(struct sk_buff *skb, struct genl_info *info)
static int smc_pnet_del(struct sk_buff *skb, struct genl_info *info) static int smc_pnet_del(struct sk_buff *skb, struct genl_info *info)
{ {
if (!info->attrs[SMC_PNETID_NAME])
return -EINVAL;
return smc_pnet_remove_by_pnetid( return smc_pnet_remove_by_pnetid(
(char *)nla_data(info->attrs[SMC_PNETID_NAME])); (char *)nla_data(info->attrs[SMC_PNETID_NAME]));
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment