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


ɳ°Í»ý¼«·ÀÓù³¢ÊÔÊÒ£¨ADLab£©


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


΢ÐÅͼƬ_20210310102858.jpg