Funny Stuff in AOSP #1

Lately, I’ve been spending a lot of time going through the Android source code, trying to understand how different pieces work.  As you can imagine, it can get pretty tedious.  Thankfully, most developers have a good sense of humor (albeit twisted sometimes), and occasionally this is reflected in their work.

I’m aware of the debate about funny commenting and Easter egg code.  For me however, coming across one of these gems after long frustrating hours of reverse-engineering is a welcome relief.  It’s also nice to be reminded of the human side of these otherwise impersonal machines.

Hopefully, this is the start of a Rat’s Nest series on funny things in the Android Open Source Project (AOSP) code.  Here’s the first installment.

OK, I know just about everyone knows this one, but I’m starting off this series with it because it’s the first funny thing I found while studying the source for a recent security evaluation. From frameworks/base/core/java/android/os/UserManager.java:

 /**
 * Used to determine whether the user making this call is subject to
 * teleportations.
 * @return whether the user making this call is a goat
 */
 public boolean isUserAGoat() {
 return false;
 }

Thankfully, it appears as though none of us are subject to teleportations!

Advertisements

Simple Web Server for Testing Apps

I usually do initial test/debug of my Android apps in a VirtualBox virtual machine before I go through the trouble of connecting a real device.  These virtual devices see VirtualBox’s host-only network, usually 192.168.56.xx, for talking to the IDE, and have a second NAT‘ed adapter which uses the host’s Internet connection.  On the host-only side, the host system gets address 192.168.56.1 and the VM gets a DHCP assignment on this subnet, like 192.168.56.101.  This is also true if you are using something like Genymotion (which is really just  wrapper around VirtualBox).

Many times, I’ve wished for a quick-and-dirty way to test apps in this environment against a web server that I control.  I came across an easy way to do this, without having to install a full server like Apache.  It uses Python 2.x‘s SimpleHTTPServer module.  Here’s the code, which I adapted from a old Linux Journal tech tip:

#!/usr/bin/env python2
import sys
import BaseHTTPServer
from SimpleHTTPServer import SimpleHTTPRequestHandler

HandlerClass = SimpleHTTPRequestHandler
ServerClass = BaseHTTPServer.HTTPServer
Protocol = "HTTP/1.0"

if sys.argv[1:]:
server = sys.argv[1]
else:
server = '127.0.0.1'

if sys.argv[2:]:
port = int(sys.argv[2])
else:
port = 8000

server_address = (server, port)

HandlerClass.protocol_version = Protocol
httpd = ServerClass(server_address, HandlerClass)

print "httpd on", server, ":", port

httpd.serve_forever()

Put this in a .py file like simple_web.py and run it using python simple_web.py <address> <port> (or make the file executable and run it directly).  It will start a server and serve up files from the directory you started it in.  Arguments are server address (1st argument) and port (2nd), with defaults of 127.0.0.1 (localhost) and 8000, respectively. You can specify neither, just an address, or both address and port.

I kept this in Python 2.x since it’s the current default on my dev system (Ubuntu 14.04 LTS).  If your setup has Python 3.x as the default, then you’ll have to either specify python2 on the command line, or translate the program to Python 3.x (hint: check out Python 3.x’s http.server module).

Quick Look at Android Lollipop’s Managed Provisioning

Earlier this year, I was part of a systematic study of the security of Android’s multi-user features, done by the Smartphone Security Research Group at Syracuse University.  The recent release of Android L Developer Preview mentioned a new enterprise feature called managed provisioning that sounded like it might be related to the earlier multi-user features.  My curiosity got the best of me, and although it was after midnight last night (this morning), I decided to do a short “quick look” at the Managed Profile feature of Android L.  I installed the Android L Preview on a Nexus 7 and then rooted it with SuperSU so that I could poke around the file system.  Next I imported the BasicManagedProfile sample app into Android Studio and ran it on the Nexus.  Here’s what I found:

The goal of Managed Provisioning/Profiles is to allow managed apps alongside personal apps in the same launcher and account.  This is graphically shown by having the managed apps’ icons overlaid with a small red suitcase badge.  In other words, in the same launcher, I can have my own Gmail for a personal account, and another Gmail for a managed, company account.  Both in the same launcher without having to switch users and they can be running at the same time.  They run as separate apps, so they can have separate configurations, providers, etc.  Here’s screenshots of the launcher and app drawer from my tests showing the mix of unmanaged and managed apps (note red badges and duplicates):

