Re: [PATCH] selftests/proc: Add support for vsyscall=xonly

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



ping?

On Sat,  6 Aug 2022 22:57:49 +0900, Shigeru Yoshida wrote:
> There are 3 vsyscall modes: emulate, xonly, and none.  proc-pid-vm
> detects the existence of the vsyscall with memory load on the vsyscall
> page.
> 
> This works for emulate and none vsyscall modes, but fails for xonly
> because read permission is omitted with xonly vsyscall page, and it
> results in the following error:
> 
>   # ./proc-pid-vm
>   proc-pid-vm: proc-pid-vm.c:328: main: Assertion `rv == len' failed.
>   Aborted (core dumped)
> 
> This patch fixes this issue with introducing the following rule:
> 
>   1. vsyscall mode is emulate if it can load memory
>   2. vsyscall mode is xonly if it can call gettimeofday() on vsyscall
>   3. vsyscall mode is node otherwise
> 
> Signed-off-by: Shigeru Yoshida <syoshida@xxxxxxxxxx>
> ---
>  tools/testing/selftests/proc/proc-pid-vm.c | 77 ++++++++++++++++++----
>  1 file changed, 65 insertions(+), 12 deletions(-)
> 
> diff --git a/tools/testing/selftests/proc/proc-pid-vm.c b/tools/testing/selftests/proc/proc-pid-vm.c
> index 28604c9f805c..dffd263beef3 100644
> --- a/tools/testing/selftests/proc/proc-pid-vm.c
> +++ b/tools/testing/selftests/proc/proc-pid-vm.c
> @@ -211,10 +211,16 @@ static int make_exe(const uint8_t *payload, size_t len)
>  }
>  #endif
>  
> -static bool g_vsyscall = false;
> -
> -static const char str_vsyscall[] =
> -"ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]\n";
> +static enum { EMULATE, XONLY, NONE } g_vsyscall_mode;
> +
> +static const char * const str_vsyscall[] = {
> +	/* emulate */
> +	"ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]\n",
> +	/* xonly */
> +	"ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0                  [vsyscall]\n",
> +	/* none */
> +	"",
> +};
>  
>  #ifdef __x86_64__
>  static void sigaction_SIGSEGV(int _, siginfo_t *__, void *___)
> @@ -225,7 +231,33 @@ static void sigaction_SIGSEGV(int _, siginfo_t *__, void *___)
>  /*
>   * vsyscall page can't be unmapped, probe it with memory load.
>   */
> -static void vsyscall(void)
> +static bool vsyscall_emulate(void)
> +{
> +	*(volatile int *)0xffffffffff600000UL;
> +	return true;
> +}
> +
> +/*
> + * vsyscall page can't be unmapped, probe it with calling gettimeofday().
> + */
> +static bool vsyscall_xonly(void)
> +{
> +	int ret;
> +	struct timeval tv;
> +	int (*f)(struct timeval *tv, struct timezone *tz);
> +
> +	/* Try to call gettimeofday() on vsyscall*/
> +	f = (void *)0xffffffffff600000UL;
> +	ret = f(&tv, NULL);
> +	if (ret < 0) {
> +		fprintf(stderr, "gettimeofday() on vsyscall, ret %d\n", ret);
> +		return false;
> +	}
> +
> +	return true;
> +}
> +
> +static bool vsyscall_test(bool (*test)(void))
>  {
>  	pid_t pid;
>  	int wstatus;
> @@ -246,13 +278,27 @@ static void vsyscall(void)
>  		act.sa_sigaction = sigaction_SIGSEGV;
>  		(void)sigaction(SIGSEGV, &act, NULL);
>  
> -		*(volatile int *)0xffffffffff600000UL;
> +		if (!test())
> +			exit(1);
> +
>  		exit(0);
>  	}
>  	waitpid(pid, &wstatus, 0);
>  	if (WIFEXITED(wstatus) && WEXITSTATUS(wstatus) == 0) {
> -		g_vsyscall = true;
> +		return true;
>  	}
> +
> +	return false;
> +}
> +
> +static void vsyscall(void)
> +{
> +	if (vsyscall_test(vsyscall_emulate))
> +		g_vsyscall_mode = EMULATE;
> +	else if (vsyscall_test(vsyscall_xonly))
> +		g_vsyscall_mode = XONLY;
> +	else
> +		g_vsyscall_mode = NONE;
>  }
>  
>  int main(void)
> @@ -314,11 +360,14 @@ int main(void)
>  
>  	/* Test /proc/$PID/maps */
>  	{
> -		const size_t len = strlen(buf0) + (g_vsyscall ? strlen(str_vsyscall) : 0);
> +		size_t len = strlen(buf0);
>  		char buf[256];
>  		ssize_t rv;
>  		int fd;
>  
> +		if (g_vsyscall_mode != NONE)
> +			len += strlen(str_vsyscall[g_vsyscall_mode]);
> +
>  		snprintf(buf, sizeof(buf), "/proc/%u/maps", pid);
>  		fd = open(buf, O_RDONLY);
>  		if (fd == -1) {
> @@ -327,8 +376,10 @@ int main(void)
>  		rv = read(fd, buf, sizeof(buf));
>  		assert(rv == len);
>  		assert(memcmp(buf, buf0, strlen(buf0)) == 0);
> -		if (g_vsyscall) {
> -			assert(memcmp(buf + strlen(buf0), str_vsyscall, strlen(str_vsyscall)) == 0);
> +		if (g_vsyscall_mode != NONE) {
> +			assert(memcmp(buf + strlen(buf0),
> +				      str_vsyscall[g_vsyscall_mode],
> +				      strlen(str_vsyscall[g_vsyscall_mode])) == 0);
>  		}
>  	}
>  
> @@ -374,8 +425,10 @@ int main(void)
>  			assert(memmem(buf, rv, S[i], strlen(S[i])));
>  		}
>  
> -		if (g_vsyscall) {
> -			assert(memmem(buf, rv, str_vsyscall, strlen(str_vsyscall)));
> +		if (g_vsyscall_mode != NONE) {
> +			assert(memmem(buf, rv,
> +				      str_vsyscall[g_vsyscall_mode],
> +				      strlen(str_vsyscall[g_vsyscall_mode])));
>  		}
>  	}
>  
> -- 
> 2.37.1
> 




[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [NTFS 3]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [NTFS 3]     [Samba]     [Device Mapper]     [CEPH Development]

  Powered by Linux