mirror of https://github.com/xemu-project/xemu.git
linux-user: handle /proc/$$ like /proc/self
Some applications use /proc/$$/... (where $$ is the own pid) instead of /proc/self/... to refer to their own proc files. Extend the interception for open and readlink to handle this case. Also, do the same interception in readlinkat. Signed-off-by: Andreas Schwab <schwab@suse.de> Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
parent
ab8bf29078
commit
463d8e7393
|
@ -4973,6 +4973,30 @@ static int open_self_auxv(void *cpu_env, int fd)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int is_proc_myself(const char *filename, const char *entry)
|
||||||
|
{
|
||||||
|
if (!strncmp(filename, "/proc/", strlen("/proc/"))) {
|
||||||
|
filename += strlen("/proc/");
|
||||||
|
if (!strncmp(filename, "self/", strlen("self/"))) {
|
||||||
|
filename += strlen("self/");
|
||||||
|
} else if (*filename >= '1' && *filename <= '9') {
|
||||||
|
char myself[80];
|
||||||
|
snprintf(myself, sizeof(myself), "%d/", getpid());
|
||||||
|
if (!strncmp(filename, myself, strlen(myself))) {
|
||||||
|
filename += strlen(myself);
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (!strcmp(filename, entry)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int do_open(void *cpu_env, const char *pathname, int flags, mode_t mode)
|
static int do_open(void *cpu_env, const char *pathname, int flags, mode_t mode)
|
||||||
{
|
{
|
||||||
struct fake_open {
|
struct fake_open {
|
||||||
|
@ -4981,15 +5005,14 @@ static int do_open(void *cpu_env, const char *pathname, int flags, mode_t mode)
|
||||||
};
|
};
|
||||||
const struct fake_open *fake_open;
|
const struct fake_open *fake_open;
|
||||||
static const struct fake_open fakes[] = {
|
static const struct fake_open fakes[] = {
|
||||||
{ "/proc/self/maps", open_self_maps },
|
{ "maps", open_self_maps },
|
||||||
{ "/proc/self/stat", open_self_stat },
|
{ "stat", open_self_stat },
|
||||||
{ "/proc/self/auxv", open_self_auxv },
|
{ "auxv", open_self_auxv },
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
for (fake_open = fakes; fake_open->filename; fake_open++) {
|
for (fake_open = fakes; fake_open->filename; fake_open++) {
|
||||||
if (!strncmp(pathname, fake_open->filename,
|
if (is_proc_myself(pathname, fake_open->filename)) {
|
||||||
strlen(fake_open->filename))) {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6262,20 +6285,18 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||||
#endif
|
#endif
|
||||||
case TARGET_NR_readlink:
|
case TARGET_NR_readlink:
|
||||||
{
|
{
|
||||||
void *p2, *temp;
|
void *p2;
|
||||||
p = lock_user_string(arg1);
|
p = lock_user_string(arg1);
|
||||||
p2 = lock_user(VERIFY_WRITE, arg2, arg3, 0);
|
p2 = lock_user(VERIFY_WRITE, arg2, arg3, 0);
|
||||||
if (!p || !p2)
|
if (!p || !p2) {
|
||||||
ret = -TARGET_EFAULT;
|
ret = -TARGET_EFAULT;
|
||||||
else {
|
} else if (is_proc_myself((const char *)p, "exe")) {
|
||||||
if (strncmp((const char *)p, "/proc/self/exe", 14) == 0) {
|
char real[PATH_MAX], *temp;
|
||||||
char real[PATH_MAX];
|
temp = realpath(exec_path, real);
|
||||||
temp = realpath(exec_path,real);
|
ret = temp == NULL ? get_errno(-1) : strlen(real) ;
|
||||||
ret = (temp==NULL) ? get_errno(-1) : strlen(real) ;
|
snprintf((char *)p2, arg3, "%s", real);
|
||||||
snprintf((char *)p2, arg3, "%s", real);
|
} else {
|
||||||
}
|
ret = get_errno(readlink(path(p), p2, arg3));
|
||||||
else
|
|
||||||
ret = get_errno(readlink(path(p), p2, arg3));
|
|
||||||
}
|
}
|
||||||
unlock_user(p2, arg2, ret);
|
unlock_user(p2, arg2, ret);
|
||||||
unlock_user(p, arg1, 0);
|
unlock_user(p, arg1, 0);
|
||||||
|
@ -6287,10 +6308,16 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||||
void *p2;
|
void *p2;
|
||||||
p = lock_user_string(arg2);
|
p = lock_user_string(arg2);
|
||||||
p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0);
|
p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0);
|
||||||
if (!p || !p2)
|
if (!p || !p2) {
|
||||||
ret = -TARGET_EFAULT;
|
ret = -TARGET_EFAULT;
|
||||||
else
|
} else if (is_proc_myself((const char *)p, "exe")) {
|
||||||
|
char real[PATH_MAX], *temp;
|
||||||
|
temp = realpath(exec_path, real);
|
||||||
|
ret = temp == NULL ? get_errno(-1) : strlen(real) ;
|
||||||
|
snprintf((char *)p2, arg4, "%s", real);
|
||||||
|
} else {
|
||||||
ret = get_errno(readlinkat(arg1, path(p), p2, arg4));
|
ret = get_errno(readlinkat(arg1, path(p), p2, arg4));
|
||||||
|
}
|
||||||
unlock_user(p2, arg3, ret);
|
unlock_user(p2, arg3, ret);
|
||||||
unlock_user(p, arg2, 0);
|
unlock_user(p, arg2, 0);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue