Mobile Apps 2023W Lecture 13

From Soma-notes
Jump to navigation Jump to search

Notes

Android Architecture & Security
-------------------------------

* I've graded all proposals
* On Friday, progress report 3 is due
* If you have something to demo, please demo in Friday!


What is running on an Android device?  How does it compare to a regular Linux system?

Android documentation uses lots of Android-specific jargon, not at all clear how it maps to more normal concepts.  So I'm going to try explaining that here.

First, Android runs on Linux.  So what does that mean?

Standard division for most Linux systems:

Applications
------------
Linux Kernel
------------
Hardware


Kernel communicates with hardware using hardware APIs (accessing special memory locations, I/O ports, interrupts, etc)

Applications talk to the Linux kernel using system calls.

Applications run inside of processes.  A process is an address space + one or more execution context.  Each address space is separate, processes cannot access the memory of other processes (unless explicitly shared).

When you run "ps" or "top" on a Linux system, you can see all of the processes that are running.

You can do the same on Android as well, underneath it is just Linux.
But...Android has a bunch of extra stuff.


One key difference is in how processes talk to each other.  Standard Linux supports multiple communication mechanisms:
  - TCP/IP sockets
  - System V IPC
  - pipes
  - shared memory (using mmap)

Android adds its own custom IPC mechanism, Binder.  Yes, they *patched* Linux to add support for a new IPC mechanism!
 - this is the mechanism that facilitates communication in Android
 - most Android APIs are built on this when they go between processes
 - key feature: it is very fast! (uses shared memory, but with kernel support)

Originally Binder wasn't in the main Linux kernel, it was kept "out of tree", but it has been upstreamed and so modern Linux systems do have support for Binder.


On a standard Linux system, permissions are all based on files and users.  Devices are special files, and access is granted or not based on the user and group of a process.

User/group file permissions are not flexible enough for a system like Android, they wanted something else to determine what applications could access what.

For example, how to control access to a camera?  The raw camera would show up as a device in /dev, how can we make sure only one app is using the camera at a time, that permission is only granted when the user says so and the user can withdraw it?

Well, every app on Android has its own user ID, and that is used to limit the access the app has.
  - not per user, per APP!

This user-ID-per-app thing is part of the Android *application sandbox* - applications have only limited access to files and other resources.  They are confined by default.

Web browsers also implement a sandbox, that's why each tab cannot access data in another tab (for JavaScript code), but it is implemented using very different technologies and with different levels of access
 - remember a sandbox is an aspiration, not a specific set of technologies!

If a regular Android app asks the Linux kernel for access to the camera, the kernel will just say no because it won't have the right permissions (it won't have the right user and group ID for access).  But then how does it get access?

Android has special background processes, "servers", that wait for requests from Android applications and then do the work on behalf of the app.
 - these services perform a role somewhat like that of the Linux kernel,
   but in an Android-specific way
 - most central one is system_server, this implements the basic plumbing,
   but there are others like media_server

Note that the camera device's permissions are setup so that an android server process has exclusive access.  Applications then ask it (via intents which are Binder-relayed messages) for access to these resources and the server can say yes or no.  Because Binder is fast this interaction is also fast.


What's cool about Binder is you don't have to know which process you want to talk to.  You can broadcast a request with specific criteria and the appropriate processes (applications or servers) will get it and respond as they see fit.
  - this is all orchestrated by system_server with the help of the Linux kernel's binder mechanism

Why does all this matter?
 - to some degree it doesn't, if you're doing normal application development
 - but when things break, it is important to know who is telling you that there is a problem and where you can potentially observe things to try and fix them