Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Segfaults in Monterey 12.3 with dsdump beta #35

Open
jslegendre opened this issue Mar 11, 2022 · 4 comments
Open

Segfaults in Monterey 12.3 with dsdump beta #35

jslegendre opened this issue Mar 11, 2022 · 4 comments

Comments

@jslegendre
Copy link

macOS Version: 12.3 (21E230)
Mapped cache: /System/Library/dyld/dyld_shared_cache_x86_64h
Current cache slide: 0x15015000 (not sure if it helps)

When running:
dsdump -oc /System/Library/Frameworks/Foundation.framework/Foundation

Result:

Crashed Thread:        0  Dispatch queue: com.apple.main-thread

Exception Type:        EXC_BAD_ACCESS (SIGSEGV)
Exception Codes:       KERN_INVALID_ADDRESS at 0x000007f856b8fdd0
Exception Codes:       0x0000000000000001, 0x000007f856b8fdd0
Exception Note:        EXC_CORPSE_NOTIFY

Termination Reason:    Namespace SIGNAL, Code 11 Segmentation fault: 11
Terminating Process:   exc handler [1998]

VM Region Info: 0x7f856b8fdd0 is not in any region.  Bytes after previous region: 8758672952785  Bytes before following region: 96789928018480
      REGION TYPE                    START - END         [ VSIZE] PRT/MAX SHRMOD  REGION DETAIL
      VM_ALLOCATE (reserved)      10d21c000-10d21f000    [   12K] r--/r-- SM=NUL  ...(unallocated)
--->  GAP OF 0x5ffef2de1000 BYTES
      MALLOC_NANO              600000000000-600008000000 [128.0M] rw-/rwx SM=PRV  

Thread 0 Crashed::  Dispatch queue: com.apple.main-thread
0   dsdump                        	       0x100013ff3 -[XRMachOLibrary(ObjectiveC) dumpObjCClassInfo:resolvedAddress:] + 39
1   dsdump                        	       0x100014c46 -[XRMachOLibrary(ObjectiveC) dumpObjectiveCClasses] + 2493
2   dsdump                        	       0x100015837 -[XRMachOLibrary(SymbolDumper) dumpSymbols] + 127
3   dsdump                        	       0x10001bf26 main + 2002
4   dyld                          	       0x10d16c51e start + 462


Thread 0 crashed with X86 Thread State (64-bit):
  rax: 0x000007f856b8fdb0  rbx: 0x00007ff7bfefebd1  rcx: 0x000007f856b8fdb0  rdx: 0x00007ff816562bc0
  rdi: 0x000007f856b8fdb0  rsi: 0x000000010014db62  rbp: 0x00007ff7bfefeb50  rsp: 0x00007ff7bfefeb30
   r8: 0x00007ff856b14988   r9: 0x0000000000000000  r10: 0x00000001003edc62  r11: 0x0000000100013fcc
  r12: 0x0000000000000000  r13: 0x00007ff856b8fd88  r14: 0x00007ff816562bc0  r15: 0x00007ffffffffff8
  rip: 0x0000000100013ff3  rfl: 0x0000000000010202  cr2: 0x000007f856b8fdd0

From LLDB:

dsdump, -[XRMachOLibrary(ObjectiveC) dumpObjCClassInfo:resolvedAddress:]
    0    0x100013fcc <+0>:    push  rbp  
    1    0x100013fcd <+1>:    mov   rbp,  rsp  
    2    0x100013fd0 <+4>:    push  r15  
    3    0x100013fd2 <+6>:    push  r14  
    4    0x100013fd4 <+8>:    push  rbx  
    5    0x100013fd5 <+9>:    push  rax  
    6    0x100013fd6 <+10>:   mov   r14,  rdx  
    7    0x100013fd9 <+13>:   movabs r15,  0x7ffffffffff8  
    8    0x100013fe3 <+23>:   mov   rdi,  rcx  
   *9    0x100013fe6 <+26>:   call  0x100004ec0  ; payload::LoadToDiskTranslator<swift_class_t, true>::disk()
    10   0x100013feb <+31>:   mov   rdi,  rax  
   *11   0x100013fee <+34>:   call  0x100004ec0  ; payload::LoadToDiskTranslator<swift_class_t, true>::disk()
