[ FAILED ] unistd_nofortify.exec_argv0_null
[ FAILED ] unistd.exec_argv0_null
这两个原因类似。
在我的环境里添加 run-as 后就好了,但是 目前这两个cases 在我的环境里是好的,在 RVI 的环境里不行,可能哪里的微小差异导致,还有待研究!
分析如下:
TEST(UNISTD_TEST, exec_argv0_null) {
// http://b/33276926
char* args[] = {nullptr};
char* envs[] = {nullptr};
ASSERT_EXIT(execve("/system/bin/run-as", args, envs), testing::ExitedWithCode(1),
"<unknown>: usage: run-as");
}
这个 case 依赖于 rootfs 中存在一个 /system/bin/run-as
,而且注意这个文件是一个 so,不是 executable。
参考 system/core/run-as/run-as.cpp
int main(int argc, char* argv[]) {
// Check arguments.
if (argc < 2) {
error(1, 0, "usage: run-as <package-name> [--user <uid>] <command> [<args>]\n");
}
......
exec_argv0_null 测试中应该走这个地方并调用 error()
参考 bionic/libc/bionic/error.cpp
中的 error()
函数,
目前出现的问题是我们期望 __error_head()
应该调用 getprogname()
打印 <unknown>
, 可是现在不是,而是一个 空 ""
Expected: contains regular expression "<unknown>: usage: run-as"
Actual msg:
[ DEATH ] : usage: run-as <package-name> [--user <uid>] <command> [<args>]
所以需要检查为啥 getprogname()
里返回的 __progname
不对。
这个值的设置在 bionic/libc/upstream-openbsd/lib/libc/gen/setprogname.c
void
setprogname(const char *progname)
{
char *tmpn;
tmpn = strrchr(progname, '/');
if (tmpn == NULL)
__progname = (char *)progname;
else
__progname = tmpn + 1;
}
具体调用只有一处:bionic/libc/bionic/libc_init_common.cpp
void __libc_init_common() {
......
setprogname(__libc_shared_globals()->init_progname ?: "<unknown>");
......
如果 argv[0] 为 null, 即 init_progname 为 null,则 __progname
就会被设置为 <unknown>
, 可是从实际返回值来看,这个似乎没有被设置上。需要在 emulator 里 printf 一下。目前跟踪打印的结果是在 emulator 上 args.argv[0]
不是 nullptr,而是一个 "",也就是说当我们强制设置 argv[0]
为 NULL 时,__libc_shared_globals()->init_progname
并没有被设置为 NULL。
而 init_progname 这个变量被赋值的地方有两处,
bionic/libc/bionic/libc_init_static.cpp
, 在静态链接程序的初始化中设置bionic/linker/linker_main.cpp
,动态链接的程序加载 linker 中设置__libc_init_common() -> setprogname()
完成对 __progname
的设置。因为 run-as 这个程序是动态链接的,所以走的是第二个路径。
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。
测试发现和内核版本处理有关,在我们的 qemu 上测试用的是我们自己的内核,而在 RVI 的 emulator 环境下用的是 RVI 的内核,在我们的环境里换成 RVI 的内核就会复现我们的问题.
仔细对比内核版本发现: pass 的内核版本是 5.10.43,fail 的内核版本是 5.10.110
而在 5.10.110 中 fs/exec.c
中 do_execveat_common()
中增加了如下一段代码:
/*
* When argv is empty, add an empty string ("") as argv[0] to
* ensure confused userspace programs that start processing
* from argv[1] won't end up walking envp. See also
* bprm_stack_limits().
*/
if (bprm->argc == 0) {
retval = copy_string_kernel("", bprm);
if (retval < 0)
goto out_free;
bprm->argc = 1;
}
也就是说目前的内核中如果应用传进来的 argv 是空的,内核会默认添加一个 argv[0] = ""
所以如果我们采用较新的内核测试这个 case 是过不了的
检查了一下这部分内容在 5.18 时被正式合入主线分支。
fixed, please refer to https://github.com/riscv-android-src/platform-bionic/pull/32
登录 后才可以发表评论