commit | e2a6576a6acef5cb066e6cc4373f463c857e79bd | [log] [tgz] |
---|---|---|
author | David 'Digit' Turner <digit@google.com> | Fri Jan 19 17:51:51 2018 |
committer | Commit Bot <commit-bot@chromium.org> | Fri Jan 19 17:51:51 2018 |
tree | 999209c5d20ce9c77add8d73c78ca63680cb1076 | |
parent | 601aae3f29b9affeb5ccee581fcf2a792344c9fd [diff] |
android: Enforce read-only mapping of Ashmem regions. This is a CL to solve the issue raised by 789959. The root of the problem is that Android ashmem regions have a very different security model than regular Posix shared memory regions: - On Posix: the region doesn't have any associated read/write/exec protection mask, mmap() uses the file descriptor's access mode to determine if writable mappings are allowed. E.g. if the descriptor is opened with O_RDONLY, then an mmap() with PROT_WRITE will fail with an EACCES error. - On Android: the Ashmem region has its own read/write/exec protection mask, and the file descriptor's access mode is ignored at mmap() time. Also, it is possible to change the region's protection mask through an ioctl(), that only allows dropping privileges. In other words, once a region has been turned read-only, it cannot be turned back to read-write, and any future mmap() attempts are affected (existing mappings that are read-write survive though). - Also, there is no reliable way in Posix or Android to duplicate a file descriptor as read-only (even when /dev/fd/ or /proc/self/fd/ are available), and no way to re-open an existing Ashmem region as read-only. This means that all Ashmem file descriptors have read-write access anyway. Chromium code assumes that it is possible to create read-only descriptors to shared memory region, then send them through IPC to another process. On Android, this cannot work because all descriptors are read-write anyway. This CL works as follows to route around the issue, in the least invasive possible way: - On Android, add a "read_only_" flag to each SharedMemoryHandle instance, indicating that it is intended to only allow read-only mappings. This can be set with SetReadOnly() and tested with IsReadOnly(). Also ensure the flag is properly maintained when copying the handle instance, or sending it through IPC. - Add a method called SetRegionReadOnly() to the Android version of the SharedMemoryHandle. This drops the write access bits from the _region_, making all future mappings _not_ writable. - Ensure that SetRegionReadOnly() is called at Map() time, when needed. - Ensure that the region is sealed read-only when it is sent through IPC or Mojo through a read-only handle on Android. - Modify the FieldTrial code to set the region read-only as soon as possible. This happens after the writable mapping has been created, and used by the PersistentMemoryAllocator, so it only affects processes that receive the region's file descriptor (i.e. sandboxed processes on Android). Also add a unit-test to verify that this works properly. - Modify the user script loader to set the region read-only as soon as it has been populated. The code clearly throws away the original writable mapping before returning a read-only SharedMemory instance, so this should not create any problem. NOTE: This code is likely not used on Android yet, but better be safe than sorry. - Fix content browser sensor-related tests, which used to map a shared memory region writable _after_ a read-only descriptor to it had been sent through Mojo to clients. - Fix DeviceSensorHost implementation to ensure that its StartPolling() method always sends read-only file descriptors to the callback argument (crbug.com/793519, not Android-specific). Also: - Add ashmem_get_prot_region() to third_party/ashmem/ashmem.h, necessary to retrieve a region's current protection mask. This shall probably go into another CL. - Fix a bug where Ashmem regions were blindy created with PROT_EXEC permission, even if the CreateOptions::executable bit was false. - Add a unit-test to verify that anonymous region that are not created with CreateOptions::executable set to true cannot be mapped with PROT_EXEC. This test is Android-specific. It turns out that it fails on Linux (because /dev/shm is mounted on a tmpfs partition without the 'noexe' option, and there is no other way provided by the system to restrict PROT_EXEC-inducing mprotect() calls for these). Bug: 789959,793519 Change-Id: Ibb02eddedd84f95462d7f8b94d3f2a100b983661 Reviewed-on: https://chromium-review.googlesource.com/805238 Commit-Queue: David Turner <digit@chromium.org> Reviewed-by: Mark Pearson <mpearson@chromium.org> Reviewed-by: Mark Mentovai <mark@chromium.org> Reviewed-by: Tim Volodine <timvolodine@chromium.org> Reviewed-by: agrieve <agrieve@chromium.org> Reviewed-by: Robert Sesek <rsesek@chromium.org> Reviewed-by: Ken Rockot <rockot@chromium.org> Reviewed-by: Brandon Jones <bajones@chromium.org> Reviewed-by: Camille Lamy <clamy@chromium.org> Cr-Commit-Position: refs/heads/master@{#530553}
Chromium is an open-source browser project that aims to build a safer, faster, and more stable way for all users to experience the web.
The project's web site is https://www.chromium.org.
Documentation in the source is rooted in docs/README.md.
Learn how to Get Around the Chromium Source Code Directory Structure .