Skip to content

Instantly share code, notes, and snippets.

@rfay
Last active May 29, 2022 16:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rfay/18ed619edc366a73b289bd23bfb70bbc to your computer and use it in GitHub Desktop.
Save rfay/18ed619edc366a73b289bd23bfb70bbc to your computer and use it in GitHub Desktop.
pv buffer overrun bug report

The description below explains a manifestation of "Dirty Pipe" on Windows WSL2 with Docker Desktop 4.8.2 and an out-of-date WSL2 kernel.

Using pv inside a container with a file mounted from the Windows filesystem using Docker resulted in massive display of inappropriate memory contents, for example docker run --rm -v 'C:\users\rfay\x\junk.txt:/junk.txt' debian:bullseye-slim bash -c "apt-get update >/dev/null && apt-get install -y pv >/dev/null && pv --version && pv /junk.txt | cat, see output.

The maintainer of pv responded correctly with:

At first glance this doesn't look like a bug in PV as such, it looks like the "dirty pipe" kernel vulnerability, or something very similar:

https://dirtypipe.cm4all.com https://www.cisa.gov/uscert/ncas/current-activity/2022/03/10/dirty-pipe-privilege-escalation-vulnerability-linux

Presumably whichever Linux kernel version is being used to run the container you're using is one of the vulnerable ones.

My assumption is that the garbage you're seeing in the output file is the contents of filesystem cache buffers that the kernel has mistakenly mapped into the address space being used by the pipe.

If it was a buffer overflow in PV, the output couldn't contain data that was never sent to PV and isn't part of its address space. There are bits of iptables data in your example - there is no way a program could acquire that data without there being a kernel memory mapping error.

Within the containers you're using, try "uname -a" to see the kernel version. If it's 5.16 less than 5.16.11, 5.15 less than 5.15.25, or 5.10 less than 5.10.102, that's probably what this is. I think there are older versions which are also vulnerable - once we see "uname -a" we can dig deeper.

Sure enough, getting the WSL2 kernel updated (currently it updates to 5.10.102) solved the problem on all systems that were demonstrating it.

A key takeaway from this experience is this: On Windows (10 and 11) kernel updates are provided via Windows Update, but to get WSL2 kernel updates, you now have to enable the "Advanced Options" -> Receive updates for other Microsoft Products" to get them.

This is a report of an obscure but serious bug report with pv 1.6.6 (but also demonstated exactly the same with pv 1.6.20). It's apparently a buffer overrun.

  • This happens on Windows 11 with Docker Desktop 4.8.2 when you run a docker container and use pv inside the container to read and pipe a mounted simple text file. The size of the file is irrelevant.
  • The basic idea is install and run pv <file.txt | cat inside a container.
  • It happens on at least some Windows machines with this sequence (done in git-bash)
mkdir -p $HOME/x && echo "hello" >$HOME/x/junk.txt
docker run --rm -v 'C:\users\rfay\x\junk.txt:/junk.txt' debian:bullseye-slim bash -c "apt-get update >/dev/null && apt-get install -y pv >/dev/null && pv --version && pv /junk.txt | cat"
  • Partial output (with loads of interesting memory content) is in partial_output.txt.
  • It does not happen if you don't put pv output to a pipe (if you just pv /junk.txt)
  • It does not happen if you copy the file to a non-mounted filesystem (cp junk.txt /tmp && pv /tmp/junk.txt | cat)
  • It does happen with pv 1.6.20, which I built and experimented with.
  • It does not happen on macOS or Linux with their Docker mounts (different mount type)
  • It does not happen when you do a similar thing with another tool (cat junk.txt | cat for example)
