Does android support the PTRACE_SINGLESTEP? - android

OK, this is a simple question.Does android support the PTRACE_SINGLESTEP when I use ptrace systemcall? when I want to ptrace a android apk program, I find that I can't process the SINGLESTEP trace. But the situation changed when I use the PTRACE_SYSCALL, It can work perfectly. Does the android wipe out this function or arm lack some supports in hardware? Any help will be appreciated!thanks.
this is my core program:
int main(int argc, char *argv[])
{
if(argc != 2) {
__android_log_print(ANDROID_LOG_DEBUG,TAG,"please input the pid!");
return -1;
}
if(0 != ptrace(PTRACE_ATTACH, target_pid, NULL, NULL))
{
__android_log_print(ANDROID_LOG_DEBUG,TAG,"ptrace attach error");
return -1;
}
__android_log_print(ANDROID_LOG_DEBUG,TAG,"start monitor process :%d",target_pid);
while(1)
{
wait(&status);
if(WIFEXITED(status))
{
break;
}
if (ptrace(PTRACE_SINGLESTEP, target_pid, 0, 0) != 0)
__android_log_print(ANDROID_LOG_DEBUG,TAG,"PTRACE_SINGLESTEP attach error");
}
ptrace(PTRACE_DETACH, target_pid, NULL, NULL);
__android_log_print(ANDROID_LOG_DEBUG,TAG,"monitor finished");
return 0;
}
I run this program on shell. And I can get the root privilege.
If I change the request to PTRACE_SYSCALL the program will run normally.
But if the request is PTRACE_SINGLESTEP, the program will get an error!

PTRACE_SINGLESTEP has been removed on ARM Linux since 2011, by this commit.
The HW has no support for single-stepping; previous kernel support involved decoding the instruction to figure out which one's next (branches) and temporarily replacing it with a debug-break software breakpoint.
Quoting a mailing list message about the same commit, describing the old situation: http://lists.infradead.org/pipermail/linux-arm-kernel/2011-February/041324.html
PTRACE_SINGLESTEP is a ptrace request designed to offer single-stepping
support to userspace when the underlying architecture has hardware
support for this operation.
On ARM, we set arch_has_single_step() to 1 and attempt to emulate
hardware single-stepping by disassembling the current instruction to
determine the next pc and placing a software breakpoint on that
location.
Unfortunately this has the following problems:
Only a subset of ARMv7 instructions are supported
Thumb-2 is unsupported
The code is not SMP safe
We could try to fix this code, but it turns out that because of the
above issues it is rarely used in practice. GDB, for example, uses
PTRACE_POKETEXT and PTRACE_PEEKTEXT to manage breakpoints itself and
does not require any kernel assistance.
This patch removes the single-step emulation code from ptrace meaning
that the PTRACE_SINGLESTEP request will return -EIO on ARM. Portable
code must check the return value from a ptrace call and handle the
failure gracefully.
Signed-off-by: Will Deacon <will.deacon at arm.com>
---
The comments I received about v1 suggest that:
If emulation is required, it is plausible to do it from userspace
ltrace uses the SINGLESTEP call (conditionally at compile-time since other architectures, such as mips, do not support this
request) but does not check the return value from ptrace. This is a
bug in ltrace.
strace does not use SINGLESTEP

Related

Modifying Android UI through linux kernel

My goal is to show a popup window in the Android UI using linux kernel. Is it possible to do so? I checked the SDM driver(DRM driver for QCOM/adreno devices) but I couldn't find an API which does so. I thought of a solution which would be to open app that shows a pop up on screen but I couldn't find an api for starting android apps from the kernel either. I was able to find some information in this thread How to start an app from kernel
However I couldn't find any solid information!
EDIT
I tried launching telegram as a test through am (and I bypassed selinux denial as well) but nothing happened. Here's the code:
static int launch_test(void){
char *envp[] = {
"ANDROID_DATA=/data",
"LOGNAME=shell",
"HOME=/",
"ANDROID_STORAGE=/storage",
"ANDROID_ASSETS=/system/app",
"SHELL=/system/bin/sh",
"EXTERNAL_STORAGE=/sdcard",
"ANDROID_CACHE=/cache",
"USER=shell",
"TMPDIR=/data/local/tmp",
"PATH=/sbin:/system/sbin:/system/bin:/system/xbin:/odm/bin:/vendor/bin:/vendor/xbin",
NULL};
char *argv[] = {"/system/bin/am", "start", "org.telegram.messenger/org.telegram.ui.LaunchActivity", NULL};
return call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC);
}

