Repository: pingcap/chaos-mesh
Pull request #276 (2020-02-24 10:50:23)

make clk id configurable
Signed-off-by: Yang Keao <keao.yang@yahoo.com>

### What problem does this PR solve?

It makes the mask of affected `clk_id` configurable.

### What is changed and how does it work?

Add a new variable in `fake_clock_gettime` function.

### Check List <!--REMOVE the items that are not applicable-->

Tests <!-- At least one of them must be included. -->

 - Unit test
 - Manual test

Code changes

 - Has Go code change

codecov-io: # [Codecov](https://codecov.io/gh/pingcap/chaos-mesh/pull/276?src=pr&el=h1) Report
> Merging [#276](https://codecov.io/gh/pingcap/chaos-mesh/pull/276?src=pr&el=desc) into [master](https://codecov.io/gh/pingcap/chaos-mesh/commit/35bafd17e01a4a732ea2e879e87ecb87ebd014ef?src=pr&el=desc) will **decrease** coverage by `1.2%`.
> The diff coverage is `37.83%`.

[![Impacted file tree graph](https://codecov.io/gh/pingcap/chaos-mesh/pull/276/graphs/tree.svg?width=650&token=a3XIzuy5Dk&height=150&src=pr)](https://codecov.io/gh/pingcap/chaos-mesh/pull/276?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master     #276      +/-   ##
==========================================
- Coverage   53.37%   52.16%   -1.21%     
==========================================
  Files          34       35       +1     
  Lines        1632     1591      -41     
==========================================
- Hits          871      830      -41     
- Misses        674      675       +1     
+ Partials       87       86       -1
```


| [Impacted Files](https://codecov.io/gh/pingcap/chaos-mesh/pull/276?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [api/v1alpha1/timechaos\_types.go](https://codecov.io/gh/pingcap/chaos-mesh/pull/276/diff?src=pr&el=tree#diff-YXBpL3YxYWxwaGExL3RpbWVjaGFvc190eXBlcy5nbw==) | `4.34% <0%> (-0.31%)` | :arrow_down: |
| [pkg/chaosdaemon/time\_server.go](https://codecov.io/gh/pingcap/chaos-mesh/pull/276/diff?src=pr&el=tree#diff-cGtnL2NoYW9zZGFlbW9uL3RpbWVfc2VydmVyLmdv) | `100% <100%> (ø)` | :arrow_up: |
| [pkg/utils/time.go](https://codecov.io/gh/pingcap/chaos-mesh/pull/276/diff?src=pr&el=tree#diff-cGtnL3V0aWxzL3RpbWUuZ28=) | `30.76% <30.76%> (ø)` | |
| [pkg/time/time\_linux.go](https://codecov.io/gh/pingcap/chaos-mesh/pull/276/diff?src=pr&el=tree#diff-cGtnL3RpbWUvdGltZV9saW51eC5nbw==) | `49.12% <66.66%> (-0.88%)` | :arrow_down: |
| [controllers/timechaos\_controller.go](https://codecov.io/gh/pingcap/chaos-mesh/pull/276/diff?src=pr&el=tree#diff-Y29udHJvbGxlcnMvdGltZWNoYW9zX2NvbnRyb2xsZXIuZ28=) | `0% <0%> (ø)` | :arrow_up: |
| [controllers/podchaos\_controller.go](https://codecov.io/gh/pingcap/chaos-mesh/pull/276/diff?src=pr&el=tree#diff-Y29udHJvbGxlcnMvcG9kY2hhb3NfY29udHJvbGxlci5nbw==) | `100% <0%> (+6.89%)` | :arrow_up: |
| [controllers/networkchaos\_controller.go](https://codecov.io/gh/pingcap/chaos-mesh/pull/276/diff?src=pr&el=tree#diff-Y29udHJvbGxlcnMvbmV0d29ya2NoYW9zX2NvbnRyb2xsZXIuZ28=) | `100% <0%> (+6.89%)` | :arrow_up: |
| [controllers/iochaos\_controller.go](https://codecov.io/gh/pingcap/chaos-mesh/pull/276/diff?src=pr&el=tree#diff-Y29udHJvbGxlcnMvaW9jaGFvc19jb250cm9sbGVyLmdv) | `100% <0%> (+7.14%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/pingcap/chaos-mesh/pull/276?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/pingcap/chaos-mesh/pull/276?src=pr&el=footer). Last update [35bafd1...4336538](https://codecov.io/gh/pingcap/chaos-mesh/pull/276?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

cwen0: @ethercflow PTAL
cwen0: @ethercflow PTAL
cwen0: @YangKeao Fix conflicts
cwen0: /merge
sre-bot: /run-all-tests

Patch:
diff --git a/Makefile b/Makefile
index c3aae741..a222168f 100644
--- a/Makefile
+++ b/Makefile
@@ -86,7 +86,7 @@ dashboard: fmt vet
 binary: chaosdaemon manager chaosfs dashboard
 
 watchmaker: fmt vet
-	$(CGOENV) go build -ldflags '$(LDFLAGS)' -o bin/watchmaker ./cmd/watchmaker/*.go
+	$(CGOENV) go build -ldflags '$(LDFLAGS)' -o bin/watchmaker ./cmd/watchmaker/...
 
 dashboard-server-frontend:
 	cd images/chaos-dashboard; yarn install; yarn build
diff --git a/api/v1alpha1/timechaos_types.go b/api/v1alpha1/timechaos_types.go
index 696cc712..7a8aa0e6 100644
--- a/api/v1alpha1/timechaos_types.go
+++ b/api/v1alpha1/timechaos_types.go
@@ -53,6 +53,13 @@ type TimeChaosSpec struct {
 	// TimeOffset defines the delta time of injected program
 	TimeOffset TimeOffset `json:"timeOffset"`
 
+	// ClockIds defines all affected clock id
+	// All available options are ["CLOCK_REALTIME","CLOCK_MONOTONIC","CLOCK_PROCESS_CPUTIME_ID","CLOCK_THREAD_CPUTIME_ID",
+	// "CLOCK_MONOTONIC_RAW","CLOCK_REALTIME_COARSE","CLOCK_MONOTONIC_COARSE","CLOCK_BOOTTIME","CLOCK_REALTIME_ALARM",
+	// "CLOCK_BOOTTIME_ALARM"]
+	// Default value is ["CLOCK_REALTIME"]
+	ClockIds []string `json:"clockIds,omitempty"`
+
 	// Duration represents the duration of the chaos action
 	Duration *string `json:"duration"`
 
@@ -68,6 +75,13 @@ type TimeChaosSpec struct {
 	NextRecover *metav1.Time `json:"nextRecover,omitempty"`
 }
 
+// SetDefaultValue will set default value for empty fields
+func (in *TimeChaos) SetDefaultValue() {
+	if in.Spec.ClockIds == nil || len(in.Spec.ClockIds) == 0 {
+		in.Spec.ClockIds = []string{"CLOCK_REALTIME"}
+	}
+}
+
 // GetSelector is a getter for Selector (for implementing SelectSpec)
 func (in *TimeChaosSpec) GetSelector() SelectorSpec {
 	return in.Selector
diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go
index c091416a..6685958e 100644
--- a/api/v1alpha1/zz_generated.deepcopy.go
+++ b/api/v1alpha1/zz_generated.deepcopy.go
@@ -663,6 +663,11 @@ func (in *TimeChaosSpec) DeepCopyInto(out *TimeChaosSpec) {
 	*out = *in
 	in.Selector.DeepCopyInto(&out.Selector)
 	out.TimeOffset = in.TimeOffset
+	if in.ClockIds != nil {
+		in, out := &in.ClockIds, &out.ClockIds
+		*out = make([]string, len(*in))
+		copy(*out, *in)
+	}
 	if in.Duration != nil {
 		in, out := &in.Duration, &out.Duration
 		*out = new(string)
diff --git a/cmd/watchmaker/main_linux.go b/cmd/watchmaker/main_linux.go
index d2b763d4..739b6948 100644
--- a/cmd/watchmaker/main_linux.go
+++ b/cmd/watchmaker/main_linux.go
@@ -17,6 +17,9 @@ import (
 	"flag"
 	"fmt"
 	"os"
+	"strings"
+
+	"github.com/pingcap/chaos-mesh/pkg/utils"
 
 	"github.com/go-logr/zapr"
 	"go.uber.org/zap"
@@ -29,16 +32,18 @@ import (
 )
 
 var (
-	pid          int
-	secDelta     int64
-	nsecDelta    int64
-	printVersion bool
+	pid           int
+	secDelta      int64
+	nsecDelta     int64
+	printVersion  bool
+	clockIdsSlice string
 )
 
 func initFlag() {
 	flag.IntVar(&pid, "pid", 0, "pid of target program")
 	flag.Int64Var(&secDelta, "sec_delta", 0, "delta time of sec field")
 	flag.Int64Var(&nsecDelta, "nsec_delta", 0, "delta time of nsec field")
+	flag.StringVar(&clockIdsSlice, "clk_ids", "CLOCK_REALTIME", "all affected clock ids split with \",\"")
 	flag.BoolVar(&printVersion, "version", false, "print version information and exit")
 
 	flag.Parse()
@@ -61,9 +66,17 @@ func main() {
 	ptrace.RegisterLogger(log.WithName("ptrace"))
 	time.RegisterLogger(log.WithName("time"))
 
-	err = time.ModifyTime(pid, secDelta, nsecDelta)
+	clkIds := strings.Split(clockIdsSlice, ",")
+	mask, err := utils.EncodeClkIds(clkIds)
+	if err != nil {
+		log.Error(err, "error while converting clock ids to mask")
+		os.Exit(1)
+	}
+	log.Info("get clock ids mask", "mask", mask)
+
+	err = time.ModifyTime(pid, secDelta, nsecDelta, mask)
 
 	if err != nil {
-		fmt.Printf("error while modifying time, pid: %d, sec_delta: %d, nsec_delta: %d\n Error: %s", pid, secDelta, nsecDelta, err.Error())
+		log.Error(err, "error while modifying time", "pid", pid, "secDelta", secDelta, "nsecDelta", nsecDelta, "mask", mask)
 	}
 }
diff --git a/config/crd/bases/pingcap.com_timechaos.yaml b/config/crd/bases/pingcap.com_timechaos.yaml
index 63d3a60a..3b0fb516 100644
--- a/config/crd/bases/pingcap.com_timechaos.yaml
+++ b/config/crd/bases/pingcap.com_timechaos.yaml
@@ -34,6 +34,14 @@ spec:
         spec:
           description: Spec defines the behavior of a time chaos experiment
           properties:
+            clockIds:
+              description: ClockIds defines all affected clock id All available options
+                are ["CLOCK_REALTIME","CLOCK_MONOTONIC","CLOCK_PROCESS_CPUTIME_ID","CLOCK_THREAD_CPUTIME_ID",
+                "CLOCK_MONOTONIC_RAW","CLOCK_REALTIME_COARSE","CLOCK_MONOTONIC_COARSE","CLOCK_BOOTTIME","CLOCK_REALTIME_ALARM",
+                "CLOCK_BOOTTIME_ALARM"] Default value is ["CLOCK_REALTIME"]
+              items:
+                type: string
+              type: array
             duration:
               description: Duration represents the duration of the chaos action
               type: string
diff --git a/controllers/timechaos/types.go b/controllers/timechaos/types.go
index 610c81f5..3f9d1e24 100644
--- a/controllers/timechaos/types.go
+++ b/controllers/timechaos/types.go
@@ -87,6 +87,8 @@ func (r *Reconciler) Apply(ctx context.Context, req ctrl.Request, chaos reconcil
 		return err
 	}
 
+	timechaos.SetDefaultValue()
+
 	pods, err := utils.SelectAndGeneratePods(ctx, r.Client, &timechaos.Spec)
 
 	if err != nil {
@@ -244,10 +246,17 @@ func (r *Reconciler) applyPod(ctx context.Context, pod *v1.Pod, chaos *v1alpha1.
 
 	containerID := pod.Status.ContainerStatuses[0].ContainerID
 
+	mask, err := utils.EncodeClkIds(chaos.Spec.ClockIds)
+	if err != nil {
+		return err
+	}
+
+	r.Log.Info("setting time shift", "mask", mask, "sec", chaos.Spec.TimeOffset.Sec, "nsec", chaos.Spec.TimeOffset.NSec)
 	_, err = pbClient.SetTimeOffset(ctx, &pb.TimeRequest{
 		ContainerId: containerID,
 		Sec:         chaos.Spec.TimeOffset.Sec,
 		Nsec:        chaos.Spec.TimeOffset.NSec,
+		ClkIdsMask:  mask,
 	})
 
 	return err
diff --git a/doc/time_chaos.md b/doc/time_chaos.md
index 83e529b4..ec91f61a 100644
--- a/doc/time_chaos.md
+++ b/doc/time_chaos.md
@@ -22,6 +22,8 @@ spec:
   timeOffset:
     sec: 100000
     nsec: 100000
+  clockIds:
+    - CLOCK_REALTIME
   duration: "10s"
   scheduler:
     cron: "@every 15s"
@@ -34,6 +36,7 @@ Description:
 * **mode** defines the mode to select pods.
 * **selector** specifies the target pods for chaos injection.
 * **timeOffset** specifies the offset of time. `sec` means the offset of seconds and `nsec` means the offset of nanoseconds.
+* **clockIds** defines all affected `clk_id`. `clk_id` refers to the first argument of `clock_gettime` call. For most application, `CLOCK_REALTIME` is enough.
 * **duration** defines the duration for each chaos experiment. In the sample file above, the time chaos lasts for 10 seconds.
 * **scheduler** defines the scheduler rules for the running time of the chaos experiment. For more rule information, see <https://godoc.org/github.com/robfig/cron>.
 
@@ -41,5 +44,4 @@ Description:
 
 * Time modification will only be injected into the main process of container
 * Time chaos has no effect on pure syscall `clock_gettime`
-* Only `CLOCK_REALTIME` will be modified. This is intended because modification on other clock such as `CLOCK_REALTIME_COARSE` (which go program uses to `time.Sleep`) will cause serious and deterministic problem. We should make it configurable in the future.
 * All injected vdso call will use pure syscall to get realtime, so clock related function call will be much slower.
\ No newline at end of file
diff --git a/go.mod b/go.mod
index b14dee2a..8169b609 100644
--- a/go.mod
+++ b/go.mod
@@ -50,7 +50,7 @@ require (
 	golang.org/x/net v0.0.0-20191004110552-13f9640d40b9
 	golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e
 	golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae // indirect
-	golang.org/x/tools v0.0.0-20200225022059-a0ec867d517c
+	golang.org/x/tools v0.0.0-20200225230052-807dcd883420
 	google.golang.org/genproto v0.0.0-20191028173616-919d9bdd9fe6 // indirect
 	google.golang.org/grpc v1.27.0
 	k8s.io/api v0.17.0
diff --git a/go.sum b/go.sum
index e765b3e2..a0a26c3e 100644
--- a/go.sum
+++ b/go.sum
@@ -287,19 +287,15 @@ github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN
 github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
 github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
 github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
-github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU=
 github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
 github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA=
 github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
 github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
-github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE=
 github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
-github.com/mattn/go-isatty v0.0.11 h1:FxPOTFNqGkuDUGi3H/qkUbQO4ZiBa2brKq5r0l8TGeM=
 github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
 github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
 github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
 github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
-github.com/mattn/go-runewidth v0.0.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54=
 github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
 github.com/mattn/go-runewidth v0.0.8 h1:3tS41NlGYSmhhe/8fhGRzc+z3AYCw1Fe1WAyLuujKs0=
 github.com/mattn/go-runewidth v0.0.8/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
@@ -605,6 +601,8 @@ golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtn
 golang.org/x/tools v0.0.0-20200221224223-e1da425f72fd/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
 golang.org/x/tools v0.0.0-20200225022059-a0ec867d517c h1:cmkqWf0jTLsPn3dn28dkzCF+MoDvuZS7pTwHwGmkqiU=
 golang.org/x/tools v0.0.0-20200225022059-a0ec867d517c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200225230052-807dcd883420 h1:4RJNOV+2rLxMEfr6QIpC7GEv9MjD6ApGXTCLrNF9+eA=
+golang.org/x/tools v0.0.0-20200225230052-807dcd883420/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898 h1:/atklqdjdhuosWIl6AIbOeHJjicWYPqR9bpxqxYG2pA=
 golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/helm/chaos-mesh/values.yaml b/helm/chaos-mesh/values.yaml
index 43dcd882..d4b8ad43 100644
--- a/helm/chaos-mesh/values.yaml
+++ b/helm/chaos-mesh/values.yaml
@@ -19,7 +19,7 @@ controllerManager:
   replicaCount: 1
 
   image: pingcap/chaos-mesh:latest
-  imagePullPolicy: Always
+  imagePullPolicy: Never
 
   nameOverride: ""
   fullnameOverride: ""
@@ -49,7 +49,7 @@ controllerManager:
 
 chaosDaemon:
   image: pingcap/chaos-daemon:latest
-  imagePullPolicy: Always
+  imagePullPolicy: Never
   grpcPort: 31767
   httpPort: 31766
 
@@ -73,7 +73,7 @@ dashboard:
   serviceAccount: chaos-dashboard
 
   image: pingcap/chaos-dashboard:latest
-  imagePullPolicy: Always
+  imagePullPolicy: Never
 
   nodeSelector: {}
 
diff --git a/manifests/crd.yaml b/manifests/crd.yaml
index f118b44c..da9bc17d 100644
--- a/manifests/crd.yaml
+++ b/manifests/crd.yaml
@@ -834,6 +834,14 @@ spec:
         spec:
           description: Spec defines the behavior of a time chaos experiment
           properties:
+            clockIds:
+              description: ClockIds defines all affected clock id All available options
+                are ["CLOCK_REALTIME","CLOCK_MONOTONIC","CLOCK_PROCESS_CPUTIME_ID","CLOCK_THREAD_CPUTIME_ID",
+                "CLOCK_MONOTONIC_RAW","CLOCK_REALTIME_COARSE","CLOCK_MONOTONIC_COARSE","CLOCK_BOOTTIME","CLOCK_REALTIME_ALARM",
+                "CLOCK_BOOTTIME_ALARM"] Default value is ["CLOCK_REALTIME"]
+              items:
+                type: string
+              type: array
             duration:
               description: Duration represents the duration of the chaos action
               type: string
diff --git a/pkg/chaosdaemon/pb/chaosdaemon.pb.go b/pkg/chaosdaemon/pb/chaosdaemon.pb.go
index acbdd94b..8f80a108 100644
--- a/pkg/chaosdaemon/pb/chaosdaemon.pb.go
+++ b/pkg/chaosdaemon/pb/chaosdaemon.pb.go
@@ -527,6 +527,7 @@ type TimeRequest struct {
 	ContainerId          string   `protobuf:"bytes,1,opt,name=container_id,json=containerId,proto3" json:"container_id,omitempty"`
 	Sec                  int64    `protobuf:"varint,2,opt,name=sec,proto3" json:"sec,omitempty"`
 	Nsec                 int64    `protobuf:"varint,3,opt,name=nsec,proto3" json:"nsec,omitempty"`
+	ClkIdsMask           uint64   `protobuf:"varint,4,opt,name=clk_ids_mask,json=clkIdsMask,proto3" json:"clk_ids_mask,omitempty"`
 	XXX_NoUnkeyedLiteral struct{} `json:"-"`
 	XXX_unrecognized     []byte   `json:"-"`
 	XXX_sizecache        int32    `json:"-"`
@@ -578,6 +579,13 @@ func (m *TimeRequest) GetNsec() int64 {
 	return 0
 }
 
+func (m *TimeRequest) GetClkIdsMask() uint64 {
+	if m != nil {
+		return m.ClkIdsMask
+	}
+	return 0
+}
+
 type ContainerAction struct {
 	Action               ContainerAction_Action `protobuf:"varint,1,opt,name=action,proto3,enum=chaosdaemon.ContainerAction_Action" json:"action,omitempty"`
 	XXX_NoUnkeyedLiteral struct{}               `json:"-"`
@@ -635,51 +643,53 @@ func init() {
 func init() { proto.RegisterFile("chaosdaemon.proto", fileDescriptor_143136706133b591) }
 
 var fileDescriptor_143136706133b591 = []byte{
-	// 701 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x54, 0xcf, 0x4e, 0xdb, 0x4e,
-	0x10, 0xc6, 0x71, 0x12, 0xe2, 0x31, 0x86, 0xb0, 0xfa, 0x09, 0x99, 0x7f, 0x52, 0x7e, 0xae, 0x90,
-	0x72, 0x69, 0xa8, 0x68, 0x2f, 0x55, 0x0f, 0x15, 0x4d, 0xd2, 0x36, 0x02, 0x41, 0x65, 0x42, 0x2f,
-	0x1c, 0x90, 0x63, 0x0f, 0xe0, 0xd6, 0x89, 0xdd, 0xf5, 0xba, 0x12, 0x6f, 0xd8, 0x67, 0xe9, 0x03,
-	0xf4, 0x5c, 0xed, 0xac, 0xed, 0x26, 0x21, 0x82, 0x48, 0x9c, 0x3c, 0x3b, 0xf3, 0x7d, 0xdf, 0xce,
-	0xce, 0x8c, 0x07, 0x36, 0xfd, 0x3b, 0x2f, 0x4e, 0x03, 0x0f, 0xc7, 0xf1, 0xa4, 0x93, 0xf0, 0x58,
-	0xc4, 0xcc, 0x9c, 0x72, 0xed, 0xec, 0xde, 0xc6, 0xf1, 0x6d, 0x84, 0x87, 0x14, 0x1a, 0x65, 0x37,
-	0x87, 0x38, 0x4e, 0xc4, 0xbd, 0x42, 0x3a, 0xdf, 0xa1, 0xd9, 0x8d, 0x27, 0xc2, 0x0b, 0x27, 0xc8,
-	0x5d, 0xfc, 0x91, 0x61, 0x2a, 0xd8, 0x1b, 0xa8, 0x7b, 0xbe, 0x08, 0xe3, 0x89, 0xad, 0xb5, 0xb4,
-	0xb6, 0x79, 0xb4, 0xd7, 0x99, 0xbe, 0xa1, 0x84, 0x1f, 0x13, 0xc6, 0xcd, 0xb1, 0xec, 0x7f, 0x58,
-	0xf3, 0x8b, 0xd0, 0x75, 0x18, 0xd8, 0x95, 0x96, 0xd6, 0x36, 0x5c, 0xb3, 0xf4, 0x0d, 0x02, 0xe7,
-	0x0a, 0xd6, 0xce, 0x50, 0xe0, 0xb8, 0xb8, 0xa8, 0x0d, 0xb5, 0x89, 0x3c, 0xe7, 0xf7, 0xb0, 0x99,
-	0x7b, 0x14, 0x52, 0x01, 0x96, 0x11, 0xff, 0x5d, 0x81, 0x1a, 0x71, 0x18, 0x83, 0xaa, 0x08, 0xc7,
-	0x48, 0xaa, 0x96, 0x4b, 0x36, 0xdb, 0x82, 0xfa, 0xb7, 0x50, 0x08, 0xe4, 0x44, 0xb5, 0xdc, 0xfc,
-	0xc4, 0xf6, 0x01, 0x02, 0x8c, 0xbc, 0xfb, 0x6b, 0x3f, 0xe6, 0xdc, 0xd6, 0x5b, 0x5a, 0xbb, 0xe2,
-	0x1a, 0xe4, 0xe9, 0xc6, 0x9c, 0xb3, 0xff, 0xa0, 0x16, 0x85, 0xe3, 0x50, 0xd8, 0x55, 0x62, 0xa9,
-	0x83, 0xbc, 0x20, 0x8a, 0xd3, 0xd4, 0xae, 0x11, 0x9c, 0x6c, 0xb6, 0x0b, 0x86, 0xfc, 0x2a, 0x9d,
-	0x3a, 0x05, 0x1a, 0xd2, 0x41, 0x32, 0x4d, 0xd0, 0x6f, 0xbd, 0xc4, 0x5e, 0x25, 0x11, 0x69, 0xb2,
-	0x3d, 0x30, 0x82, 0x2c, 0x89, 0x42, 0xdf, 0x13, 0x68, 0x37, 0xf2, 0x6b, 0x0b, 0x07, 0x3b, 0x80,
-	0xf5, 0xf2, 0xa0, 0x14, 0x0d, 0x82, 0x58, 0xa5, 0x97, 0x64, 0x6d, 0x58, 0xe5, 0x18, 0xf3, 0x00,
-	0xb9, 0x0d, 0x14, 0x2f, 0x8e, 0xb2, 0x5e, 0xb9, 0xa9, 0xe8, 0x26, 0x85, 0xcd, 0xdc, 0x57, 0x90,
-	0x65, 0x28, 0x4b, 0x84, 0xbd, 0xa6, 0xc8, 0xf9, 0x51, 0x15, 0x9b, 0x4c, 0x45, 0xb6, 0x14, 0x39,
-	0xf7, 0x49, 0xb2, 0xec, 0xe4, 0x20, 0xb9, 0x40, 0x31, 0xd5, 0xc9, 0x30, 0x49, 0x51, 0x2c, 0xec,
-	0xa4, 0x42, 0x2a, 0xc0, 0x32, 0x9d, 0x7c, 0x09, 0x35, 0xa2, 0xc8, 0x3a, 0x4f, 0xbc, 0xbc, 0x91,
-	0x86, 0x4b, 0xb6, 0x2c, 0x65, 0x98, 0xa4, 0x76, 0xa5, 0xa5, 0xb7, 0x0d, 0x57, 0x9a, 0xce, 0x15,
-	0x6c, 0x0c, 0x92, 0xa1, 0x37, 0x8a, 0x30, 0x2d, 0xd2, 0x39, 0x80, 0x2a, 0xcf, 0x22, 0xcc, 0xb3,
-	0xd9, 0x9c, 0xc9, 0xc6, 0xcd, 0x22, 0x74, 0x29, 0xbc, 0x4c, 0x2e, 0xbf, 0x34, 0xa8, 0x4a, 0x06,
-	0x7b, 0x35, 0xf3, 0x53, 0xac, 0x1f, 0xd9, 0x0f, 0x44, 0x3b, 0x73, 0x3f, 0xc4, 0x5b, 0x30, 0x82,
-	0x90, 0xa3, 0x22, 0x55, 0x88, 0xb4, 0xfb, 0x90, 0xd4, 0x2b, 0x20, 0xee, 0x3f, 0xb4, 0x7c, 0xa4,
-	0x2c, 0xa6, 0x4e, 0xf9, 0x48, 0xd3, 0xd9, 0x87, 0xba, 0x92, 0x67, 0xab, 0xa0, 0x1f, 0xf7, 0x7a,
-	0xcd, 0x15, 0x06, 0x50, 0xef, 0xf5, 0x4f, 0xfb, 0xc3, 0x7e, 0x53, 0x73, 0x1c, 0x30, 0x4a, 0x21,
-	0x66, 0x40, 0x6d, 0x70, 0xf6, 0xe5, 0x72, 0xa8, 0x30, 0xe7, 0x97, 0x43, 0x69, 0x6b, 0xce, 0x57,
-	0x30, 0x87, 0xe1, 0x18, 0x8b, 0x1a, 0xcd, 0x3f, 0x5e, 0x7b, 0xf0, 0x78, 0x95, 0x86, 0x4f, 0xb9,
-	0xeb, 0x32, 0x0d, 0x9f, 0x3a, 0x22, 0x5d, 0x3a, 0xb9, 0xc8, 0x76, 0x46, 0xb0, 0x31, 0xb7, 0x13,
-	0xd8, 0xbb, 0xb9, 0x62, 0xbd, 0x78, 0x6c, 0x83, 0xcc, 0xd5, 0xcd, 0x61, 0xe5, 0x53, 0x1b, 0x50,
-	0x3d, 0x19, 0x9c, 0x9e, 0x36, 0x57, 0x8e, 0xfe, 0xe8, 0x60, 0x76, 0xa5, 0x44, 0x8f, 0x24, 0xd8,
-	0x7b, 0x68, 0x5c, 0xa0, 0x50, 0xbf, 0xfb, 0xf6, 0x82, 0xb5, 0xa1, 0xde, 0xb8, 0xb3, 0xd5, 0x51,
-	0xbb, 0xaf, 0x53, 0xec, 0xbe, 0x4e, 0x5f, 0xee, 0x3e, 0x67, 0x85, 0x7d, 0x00, 0xb3, 0x87, 0x11,
-	0x0a, 0x7c, 0x86, 0xc6, 0x31, 0xc0, 0xc7, 0x28, 0x4b, 0xef, 0xd4, 0xb0, 0x6e, 0x2f, 0x98, 0xf9,
-	0x27, 0x25, 0x3e, 0x81, 0x95, 0x4b, 0x08, 0x1a, 0x60, 0xb6, 0x37, 0xa7, 0x32, 0x33, 0xd7, 0x8f,
-	0x08, 0x75, 0xc1, 0xba, 0x40, 0x21, 0xfb, 0x7b, 0x7e, 0x73, 0x23, 0xff, 0xb3, 0xd9, 0xf9, 0x9c,
-	0x6a, 0xfc, 0xa3, 0xd9, 0x6c, 0xba, 0xe8, 0xc7, 0x3f, 0x91, 0x3f, 0x53, 0xe8, 0x33, 0x58, 0x65,
-	0x93, 0x4f, 0xc2, 0x28, 0x62, 0xfb, 0x8b, 0x07, 0xe0, 0x49, 0xa5, 0x51, 0x9d, 0x3c, 0xaf, 0xff,
-	0x06, 0x00, 0x00, 0xff, 0xff, 0xc1, 0xda, 0xec, 0x84, 0xe5, 0x06, 0x00, 0x00,
+	// 728 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x54, 0x4f, 0x4f, 0xdb, 0x4a,
+	0x10, 0xc7, 0x71, 0x12, 0xe2, 0x71, 0x02, 0x61, 0xf5, 0x84, 0xcc, 0x3f, 0x29, 0xcf, 0x4f, 0x48,
+	0xb9, 0xbc, 0xf0, 0xc4, 0xeb, 0xa5, 0xea, 0xa1, 0xa2, 0x49, 0xda, 0x46, 0x50, 0xa8, 0x4c, 0x38,
+	0x71, 0x88, 0x1c, 0x7b, 0x80, 0x6d, 0x36, 0xb1, 0x6b, 0x6f, 0xaa, 0xf2, 0x0d, 0xfb, 0x59, 0xfa,
+	0x01, 0x7a, 0xae, 0x76, 0xd6, 0x4e, 0x93, 0x10, 0x01, 0x12, 0x27, 0xcf, 0xce, 0xfc, 0x7e, 0xbf,
+	0x1d, 0xcf, 0xcc, 0x0e, 0x6c, 0x05, 0x77, 0x7e, 0x94, 0x86, 0x3e, 0x8e, 0xa3, 0x49, 0x2b, 0x4e,
+	0x22, 0x19, 0x31, 0x7b, 0xce, 0xb5, 0xbb, 0x77, 0x1b, 0x45, 0xb7, 0x02, 0x8f, 0x28, 0x34, 0x9c,
+	0xde, 0x1c, 0xe1, 0x38, 0x96, 0xf7, 0x1a, 0xe9, 0x8e, 0xa0, 0xde, 0x8e, 0x26, 0xd2, 0xe7, 0x13,
+	0x4c, 0x3c, 0xfc, 0x3a, 0xc5, 0x54, 0xb2, 0x57, 0x50, 0xf6, 0x03, 0xc9, 0xa3, 0x89, 0x63, 0x34,
+	0x8c, 0xa6, 0x7d, 0xbc, 0xdf, 0x9a, 0xbf, 0x61, 0x06, 0x3f, 0x21, 0x8c, 0x97, 0x61, 0xd9, 0xdf,
+	0x50, 0x0d, 0xf2, 0xd0, 0x80, 0x87, 0x4e, 0xa1, 0x61, 0x34, 0x2d, 0xcf, 0x9e, 0xf9, 0x7a, 0xa1,
+	0x7b, 0x0d, 0xd5, 0x73, 0x94, 0x38, 0xce, 0x2f, 0x6a, 0x42, 0x69, 0xa2, 0xce, 0xd9, 0x3d, 0x6c,
+	0xe1, 0x1e, 0x8d, 0xd4, 0x80, 0xe7, 0x88, 0xff, 0x2c, 0x40, 0x89, 0x38, 0x8c, 0x41, 0x51, 0xf2,
+	0x31, 0x92, 0x6a, 0xcd, 0x23, 0x9b, 0x6d, 0x43, 0xf9, 0x0b, 0x97, 0x12, 0x13, 0xa2, 0xd6, 0xbc,
+	0xec, 0xc4, 0x0e, 0x00, 0x42, 0x14, 0xfe, 0xfd, 0x20, 0x88, 0x92, 0xc4, 0x31, 0x1b, 0x46, 0xb3,
+	0xe0, 0x59, 0xe4, 0x69, 0x47, 0x49, 0xc2, 0xfe, 0x82, 0x92, 0xe0, 0x63, 0x2e, 0x9d, 0x22, 0xb1,
+	0xf4, 0x41, 0x5d, 0x20, 0xa2, 0x34, 0x75, 0x4a, 0x04, 0x27, 0x9b, 0xed, 0x81, 0xa5, 0xbe, 0x5a,
+	0xa7, 0x4c, 0x81, 0x8a, 0x72, 0x90, 0x4c, 0x1d, 0xcc, 0x5b, 0x3f, 0x76, 0xd6, 0x49, 0x44, 0x99,
+	0x6c, 0x1f, 0xac, 0x70, 0x1a, 0x0b, 0x1e, 0xf8, 0x12, 0x9d, 0x4a, 0x76, 0x6d, 0xee, 0x60, 0x87,
+	0xb0, 0x31, 0x3b, 0x68, 0x45, 0x8b, 0x20, 0xb5, 0x99, 0x97, 0x64, 0x1d, 0x58, 0x4f, 0x30, 0x4a,
+	0x42, 0x4c, 0x1c, 0xa0, 0x78, 0x7e, 0x54, 0xf5, 0xca, 0x4c, 0x4d, 0xb7, 0x29, 0x6c, 0x67, 0xbe,
+	0x9c, 0xac, 0x42, 0xd3, 0x58, 0x3a, 0x55, 0x4d, 0xce, 0x8e, 0xba, 0xd8, 0x64, 0x6a, 0x72, 0x4d,
+	0x93, 0x33, 0x9f, 0x22, 0xab, 0x4e, 0xf6, 0xe2, 0x4b, 0x94, 0x73, 0x9d, 0xe4, 0x71, 0x8a, 0x72,
+	0x65, 0x27, 0x35, 0x52, 0x03, 0x9e, 0xd3, 0xc9, 0x7f, 0xa1, 0x44, 0x14, 0x55, 0xe7, 0x89, 0x9f,
+	0x35, 0xd2, 0xf2, 0xc8, 0x56, 0xa5, 0xe4, 0x71, 0xea, 0x14, 0x1a, 0x66, 0xd3, 0xf2, 0x94, 0xe9,
+	0x5e, 0xc3, 0x66, 0x2f, 0xee, 0xfb, 0x43, 0x81, 0x69, 0x9e, 0xce, 0x21, 0x14, 0x93, 0xa9, 0xc0,
+	0x2c, 0x9b, 0xad, 0x85, 0x6c, 0xbc, 0xa9, 0x40, 0x8f, 0xc2, 0xcf, 0xc9, 0xe5, 0x87, 0x01, 0x45,
+	0xc5, 0x60, 0xff, 0x2d, 0x3c, 0x8a, 0x8d, 0x63, 0xe7, 0x81, 0x68, 0x6b, 0xe9, 0x41, 0xbc, 0x06,
+	0x2b, 0xe4, 0x09, 0x6a, 0x52, 0x81, 0x48, 0x7b, 0x0f, 0x49, 0x9d, 0x1c, 0xe2, 0xfd, 0x41, 0xab,
+	0x9f, 0x54, 0xc5, 0x34, 0x29, 0x1f, 0x65, 0xba, 0x07, 0x50, 0xd6, 0xf2, 0x6c, 0x1d, 0xcc, 0x93,
+	0x4e, 0xa7, 0xbe, 0xc6, 0x00, 0xca, 0x9d, 0xee, 0x59, 0xb7, 0xdf, 0xad, 0x1b, 0xae, 0x0b, 0xd6,
+	0x4c, 0x88, 0x59, 0x50, 0xea, 0x9d, 0x7f, 0xbe, 0xea, 0x6b, 0xcc, 0xc5, 0x55, 0x5f, 0xd9, 0x86,
+	0xfb, 0x1d, 0xec, 0x3e, 0x1f, 0x63, 0x5e, 0xa3, 0xe5, 0x9f, 0x37, 0x1e, 0xfc, 0xbc, 0x4e, 0x23,
+	0xa0, 0xdc, 0x4d, 0x95, 0x46, 0x40, 0x1d, 0x51, 0x2e, 0x93, 0x5c, 0x64, 0xb3, 0x06, 0x54, 0x03,
+	0x31, 0x1a, 0xf0, 0x30, 0x1d, 0x8c, 0xfd, 0x74, 0x44, 0x4f, 0xa5, 0xe8, 0x41, 0x20, 0x46, 0xbd,
+	0x30, 0xfd, 0xe4, 0xa7, 0x23, 0x77, 0x08, 0x9b, 0x4b, 0x5b, 0x83, 0xbd, 0x59, 0x2a, 0xe7, 0x3f,
+	0x8f, 0xed, 0x98, 0xa5, 0xca, 0xba, 0x6c, 0x56, 0x8c, 0x0a, 0x14, 0x4f, 0x7b, 0x67, 0x67, 0xf5,
+	0xb5, 0xe3, 0x5f, 0x26, 0xd8, 0x6d, 0x25, 0xd1, 0x21, 0x09, 0xf6, 0x16, 0x2a, 0x97, 0x28, 0xf5,
+	0x42, 0xd8, 0x59, 0xb1, 0x58, 0x74, 0x15, 0x76, 0xb7, 0x5b, 0x7a, 0x3b, 0xb6, 0xf2, 0xed, 0xd8,
+	0xea, 0xaa, 0xed, 0xe8, 0xae, 0xb1, 0x77, 0x60, 0x77, 0x50, 0xa0, 0xc4, 0x17, 0x68, 0x9c, 0x00,
+	0xbc, 0x17, 0xd3, 0xf4, 0x4e, 0x8f, 0xf3, 0xce, 0x8a, 0x57, 0xf1, 0xa4, 0xc4, 0x07, 0xa8, 0x65,
+	0x12, 0x92, 0x46, 0x9c, 0xed, 0x2f, 0xa9, 0x2c, 0x4c, 0xfe, 0x23, 0x42, 0x6d, 0xa8, 0x5d, 0xa2,
+	0x54, 0x13, 0x70, 0x71, 0x73, 0xa3, 0x5e, 0xe2, 0xe2, 0x04, 0xcf, 0x8d, 0xc6, 0xa3, 0xd9, 0x6c,
+	0x79, 0x18, 0x44, 0xdf, 0x30, 0x79, 0xa1, 0xd0, 0x47, 0xa8, 0xcd, 0x9a, 0x7c, 0xca, 0x85, 0x60,
+	0x07, 0xab, 0x07, 0xe0, 0x49, 0xa5, 0x61, 0x99, 0x3c, 0xff, 0xff, 0x0e, 0x00, 0x00, 0xff, 0xff,
+	0xe1, 0x33, 0xf4, 0x4a, 0x07, 0x07, 0x00, 0x00,
 }
 
 // Reference imports to suppress errors if they are not otherwise used.
diff --git a/pkg/chaosdaemon/pb/chaosdaemon.proto b/pkg/chaosdaemon/pb/chaosdaemon.proto
index 29f5877e..2de6ef3d 100644
--- a/pkg/chaosdaemon/pb/chaosdaemon.proto
+++ b/pkg/chaosdaemon/pb/chaosdaemon.proto
@@ -76,6 +76,7 @@ message TimeRequest {
   string container_id = 1;
   int64 sec = 2;
   int64 nsec = 3;
+  uint64 clk_ids_mask = 4;
 }
 
 message ContainerAction {
diff --git a/pkg/chaosdaemon/time_server.go b/pkg/chaosdaemon/time_server.go
index 7bcbaf5e..8438e0d4 100644
--- a/pkg/chaosdaemon/time_server.go
+++ b/pkg/chaosdaemon/time_server.go
@@ -19,7 +19,7 @@ func (s *daemonServer) SetTimeOffset(ctx context.Context, req *pb.TimeRequest) (
 		return nil, err
 	}
 
-	err = time.ModifyTime(int(pid), int64(req.Sec), int64(req.Nsec))
+	err = time.ModifyTime(int(pid), req.Sec, req.Nsec, req.ClkIdsMask)
 	if err != nil {
 		log.Error(err, "error while modifying time", "pid", pid)
 		return nil, err
@@ -36,7 +36,7 @@ func (s *daemonServer) RecoverTimeOffset(ctx context.Context, req *pb.TimeReques
 		return nil, err
 	}
 
-	err = time.ModifyTime(int(pid), int64(0), int64(0))
+	err = time.ModifyTime(int(pid), int64(0), int64(0), 0)
 	if err != nil {
 		log.Error(err, "error while recovering", "pid", pid)
 		return nil, err
diff --git a/pkg/fakeclockgettime/fake_clock_gettime.c b/pkg/fakeclockgettime/fake_clock_gettime.c
index f97585d7..2e14418c 100644
--- a/pkg/fakeclockgettime/fake_clock_gettime.c
+++ b/pkg/fakeclockgettime/fake_clock_gettime.c
@@ -3,6 +3,7 @@
 
 int64_t TV_SEC_DELTA = 0;
 int64_t TV_NSEC_DELTA = 0;
+uint64_t CLOCK_IDS_MASK = 0;
 
 long syscall(long number, ...);
 
@@ -18,10 +19,12 @@ int clock_gettime(clockid_t clk_id, struct timespec *tp) {
 
     int64_t sec_delta = TV_SEC_DELTA;
     int64_t nsec_delta = TV_NSEC_DELTA;
+    uint64_t clock_ids_mask = CLOCK_IDS_MASK;
 
     int64_t billion = 1000000000;
 
-    if(clk_id == CLOCK_REALTIME) {
+    uint64_t clk_id_mask = 1 << clk_id;
+    if((clk_id_mask & clock_ids_mask) != 0) {
         while (nsec_delta + tp->tv_nsec > billion) {
             sec_delta += 1;
             nsec_delta -= billion;
diff --git a/pkg/time/time_linux.go b/pkg/time/time_linux.go
index 2014c874..997599e5 100644
--- a/pkg/time/time_linux.go
+++ b/pkg/time/time_linux.go
@@ -39,40 +39,48 @@ func RegisterLogger(logger logr.Logger) {
 var fakeImage = []byte{
 	0xb8, 0xe4, 0x00, 0x00, 0x00, //mov    $0xe4,%eax
 	0x0f, 0x05, //syscall
-	0x85, 0xff, //test   %edi,%edi
-	0x75, 0x67, //jne    <clock_gettime+0x72>
-	0x48, 0x8d, 0x15, 0x61, 0x00, 0x00, 0x00, //lea    0x61(%rip),%rdx        # <TV_SEC_DELTA>
+	0xba, 0x01, 0x00, 0x00, 0x00, //mov    $0x1,%edx
+	0x89, 0xf9, //mov    %edi,%ecx
+	0xd3, 0xe2, //shl    %cl,%edx
+	0x48, 0x8d, 0x0d, 0x74, 0x00, 0x00, 0x00, //lea    0x74(%rip),%rcx        # <CLOCK_IDS_MASK>
+	0x48, 0x63, 0xd2, //movslq %edx,%rdx
+	0x48, 0x85, 0x11, //test   %rdx,(%rcx)
+	0x74, 0x6b, //je     108a <clock_gettime+0x8a>
+	0x48, 0x8d, 0x15, 0x6d, 0x00, 0x00, 0x00, //lea    0x6d(%rip),%rdx        # <TV_SEC_DELTA>
 	0x4c, 0x8b, 0x46, 0x08, //mov    0x8(%rsi),%r8
 	0x48, 0x8b, 0x0a, //mov    (%rdx),%rcx
-	0x48, 0x8d, 0x15, 0x5b, 0x00, 0x00, 0x00, //lea    0x2fd8(%rip),%rdx        # <TV_NSEC_DELTA>
+	0x48, 0x8d, 0x15, 0x67, 0x00, 0x00, 0x00, //lea    0x67(%rip),%rdx        # <TV_NSEC_DELTA>
 	0x48, 0x8b, 0x3a, //mov    (%rdx),%rdi
 	0x4a, 0x8d, 0x14, 0x07, //lea    (%rdi,%r8,1),%rdx
-	0x48, 0x81, 0xfa, 0x00, 0xca, 0x9a, 0x3b, //cmp    $1000000000,%rdx
-	0x7e, 0x18, //jle    1048 <clock_gettime+0x48>
-	0x48, 0x81, 0xef, 0x00, 0xca, 0x9a, 0x3b, //sub    $1000000000,%rdi
+	0x48, 0x81, 0xfa, 0x00, 0xca, 0x9a, 0x3b, //cmp    $0x3b9aca00,%rdx
+	0x7e, 0x1c, //jle    <clock_gettime+0x60>
+	0x0f, 0x1f, 0x40, 0x00, //nopl   0x0(%rax)
+	0x48, 0x81, 0xef, 0x00, 0xca, 0x9a, 0x3b, //sub    $0x3b9aca00,%rdi
 	0x48, 0x83, 0xc1, 0x01, //add    $0x1,%rcx
 	0x49, 0x8d, 0x14, 0x38, //lea    (%r8,%rdi,1),%rdx
-	0x48, 0x81, 0xfa, 0x00, 0xca, 0x9a, 0x3b, //cmp    $1000000000,%rdx
-	0x7f, 0xe8, //jg     <clock_gettime+0x30>
+	0x48, 0x81, 0xfa, 0x00, 0xca, 0x9a, 0x3b, //cmp    $0x3b9aca00,%rdx
+	0x7f, 0xe8, //jg     <clock_gettime+0x48>
 	0x48, 0x85, 0xd2, //test   %rdx,%rdx
-	0x79, 0x1e, //jns    <clock_gettime+0x6b>
-	0x4a, 0x8d, 0xbc, 0x07, 0x00, 0xca, 0x9a, 0x3b, //lea    $1000000000(%rdi,%r8,1),%rdi
+	0x79, 0x1e, //jns    <clock_gettime+0x83>
+	0x4a, 0x8d, 0xbc, 0x07, 0x00, 0xca, 0x9a, //lea    0x3b9aca00(%rdi,%r8,1),%rdi
+	0x3b,             //
 	0x0f, 0x1f, 0x00, //nopl   (%rax)
 	0x48, 0x89, 0xfa, //mov    %rdi,%rdx
 	0x48, 0x83, 0xe9, 0x01, //sub    $0x1,%rcx
-	0x48, 0x81, 0xc7, 0x00, 0xca, 0x9a, 0x3b, //add    $1000000000,%rdi
+	0x48, 0x81, 0xc7, 0x00, 0xca, 0x9a, 0x3b, //add    $0x3b9aca00,%rdi
 	0x48, 0x85, 0xd2, //test   %rdx,%rdx
-	0x78, 0xed, //js     <clock_gettime+0x58>
+	0x78, 0xed, //js     <clock_gettime+0x70>
 	0x48, 0x01, 0x0e, //add    %rcx,(%rsi)
 	0x48, 0x89, 0x56, 0x08, //mov    %rdx,0x8(%rsi)
 	0xc3, //retq
 	// constant
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //CLOCK_IDS_MASK
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //TV_SEC_DELTA
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //TV_NSEC_DELTA
 }
 
 // ModifyTime modifies time of target process
-func ModifyTime(pid int, deltaSec int64, deltaNsec int64) error {
+func ModifyTime(pid int, deltaSec int64, deltaNsec int64, clockIdsMask uint64) error {
 	// Mock point to return error in unit test
 	if err := mock.On("ModifyTimeError"); err != nil {
 		if e, ok := err.(error); ok {
@@ -137,14 +145,20 @@ func ModifyTime(pid int, deltaSec int64, deltaNsec int64) error {
 	}
 	fakeAddr := fakeEntry.StartAddress
 
-	// 115 is the index of TV_SEC_DELTA in fakeImage
-	err = program.WriteUint64ToAddr(fakeAddr+115, uint64(deltaSec))
+	// 139 is the index of CLOCK_IDS_MASK in fakeImage
+	err = program.WriteUint64ToAddr(fakeAddr+139, clockIdsMask)
 	if err != nil {
 		return err
 	}
 
-	// 123 is the index of TV_NSEC_DELTA in fakeImage
-	err = program.WriteUint64ToAddr(fakeAddr+123, uint64(deltaNsec))
+	// 147 is the index of TV_SEC_DELTA in fakeImage
+	err = program.WriteUint64ToAddr(fakeAddr+147, uint64(deltaSec))
+	if err != nil {
+		return err
+	}
+
+	// 155 is the index of TV_NSEC_DELTA in fakeImage
+	err = program.WriteUint64ToAddr(fakeAddr+155, uint64(deltaNsec))
 	if err != nil {
 		return err
 	}
diff --git a/pkg/utils/time.go b/pkg/utils/time.go
new file mode 100644
index 00000000..802b67f1
--- /dev/null
+++ b/pkg/utils/time.go
@@ -0,0 +1,51 @@
+// Copyright 2020 PingCAP, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package utils
+
+import "fmt"
+
+// EncodeClkIds will convert array of clk ids into a mask
+func EncodeClkIds(clkIds []string) (uint64, error) {
+	mask := uint64(0)
+
+	for _, id := range clkIds {
+		// refer to `uapi/linux/time.h`
+		switch id {
+		case "CLOCK_REALTIME":
+			mask |= 1 << 0
+		case "CLOCK_MONOTONIC":
+			mask |= 1 << 1
+		case "CLOCK_PROCESS_CPUTIME_ID":
+			mask |= 1 << 2
+		case "CLOCK_THREAD_CPUTIME_ID":
+			mask |= 1 << 3
+		case "CLOCK_MONOTONIC_RAW":
+			mask |= 1 << 4
+		case "CLOCK_REALTIME_COARSE":
+			mask |= 1 << 5
+		case "CLOCK_MONOTONIC_COARSE":
+			mask |= 1 << 6
+		case "CLOCK_BOOTTIME":
+			mask |= 1 << 7
+		case "CLOCK_REALTIME_ALARM":
+			mask |= 1 << 8
+		case "CLOCK_BOOTTIME_ALARM":
+			mask |= 1 << 9
+		default:
+			return 0, fmt.Errorf("unknown clock id %s", id)
+		}
+	}
+
+	return mask, nil
+}


Test patch:
diff --git a/pkg/time/time_linux_test.go b/pkg/time/time_linux_test.go
index 9fbf2aa1..c3fe2306 100644
--- a/pkg/time/time_linux_test.go
+++ b/pkg/time/time_linux_test.go
@@ -78,7 +78,7 @@ var _ = Describe("ModifyTime", func() {
 
 			sec := now.Unix()
 
-			err = ModifyTime(t.Pid(), 10000, 0)
+			err = ModifyTime(t.Pid(), 10000, 0, 1)
 			Expect(err).ShouldNot(HaveOccurred(), "error: %+v", err)
 
 			newTime, err := t.GetTime()
@@ -97,7 +97,7 @@ var _ = Describe("ModifyTime", func() {
 
 			sec := now.Unix()
 
-			err = ModifyTime(t.Pid(), -10000, 0)
+			err = ModifyTime(t.Pid(), -10000, 0, 1)
 			Expect(err).ShouldNot(HaveOccurred(), "error: %+v", err)
 
 			newTime, err := t.GetTime()
@@ -116,7 +116,7 @@ var _ = Describe("ModifyTime", func() {
 
 			sec := now.Unix()
 
-			err = ModifyTime(t.Pid(), 0, 1000000000)
+			err = ModifyTime(t.Pid(), 0, 1000000000, 1)
 			Expect(err).ShouldNot(HaveOccurred(), "error: %+v", err)
 
 			newTime, err := t.GetTime()
diff --git a/pkg/utils/time_test.go b/pkg/utils/time_test.go
new file mode 100644
index 00000000..9ba5b45b
--- /dev/null
+++ b/pkg/utils/time_test.go
@@ -0,0 +1,23 @@
+package utils
+
+import (
+	. "github.com/onsi/gomega"
+
+	"testing"
+)
+
+func TestEncodeClkIds(t *testing.T) {
+	g := NewGomegaWithT(t)
+
+	mask, err := EncodeClkIds([]string{"CLOCK_REALTIME"})
+	g.Expect(err).ShouldNot(HaveOccurred(), "error: %+v", err)
+	g.Expect(mask).Should(Equal(uint64(1)))
+
+	mask, err = EncodeClkIds([]string{"CLOCK_REALTIME", "CLOCK_MONOTONIC"})
+	g.Expect(err).ShouldNot(HaveOccurred(), "error: %+v", err)
+	g.Expect(mask).Should(Equal(uint64(3)))
+
+	mask, err = EncodeClkIds([]string{"CLOCK_MONOTONIC"})
+	g.Expect(err).ShouldNot(HaveOccurred(), "error: %+v", err)
+	g.Expect(mask).Should(Equal(uint64(2)))
+}