pv 1.6.6 - Copyright 2015 Andrew Wood <andrew.wood@ivarch.com>
Web site: http://www.ivarch.com/programs/pv.shtml
This program is free software, and is being distributed under the
terms of the Artistic License 2.0.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
hello
‼↑♦�↨!= local fib saddr . mark . iif oif %s0rpfilter match options:
--loose permit reverse path via any interface
--validmark use skb nfmark when performing route lookup
--accept-local do not reject packets with a local source address
--invert match packets that failed the reverse path testloose %s%svalidmarkaccept-localinvert-- rpfilterlibxtables.so.12☺♥T h���p������
���|☺��������������♦☺����↑☺X���L☺h���`☺¶☺zR☺x►☺ ☺$∟����`►F↑J �?→;*3$"¶D(���↑(
w $�����<A►�☻D↑�♥A s↑A►A ►�����
0������A►�☻D↑�♥E ☻Z
↑D►Q E ►�♦���►↑ ►(☺\���
�↓��68♣$�A�♥�♥☺►►�\�b�_�/{\�b�jK&{\�b�jK&����������������_!k!☺u!☻�!♥☺�☺�
U‼↓�<☻♣�♥♠0☻
�=&►6►F►V►f►ELF☻☺☺♥>☺(◄@�1@8 �☺ ↑↑���o☺���o
►☺♣►►►�↨H♠�♦ @↑↨☺♦ x ►☺♠�*�:�: ♠
� P�td♦�%�%�%tt♦Q�td♠►R�td♦�*�:�:(♣(♣☺♥↑☺♠�►♠@☺↑↓→Uz���������↕�↕�↕="☺↕�◄L # �◄�↕�↕ �↕�↕▼☺↕�↕�↕�↕z↕�↕�
◄d �↕☺↕
(◄
↓☺↕♠►☺☺↕
�∟☺_fini_ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalize__deregister_frame_info__register_frame_infoxt_xlate_addputsprintfhtonsgetservbyportputch
arstrdupstrchrxtables_parse_portxt_paramsfreeoptargoptindstrcasecmpstrtoktouppertolowerlibxt_sctp_initxtables_register_matchlibxtables.so.12libc.musl-x86_64.so.1;
�$►; �$↑; �$(; �$0; �$
�$H; �$X; �$`; �$p; �$x; �$�; �$�;
�$�; �$�; ♠%�; �$�; %�; �$�; ∟%�;
�$�; "%< �$ < .%↑< �$ < 9%0< �$8<
�$P< J%`< �$h< \%x< �$�< c%�< �$
n%�< �$�< z%�< �%= �% = �%@= �$@
@ @ �$0@ �$X@ ]‼`@ ;↕h@ ☻§x@ � ' �<
X↕�:☺↑�?♠♦�?♠♠�?♠�?♠ �?♠ �?♠
�?♠§�?♠▬8?☺@?☻H?♥P?♣X?
`?
p?x?�?►�?◄�?↕�?‼�?¶�?↨P�☻��
X��5↕/�%¶/▼@�%↕/h������%
/h☺������%☻/h☻������%�.h♥������%�.h♦������%�.h♣������%�.h♠������%�.h�p����%�.h �`����%�.h �P����%�.h
�@����%�.h
�0����%�.h
�►����%�.h�����%�.f��%�.f��%�.f�H�=�.�l���H�=�/H�♣�/H9�tH�♣�.H��t☻���H�=�/H�5|/�☻H)�H��♥H��H�H��H��H��tH�♣A.H��t☻��À=J/u{UH�=.H��ATSt
H�=P.�[���H�♣4)H�↔5)H)�I��H��♥H��H�♣◄/H9�s►H��H�♣☻/A�¶����C���H�=�-t
��☺��<☺☻te��@☺D�C D�K"��☻fE9�t'��H�☺��H�♣T��H�5����Ƈ,☺�Ƈ/☺�Ƈ2☺�Ƈ5☺��ATE1�USH�^
H�♣◄H��HD�H�5�
��������%��H�
H�♣�►H��HD�H�5� �����D���8����:���������[]A\A]A^�∟���[]A\A]A^�ATI��US�▲����:H��H���~���H��u∟H�5H�►�
☻1��R(��<☺☻H�♣‼*H�s H�8�����E��t��@☺☻�M☻�`♥�☺♦t‼H�♣*H�5�♥�☺☺t‼H�♣�*H�5&☻fA9♦$v�♣�*H�5b
H�►��H�♣�)HcL�$�M��t
A�♦$<!t♦<-u▬H�♣�)H�5������H��t�H�0H��t�H�=�1�]�|���AVI��AUATA��UD��S�Ӆ�u¶f��u♠f���twL�-C►�L�-i►L��H�=R1�E���5���L��fA9�u§H�=<1��▲�����D���'H�=&1��
H�►�z���H�♣�)��<☺♦H�5�
L�0L���-�����u
ǃ(☺☺�TH�5L��������u
ǃ(☺☻�5H�5�
L���������u
ǃ(☺♦�▬H�♣X)H�5k
I��D����L���������u◄�☺��L�����▲☻H�5O��H�5�
L���j�����u�@L������☺H�5↔
�#1�H�9L���T$�H�☺�:L�������I�������H�=�#E1�Hk�↑H☺��☺�H ������♣ |�(M����H�D$ H��,☺H�♦$��E� H�H►H��H�L$►�‼����T$∟H���☺H�L$►D�
L$↑L�¶$H)ȹ F☻��↓wF☺A��H���L��1�D����H��H��H9��S���H�5�
1��������H��↑��↕�����H�♣`'L���☻H�5�
H� 1��Q(A���p�����♦u▬H�♣5'H�5�
H�►�����Hc�A�☺H�4vH♥4$A���▬D F☻��↓w♦F☺����8☺�R���H�♣�&H�5 1��Q(L�������E��t��@☺♦H�♣�&��M♦H��(�☺[]A\A]A^A_�AWAVAUATUSH��H��(��↑☺�� ☺�t$∟�L$↑�
�☻t↕��♦t↔��H�=�
uH�=�
1�������§H�=�
��H�=�
�����1��|♥ u↑H��♦H=☺u�H�=� �V☺1��|♥ �u↑H��♦H=☺u�H�=q
�5☺L�5∟!1�1�M��H���☺��A��H��♣���D� ���,��u♣� �♣����|$∟t▬D��H�=▬
1������E1��FI���☺M��H�D$ E;u◄I�7H�=�1������I��↑L;|$ u���K�♦d��♥
☺9�t
☺�L$9�D$¶��t�♥☺��♥
�:�s���E1��T$ �D)���s▲I�M►B�<9�L$¶��r�x������A���I��I�� u�둺☺H��I��↑H��☺�����H��([]A\A]A^A_�H��(1�[]A\A]A^A_� ���SH����<☺☺tB��@☺☺tH�=
1�������s$�S&f9�t►H�=� 1�������H�=� 1��������<☺☻tB��@☺☻tH�=� 1�������s �S"f9�t►H�=� 1������H�=� 1��o�����<☺♦t1��@☺♦tH�=t 1��O���H�=�
1��A���H�{ 1�[�?���[�U1�H�=� ��SH��Q�↔�����<☺☺t ��@☺�S&A��H�=l �s$��☺�x�����<☺☻t ��@☺�S"A��H�=G �s ��☻�O�����<☺♦t%��@☺♦tH�=�1������ZH�{ ��
��H���X[]�P�����X� !=sctp sport%s %u-%usport%s %u%sdport%s %u-%u%sdport%s %usctp match options
[!] --source-port port[:port] match source port(s)
--sport ...
[!] --destination-port port[:port] match destination port(s)
--dport ...
[!] --chunk-types (all|any|none) (chunktype[:flags])+ match if all, any or none of
chunktypes are present
chunktypes - DATA INIT INIT_ACK SACK HEARTBEAT HEARTBEAT_ACK ABORT SHUTDOWN SHUTDOWN_ACK ERROR COOKIE_ECHO COOKIE_ACK ECN_ECNE ECN_CWR SHUTDOWN_COMPLETE ASCONF ASC
ONF_ACK FORWARD_TSN ALL NONE %ss:%sinvalid portrange (min > max)Only one `--source-port' allowedOnly one `--destination-port' allowedOnly one `--chunk-types' allow
ed--chunk-types requires two argsANYONLYMatch type has to be one of "ALL", "ANY" or "ONLY",Unknown sctp chunk `%s'Number of chunk types with flags exceeds currentl
y allowed limit.Increasing this limit involves changing IPT_NUM_SCTP_FLAGS andrecompiling both the kernel space and user space modules
Invalid flags for chunk type %d
any all onlyNever reach here0x%04X ALL ! --sport %u:%u --sport %u --dport %u:%u --dport %u --chunk-types sctpsptdptlibxtables.so.12DATA----IUBEINIT--------INIT_AC
KSACKHEARTBEATHEARTBEAT_ACKABORT-------TSHUTDOWNSHUTDOWN_ACKERRORCOOKIE_ECHOCOOKIE_ACKECN_ECNEECN_CWRSHUTDOWN_COMPLETEASCONFASCONF_ACKFORWARD_TSNsource-porl����l��
�������☻�������������� ☺$∟����☺►F↑J �?→;*
w���� ☺►���@☺�����☺^����☺����♦☻����h☻Y����☻¶☺zR☺x►☺ ►�����
∟�����KA►�☻S
E H������B►�☻E↑�♥B �♦D(�♣D0�♠☻|
(A B↑B►B E (∟☺▲����B►�☻D↑�♥A �♦☻�↑D►B HH☺����8♦B►�☻B↑�♥B �♦E(�♣A0�♠D8�D`♥¶♦8F0A(B B↑B►B `�☺�����☺B►�☻B↑�♥B �♦B(�
♣A0�♠A8�G`♥�☺
8A0A(B B↑B►B A ∟�☺‼����A►�☻☻�
E8C0↑☻�����A►�☻L↑�♥D ☻x
↑G►A E ►L☻����
�����������������$�$�$☺�$�$☻�$�$♥�$�$♦�$�$♣�$�$♠�$♠%�$%
�$∟% �$"%
�$.%
�$9%
�$J%�$\%��$c%��$n%��$z%☺1�%☺1�%☺2�%☺2�$☺3☺6☺☺G☺
�∟↓�:☻♣�♦♠0☻
]☺ �♣ ↑↑���o☺���o3�=&►6►F►V►f►v►�►�►�►�►�►�►�►�►♠
◄@�$�$(☺(☺]‼;↕☻§�↕GCC: (Alpine 9.2.0) 9.2.0.shstrtab.gnu.hash.dynsym.dynstr.rela.dyn.rela.plt.init.plt.got.text.fini.rodata.eh_frame_hdr.eh_frame.init_array.ctors.
dtors.data.rel.ro.dynamic.data.bss.comment
���o☻☻☻0☻ § ↑↔♥
☻0☻0☻�☻♥☺ ↑/♦B�
☺4☺♠►►►►☺►►?☺♠►◄►◄↑ H
h☺ ☺T☺2 �♣☺☺\☺☻�%�%t♦j☺☻↑&↑&`☻
t
�☺♥�:�*► �☺♥�:�*►
�☺♥;+�☻ �♠♥�=�-�☺♥ ►C☺♥
�☺♥@0� � ♥�@�0P �☺0�0→☺☺☺♥�0�☺
@↑↨☺♦X♠X♠►☺♣►►►8☻8☻►☺♦ �☺�☺►☺♠X-X=X=�♥
P�td♦� � � LL♦Q�td♠►R�td♦X-X=X=�☻�☻☺♥
☺♠�♦☺♦@☺
�������¶h��↕�↕="L # z↕ �↕�◄d �↕♠►☺☺↕
0↕☺�↕ x►
_fini_ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalize__deregister_frame_info__register_frame_infoxtables_option_parsepr� @fxt_paramsputslibxt�?♠♥
�?♠♦�?♠♣�?♠�?♠es_r� 0@ter_targetlibxtabl� X@o.12libc.musl-x86_☻↕x@o.1�= �◄�@ �◄�@ �?♠ �◄�@ �=X=☺�?☺�?☻�?
♠�? P�^☺�♥☻X��5r/�%t/▼@�%r/h������%j/h☺������%b/h☻������%Z/h♥������%R/f��%R/f��%j/f�H
�=�/�����H�=]0H�♣V0H9�tH�♣2/H��t☻���H�=;0H�540�☻H)�H��♥H��H�H��H��H��tH�♣�.H��t☻��À=→0u{UH�=�.H��ATSt
H�=/�[���H�♣d,H�↔e,H)�I��H��♥H��H�♣�/H9�s►H��H�♣�/A�¶����C���H�=w.t
H�=►�◄���[A\�♣�/☺]��H�=t.t↑UH�5�/H�=�H�������]���SH�_↑������♥☺[��↨��☺u↕H�w
1�H�=Q�l���PH�♣∟.H�5G
1��Q(SH�=UH��1��>���H�{ [��SH�=@H��1��%���H�{ [��H�=2�"���UH��SH�↔F+RH�♥H���t ��H���X[]�P�����X�selctx %sSECMARK target: invalid mode %hhu
-- SECMARK SECMARK target options:
--selctx value Set the SELinux security contextlibxtables.so.12SECMARKselctx☺♥H T���d��������� ☺����������¶����-����F���
☺¶☺zR☺x►☺ ☺$∟����P►F↑J �?→;*3$"¶D►���↑↑\#���A►�☻M ►x▬���6[►↑�8�
w ↑�5���↓A►�☻V ►�2���
►�����
�����������������
# uname -a
Linux 278aab42474d 5.10.16.3-microsoft-standard-WSL2 #1 SMP Fri Apr 2 22:23:49 UTC 2021 x86_64 GNU/Linux
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment