当前位置: 首页 > 工具软件 > xHook > 使用案例 >

libicuuc android fatal http,xhook android10.0监听文件关闭

司空镜
2023-12-01

背景

xhook注册了close方法,但是在android10上,还是无法拦截java层close一个io流

调研FileoutputStream是怎么关闭文件的

FileoutputStream.java

public void close() throws IOException {

synchronized (closeLock) {

if (closed) {

return;

}

closed = true;

}

// Android-added: CloseGuard support.

guard.close();

if (channel != null) {

channel.close();

}

// BEGIN Android-changed: Close handling / notification of blocked threads.

if (isFdOwner) {

IoBridge.closeAndSignalBlockedThreads(fd);

}

// END Android-changed: Close handling / notification of blocked threads.

}

这里用到了IoBridge

closeAndSignalBlockedThreads(fd)代码

public static void closeAndSignalBlockedThreads(FileDescriptor fd) throws IOException {

if (fd == null || !fd.valid()) {

return;

}

int intFd = fd.getInt$();

fd.setInt$(-1);

FileDescriptor oldFd = new FileDescriptor();

oldFd.setInt$(intFd);

AsynchronousCloseMonitor.signalBlockedThreads(oldFd);

try {

Libcore.os.close(oldFd);

} catch (ErrnoException errnoException) {

// TODO: are there any cases in which we should throw?

}

}

这里用到Libcore

Libcore.os.close(oldFd); 代码

public final class Libcore {

private Libcore() { }

/**

* Direct access to syscalls. Code should strongly prefer using {@link #os}

* unless it has a strong reason to bypass the helpful checks/guards that it

* provides.

*/

public static Os rawOs = new Linux();

/**

* Access to syscalls with helpful checks/guards.

*/

public static Os os = new BlockGuardOs(rawOs);

}

libcore.os.Linux 代码

public native void close(FileDescriptor fd) throws ErrnoException;

java层就到此结束,我们可以在openGrok上搜索Linux_close

其实就是调用了close

static void Linux_close(JNIEnv* env, jobject, jobject javaFd) {

// Get the FileDescriptor's 'fd' field and clear it.

// We need to do this before we can throw an IOException (http://b/3222087).

int fd = jniGetFDFromFileDescriptor(env, javaFd);

jniSetFileDescriptorOfFD(env, javaFd, -1);

// Even if close(2) fails with EINTR, the fd will have been closed.

// Using TEMP_FAILURE_RETRY will either lead to EBADF or closing someone else's fd.

// http://lkml.indiana.edu/hypermail/linux/kernel/0509.1/0877.html

throwIfMinusOne(env, "close", close(fd));

}

疑问

那为啥xhook监听不到呢?难道androidQ代码有变?

来看看10.0的代码

static void Linux_close(JNIEnv* env, jobject, jobject javaFd) {

// Get the FileDescriptor's 'fd' field and clear it.

// We need to do this before we can throw an IOException (http://b/3222087).

if (javaFd == nullptr) {

jniThrowNullPointerException(env, "null fd");

return;

}

int fd = jniGetFDFromFileDescriptor(env, javaFd);

jniSetFileDescriptorOfFD(env, javaFd, -1);

#if defined(__BIONIC__)

jlong ownerId = jniGetOwnerIdFromFileDescriptor(env, javaFd);

// Close with bionic's fd ownership tracking (which returns 0 in the case of EINTR).

throwIfMinusOne(env, "close", android_fdsan_close_with_tag(fd, ownerId));

#else

// Even if close(2) fails with EINTR, the fd will have been closed.

// Using TEMP_FAILURE_RETRY will either lead to EBADF or closing someone else's fd.

// http://lkml.indiana.edu/hypermail/linux/kernel/0509.1/0877.html

throwIfMinusOne(env, "close", close(fd));

#endif

}

这里出现了两种可能:android_fdsan_close_with_tag(fd, ownerId) 和 close(fd)

于是hook:android_fdsan_close_with_tag,但是不知道libcore_io_Linux.cpp是哪个so

来看看/Users/seekting/work/projects/tsinghua/libcore/luni/src/main/native/Android.bp

