#267 ✓resolved
Ian Woods

idevicerestore SIGSEGV in "restore_is_current_device" freeing restored_client_t instance

Reported by Ian Woods | May 16th, 2012 @ 10:15 AM | in 1.2.0 Release

idevicerestore crashes (in some situations) when trying to connect to a device after placing it in recovery mode when a second device is attached.

The conditions to reproduce this seem to require at least two devices attached to USB - one device as the target for idevicerestore (specified using the -i option and the devices ECID) in DFU mode, and one or more additional devices in "normal mode" that are connected but otherwise inactive.

The SIGSEGV does not always occur with this configuration, but once a configuration which causes the fault exists, the SIGSEGV occurs deterministically for that particular configuration. The order of devices as reported by idevice_get_device_list() may be important - the SIGSEGV occurs when checking the "normal mode" device before the target device has finished booting into recovery mode. The order of the USB ports the devices are attached to may also be a factor.

The SIGSEGV occurs due to some kind of data-corruption that occurs in restore_is_current_device() between opening the restored_client_t instance to the "normal" mode device and freeing it. Freeing the corrupted handle causes the SIGSEGV.

The recent patch to libusbmuxd to add a mutex to prevent simultaneous access does not seem to affect this issue.

Stepping through the code in restore_is_current_device():

restore_error = restored_client_new(device, &restored, "idevicerestore");
// This succeeds... snipping error handling code.
// POINT A

restore_error = restored_query_type(restored, &type, &version);
if ((restore_error == RESTORE_E_SUCCESS) && type && (strcmp(type, "com.apple.mobile.restored") == 0)) {
    debug("%s: Connected to %s, version %d\n", __func__, type, (int)version);
} else {
    // This branch is reached and...
    info("%s: device %s is not in restore mode\n", __func__, uuid);

    // The SIGSEGV occurs in this function
    // POINT B
    restored_client_free(restored);
    idevice_free(device);
    return 0;
}

The corruption occurs between point A and point B. For example, at POINT A the restored_client_t handle has members such that:

  • restored->parent points to the libplist client structure and seems correct
  • restored->uuid points to a string that contains the correct uuid for the device... e.g. the string contains "e3a2828ad3ed..."
  • restored->label points to a string that contains "idevicerestore" (as copied from the literal)
  • restored->info points to a structure in allocated memory region and seems correct

... but at POINT B ...

  • restored->parent still points to the libplist client structure and seems correct
  • restored->uuid points to the same string, but the first 4 bytes are corrupted. It seems the first four bytes of the string have been overwritten by a pointer to something... e.g. the string contains "[4 non-ascii bytes for the pointer]828ad3ed..."
  • restored->label points to the same string, but the first 4 bytes are corrupted. Again, the first four bytes of the string have been overwritten by a pointer to something (different from the uuid-string-corrupting-pointer)... e.g. it contains"[4 non-ascii bytes for the point]icerestore"
  • restored->info points to a location in the code area of the process, not the same location as at point A. The SIGSEGV occurs when free() is called on this (by the libplist cleanup code for this structure).

Commenting out the call to restored_client_free() prevents the SIGSEGV, but obviously leaks.

Any ideas what could be causing this?

Comments and changes to this ticket

  • Martin S.

    Martin S. May 16th, 2012 @ 02:42 PM

    • State changed from “new” to “open”
    • Tag changed from idevicerestore to corruption, crash, idevicerestore, restored, segfault
    • Assigned user set to “Martin S.”
    • Milestone set to 1.2.0 Release
    • Milestone order changed from “190961” to “0”

    Thanks for the very detailed report.

    I think this was fixed with his commit:
    http://cgit.sukimashita.com/libimobiledevice.git/commit/?id=b9620d3...

    By not initializing the info member to NULL, we were hitting a memory corruption which was leading to the crash you describe.

    Could you please verify if this fixes it for you?

  • Martin S.

    Martin S. August 24th, 2012 @ 04:16 PM

    • State changed from “open” to “resolved”

    Since there was no feedback so far and we hit the same issue I'll mark this as fixed.

    Feel free to reopen if you still notice the issue.

Please Sign in or create a free account to add a new ticket.

With your very own profile, you can contribute to projects, track your activity, watch tickets, receive and update tickets through your email and much more.

New-ticket Create new ticket

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile »

A project around supporting the iPhone in Linux.

See http://libimobiledevice.org

People watching this ticket

Pages