int __execute_only_pkey(struct mm_struct *mm)
{ bool need_to_set_mm_pkey = false; int execute_only_pkey = mm->context.execute_only_pkey; int ret;
/* Do we need to assign a pkey for mm's execute-only maps? */ if (execute_only_pkey == -1) { /* Go allocate one to use, which might fail */
execute_only_pkey = mm_pkey_alloc(mm); if (execute_only_pkey < 0) return -1;
need_to_set_mm_pkey = true;
}
/* * We do not want to go through the relatively costly * dance to set PKRU if we do not need to. Check it * first and assume that if the execute-only pkey is * write-disabled that we do not have to set it * ourselves.
*/ if (!need_to_set_mm_pkey &&
!__pkru_allows_read(read_pkru(), execute_only_pkey)) { return execute_only_pkey;
}
/* * Set up PKRU so that it denies access for everything * other than execution.
*/
ret = arch_set_user_pkey_access(current, execute_only_pkey,
PKEY_DISABLE_ACCESS); /* * If the PKRU-set operation failed somehow, just return * 0 and effectively disable execute-only support.
*/ if (ret) {
mm_set_pkey_free(mm, execute_only_pkey); return -1;
}
/* We got one, store it and use it from here on out */ if (need_to_set_mm_pkey)
mm->context.execute_only_pkey = execute_only_pkey; return execute_only_pkey;
}
staticinlinebool vma_is_pkey_exec_only(struct vm_area_struct *vma)
{ /* Do this check first since the vm_flags should be hot */ if ((vma->vm_flags & VM_ACCESS_FLAGS) != VM_EXEC) returnfalse; if (vma_pkey(vma) != vma->vm_mm->context.execute_only_pkey) returnfalse;
returntrue;
}
/* * This is only called for *plain* mprotect calls.
*/ int __arch_override_mprotect_pkey(struct vm_area_struct *vma, int prot, int pkey)
{ /* * Is this an mprotect_pkey() call? If so, never * override the value that came from the user.
*/ if (pkey != -1) return pkey;
/* * The mapping is execute-only. Go try to get the * execute-only protection key. If we fail to do that, * fall through as if we do not have execute-only * support in this mm.
*/ if (prot == PROT_EXEC) {
pkey = execute_only_pkey(vma->vm_mm); if (pkey > 0) return pkey;
} elseif (vma_is_pkey_exec_only(vma)) { /* * Protections are *not* PROT_EXEC, but the mapping * is using the exec-only pkey. This mapping was * PROT_EXEC and will no longer be. Move back to * the default pkey.
*/ return ARCH_DEFAULT_PKEY;
}
/* * This is a vanilla, non-pkey mprotect (or we failed to * setup execute-only), inherit the pkey from the VMA we * are working on.
*/ return vma_pkey(vma);
}
/* * Make the default PKRU value (at execve() time) as restrictive * as possible. This ensures that any threads clone()'d early * in the process's lifetime will not accidentally get access * to data which is pkey-protected later on.
*/
u32 init_pkru_value = PKRU_AD_MASK( 1) | PKRU_AD_MASK( 2) |
PKRU_AD_MASK( 3) | PKRU_AD_MASK( 4) |
PKRU_AD_MASK( 5) | PKRU_AD_MASK( 6) |
PKRU_AD_MASK( 7) | PKRU_AD_MASK( 8) |
PKRU_AD_MASK( 9) | PKRU_AD_MASK(10) |
PKRU_AD_MASK(11) | PKRU_AD_MASK(12) |
PKRU_AD_MASK(13) | PKRU_AD_MASK(14) |
PKRU_AD_MASK(15);
len = min(count, sizeof(buf) - 1); if (copy_from_user(buf, user_buf, len)) return -EFAULT;
/* Make the buffer a valid string that we can not overrun */
buf[len] = '\0'; if (kstrtouint(buf, 0, &new_init_pkru)) return -EINVAL;
/* * Don't allow insane settings that will blow the system * up immediately if someone attempts to disable access * or writes to pkey 0.
*/ if (new_init_pkru & (PKRU_AD_BIT|PKRU_WD_BIT)) return -EINVAL;
staticint __init create_init_pkru_value(void)
{ /* Do not expose the file if pkeys are not supported. */ if (!cpu_feature_enabled(X86_FEATURE_OSPKE)) return 0;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.