->  12   0x100013ff3 <+39>:   mov   rbx,  qword ptr [rax + 0x20]  
    13   0x100013ff7 <+43>:   and   rbx,  r15  
    14   0x100013ffa <+46>:   lea   rax,  [rip + 0x5428df] payload::isInDyldSharedCache ; 0x1005568e0 dsdump.__DATA.__common
    15   0x100014001 <+53>:   cmp   byte ptr [rax],  0x0  

When running:
dsdump -sc /System/Library/Frameworks/Combine.framework/Combine

Result:

Crashed Thread:        0  Dispatch queue: com.apple.main-thread

Exception Type:        EXC_BAD_ACCESS (SIGSEGV)
Exception Codes:       KERN_INVALID_ADDRESS at 0x00007ff7e4e02f2c
Exception Codes:       0x0000000000000001, 0x00007ff7e4e02f2c
Exception Note:        EXC_CORPSE_NOTIFY

Termination Reason:    Namespace SIGNAL, Code 11 Segmentation fault: 11
Terminating Process:   exc handler [2061]

VM Region Info: 0x7ff7e4e02f2c is not in any region.  Bytes after previous region: 619720493  Bytes before following region: 807477460
      REGION TYPE                    START - END         [ VSIZE] PRT/MAX SHRMOD  REGION DETAIL
      Stack                    7ff7bf700000-7ff7bff00000 [ 8192K] rw-/rwx SM=PRV  thread 0
--->  GAP OF 0x55115000 BYTES
      unused shlib __TEXT      7ff815015000-7ff815067000 [  328K] r-x/r-x SM=COW  ... this process

Thread 0 Crashed::  Dispatch queue: com.apple.main-thread
0   dsdump                        	       0x1000045be -[XRMachOLibrary(Swift) preparseSwiftTypes] + 246
1   dsdump                        	       0x1000157fc -[XRMachOLibrary(SymbolDumper) dumpSymbols] + 68
2   dsdump                        	       0x10001bf26 main + 2002
3   dyld                          	       0x10cf3851e start + 462


Thread 0 crashed with X86 Thread State (64-bit):
  rax: 0x00007ff7e4e02f28  rbx: 0x0000000000000000  rcx: 0xffffffffc08348f8  rdx: 0x00007ff7e4e02f28
  rdi: 0x00007ff7e4e02f28  rsi: 0x0000000000000008  rbp: 0x00007ff7bfeff210  rsp: 0x00007ff7bfeff170
   r8: 0x00007ff824555b98   r9: 0x0000000000000ed0  r10: 0x00007ff824555000  r11: 0xffffffff9b9a9a50
  r12: 0x00007ff82464b78c  r13: 0x1fffffffffffffff  r14: 0x00007ff7e4e02f28  r15: 0x0000000100455d20
  rip: 0x00000001000045be  rfl: 0x0000000000010202  cr2: 0x00007ff7e4e02f2c

From LLDB:

