github.com/nicocha30/gvisor-ligolo@v0.0.0-20230726075806-989fa2c0a413/pkg/sentry/syscalls/linux/timespec.go (about) 1 // Copyright 2018 The gVisor 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 package linux 16 17 import ( 18 "time" 19 20 "github.com/nicocha30/gvisor-ligolo/pkg/abi/linux" 21 "github.com/nicocha30/gvisor-ligolo/pkg/errors/linuxerr" 22 "github.com/nicocha30/gvisor-ligolo/pkg/hostarch" 23 "github.com/nicocha30/gvisor-ligolo/pkg/sentry/kernel" 24 ) 25 26 // copyTimespecIn copies a Timespec from the untrusted app range to the kernel. 27 func copyTimespecIn(t *kernel.Task, addr hostarch.Addr) (linux.Timespec, error) { 28 switch t.Arch().Width() { 29 case 8: 30 ts := linux.Timespec{} 31 in := t.CopyScratchBuffer(16) 32 _, err := t.CopyInBytes(addr, in) 33 if err != nil { 34 return ts, err 35 } 36 ts.Sec = int64(hostarch.ByteOrder.Uint64(in[0:])) 37 ts.Nsec = int64(hostarch.ByteOrder.Uint64(in[8:])) 38 return ts, nil 39 default: 40 return linux.Timespec{}, linuxerr.ENOSYS 41 } 42 } 43 44 // copyTimespecOut copies a Timespec to the untrusted app range. 45 func copyTimespecOut(t *kernel.Task, addr hostarch.Addr, ts *linux.Timespec) error { 46 switch t.Arch().Width() { 47 case 8: 48 out := t.CopyScratchBuffer(16) 49 hostarch.ByteOrder.PutUint64(out[0:], uint64(ts.Sec)) 50 hostarch.ByteOrder.PutUint64(out[8:], uint64(ts.Nsec)) 51 _, err := t.CopyOutBytes(addr, out) 52 return err 53 default: 54 return linuxerr.ENOSYS 55 } 56 } 57 58 // copyTimevalIn copies a Timeval from the untrusted app range to the kernel. 59 func copyTimevalIn(t *kernel.Task, addr hostarch.Addr) (linux.Timeval, error) { 60 switch t.Arch().Width() { 61 case 8: 62 tv := linux.Timeval{} 63 in := t.CopyScratchBuffer(16) 64 _, err := t.CopyInBytes(addr, in) 65 if err != nil { 66 return tv, err 67 } 68 tv.Sec = int64(hostarch.ByteOrder.Uint64(in[0:])) 69 tv.Usec = int64(hostarch.ByteOrder.Uint64(in[8:])) 70 return tv, nil 71 default: 72 return linux.Timeval{}, linuxerr.ENOSYS 73 } 74 } 75 76 // copyTimevalOut copies a Timeval to the untrusted app range. 77 func copyTimevalOut(t *kernel.Task, addr hostarch.Addr, tv *linux.Timeval) error { 78 switch t.Arch().Width() { 79 case 8: 80 out := t.CopyScratchBuffer(16) 81 hostarch.ByteOrder.PutUint64(out[0:], uint64(tv.Sec)) 82 hostarch.ByteOrder.PutUint64(out[8:], uint64(tv.Usec)) 83 _, err := t.CopyOutBytes(addr, out) 84 return err 85 default: 86 return linuxerr.ENOSYS 87 } 88 } 89 90 // copyTimespecInToDuration copies a Timespec from the untrusted app range, 91 // validates it and converts it to a Duration. 92 // 93 // If the Timespec is larger than what can be represented in a Duration, the 94 // returned value is the maximum that Duration will allow. 95 // 96 // If timespecAddr is NULL, the returned value is negative. 97 func copyTimespecInToDuration(t *kernel.Task, timespecAddr hostarch.Addr) (time.Duration, error) { 98 // Use a negative Duration to indicate "no timeout". 99 timeout := time.Duration(-1) 100 if timespecAddr != 0 { 101 var timespec linux.Timespec 102 if _, err := timespec.CopyIn(t, timespecAddr); err != nil { 103 return 0, err 104 } 105 if !timespec.Valid() { 106 return 0, linuxerr.EINVAL 107 } 108 timeout = time.Duration(timespec.ToNsecCapped()) 109 } 110 return timeout, nil 111 }