diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 05521fb53..74f576290 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -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, struct nl_handle *nl_handle, struct nl_msg *msg, int (*valid_handler)(struct nl_msg *, void *), @@ -320,6 +336,8 @@ static int send_and_recv(struct nl80211_global *global, } out: nl_cb_put(cb); + if (!valid_handler && valid_data == (void *) -1) + nl80211_nlmsg_clear(msg); nlmsg_free(msg); 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, QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY) || nla_put(msg, NL80211_ATTR_VENDOR_DATA, key_len, key)) { + nl80211_nlmsg_clear(msg); nlmsg_free(msg); return -1; } - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, (void *) -1); if (ret) { wpa_printf(MSG_DEBUG, "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)) 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) ret = 0; if (ret) @@ -2477,6 +2496,7 @@ static int wpa_driver_nl80211_set_key(const char *ifname, struct i802_bss *bss, return ret; fail: + nl80211_nlmsg_clear(msg); nlmsg_free(msg); 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_REPLAY_CTR, NL80211_REPLAY_CTR_LEN, replay_ctr)) { + nl80211_nlmsg_clear(msg); nlmsg_free(msg); return; } nla_nest_end(msg, replay_nested); - send_and_recv_msgs(drv, msg, NULL, NULL); + send_and_recv_msgs(drv, msg, NULL, (void *) -1); }