dsdump, -[XRMachOLibrary(Swift) preparseSwiftTypes]
    0    0x1000044c8 <+0>:    push  rbp  
    1    0x1000044c9 <+1>:    mov   rbp,  rsp  
    2    0x1000044cc <+4>:    push  r15  
    3    0x1000044ce <+6>:    push  r14  
    4    0x1000044d0 <+8>:    push  r13  
    5    0x1000044d2 <+10>:   push  r12  
    6    0x1000044d4 <+12>:   push  rbx  
    7    0x1000044d5 <+13>:   sub   rsp,  0x78  
    8    0x1000044d9 <+17>:   mov   rsi,  qword ptr [rip + 0x3e8e40]  ; "ma_ptr"
   *9    0x1000044e0 <+24>:   call  qword ptr [rip + 0x397baa] (void *)0x00007ff8151cd400: objc_msgSend ; 0x10039c090 dsdump.__DATA.__got
    10   0x1000044e6 <+30>:   mov   rbx,  rax  
    11   0x1000044e9 <+33>:   lea   rcx,  [rbp - 0x30]  
    12   0x1000044ed <+37>:   mov   qword ptr [rcx],  0x0  
    13   0x1000044f4 <+44>:   lea   rsi,  [rip + 0x149c2b] "__TEXT" ; 0x10014e126 dsdump.__TEXT.__cstring
    14   0x1000044fb <+51>:   lea   rdx,  [rip + 0x149c2b] "__swift5_types" ; 0x10014e12d dsdump.__TEXT.__cstring
    15   0x100004502 <+58>:   mov   rdi,  rax  
   *16   0x100004505 <+61>:   call  0x10002229e  ; dyld3::MachOLoaded::findSectionContent(char const*, char const*, unsigned long long&) const
    17   0x10000450a <+66>:   test  rax,  rax  
   *18   0x10000450d <+69>:   je    0x100004c0c <+1860> 
    19   0x100004513 <+75>:   mov   r12,  rax  
    20   0x100004516 <+78>:   mov   rax,  qword ptr [rbp - 0x30]  
    21   0x10000451a <+82>:   test  rax,  rax  
   *22   0x10000451d <+85>:   je    0x100004c0c <+1860> 
    23   0x100004523 <+91>:   mov   qword ptr [rbp - 0x90],  rbx  
    24   0x10000452a <+98>:   cmp   rax,  0x4  
   *25   0x10000452e <+102>:  jb    0x100004b46 <+1662> 
    26   0x100004534 <+108>:  movabs r13,  0x1fffffffffffffff  
    27   0x10000453e <+118>:  lea   r15,  [rip + 0x4517db] moduleDescriptorDictionary ; 0x100455d20 dsdump.__DATA.__bss
    28   0x100004545 <+125>:  xor   ebx,  ebx  
    29   0x100004547 <+127>:  mov   qword ptr [rbp - 0x48],  r12  
    30   0x10000454b <+131>:  lea   rax,  [r12 + 4*rbx]  
    31   0x10000454f <+135>:  movsxd rcx,  dword ptr [r12 + 4*rbx]  
    32   0x100004553 <+139>:  lea   r14,  [rax + 4*rcx]  
    33   0x100004557 <+143>:  mov   rdi,  r14  
   *34   0x10000455a <+146>:  call  0x100004cb8  ; payload::LoadToDiskTranslator<swift::TargetContextDescriptor<swift::InProcess>, false>::disk()
    35   0x10000455f <+151>:  mov   ecx,  dword ptr [rax + 0x4]  
    36   0x100004562 <+154>:  mov   qword ptr [rbp - 0x38],  r14  
    37   0x100004566 <+158>:  test  ecx,  ecx  
   *38   0x100004568 <+160>:  je    0x1000045c9 <+257> 
    39   0x10000456a <+162>:  add   rax,  0x4  
    40   0x10000456e <+166>:  mov   r14,  qword ptr [rbp - 0x38]  
    41   0x100004572 <+170>:  mov   edx,  ecx  
    42   0x100004574 <+172>:  and   edx,  -0x2  
    43   0x100004577 <+175>:  movsxd rdx,  edx  
    44   0x10000457a <+178>:  add   rdx,  rax  
    45   0x10000457d <+181>:  test  cl,  0x1  
   *46   0x100004580 <+184>:  je    0x100004585 <+189> 
    47   0x100004582 <+186>:  mov   rdx,  qword ptr [rdx]  
    48   0x100004585 <+189>:  test  rdx,  rdx  
   *49   0x100004588 <+192>:  je    0x1000045c9 <+257> 
    50   0x10000458a <+194>:  mov   rdi,  r14  
   *51   0x10000458d <+197>:  call  0x100004cb8  ; payload::LoadToDiskTranslator<swift::TargetContextDescriptor<swift::InProcess>, false>::disk()
    52   0x100004592 <+202>:  movsxd rcx,  dword ptr [rax + 0x4]  
    53   0x100004596 <+206>:  test  rcx,  rcx  
   *54   0x100004599 <+209>:  je    0x1000045b3 <+235> 
    55   0x10000459b <+211>:  add   rax,  0x4  
    56   0x10000459f <+215>:  mov   r14,  rcx  
    57   0x1000045a2 <+218>:  and   r14,  -0x2  
    58   0x1000045a6 <+222>:  add   r14,  rax  
    59   0x1000045a9 <+225>:  test  cl,  0x1  
   *60   0x1000045ac <+228>:  je    0x1000045b6 <+238> 
    61   0x1000045ae <+230>:  mov   r14,  qword ptr [r14]  
   *62   0x1000045b1 <+233>:  jmp   0x1000045b6 <+238> 
    63   0x1000045b3 <+235>:  xor   r14d,  r14d  
    64   0x1000045b6 <+238>:  mov   rdi,  r14  
   *65   0x1000045b9 <+241>:  call  0x100004cb8  ; payload::LoadToDiskTranslator<swift::TargetContextDescriptor<swift::InProcess>, false>::disk()
