Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
*.so
tags
test/test-*
.vscode
8 changes: 4 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
CFLAGS += -fpic -shared -std=c11 -Wall -Wextra
LDFLAGS += -Wl,--version-script=exports.txt

libandroid-shmem.a: shmem.o
$(AR) rcu $@ shmem.o
libandroid-shmem.a: shmem.o shmem_vanilla.o
$(AR) rcu $@ shmem.o shmem_vanilla.o

libandroid-shmem.so: shmem.o
$(CC) $(LDFLAGS) -shared shmem.o -o $@ -llog -landroid
libandroid-shmem.so: shmem.o shmem_vanilla.o
$(CC) $(LDFLAGS) -shared shmem.o shmem_vanilla.o -o $@ -llog -landroid

shmem.o: shmem.c shm.h
$(CC) $(CFLAGS) -c shmem.c -o $@
Expand Down
51 changes: 51 additions & 0 deletions shm_vanilla.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Copyright (C) 2016 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/

/** fork of https://android.googlesource.com/platform/bionic/+/02ce401d1e2b31586c94c8b6999364bbbce27388/libc/include/sys/shm.h */

#pragma once

#include <sys/cdefs.h>
#include <sys/ipc.h>
#include <sys/types.h>
#include <unistd.h>
#include <linux/shm.h>

__BEGIN_DECLS

/** Not useful on normal Android; disallowed by SELinux. */
/** useful for partial Android userspace components running inside the unmodified kernel of a */
/** different operating system that doesn't have ashmem, ion, dma-buf or SELinux, */
/** for example using a container, or other method */

void* _Nonnull shmat_vanilla(int __shm_id, const void* _Nullable __addr, int __flags);
int shmctl_vanilla(int __shm_id, int __op, struct shmid64_ds* _Nullable __buf);
int shmdt_vanilla(const void* _Nonnull __addr);
int shmget_vanilla(key_t __key, size_t __size, int __flags);

__END_DECLS
32 changes: 31 additions & 1 deletion shmem.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#endif

#include "shm.h"
#include "shm_vanilla.h"

#define DBG(...) __android_log_print(ANDROID_LOG_INFO, "shmem", __VA_ARGS__)
#define ASHV_KEY_SYMLINK_PATH _PATH_TMP "ashv_key_%d"
Expand Down Expand Up @@ -153,6 +154,21 @@ static int ashmem_create_region(char const* name, size_t size)
#endif
}

static bool ashmem_is_available(void) {
#if __ANDROID_API__ >= 26
int fd = ASharedMemory_create("libandroid-shmem-test", 1);
if (fd == -1) {
#else
if (access("/dev/ashmem", F_OK) != 0) {
#endif
return false;
}
#if __ANDROID_API__ >= 26
close(fd);
#endif
return true;
}

static void ashv_check_pid()
{
pid_t mypid = getpid();
Expand Down Expand Up @@ -296,7 +312,9 @@ static int ashv_read_remote_segment(int shmid)
/* Get shared memory area identifier. */
int shmget(key_t key, size_t size, int flags)
{
(void) flags;
if (!ashmem_is_available()) {
return shmget_vanilla(key, size, flags);
}

ashv_check_pid();

Expand Down Expand Up @@ -441,6 +459,10 @@ int shmget(key_t key, size_t size, int flags)
/* Attach shared memory segment. */
void* shmat(int shmid, void const* shmaddr, int shmflg)
{
if (!ashmem_is_available()) {
return shmat_vanilla(shmid, shmaddr, shmflg);
}

ashv_check_pid();

int socket_id = ashv_socket_id_from_shmid(shmid);
Expand Down Expand Up @@ -479,6 +501,10 @@ void* shmat(int shmid, void const* shmaddr, int shmflg)
/* Detach shared memory segment. */
int shmdt(void const* shmaddr)
{
if (!ashmem_is_available()) {
return shmdt_vanilla(shmaddr);
}

ashv_check_pid();

pthread_mutex_lock(&mutex);
Expand Down Expand Up @@ -561,6 +587,10 @@ int libandroid_shmdt_fd(int fd)
/* Shared memory control operation. */
int shmctl(int shmid, int cmd, struct shmid_ds *buf)
{
if (!ashmem_is_available()) {
return shmctl_vanilla(shmid, cmd, buf);
}

ashv_check_pid();

if (cmd == IPC_RMID) {
Expand Down
62 changes: 62 additions & 0 deletions shmem_vanilla.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* Copyright (C) 2016 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/

/** fork of https://android.googlesource.com/platform/bionic/+/02ce401d1e2b31586c94c8b6999364bbbce27388/libc/bionic/sys_shm.cpp */

#include <sys/syscall.h>
#include <unistd.h>

#include "shm_vanilla.h"

void* shmat_vanilla(int id, const void* address, int flags) {
return (void*)(syscall(SYS_shmat, id, address, flags));
}

int shmctl_vanilla(int id, int cmd, struct shmid64_ds* buf) {
// upstream bionic libc and also other libc implementations contain
// this code that ORs cmd with IPC_64, but unfortunately, for some reason
// in 32-bit termux-docker, an error always occurs during test-with-key
// 'shmctl: Invalid argument' unless the ORing with IPC_64 is disabled.
// when that is disabled, all tests pass. This result holds for both arm and i686
// termux-docker running in both fully 32-bit kernels and the 32-bit mode of
// 64-bit kernels.
#if 0
//#if !defined(__LP64__)
// Annoyingly, the kernel requires this for 32-bit but rejects it for 64-bit.
cmd |= IPC_64;
#endif
return syscall(SYS_shmctl, id, cmd, buf);
}

int shmdt_vanilla(const void* address) {
return syscall(SYS_shmdt, address);
}

int shmget_vanilla(key_t key, size_t size, int flags) {
return syscall(SYS_shmget, key, size, flags);
}
6 changes: 3 additions & 3 deletions test/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ OS := $(shell uname -o 2> /dev/null)

ifeq ($(OS), Android)
CFLAGS += -I.. -llog
EXTRA_CFILE = ../shmem.c
EXTRA_CFILES = ../shmem.c ../shmem_vanilla.c
cleanup-memory: test ;
else
CFLAGS += -DSYSV_ASHMEM_TEST_SYSTEM
EXTRA_CFILE =
EXTRA_CFILES =
cleanup-memory: test
./cleanup-shared-memory.sh
endif
Expand All @@ -18,7 +18,7 @@ test: $(addprefix testcase-,$(patsubst %.c,%,$(wildcard *.c))) ;
testcase-% : test-%
./$^

test-%: %.c $(EXTRA_CFILE)
test-%: %.c $(EXTRA_CFILES)
$(CC) $(CFLAGS) $+ -o $@

clean:
Expand Down