Bug 1598068 - Add ashmem abstraction to mozglue and use it everywhere r=glandium,jld

Apps targeting SDK 29 are not allowed to open /dev/ashmem directly, and
instead must use NDK functions. Those functions are only available in
SDK 26 and higher, so we need this shim to use the functions if they
are available, else fallback to opening /dev/ashmem directly.

Differential Revision: https://phabricator.services.mozilla.com/D61012

--HG--
extra : moz-landing-system : lando
This commit is contained in:
James Willcox 2020-02-13 22:17:05 +00:00
Родитель 889cf591cf
Коммит 5a405a1191
7 изменённых файлов: 112 добавлений и 40 удалений

Просмотреть файл

@ -13,7 +13,7 @@
#include <unistd.h>
#ifdef ANDROID
# include <linux/ashmem.h>
# include "mozilla/Ashmem.h"
#endif
#include "base/eintr_wrapper.h"
@ -202,15 +202,11 @@ bool SharedMemory::CreateInternal(size_t size, bool freezeable) {
#ifdef ANDROID
// Android has its own shared memory facility:
fd.reset(open("/" ASHMEM_NAME_DEF, O_RDWR, 0600));
fd.reset(mozilla::android::ashmem_create(nullptr, size));
if (!fd) {
CHROMIUM_LOG(WARNING) << "failed to open shm: " << strerror(errno);
return false;
}
if (ioctl(fd.get(), ASHMEM_SET_SIZE, size) != 0) {
CHROMIUM_LOG(WARNING) << "failed to set shm size: " << strerror(errno);
return false;
}
needs_truncate = false;
#else
// Generic Unix: shm_open + shm_unlink
@ -271,7 +267,7 @@ bool SharedMemory::Freeze() {
Unmap();
#ifdef ANDROID
if (ioctl(mapped_file_, ASHMEM_SET_PROT_MASK, PROT_READ) != 0) {
if (mozilla::android::ashmem_setProt(mapped_file_, PROT_READ) != 0) {
CHROMIUM_LOG(WARNING) << "failed to freeze shm: " << strerror(errno);
return false;
}

Просмотреть файл

@ -18,11 +18,7 @@
#include "SharedMemoryBasic.h"
//
// Temporarily go directly to the kernel interface until we can
// interact better with libcutils.
//
#include <linux/ashmem.h>
#include "mozilla/Ashmem.h"
namespace mozilla {
namespace ipc {
@ -51,18 +47,12 @@ bool SharedMemoryBasic::Create(size_t aNbytes) {
MOZ_ASSERT(-1 == mShmFd, "Already Create()d");
// Carve a new instance off of /dev/ashmem
int shmfd = open("/" ASHMEM_NAME_DEF, O_RDWR, 0600);
int shmfd = mozilla::android::ashmem_create(nullptr, aNbytes);
if (-1 == shmfd) {
LogError("ShmemAndroid::Create():open");
return false;
}
if (ioctl(shmfd, ASHMEM_SET_SIZE, aNbytes)) {
LogError("ShmemAndroid::Unmap():ioctl(SET_SIZE)");
close(shmfd);
return false;
}
mShmFd = shmfd;
Created(aNbytes);
return true;

Просмотреть файл

@ -7,12 +7,13 @@
#include "mozilla/mozalloc.h"
#include <fcntl.h>
#include <linux/ashmem.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include "mozilla/Ashmem.h"
#ifdef MOZ_MEMORY
extern "C" int posix_memalign(void** memptr, size_t alignment, size_t size);
#endif
@ -38,15 +39,11 @@ bool VolatileBuffer::Init(size_t aSize, size_t aAlignment) {
goto heap_alloc;
}
mFd = open("/" ASHMEM_NAME_DEF, O_RDWR);
mFd = mozilla::android::ashmem_create(nullptr, mSize);
if (mFd < 0) {
goto heap_alloc;
}
if (ioctl(mFd, ASHMEM_SET_SIZE, mSize) < 0) {
goto heap_alloc;
}
mBuf = mmap(nullptr, mSize, PROT_READ | PROT_WRITE, MAP_SHARED, mFd, 0);
if (mBuf != MAP_FAILED) {
return true;

Просмотреть файл

@ -0,0 +1,67 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <cstring>
#include <fcntl.h>
#include <linux/ashmem.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include "Ashmem.h"
namespace mozilla {
namespace android {
// Use weak symbols for these, since we may not be running
// on a device that has them.
MOZ_EXPORT extern "C" int __attribute__((weak))
ASharedMemory_create(const char*, size_t);
MOZ_EXPORT extern "C" size_t __attribute__((weak)) ASharedMemory_getSize(int);
MOZ_EXPORT extern "C" int __attribute__((weak)) ASharedMemory_setProt(int, int);
int ashmem_create(const char* name, size_t size) {
if (ASharedMemory_create) {
return ASharedMemory_create(name, size);
}
int fd = open("/" ASHMEM_NAME_DEF, O_RDWR, 0600);
if (fd < 0) {
return fd;
}
if (name) {
char str[ASHMEM_NAME_LEN];
strlcpy(str, name, sizeof(str));
ioctl(fd, ASHMEM_SET_NAME, str);
}
if (ioctl(fd, ASHMEM_SET_SIZE, size) != 0) {
close(fd);
return -1;
}
return fd;
}
size_t ashmem_getSize(int fd) {
if (ASharedMemory_getSize) {
return ASharedMemory_getSize(fd);
}
return (size_t)ioctl(fd, ASHMEM_GET_SIZE, nullptr);
}
int ashmem_setProt(int fd, int prot) {
if (ASharedMemory_setProt) {
return ASharedMemory_setProt(fd, prot);
}
return ioctl(fd, ASHMEM_SET_PROT_MASK, prot);
}
} // namespace android
} // namespace mozilla

22
mozglue/android/Ashmem.h Normal file
Просмотреть файл

@ -0,0 +1,22 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef Ashmem_h__
#define Ashmem_h__
#include <linux/ashmem.h>
namespace mozilla {
namespace android {
// Wrappers for the ASharedMemory function in the NDK
// https://developer.android.com/ndk/reference/group/memory
MFBT_API int ashmem_create(const char* name, size_t size);
MFBT_API size_t ashmem_getSize(int fd);
MFBT_API int ashmem_setProt(int fd, int prot);
} // namespace android
} // namespace mozilla
#endif // Ashmem_h__

Просмотреть файл

@ -8,8 +8,13 @@ EXPORTS += [
'APKOpen.h',
]
EXPORTS.mozilla += ['Ashmem.h']
OS_LIBS += ['android']
SOURCES += [
'APKOpen.cpp',
'Ashmem.cpp',
'NativeCrypto.cpp',
'nsGeckoUtils.cpp',
'NSSBridge.cpp',

Просмотреть файл

@ -17,7 +17,7 @@
#include "mozilla/UniquePtr.h"
#ifdef ANDROID
# include <linux/ashmem.h>
# include "mozilla/Ashmem.h"
#endif
#include <sys/stat.h>
#include <errno.h>
@ -243,19 +243,14 @@ class _MappableBuffer : public MappedPtr {
AutoCloseFD fd;
#ifdef ANDROID
/* On Android, initialize an ashmem region with the given length */
fd = open("/" ASHMEM_NAME_DEF, O_RDWR, 0600);
if (fd == -1) return nullptr;
char str[ASHMEM_NAME_LEN];
strlcpy(str, name, sizeof(str));
ioctl(fd, ASHMEM_SET_NAME, str);
if (ioctl(fd, ASHMEM_SET_SIZE, length)) return nullptr;
fd = mozilla::android::ashmem_create(name, length);
/* The Gecko crash reporter is confused by adjacent memory mappings of
* the same file and chances are we're going to map from the same file
* descriptor right away. To avoid problems with the crash reporter,
* create an empty anonymous page before or after the ashmem mapping,
* depending on how mappings grow in the address space.
*/
/* The Gecko crash reporter is confused by adjacent memory mappings of
* the same file and chances are we're going to map from the same file
* descriptor right away. To avoid problems with the crash reporter,
* create an empty anonymous page before or after the ashmem mapping,
* depending on how mappings grow in the address space.
*/
# if defined(__arm__)
// Address increases on ARM.
void* buf = ::mmap(nullptr, length + PAGE_SIZE, PROT_READ | PROT_WRITE,
@ -266,7 +261,7 @@ class _MappableBuffer : public MappedPtr {
0);
DEBUG_LOG("Decompression buffer of size 0x%" PRIxPTR
" in ashmem \"%s\", mapped @%p",
length, str, buf);
length, name, buf);
return new _MappableBuffer(fd.forget(), buf, length);
}
# elif defined(__i386__) || defined(__x86_64__) || defined(__aarch64__)
@ -289,7 +284,7 @@ class _MappableBuffer : public MappedPtr {
DEBUG_LOG("Decompression buffer of size 0x%" PRIxPTR
" in ashmem \"%s\", mapped @%p",
length, str, actual_buf);
length, name, actual_buf);
return new _MappableBuffer(fd.forget(), actual_buf, length);
}
# else