->  66   0x1000045be <+246>:  mov   ecx,  dword ptr [rax + 0x4]  
    67   0x1000045c1 <+249>:  add   rax,  0x4  
    68   0x1000045c5 <+253>:  test  ecx,  ecx 

When running:
dsdump -a x86_64 -oc /System/Applications/Calculator.app/Contents/MacOS/Calculator

Result:

0x400000000 is mapped to existing memory, exiting

When running:
dsdump -a x86_64 -sc /System/Library/CoreServices/ControlCenter.app/Contents/MacOS/ControlCenter

Result:

0x400000000 is mapped to existing memory, exiting

After NOPing the jne instruction at 0x010000da5d (skipping the check that leads to the above)

 -[XRMachOLibrary initWithPath:]
...
000000010000da59         cmp        dword [rbp+var_60], 0x0
-> 000000010000da5d         jne        loc_10000e104
...
000000010000e104         lea        rdi, qword [aPIsMappedToExi]                ; argument "format" for method imp___stubs__printf, "%p is mapped to existing memory, exiting\\n", CODE XREF=-[XRMachOLibrary initWithPath:]+339
000000010000e10b         mov        rsi, r15
000000010000e10e         xor        eax, eax
000000010000e110         call       imp___stubs__printf                         ; printf
000000010000e115         mov        edi, 0x1                                    ; argument "status" for method imp___stubs__exit
000000010000e11a         call       imp___stubs__exit                           ; exit

When running:
dsdump_patched -a x86_64 -oc /System/Applications/Calculator.app/Contents/MacOS/Calculator

Result:
Works as expected

When running:
dsdump_patched -a x86_64 -sc /System/Library/CoreServices/ControlCenter.app/Contents/MacOS/ControlCenter

Result:

Crashed Thread:        0  Dispatch queue: com.apple.main-thread

Exception Type:        EXC_BAD_ACCESS (SIGSEGV)
Exception Codes:       KERN_INVALID_ADDRESS at 0x00000004245a24a0
Exception Codes:       0x0000000000000001, 0x00000004245a24a0
Exception Note:        EXC_CORPSE_NOTIFY

Termination Reason:    Namespace SIGNAL, Code 11 Segmentation fault: 11
Terminating Process:   exc handler [2526]

VM Region Info: 0x4245a24a0 is not in any region.  Bytes after previous region: 605017249  Bytes before following region: 105535326509920
      REGION TYPE                    START - END         [ VSIZE] PRT/MAX SHRMOD  REGION DETAIL
      mapped file                 400000000-4004a5000    [ 4756K] r--/rwx SM=COW  ...t_id=c08ab0d9
--->  GAP OF 0x5ffbffb5b000 BYTES
      MALLOC_NANO              600000000000-600008000000 [128.0M] rw-/rwx SM=PRV  

Thread 0 Crashed::  Dispatch queue: com.apple.main-thread
0   dsdump_patched                      	       0x100004582 -[XRMachOLibrary(Swift) preparseSwiftTypes] + 186
1   dsdump_patched                      	       0x1000157fc -[XRMachOLibrary(SymbolDumper) dumpSymbols] + 68
2   dsdump_patched                      	       0x10001bf26 main + 2002
3   dyld                          	       0x109a7a51e start + 462


Thread 0 crashed with X86 Thread State (64-bit):
  rax: 0x0000000400159958  rbx: 0x0000000000000000  rcx: 0x0000000024448b49  rdx: 0x00000004245a24a0
  rdi: 0x0000000400159954  rsi: 0x0000000000000008  rbp: 0x00007ff7bfeff1e0  rsp: 0x00007ff7bfeff140
   r8: 0x0000000400003290   r9: 0x0000000000000ed0  r10: 0x0000000400000000  r11: 0x00007ff3bfefe530
  r12: 0x000000040039e354  r13: 0x1fffffffffffffff  r14: 0x0000000400159954  r15: 0x0000000100455d20
  rip: 0x0000000100004582  rfl: 0x0000000000010202  cr2: 0x00000004245a24a0

From LLDB:

dsdump_patched, -[XRMachOLibrary(Swift) preparseSwiftTypes]
    0    0x1000044c8 <+0>:    push  rbp  
    1    0x1000044c9 <+1>:    mov   rbp,  rsp  
    2    0x1000044cc <+4>:    push  r15  
    3    0x1000044ce <+6>:    push  r14  
    4    0x1000044d0 <+8>:    push  r13  
    5    0x1000044d2 <+10>:   push  r12  
    6    0x1000044d4 <+12>:   push  rbx  
    7    0x1000044d5 <+13>:   sub   rsp,  0x78  
    8    0x1000044d9 <+17>:   mov   rsi,  qword ptr [rip + 0x3e8e40]  ; "ma_ptr"
   *9    0x1000044e0 <+24>:   call  qword ptr [rip + 0x397baa] (void *)0x00007ff8151cd400: objc_msgSend ; 0x10039c090 dsdump_1.__DATA.__got
    10   0x1000044e6 <+30>:   mov   rbx,  rax  
    11   0x1000044e9 <+33>:   lea   rcx,  [rbp - 0x30]  
    12   0x1000044ed <+37>:   mov   qword ptr [rcx],  0x0  
    13   0x1000044f4 <+44>:   lea   rsi,  [rip + 0x149c2b] "__TEXT" ; 0x10014e126 dsdump_1.__TEXT.__cstring
    14   0x1000044fb <+51>:   lea   rdx,  [rip + 0x149c2b] "__swift5_types" ; 0x10014e12d dsdump_1.__TEXT.__cstring
    15   0x100004502 <+58>:   mov   rdi,  rax  
   *16   0x100004505 <+61>:   call  0x10002229e  ; dyld3::MachOLoaded::findSectionContent(char const*, char const*, unsigned long long&) const
    17   0x10000450a <+66>:   test  rax,  rax  
   *18   0x10000450d <+69>:   je    0x100004c0c <+1860> 
    19   0x100004513 <+75>:   mov   r12,  rax  
    20   0x100004516 <+78>:   mov   rax,  qword ptr [rbp - 0x30]  
    21   0x10000451a <+82>:   test  rax,  rax  
   *22   0x10000451d <+85>:   je    0x100004c0c <+1860> 
    23   0x100004523 <+91>:   mov   qword ptr [rbp - 0x90],  rbx  
    24   0x10000452a <+98>:   cmp   rax,  0x4  
   *25   0x10000452e <+102>:  jb    0x100004b46 <+1662> 
    26   0x100004534 <+108>:  movabs r13,  0x1fffffffffffffff  
    27   0x10000453e <+118>:  lea   r15,  [rip + 0x4517db] moduleDescriptorDictionary ; 0x100455d20 dsdump_1.__DATA.__bss
    28   0x100004545 <+125>:  xor   ebx,  ebx  
    29   0x100004547 <+127>:  mov   qword ptr [rbp - 0x48],  r12  
    30   0x10000454b <+131>:  lea   rax,  [r12 + 4*rbx]  
    31   0x10000454f <+135>:  movsxd rcx,  dword ptr [r12 + 4*rbx]  
    32   0x100004553 <+139>:  lea   r14,  [rax + 4*rcx]  
    33   0x100004557 <+143>:  mov   rdi,  r14  
   *34   0x10000455a <+146>:  call  0x100004cb8  ; payload::LoadToDiskTranslator<swift::TargetContextDescriptor<swift::InProcess>, false>::disk()
    35   0x10000455f <+151>:  mov   ecx,  dword ptr [rax + 0x4]  
    36   0x100004562 <+154>:  mov   qword ptr [rbp - 0x38],  r14  
    37   0x100004566 <+158>:  test  ecx,  ecx  
   *38   0x100004568 <+160>:  je    0x1000045c9 <+257> 
    39   0x10000456a <+162>:  add   rax,  0x4  
    40   0x10000456e <+166>:  mov   r14,  qword ptr [rbp - 0x38]  
    41   0x100004572 <+170>:  mov   edx,  ecx  
    42   0x100004574 <+172>:  and   edx,  -0x2  
    43   0x100004577 <+175>:  movsxd rdx,  edx  
    44   0x10000457a <+178>:  add   rdx,  rax  
    45   0x10000457d <+181>:  test  cl,  0x1  
   *46   0x100004580 <+184>:  je    0x100004585 <+189> 
