LinuxÄÚºËAF_VSOCKÌ×½Ó×ÖǰÌᾺÕù·ì϶£¨CVE-2021-26708£©·ÖÎö

°ä²¼¹¦·ò 2021-03-10

·ì϶²¼¾°


½üÆÚ £¬¹ú±í°²È«×êÑÐÈËÔ±ÔÚoss-securityÉÏÅû¶ÁËÒ»¸öAF_VSOCKÌ×½Ó×ÖǰÌᾺÕù¸ßΣ·ì϶CVE-2021-26708£¨CNVD-2021-10822¡¢CNNVD-202102-529£©¡£Æ¾¾ÝÅû¶ϸ½Ú £¬¸Ã·ì϶ÊÇÓÉÓÚÃýÎó¼ÓËøµ¼Ö £¬Äܹ»ÔÚµÍȨÏÞÏ´¥·¢²¢×Ô¶¯¼ÓÔØÒ×Êܹ¥»÷Çý¶¯Ä£¿é´´½¨AF_VSOCKÌ×½Ó×Ö £¬½ø¶øµ¼Ö±¾µØÈ¨ÏÞÌáÉý¡£¸Ã·ì϶²¹¶¡ÒѾ­¹é²¢µ½LinuxÄÚºËÖ÷ÏßÖС£


VSOCK½éÉܺͼܹ¹


VSOCK½éÉÜ


VMÌ×½Ó×Ö×îÔçÊÇÓÉVmware¿ª·¢²¢Ìá½»µ½LinuxÄÚºËÖ÷ÏßÖС£VMÌ×½Ó×ÖÔÊÐíÐé¹¹»úÓëÐé¹¹»úÖÎÀí·¨Ê½Ö®¼ä½øÐÐͨѶ¡£Ðé¹¹»úºÍÖ÷»úÉϵÄÓû§¼¶ÀûÓ÷¨Ê½¶¼Äܹ»Ê¹ÓÃVM Ì×½Ó×ÖAPI £¬´Ó¶øÍƽøguestÐé¹¹»úÓëÆähostÖ®¼äµÄ¼±¾çÓÐЧͨѶ¡£¸Ã»úÔìÌṩÁËÒ»¸övsockÌ×½Ó×ÖµØÖ·ÏµÁм°Æävmci´«Êä £¬Ö¼ÔÚÓë½Ó¿Ú¼¶´ËÍâUDPºÍTCP¼æÈÝ¡£VSOCK»úÔìËæ¼´µÃµ½LinuxÉçÇøµÄÏìÓ¦ £¬RedhatÔÚVSOCKÖÐΪvsockÔö³¤ÁËvirtio´«Êä £¬QEMU/KVMÐé¹¹»úÖÎÀíÌṩ֧³Ö £¬MicrosoftÔö³¤ÁËHyperV´«Êä¡£


VSOCK¼Ü¹¹


VMÌ×½Ó×ÖÓëÆäËûÌ×½Ó×ÖÀàÐÍÀàËÆ £¬ÀýÈçBerkeley UNIXÌ×½Ó×Ö½Ó¿Ú¡£VMÌ×½Ó×ÖÄ£¿éÖ§³ÖÃæÏòÏνӵÄÁ÷Ì×½Ó×Ö£¨ÀýÈçTCP£©ºÍÎÞÏνÓÊý¾Ý±¨Ì×½Ó×Ö£¨ÀýÈçUDP£©¡£VMÌ×½Ó×ÖºÍ̸ϵÁнç˵Ϊ¡°AF_VSOCK¡± £¬²¢ÇÒÌ×½Ó×Ö²Ù×÷·ÖΪSOCK_DGRAMºÍSOCK_STREAM¡£ÈçÏÂͼËùʾ£º


1.png


VSOCKÖ§³Ösocket API¡£AF_SOCKµØÖ·´ØÔ̺¬Á½¸öÉí·Ö£ºCIDºÍport¡£CIDΪContextIdentifier £¬¸ßµÍÎıêʶ·û  £»portΪ¶Ë¿Ú¡£TCP/IPÀûÓ÷¨Ê½ÏÕЩ²»±ØÒª¸ü¸Ä¾ÍÄܹ»ÊÊÅä £¬Ã¿Ò»¸öµØÖ·°µÊ¾Îª¡  £»¹ÓÐÒ»²ãΪtransport £¬VSOCK transportÓÃÓÚʵÏÖguestºÍhostÖ®¼äͨѶµÄÊý¾Ýͨ·¡£ÈçÏÂͼËùʾ£º


