nl80211: Clear nlmsg payload with keys before freeing
This reduces the time possible keys could remain in heap memory. Couple of the nl80211 messages include keys (TK for normal ciphers and KCK/KEK/PMK for various offloading cases). Signed-off-by: Jouni Malinen <j@w1.fi>
This commit is contained in:
parent
f2535da879
commit
bbd89bfca0
1 changed files with 24 additions and 3 deletions
|
@ -281,6 +281,22 @@ static int no_seq_check(struct nl_msg *msg, void *arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void nl80211_nlmsg_clear(struct nl_msg *msg)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Clear nlmsg data, e.g., to make sure key material is not left in
|
||||||
|
* heap memory for unnecessarily long time.
|
||||||
|
*/
|
||||||
|
if (msg) {
|
||||||
|
struct nlmsghdr *hdr = nlmsg_hdr(msg);
|
||||||
|
void *data = nlmsg_data(hdr);
|
||||||
|
int len = nlmsg_datalen(hdr);
|
||||||
|
|
||||||
|
os_memset(data, 0, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int send_and_recv(struct nl80211_global *global,
|
static int send_and_recv(struct nl80211_global *global,
|
||||||
struct nl_handle *nl_handle, struct nl_msg *msg,
|
struct nl_handle *nl_handle, struct nl_msg *msg,
|
||||||
int (*valid_handler)(struct nl_msg *, void *),
|
int (*valid_handler)(struct nl_msg *, void *),
|
||||||
|
@ -320,6 +336,8 @@ static int send_and_recv(struct nl80211_global *global,
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
nl_cb_put(cb);
|
nl_cb_put(cb);
|
||||||
|
if (!valid_handler && valid_data == (void *) -1)
|
||||||
|
nl80211_nlmsg_clear(msg);
|
||||||
nlmsg_free(msg);
|
nlmsg_free(msg);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -2331,10 +2349,11 @@ static int issue_key_mgmt_set_key(struct wpa_driver_nl80211_data *drv,
|
||||||
nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
|
nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
|
||||||
QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY) ||
|
QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY) ||
|
||||||
nla_put(msg, NL80211_ATTR_VENDOR_DATA, key_len, key)) {
|
nla_put(msg, NL80211_ATTR_VENDOR_DATA, key_len, key)) {
|
||||||
|
nl80211_nlmsg_clear(msg);
|
||||||
nlmsg_free(msg);
|
nlmsg_free(msg);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
ret = send_and_recv_msgs(drv, msg, NULL, NULL);
|
ret = send_and_recv_msgs(drv, msg, NULL, (void *) -1);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
"nl80211: Key management set key failed: ret=%d (%s)",
|
"nl80211: Key management set key failed: ret=%d (%s)",
|
||||||
|
@ -2426,7 +2445,7 @@ static int wpa_driver_nl80211_set_key(const char *ifname, struct i802_bss *bss,
|
||||||
if (nla_put_u8(msg, NL80211_ATTR_KEY_IDX, key_idx))
|
if (nla_put_u8(msg, NL80211_ATTR_KEY_IDX, key_idx))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
ret = send_and_recv_msgs(drv, msg, NULL, NULL);
|
ret = send_and_recv_msgs(drv, msg, NULL, key ? (void *) -1 : NULL);
|
||||||
if ((ret == -ENOENT || ret == -ENOLINK) && alg == WPA_ALG_NONE)
|
if ((ret == -ENOENT || ret == -ENOLINK) && alg == WPA_ALG_NONE)
|
||||||
ret = 0;
|
ret = 0;
|
||||||
if (ret)
|
if (ret)
|
||||||
|
@ -2477,6 +2496,7 @@ static int wpa_driver_nl80211_set_key(const char *ifname, struct i802_bss *bss,
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
|
nl80211_nlmsg_clear(msg);
|
||||||
nlmsg_free(msg);
|
nlmsg_free(msg);
|
||||||
return -ENOBUFS;
|
return -ENOBUFS;
|
||||||
}
|
}
|
||||||
|
@ -6717,13 +6737,14 @@ static void nl80211_set_rekey_info(void *priv, const u8 *kek, const u8 *kck,
|
||||||
nla_put(msg, NL80211_REKEY_DATA_KCK, NL80211_KCK_LEN, kck) ||
|
nla_put(msg, NL80211_REKEY_DATA_KCK, NL80211_KCK_LEN, kck) ||
|
||||||
nla_put(msg, NL80211_REKEY_DATA_REPLAY_CTR, NL80211_REPLAY_CTR_LEN,
|
nla_put(msg, NL80211_REKEY_DATA_REPLAY_CTR, NL80211_REPLAY_CTR_LEN,
|
||||||
replay_ctr)) {
|
replay_ctr)) {
|
||||||
|
nl80211_nlmsg_clear(msg);
|
||||||
nlmsg_free(msg);
|
nlmsg_free(msg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
nla_nest_end(msg, replay_nested);
|
nla_nest_end(msg, replay_nested);
|
||||||
|
|
||||||
send_and_recv_msgs(drv, msg, NULL, NULL);
|
send_and_recv_msgs(drv, msg, NULL, (void *) -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue