精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

硬核!如何在容器中做時間漫游者

存儲 存儲軟件
分布式數(shù)據(jù)庫要實現(xiàn)全局一致性快照,很多方案使用時間做邏輯時鐘,所以需要解決不同節(jié)點之間時鐘一致的問題。

[[402031]]

本文轉(zhuǎn)載自微信公眾號「董澤潤的技術筆記」,作者董澤潤。轉(zhuǎn)載本文請聯(lián)系董澤潤的技術筆記公眾號。

題目稍有些標題黨,最近公司想用 chaos-mesh 對 k8s 做混沌測試,開始做前期的調(diào)研,發(fā)現(xiàn) pingcap[1] 對時間的注入非常硬核,而且最終方案居然是實習生構思出來的 ^^ 感謝 pingcap 貢獻的項目

TL;DR: 通過劫持 vdso, 將時間函數(shù)跳轉(zhuǎn)到 hack 過的匯編指令來實現(xiàn) time skew. 原理不難懂,但細節(jié)超多,參考官方文檔[2]

為什么需要 time skew

可以參考 Chaos Mesh - 讓時間在容器中自由搖擺[3], 簡單來說就是:

分布式數(shù)據(jù)庫要實現(xiàn)全局一致性快照,很多方案使用時間做邏輯時鐘,所以需要解決不同節(jié)點之間時鐘一致的問題。但往往物理節(jié)點上的物理時間總是會出現(xiàn)偏差,不管是使用 NPT 服務同步也好,或者其他方法總是沒辦法完全避免出現(xiàn)誤差,這時候如果我們的應用不能夠很好的處理這樣的情況的話,就可能造成無法預知的錯誤。

其實這很符合工程設計哲學:design for failure, 任何一個硬件或是軟件都會有錯誤(fault),系統(tǒng)如何在不影響對外提供服務的前提下,如何處理這些故障,就是我們常說的 fault tolerance

但是對于非金融業(yè)務來說,時間偏移一點影響并不大,相比其它 chaos, time的場景還是受限一些

如何注入

從實體機的經(jīng)驗來看,所謂的混沌測試都比較直觀的,比如用 tc 做網(wǎng)絡的丟包,限速來模擬網(wǎng)絡故障,使用 stress 模擬 cpu 壓力。但是在容器中做如何模擬 time skew 呢?

如果直接使用 linux date 命令修改,會影響到宿主機上其它所有容器。有沒有方法能只影響某個容器?

之前發(fā)過一篇文章 時鐘源為什么會影響性能[4], 從中可以看到,go 調(diào)用系統(tǒng)時間函數(shù)時,會先調(diào)用 vdso 的代碼,如果時鐘源符合條件,直接在用戶空間完成,并不會進入內(nèi)核空間,所以針對這一現(xiàn)象,syscall 劫持的方法就不能使用了

那么是否可以直接修改 vdso 段代碼呢?

查看 vdso

  1. # cat /proc/1970/maps 
  2. ...... 
  3. 7ffe8478a000-7ffe847ab000 rw-p 00000000 00:00 0                          [stack] 
  4. 7ffe847bb000-7ffe847be000 r--p 00000000 00:00 0                          [vvar] 
  5. 7ffe847be000-7ffe847bf000 r-xp 00000000 00:00 0                          [vdso] 
  6. ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0                  [vsyscall] 

可以看到 vdso 代碼段的起始邏輯地址,同時注意權限位是 r-xp, 這就意味著用戶態(tài)的進程是無法直接修改該內(nèi)容。

真的就沒辦法了嘛?有的,ptrace[5] 法力無邊

The ptrace() system call provides a means by which one process (the "tracer") may observe and control the execution of another process (the "tracee"), and examine and change the tracee's memory and registers. It is primarily used to implement breakpoint debugging and system call tracing.

ptrace 提供了一種修改和觀察其它進程的手段,包括修改內(nèi)存值和寄存器,巧了這些 chaos-mesh 都用到了。如何實現(xiàn) go 調(diào)試器[6] 這篇文章也講了 ptrace 的用途,很棒的文章。

整體實現(xiàn)