L Desktop

Home launcher showing the unmanged Calendar app (no badge) and the managed profile’s Calendar app (red badge).

L Launcher

App drawer showing a mix of unmanaged (no badge) and managed (red badge) apps.

Google has most definitely used the same multi-user framework that we previously studied to implement this.  When I created a Managed Profile using their sample app (see below), it set up a userId 10 just like as if I had created a secondary user or restricted profile.  All of the files and folders are pretty much the same as before:

  • /data/user/<userId>: contains the data directories for all of the installed apps (same as multi-user).
  • /data/system/users/<userId>.xml: describes the user, restricted profile or managed profile (same as multi-user).  For a managed profile, is linked to the owning user with a (new?) tag, profileGroupId, that seems to be set to the userId of the owning user.
  • /data/system/users/userlist.xml: keeps track of the assigned userIds, next available ID and some other things (same as multi-user).
  • /data/system/users/<userId>: contains SQLite databases for that userId‘s accounts, personal settings, and wallpaper.  Also has a few XML files: device_policies.xml, appwidgets.xml, and package-restrictions.xml.   While this is also stuff we saw in multi-user, there seem to be some additional interesting tags in a couple of these files. For example, the restrictions file for the managed profile I created has what appears to be provisions to block apps and control the destination userId for certain intents. In other words, it seems to specify which intents that originate in the managed profile can go to unmanaged apps of the owning user.

Furthermore, I confirmed that things are very similar to multi-user by launching both Calendar apps, unmanaged and managed, and then checking ps:

$ ps | grep calendar
u0_a29    7009  224   1389256 50788 ffffffff 00000000 S com.google.android.calendar
u0_a1     7041  224   1361328 34904 ffffffff 00000000 S com.android.providers.calendar
u10_a29   7112  224   1389640 50868 ffffffff 00000000 S com.google.android.calendar
u10_a1    7140  224   1361328 34920 ffffffff 00000000 S com.android.providers.calendar
$

As you can see, the unmanaged Calendar and its provider are running as the Owner (userId 0), and the managed pair is running as userId 10.  They are in fact the same app (appId 10029), just like different users or restricted profiles share the same app installation, but run them as different UIDs.

As far as I can tell, there’s no setup for this in the Settings menus at this time.  The Users menu only has what we saw before (Add User/Add Restricted Profile for the Owner), although once the managed profile was created, the Users menu listed it and included the capability to delete it.  The lack of an add capability may be either a facet of the L Preview being incomplete or because of the fact that the feature is managed by a Device Administrator via API and therefore should not be a part of Settings.  We’ll have to wait and see.

To play with it on the device, I had to get the sample app, BasicManagedProfile, from the L Preview SDK and import it into Android Studio.  The source code contains this information:

This sample demonstrates how to create a managed profile. You can also learn how to enable or disable other apps and how to set restrictions to them. Intents can be configured to be forwarded between primary account and managed profile. Finally, you can wipe all the data associated with the profile. Note that there can only be one managed profile on a device.

This app lets users set up a managed profile, and do some sample operations: 1) add Calculator and/or Chrome to the set of managed apps that it sets up by default (Calendar, Google Search, etc.); 2) set restrictions on Chrome; 3) enable/disable Intent forwarding; and 4) wipe the profile.  It has android.permission.BIND_DEVICE_ADMIN.  Here’s a screenshot of the app running in the managed profile, and the window that comes up when you hit the “Set Chrome Restrictions” button:

BasicManagedProfile

Main activity of BasicManagedProfile sample app.

Chrome restrictions.

Information pop-up showing details of restrictions applied to managed profile instance of the Chrome browser.

So after my quick look, I’m pretty confident that Managed Profiles are basically the same thing as Restricted Profiles except that the apps of the different profiles can coexist on the same launcher so you don’t need to switch users to use them all.  Also, there are new rules having to do with Intents between unmanaged and managed apps that are tied to the same user group. The userIdDest and Intent filter parts of  package-restrictions.xml, as well as the “Share Intent” buttons of the sample app are evidence of this.  This aspect could be very interesting to learn more about.   Finally, there are some more fine-grained restrictions that can be applied to apps in the managed profile.