diff options
author | Niel Fourie <lusus@denx.de> | 2022-02-11 14:45:18 +0100 |
---|---|---|
committer | Daniel Wagner <wagi@monom.org> | 2022-02-21 09:22:08 +0100 |
commit | 481d08f108fed108a6174ad00ef73393edd99139 (patch) | |
tree | 9a4dc8c2853cd4aa47baeb35873717022f1724da | |
parent | 4a27c58ad8b1afd980ebe122ca178c7f659c025e (diff) | |
download | connman-481d08f108fed108a6174ad00ef73393edd99139.tar.gz |
wifi: Duplicate GSupplicantSSID pointer members
In ssid_init(), the pointer members of GSupplicantSSID *ssid was
initialised to point to members of a connman_network, which get
freed and replaced, causing ssid's pointers to point to freed heap
memory. To mitigate this, these members are duplicated and then
freed and along with ssid when no longer needed.
-rw-r--r-- | gsupplicant/supplicant.c | 42 | ||||
-rw-r--r-- | plugins/wifi.c | 80 |
2 files changed, 83 insertions, 39 deletions
diff --git a/gsupplicant/supplicant.c b/gsupplicant/supplicant.c index 470d99eb..1b92ec44 100644 --- a/gsupplicant/supplicant.c +++ b/gsupplicant/supplicant.c @@ -810,6 +810,33 @@ static void remove_peer(gpointer data) g_free(peer); } +static void remove_ssid(gpointer data) +{ + GSupplicantSSID *ssid = data; + + if (!ssid) + return; + + g_free((void *) ssid->ssid); + g_free((char *) ssid->eap); + g_free((char *) ssid->passphrase); + g_free((char *) ssid->identity); + g_free((char *) ssid->anonymous_identity); + g_free((char *) ssid->ca_cert_path); + g_free((char *) ssid->subject_match); + g_free((char *) ssid->altsubject_match); + g_free((char *) ssid->domain_suffix_match); + g_free((char *) ssid->domain_match); + g_free((char *) ssid->client_cert_path); + g_free((char *) ssid->private_key_path); + g_free((char *) ssid->private_key_passphrase); + g_free((char *) ssid->phase2_auth); + g_free((char *) ssid->pin_wps); + g_free((char *) ssid->bgscan); + + g_free(ssid); +} + static void debug_strvalmap(const char *label, struct strvalmap *map, unsigned int val) { @@ -4151,6 +4178,7 @@ done: if (data->callback) data->callback(err, NULL, data->user_data); + remove_ssid(data->ssid); dbus_free(data); } @@ -4469,7 +4497,7 @@ static void interface_select_network_result(const char *error, if (data->callback) data->callback(err, data->interface, data->user_data); - g_free(data->ssid); + remove_ssid(data->ssid); dbus_free(data); } @@ -4525,7 +4553,7 @@ error: } g_free(data->path); - g_free(data->ssid); + remove_ssid(data->ssid); g_free(data); } @@ -5030,7 +5058,7 @@ static void interface_wps_start_result(const char *error, data->callback(err, data->interface, data->user_data); g_free(data->path); - g_free(data->ssid); + remove_ssid(data->ssid); dbus_free(data); } @@ -5070,7 +5098,7 @@ static void wps_start(const char *error, DBusMessageIter *iter, void *user_data) if (error) { SUPPLICANT_DBG("error: %s", error); g_free(data->path); - g_free(data->ssid); + remove_ssid(data->ssid); dbus_free(data); return; } @@ -5159,6 +5187,7 @@ int g_supplicant_interface_connect(GSupplicantInterface *interface, * type is 802.11x). */ if (compare_network_parameters(interface, ssid)) { + remove_ssid(ssid); return -EALREADY; } @@ -5184,6 +5213,7 @@ int g_supplicant_interface_connect(GSupplicantInterface *interface, if (ret < 0) { g_free(data->path); + remove_ssid(data->ssid); dbus_free(data); return ret; } @@ -5234,6 +5264,7 @@ static void network_remove_result(const char *error, } else { if (data->callback) data->callback(result, data->interface, data->user_data); + remove_ssid(data->ssid); } g_free(data->path); dbus_free(data); @@ -5287,6 +5318,7 @@ static void interface_disconnect_result(const char *error, data->user_data); g_free(data->path); + remove_ssid(data->ssid); dbus_free(data); return; } @@ -5299,10 +5331,12 @@ static void interface_disconnect_result(const char *error, if (result != -ECONNABORTED) { if (network_remove(data) < 0) { g_free(data->path); + remove_ssid(data->ssid); dbus_free(data); } } else { g_free(data->path); + remove_ssid(data->ssid); dbus_free(data); } } diff --git a/plugins/wifi.c b/plugins/wifi.c index e947b169..2a933708 100644 --- a/plugins/wifi.c +++ b/plugins/wifi.c @@ -2163,21 +2163,29 @@ static GSupplicantSecurity network_security(const char *security) static void ssid_init(GSupplicantSSID *ssid, struct connman_network *network) { struct wifi_network *network_data = connman_network_get_data(network); + const char *ssid_blob; const char *security; memset(ssid, 0, sizeof(*ssid)); ssid->mode = G_SUPPLICANT_MODE_INFRA; - ssid->ssid = connman_network_get_blob(network, "WiFi.SSID", - &ssid->ssid_len); + ssid->ssid_len = 0; + ssid_blob = + connman_network_get_blob(network, "WiFi.SSID", &ssid->ssid_len); + ssid->ssid = g_try_malloc(ssid->ssid_len); + if (ssid->ssid) + memcpy((void *)ssid->ssid, ssid_blob, ssid->ssid_len); + else + ssid->ssid_len = 0; + ssid->scan_ssid = 1; security = connman_network_get_string(network, "WiFi.Security"); ssid->security = network_security(security); ssid->keymgmt = network_data->keymgmt; ssid->ieee80211w = G_SUPPLICANT_MFP_OPTIONAL; - ssid->passphrase = connman_network_get_string(network, - "WiFi.Passphrase"); + ssid->passphrase = g_strdup( + connman_network_get_string(network, "WiFi.Passphrase")); - ssid->eap = connman_network_get_string(network, "WiFi.EAP"); + ssid->eap = g_strdup(connman_network_get_string(network, "WiFi.EAP")); /* * If our private key password is unset, @@ -2186,42 +2194,44 @@ static void ssid_init(GSupplicantSSID *ssid, struct connman_network *network) * cert may have to be provided. */ if (!connman_network_get_string(network, "WiFi.PrivateKeyPassphrase")) - connman_network_set_string(network, - "WiFi.PrivateKeyPassphrase", - ssid->passphrase); + connman_network_set_string(network, "WiFi.PrivateKeyPassphrase", + ssid->passphrase); /* We must have an identity for both PEAP and TLS */ - ssid->identity = connman_network_get_string(network, "WiFi.Identity"); + ssid->identity = + g_strdup(connman_network_get_string(network, "WiFi.Identity")); /* Use agent provided identity as a fallback */ if (!ssid->identity || strlen(ssid->identity) == 0) - ssid->identity = connman_network_get_string(network, - "WiFi.AgentIdentity"); - - ssid->anonymous_identity = connman_network_get_string(network, - "WiFi.AnonymousIdentity"); - ssid->ca_cert_path = connman_network_get_string(network, - "WiFi.CACertFile"); - ssid->subject_match = connman_network_get_string(network, - "WiFi.SubjectMatch"); - ssid->altsubject_match = connman_network_get_string(network, - "WiFi.AltSubjectMatch"); - ssid->domain_suffix_match = connman_network_get_string(network, - "WiFi.DomainSuffixMatch"); - ssid->domain_match = connman_network_get_string(network, - "WiFi.DomainMatch"); - ssid->client_cert_path = connman_network_get_string(network, - "WiFi.ClientCertFile"); - ssid->private_key_path = connman_network_get_string(network, - "WiFi.PrivateKeyFile"); - ssid->private_key_passphrase = connman_network_get_string(network, - "WiFi.PrivateKeyPassphrase"); - ssid->phase2_auth = connman_network_get_string(network, "WiFi.Phase2"); + ssid->identity = g_strdup(connman_network_get_string( + network, "WiFi.AgentIdentity")); + + ssid->anonymous_identity = g_strdup( + connman_network_get_string(network, "WiFi.AnonymousIdentity")); + ssid->ca_cert_path = g_strdup( + connman_network_get_string(network, "WiFi.CACertFile")); + ssid->subject_match = g_strdup( + connman_network_get_string(network, "WiFi.SubjectMatch")); + ssid->altsubject_match = g_strdup( + connman_network_get_string(network, "WiFi.AltSubjectMatch")); + ssid->domain_suffix_match = g_strdup( + connman_network_get_string(network, "WiFi.DomainSuffixMatch")); + ssid->domain_match = g_strdup( + connman_network_get_string(network, "WiFi.DomainMatch")); + ssid->client_cert_path = g_strdup( + connman_network_get_string(network, "WiFi.ClientCertFile")); + ssid->private_key_path = g_strdup( + connman_network_get_string(network, "WiFi.PrivateKeyFile")); + ssid->private_key_passphrase = g_strdup(connman_network_get_string( + network, "WiFi.PrivateKeyPassphrase")); + ssid->phase2_auth = + g_strdup(connman_network_get_string(network, "WiFi.Phase2")); ssid->use_wps = connman_network_get_bool(network, "WiFi.UseWPS"); - ssid->pin_wps = connman_network_get_string(network, "WiFi.PinWPS"); + ssid->pin_wps = + g_strdup(connman_network_get_string(network, "WiFi.PinWPS")); if (connman_setting_get_bool("BackgroundScanning")) - ssid->bgscan = BGSCAN_DEFAULT; + ssid->bgscan = g_strdup(BGSCAN_DEFAULT); } static int network_connect(struct connman_network *network) @@ -2246,12 +2256,12 @@ static int network_connect(struct connman_network *network) interface = wifi->interface; - ssid_init(ssid, network); - if (wifi->disconnecting) { wifi->pending_network = network; g_free(ssid); } else { + ssid_init(ssid, network); + wifi->network = connman_network_ref(network); wifi->retries = 0; |