1
2
3
4
5
6
7
8
9
10
11
12
13
14 package time
15
16 import (
17 "bytes"
18 "errors"
19 "runtime"
20
21 "github.com/chaos-mesh/chaos-mesh/pkg/mapreader"
22 "github.com/chaos-mesh/chaos-mesh/pkg/mock"
23 "github.com/chaos-mesh/chaos-mesh/pkg/ptrace"
24 )
25
26
27
28 var fakeImage = []byte{
29 0xb8, 0xe4, 0x00, 0x00, 0x00,
30 0x0f, 0x05,
31 0xba, 0x01, 0x00, 0x00, 0x00,
32 0x89, 0xf9,
33 0xd3, 0xe2,
34 0x48, 0x8d, 0x0d, 0x74, 0x00, 0x00, 0x00,
35 0x48, 0x63, 0xd2,
36 0x48, 0x85, 0x11,
37 0x74, 0x6b,
38 0x48, 0x8d, 0x15, 0x6d, 0x00, 0x00, 0x00,
39 0x4c, 0x8b, 0x46, 0x08,
40 0x48, 0x8b, 0x0a,
41 0x48, 0x8d, 0x15, 0x67, 0x00, 0x00, 0x00,
42 0x48, 0x8b, 0x3a,
43 0x4a, 0x8d, 0x14, 0x07,
44 0x48, 0x81, 0xfa, 0x00, 0xca, 0x9a, 0x3b,
45 0x7e, 0x1c,
46 0x0f, 0x1f, 0x40, 0x00,
47 0x48, 0x81, 0xef, 0x00, 0xca, 0x9a, 0x3b,
48 0x48, 0x83, 0xc1, 0x01,
49 0x49, 0x8d, 0x14, 0x38,
50 0x48, 0x81, 0xfa, 0x00, 0xca, 0x9a, 0x3b,
51 0x7f, 0xe8,
52 0x48, 0x85, 0xd2,
53 0x79, 0x1e,
54 0x4a, 0x8d, 0xbc, 0x07, 0x00, 0xca, 0x9a,
55 0x3b,
56 0x0f, 0x1f, 0x00,
57 0x48, 0x89, 0xfa,
58 0x48, 0x83, 0xe9, 0x01,
59 0x48, 0x81, 0xc7, 0x00, 0xca, 0x9a, 0x3b,
60 0x48, 0x85, 0xd2,
61 0x78, 0xed,
62 0x48, 0x01, 0x0e,
63 0x48, 0x89, 0x56, 0x08,
64 0xc3,
65
66 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
67 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
68 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
69 }
70
71
72 func ModifyTime(pid int, deltaSec int64, deltaNsec int64, clockIdsMask uint64) error {
73
74 if err := mock.On("ModifyTimeError"); err != nil {
75 if e, ok := err.(error); ok {
76 return e
77 }
78 if ignore, ok := err.(bool); ok && ignore {
79 return nil
80 }
81 }
82
83 runtime.LockOSThread()
84 defer func() {
85 runtime.UnlockOSThread()
86 }()
87
88 program, err := ptrace.Trace(pid)
89 if err != nil {
90 return err
91 }
92 defer func() {
93 err = program.Detach()
94 if err != nil {
95 log.Error(err, "fail to detach program", "pid", program.Pid())
96 }
97 }()
98
99 var vdsoEntry *mapreader.Entry
100 for index := range program.Entries {
101
102 e := program.Entries[len(program.Entries)-index-1]
103 if e.Path == "[vdso]" {
104 vdsoEntry = &e
105 break
106 }
107 }
108 if vdsoEntry == nil {
109 return errors.New("cannot find [vdso] entry")
110 }
111
112
113
114 constImageLen := len(fakeImage) - 24
115 var fakeEntry *mapreader.Entry
116
117
118 for _, e := range program.Entries {
119 e := e
120
121 image, err := program.ReadSlice(e.StartAddress, uint64(constImageLen))
122 if err != nil {
123 continue
124 }
125
126 if bytes.Equal(*image, fakeImage[0:constImageLen]) {
127 fakeEntry = &e
128 log.Info("found injected image", "addr", fakeEntry.StartAddress)
129 break
130 }
131 }
132 if fakeEntry == nil {
133 fakeEntry, err = program.MmapSlice(fakeImage)
134 if err != nil {
135 return err
136 }
137 }
138 fakeAddr := fakeEntry.StartAddress
139
140
141 err = program.WriteUint64ToAddr(fakeAddr+139, clockIdsMask)
142 if err != nil {
143 return err
144 }
145
146
147 err = program.WriteUint64ToAddr(fakeAddr+147, uint64(deltaSec))
148 if err != nil {
149 return err
150 }
151
152
153 err = program.WriteUint64ToAddr(fakeAddr+155, uint64(deltaNsec))
154 if err != nil {
155 return err
156 }
157
158 originAddr, err := program.FindSymbolInEntry("clock_gettime", vdsoEntry)
159 if err != nil {
160 return err
161 }
162
163 err = program.JumpToFakeFunc(originAddr, fakeAddr)
164 return err
165 }
166