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¡£ÈçÏÂͼËùʾ£º
VSOCKÖ§³Ösocket API¡£AF_SOCKµØÖ·´Ø°üÂÞÁ½¸öÒªËØ£ºCIDºÍport¡£CIDΪContextIdentifier£¬ÉÏÏÂÎıêʶ·û£»portΪ¶Ë¿Ú¡£TCP/IPÓ¦Ó÷¨Ê½¼¸ºõ²»ÐèÒª¸ü¸Ä¾Í¿ÉÒÔÊÊÅ䣬ÿһ¸öµØÖ·ÌåÏÖΪ
Transportƾ¾Ý´«ÊäÆ«Ïò·ÖΪÁ½ÖÖ£¨ÒÔSOCK_STREAMÀàÐÍΪÀý£©£¬Ò»ÖÖΪG2H transport£¬ÌåÏÖguestµ½hostµÄ´«ÊäÀàÐÍ£¬ÔËÐÐÔÚguestÖС£ÁíÒ»ÖÖΪH2G transport£¬ÌåÏÖhostµ½guestµÄ´«ÊäÀàÐÍ¡£ÒÔQEMU/KVM´«ÊäΪÀý£¬ÈçÏÂͼËùʾ£º
¸Ã´«ÊäÌṩÌ×½Ó×Ö²ã½Ó¿ÚµÄÇý¶¯·ÖΪÁ½¸ö²¿ÃÅ£ºÒ»¸öÊÇÔËÐÐÔÚguestÖеÄvirtio-transport£¬ÓÃÓÚÅäºÏguest½øÐÐÊý¾Ý´«Ê䣻ÁíÒ»¸öÊÇÔËÐÐÔÚhostÖеÄvhost-transport£¬ÓÃÓÚÅäºÏhost½øÐÐÊý¾Ý´«Êä¡£VSOCK transport»¹Ìṩ¶à´«ÊäͨµÀģʽ£¬¸Ã¹¦Ð§ÊÇΪÁËÖ§³ÖǶÌ×ÐéÄâ»úÖеÄVSOCK¹¦Ð§¡£ÈçÏÂͼËùʾ£º
Ö§³ÖL1ÐéÄâ»úͬʱ¼ÓÔØH2GºÍG2HÁ½¸ö´«ÊäͨµÀ£¬´ËʱL1ÐéÄâ»ú¼´ÊÇhostÒ²ÊÇguest£¬Í¨¹ýH2G´«ÊäͨµÀºÍL2ǶÌ×ÐéÄâ»úͨÐÅ£¬Í¨¹ýG2H´«ÊäͨµÀºÍL0 hostͨÐÅ¡£VSOCK transport»¹Ö§³Öµ±µØ»·»Ø´«ÊäͨµÀģʽ£¬²»ÐèÒªÓÐÐéÄâ»ú¡£ÈçÏÂͼËùʾ£º
¸ÃģʽÓÃÓÚ²âÊԺ͵÷ÊÔ£¬ÓÉvsock-loopbackÌṩ֧³Ö£¬²¢¶ÔµØÖ·´ØÖеÄCID½øÐÐÁË·ÖÀ࣬°üÂÞÁ½ÖÖÀàÐÍ£ºÒ»ÖÖÊÇVMADDR_CID_LOCAL£¬ÌåÏÖµ±µØ»·»Ø£»Ò»ÖÖΪVMADDR_CID_HOST£¬ÌåÏÖH2G´«ÊäͨµÀ¼ÓÔØ£¬G2H´«ÊäͨµÀδ¼ÓÔØ¡£
©¶´·ÖÎöÓë´¥·¢¹ý³Ì
©¶´·ÖÎö
¸Ã©¶´´¥·¢ÔÒòÊÇ´íÎó¼ÓËøµ¼ÖÂÌõ¼þ¾ºÕù£¬Æ¾¾Ý²¹¶¡¿ÉÖª£¬´æÔڶദ´íÎó¼ÓËø£¬ÕâÀïÒÔvsock_stream_setsockopt()º¯Êý²¹¶¡ÎªÀý£¬ÈçÏÂͼËùʾ£º
²¹¶¡ºÜ¼ò½à£¬½«µÚ1564ÐдúÂëÒƶ¯µ½µÚ1571ÐУ¬Öмä¾Í¸ô×ŵÚ1569ÐдúÂ룺lock_sock(sk)¡£¼ÓËøÇ°£¬vsk->transportÒѾ¸³Öµµ½transport±äÁ¿ÖУ¬ÕâÀï·¢ÉúÁËÒ»¸öÒýÓã¬È»ºó²Å½øÐÐlock_sock(sk)½«skËø¶¨¡£µ«ÊÇvsk->transport»áÔڶദ±»µ÷ÓÃÉõÖÁ±»ÊÍ·Å£¬Õâ¾ÍÓпÉÄÜͨ¹ýÌõ¼þ¾ºÕùÔì³ÉUse After Free¡£
´¥·¢¹ý³Ì
Ê×ÏÈÕÒµ½Ð޸ĻòÊÍ·Åvsk->transportµÄµ÷Ó÷¾¶£¬À´¿´Òªº¦º¯Êývsock_assign_transport()µÄʵÏÖ¡£¶ÔÓڶഫÊäģʽ£¬¸Ãº¯ÊýÓÃÓÚƾ¾Ý²îÒìCID·ÖÅä²îÒìµÄ´«ÊäͨµÀ¡£ÊµÏÖ´úÂëÈçÏÂͼËùʾ£º
ƾ¾Ýsk->sk_type·ÖΪSOCK_DGRAMºÍSOCK_STREAM£¬ÔÚSOCK_STREAMÖУ¬·ÖΪÈýÖÖ´«ÊäͨµÀ¡£ÕâÀï¿ÉÒÔͨ¹ý½«CIDÉèÖÃΪµ±µØ»·»Øģʽ£¬µÃµ½transport_local´«ÊäͨµÀ¡£½ÓÏÂÀ´ÈçÏÂͼËùʾ£º
Èç¹ûvsk->transport²»Îª¿Õ£¬Ôò½øÈëifÓï¾ä¡£ÏÈÅжÏvsk->transportÊÇ·ñ¼´ÊÇnew_transport£¬Èç¹û¼´ÊÇÖ±½Ó·µ»Ø£¬ÔÚ´¥·¢¹ý³ÌÖУ¬Òª±£Ö¤ÄÜ×ßµ½vsock_deassign_transport()º¯Êý£¬¸Ãº¯ÊýÊÇÎö¹¹º¯Êý£¬ÓÃÓÚÊÍ·Åtransport¡£ÈçÏ´úÂëËùʾ£º
ÐÐ411£¬µ÷ÓÃvsk->transport->destruct()£¬ÒªÃ÷ȷʹÓÃtransportÀàÐÍ£¬Ç°ÎÄÒѾȷ¶¨Ê¹ÓÃtransport_local¡£Transport_localΪȫ¾Ö±äÁ¿£¬»áÔÚvsock_core_register()º¯ÊýÖб»³õʼ»¯¡£¸Ãº¯Êý±»µ÷ÓÃÇé¿öÈçÏÂͼËùʾ£º
*_init()º¯ÊýÓÃÀ´³õʼ»¯transportµÄ»Øµ÷º¯Êý£¬Æ¾¾ÝµÚ¶þ²¿ÃŽéÉÜ£¬vhost_vsock_init()¡¢virtio_vsock_init()ºÍvsock_loopback_init()º¯ÊýΪQEMU/KVM»·¾³ÏµÄÖ§³Öº¯Êý¡£ÎÒÃÇ·¢ÏÖtransport->destruct()º¯ÊýµÄ×îºóʵÏÖ¶¼ÊÇͬһ¸öº¯Êý¡£ÈçÏÂͼËùʾ£º
¸Ãdestruct()º¯ÊýÊÍ·Åvsk->trans£¬ÈçÏÂͼËùʾ£º
¶øvsk->transÖ¸ÕëÊÇÖ¸ÏòtransportµÄ¡£½á¹¹Ìåvsock_sock½ç˵ÈçÏÂËùʾ£º
×îÖÕ¿ÉÒԽṹһ¸öÊÍ·ÅtransportµÄº¯Êý·¾¶Îª£ºvsock_stream_connect-> vsock_assign_transport->virtio_transport_destrcut¡£
ÕÒµ½ÁËÊÍ·Å·¾¶£¬ÏÂÒ»²½ÕÒʹÓ÷¾¶£¬virtio_transport_notify_buffer_size()º¯Êý»áʹÓÃtransport¡£ÈçÏÂͼËùʾ£º
µÚ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Ëø¶¨£¬È»ºóÔÚÈ¥ÊÍ·ÅËø£¬½øÐÐÌõ¼þ¾ºÕù¡£Â©¶´´¥·¢¹ý³ÌÈçÏÂͼËùʾ£º
À¶¿òÖÐÊÇ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¼Æ»®ºËÐijÉÔ±£¬¡°ºÚȸ¹¥»÷¡±¿´·¨Ê×ÍÆÕß¡£½ØֹĿǰ£¬ADLabÒÑͨ¹ýCVEÀÛ¼ÆÐû²¼Äþ¾²Â©¶´½ü1100¸ö£¬Í¨¹ý CNVD/CNNVDÀÛ¼ÆÐû²¼Äþ¾²Â©¶´1000Óà¸ö£¬Á¬Ðø±£³Ö¹ú¼ÊÍøÂçÄþ¾²ÁìÓòÒ»Á÷Ë®×¼¡£ÊµÑéÊÒÑо¿Æ«Ïòº¸Ç²Ù×÷ϵͳÓëÓ¦ÓÃϵͳÄþ¾²Ñо¿¡¢ÖÇÄÜÖÕ¶ËÄþ¾²Ñо¿¡¢ÎïÁªÍøÖÇÄÜÉ豸Äþ¾²Ñо¿¡¢WebÄþ¾²Ñо¿¡¢¹¤¿ØϵͳÄþ¾²Ñо¿¡¢ÔÆÄþ¾²Ñо¿¡£Ñо¿½á¹ûÓ¦ÓÃÓÚ²úÎïºËÐļ¼ÊõÑо¿¡¢¹ú¼ÒÖصã¿Æ¼¼ÏîÄ¿¹¥¹Ø¡¢×¨ÒµÄþ¾²·þÎñµÈ¡£