Skip to content

Commit

Permalink
nl80211: add a few extended error strings to key parsing
Browse files Browse the repository at this point in the history
This mostly serves as an example for how to add error strings
and erroneous attribute pointers.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
  • Loading branch information
Johannes Berg committed Dec 11, 2017
1 parent 6c2fb1e commit 768075e
Showing 1 changed file with 41 additions and 20 deletions.
61 changes: 41 additions & 20 deletions net/wireless/nl80211.c
Original file line number Diff line number Diff line change
Expand Up @@ -734,11 +734,12 @@ struct key_parse {
bool def_uni, def_multi;
};

static int nl80211_parse_key_new(struct nlattr *key, struct key_parse *k)
static int nl80211_parse_key_new(struct genl_info *info, struct nlattr *key,
struct key_parse *k)
{
struct nlattr *tb[NL80211_KEY_MAX + 1];
int err = nla_parse_nested(tb, NL80211_KEY_MAX, key,
nl80211_key_policy, NULL);
nl80211_key_policy, info->extack);
if (err)
return err;

Expand Down Expand Up @@ -771,15 +772,17 @@ static int nl80211_parse_key_new(struct nlattr *key, struct key_parse *k)
if (tb[NL80211_KEY_TYPE]) {
k->type = nla_get_u32(tb[NL80211_KEY_TYPE]);
if (k->type < 0 || k->type >= NUM_NL80211_KEYTYPES)
return -EINVAL;
return genl_err_attr(info, -EINVAL,
tb[NL80211_KEY_TYPE]);
}

if (tb[NL80211_KEY_DEFAULT_TYPES]) {
struct nlattr *kdt[NUM_NL80211_KEY_DEFAULT_TYPES];

err = nla_parse_nested(kdt, NUM_NL80211_KEY_DEFAULT_TYPES - 1,
tb[NL80211_KEY_DEFAULT_TYPES],
nl80211_key_default_policy, NULL);
nl80211_key_default_policy,
info->extack);
if (err)
return err;

Expand Down Expand Up @@ -820,8 +823,10 @@ static int nl80211_parse_key_old(struct genl_info *info, struct key_parse *k)

if (info->attrs[NL80211_ATTR_KEY_TYPE]) {
k->type = nla_get_u32(info->attrs[NL80211_ATTR_KEY_TYPE]);
if (k->type < 0 || k->type >= NUM_NL80211_KEYTYPES)
if (k->type < 0 || k->type >= NUM_NL80211_KEYTYPES) {
GENL_SET_ERR_MSG(info, "key type out of range");
return -EINVAL;
}
}

if (info->attrs[NL80211_ATTR_KEY_DEFAULT_TYPES]) {
Expand Down Expand Up @@ -850,31 +855,42 @@ static int nl80211_parse_key(struct genl_info *info, struct key_parse *k)
k->type = -1;

if (info->attrs[NL80211_ATTR_KEY])
err = nl80211_parse_key_new(info->attrs[NL80211_ATTR_KEY], k);
err = nl80211_parse_key_new(info, info->attrs[NL80211_ATTR_KEY], k);
else
err = nl80211_parse_key_old(info, k);

if (err)
return err;

if (k->def && k->defmgmt)
if (k->def && k->defmgmt) {
GENL_SET_ERR_MSG(info, "key with def && defmgmt is invalid");
return -EINVAL;
}

if (k->defmgmt) {
if (k->def_uni || !k->def_multi)
if (k->def_uni || !k->def_multi) {
GENL_SET_ERR_MSG(info, "defmgmt key must be mcast");
return -EINVAL;
}
}

if (k->idx != -1) {
if (k->defmgmt) {
if (k->idx < 4 || k->idx > 5)
if (k->idx < 4 || k->idx > 5) {
GENL_SET_ERR_MSG(info,
"defmgmt key idx not 4 or 5");
return -EINVAL;
}
} else if (k->def) {
if (k->idx < 0 || k->idx > 3)
if (k->idx < 0 || k->idx > 3) {
GENL_SET_ERR_MSG(info, "def key idx not 0-3");
return -EINVAL;
}
} else {
if (k->idx < 0 || k->idx > 5)
if (k->idx < 0 || k->idx > 5) {
GENL_SET_ERR_MSG(info, "key idx not 0-5");
return -EINVAL;
}
}
}

Expand All @@ -883,8 +899,9 @@ static int nl80211_parse_key(struct genl_info *info, struct key_parse *k)

static struct cfg80211_cached_keys *
nl80211_parse_connkeys(struct cfg80211_registered_device *rdev,
struct nlattr *keys, bool *no_ht)
struct genl_info *info, bool *no_ht)
{
struct nlattr *keys = info->attrs[NL80211_ATTR_KEYS];
struct key_parse parse;
struct nlattr *key;
struct cfg80211_cached_keys *result;
Expand All @@ -909,17 +926,22 @@ nl80211_parse_connkeys(struct cfg80211_registered_device *rdev,
memset(&parse, 0, sizeof(parse));
parse.idx = -1;

err = nl80211_parse_key_new(key, &parse);
err = nl80211_parse_key_new(info, key, &parse);
if (err)
goto error;
err = -EINVAL;
if (!parse.p.key)
goto error;
if (parse.idx < 0 || parse.idx > 3)
if (parse.idx < 0 || parse.idx > 3) {
GENL_SET_ERR_MSG(info, "key index out of range [0-3]");
goto error;
}
if (parse.def) {
if (def)
if (def) {
GENL_SET_ERR_MSG(info,
"only one key can be default");
goto error;
}
def = 1;
result->def = parse.idx;
if (!parse.def_uni || !parse.def_multi)
Expand All @@ -932,6 +954,7 @@ nl80211_parse_connkeys(struct cfg80211_registered_device *rdev,
goto error;
if (parse.p.cipher != WLAN_CIPHER_SUITE_WEP40 &&
parse.p.cipher != WLAN_CIPHER_SUITE_WEP104) {
GENL_SET_ERR_MSG(info, "connect key must be WEP");
err = -EINVAL;
goto error;
}
Expand All @@ -947,6 +970,7 @@ nl80211_parse_connkeys(struct cfg80211_registered_device *rdev,

if (result->def < 0) {
err = -EINVAL;
GENL_SET_ERR_MSG(info, "need a default/TX key");
goto error;
}

Expand Down Expand Up @@ -8611,9 +8635,7 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
if (ibss.privacy && info->attrs[NL80211_ATTR_KEYS]) {
bool no_ht = false;

connkeys = nl80211_parse_connkeys(rdev,
info->attrs[NL80211_ATTR_KEYS],
&no_ht);
connkeys = nl80211_parse_connkeys(rdev, info, &no_ht);
if (IS_ERR(connkeys))
return PTR_ERR(connkeys);

Expand Down Expand Up @@ -9017,8 +9039,7 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
}

if (connect.privacy && info->attrs[NL80211_ATTR_KEYS]) {
connkeys = nl80211_parse_connkeys(rdev,
info->attrs[NL80211_ATTR_KEYS], NULL);
connkeys = nl80211_parse_connkeys(rdev, info, NULL);
if (IS_ERR(connkeys))
return PTR_ERR(connkeys);
}
Expand Down

0 comments on commit 768075e

Please sign in to comment.