network: Fix a bunch of double-frees
Missing secrets are freed by eap_send_agent_req() even in case of failure, so it was erroneous to try to free them on error. ==1048== Invalid read of size 8 ==1048== at 0x1603EC: l_queue_clear (queue.c:101) ==1048== by 0x1603B8: l_queue_destroy (queue.c:82) ==1048== by 0x135328: network_connect_8021x (network.c:943) ==1048== by 0x1354C4: network_connect (network.c:987) ==1048== by 0x178DD2: _dbus_object_tree_dispatch (dbus-service.c:1690) ==1048== by 0x16D32A: message_read_handler (dbus.c:285) ==1048== by 0x166EC3: io_callback (io.c:123) ==1048== by 0x165A1A: l_main_iterate (main.c:376) ==1048== by 0x165B58: l_main_run (main.c:423) ==1048== by 0x1102DA: main (main.c:458) ==1048== Address 0x5461850 is 0 bytes inside a block of size 24 free'd ==1048== at 0x4C2C13B: free (vg_replace_malloc.c:530) ==1048== by 0x15ED03: l_free (util.c:136) ==1048== by 0x1603C4: l_queue_destroy (queue.c:83) ==1048== by 0x134BD5: eap_secret_request_free (network.c:719) ==1048== by 0x134EF9: eap_send_agent_req (network.c:817) ==1048== by 0x1352F7: network_connect_8021x (network.c:936) ==1048== by 0x1354C4: network_connect (network.c:987) ==1048== by 0x178DD2: _dbus_object_tree_dispatch (dbus-service.c:1690) ==1048== by 0x16D32A: message_read_handler (dbus.c:285) ==1048== by 0x166EC3: io_callback (io.c:123) ==1048== by 0x165A1A: l_main_iterate (main.c:376) ==1048== by 0x165B58: l_main_run (main.c:423)
This commit is contained in:
parent
75b492eacc
commit
250568025c
47
src/eap.c
47
src/eap.c
|
@ -414,12 +414,30 @@ void eap_secret_info_free(void *data)
|
||||||
l_free(info);
|
l_free(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int eap_setting_exists(struct l_settings *settings,
|
||||||
|
const char *setting,
|
||||||
|
struct l_queue *secrets,
|
||||||
|
struct l_queue *missing)
|
||||||
|
{
|
||||||
|
if (l_settings_get_value(settings, "Security", setting))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (l_queue_find(secrets, eap_secret_info_match, setting))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (l_queue_find(missing, eap_secret_info_match, setting))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
int eap_check_settings(struct l_settings *settings, struct l_queue *secrets,
|
int eap_check_settings(struct l_settings *settings, struct l_queue *secrets,
|
||||||
const char *prefix, bool set_key_material,
|
const char *prefix, bool set_key_material,
|
||||||
struct l_queue **out_missing)
|
struct l_queue **out_missing)
|
||||||
{
|
{
|
||||||
char setting[64];
|
char setting[64];
|
||||||
const char *method_name;
|
const char *method_name;
|
||||||
|
struct l_queue *missing = NULL;
|
||||||
const struct l_queue_entry *entry;
|
const struct l_queue_entry *entry;
|
||||||
struct eap_method *method;
|
struct eap_method *method;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
@ -429,7 +447,6 @@ int eap_check_settings(struct l_settings *settings, struct l_queue *secrets,
|
||||||
|
|
||||||
if (!method_name) {
|
if (!method_name) {
|
||||||
l_error("Property %s missing", setting);
|
l_error("Property %s missing", setting);
|
||||||
|
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -443,7 +460,6 @@ int eap_check_settings(struct l_settings *settings, struct l_queue *secrets,
|
||||||
|
|
||||||
if (!entry) {
|
if (!entry) {
|
||||||
l_error("EAP method \"%s\" unsupported", method_name);
|
l_error("EAP method \"%s\" unsupported", method_name);
|
||||||
|
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -451,36 +467,37 @@ int eap_check_settings(struct l_settings *settings, struct l_queue *secrets,
|
||||||
if (set_key_material && !method->exports_msk) {
|
if (set_key_material && !method->exports_msk) {
|
||||||
l_error("EAP method \"%s\" doesn't export key material",
|
l_error("EAP method \"%s\" doesn't export key material",
|
||||||
method_name);
|
method_name);
|
||||||
|
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (method->check_settings)
|
if (method->check_settings)
|
||||||
ret = method->check_settings(settings, secrets,
|
ret = method->check_settings(settings, secrets,
|
||||||
prefix, out_missing);
|
prefix, &missing);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
goto error;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Methods that provide the get_identity callback are responsible
|
* Methods that provide the get_identity callback are responsible
|
||||||
* for ensuring, inside check_settings(), that they have enough data
|
* for ensuring, inside check_settings(), that they have enough data
|
||||||
* to return the identity after load_settings().
|
* to return the identity after load_settings().
|
||||||
*/
|
*/
|
||||||
if (method->get_identity)
|
if (!method->get_identity) {
|
||||||
return 0;
|
|
||||||
|
|
||||||
snprintf(setting, sizeof(setting), "%sIdentity", prefix);
|
snprintf(setting, sizeof(setting), "%sIdentity", prefix);
|
||||||
if (!l_settings_get_value(settings, "Security", setting) &&
|
|
||||||
!l_queue_find(secrets, eap_secret_info_match,
|
|
||||||
setting) &&
|
|
||||||
!l_queue_find(*out_missing, eap_secret_info_match,
|
|
||||||
setting)) {
|
|
||||||
l_error("Property %s is missing", setting);
|
|
||||||
|
|
||||||
return -ENOENT;
|
ret = eap_setting_exists(settings, setting, secrets, missing);
|
||||||
|
if (ret < 0) {
|
||||||
|
l_error("Property %s is missing", setting);
|
||||||
|
ret = -ENOENT;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*out_missing = missing;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
error:
|
||||||
|
l_queue_destroy(missing, eap_secret_info_free);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool eap_load_settings(struct eap_state *eap, struct l_settings *settings,
|
bool eap_load_settings(struct eap_state *eap, struct l_settings *settings,
|
||||||
|
|
|
@ -940,8 +940,6 @@ static struct l_dbus_message *network_connect_8021x(struct network *network,
|
||||||
reply = dbus_error_no_agent(message);
|
reply = dbus_error_no_agent(message);
|
||||||
|
|
||||||
error:
|
error:
|
||||||
l_queue_destroy(missing_secrets, eap_secret_info_free);
|
|
||||||
|
|
||||||
network_settings_close(network);
|
network_settings_close(network);
|
||||||
|
|
||||||
l_queue_destroy(network->secrets, eap_secret_info_free);
|
l_queue_destroy(network->secrets, eap_secret_info_free);
|
||||||
|
|
Loading…
Reference in New Issue