github.com/usbarmory/GoTEE@v0.0.0-20240405084336-c52770d9fcdb/monitor/rpc.go (about) 1 // Copyright (c) WithSecure Corporation 2 // https://foundry.withsecure.com 3 // 4 // Use of this source code is governed by the license 5 // that can be found in the LICENSE file. 6 7 package monitor 8 9 import ( 10 "fmt" 11 "net/rpc/jsonrpc" 12 13 "github.com/usbarmory/GoTEE/syscall" 14 ) 15 16 // Read reads up to len(p) bytes into p. The read data is received from the 17 // execution context memory, after it is being written with syscall.Write(). 18 func (ctx *ExecCtx) Read(p []byte) (int, error) { 19 r := len(ctx.in) 20 n := len(p) 21 22 switch { 23 case r <= 0: 24 return 0, nil 25 case r < n: 26 n = r 27 } 28 29 copy(p, ctx.in[0:n]) 30 ctx.in = ctx.in[n:] 31 32 return n, nil 33 } 34 35 // Write writes len(p) bytes from p to the underlying data stream, it never 36 // returns an error. The written data is buffered within the execution context, 37 // waiting for its read through syscall.Read(). 38 func (ctx *ExecCtx) Write(p []byte) (int, error) { 39 ctx.out = append(ctx.out, p...) 40 return len(p), nil 41 } 42 43 // Close has no effect. 44 func (ctx *ExecCtx) Close() error { 45 return nil 46 } 47 48 // Recv handles syscall.Write() as received from the execution context memory, 49 // the written data is buffered (see Read()). 50 func (ctx *ExecCtx) Recv() (err error) { 51 off, n, err := ctx.TransferRegion() 52 53 if err != nil { 54 return 55 } 56 57 buf := make([]byte, n) 58 59 ctx.Memory.Read(ctx.Memory.Start(), off, buf) 60 ctx.in = append(ctx.in, buf...) 61 62 return nil 63 } 64 65 // Flush handles syscall.Read() as received from the execution context, the 66 // buffered data (see Write()) is returned to the execution context memory. 67 // 68 // A negative error number can passed as return value for syscall.Read() 69 // causing no data to be returned or flushed, zero or positive values are 70 // ignored as the number of bytes read is returned. 71 func (ctx *ExecCtx) Flush(errno int) (n int, err error) { 72 off, n, err := ctx.TransferRegion() 73 74 if err != nil { 75 return 76 } 77 78 r := len(ctx.out) 79 80 switch { 81 case errno < 0: 82 ctx.Ret(errno) 83 return 0, nil 84 case r <= 0: 85 ctx.Ret(0) 86 return 0, nil 87 case r < n: 88 n = r 89 } 90 91 ctx.Memory.Write(ctx.Memory.Start(), off, ctx.out[0:n]) 92 ctx.Ret(n) 93 94 ctx.out = ctx.out[n:] 95 96 return n, nil 97 } 98 99 func (ctx *ExecCtx) rpc() (err error) { 100 switch num := ctx.A0(); num { 101 case syscall.SYS_RPC_REQ: 102 if err = ctx.Recv(); err != nil { 103 return 104 } 105 106 err = ctx.Server.ServeRequest(jsonrpc.NewServerCodec(ctx)) 107 case syscall.SYS_RPC_RES: 108 _, err = ctx.Flush(0) 109 default: 110 err = fmt.Errorf("invalid syscall %d", num) 111 } 112 113 return 114 }