2.png


Transportƾ¾Ý´«Êä·½Ïò·ÖΪÁ½ÖÖ£¨ÒÔSOCK_STREAMÀàÐÍΪÀý£© £¬Ò»ÖÖΪG2H transport £¬°µÊ¾guestµ½hostµÄ´«ÊäÀàÐÍ £¬ÔËÐÐÔÚguestÖС£ÁíÒ»ÖÖΪH2G transport £¬°µÊ¾hostµ½guestµÄ´«ÊäÀàÐÍ¡£ÒÔQEMU/KVM´«ÊäΪÀý £¬ÈçÏÂͼËùʾ£º


3.png


¸Ã´«ÊäÌṩÌ×½Ó×Ö²ã½Ó¿ÚµÄÇý¶¯·ÖΪÁ½¸ö²¿ÃÅ£ºÒ»¸öÊÇÔËÐÐÔÚguestÖеÄvirtio-transport £¬ÓÃÓÚ¹²Í¬guest½øÐÐÊý¾Ý´«Êä  £»ÁíÒ»¸öÊÇÔËÐÐÔÚhostÖеÄvhost-transport £¬ÓÃÓÚ¹²Í¬host½øÐÐÊý¾Ý´«Êä¡£VSOCK transport»¹Ìṩ¶à´«Êäͨ·ģʽ £¬¸ÃÖ°ÄÜÊÇΪÁËÖ§³ÖǶÌ×Ðé¹¹»úÖеÄVSOCKÖ°ÄÜ¡£ÈçÏÂͼËùʾ£º


4.png


Ö§³ÖL1Ðé¹¹»úͬʱ¼ÓÔØH2GºÍG2HÁ½¸ö´«Êäͨ· £¬´ËʱL1Ðé¹¹»ú¼´ÊÇhostÒ²ÊÇguest £¬Í¨¹ýH2G´«Êäͨ·ºÍL2ǶÌ×Ðé¹¹»úͨѶ £¬Í¨¹ýG2H´«Êäͨ·ºÍL0 hostͨѶ¡£VSOCK transport»¹Ö§³Ö±¾µØ»·»Ø´«Êäͨ·ģʽ £¬²»±ØÒªÓÐÐé¹¹»ú¡£ÈçÏÂͼËùʾ£º


5.png


¸ÃģʽÓÃÓÚ²âÊԺ͵÷ÊÔ £¬ÓÉvsock-loopbackÌṩ֧³Ö £¬²¢¶ÔµØÖ·´ØÖеÄCID½øÐÐÁË·ÖÀà £¬Ô̺¬Á½ÖÖÀàÐÍ£ºÒ»ÖÖÊÇVMADDR_CID_LOCAL £¬°µÊ¾±¾µØ»·»Ø  £»Ò»ÖÖΪVMADDR_CID_HOST £¬°µÊ¾H2G´«Êäͨ·¼ÓÔØ £¬G2H´«Êäͨ·δ¼ÓÔØ¡£

 

·ì϶·ÖÎöÓë´¥·¢¹ý³Ì


·ì϶·ÖÎö


¸Ã·ì϶´¥·¢Ô­ÒòÊÇÃýÎó¼ÓËøµ¼ÖÂǰÌᾺÕù £¬Æ¾¾Ý²¹¶¡¿ÉÖª £¬´æÔÚ¶à´¦ÃýÎó¼ÓËø £¬ÕâÀïÒÔvsock_stream_setsockopt()º¯Êý²¹¶¡ÎªÀý £¬ÈçÏÂͼËùʾ£º


6.png


²¹¶¡ºÜ¼ò½à £¬½«µÚ1564ÐдúÂëÒÆ¶¯µ½µÚ1571ÐÐ £¬ÖÐÑë¾Í¸ô×ŵÚ1569ÐдúÂ룺lock_sock(sk)¡£¼ÓËøÇ° £¬vsk->transportÒѾ­¸³Öµµ½transport±äÁ¿ÖÐ £¬ÕâÀï²úÉúÁËÒ»¸öÒýÓà £¬¶øºó²Å½øÐÐlock_sock(sk)½«skËø¶¨¡£µ«ÊÇvsk->transport»áÔÚ¶à´¦±»Å²ÓÃÉõÖÁ±»¿ªÊÍ £¬Õâ¾ÍÓпÉÄÜͨ¹ýǰÌᾺÕùÔì³ÉUse After Free¡£