filegroup {

name: "luni_native_srcs",

visibility: [

"//libcore",

],

srcs: [

"ExecStrings.cpp",

"IcuUtilities.cpp",

"JniConstants.cpp",

"JniException.cpp",

"NetworkUtilities.cpp",

"Register.cpp",

"ZipUtilities.cpp",

"android_system_OsConstants.cpp",

"cbigint.cpp",

"java_lang_StringToReal.cpp",

"java_lang_invoke_MethodHandle.cpp",

"java_lang_invoke_VarHandle.cpp",

"java_math_NativeBN.cpp",

"libcore_icu_ICU.cpp",

"libcore_icu_TimeZoneNames.cpp",

"libcore_io_AsynchronousCloseMonitor.cpp",

"libcore_io_Linux.cpp",

"libcore_io_Memory.cpp",

"libcore_util_NativeAllocationRegistry.cpp",

"org_apache_harmony_xml_ExpatParser.cpp",

"sun_misc_Unsafe.cpp",

"valueOf.cpp",

],

}

发现是libjavacore

cc_library_shared {

name: "libjavacore",

visibility: [

"//art/build/apex",

],

apex_available: [

"com.android.art.release",

"com.android.art.debug",

],

defaults: [

"core_native_default_flags",

"core_native_default_libs",

],

srcs: [

":luni_native_srcs",

"dalvik/src/main/native/org_apache_harmony_dalvik_NativeTestTarget.cpp",

],

shared_libs: [

"libandroidio",

"libbase",

"libcrypto",

"libexpat",

"libicuuc",

"libicui18n",

"libnativehelper",

"libz",

],

static_libs: [

"libandroidicuinit",

"libziparchive",

],

target: {

android: {

cflags: [

// -DANDROID_LINK_SHARED_ICU4C to enable access to the full ICU4C.

// See external/icu/android_icu4c/include/uconfig_local.h

// for more information.

"-DANDROID_LINK_SHARED_ICU4C",

],

},

},

}

所以最后只需要xhook加上android_fdsan_close_with_tag的hook就可以了

static int (*original_android_fdsan_close_with_tag)(int fd, uint64_t expected_tag);

int hook_android_fdsan_close_with_tag(int fd, uint64_t expected_tag) {

std::string fileName = read_link(fd);

int ret = original_android_fdsan_close_with_tag(fd, expected_tag);

__android_log_print(ANDROID_LOG_WARN, "seekting",

"hook_android_fdsan_close_with_tag %d fileName=%s", fd, fileName.c_str());

return ret;

}

void hook(){

xhook_register("libjavacore.so", "android_fdsan_close_with_tag", (void *) hook_android_fdsan_close_with_tag, (void **) &original_android_fdsan_close_with_tag);

}

看日志:

2021-02-20 19:05:09.218 26130-26130/com.seekting.xhookdemo I/xhook: hooking android_fdsan_close_with_tag in /apex/com.android.vndk.v30/lib64/libbase.so

2021-02-20 19:05:09.218 26130-26130/com.seekting.xhookdemo I/xhook: found android_fdsan_close_with_tag at symidx: 21 (GNU_HASH UNDEF)

2021-02-20 19:05:09.218 26130-26130/com.seekting.xhookdemo I/xhook: found android_fdsan_close_with_tag at .rela.plt offset: 0x3b648

2021-02-20 19:05:09.219 26130-26130/com.seekting.xhookdemo I/xhook: XH_HK_OK 0x79c10fc648: 0x7c70f80d04 -> 0x79728ebf74 android_fdsan_close_with_tag /apex/com.android.vndk.v30/lib64/libbase.so

2021-02-20 19:05:09.219 26130-26130/com.seekting.xhookdemo I/xhook: found android_fdsan_close_with_tag at .rela.android offset: 0x3b488

2021-02-20 19:05:09.219 26130-26130/com.seekting.xhookdemo I/xhook: XH_HK_OK 0x79c10fc488: 0x7c70f80d04 -> 0x79728ebf74 android_fdsan_close_with_tag /apex/com.android.vndk.v30/lib64/libbase.so

2021-02-20 19:05:09.221 26130-26130/com.seekting.xhookdemo I/xhook: hooking android_fdsan_close_with_tag in /apex/com.android.art/lib64/libopenjdkjvm.so

2021-02-20 19:05:09.224 26130-26130/com.seekting.xhookdemo I/xhook: hooking android_fdsan_close_with_tag in /apex/com.android.art/lib64/libopenjdk.so

