C code: void foo() {}
Assembler fragment: nacljmp %r11d,%r15
Disassembly fragment: 7: 41 83 e3 e0 and $0xffffffffffffffe0,%r11d b: 4d 01 fb add %r15,%r11 e: 41 ff e3 jmpq *%r11
C code: int get_word(int *x) { return *x; }
Assembler fragment: movl %nacl:(%r15,%rax), %eax
Disassembly fragment: 2a: 89 c0 mov %eax,%eax 2c: 41 8b 04 07 mov (%r15,%rax,1),%eax
The instruction mov %eax,%eax
is not a no-op; it truncates %rax
to 32 bits.
Sandboxing of reads is optional. Without it, we get integrity but not necessarily confidentiality, depending on what else is mapped into address space. sel_ldr would need to be careful not to map sensitive information. We may need to worry about the presence of other DLLs (see WindowsDLLInjectionProblem). We would want sandboxing of reads in cases where we want to enforce DeterministicExecution.
C code: int put_word(int *x) { *x = 0x100; }
Assembler fragment: movl $256, %nacl:(%r15,%rax)
Disassembly fragment: 4a: 89 c0 mov %eax,%eax 4c: 41 c7 04 07 00 01 00 movl $0x100,(%r15,%rax,1)
C code: static int var; void set_var() { var = 0x100; }
Assembler fragment: movl $256, var(%rip)
Disassembly fragment: 104: c7 05 00 00 00 00 00 movl $0x100,0x0(%rip) 10b: 01 00 00 106: R_X86_64_PC32 .bss-0x8
RIP-relative addressing is always safe. You can only use 2GB offset from %rip (x86-64 limitation) and so can not address anything outside of protected area, which has 40GB unmapped gaps before and after.