´¥·¢¹ý³Ì


Ê×ÏÈÕÒµ½Åú¸Ä»ò¿ªÊÍvsk->transportµÄŲÓÃõè¾¶ £¬À´¿´¹Ø¼üº¯Êývsock_assign_transport()µÄʵÏÖ¡£¶ÔÓÚ¶à´«Êäģʽ £¬¸Ãº¯ÊýÓÃÓÚÆ¾¾Ý·ÖÆçCID·ÖÅä·ÖÆçµÄ´«Êäͨ·¡£ÊµÏÖ´úÂëÈçÏÂͼËùʾ£º


7.png


ƾ¾Ýsk->sk_type·ÖΪSOCK_DGRAMºÍSOCK_STREAM £¬ÔÚSOCK_STREAMÖÐ £¬·ÖΪÈýÖÖ´«Êäͨ·¡£ÕâÀïÄܹ»Í¨¹ý½«CIDÉèÖÃΪ±¾µØ»·»ØÄ£Ê½ £¬µÃµ½transport_local´«Êäͨ·¡£½ÓÏÂÀ´ÈçÏÂͼËùʾ£º


8.png


ÈôÊÇvsk->transport²»Îª¿Õ £¬Ôò½øÈëifÓï¾ä¡£ÏÈÅжÏvsk->transportÊÇ·ñµÅ×Únew_transport £¬ÈôÊǵÅ×ÚÖ±½Ó·µ»Ø £¬ÔÚ´¥·¢¹ý³ÌÖÐ £¬Òª±£ÕÏÄÜ×ßµ½vsock_deassign_transport()º¯Êý £¬¸Ãº¯ÊýÊÇÎö¹¹º¯Êý £¬ÓÃÓÚ¿ªÊÍtransport¡£ÈçÏ´úÂëËùʾ£º


9.png


ÐÐ411 £¬Å²ÓÃvsk->transport->destruct() £¬ÒªÃ÷ȷʹÓÃtransportÀàÐÍ £¬Ç°ÎÄÒѾ­È·¶¨Ê¹ÓÃtransport_local¡£Transport_localΪȫ¾Ö±äÁ¿ £¬»áÔÚvsock_core_register()º¯ÊýÖб»³õʼ»¯¡£¸Ãº¯Êý±»Å²ÓÃÇé¿öÈçÏÂͼËùʾ£º


10.png


*_init()º¯ÊýÓÃÀ´³õʼ»¯transportµÄ»Øµ÷º¯Êý £¬Æ¾¾ÝµÚ¶þ²¿ÃŽéÉÜ £¬vhost_vsock_init()¡¢virtio_vsock_init()ºÍvsock_loopback_init()º¯ÊýΪQEMU/KVM»·¾³ÏµÄÖ§³Öº¯Êý¡£ÎÒÃÇ·¢ÏÖtransport->destruct()º¯ÊýµÄ×îºóʵÏÖ¶¼ÊÇͳһ¸öº¯Êý¡£ÈçÏÂͼËùʾ£º


11.png


¸Ãdestruct()º¯Êý¿ªÊÍvsk->trans £¬ÈçÏÂͼËùʾ£º


12.png


¶øvsk->transÖ¸ÕëÊÇÖ¸ÏòtransportµÄ¡£½á¹¹Ìåvsock_sock½ç˵ÈçÏÂËùʾ£º


13.png


×îÖÕÄܹ»»ú¹ØÒ»¸ö¿ªÊÍtransportµÄº¯Êýõ辶Ϊ£ºvsock_stream_connect-> vsock_assign_transport->virtio_transport_destrcut¡£


ÕÒµ½ÁË¿ªÊÍõè¾¶ £¬ÏÂÒ»²½ÕÒʹÓÃõè¾¶ £¬virtio_transport_notify_buffer_size()º¯Êý»áʹÓÃtransport¡£ÈçÏÂͼËùʾ£º


14.png