2021-02-20 19:05:09.225 26130-26130/com.seekting.xhookdemo I/xhook: hooking android_fdsan_close_with_tag in /apex/com.android.art/lib64/libjavacore.so

2021-02-20 19:05:09.225 26130-26130/com.seekting.xhookdemo I/xhook: found android_fdsan_close_with_tag at symidx: 171 (GNU_HASH UNDEF)

2021-02-20 19:05:09.225 26130-26130/com.seekting.xhookdemo I/xhook: found android_fdsan_close_with_tag at .rela.plt offset: 0x389a8

2021-02-20 19:05:09.226 26130-26130/com.seekting.xhookdemo I/xhook: XH_HK_OK 0x79d48789a8: 0x7c70f80d04 -> 0x79728ebf74 android_fdsan_close_with_tag /apex/com.android.art/lib64/libjavacore.so

2021-02-20 19:05:09.226 26130-26130/com.seekting.xhookdemo I/xhook: found android_fdsan_close_with_tag at .rela.android offset: 0x382c8

2021-02-20 19:05:09.227 26130-26130/com.seekting.xhookdemo I/xhook: XH_HK_OK 0x79d48782c8: 0x7c70f80d04 -> 0x79728ebf74 android_fdsan_close_with_tag /apex/com.android.art/lib64/libjavacore.so

2021-02-20 19:05:09.230 26130-26130/com.seekting.xhookdemo I/xhook: hooking android_fdsan_close_with_tag in /apex/com.android.art/lib64/libart.so

2021-02-20 19:05:09.230 26130-26130/com.seekting.xhookdemo I/xhook: found android_fdsan_close_with_tag at symidx: 252 (GNU_HASH UNDEF)

2021-02-20 19:05:09.230 26130-26130/com.seekting.xhookdemo I/xhook: found android_fdsan_close_with_tag at .rela.plt offset: 0x6a4bb0

2021-02-20 19:05:09.231 26130-26130/com.seekting.xhookdemo I/xhook: XH_HK_OK 0x79dceaebb0: 0x7c70f80d04 -> 0x79728ebf74 android_fdsan_close_with_tag /apex/com.android.art/lib64/libart.so

2021-02-20 19:05:09.231 26130-26130/com.seekting.xhookdemo I/xhook: found android_fdsan_close_with_tag at .rela.android offset: 0x6a3c70

2021-02-20 19:05:09.232 26130-26130/com.seekting.xhookdemo I/xhook: XH_HK_OK 0x79dceadc70: 0x7c70f80d04 -> 0x79728ebf74 android_fdsan_close_with_tag /apex/com.android.art/lib64/libart.so

2021-02-20 19:05:09.236 26130-26130/com.seekting.xhookdemo I/xhook: hooking android_fdsan_close_with_tag in /system/lib64/libbase.so

2021-02-20 19:05:09.236 26130-26130/com.seekting.xhookdemo I/xhook: found android_fdsan_close_with_tag at symidx: 21 (GNU_HASH UNDEF)

2021-02-20 19:05:09.236 26130-26130/com.seekting.xhookdemo I/xhook: found android_fdsan_close_with_tag at .rela.plt offset: 0x3b648

2021-02-20 19:05:09.237 26130-26130/com.seekting.xhookdemo I/xhook: XH_HK_OK 0x7c6db7c648: 0x7c70f80d04 -> 0x79728ebf74 android_fdsan_close_with_tag /system/lib64/libbase.so

2021-02-20 19:05:09.237 26130-26130/com.seekting.xhookdemo I/xhook: found android_fdsan_close_with_tag at .rela.android offset: 0x3b488

2021-02-20 19:05:09.238 26130-26130/com.seekting.xhookdemo I/xhook: XH_HK_OK 0x7c6db7c488: 0x7c70f80d04 -> 0x79728ebf74 android_fdsan_close_with_tag /system/lib64/libbase.so

2021-02-20 19:05:09.249 26130-26130/com.seekting.xhookdemo I/xhook: hooking android_fdsan_close_with_tag in /apex/com.android.runtime/lib64/bionic/libc.so

2021-02-20 19:05:09.249 26130-26130/com.seekting.xhookdemo I/xhook: found android_fdsan_close_with_tag at symidx: 381 (GNU_HASH DEF)

