Rooting the Toshiba Thrive

... because Toshiba is a horrible system administrator

I recently acquired a tablet computer running the Android operating system. It's a model called "Thrive" made by the company "Toshiba".

The device itself is nice, and Android has a very polished-looking user interface. I was a happy consumer, using apps from the Android Market to generate data on the system assuming that the data was being backed up to the "Google Cloud" since I had checked a box to that affect during initial setup.

My happiness went on for several months until the system suddenly started prompting me for a password at boot-up. This was unexpected as no password had ever been set for the system. Puzzled I called the manufacturer (Toshiba)'s technical support. They respond that the only way to resolve the issue is to reset the system to its factory default settings which will lose all my data.

Not wanting to lose my data, and not having a lot of time to look into the issue I put the device away for a while. I eventually give in and do a factory default reset -- I'm not in a WiFi area so I don't get my data back from the "Google Cloud" -- oops!

I chalk it up to chance and recreate the data I lost as much as possible and as best as possible. I enable "USB Debugging" so I can interface with the system the next time it happens.

A few weeks later, I power the system down forcefully due to an issue and it refuses to boot back up.

Fortunately "USB Debugging" is enabled so I can login to the system over USB and look at the system and fix the issue.

I found the issue fairly quickly -- "/data" is mounted read-only due to a corrupted EXT4 journal. The "/data" filesystem needs to be checked with "fsck". This is an easy enough procedure, however there are a few problems:

  1. I am not root; and
  2. There is no "fsck" on the system

This makes me mad. I am faced with the possibility of losing data because the GUI won't start because "/data" is mounted read-only due to something as simple as not being able to perform a filesystem check (fsck). I call the manufacturer (Toshiba) and they are complete failures with regards to performing administrative operations on the system that they support (I say they support it because they have locked me out of the system so that it is impossible for me to support it). They promise to call be back in "3 to 5 business day". They never do.

Eventually I give up on that dream and wipe my data again, this time in a WiFi area so I can restore from the "Google Cloud". I then find out the "Google Cloud" only keeps a very tiny amount of my data backed up. Awesome.