µÚ492ÐÐ £¬Í¨¹ývsk->trans»ñȡָÏòtransportµÄÖ¸Õë £¬µÚ497ÐÐ £¬½âÒýÓÃvvsÖ¸Õë £¬¶Ôvvs->buf_alloc½øÐи³Öµ¡£¶øÅ²ÓÃvirtio_transport_notify_buffer_size()º¯Êý×îÖջᱻvsock_stream_setsockopt()º¯ÊýŲÓá£×îÖÕÄܹ»»ú¹ØÒ»¸öʹÓÃtransportµÄº¯Êýõ辶Ϊ£ºvsock_stream_setsockopt-> vsock_update_buffer_size->virtio_transport_notify_buffer_size¡£


½ÓÏÂÀ´¾ÍÊÇÓªÔìÒ»¸öÇÀËøµÄǰÌᾺÕù»·¾³ £¬ºÜÏÔÖø±ØÐëÊÇconnect()ϵͳŲÓÃÏÈÇÀµ½Ëø¶Ôtransport½øÐпªÊÍ £¬¶øºóÔÙŲÓÃsetsockopt()ÄÜÁ¦´¥·¢·ì϶¡£Óпª·¢ÈËÔ±Ìá³öʹÓÃuserfaultfd»úÔìÏȽ«lock_sockËø¶¨ £¬¶øºóÔÚÈ¥¿ªÊÍËø £¬½øÐÐǰÌᾺÕù¡£·ì϶´¥·¢¹ý³ÌÈçÏÂͼËùʾ£º


15.png


À¶¿òÖÐÊÇconnect()ŲÓùý³Ì £¬×îºóŲÓÃvirtio_transport_destruct()º¯Êý¿ªÊÍvsk->trans¡£ºì¿òÖÐÊÇsetsockopt()ŲÓùý³Ì £¬Å²ÓÃvirtio_transport_notify_buffer_size()º¯ÊýʹÓÃvvs £¬¸ÃÖµÊÇ0xffff888107a74500 £¬ÔÚ0xffff888107a74500+0x28´¦»áдÈë4×Ö½Ú¡£


²Î¿¼Á´½Ó£º

[1]https://github.com/torvalds/linux/commit/d021c344051af91f42c5ba9fdedc176740cbd238

[2]https://static.sched.com/hosted_files/devconfcz2020a/b1/DevConf.CZ_2020_vsock_v1.1.pdf

[3]https://github.com/jordan9001/vsock_poc

[4]https://terenceli.github.io/%E6%8A%80%E6%9C%AF/2020/04/18/vsock-internals


GA»Æ½ð¼×»ý¼«·ÀÓù³¢ÊÔÊÒ£¨ADLab£©


ADLab³ÉÁ¢ÓÚ1999Äê £¬ÊÇÖйú°²È«ÐÐÒµ×îÔç³ÉÁ¢µÄ¹¥·À¼¼Êõ×êÑг¢ÊÔÊÒÖ®Ò» £¬Î¢ÈíMAPP´òËãÖ÷Ìâ³ÉÔ± £¬¡°ºÚȸ¹¥»÷¡±¸ÅÏëÊ×ÍÆÕß¡£½ØÖ¹Ä¿Ç° £¬ADLabÒÑͨ¹ýCVEÀۼư䲼°²È«·ì϶½ü1100¸ö £¬Í¨¹ý CNVD/CNNVDÀۼư䲼°²È«·ì϶1000Óà¸ö £¬³ÖÐøÎ¬³Ö¹ú¼ÊÍøÂ簲ȫÁìÓòÒ»Á÷Ë®×¼¡£³¢ÊÔÊÒ×êÑз½Ïòº­¸Ç²Ù×÷ϵͳÓëÀûÓÃϵͳ°²È«×êÑÓ×¢ÖÇÄÜÖն˰²È«×êÑÓ×¢ÎïÁªÍøÖÇÄÜÉ豸°²È«×êÑÓ×¢Web°²È«×êÑÓ×¢¹¤¿ØÏµÍ³°²È«×êÑÓ×¢ÔÆ°²È«×êÑС£×êÑгɾÍÀûÓÃÓÚ²úÆ·Ö÷Ìâ¼¼Êõ×êÑÓ×¢¹ú¶È³Áµã¿Æ¼¼ÏîÄ¿¹¥¹Ø¡¢×¨Òµ°²È«·þÎñµÈ¡£


΢ÐÅͼƬ_20210310102858.jpg