@@ -1107,10 +1107,28 @@ access_error(unsigned long error_code, struct vm_area_struct *vma)
(error_code & X86_PF_INSTR), foreign))
return 1;
- if (error_code & X86_PF_WRITE) {
+ if (error_code & (X86_PF_WRITE | X86_PF_INSTR)) {
+ /*
+ * CPUs are not expected to set the two error code bits
+ * together, but to ensure that hypervisors do not misbehave,
+ * run an additional sanity check.
+ */
+ if ((error_code & (X86_PF_WRITE|X86_PF_INSTR)) ==
+ (X86_PF_WRITE|X86_PF_INSTR)) {
+ WARN_ON_ONCE(1);
+ return 1;
+ }
+
/* write, present and write, not present: */
- if (unlikely(!(vma->vm_flags & VM_WRITE)))
+ if ((error_code & X86_PF_WRITE) &&
+ unlikely(!(vma->vm_flags & VM_WRITE)))
+ return 1;
+
+ /* exec, present and exec, not present: */
+ if ((error_code & X86_PF_INSTR) &&
+ unlikely(!(vma->vm_flags & VM_EXEC)))
return 1;
+
return 0;
}