這就是簡單的流程圖,主要代碼都是 time_linux_amd64.go[7], 當前僅支持 linux amd64 平臺,不支持 Windows/MacOS

  1. // ModifyTime modifies time of target process 
  2. func ModifyTime(pid int, deltaSec int64, deltaNsec int64, clockIdsMask uint64) error { 
  3.   ...... 
  4.  runtime.LockOSThread() // 將當前 goroutine 綁定底層線程 
  5.  defer func() { 
  6.   runtime.UnlockOSThread() 
  7.  }() 
  8.  
  9.  program, err := ptrace.Trace(pid) // ptrace 獲得 program 
  10.  if err != nil { 
  11.   return err 
  12.  } 
  13.  defer func() { 
  14.   err = program.Detach() 
  15.   if err != nil { 
  16.    log.Error(err, "fail to detach program""pid", program.Pid()) 
  17.   } 
  18.  }() 
  19.  
  20.  var vdsoEntry *mapreader.Entry // 遍歷 entry 找到 vdso 
  21.  for index := range program.Entries { 
  22.   // reverse loop is faster 
  23.   e := program.Entries[len(program.Entries)-index-1] 
  24.   if e.Path == "[vdso]" { 
  25.    vdsoEntry = &e 
  26.    break 
  27.   } 
  28.  } 
  29.  if vdsoEntry == nil { 
  30.   return errors.New("cannot find [vdso] entry"
  31.  } 
  32.  
  33.  // minus tailing variable part 
  34.  // 24 = 3 * 8 because we have three variables 
  35.  constImageLen := len(fakeImage) - 24 
  36.  var fakeEntry *mapreader.Entry 
  37.  
  38.  // find injected image to avoid redundant inject (which will lead to memory leak) 
  39.  for _, e := range program.Entries { 
  40.   e := e 
  41.  
  42.   image, err := program.ReadSlice(e.StartAddress, uint64(constImageLen)) 
  43.   if err != nil { 
  44.    continue 
  45.   } 
  46.  
  47.   if bytes.Equal(*image, fakeImage[0:constImageLen]) { 
  48.    fakeEntry = &e // 遍歷找到 fake Image Entry,不能重復生成 
  49.    log.Info("found injected image""addr", fakeEntry.StartAddress) 
  50.    break 
  51.   } 
  52.  } 
  53.  if fakeEntry == nil { // 如果 fakeEntry 不存在,用 Mmap 分配內(nèi)存,內(nèi)容是 fakeImage 匯編指令 
  54.   fakeEntry, err = program.MmapSlice(fakeImage) 
  55.   if err != nil { 
  56.    return err 
  57.   } 
  58.  } 
  59.  fakeAddr := fakeEntry.StartAddress 
  60.  
  61.  // 139 is the index of CLOCK_IDS_MASK in fakeImage 寫 clockidsmask 
  62.  err = program.WriteUint64ToAddr(fakeAddr+139, clockIdsMask) 
  63.  if err != nil { 
  64.   return err 
  65.  } 
  66.  
  67.  // 147 is the index of TV_SEC_DELTA in fakeImage 寫偏移量秒 
  68.  err = program.WriteUint64ToAddr(fakeAddr+147, uint64(deltaSec)) 
  69.  if err != nil { 
  70.   return err 
  71.  } 
  72.  
  73.  // 155 is the index of TV_NSEC_DELTA in fakeImage 寫偏移量納秒 
  74.  err = program.WriteUint64ToAddr(fakeAddr+155, uint64(deltaNsec)) 
  75.  if err != nil { 
  76.   return err 
  77.  } 
  78.   // 找到 clock_gettime 在 vdso 中的位置 
  79.  originAddr, err := program.FindSymbolInEntry("clock_gettime", vdsoEntry) 
  80.  if err != nil { 
  81.   return err 
  82.  } 
  83.   // originAddr 位置 hijack, 寫上 jump 指令,跳轉(zhuǎn)到 fakeImage 
  84.  err = program.JumpToFakeFunc(originAddr, fakeAddr) 
  85.  return err 

代碼寫上了注釋,分別對應上面的流程圖。下面分解來看。

1. Ptrace

  1. type TracedProgram struct { 
  2.  pid     int 
  3.  tids    []int 
  4.  Entries []mapreader.Entry 
  5.  
  6.  backupRegs *syscall.PtraceRegs 
  7.  backupCode []byte 

TracedProgram 結(jié)構體比較簡單,pid 是待注入 chaos 的進程 id, 同時 tids 保存所有的線程 id, Entries 是進程邏輯地址空間,

Trace 函數(shù)在代碼 ptrace_linux_amd64.go[8] 中

通過讀取 /proc/{pid}/task 獲取進程的所有線程,然后分別對所有線程執(zhí)行 linux ptrace 調(diào)用。然后生成 Entries, 什么是 Entry 呢?就是上文提到的 /proc/{pid}/maps 內(nèi)容

  1. ...... 
  2. 7ffe8478a000-7ffe847ab000 rw-p 00000000 00:00 0                          [stack] 
  3. 7ffe847bb000-7ffe847be000 r--p 00000000 00:00 0                          [vvar] 
  4. 7ffe847be000-7ffe847bf000 r-xp 00000000 00:00 0                          [vdso] 
  5. ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0                  [vsyscall] 

2. Mmap FakeImage

查找 vdso[9], 如何失敗,直接退出。一般 vdso 都在最后,所以從尾開始遍歷

同時還要查找 fakeEntry, 如果存在,直接復用。否則會造成內(nèi)存泄漏,當然了,一直創(chuàng)建新的 fakeEntry .....

  1. // MmapSlice mmaps a slice and return it's addr 
  2. func (p *TracedProgram) MmapSlice(slice []byte) (*mapreader.Entry, error) { 
  3.  size := uint64(len(slice)) 
  4.  
  5.  addr, err := p.Mmap(size, 0) 
  6.  if err != nil { 
  7.   return nil, errors.WithStack(err) 
  8.  } 
  9.  
  10.  err = p.WriteSlice(addr, slice) 
  11.  if err != nil { 
  12.   return nil, errors.WithStack(err) 
  13.  } 
  14.  
  15.  return &mapreader.Entry{ 
  16.   StartAddress: addr, 
  17.   EndAddress:   addr + size
  18.   Privilege:    "rwxp"
  19.   PaddingSize:  0, 
  20.   Path:         ""
  21.  }, nil 

注意,這不是簡單的調(diào)用 Mmap Syscall !!! ptrace.Syscall[12] 是利用 ptrace 控制進程,讓目標進程單步執(zhí)行 syscall

  1. // Syscall runs a syscall at main thread of process 
  2. func (p *TracedProgram) Syscall(number uint64, args ...uint64) (uint64, error) { 
  3.  err := p.Protect() // 保存目標進程的寄存器 
  4.  if err != nil { 
  5.   return 0, err 
  6.  } 
  7.  
  8.  var regs syscall.PtraceRegs 
  9.  
  10.  err = syscall.PtraceGetRegs(p.pid, &regs) 
  11.  if err != nil { 
  12.   return 0, err 
  13.  } 
  14.  regs.Rax = number // 設置操作 syscall number, 填充其它參數(shù) 
  15.  for index, arg := range args { 
  16.   // All these registers are hard coded for x86 platform 
  17.   if index == 0 { 
  18.    regs.Rdi = arg 
  19.   } else if index == 1 { 
  20.    regs.Rsi = arg 
  21.   } else if index == 2 { 
  22.    regs.Rdx = arg 
  23.   } else if index == 3 { 
  24.    regs.R10 = arg 
  25.   } else if index == 4 { 
  26.    regs.R8 = arg 
  27.   } else if index == 5 { 
  28.    regs.R9 = arg 
  29.   } else { 
  30.    return 0, fmt.Errorf("too many arguments for a syscall"
  31.   } 
  32.  } 
  33.  err = syscall.PtraceSetRegs(p.pid, &regs) 
  34.  if err != nil { 
  35.   return 0, err 
  36.  } 
  37.  
  38.  ip := make([]byte, ptrSize) 
  39.  
  40.  // We only support x86-64 platform now, so using hard coded `LittleEndian` here is ok. 設置 rip 寄存器 
  41.  binary.LittleEndian.PutUint16(ip, 0x050f) 
  42.  _, err = syscall.PtracePokeData(p.pid, uintptr(p.backupRegs.Rip), ip) 
  43.  if err != nil { 
  44.   return 0, err 
  45.  } 
  46.  
  47.  err = p.Step() // 單步執(zhí)行 
  48.  if err != nil { 
  49.   return 0, err 
  50.  } 
  51.  
  52.  err = syscall.PtraceGetRegs(p.pid, &regs) 
  53.  if err != nil { 
  54.   return 0, err 
  55.  } 
  56.  
  57.  return regs.Rax, p.Restore() // 獲取返回值,并且恢復寄存器 

參考代碼的注釋,搞過嵌入式的肯定熟悉:保存寄存器現(xiàn)場,設置新的寄存器值為 syscall number 以及參數(shù),最后設置指令寄存器 rip 單步執(zhí)行,就完成了讓目標進程執(zhí)行 mmap 的操作,最后也要恢復寄存器,還原現(xiàn)場。

這里為什么 rip 寄存器要設置成 0x050f 呢???其實這是 syscall 的操作碼

另外 p.WriteSlice 是使用 syscall process_vm_writev 將數(shù)據(jù)寫入目標進程的內(nèi)存邏輯地址空間。

3. FindSymbolInEntry

  1. ~# file /tmp/vdso.so 
  2. /tmp/vdso.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=17d65245b85cd032de7ab130d053551fb0bd284a, stripped 
  3. ~# objdump -T /tmp/vdso.so 
  4.  
  5. /tmp/vdso.so:     file format elf64-x86-64 
  6.  
  7. DYNAMIC SYMBOL TABLE
  8. 0000000000000950  w   DF .text 00000000000000a1  LINUX_2.6   clock_gettime 
  9. 00000000000008a0 g    DF .text 0000000000000083  LINUX_2.6   __vdso_gettimeofday 
  10. 0000000000000a00  w   DF .text 000000000000000a  LINUX_2.6   clock_getres 
  11. 0000000000000a00 g    DF .text 000000000000000a  LINUX_2.6   __vdso_clock_getres 
  12. 00000000000008a0  w   DF .text 0000000000000083  LINUX_2.6   gettimeofday 
  13. 0000000000000930 g    DF .text 0000000000000015  LINUX_2.6   __vdso_time 
  14. 0000000000000930  w   DF .text 0000000000000015  LINUX_2.6   time 
  15. 0000000000000950 g    DF .text 00000000000000a1  LINUX_2.6   __vdso_clock_gettime 
  16. 0000000000000000 g    DO *ABS* 0000000000000000  LINUX_2.6   LINUX_2.6 
  17. 0000000000000a10 g    DF .text 000000000000002a  LINUX_2.6   __vdso_getcpu 
  18. 0000000000000a10  w   DF .text 000000000000002a  LINUX_2.6   getcpu 

FindSymbolInEntry 函數(shù)很簡單,就是要找到 clock_gettime 在 vdso 中的地址,參考我之前的文章,上面是 dump 出來的符號表

4. JumpToFakeFunc

  1. // JumpToFakeFunc writes jmp instruction to jump to fake function 
  2. func (p *TracedProgram) JumpToFakeFunc(originAddr uint64, targetAddr uint64) error { 
  3.  instructions := make([]byte, 16) 
  4.  
  5.  // mov rax, targetAddr; 
  6.  // jmp rax ; 
  7.  instructions[0] = 0x48 
  8.  instructions[1] = 0xb8 
  9.  binary.LittleEndian.PutUint64(instructions[2:10], targetAddr) 
  10.  instructions[10] = 0xff 
  11.  instructions[11] = 0xe0 
  12.  
  13.  return p.PtraceWriteSlice(originAddr, instructions) 

JumpToFakeFunc[13], 修改 vdso 符號表中的匯編代碼,使所有調(diào)用 clock_gettime 的都跳轉(zhuǎn)到我們 fakeEntry 的地址,劫持 vdso

FakeImage

  1. var fakeImage = []byte{ 
  2.  0xb8, 0xe4, 0x00, 0x00, 0x00, //mov    $0xe4,%eax 
  3.  0x0f, 0x05, //syscall 
  4.  0xba, 0x01, 0x00, 0x00, 0x00, //mov    $0x1,%edx 
  5.  0x89, 0xf9, //mov    %edi,%ecx 
  6.  0xd3, 0xe2, //shl    %cl,%edx 
  7.  0x48, 0x8d, 0x0d, 0x74, 0x00, 0x00, 0x00, //lea    0x74(%rip),%rcx        # <CLOCK_IDS_MASK> 
  8.  0x48, 0x63, 0xd2, //movslq %edx,%rdx 
  9.  0x48, 0x85, 0x11, //test   %rdx,(%rcx) 
  10.  0x74, 0x6b, //je     108a <clock_gettime+0x8a> 
  11.  0x48, 0x8d, 0x15, 0x6d, 0x00, 0x00, 0x00, //lea    0x6d(%rip),%rdx        # <TV_SEC_DELTA> 
  12.  0x4c, 0x8b, 0x46, 0x08, //mov    0x8(%rsi),%r8 
  13.  0x48, 0x8b, 0x0a, //mov    (%rdx),%rcx 
  14.  0x48, 0x8d, 0x15, 0x67, 0x00, 0x00, 0x00, //lea    0x67(%rip),%rdx        # <TV_NSEC_DELTA> 
  15.  0x48, 0x8b, 0x3a, //mov    (%rdx),%rdi 
  16.  0x4a, 0x8d, 0x14, 0x07, //lea    (%rdi,%r8,1),%rdx 
  17.  0x48, 0x81, 0xfa, 0x00, 0xca, 0x9a, 0x3b, //cmp    $0x3b9aca00,%rdx 
  18.  0x7e, 0x1c, //jle    <clock_gettime+0x60> 
  19.  0x0f, 0x1f, 0x40, 0x00, //nopl   0x0(%rax) 
  20.  0x48, 0x81, 0xef, 0x00, 0xca, 0x9a, 0x3b, //sub    $0x3b9aca00,%rdi 
  21.  0x48, 0x83, 0xc1, 0x01, //add    $0x1,%rcx 
  22.  0x49, 0x8d, 0x14, 0x38, //lea    (%r8,%rdi,1),%rdx 
  23.  0x48, 0x81, 0xfa, 0x00, 0xca, 0x9a, 0x3b, //cmp    $0x3b9aca00,%rdx 
  24.  0x7f, 0xe8, //jg     <clock_gettime+0x48> 
  25.  0x48, 0x85, 0xd2, //test   %rdx,%rdx 
  26.  0x79, 0x1e, //jns    <clock_gettime+0x83> 
  27.  0x4a, 0x8d, 0xbc, 0x07, 0x00, 0xca, 0x9a, //lea    0x3b9aca00(%rdi,%r8,1),%rdi 
  28.  0x3b,             // 
  29.  0x0f, 0x1f, 0x00, //nopl   (%rax) 
  30.  0x48, 0x89, 0xfa, //mov    %rdi,%rdx 
  31.  0x48, 0x83, 0xe9, 0x01, //sub    $0x1,%rcx 
  32.  0x48, 0x81, 0xc7, 0x00, 0xca, 0x9a, 0x3b, //add    $0x3b9aca00,%rdi 
  33.  0x48, 0x85, 0xd2, //test   %rdx,%rdx 
  34.  0x78, 0xed, //js     <clock_gettime+0x70> 
  35.  0x48, 0x01, 0x0e, //add    %rcx,(%rsi) 
  36.  0x48, 0x89, 0x56, 0x08, //mov    %rdx,0x8(%rsi) 
  37.  0xc3, //retq 
  38.  // constant 
  39.  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //CLOCK_IDS_MASK 
  40.  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //TV_SEC_DELTA 
  41.  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //TV_NSEC_DELTA 

fakeImage 最后三個參數(shù)是偏移量,以及傳遞的 CLOCK_IDS_MASK, 這些匯編是什么意思呢???

查看匯編操作碼[14],0xe4 是系統(tǒng)調(diào)用 clock_gettime 的操作碼,后續(xù)都是對結(jié)果進行注入,要么增要么減,制造偏移量 time skew

測試案例

  1. # git clone https://github.com/chaos-mesh/chaos-mesh 
  2. # cd chaos-mesh; make watchmaker 

首先下載 chaos-mesh, 然后編譯 watchmaker, 這是一個方便注入的小工具。

  1. package main 
  2.  
  3. import ( 
  4.         "fmt" 
  5.         "time" 
  6.  
  7. func main() { 
  8.         fmt.Println("start print time"
  9.         for { 
  10.                 fmt.Printf("now %v\n"time.Now()) 
  11.                 time.Sleep(time.Second * 20) 
  12.         } 

上面是測試的代碼,每隔 20 打印當前時間,編譯執(zhí)行,同時用 watchmaker 注入 time skew

  1. # ./watchmaker -pid 1970 -sec_delta -300 

隔一段時間間后,再次執(zhí)行停止執(zhí)行注入

  1. # ./watchmaker -pid 1970 -sec_delta 0 
  1. # ./test 
  2. start print time 
  3. now 2021-05-26 03:31:46.701902309 +0000 UTC m=+0.000131483 
  4. now 2021-05-26 03:32:06.702230391 +0000 UTC m=+20.000459585 
  5. now 2021-05-26 03:32:26.702406569 +0000 UTC m=+40.000635793 
  6. now 2021-05-26 03:27:46.702688433 +0000 UTC m=+60.000918297 
  7. ^@now 2021-05-26 03:28:06.702914898 +0000 UTC m=+80.001145022 
  8. now 2021-05-26 03:28:26.703120914 +0000 UTC m=+100.001350878 
  9. now 2021-05-26 03:28:46.703398463 +0000 UTC m=+120.001628357 
  10. ^@now 2021-05-26 03:29:06.703707514 +0000 UTC m=+140.001937468 
  11. now 2021-05-26 03:29:26.704025346 +0000 UTC m=+160.002255480 
  12. now 2021-05-26 03:29:46.704302832 +0000 UTC m=+180.002532766 
  13. ^@now 2021-05-26 03:35:06.704505387 +0000 UTC m=+200.002735491 
  14.  
  15. now 2021-05-26 03:35:26.704931111 +0000 UTC m=+220.003161235 

上面是代碼執(zhí)行的輸出,可以看到 03:32:26 之后時間變成了 03:27:46, 停止注入后恢復

Limits

當前的實現(xiàn),停止注入,并不會還原 vdso 代碼,也就是說 fakeEntry 會一直存在,每次 clock_gettime 都會跳轉(zhuǎn),只不過偏移量為 0 而己

由于以上原因的存在,注入及注入之后的 clock_gettime 都是走的 syscall 系統(tǒng)調(diào)用,性能很慢,敏感業(yè)務需要重啟,細節(jié)可以參考我之前的文章《時鐘源為什么會影響性能》

當前注入,只能針對容器里的主進程,那些 fork 出來,派生出來的無做做到注入

以上限制有沒有優(yōu)化空間呢?當然有,問題都是用來解決的嘛~

小結(jié)

這次分享就這些,以后面還會分享更多的內(nèi)容,如果感興趣,可以關注并點擊左下角的分享轉(zhuǎn)發(fā)哦(:

參考資料

[1]Chaos Mesh - 讓時間在容器中自由搖擺: https://www.jianshu.com/p/6425050591b7,

[2]官方文檔: https://chaos-mesh.org/docs/chaos_experiments/timechaos_experiment/#limitation,

[3]讓時間在容器中自由搖擺: https://www.jianshu.com/p/6425050591b7,

[4]時鐘源為什么會影響性能: https://mp.weixin.qq.com/s/06SDQLzDprJf2AEaDnX-QQ,

[5]ptrace: https://man7.org/linux/man-pages/man2/ptrace.2.html,

[6]如何實現(xiàn) go 調(diào)試器: https://studygolang.com/articles/12804,

[7]time_linux_amd64.go: https://github.com/chaos-mesh/chaos-mesh/blob/master/pkg/time/time_linux_amd64.go#L72,

[8]ptrace_linux_amd64.go: https://github.com/chaos-mesh/chaos-mesh/blob/master/pkg/ptrace/ptrace_linux_amd64.go#L87,

[9]time_linux_amd64.go#L102 vdso: https://github.com/chaos-mesh/chaos-mesh/blob/master/pkg/time/time_linux_amd64.go#L102,

[10]program.MmapSlice: https://github.com/chaos-mesh/chaos-mesh/blob/master/pkg/time/time_linux_amd64.go#L132,

[11]FakeImage: https://github.com/chaos-mesh/chaos-mesh/blob/master/pkg/time/time_linux_amd64.go#L28,

[12]ptrace.Syscall: https://github.com/chaos-mesh/chaos-mesh/blob/master/pkg/ptrace/ptrace_linux_amd64.go#L251,

[13]JumpToFakeFunc: https://github.com/chaos-mesh/chaos-mesh/blob/master/pkg/ptrace/ptrace_linux_amd64.go#L480,

[14]匯編操作碼: https://chromium.googlesource.com/chromiumos/docs/+/master/constants/syscalls.md,

 

責任編輯:武曉燕 來源: 董澤潤的技術筆記
相關推薦

2021-09-03 09:06:42

代碼時間開發(fā)

2022-06-27 05:48:24

Kubernetes容器

2011-04-11 14:45:15

Oracle表系統(tǒng)時間

2015-08-07 10:10:18

LinuxDocker容器

2020-09-19 18:03:42

Docker

2018-07-02 06:33:25

物聯(lián)網(wǎng)手機漫游網(wǎng)絡

2017-09-18 10:05:15

WindowsLinux容器

2018-11-05 14:53:14

Go函數(shù)代碼

2021-04-02 14:23:12

WiFi網(wǎng)絡技術

2021-03-31 21:20:15

WiFi網(wǎng)絡漫游

2013-09-27 10:51:00

Github

2018-07-02 09:00:27

Linux特定時間運行命令

2022-01-05 18:19:30

容器鏡像Golang

2015-05-12 10:03:55

OpenStack環(huán)境容器編排Docker

2024-11-20 16:09:04

API開源Bruno

2022-04-20 11:40:51

元宇宙區(qū)塊鏈代幣

2019-08-13 16:10:38

UbuntuLinux時間同步

2014-11-18 00:45:58

UbuntuLXC容器

2014-05-07 09:56:48

Docker管理Linux容器

2019-07-08 08:59:41

Docker容器主機
點贊
收藏

51CTO技術棧公眾號

国产精品第七十二页| 亚洲大片免费看| 国产日韩中文在线| 美女福利视频在线观看| 黄色欧美在线| 日本精品免费观看高清观看| 亚洲乱码一区二区三区| 国产农村老头老太视频| 一区二区福利| 精品国产一区二区在线| 国产 xxxx| 麻豆久久久久| 欧美日韩一二三四五区| 国产一区一区三区| 欧美美女搞黄| 国产精品夜夜嗨| 国产精品18久久久久久首页狼| 蜜臀久久精品久久久用户群体| 香蕉一区二区| 日韩成人影院| 国产精品激情偷乱一区二区∴| **亚洲第一综合导航网站| 黄色片视频免费| 激情久久中文字幕| www日韩欧美| 国产美女免费网站| 理论片一区二区在线| 8x8x8国产精品| 国产视频一区二区视频| 国产在线88av| 亚洲伊人色欲综合网| 在线观看欧美激情| 成年人免费在线视频| 9人人澡人人爽人人精品| 91在线|亚洲| 亚洲无码久久久久| 奇米影视在线99精品| 国产69久久精品成人| 久久影院一区二区| 欧美区亚洲区| 米奇精品一区二区三区在线观看| 日韩福利在线视频| 国产99久久| 亚洲人成电影网站色| 亚洲国产精品自拍视频| 国内视频在线精品| 精品国产髙清在线看国产毛片| 手机免费av片| 亚洲精品tv| 欧美日韩在线精品一区二区三区激情| 国产福利视频在线播放| 黄色在线观看视频网站| 亚洲综合激情小说| 国产a级黄色大片| 99热国产在线| 一区二区三区四区不卡在线| 日本道在线视频| 国产激情小视频在线| 亚洲人成网站色在线观看| 亚洲啪啪av| 最新av网站在线观看| 国产精品情趣视频| 亚洲欧洲一二三| 成人福利网站| 国产一区二区视频在线看 | 午夜xxxxx| 欧美成人xxxx| 宅男噜噜噜66一区二区66| 欧美一级xxxx| 一区二区三区欧洲区| 欧美变态凌虐bdsm| 大尺度做爰床戏呻吟舒畅| 极品国产人妖chinesets亚洲人妖| 精品国产一区二区三区av性色| 特级特黄刘亦菲aaa级| 精品欧美午夜寂寞影院| 精品一区电影国产| 色欲狠狠躁天天躁无码中文字幕 | 9999精品| 日韩欧美国产麻豆| 一级欧美一级日韩片| 日韩在线影视| 中文字幕av一区二区| 天堂网avav| 亚洲欧洲综合| 国产精品九九九| 国产精品无码久久av| 国产成人免费视频网站| 好看的日韩精品| 国产youjizz在线| 亚洲色图19p| 国产精品无码av在线播放| 成人日韩av| 日韩欧美一二三区| 亚洲午夜久久久久久久久红桃| 欧美亚洲国产一区| 久国内精品在线| 超碰在线观看91| 韩国v欧美v日本v亚洲v| 狠狠色综合网站久久久久久久| 超碰免费在线| 亚洲国产另类av| 亚洲 激情 在线| 久久精品福利| www.日韩av.com| 国产一区二区99| 国产一区二区三区综合| 亚洲一区二区三区精品在线| 国产一区二区三区四区五区在线| 国内精品在线视频| 一区二区三区色| 男女啪啪网站视频| 成人av动漫| 北条麻妃一区二区三区中文字幕 | 阿v免费在线观看| 亚洲成av人片一区二区| 极品粉嫩美女露脸啪啪| 亚洲影院天堂中文av色| 九九久久精品一区| 夜夜躁日日躁狠狠久久av| 成人一区二区三区视频在线观看| 水蜜桃亚洲精品| 午夜影院在线播放| 欧美成人a在线| 97在线观看视频免费| 奶水喷射视频一区| 国产精品视频在线免费观看| 欧美成人高清在线| 欧美在线观看你懂的| 亚洲一区二区三区四区五区六区 | 国产极品尤物在线| 欧美午夜网站| 久久精品99国产精品酒店日本| 日本免费在线观看视频| 波多野结衣精品在线| 特级西西444| av一级久久| 中文字幕欧美日韩va免费视频| 久久艹免费视频| 成人av网站免费| 欧美中日韩在线| 欧美影院精品| 欧美成人性色生活仑片| 国产精品欧美综合亚洲| 国产精品久久精品日日| xxxx一级片| 成人免费看片39| 国产成人在线亚洲欧美| 欧美日韩在线中文字幕| 欧美日韩免费在线| 日本xxxx裸体xxxx| 日韩视频一区| 久久久久高清| 日韩大尺度黄色| 亚洲香蕉成人av网站在线观看| 国产精品福利网站| 国产精品视频久久久久久久| 成人蜜臀av电影| 妞干网在线视频观看| 久久动漫网址| 日本高清+成人网在线观看| 四虎影院在线域名免费观看| 欧美性极品xxxx做受| 国产交换配乱淫视频免费| 国产精品老牛| 日本在线免费观看一区| 国产在线|日韩| 色偷偷9999www| 国产免费福利视频| 一区二区三区四区乱视频| 色哟哟无码精品一区二区三区| 亚洲精品系列| 欧美久久在线| 97人人做人人爽香蕉精品| 久久久97精品| 蜜臀av中文字幕| 欧美性猛交xxxx免费看久久久| 国产一二三四五区| 久热成人在线视频| 青草全福视在线| 麻豆一区二区| 国产精品视频一区二区高潮| 黄色大片在线播放| 亚洲精品一区二区三区在线观看 | 色视频成人在线观看免| 在线免费看视频| 国产福利精品导航| 亚洲中文字幕无码中文字| 欧美日韩色图| 97人人模人人爽人人喊38tv| 极品视频在线| 中文字幕亚洲在线| 亚洲精品国产精| 色老头久久综合| 欧美在线视频第一页| 91在线精品一区二区| xxx国产在线观看| 伊人成人在线视频| 日韩一区二区电影在线观看| 日本免费一区二区视频| 人体精品一二三区| 手机电影在线观看| 亚洲一二三在线| 性欧美18一19性猛交| 色国产综合视频| 久久亚洲成人av| 国产精品电影院| 国产精品无码毛片| 欧美6一10sex性hd| 一本大道久久a久久精品综合| 天天色天天综合| www.亚洲在线| 91丝袜超薄交口足| 久久这里有精品15一区二区三区| 精品嫩模一区二区三区| 国产精品一区高清| 国产精品sss| 国产精品中文| 国产精品久久久久久久一区探花 | 日本中文字幕成人| 欧美aaaaaaa| 久久中文字幕在线视频| www.在线播放| 亚洲人成在线观看| 天堂v在线观看| 精品久久五月天| 91精品国自产| 欧美系列亚洲系列| 国产成人一级片| 午夜精品爽啪视频| 久视频在线观看| 亚洲精品日韩一| 手机av在线看| 国产精品传媒在线| 色屁屁草草影院ccyy.com| 久久久美女毛片| 亚洲欧美色图视频| av毛片久久久久**hd| 亚洲精品乱码久久久久久9色| 精品一区二区三区在线观看国产| 久久久国产欧美| 老牛国产精品一区的观看方式| 日本免费黄视频| 亚洲一区二区成人| 亚洲熟妇国产熟妇肥婆| 在线亚洲一区| 91国视频在线| 久久精品女人天堂| 日韩精品一区二区三区色欲av| 亚洲在线国产日韩欧美| 成人在线免费观看av| 国产日韩欧美一区在线| 欧美老熟妇喷水| 免费日韩精品中文字幕视频在线| 久久久久久久久久久视频| 国产精品一页| 国产男女激情视频| 日韩va亚洲va欧美va久久| 九九热在线免费| 精品一区二区影视| 自拍偷拍激情视频| 99久久久无码国产精品| 国产精品无码网站| 国产午夜精品久久久久久久| 国产手机在线观看| 中文一区在线播放| 欧美日韩亚洲在线| 久久精品蜜桃| 色妞色视频一区二区三区四区| 香蕉视频在线免费看| 久久亚洲国产精品| 波多野结衣在线观看| 欧美最猛黑人xxxx黑人猛叫黄| 欧美色999| 亚洲a级在线播放观看| 国产乱人伦精品一区| 欧洲亚洲一区二区| 在线观看免费一区二区| 日韩精品―中文字幕| 日本人妖一区二区| 亚洲精品无码久久久久久久| 成人黄色在线看| 男人的天堂官网| 亚洲激情图片小说视频| 久草国产精品视频| 欧美日韩性生活| 亚洲国产精品suv| 亚洲人成免费电影| 最新国产在线拍揄自揄视频| 69视频在线免费观看| 青青国产精品| 国产视频在线观看一区| 日韩片欧美片| 久久99久久99精品| 免费观看在线色综合| 超碰caoprom| 国产精品美女久久久久久久| 久久丫精品久久丫| 欧美日免费三级在线| 手机看片福利永久| yw.139尤物在线精品视频| 蜜桃av在线播放| 亚洲一区二区三区成人在线视频精品 | 亚洲午夜av在线| 伊人久久国产精品| 亚洲国产成人精品久久久国产成人一区| 高清福利在线观看| 国语对白做受69| 国产午夜亚洲精品一级在线| 久久综合九色99| 中国成人一区| 欧美成人黄色网址| 91亚洲午夜精品久久久久久| 国产成人久久久久| 在线视频国内自拍亚洲视频| 人妻精品一区二区三区| 久久韩国免费视频| 成人不卡视频| 久久久久久国产精品mv| 久久91成人| 国产精品久久中文字幕| 国产在线一区二区综合免费视频| 91精彩刺激对白露脸偷拍| 亚洲国产视频直播| jizz国产视频| 波霸ol色综合久久| 欧美不卡高清一区二区三区| 久99久视频| 亚洲天堂成人| 成年人看片网站| 一区二区三区资源| 国产老女人乱淫免费| 在线观看成人黄色| 国精产品一区二区三区有限公司| 麻豆一区区三区四区产品精品蜜桃| 欧美日韩网站| gogo亚洲国模私拍人体| √…a在线天堂一区| 一本久道久久综合无码中文| 亚洲精品久久久久中文字幕欢迎你| 亚洲综合图区| av在线不卡观看| 一本到12不卡视频在线dvd| 色噜噜狠狠一区二区三区狼国成人| 国产精品久久久久天堂| 亚洲香蕉在线视频| 欧美亚洲网站| 欧美wwwwwww| 一区二区中文字幕在线| 国产精品无码久久久久成人app| 日韩专区在线播放| 亚洲国产精选| 水蜜桃在线免费观看| 国产精品正在播放| 久久久久久久国产视频| 精品国产不卡一区二区三区| free性欧美| 久久av二区| 久久久久久久性潮| 免费看污污视频| 国产精品99久久久久久久女警 | 国内av免费观看| 亚洲精品午夜久久久| 成人无码一区二区三区| 日韩在线观看免费全| 午夜久久av| 国产 日韩 欧美在线| 久久夜色精品一区| 免费在线不卡av| 久久精品国产精品亚洲| 日韩精品中文字幕吗一区二区| 日本福利视频一区| 久久夜色精品国产噜噜av| 在线观看免费中文字幕| 欧美成人精品在线播放| 国产精品17p| 欧美三级午夜理伦三级| 国产精品久久福利| 亚洲女同志亚洲女同女播放| 青草青草久热精品视频在线观看| 波多野结衣在线观看一区二区三区 | 欧美sm极限捆绑bd| 看黄在线观看| 亚洲一二三区在线| 成人激情综合网站| 免费看毛片网站| 久久五月情影视| 日韩有码中文字幕在线| 欧美国产日韩另类| 午夜精品国产更新| 成人影视在线播放| 成人动漫在线视频| 日韩av高清在线观看| 老女人性淫交视频| 亚洲片在线资源| 国产电影一区| 欧洲av无码放荡人妇网站| 亚洲人123区| 青青久在线视频| 91丝袜脚交足在线播放|