1. ia32 code modification rules

  1. Replacement code block must be valid as per regular NaCl ia32 rules with one exception (see below).
  2. Boundaries of the instructions must not be changed.
  3. Superinstructions (naclcall/nacljmp) must not be changed.
  4. One tiny exception to the rule #1: if instruction is direct jump or direct call and it refers unaligned address outside of the [dest, dest+size) region then it’s allowed as long as it’s not modified.

The exception above exist to support modifications of small pieces of code in a large code block. If code was accepted by the nacl_dyncode_create then it means that all the targets in all jcc, jmp, and call instructions are valid WRT their targets — and if jcc, jmp, or call point to unknown (in the nacl_dyncode_modify) address everything is fine as long as this address is unmodified: if it was valid once it’s valid always because modifications of instruction boundaries are not allowed.


2. amd64 (aka x86-64, aka intel64) code modification rules

  1. Replacement code block must be valid as per regular NaCl amd64 rules with one exception (see below).
  2. Only instructions in the following list can be modified:
  3. Instructions can only be modified by altering their anyfields (that is: displacements, relative offsets or immediates).
  4. Note: since we don’t allow any modifications to the instructions (except for the anyfields which don’t affect length) instruction boundaries are automatically unchanged in this case, too.
  5. One tiny exception to the rule #1: if instruction is direct jump or direct call and it refers unaligned address outside of the [dest, dest+size) region then it’s allowed as long as it’s not modified.

Rationale for the exception in x86-64 case is the same as in ia32 case.


This logic is implemented in dfa_validate_xxx.c files. Function ApplyDfaValidator_x86_xx implements initial validation (used in nacl_dyncode_create) while couple of functions ValidatorCodeReplacement_x86_xx/ValidatorCopy_x86_xx are used in nacl_dyncode_modify (ValidatorCodeReplacement_x86_xx determines if the rules above are unbroken and ValidatorCopy_x86_xx is used to process instructions one-after-another by NaClCopyInstructionFunc). Note: ValidatorCopy_x86_xx assumes code was accepted by the ValidatorCodeReplacement_x86_xx function. Result for code which is not verified by ValidatorCodeReplacement_x86_xx is not defined and NaClCopyInstructionFunc is external function passed to ValidatorCopy_x86_xx which guarantees safe replacement of a single instruction in a presence of threads.