I look into the issue some more and discover that there is in fact no way for me to back the system up (since I do not have administrative access to it, and there's no pre-installed services for it). Fail.

Since Toshiba has failed to support the system as the defacto system administrator I decide to fire them and take control of the system myself.

Since I upgraded the system to the latest supported operating system and bootloader when it came out the "fastboot" option was removed from the bootloader so I had no easy way to boot off of a custom kernel and initramfs/initrd and add a "su" to the system.

So I went looking around the Internet and discovered someone had found an exploit related to the GPS software.

They found out that if you started Google Maps it would create "/data/gps/gldata.sto" with world-writable permissions as root, and that "/data/gps" was itself world-writable. So if you setup a symlink named "/data/gps/gldata.sto" that points to a non-existant file you want to write to it will create it with world-writable permissions for you. The file "/data/local.prop" is such a file and you can use that to convince the system to start "adb" as root on next boot.

Once you are root on the system it's "game over" and you can install a suid root "su" in "/system/bin" for future use. I installed my own custom "su" (source [1]) that reads from "/data/x-root/etc/su-allowed-uids" UIDs that are allowed to execute commands as root. You may want to do something different.

Here are the exact steps I took to take control of my Toshiba Thrive:

  1. Enable USB Debugging through the Settings on the system
  2. Plug the Android system into a computer using a USB cable
  3. Run "adb shell" on the computer ("adb" is the Android Debugging Bridge and part of the Android SDK)
  4. This should start a shell on the Android system as user "shell"
    1. You can verify this by running "id" at the $ prompt
  5. Move the "gldata.sto" out of the way and replace it with a (dangling) symlink to "/data/local.prop"
    1. $ mv /data/gps/gldata.sto /data/gps/gldata.sto.bak
    2. $ ln -s /data/local.prop /data/gps/gldata.sto
  6. Start "Google Maps" on the system and wait for it to acquire a GPS lock
  7. Exit "Google Maps"
  8. Verify that "/data/local.prop" has been created with world-writable permissions
    1. $ ls -l /data/local.prop
  9. If not, return to step #6 and try again
  10. Next restore the "gldata.sto" file
    1. $ rm -f /data/gps/gldata.sto
    2. $ mv /data/gps/gldata.sto.bak /data/gps/gldata.sto
  11. Then write the data you want to be in "/data/local.prop":
    1. $ echo "ro.kernel.qemu=1" > /data/local.prop
    2. $ echo "ro.sys.atvc_allow_all_adb=1" >> /data/local.prop
  12. Reboot the Android system by holding down the power button until it asks if you want to Shutdown, then respond "Yes"
  13. Restart your shell (hopefully as root!) by running "adb shell" on the computer
  14. You should now be root
  15. You can verify this by running "id" at the prompt (which should be a #)
  16. The next step is to install a suid-root "su"
    1. Since "/system" is the only filesystem mounted without the "nosuid" option it will need to live here
    2. Since "/system" is mounted read-only, we need to remount it read-write (or mount it read-write somewhere else)
    3. Attempting to remount "/system" read-write (i.e., # mount -o remount,rw /system resulted in "Operation not permitted") and attempting to simply mount the device read-write somewhere else (i.e., # mount -t ext4 /dev/block/mmcblk0p3 /dev/tmpdir) also failed similarly. I am guessing this is some sort of misguided attempt by Toshiba to prevent people from becoming their own system administrator.
    4. In order to mount up the filesystem read-write, therefore, we must find the filesystem first.
    5. To do this I installed "busybox" in a directory in "/data" (I named mine "/data/x-root")
      1. # mkdir /data/x-root
      2. # mkdir /data/x-root/bin
      3. user@workstation$ wget
      4. user@workstation$ wget
      5. user@workstation$ adb push busybox /data/x-root/bin/busybox
      6. user@workstation$ adb push su /data/x-root/bin/su
      7. user@workstation$ adb shell
      8. # cd /data/x-root/bin
      9. # chmod 755 busybox
      10. # unset PS1 PROMPT_COMMAND
      11. # ./busybox bash
      12. # for tool in $(./busybox --list); do ln -s busybox $tool; done
    6. I added my new directory to my path:
      1. # PATH="${PATH}:/data/x-root/bin"; export PATH
    7. Next, I ran "losetup" to create a loop device to mount "/system" from with an offset into the disk simulating having a partition table
      1. # mknod /dev/loop0 b 7 0
      2. # losetup -o 20971520 /dev/loop0 /dev/block/mmcblk0
        1. The 20971520 above is the offset to the start of "mmcblk0p3" from the start of "mmcblk0". This value will differ between differing devices.
        2. I've heard that for the Acer IconiaTab A200 one must instead:
          1. # losetup -o 25165824 /dev/loop0 /dev/block/mmcblk0
      3. NOTE: This looks like it is broken in the latest release of Thrive software (released 24-FEB-2012). A workaround is to copy the block device out to your workstation, make the changes, and then copy it back. This is much more involved. I do not recommend you do this if you don't already know what the commands do.
        1. # mkdir /data/x-root/tmp
        2. workstation$ adb pull /dev/loop0
        3. workstation$ mkdir system
        4. workstation$ sudo mount -t ext4 -o loop loop0 system
        5. Make changes to "system" below, and then return here
        6. workstation$ sudo umount system
        7. workstation$ dd if=loop0 of=loop0.only bs=1024 count=716800
        8. workstation$ adb push loop0.only /data/x-root/tmp/loop0.only
        9. # /data/x-root/bin/dd if=/data/x-root/tmp/loop0.only of=/dev/loop0 bs=1024 count=716800
    8. Then I mounted up that block device read-only to verify that it is what I expected
      1. # mkdir /dev/tmpdir
      2. # mount -o ro -t ext4 /dev/loop0 /dev/tmpdir
      3. # ls -l /dev/tmpdir
    9. After confirming that "/dev/tmpdir" and "/system" are indeed the same filesystem, I mounted it read-write
      1. # umount /dev/loop0
      2. # mount -t ext4 /dev/loop0 /dev/tmpdir
    10. Then, finally, I copied "su" over and made it setuid-root
      1. # cp /data/x-root/bin/su /dev/tmpdir/bin/
      2. # chmod 4555 /dev/tmpdir/bin/su
    11. Next I unmounted the filesystem
      1. # umount /dev/tmpdir
      2. # losetup -d /dev/loop0
      3. # sync
    12. And rebooted the system (again, by holding down the power button until prompted to shutdown, then selecting yes) so "/system" would get remounted with its new contents
  17. Now that I'm root I can backup the system
    1. Installed DroidSSHd
    2. Installed "rsync" [2] and "tincd" [3] into "/data/x-root/bin"
    3. Installed "tun.ko" [4] into "/system/lib/modules" (using the procedure above) since that's the only place where "insmod" would load it from
    4. Reconfigure DroidSSHd to start-up my applications
      1. # cd /data/data/
      2. # mkdir startup
      3. # rm dropbear
      4. # cd startup
      5. # ln -s ../dropbearmulti dropbear
      6. # echo '#! /system/bin/sh' > startup-script
      7. # echo 'PATH="${PATH}:/system/bin:/data/x-root/bin"' >> startup-script
      8. # echo 'export PATH' >> startup-script
      9. # echo 'mkdir /dev/net' >> startup-script
      10. # echo 'mknod /dev/net/tun c 10 200' >> startup-script
      11. # echo 'insmod /system/lib/modules/tun.ko' >> startup-script
      12. # echo 'tincd -n ocvpn >/dev/null 2>/dev/null' >> startup-script
      13. # echo 'exec /data/data/ "$@"' >> startup-script
      14. # chmod 755 startup-script
      15. # cd ..
      16. # ln -s startup/startup-script dropbear
    5. I use BackupPC to back the system up over my VPN
  18. I declared victory.