2021-02-20 19:05:09.249 26130-26130/com.seekting.xhookdemo I/xhook: found android_fdsan_close_with_tag at .rela.plt offset: 0xb8f48

2021-02-20 19:05:09.251 26130-26130/com.seekting.xhookdemo I/xhook: XH_HK_OK 0x7c70fe7f48: 0x7c70f80d04 -> 0x79728ebf74 android_fdsan_close_with_tag /apex/com.android.runtime/lib64/bionic/libc.so

2021-02-20 19:05:09.262 26130-26130/com.seekting.xhookdemo I/xhook: hooking android_fdsan_close_with_tag in /apex/com.android.art/lib64/libartbase.so

2021-02-20 19:05:09.262 26130-26130/com.seekting.xhookdemo I/xhook: found android_fdsan_close_with_tag at symidx: 86 (GNU_HASH UNDEF)

2021-02-20 19:05:09.262 26130-26130/com.seekting.xhookdemo I/xhook: found android_fdsan_close_with_tag at .rela.plt offset: 0x70eb8

2021-02-20 19:05:09.265 26130-26130/com.seekting.xhookdemo I/xhook: XH_HK_OK 0x7c72171eb8: 0x7c70f80d04 -> 0x79728ebf74 android_fdsan_close_with_tag /apex/com.android.art/lib64/libartbase.so

2021-02-20 19:05:09.265 26130-26130/com.seekting.xhookdemo I/xhook: found android_fdsan_close_with_tag at .rela.android offset: 0x70b30

2021-02-20 19:05:09.269 26130-26130/com.seekting.xhookdemo I/xhook: XH_HK_OK 0x7c72171b30: 0x7c70f80d04 -> 0x79728ebf74 android_fdsan_close_with_tag /apex/com.android.art/lib64/libartbase.so

扩展

看看android_fdsan_close_with_tag底层实现

前提要android10源码

/Users/seekting/work/projects/tsinghua/bionic/libc/bionic/fdsan.cpp

int android_fdsan_close_with_tag(int fd, uint64_t expected_tag) {

FdEntry* fde = GetFdEntry(fd);

if (!fde) {

return ___close(fd);

}

uint64_t tag = expected_tag;

if (!atomic_compare_exchange_strong(&fde->close_tag, &tag, 0)) {

const char* expected_type = android_fdsan_get_tag_type(expected_tag);

uint64_t expected_owner = android_fdsan_get_tag_value(expected_tag);

const char* actual_type = android_fdsan_get_tag_type(tag);

uint64_t actual_owner = android_fdsan_get_tag_value(tag);

if (expected_tag && tag) {

fdsan_error(

"attempted to close file descriptor %d, "

"expected to be owned by %s 0x%" PRIx64 ", actually owned by %s 0x%" PRIx64,

fd, expected_type, expected_owner, actual_type, actual_owner);

} else if (expected_tag && !tag) {

fdsan_error(

"attempted to close file descriptor %d, "

"expected to be owned by %s 0x%" PRIx64 ", actually unowned",

fd, expected_type, expected_owner);

} else if (!expected_tag && tag) {

fdsan_error(

"attempted to close file descriptor %d, "

"expected to be unowned, actually owned by %s 0x%" PRIx64,

fd, actual_type, actual_owner);

} else if (!expected_tag && !tag) {

// This should never happen: our CAS failed, but expected == actual?

async_safe_fatal("fdsan atomic_compare_exchange_strong failed unexpectedly while closing");

}

}

int rc = ___close(fd);

// If we were expecting to close with a tag, abort on EBADF.

if (expected_tag && rc == -1 && errno == EBADF) {

fdsan_error("double-close of file descriptor %d detected", fd);

}

return rc;

}

___close在哪里申明了,但是这个方法无法hook不知道为啥

android_fdsan_close_with_tag是什么机制

fdsan是File descriptor sanitizer的缩写

Android 10引入了fdsan(文件描述符清理程序)。 fdsan可检测到文件描述符所有权的不当处理,例如使用后关闭和两次关闭。 fdsan的默认模式在Android 11中更改。fdsan现在在检测到错误时中止;以前的行为是记录警告并继续。如果您在应用程序中看到由于fdsan导致的崩溃,请参阅fdsan文档。

参考:

 类似资料: