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  }