Native network-related functions randomly blocking in android

I have a library written in C that I'm using from an Android application. I discovered that the application blocks sometimes while executing various functions (what is common is they are all related to networking).
I'm testing on a real Android device running Android 6.
The library is compiled with NDK version 21.
So far I have observed this behavior with 3 functions - getaddrinfo, poll and socket:
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
getaddrinfo(hostname, port, &hints, &result);
////
struct pollfd wait = {
.fd = fd,
.events = event,
.revents = 0
};
status = poll(&wait, 1, 10000);
////
fd = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
These functions are called several times each after the program starts running. The same call can work fine one time and block indefinitely (at least several minutes) the next time. The internet connection on the device seems to be fine.
Any ideas? How can I even approach debugging such a problem?
I didn't actually find the reason for the problem, but I found how to fix it. Part of the code was written by somebody else and I wasn't sure what exactly it was doing. After rewriting this part, everything started to work fine.
Among other things, the code was spawning a new process with fork(). I suspect the problem to be related to that.

Operator new does not throw bad_alloc on Android

I am developing a C++ game on Android NDK (android-ndk-r9b). If I write this:
class Test
{
char c[1024*1024*1024];
};
//in main
try {
Test* p;
while (1) {
p = new Test();
}
} catch (bad_alloc) {
cout << "bad_alloc\n";
}
it doesn't throw. If I try this:
void no_memory_by_new() {
cout << "no_memory_by_new\n";
throw bad_alloc();
}
//in main
set_new_handler(no_memory_by_new);
Test* p;
while (1) {
p = new Test();
}
it doesn't work either. Finally, if I try this:
//in main
set_new_handler(no_memory_by_new);
int* p;
while (1) {
p = new int[1024*1024*1024];
}
then no_memory_by_new is called. I'm really confused about this. Can anyone help me?
This is bug in Android build of GNU libstdc++. If you look into operator new implementation, you'll see it call _GLIBCXX_THROW_OR_ABORT if malloc return NULL. Next, if you look on definition of _GLIBCXX_THROW_OR_ABORT, you'll see it throw bad_alloc only if __EXCEPTIONS defined; otherwise, it just call abort. For some reason, __EXCEPTIONS macro is not defined in Android build of GNU libstdc++, so it call abort - exactly what you see in your case.
I've checked this behaviour with both Android NDK r10d and CrystaX NDK 10.1 - and it's the same in both cases. I've filed ticket to fix this in CrystaX NDK. For fixing that in Google's NDK, you should also file ticket in Google's NDK bug tracker
UPD: It seems that situation is not so simple... Investigating it further, I've found more details pointing to the fact there is something bit more complicated than I've described above. Looking further; will update answer when have strict results.
UPD2: After deep investigation I've found that my previous answer was completely wrong. In fact, __EXCEPTIONS are defined when building GNU libstdc++, so operator new actually throw bad_alloc if malloc return NULL. The problem is in your code actually, but it was bit tricky to figure out. See explanation below.
TL;DR: operator new return pointer to the "allocated" memory (so from its point of view, there's no reason to throw std::bad_alloc), but first access to that memory cause crash because actually those pages are not available.
More detailed explanation:
Here is complete code I've used for testing:
#include <new>
#include <stdio.h>
#include <string.h>
class Test
{
public:
Test() {
::fprintf(stderr, "ctor start\n");
//memset(c, 0, sizeof(c));
::fprintf(stderr, "ctor finish\n");
}
private:
char c[1024*1024*1024];
};
int main()
{
try {
while (1) {
Test *p = new Test();
if (!p)
return 1;
}
return 1;
} catch (std::bad_alloc) {
return 0;
}
}
If you compile this test and run it on device, you'll get std::bad_alloc on some iteration (I get it on third iteration). But if you uncomment memset in constructor of Test, application will crash on the first memset call. If you remove constructor of Test completely, it will crash too - just because in this case compiler will generate constructor, which do zero-initialization of all members - i.e. the same as we do with memset.
The difference here is that malloc (used internally in operator new) returns pointer to the "allocated" memory, but actually it is not allocated; this region is just marked as "need to be allocated in future, when application will actually refer it". This is how Linux kernel handle it, for performance reasons. On next step, when you (or compiler) fill array with zeros, application actually access those pages but, unfortunately, there's just no free memory in system, so Linux kernel call OOM killer, killing the process as result.
This is not Android-specific. In fact, the same happens on GNU/Linux systems; the only difference is amount of memory available to the system (on Android it much lower than on servers, for obvious reasons).
In order to have working exceptions, you need to build using one of the other C++ standard libraries, other than the default one. Add e.g. APP_STL := gnustl_static to jni/Application.mk. Additionally, you need to enable exceptions, add LOCAL_CPP_FEATURES += exceptions to your Android.mk, or add APP_CPPFLAGS += -fexceptions to jni/Application.mk.

Accessing /dev/input/events0 file through jni in Android 4.2

I need to port an automation tool from Android 2.3 to Android 4.2 based target. I am trying to get some touch events from /dev/input/events0 using open() system call and then use a poll() system call to wait for any changes on its file descriptor.
This works just fine if I write the logic in a C file and run the binary by placing it in system/bin directory. poll method returns and I can read the content using read() method on the descriptor.
I call these methods using JNI in Android 2.3 based target. It works fine, but only if the app is a part of the system image and the library(native code) exists in system/lib directory as a .so file.
But now the problem is, the same code is not running in Android 4.2. The poll() system call never returns, even if I give a lower timeout value.
One important point to note here is, this same behavior was observed when the library existed as a part of the APK file in Android 2.3 and was run as an installed application.
Also currently I have only quick boot build working, no normal boot. APK/ODEX and *.so files is what I have at my disposal.
I am suspecting it is an issue with permissions. Internally android is not giving me access to driver files in 4.2, as application seems to be better sandboxed than it was in 2.3. Ironically, open() works just fine, only when I do poll(), it is not working.
I need to overcome this problem. Please help.
Here is code snippet:-
int i, numread, value, ret, readlen;
struct input_event event;
struct timeval now;
struct timespec tm;
while (run) {
/* wait for input from any of the input devices(/dev/input/events0) */
if (poll(input_fds, NUM_DEVICES , -1) < 0) {
return EVENT_RECORDER_ERROR;
}
__android_log_print(ANDROID_LOG_INFO, "EVENT_RECORD",
"Poll completed");
for (i = 0; i < NUM_DEVICES; i++) {
__android_log_print(ANDROID_LOG_INFO, "EVENT_RECORD",
"device no %d", i);
if (input_fds[i].revents & POLLIN) {
if (input_fds[i].fd == sockfd)
readlen = MAX_DATA_LENGTH;
else
readlen = sizeof(event);
/* read the data here and write it to the output file */
numread = read(input_fds[i].fd, buffer, readlen);
}
}
}

Android ndk-r9 compiler optimization issues

I recently switched to using Android ndk-r9 and am having some difficulty with my app that seems to be related to compiler optimization. I have the following function:
int GetTouchPos(GTouchEvents * pEvents, GPointF * pPos, int * pButton = 0)
{
int count = 0;
GTouchEvent * pEvent;
if (pEvents->GetCount(&count) == GResult_Ok)
{
GDebugLog((GS("GetTouchPos: count = %d"), count));
if (pEvents->GetEvent(0, &pEvent) == GResult_Ok)
{
pEvent->GetTapPos(pPos);
if (pButton)
{
pEvent->GetButton(pButton);
}
pEvent->Release();
}
}
return(count);
}
If I build my project and run it, the call to GDebugLog formats and logs the value of the variable 'count'. When I do this, 'count' is 1 and my app works correctly. However if I comment out the GDebugLog line (and make NO other changes), when I run my app, it no longer works. In the function GTouchEvents::GetCount, I also am logging what it is returning and the value is always correctly '1'. Also, I log the return from the call to the function above (i.e. GetTouchPos). When the GDebugLog line is present, the logged return value is the correct value '1'. However when I comment out the GDebugLog call, the logged return value is a seemingly random number, which looks suspiciously like an uninitialized variable.
Note that this all works with our without the GDebugLog line when I was using r8b. Also note that if I turn optimization off, this code works perfectly using r9 whether the debugging line is present or not. Also note that this behavior only presents itself when compiling for the ARM processor. The version I build for x86 works without problem.
Am I doing something questionable here that is causing the optimizer to generate incorrect code?
Can anyone shed some light on what might be happening?
Thanks.

Categories

Resources