gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/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 "gvisor.dev/gvisor/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 // CopyInN is like CopyIn, but explicitly requests a partial 116 // copy-in. Note that this may yield unexpected results for non-packed 117 // types and the caller may only want to allow this for packed types. See 118 // comment on UnmarshalBytes. 119 // 120 // The limit must be less than or equal to SizeBytes(). 121 CopyInN(cc CopyContext, addr hostarch.Addr, limit int) (int, error) 122 123 // CopyOut serializes a Marshallable type to a task's memory. This may only 124 // be called from a task goroutine. This is more efficient than calling 125 // MarshalUnsafe on Marshallable.Packed types, as the type being serialized 126 // does not escape. The implementation should avoid creating extra copies in 127 // memory by directly serializing from the object's underlying memory. 128 // 129 // The copy-out to the task memory may be partially successful, in which 130 // case CopyOut returns how much data was serialized. See comment for 131 // MarshalBytes for implications. 132 CopyOut(cc CopyContext, addr hostarch.Addr) (int, error) 133 134 // CopyOutN is like CopyOut, but explicitly requests a partial 135 // copy-out. Note that this may yield unexpected results for non-packed 136 // types and the caller may only want to allow this for packed types. See 137 // comment on MarshalBytes. 138 // 139 // The limit must be less than or equal to SizeBytes(). 140 CopyOutN(cc CopyContext, addr hostarch.Addr, limit int) (int, error) 141 } 142 143 // CheckedMarshallable represents operations on a type that can be marshalled 144 // to and from memory and additionally does bound checking. 145 type CheckedMarshallable interface { 146 // CheckedMarshal is the same as Marshallable.MarshalUnsafe but without the 147 // precondition that dst must at least have some appropriate length. Similar 148 // to Marshallable.MarshalBytes, it returns a shifted slice according to how 149 // much data is consumed. Additionally it returns a bool indicating whether 150 // marshalling was successful. Unsuccessful marshalling doesn't consume any 151 // data. 152 CheckedMarshal(dst []byte) ([]byte, bool) 153 154 // CheckedUnmarshal is the same as Marshallable.UmarshalUnsafe but without 155 // the precondition that src must at least have some appropriate length. 156 // Similar to Marshallable.UnmarshalBytes, it returns a shifted slice 157 // according to how much data is consumed. Additionally it returns a bool 158 // indicating whether marshalling was successful. Unsuccessful marshalling 159 // doesn't consume any data. 160 CheckedUnmarshal(src []byte) ([]byte, bool) 161 } 162 163 // go-marshal generates additional functions for a type based on additional 164 // clauses to the +marshal directive. They are documented below. 165 // 166 // Slice API 167 // ========= 168 // 169 // Adding a "slice" clause to the +marshal directive for structs or newtypes on 170 // primitives like this: 171 // 172 // // +marshal slice:FooSlice 173 // type Foo struct { ... } 174 // 175 // Generates four additional functions for marshalling slices of Foos like this: 176 // 177 // // MarshalUnsafeFooSlice is like Foo.MarshalUnsafe, buf for a []Foo. It 178 // // might be more efficient that repeatedly calling Foo.MarshalUnsafe 179 // // over a []Foo in a loop if the type is Packed. 180 // // Preconditions: dst must be at least len(src)*Foo.SizeBytes() in length. 181 // func MarshalUnsafeFooSlice(src []Foo, dst []byte) []byte { ... } 182 // 183 // // UnmarshalUnsafeFooSlice is like Foo.UnmarshalUnsafe, buf for a []Foo. It 184 // // might be more efficient that repeatedly calling Foo.UnmarshalUnsafe 185 // // over a []Foo in a loop if the type is Packed. 186 // // Preconditions: src must be at least len(dst)*Foo.SizeBytes() in length. 187 // func UnmarshalUnsafeFooSlice(dst []Foo, src []byte) []byte { ... } 188 // 189 // // CopyFooSliceIn copies in a slice of Foo objects from the task's memory. 190 // func CopyFooSliceIn(cc marshal.CopyContext, addr hostarch.Addr, dst []Foo) (int, error) { ... } 191 // 192 // // CopyFooSliceIn copies out a slice of Foo objects to the task's memory. 193 // func CopyFooSliceOut(cc marshal.CopyContext, addr hostarch.Addr, src []Foo) (int, error) { ... } 194 // 195 // The name of the functions are of the format "Copy%sIn" and "Copy%sOut", where 196 // %s is the first argument to the slice clause. This directive is not supported 197 // for newtypes on arrays. 198 // 199 // Note: Partial copies are not supported for Slice API UnmarshalUnsafe and 200 // MarshalUnsafe. 201 // 202 // The slice clause also takes an optional second argument, which must be the 203 // value "inner": 204 // 205 // // +marshal slice:Int32Slice:inner 206 // type Int32 int32 207 // 208 // This is only valid on newtypes on primitives, and causes the generated 209 // functions to accept slices of the inner type instead: 210 // 211 // func CopyInt32SliceIn(cc marshal.CopyContext, addr hostarch.Addr, dst []int32) (int, error) { ... } 212 // 213 // Without "inner", they would instead be: 214 // 215 // func CopyInt32SliceIn(cc marshal.CopyContext, addr hostarch.Addr, dst []Int32) (int, error) { ... } 216 // 217 // This may help avoid a cast depending on how the generated functions are used. 218 // 219 // Bound Checking 220 // ============== 221 // 222 // Some users might want to do bound checking on marshal and unmarshal. This is 223 // is useful when the user does not control the buffer size. To prevent 224 // repeated bound checking code around Marshallable, users can add a 225 // "boundCheck" clause to the +marshal directive. go_marshal will generate the 226 // CheckedMarshallable interface methods on the type.