We have a bunch of magic that mounts the correct view of storage
access based on the runtime permissions of an app, but we forgot to
protect the real underlying data sources; oops.
This series of changes just bumps the directory heirarchy one level
to give us /mnt/runtime which we can mask off as 0700 to prevent
people from jumping to the exposed internals.
Also add CTS tests to verify that we're protecting access to
internal mount points like this.
Bug: 22964288
Change-Id: I83f09f0423f4993e766273c50389dd29b1c50589
This allows apps like ExternalStorageProvider to still read/write
files on transient storage devices which aren't mounted as visible.
Bug: 22545248
Change-Id: Idacb15f2233245a8e1861d9be977535a82b218ec
Long ago, we mounted secondary physical cards as readable by all
users on the device, which enabled the use-case of loading media on
a card and viewing it from all users.
More recently, we started giving write access to these secondary
physical cards, but this created a one-directional channel for
communication across user boundaries; something that CDD disallows.
This change is designed to give us the best of both worlds: the
package-specific directories are writable for the user that mounted
the card, but access to those "Android" directories are blocked for
all other users. Other users remain able to read content elsewhere
on the card.
Bug: 22787184
Change-Id: I75dbd339f11402ae774c7e4b8f2b15ee216270e8
In order to compare results from readlink() calls, we need to null
terminate the read value, otherwise we can end up doing an infinitely
recursive remount in the root namespace.
When remounting inside a namespace, unmount all existing mounts before
mounting the new storage into place. This also means we need to mount
the user-specific symlinks back into place.
Skip spinning up the FUSE daemon when not visible, otherwise we get
stuck waiting for a daemon that never shows up.
Bug: 22192518, 22204412
Change-Id: Icc7db822354ab7ffc47c39cd0611f65edecc32e5
Now that we're treating storage as a runtime permission, we need to
grant read/write access without killing the app. This is really
tricky, since we had been using GIDs for access control, and they're
set in stone once Zygote drops privileges.
The only thing left that can change dynamically is the filesystem
itself, so let's do that. This means changing the FUSE daemon to
present itself as three different views:
/mnt/runtime_default/foo - view for apps with no access
/mnt/runtime_read/foo - view for apps with read access
/mnt/runtime_write/foo - view for apps with write access
There is still a single location for all the backing files, and
filesystem permissions are derived the same way for each view, but
the file modes are masked off differently for each mountpoint.
During Zygote fork, it wires up the appropriate storage access into
an isolated mount namespace based on the current app permissions. When
the app is granted permissions dynamically at runtime, the system
asks vold to jump into the existing mount namespace and bind mount
the newly granted access model into place.
Bug: 21858077
Change-Id: Iade538e4bc7af979fe20095f74416e8a0f165a4a
When formatting volumes, pass along fsType string which can be "auto"
to let the volume select the best choice. For now, private volumes
assume that MMC devices (like SD cards) are best off using f2fs when
both kernel support and tools are present, otherwise fall back to
ext4. Use blkid when mounting to pick the right set of tools.
Move filesystem utility methods into namespaces and place in separate
directory to be more organized.
Bug: 20275581
Change-Id: Id5f82d8672dda2e9f68c35b075f28232b0b55ed4
This is cleaner and more direct than the reverse of having the disk
publish child volume membership. Rename state constants to match
public API. Add state representing bad removal. Make it clear that
volume flags are related to mounting.
Send new unsupported disk event when we finish scanning an entire
disk and have no meaningful volumes.
Bug: 19993667
Change-Id: I08a91452ff561171a484d1da5745293ec893aec0
Sadly setexeccon() is process global, so we need to carefully ensure
that all exec() are mutually exclusive to avoid transitioning into
unwanted domains. Also, because we have several threads floating
around, we need to guard all our FDs with O_CLOEXEC.
Format all newly created volumes immediately after partitioning,
but silence all events emitted from those volumes to prevent the
framework from getting all excited. Unify all notify events under a
single codepath to make them easy to silence.
Sent SIGINT before escalating to SIGTERM when unmounting.
Bug: 19993667
Change-Id: Idc6c806afc7919a004a93e2240b42884f6b52d6b
Mount private volumes at /mnt/expand, which is where we have new
SELinux policy waiting for us. Also ensure that foundational
directories are ready when mounting.
Create local fs_prepare_dir() wrapper that sets SELinux context
based on path, avoiding the need for a later restorecon.
Use UUID as directory name for public volumes. Wait a few seconds
before issuing first signal when force unmounting.
Bug: 19993667
Change-Id: If22595380faaae321705b06c87d877419620da48
vold works with two broad classes of block devices: untrusted devices
that come in from the wild, and trusted devices like PrivateVolume
which are encrypted.
When running blkid and fsck, we pick which SELinux execution domain
to use based on which class the device belongs to.
Bug: 19993667
Change-Id: I2695f028710a4863f0c3b2ed6da437f466401272
This adds support for private volumes which is just a filesystem
wrapped in a dm-crypt layer. For now we're using the exact same
configuration as internal encryption (aes-cbc-essiv:sha256), but we
don't store any key material on the removable media. Instead, we
store the key on internal storage, and use the GPT partition GUID
to identify which key should be used.
This means that private external storage is effectively as secure as
the internal storage of the device. That is, if the internal storage
is encrypted, then our external storage key is also encrypted.
When partitioning disks, we now support a "private" mode which has
a PrivateVolume partition, and a currently unused 16MB metadata
partition reserved for future use. It also supports a "mixed" mode
which creates both a PublicVolume and PrivateVolume on the same
disk. Mixed mode is currently experimental.
For now, just add ext4 support to PrivateVolume; we'll look at f2fs
in a future change. Add VolumeBase lifecycle for setting up crypto
mappings, and extract blkid logic into shared method. Sprinkle some
more "static" around the cryptfs code to improve invariants.
Bug: 19993667
Change-Id: Ibd1df6250735b706959a1eb9d9f7219ea85912a0
Wire up new Disk and VolumeBase objects and events to start replacing
older DirectVolume code. Use filesystem UUID as visible PublicVolume
name to be more deterministic.
When starting, create DiskSource instances based on fstab, and watch
for kernel devices to appear. Turn matching devices into Disk
objects, scan for partitions, and create any relevant VolumeBase
objects. Broadcast all of these events towards userspace so the
framework can decide what to mount.
Keep track of the primary VolumeBase, and update the new per-user
/storage/self/primary symlink for all started users.
Provide a reset command that framework uses to start from a known
state when runtime is restarted. When vold is unexpectedly killed,
try recovering by unmounting everything under /mnt and /storage
before moving forward.
Remove UMS sharing support for now, since no current devices support
it; MTP is the recommended solution going forward because it offers
better multi-user support.
Switch killProcessesWithOpenFiles() to directly take signal. Fix
one SOCK_CLOEXEC bug, but SELinux says there are more lurking.
Bug: 19993667
Change-Id: I2dad1303aa4667ec14c52f774e2a28b3c1c1ff6d
This is the first in a series of changes that are designed to
introduce better support for dynamic block devices.
It starts by defining a new Volume object which represents a storage
endpoint that knows how to mount, unmount, and format itself. This
could be a filesystem directly on a partition, or it could be an
emulated FUSE filesystem, an ASEC, or an OBB.
These new volumes can be "stacked" so that unmounting a volume will
also unmount any volumes stacked above it. Volumes that provide
shared storage can also be asked to present themselves (through bind
mounts) into user-specific mount areas.
This change also adds a Disk class which is created based on block
kernel netlink events. Instead of waiting for partition events from
the kernel, it uses gptfdisk to read partition details and creates
the relevant Volume objects.
Change-Id: I0e8bc1f8f9dcb24405f5e795c0658998e22ae2f7