| OLD | NEW |
| 1 #!/usr/bin/python | 1 #!/usr/bin/python |
| 2 # Copyright 2014 The Chromium Authors. All rights reserved. | 2 # Copyright 2014 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 | 5 |
| 6 # pylint: disable=W0104,W0106,F0401,R0201 | 6 # pylint: disable=W0104,W0106,F0401,R0201 |
| 7 | 7 |
| 8 import optparse | 8 import optparse |
| 9 import os.path | 9 import os.path |
| 10 import sys | 10 import sys |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 150 # Parameters passed into trusted code are handled differently depending on | 150 # Parameters passed into trusted code are handled differently depending on |
| 151 # details of the parameter. ParamImpl instances encapsulate these differences | 151 # details of the parameter. ParamImpl instances encapsulate these differences |
| 152 # and are used to generate the code that transfers parameters across the | 152 # and are used to generate the code that transfers parameters across the |
| 153 # untrusted/trusted boundary. | 153 # untrusted/trusted boundary. |
| 154 class ParamImpl(object): | 154 class ParamImpl(object): |
| 155 def __init__(self, param): | 155 def __init__(self, param): |
| 156 self.param = param | 156 self.param = param |
| 157 | 157 |
| 158 # Declare whatever variables are needed to handle this particular parameter. | 158 # Declare whatever variables are needed to handle this particular parameter. |
| 159 def DeclareVars(self, code): | 159 def DeclareVars(self, code): |
| 160 raise NotImplementedError() | 160 raise NotImplementedError(type(self)) |
| 161 | 161 |
| 162 # Convert the untrusted representation of the parameter into a trusted | 162 # Convert the untrusted representation of the parameter into a trusted |
| 163 # representation, such as a scalar value or a trusted pointer into the | 163 # representation, such as a scalar value or a trusted pointer into the |
| 164 # untrusted address space. | 164 # untrusted address space. |
| 165 def ConvertParam(self): | 165 def ConvertParam(self): |
| 166 raise NotImplementedError() | 166 raise NotImplementedError(type(self)) |
| 167 | 167 |
| 168 # For this particular parameter, what expression should be passed when | 168 # For this particular parameter, what expression should be passed when |
| 169 # invoking the trusted Mojo API function? | 169 # invoking the trusted Mojo API function? |
| 170 def CallParam(self): | 170 def CallParam(self): |
| 171 raise NotImplementedError() | 171 raise NotImplementedError(type(self)) |
| 172 | 172 |
| 173 # After invoking the trusted Mojo API function, transfer data back into | 173 # After invoking the trusted Mojo API function, transfer data back into |
| 174 # untrusted memory. Overriden for Out and InOut parameters. | 174 # untrusted memory. Overriden for Out and InOut parameters. |
| 175 def CopyOut(self, code): | 175 def CopyOut(self, code): |
| 176 pass | 176 pass |
| 177 | 177 |
| 178 # Converting array parameters needs to be defered until after the scalar | 178 # Converting array parameters needs to be defered until after the scalar |
| 179 # parameter containing the size of the array has itself been converted. | 179 # parameter containing the size of the array has itself been converted. |
| 180 def IsArray(self): | 180 def IsArray(self): |
| 181 return False | 181 return False |
| (...skipping 12 matching lines...) Expand all Loading... |
| 194 return '%s_value' % self.param.name | 194 return '%s_value' % self.param.name |
| 195 | 195 |
| 196 | 196 |
| 197 class ScalarOutputImpl(ParamImpl): | 197 class ScalarOutputImpl(ParamImpl): |
| 198 def DeclareVars(self, code): | 198 def DeclareVars(self, code): |
| 199 code << '%s volatile* %s_ptr;' % (self.param.base_type, self.param.name) | 199 code << '%s volatile* %s_ptr;' % (self.param.base_type, self.param.name) |
| 200 code << '%s %s_value;' % (self.param.base_type, self.param.name) | 200 code << '%s %s_value;' % (self.param.base_type, self.param.name) |
| 201 | 201 |
| 202 def ConvertParam(self): | 202 def ConvertParam(self): |
| 203 p = self.param | 203 p = self.param |
| 204 return 'ConvertScalarOutput(nap, params[%d], &%s_ptr)' % (p.uid + 1, p.name) | 204 return ('ConvertScalarOutput(nap, params[%d], %s, &%s_ptr)' % |
| 205 (p.uid + 1, CBool(p.is_optional), p.name)) |
| 205 | 206 |
| 206 def CallParam(self): | 207 def CallParam(self): |
| 207 return '&%s_value' % self.param.name | 208 name = self.param.name |
| 209 expr = '&%s_value' % name |
| 210 if self.param.is_optional: |
| 211 expr = '%s_ptr ? %s : NULL' % (name, expr) |
| 212 return expr |
| 208 | 213 |
| 209 def CopyOut(self, code): | 214 def CopyOut(self, code): |
| 210 name = self.param.name | 215 name = self.param.name |
| 211 code << '*%s_ptr = %s_value;' % (name, name) | 216 if self.param.is_struct: |
| 217 # C++ errors when you try to copy a volatile struct pointer. |
| 218 # (There are no default copy constructors for this case.) |
| 219 # memcpy instead. |
| 220 copy_stmt = ('memcpy_volatile_out(%s_ptr, &%s_value, sizeof(%s));' % |
| 221 (name, name, self.param.base_type)) |
| 222 else: |
| 223 copy_stmt = '*%s_ptr = %s_value;' % (name, name) |
| 224 |
| 225 if self.param.is_optional: |
| 226 code << 'if (%s_ptr != NULL) {' % (name) |
| 227 with code.Indent(): |
| 228 code << copy_stmt |
| 229 code << '}' |
| 230 else: |
| 231 code << copy_stmt |
| 212 | 232 |
| 213 | 233 |
| 214 class ScalarInOutImpl(ParamImpl): | 234 class ScalarInOutImpl(ParamImpl): |
| 215 def DeclareVars(self, code): | 235 def DeclareVars(self, code): |
| 216 code << '%s volatile* %s_ptr;' % (self.param.base_type, self.param.name) | 236 code << '%s volatile* %s_ptr;' % (self.param.base_type, self.param.name) |
| 217 code << '%s %s_value;' % (self.param.base_type, self.param.name) | 237 code << '%s %s_value;' % (self.param.base_type, self.param.name) |
| 218 | 238 |
| 219 def ConvertParam(self): | 239 def ConvertParam(self): |
| 220 p = self.param | 240 p = self.param |
| 221 return ('ConvertScalarInOut(nap, params[%d], %s, &%s_value, &%s_ptr)' % | 241 return ('ConvertScalarInOut(nap, params[%d], %s, &%s_value, &%s_ptr)' % |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 254 (p.uid + 1, p.size + '_value', element_size, CBool(p.is_optional), | 274 (p.uid + 1, p.size + '_value', element_size, CBool(p.is_optional), |
| 255 p.name)) | 275 p.name)) |
| 256 | 276 |
| 257 def CallParam(self): | 277 def CallParam(self): |
| 258 return self.param.name | 278 return self.param.name |
| 259 | 279 |
| 260 def IsArray(self): | 280 def IsArray(self): |
| 261 return True | 281 return True |
| 262 | 282 |
| 263 | 283 |
| 264 class StructInputImpl(ParamImpl): | 284 class ExtensibleStructInputImpl(ParamImpl): |
| 265 def DeclareVars(self, code): | 285 def DeclareVars(self, code): |
| 266 code << '%s %s;' % (self.param.param_type, self.param.name) | 286 code << '%s %s;' % (self.param.param_type, self.param.name) |
| 267 | 287 |
| 268 def ConvertParam(self): | 288 def ConvertParam(self): |
| 269 p = self.param | 289 p = self.param |
| 270 return ('ConvertStruct(nap, params[%d], %s, &%s)' % | 290 return ('ConvertExtensibleStructInput(nap, params[%d], %s, &%s)' % |
| 271 (p.uid + 1, CBool(p.is_optional), p.name)) | 291 (p.uid + 1, CBool(p.is_optional), p.name)) |
| 272 | 292 |
| 273 def CallParam(self): | 293 def CallParam(self): |
| 274 return self.param.name | 294 return self.param.name |
| 275 | 295 |
| 276 | |
| 277 def ImplForParam(p): | 296 def ImplForParam(p): |
| 278 if p.IsScalar(): | 297 if p.IsScalar(): |
| 279 if p.is_output: | 298 if p.is_output: |
| 280 if p.is_input: | 299 if p.is_input: |
| 281 return ScalarInOutImpl(p) | 300 return ScalarInOutImpl(p) |
| 282 else: | 301 else: |
| 283 return ScalarOutputImpl(p) | 302 if p.is_always_written: |
| 303 return ScalarOutputImpl(p) |
| 304 else: |
| 305 # Mojo defines that some of its outputs will not be set in specific |
| 306 # cases. To avoid the complexity of determining if the output was set |
| 307 # by Mojo, copy the output's current value (possibly junk) and copy it |
| 308 # back to untrusted memory afterwards. |
| 309 return ScalarInOutImpl(p) |
| 284 else: | 310 else: |
| 285 return ScalarInputImpl(p) | 311 return ScalarInputImpl(p) |
| 286 elif p.is_array: | 312 elif p.is_array: |
| 287 return ArrayImpl(p) | 313 return ArrayImpl(p) |
| 288 elif p.is_struct: | 314 elif p.is_struct: |
| 289 return StructInputImpl(p) | 315 if p.is_input and not p.is_output and p.is_extensible: |
| 290 else: | 316 return ExtensibleStructInputImpl(p) |
| 291 assert False, p | 317 if not p.is_input and p.is_output and not p.is_extensible: |
| 318 return ScalarOutputImpl(p) |
| 319 assert False, p.name |
| 292 | 320 |
| 293 | 321 |
| 294 def CBool(value): | 322 def CBool(value): |
| 295 return 'true' if value else 'false' | 323 return 'true' if value else 'false' |
| 296 | 324 |
| 297 | 325 |
| 298 # A trusted wrapper that validates the arguments passed from untrusted code | 326 # A trusted wrapper that validates the arguments passed from untrusted code |
| 299 # before passing them to the underlying public Mojo API. | 327 # before passing them to the underlying public Mojo API. |
| 300 def GenerateMojoSyscall(functions, out): | 328 def GenerateMojoSyscall(functions, out): |
| 301 template = jinja_env.get_template('mojo_syscall.cc.tmpl') | 329 template = jinja_env.get_template('mojo_syscall.cc.tmpl') |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 395 | 423 |
| 396 out = OutFile(options.out_dir, 'libmojo.cc') | 424 out = OutFile(options.out_dir, 'libmojo.cc') |
| 397 GenerateLibMojo(mojo.functions, out) | 425 GenerateLibMojo(mojo.functions, out) |
| 398 | 426 |
| 399 out = OutFile(options.out_dir, 'mojo_syscall.cc') | 427 out = OutFile(options.out_dir, 'mojo_syscall.cc') |
| 400 GenerateMojoSyscall(mojo.functions, out) | 428 GenerateMojoSyscall(mojo.functions, out) |
| 401 | 429 |
| 402 | 430 |
| 403 if __name__ == '__main__': | 431 if __name__ == '__main__': |
| 404 main(sys.argv[1:]) | 432 main(sys.argv[1:]) |
| OLD | NEW |