AOSP Framework & Internals
5 min read

UID Sandbox & App Isolation

Learn about UID Sandbox & App Isolation.

Why Your Mobile Needs a New Kind of Sandbox

Desktop operating systems assume you trust every program you run. You log in as one user, and everything runs under your account. Your code editor and a random calculator application share the exact same permissions. They can both read your personal documents, access your keys, and modify your files. This model fails completely on mobile devices where users install dozens of untrusted applications. Giving a flashlight app full access to your personal files creates a massive security disaster.

Android solves this by flipping the Linux user model upside down. Instead of treating the human as the user, Android treats every installed application as a distinct user.

When you install an application, the system assigns it a unique, permanent Linux User ID. This turns the standard Discretionary Access Control system into a perfect application sandbox. Any file created in the application's data directory belongs exclusively to its UID. Default permissions strictly prevent any other UID from reading or writing there. The kernel also uses these UIDs to isolate processes, blocking an application from sending kill signals to another application's processes.

This approach reuses deeply tested core security features of the Linux kernel rather than building a custom userspace sandbox. The kernel simply sees two different users trying to interfere with each other and blocks the action.

You are about to see how the kernel isolates two applications. This visual helps you see how standard Linux permissions block cross-app access at the filesystem layer. Notice how App B gets rejected simply because its UID does not match the file owner.

The DAC check happens entirely inside kernel space. By rejecting the read request, the kernel instantly stops App B and returns a permission error.

But what happens when two applications from the same developer actually need to share data?

Breaking the Sandbox on Purpose

Strict isolation creates problems for application suites. A company might publish several applications that need tight integration and shared data access. If the system treats every application as an isolated user, they cannot easily cooperate. They would have to rely on complex, slow communication channels to share simple files.

Android provides an escape hatch called the shared UID. You declare the android:sharedUserId attribute in your application manifest to request a shared identity.

If two applications declare the exact same shared ID and are signed with the exact same developer certificate, the Package Manager groups them together. The system assigns both applications the identical Linux UID during installation. Both applications can now freely read and write inside each other's private data directories. They can even run components in the same Linux process to reduce memory overhead.

This shared UID completely bypasses the standard sandbox boundary between those specific applications.

Warning: Google deprecated the shared UID feature in recent API levels. The security implications of tying multiple applications to a single identity caused too many complications. You should use explicit mechanisms like ContentProvider or Service binding for modern data sharing.

While UIDs prevent applications from touching each other, they do not stop applications from talking to the underlying operating system.

Locking Down the Kernel

The Linux kernel exposes hundreds of system calls to userspace applications. A mobile application only needs a small fraction of these calls to function correctly. Every unnecessary system call represents a potential attack vector. If a compromised application invokes an obscure kernel function, it might trigger a vulnerability and gain root access.

Android restricts this attack surface using a technology called seccomp. While UIDs restrict horizontal access between applications, seccomp restricts vertical access to the kernel.

Seccomp acts as a strict allowlist for system calls. When the Zygote process forks a new application process, it applies a seccomp filter before executing the application code. This filter intercepts every system call the application attempts to make. Normal functions pass through without issue. If the application attempts to call a restricted function, the kernel steps in immediately and sends a SIGSYS signal to terminate the process.

The compromised code gets no second chance and no error code to inspect. This aggressive termination significantly mitigates kernel privilege escalation exploits launched from untrusted code.

You are about to see how the seccomp filter handles a malicious system call. It shows the exact moment the kernel intercepts the request and neutralizes the threat. Watch how the process terminates before the kernel even attempts to execute the dangerous function.

The restricted call stops dead at the filter boundary. A rogue attempt never reaches the core kernel because the system kills the application instantly.

UIDs keep applications isolated from each other, while seccomp keeps the kernel isolated from the applications. Understanding these boundaries prepares you to learn how Android allows secure, controlled communication across them using Binder.