...

Source file src/github.com/chaos-mesh/chaos-mesh/pkg/time/time_skew_amd64.go

Documentation: github.com/chaos-mesh/chaos-mesh/pkg/time

     1  // Copyright 2021 Chaos Mesh Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  // http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  //
    15  
    16  package time
    17  
    18  import (
    19  	"bytes"
    20  	"runtime"
    21  
    22  	"github.com/pkg/errors"
    23  
    24  	"github.com/chaos-mesh/chaos-mesh/pkg/mapreader"
    25  	"github.com/chaos-mesh/chaos-mesh/pkg/ptrace"
    26  )
    27  
    28  // timeSkewFakeImage is the filename of fake image after compiling
    29  const timeSkewFakeImage = "fake_clock_gettime.o"
    30  
    31  // vdsoEntryName is the name of the vDSO entry
    32  const vdsoEntryName = "[vdso]"
    33  
    34  // clockGettime is the target function would be replaced
    35  const clockGettime = "clock_gettime"
    36  
    37  // These three consts corresponding to the three extern variables in the fake_clock_gettime.c
    38  const (
    39  	externVarClockIdsMask = "CLOCK_IDS_MASK"
    40  	externVarTvSecDelta   = "TV_SEC_DELTA"
    41  	externVarTvNsecDelta  = "TV_NSEC_DELTA"
    42  )
    43  
    44  type TimeSkew struct {
    45  	deltaSeconds     int64
    46  	deltaNanoSeconds int64
    47  	clockIDsMask     uint64
    48  	fakeImage        *FakeImage
    49  }
    50  
    51  func NewTimeSkew(deltaSeconds int64, deltaNanoSeconds int64, clockIDsMask uint64) (*TimeSkew, error) {
    52  	var image *FakeImage
    53  	var err error
    54  
    55  	if image, err = LoadFakeImageFromEmbedFs(timeSkewFakeImage); err != nil {
    56  		return nil, errors.Wrap(err, "load fake image")
    57  	}
    58  
    59  	return NewTimeSkewWithCustomFakeImage(deltaSeconds, deltaNanoSeconds, clockIDsMask, image), nil
    60  }
    61  
    62  func NewTimeSkewWithCustomFakeImage(deltaSeconds int64, deltaNanoSeconds int64, clockIDsMask uint64, fakeImage *FakeImage) *TimeSkew {
    63  	return &TimeSkew{deltaSeconds: deltaSeconds, deltaNanoSeconds: deltaNanoSeconds, clockIDsMask: clockIDsMask, fakeImage: fakeImage}
    64  }
    65  
    66  func (it *TimeSkew) Inject(pid int) error {
    67  
    68  	runtime.LockOSThread()
    69  	defer func() {
    70  		runtime.UnlockOSThread()
    71  	}()
    72  
    73  	program, err := ptrace.Trace(pid)
    74  	if err != nil {
    75  		return errors.Wrapf(err, "ptrace on target process, pid: %d", pid)
    76  	}
    77  	defer func() {
    78  		err = program.Detach()
    79  		if err != nil {
    80  			log.Error(err, "fail to detach program", "pid", program.Pid())
    81  		}
    82  	}()
    83  
    84  	var vdsoEntry *mapreader.Entry
    85  	for index := range program.Entries {
    86  		// reverse loop is faster
    87  		e := program.Entries[len(program.Entries)-index-1]
    88  		if e.Path == vdsoEntryName {
    89  			vdsoEntry = &e
    90  			break
    91  		}
    92  	}
    93  	if vdsoEntry == nil {
    94  		return errors.Errorf("cannot find [vdso] entry, pid: %d", pid)
    95  	}
    96  
    97  	// minus tailing variable part
    98  	// every variable has 8 bytes
    99  	constImageLen := len(it.fakeImage.content) - 8*len(it.fakeImage.offset)
   100  	var fakeEntry *mapreader.Entry
   101  
   102  	// find injected image to avoid redundant inject (which will lead to memory leak)
   103  	for _, e := range program.Entries {
   104  		e := e
   105  
   106  		image, err := program.ReadSlice(e.StartAddress, uint64(constImageLen))
   107  		if err != nil {
   108  			continue
   109  		}
   110  
   111  		if bytes.Equal(*image, it.fakeImage.content[0:constImageLen]) {
   112  			fakeEntry = &e
   113  			log.Info("found injected image", "addr", fakeEntry.StartAddress, "pid", pid)
   114  			break
   115  		}
   116  	}
   117  
   118  	// target process has not been injected yet
   119  	if fakeEntry == nil {
   120  		fakeEntry, err = program.MmapSlice(it.fakeImage.content)
   121  		if err != nil {
   122  			return errors.Wrapf(err, "mmap fake image, pid: %d", pid)
   123  		}
   124  
   125  		originAddr, err := program.FindSymbolInEntry(clockGettime, vdsoEntry)
   126  		if err != nil {
   127  			return errors.Wrapf(err, "find origin clock_gettime in vdso, pid: %d", pid)
   128  		}
   129  
   130  		err = program.JumpToFakeFunc(originAddr, fakeEntry.StartAddress)
   131  		if err != nil {
   132  			return errors.Wrapf(err, "override origin clock_gettime, pid: %d", pid)
   133  		}
   134  	}
   135  
   136  	err = program.WriteUint64ToAddr(fakeEntry.StartAddress+uint64(it.fakeImage.offset[externVarClockIdsMask]), it.clockIDsMask)
   137  	if err != nil {
   138  		return errors.Wrapf(err, "set %s for time skew, pid: %d", externVarClockIdsMask, pid)
   139  	}
   140  
   141  	err = program.WriteUint64ToAddr(fakeEntry.StartAddress+uint64(it.fakeImage.offset[externVarTvSecDelta]), uint64(it.deltaSeconds))
   142  	if err != nil {
   143  		return errors.Wrapf(err, "set %s for time skew, pid: %d", externVarTvSecDelta, pid)
   144  	}
   145  
   146  	err = program.WriteUint64ToAddr(fakeEntry.StartAddress+uint64(it.fakeImage.offset[externVarTvNsecDelta]), uint64(it.deltaNanoSeconds))
   147  	if err != nil {
   148  		return errors.Wrapf(err, "set %s for time skew, pid: %d", externVarTvNsecDelta, pid)
   149  	}
   150  	return nil
   151  }
   152  
   153  func (it *TimeSkew) Recover(pid int) error {
   154  	zeroSkew := NewTimeSkewWithCustomFakeImage(0, 0, it.clockIDsMask, it.fakeImage)
   155  	return zeroSkew.Inject(pid)
   156  }
   157