1414#include <sys/auxv.h>
1515#include <sys/mman.h>
1616#include <sys/shm.h>
17+ #include <sys/ptrace.h>
1718#include <sys/syscall.h>
1819#include <sys/wait.h>
20+ #include <sys/uio.h>
1921
2022#include "../kselftest.h" /* For __cpuid_count() */
2123
@@ -583,6 +585,13 @@ static void test_dynamic_state(void)
583585 _exit (0 );
584586}
585587
588+ static inline int __compare_tiledata_state (struct xsave_buffer * xbuf1 , struct xsave_buffer * xbuf2 )
589+ {
590+ return memcmp (& xbuf1 -> bytes [xtiledata .xbuf_offset ],
591+ & xbuf2 -> bytes [xtiledata .xbuf_offset ],
592+ xtiledata .size );
593+ }
594+
586595/*
587596 * Save current register state and compare it to @xbuf1.'
588597 *
@@ -599,9 +608,7 @@ static inline bool __validate_tiledata_regs(struct xsave_buffer *xbuf1)
599608 fatal_error ("failed to allocate XSAVE buffer\n" );
600609
601610 xsave (xbuf2 , XFEATURE_MASK_XTILEDATA );
602- ret = memcmp (& xbuf1 -> bytes [xtiledata .xbuf_offset ],
603- & xbuf2 -> bytes [xtiledata .xbuf_offset ],
604- xtiledata .size );
611+ ret = __compare_tiledata_state (xbuf1 , xbuf2 );
605612
606613 free (xbuf2 );
607614
@@ -826,6 +833,99 @@ static void test_context_switch(void)
826833 free (finfo );
827834}
828835
836+ /* Ptrace test */
837+
838+ /*
839+ * Make sure the ptracee has the expanded kernel buffer on the first
840+ * use. Then, initialize the state before performing the state
841+ * injection from the ptracer.
842+ */
843+ static inline void ptracee_firstuse_tiledata (void )
844+ {
845+ load_rand_tiledata (stashed_xsave );
846+ init_xtiledata ();
847+ }
848+
849+ /*
850+ * Ptracer injects the randomized tile data state. It also reads
851+ * before and after that, which will execute the kernel's state copy
852+ * functions. So, the tester is advised to double-check any emitted
853+ * kernel messages.
854+ */
855+ static void ptracer_inject_tiledata (pid_t target )
856+ {
857+ struct xsave_buffer * xbuf ;
858+ struct iovec iov ;
859+
860+ xbuf = alloc_xbuf ();
861+ if (!xbuf )
862+ fatal_error ("unable to allocate XSAVE buffer" );
863+
864+ printf ("\tRead the init'ed tiledata via ptrace().\n" );
865+
866+ iov .iov_base = xbuf ;
867+ iov .iov_len = xbuf_size ;
868+
869+ memset (stashed_xsave , 0 , xbuf_size );
870+
871+ if (ptrace (PTRACE_GETREGSET , target , (uint32_t )NT_X86_XSTATE , & iov ))
872+ fatal_error ("PTRACE_GETREGSET" );
873+
874+ if (!__compare_tiledata_state (stashed_xsave , xbuf ))
875+ printf ("[OK]\tThe init'ed tiledata was read from ptracee.\n" );
876+ else
877+ printf ("[FAIL]\tThe init'ed tiledata was not read from ptracee.\n" );
878+
879+ printf ("\tInject tiledata via ptrace().\n" );
880+
881+ load_rand_tiledata (xbuf );
882+
883+ memcpy (& stashed_xsave -> bytes [xtiledata .xbuf_offset ],
884+ & xbuf -> bytes [xtiledata .xbuf_offset ],
885+ xtiledata .size );
886+
887+ if (ptrace (PTRACE_SETREGSET , target , (uint32_t )NT_X86_XSTATE , & iov ))
888+ fatal_error ("PTRACE_SETREGSET" );
889+
890+ if (ptrace (PTRACE_GETREGSET , target , (uint32_t )NT_X86_XSTATE , & iov ))
891+ fatal_error ("PTRACE_GETREGSET" );
892+
893+ if (!__compare_tiledata_state (stashed_xsave , xbuf ))
894+ printf ("[OK]\tTiledata was correctly written to ptracee.\n" );
895+ else
896+ printf ("[FAIL]\tTiledata was not correctly written to ptracee.\n" );
897+ }
898+
899+ static void test_ptrace (void )
900+ {
901+ pid_t child ;
902+ int status ;
903+
904+ child = fork ();
905+ if (child < 0 ) {
906+ err (1 , "fork" );
907+ } else if (!child ) {
908+ if (ptrace (PTRACE_TRACEME , 0 , NULL , NULL ))
909+ err (1 , "PTRACE_TRACEME" );
910+
911+ ptracee_firstuse_tiledata ();
912+
913+ raise (SIGTRAP );
914+ _exit (0 );
915+ }
916+
917+ do {
918+ wait (& status );
919+ } while (WSTOPSIG (status ) != SIGTRAP );
920+
921+ ptracer_inject_tiledata (child );
922+
923+ ptrace (PTRACE_DETACH , child , NULL , NULL );
924+ wait (& status );
925+ if (!WIFEXITED (status ) || WEXITSTATUS (status ))
926+ err (1 , "ptrace test" );
927+ }
928+
829929int main (void )
830930{
831931 /* Check hardware availability at first */
@@ -846,6 +946,8 @@ int main(void)
846946 ctxtswtest_config .num_threads = 5 ;
847947 test_context_switch ();
848948
949+ test_ptrace ();
950+
849951 clearhandler (SIGILL );
850952 free_stashed_xsave ();
851953
0 commit comments