€•—DŒsphinx.addnodes”Œdocument”“”)”}”(Œ rawsource”Œ”Œchildren”]”(Œ translations”Œ LanguagesNode”“”)”}”(hhh]”(hŒ pending_xref”“”)”}”(hhh]”Œdocutils.nodes”ŒText”“”ŒChinese (Simplified)”…””}”Œparent”hsbaŒ attributes”}”(Œids”]”Œclasses”]”Œnames”]”Œdupnames”]”Œbackrefs”]”Œ refdomain”Œstd”Œreftype”Œdoc”Œ reftarget”Œ,/translations/zh_CN/core-api/protection-keys”Œmodname”NŒ classname”NŒ refexplicit”ˆuŒtagname”hhh ubh)”}”(hhh]”hŒChinese (Traditional)”…””}”hh2sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ,/translations/zh_TW/core-api/protection-keys”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒItalian”…””}”hhFsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ,/translations/it_IT/core-api/protection-keys”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒJapanese”…””}”hhZsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ,/translations/ja_JP/core-api/protection-keys”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒKorean”…””}”hhnsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ,/translations/ko_KR/core-api/protection-keys”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒPortuguese (Brazilian)”…””}”hh‚sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ,/translations/pt_BR/core-api/protection-keys”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒSpanish”…””}”hh–sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ,/translations/sp_SP/core-api/protection-keys”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubeh}”(h]”h ]”h"]”h$]”h&]”Œcurrent_language”ŒEnglish”uh1h hhŒ _document”hŒsource”NŒline”NubhŒcomment”“”)”}”(hŒ SPDX-License-Identifier: GPL-2.0”h]”hŒ SPDX-License-Identifier: GPL-2.0”…””}”hh·sbah}”(h]”h ]”h"]”h$]”h&]”Œ xml:space”Œpreserve”uh1hµhhh²hh³ŒF/var/lib/git/docbuild/linux/Documentation/core-api/protection-keys.rst”h´KubhŒsection”“”)”}”(hhh]”(hŒtitle”“”)”}”(hŒMemory Protection Keys”h]”hŒMemory Protection Keys”…””}”(hhÏh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhhÊh²hh³hÇh´KubhŒ paragraph”“”)”}”(hŒ¶Memory Protection Keys provide a mechanism for enforcing page-based protections, but without requiring modification of the page tables when an application changes protection domains.”h]”hŒ¶Memory Protection Keys provide a mechanism for enforcing page-based protections, but without requiring modification of the page tables when an application changes protection domains.”…””}”(hhßh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´KhhÊh²hubhŒdefinition_list”“”)”}”(hhh]”hŒdefinition_list_item”“”)”}”(hŒõPkeys Userspace (PKU) is a feature which can be found on: * Intel server CPUs, Skylake and later * Intel client CPUs, Tiger Lake (11th Gen Core) and later * Future AMD CPUs * arm64 CPUs implementing the Permission Overlay Extension (FEAT_S1POE) ”h]”(hŒterm”“”)”}”(hŒ9Pkeys Userspace (PKU) is a feature which can be found on:”h]”hŒ9Pkeys Userspace (PKU) is a feature which can be found on:”…””}”(hhúh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1høh³hÇh´KhhôubhŒ definition”“”)”}”(hhh]”hŒ bullet_list”“”)”}”(hhh]”(hŒ list_item”“”)”}”(hŒ$Intel server CPUs, Skylake and later”h]”hÞ)”}”(hjh]”hŒ$Intel server CPUs, Skylake and later”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K hjubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjubj)”}”(hŒ7Intel client CPUs, Tiger Lake (11th Gen Core) and later”h]”hÞ)”}”(hj-h]”hŒ7Intel client CPUs, Tiger Lake (11th Gen Core) and later”…””}”(hj/h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K hj+ubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjubj)”}”(hŒFuture AMD CPUs”h]”hÞ)”}”(hjDh]”hŒFuture AMD CPUs”…””}”(hjFh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´KhjBubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjubj)”}”(hŒFarm64 CPUs implementing the Permission Overlay Extension (FEAT_S1POE) ”h]”hÞ)”}”(hŒEarm64 CPUs implementing the Permission Overlay Extension (FEAT_S1POE)”h]”hŒEarm64 CPUs implementing the Permission Overlay Extension (FEAT_S1POE)”…””}”(hj]h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´KhjYubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjubeh}”(h]”h ]”h"]”h$]”h&]”Œbullet”Œ*”uh1j h³hÇh´K hj ubah}”(h]”h ]”h"]”h$]”h&]”uh1jhhôubeh}”(h]”h ]”h"]”h$]”h&]”uh1hòh³hÇh´Khhïubah}”(h]”h ]”h"]”h$]”h&]”uh1híhhÊh²hh³Nh´NubhÉ)”}”(hhh]”(hÎ)”}”(hŒx86_64”h]”hŒx86_64”…””}”(hjŽh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhj‹h²hh³hÇh´KubhÞ)”}”(hŒ|Pkeys work by dedicating 4 previously Reserved bits in each page table entry to a "protection key", giving 16 possible keys.”h]”hŒ€Pkeys work by dedicating 4 previously Reserved bits in each page table entry to a “protection keyâ€, giving 16 possible keys.”…””}”(hjœh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´Khj‹h²hubhÞ)”}”(hŒÁProtections for each key are defined with a per-CPU user-accessible register (PKRU). Each of these is a 32-bit register storing two bits (Access Disable and Write Disable) for each of 16 keys.”h]”hŒÁProtections for each key are defined with a per-CPU user-accessible register (PKRU). Each of these is a 32-bit register storing two bits (Access Disable and Write Disable) for each of 16 keys.”…””}”(hjªh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´Khj‹h²hubhÞ)”}”(hŒBeing a CPU register, PKRU is inherently thread-local, potentially giving each thread a different set of protections from every other thread.”h]”hŒBeing a CPU register, PKRU is inherently thread-local, potentially giving each thread a different set of protections from every other thread.”…””}”(hj¸h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´Khj‹h²hubhÞ)”}”(hXThere are two instructions (RDPKRU/WRPKRU) for reading and writing to the register. The feature is only available in 64-bit mode, even though there is theoretically space in the PAE PTEs. These permissions are enforced on data access only and have no effect on instruction fetches.”h]”hXThere are two instructions (RDPKRU/WRPKRU) for reading and writing to the register. The feature is only available in 64-bit mode, even though there is theoretically space in the PAE PTEs. These permissions are enforced on data access only and have no effect on instruction fetches.”…””}”(hjÆh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´Khj‹h²hubeh}”(h]”Œx86-64”ah ]”h"]”Œx86_64”ah$]”h&]”uh1hÈhhÊh²hh³hÇh´KubhÉ)”}”(hhh]”(hÎ)”}”(hŒarm64”h]”hŒarm64”…””}”(hjßh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhjÜh²hh³hÇh´K#ubhÞ)”}”(hŒfPkeys use 3 bits in each page table entry, to encode a "protection key index", giving 8 possible keys.”h]”hŒjPkeys use 3 bits in each page table entry, to encode a “protection key indexâ€, giving 8 possible keys.”…””}”(hjíh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K%hjÜh²hubhÞ)”}”(hŒËProtections for each key are defined with a per-CPU user-writable system register (POR_EL0). This is a 64-bit register encoding read, write and execute overlay permissions for each protection key index.”h]”hŒËProtections for each key are defined with a per-CPU user-writable system register (POR_EL0). This is a 64-bit register encoding read, write and execute overlay permissions for each protection key index.”…””}”(hjûh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K(hjÜh²hubhÞ)”}”(hŒBeing a CPU register, POR_EL0 is inherently thread-local, potentially giving each thread a different set of protections from every other thread.”h]”hŒBeing a CPU register, POR_EL0 is inherently thread-local, potentially giving each thread a different set of protections from every other thread.”…””}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K,hjÜh²hubhÞ)”}”(hŒPUnlike x86_64, the protection key permissions also apply to instruction fetches.”h]”hŒPUnlike x86_64, the protection key permissions also apply to instruction fetches.”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K/hjÜh²hubeh}”(h]”Œarm64”ah ]”h"]”Œarm64”ah$]”h&]”uh1hÈhhÊh²hh³hÇh´K#ubhÉ)”}”(hhh]”(hÎ)”}”(hŒSyscalls”h]”hŒSyscalls”…””}”(hj0h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhj-h²hh³hÇh´K3ubhÞ)”}”(hŒ=There are 3 system calls which directly interact with pkeys::”h]”hŒh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K5hj-h²hubhŒ literal_block”“”)”}”(hŒÂint pkey_alloc(unsigned long flags, unsigned long init_access_rights) int pkey_free(int pkey); int pkey_mprotect(unsigned long start, size_t len, unsigned long prot, int pkey);”h]”hŒÂint pkey_alloc(unsigned long flags, unsigned long init_access_rights) int pkey_free(int pkey); int pkey_mprotect(unsigned long start, size_t len, unsigned long prot, int pkey);”…””}”hjNsbah}”(h]”h ]”h"]”h$]”h&]”hÅhÆuh1jLh³hÇh´K7hj-h²hubhÞ)”}”(hXBefore a pkey can be used, it must first be allocated with pkey_alloc(). An application writes to the architecture specific CPU register directly in order to change access permissions to memory covered with a key. In this example this is wrapped by a C function called pkey_set(). ::”h]”hXBefore a pkey can be used, it must first be allocated with pkey_alloc(). An application writes to the architecture specific CPU register directly in order to change access permissions to memory covered with a key. In this example this is wrapped by a C function called pkey_set().”…””}”(hj\h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K