->  47   0x100004582 <+186>:  mov   rdx,  qword ptr [rdx]  
    48   0x100004585 <+189>:  test  rdx,  rdx

Hope this provides you with enough information. If you need anything else please let me know and if you ever decide to push the source for this version I am fairly confident I could fix it myself.

Thanks again for taking the time!

@duraki
Copy link

duraki commented Mar 14, 2022

Possibly related to #30 (comment). Basically, dsdump fixed allocated offset gets to some edge-case where the app offset yields the same or bigger value, such overlapping the dsdump bin allocation.

@malhal
Copy link
Contributor

malhal commented Mar 23, 2022

-oc works for me but -sc seg faults

dsdump -sc /usr/libexec/sharingd -a x86_64
WARNING: couldn't find address 0x46f8f0b76 (0x46f8f0b76) in binary!
zsh: segmentation fault  dsdump -sc /usr/libexec/sharingd -a x86_64

macOS 12.3
M1 Air
dsdump Version: 0.8.0 Built: (12:52:07, Feb 8 2022)

@ynyyn
Copy link

ynyyn commented Jul 8, 2022

It seems that somehow for dsdump, the next closest VM region after (0x400000000) now is with a protection of (vm_prot_t)0x03 (rw-) when running on Monterey. Examined with Instruments, it was MALLOC_NANO.

MALLOC_SMALL	0x101000000 - 0x103000000	rw-/rwx	
MALLOC_NANO	0x600000000000 - 0x600020000000	rw-/rwx	
Stack Guard	0x7ff7bbf00000 - 0x7ff7bf700000	---/rwx	

And bypassing this protection check does not work indeed. mmap would return -1 with error Invalid argument.

if (info.protection != VM_PROT_NONE) {

P.S. run dsdump (0.8.3, 74ee2c3, with patched) with environment variable DEBUG=1, we could see some debug log printed like this:

...
   mem for 0x000400000000-0x000408000000 in dsdumpstruct vm_region_basic_info_64 {
vm_prot_t protection : 3
vm_prot_t max_protection : 7
vm_inherit_t inheritance : 1
boolean_t shared : 0
boolean_t reserved : 0
memory_object_offset_t offset : 0
vm_behavior_t behavior : 0
unsigned short user_wired_count : 0
}
mem for expected file 225200
mmap failed! Invalid argument 22, will try an address
...

Then, dsdump will fallback to another trial of mmap, and this time it seems success but actually not. The address return by mmap is not -1 but invalid either*, dsdump will hit segmentation fault once it starts reading Mach-O upon this address.

...
mmap mapped to addres 0x400000000
[1] segmentation fault

*Correction: the fallback mmap (which is without MAP_FIXED flag) did succeed, which would map file to higher address like 0x00007FF7_BFF00000, but dsdump falsely truncated its higher order bits to 0x000007F7_BFF00000 (7FF7->7F7) when reading, and that results to segmentation fault.

return reinterpret_cast<T*>(ARM64E_POINTER(retT)) ;

@ynyyn
Copy link

ynyyn commented Jul 8, 2022

The clues above inspired me.

For Monterey, running the old stable release (dsdump_compiled.zip, 1a8857e) with env MallocNanoZone=0 should work to some degree.

# Use the old dsdump from stable release.
$ dsdump
Version: 0.1.0 Built: (16:31:02, Jul  5 2020) dsdump [option..] <mach-o-file>

# Normally, it refused to do job on Monterey.
$ dsdump --objc dsdump
0x400000000 is mapped to existing memory, exiting

# To make it work, run it with MallocNanoZone=0. 
$ MallocNanoZone=0 dsdump --objc dsdump
@protocol NSObject
 -[NSObject isEqual:]
...
...

Note: This trick does not work for beta version.
Related discussions: https://stackoverflow.com/a/69861354/9164600, https://reviews.llvm.org/D114825

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants