github.com/MerlinKodo/gvisor@v0.0.0-20231110090155-957f62ecf90e/pkg/sentry/syscalls/linux/sys_timer.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/MerlinKodo/gvisor/pkg/abi/linux" 21 "github.com/MerlinKodo/gvisor/pkg/errors/linuxerr" 22 "github.com/MerlinKodo/gvisor/pkg/sentry/arch" 23 "github.com/MerlinKodo/gvisor/pkg/sentry/kernel" 24 ) 25 26 const nsecPerSec = int64(time.Second) 27 28 // Getitimer implements linux syscall getitimer(2). 29 func Getitimer(t *kernel.Task, sysno uintptr, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 30 if t.Arch().Width() != 8 { 31 // Definition of linux.ItimerVal assumes 64-bit architecture. 32 return 0, nil, linuxerr.ENOSYS 33 } 34 35 timerID := args[0].Int() 36 addr := args[1].Pointer() 37 38 olditv, err := t.Getitimer(timerID) 39 if err != nil { 40 return 0, nil, err 41 } 42 // A NULL address is allowed, in which case no copy out takes place. 43 if addr == 0 { 44 return 0, nil, nil 45 } 46 _, err = olditv.CopyOut(t, addr) 47 return 0, nil, err 48 } 49 50 // Setitimer implements linux syscall setitimer(2). 51 func Setitimer(t *kernel.Task, sysno uintptr, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 52 if t.Arch().Width() != 8 { 53 // Definition of linux.ItimerVal assumes 64-bit architecture. 54 return 0, nil, linuxerr.ENOSYS 55 } 56 57 timerID := args[0].Int() 58 newAddr := args[1].Pointer() 59 oldAddr := args[2].Pointer() 60 61 var newitv linux.ItimerVal 62 // A NULL address is allowed because because Linux allows 63 // setitimer(which, NULL, &old_value) which disables the timer. There is a 64 // KERN_WARN message saying this misfeature will be removed. However, that 65 // hasn't happened as of 3.19, so we continue to support it. 66 if newAddr != 0 { 67 if _, err := newitv.CopyIn(t, newAddr); err != nil { 68 return 0, nil, err 69 } 70 } 71 olditv, err := t.Setitimer(timerID, newitv) 72 if err != nil { 73 return 0, nil, err 74 } 75 // A NULL address is allowed, in which case no copy out takes place. 76 if oldAddr == 0 { 77 return 0, nil, nil 78 } 79 _, err = olditv.CopyOut(t, oldAddr) 80 return 0, nil, err 81 } 82 83 // Alarm implements linux syscall alarm(2). 84 func Alarm(t *kernel.Task, sysno uintptr, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 85 duration := time.Duration(args[0].Uint()) * time.Second 86 87 olditv, err := t.Setitimer(linux.ITIMER_REAL, linux.ItimerVal{ 88 Value: linux.DurationToTimeval(duration), 89 }) 90 if err != nil { 91 return 0, nil, err 92 } 93 olddur := olditv.Value.ToDuration() 94 secs := olddur.Round(time.Second).Nanoseconds() / nsecPerSec 95 if secs == 0 && olddur != 0 { 96 // We can't return 0 if an alarm was previously scheduled. 97 secs = 1 98 } 99 return uintptr(secs), nil, nil 100 } 101 102 // TimerCreate implements linux syscall timer_create(2). 103 func TimerCreate(t *kernel.Task, sysno uintptr, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 104 clockID := args[0].Int() 105 sevp := args[1].Pointer() 106 timerIDp := args[2].Pointer() 107 108 c, err := getClock(t, clockID) 109 if err != nil { 110 return 0, nil, err 111 } 112 113 var sev *linux.Sigevent 114 if sevp != 0 { 115 sev = &linux.Sigevent{} 116 if _, err = sev.CopyIn(t, sevp); err != nil { 117 return 0, nil, err 118 } 119 } 120 121 id, err := t.IntervalTimerCreate(c, sev) 122 if err != nil { 123 return 0, nil, err 124 } 125 126 if _, err := id.CopyOut(t, timerIDp); err != nil { 127 t.IntervalTimerDelete(id) 128 return 0, nil, err 129 } 130 131 return 0, nil, nil 132 } 133 134 // TimerSettime implements linux syscall timer_settime(2). 135 func TimerSettime(t *kernel.Task, sysno uintptr, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 136 timerID := linux.TimerID(args[0].Value) 137 flags := args[1].Int() 138 newValAddr := args[2].Pointer() 139 oldValAddr := args[3].Pointer() 140 141 var newVal linux.Itimerspec 142 if _, err := newVal.CopyIn(t, newValAddr); err != nil { 143 return 0, nil, err 144 } 145 oldVal, err := t.IntervalTimerSettime(timerID, newVal, flags&linux.TIMER_ABSTIME != 0) 146 if err != nil { 147 return 0, nil, err 148 } 149 if oldValAddr != 0 { 150 _, err = oldVal.CopyOut(t, oldValAddr) 151 return 0, nil, err 152 } 153 return 0, nil, nil 154 } 155 156 // TimerGettime implements linux syscall timer_gettime(2). 157 func TimerGettime(t *kernel.Task, sysno uintptr, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 158 timerID := linux.TimerID(args[0].Value) 159 curValAddr := args[1].Pointer() 160 161 curVal, err := t.IntervalTimerGettime(timerID) 162 if err != nil { 163 return 0, nil, err 164 } 165 _, err = curVal.CopyOut(t, curValAddr) 166 return 0, nil, err 167 } 168 169 // TimerGetoverrun implements linux syscall timer_getoverrun(2). 170 func TimerGetoverrun(t *kernel.Task, sysno uintptr, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 171 timerID := linux.TimerID(args[0].Value) 172 173 o, err := t.IntervalTimerGetoverrun(timerID) 174 if err != nil { 175 return 0, nil, err 176 } 177 return uintptr(o), nil, nil 178 } 179 180 // TimerDelete implements linux syscall timer_delete(2). 181 func TimerDelete(t *kernel.Task, sysno uintptr, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 182 timerID := linux.TimerID(args[0].Value) 183 return 0, nil, t.IntervalTimerDelete(timerID) 184 }