github.com/nicocha30/gvisor-ligolo@v0.0.0-20230726075806-989fa2c0a413/pkg/marshal/marshal.go (about) 1 // Copyright 2019 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 marshal defines the Marshallable interface for 16 // serialize/deserializing go data structures to/from memory, according to the 17 // Linux ABI. 18 // 19 // Implementations of this interface are typically automatically generated by 20 // tools/go_marshal. See the go_marshal README for details. 21 package marshal 22 23 import ( 24 "io" 25 26 "github.com/nicocha30/gvisor-ligolo/pkg/hostarch" 27 ) 28 29 // CopyContext defines the memory operations required to marshal to and from 30 // user memory. Typically, kernel.Task is used to provide implementations for 31 // these operations. 32 type CopyContext interface { 33 // CopyScratchBuffer provides a task goroutine-local scratch buffer. See 34 // kernel.CopyScratchBuffer. 35 CopyScratchBuffer(size int) []byte 36 37 // CopyOutBytes writes the contents of b to the task's memory. See 38 // kernel.CopyOutBytes. 39 CopyOutBytes(addr hostarch.Addr, b []byte) (int, error) 40 41 // CopyInBytes reads the contents of the task's memory to b. See 42 // kernel.CopyInBytes. 43 CopyInBytes(addr hostarch.Addr, b []byte) (int, error) 44 } 45 46 // Marshallable represents operations on a type that can be marshalled to and 47 // from memory. 48 // 49 // go-marshal automatically generates implementations for this interface for 50 // types marked as '+marshal'. 51 type Marshallable interface { 52 io.WriterTo 53 54 // SizeBytes is the size of the memory representation of a type in 55 // marshalled form. 56 // 57 // SizeBytes must handle a nil receiver. Practically, this means SizeBytes 58 // cannot deference any fields on the object implementing it (but will 59 // likely make use of the type of these fields). 60 SizeBytes() int 61 62 // MarshalBytes serializes a copy of a type to dst and returns the remaining 63 // buffer. 64 // Precondition: dst must be at least SizeBytes() in length. 65 MarshalBytes(dst []byte) []byte 66 67 // UnmarshalBytes deserializes a type from src and returns the remaining 68 // buffer. 69 // Precondition: src must be at least SizeBytes() in length. 70 UnmarshalBytes(src []byte) []byte 71 72 // Packed returns true if the marshalled size of the type is the same as the 73 // size it occupies in memory. This happens when the type has no fields 74 // starting at unaligned addresses (should always be true by default for ABI 75 // structs, verified by automatically generated tests when using 76 // go_marshal), and has no fields marked `marshal:"unaligned"`. 77 // 78 // Packed must return the same result for all possible values of the type 79 // implementing it. Violating this constraint implies the type doesn't have 80 // a static memory layout, and will lead to memory corruption. 81 // Go-marshal-generated code reuses the result of Packed for multiple values 82 // of the same type. 83 Packed() bool 84 85 // MarshalUnsafe serializes a type by bulk copying its in-memory 86 // representation to the dst buffer. This is only safe to do when the type 87 // has no implicit padding, see Marshallable.Packed. When Packed would 88 // return false, MarshalUnsafe should fall back to the safer but slower 89 // MarshalBytes. 90 // Precondition: dst must be at least SizeBytes() in length. 91 MarshalUnsafe(dst []byte) []byte 92 93 // UnmarshalUnsafe deserializes a type by directly copying to the underlying 94 // memory allocated for the object by the runtime. 95 // 96 // This allows much faster unmarshalling of types which have no implicit 97 // padding, see Marshallable.Packed. When Packed would return false, 98 // UnmarshalUnsafe should fall back to the safer but slower unmarshal 99 // mechanism implemented in UnmarshalBytes. 100 // Precondition: src must be at least SizeBytes() in length. 101 UnmarshalUnsafe(src []byte) []byte 102 103 // CopyIn deserializes a Marshallable type from a task's memory. This may 104 // only be called from a task goroutine. This is more efficient than calling 105 // UnmarshalUnsafe on Marshallable.Packed types, as the type being 106 // marshalled does not escape. The implementation should avoid creating 107 // extra copies in memory by directly deserializing to the object's 108 // underlying memory. 109 // 110 // If the copy-in from the task memory is only partially successful, CopyIn 111 // should still attempt to deserialize as much data as possible. See comment 112 // for UnmarshalBytes. 113 CopyIn(cc CopyContext, addr hostarch.Addr) (int, error) 114 115 // CopyOut serializes a Marshallable type to a task's memory. This may only 116 // be called from a task goroutine. This is more efficient than calling 117 // MarshalUnsafe on Marshallable.Packed types, as the type being serialized 118 // does not escape. The implementation should avoid creating extra copies in 119 // memory by directly serializing from the object's underlying memory. 120 // 121 // The copy-out to the task memory may be partially successful, in which 122 // case CopyOut returns how much data was serialized. See comment for 123 // MarshalBytes for implications. 124 CopyOut(cc CopyContext, addr hostarch.Addr) (int, error) 125 126 // CopyOutN is like CopyOut, but explicitly requests a partial 127 // copy-out. Note that this may yield unexpected results for non-packed 128 // types and the caller may only want to allow this for packed types. See 129 // comment on MarshalBytes. 130 // 131 // The limit must be less than or equal to SizeBytes(). 132 CopyOutN(cc CopyContext, addr hostarch.Addr, limit int) (int, error) 133 } 134 135 // CheckedMarshallable represents operations on a type that can be marshalled 136 // to and from memory and additionally does bound checking. 137 type CheckedMarshallable interface { 138 // CheckedMarshal is the same as Marshallable.MarshalUnsafe but without the 139 // precondition that dst must at least have some appropriate length. Similar 140 // to Marshallable.MarshalBytes, it returns a shifted slice according to how 141 // much data is consumed. Additionally it returns a bool indicating whether 142 // marshalling was successful. Unsuccessful marshalling doesn't consume any 143 // data. 144 CheckedMarshal(dst []byte) ([]byte, bool) 145 146 // CheckedUnmarshal is the same as Marshallable.UmarshalUnsafe but without 147 // the precondition that src must at least have some appropriate length. 148 // Similar to Marshallable.UnmarshalBytes, it returns a shifted slice 149 // according to how much data is consumed. Additionally it returns a bool 150 // indicating whether marshalling was successful. Unsuccessful marshalling 151 // doesn't consume any data. 152 CheckedUnmarshal(src []byte) ([]byte, bool) 153 } 154 155 // go-marshal generates additional functions for a type based on additional 156 // clauses to the +marshal directive. They are documented below. 157 // 158 // Slice API 159 // ========= 160 // 161 // Adding a "slice" clause to the +marshal directive for structs or newtypes on 162 // primitives like this: 163 // 164 // // +marshal slice:FooSlice 165 // type Foo struct { ... } 166 // 167 // Generates four additional functions for marshalling slices of Foos like this: 168 // 169 // // MarshalUnsafeFooSlice is like Foo.MarshalUnsafe, buf for a []Foo. It 170 // // might be more efficient that repeatedly calling Foo.MarshalUnsafe 171 // // over a []Foo in a loop if the type is Packed. 172 // // Preconditions: dst must be at least len(src)*Foo.SizeBytes() in length. 173 // func MarshalUnsafeFooSlice(src []Foo, dst []byte) []byte { ... } 174 // 175 // // UnmarshalUnsafeFooSlice is like Foo.UnmarshalUnsafe, buf for a []Foo. It 176 // // might be more efficient that repeatedly calling Foo.UnmarshalUnsafe 177 // // over a []Foo in a loop if the type is Packed. 178 // // Preconditions: src must be at least len(dst)*Foo.SizeBytes() in length. 179 // func UnmarshalUnsafeFooSlice(dst []Foo, src []byte) []byte { ... } 180 // 181 // // CopyFooSliceIn copies in a slice of Foo objects from the task's memory. 182 // func CopyFooSliceIn(cc marshal.CopyContext, addr hostarch.Addr, dst []Foo) (int, error) { ... } 183 // 184 // // CopyFooSliceIn copies out a slice of Foo objects to the task's memory. 185 // func CopyFooSliceOut(cc marshal.CopyContext, addr hostarch.Addr, src []Foo) (int, error) { ... } 186 // 187 // The name of the functions are of the format "Copy%sIn" and "Copy%sOut", where 188 // %s is the first argument to the slice clause. This directive is not supported 189 // for newtypes on arrays. 190 // 191 // Note: Partial copies are not supported for Slice API UnmarshalUnsafe and 192 // MarshalUnsafe. 193 // 194 // The slice clause also takes an optional second argument, which must be the 195 // value "inner": 196 // 197 // // +marshal slice:Int32Slice:inner 198 // type Int32 int32 199 // 200 // This is only valid on newtypes on primitives, and causes the generated 201 // functions to accept slices of the inner type instead: 202 // 203 // func CopyInt32SliceIn(cc marshal.CopyContext, addr hostarch.Addr, dst []int32) (int, error) { ... } 204 // 205 // Without "inner", they would instead be: 206 // 207 // func CopyInt32SliceIn(cc marshal.CopyContext, addr hostarch.Addr, dst []Int32) (int, error) { ... } 208 // 209 // This may help avoid a cast depending on how the generated functions are used. 210 // 211 // Bound Checking 212 // ============== 213 // 214 // Some users might want to do bound checking on marshal and unmarshal. This is 215 // is useful when the user does not control the buffer size. To prevent 216 // repeated bound checking code around Marshallable, users can add a 217 // "boundCheck" clause to the +marshal directive. go_marshal will generate the 218 // CheckedMarshallable interface methods on the type.