€•{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/arch/x86/shstk”Œ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/arch/x86/shstk”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒItalian”…””}”hhFsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ"/translations/it_IT/arch/x86/shstk”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒJapanese”…””}”hhZsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ"/translations/ja_JP/arch/x86/shstk”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒKorean”…””}”hhnsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ"/translations/ko_KR/arch/x86/shstk”Œ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/arch/x86/shstk”Œ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ŸŒ | grep -a SHSTK properties: x86 feature: SHSTK”h]”hŒKreadelf -n | grep -a SHSTK properties: x86 feature: SHSTK”…””}”hjrsbah}”(h]”h ]”h"]”h$]”h&]”h±h²uh1jphŸh³h K/hjQhžhubhÛ)”}”(hXThe kernel does not process these applications markers directly. Applications or loaders must enable CET features using the interface described in section 4. Typically this would be done in dynamic loader or static runtime objects, as is the case in GLIBC.”h]”hXThe kernel does not process these applications markers directly. Applications or loaders must enable CET features using the interface described in section 4. Typically this would be done in dynamic loader or static runtime objects, as is the case in GLIBC.”…””}”(hj€hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÚhŸh³h K2hjQhžhubeh}”(h]”Œapplication-enabling”ah ]”h"]”Œapplication enabling”ah$]”h&]”uh1h´hh¶hžhhŸh³h K*ubhµ)”}”(hhh]”(hº)”}”(hŒEnabling arch_prctl()'s”h]”hŒEnabling arch_prctl()’s”…””}”(hj™hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h¹hj–hžhhŸh³h K8ubhÛ)”}”(hXDElf features should be enabled by the loader using the below arch_prctl's. They are only supported in 64 bit user applications. These operate on the features on a per-thread basis. The enablement status is inherited on clone, so if the feature is enabled on the first thread, it will propagate to all the thread's in an app.”h]”hXHElf features should be enabled by the loader using the below arch_prctl’s. They are only supported in 64 bit user applications. These operate on the features on a per-thread basis. The enablement status is inherited on clone, so if the feature is enabled on the first thread, it will propagate to all the thread’s in an app.”…””}”(hj§hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÚhŸh³h K:hj–hžhubhŒdefinition_list”“”)”}”(hhh]”(hŒdefinition_list_item”“”)”}”(hŒarch_prctl(ARCH_SHSTK_ENABLE, unsigned long feature) Enable a single feature specified in 'feature'. Can only operate on one feature at a time. ”h]”(hŒterm”“”)”}”(hŒ4arch_prctl(ARCH_SHSTK_ENABLE, unsigned long feature)”h]”hŒ4arch_prctl(ARCH_SHSTK_ENABLE, unsigned long feature)”…””}”(hjÂhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jÀhŸh³h KBhj¼ubhŒ definition”“”)”}”(hhh]”hÛ)”}”(hŒZEnable a single feature specified in 'feature'. Can only operate on one feature at a time.”h]”hŒ^Enable a single feature specified in ‘feature’. Can only operate on one feature at a time.”…””}”(hjÕhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÚhŸh³h KAhjÒubah}”(h]”h ]”h"]”h$]”h&]”uh1jÐhj¼ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jºhŸh³h KBhj·ubj»)”}”(hŒ’arch_prctl(ARCH_SHSTK_DISABLE, unsigned long feature) Disable a single feature specified in 'feature'. Can only operate on one feature at a time. ”h]”(jÁ)”}”(hŒ5arch_prctl(ARCH_SHSTK_DISABLE, unsigned long feature)”h]”hŒ5arch_prctl(ARCH_SHSTK_DISABLE, unsigned long feature)”…””}”(hjóhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jÀhŸh³h KFhjïubjÑ)”}”(hhh]”hÛ)”}”(hŒ[Disable a single feature specified in 'feature'. Can only operate on one feature at a time.”h]”hŒ_Disable a single feature specified in ‘feature’. Can only operate on one feature at a time.”…””}”(hjhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÚhŸh³h KEhjubah}”(h]”h ]”h"]”h$]”h&]”uh1jÐhjïubeh}”(h]”h ]”h"]”h$]”h&]”uh1jºhŸh³h KFhj·hžhubj»)”}”(hXEarch_prctl(ARCH_SHSTK_LOCK, unsigned long features) Lock in features at their current enabled or disabled status. 'features' is a mask of all features to lock. All bits set are processed, unset bits are ignored. The mask is ORed with the existing value. So any feature bits set here cannot be enabled or disabled afterwards. ”h]”(jÁ)”}”(hŒ3arch_prctl(ARCH_SHSTK_LOCK, unsigned long features)”h]”hŒ3arch_prctl(ARCH_SHSTK_LOCK, unsigned long features)”…””}”(hj"hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jÀhŸh³h KLhjubjÑ)”}”(hhh]”hÛ)”}”(hXLock in features at their current enabled or disabled status. 'features' is a mask of all features to lock. All bits set are processed, unset bits are ignored. The mask is ORed with the existing value. So any feature bits set here cannot be enabled or disabled afterwards.”h]”hXLock in features at their current enabled or disabled status. ‘features’ is a mask of all features to lock. All bits set are processed, unset bits are ignored. The mask is ORed with the existing value. So any feature bits set here cannot be enabled or disabled afterwards.”…””}”(hj3hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÚhŸh³h KIhj0ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÐhjubeh}”(h]”h ]”h"]”h$]”h&]”uh1jºhŸh³h KLhj·hžhubj»)”}”(hŒÂarch_prctl(ARCH_SHSTK_UNLOCK, unsigned long features) Unlock features. 'features' is a mask of all features to unlock. All bits set are processed, unset bits are ignored. Only works via ptrace. ”h]”(jÁ)”}”(hŒ5arch_prctl(ARCH_SHSTK_UNLOCK, unsigned long features)”h]”hŒ5arch_prctl(ARCH_SHSTK_UNLOCK, unsigned long features)”…””}”(hjQhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jÀhŸh³h KPhjMubjÑ)”}”(hhh]”hÛ)”}”(hŒ‹Unlock features. 'features' is a mask of all features to unlock. All bits set are processed, unset bits are ignored. Only works via ptrace.”h]”hŒUnlock features. ‘features’ is a mask of all features to unlock. All bits set are processed, unset bits are ignored. Only works via ptrace.”…””}”(hjbhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÚhŸh³h KOhj_ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÐhjMubeh}”(h]”h ]”h"]”h$]”h&]”uh1jºhŸh³h KPhj·hžhubj»)”}”(hŒÅarch_prctl(ARCH_SHSTK_STATUS, unsigned long addr) Copy the currently enabled features to the address passed in addr. The features are described using the bits passed into the others in 'features'. ”h]”(jÁ)”}”(hŒ1arch_prctl(ARCH_SHSTK_STATUS, unsigned long addr)”h]”hŒ1arch_prctl(ARCH_SHSTK_STATUS, unsigned long addr)”…””}”(hj€hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jÀhŸh³h KUhj|ubjÑ)”}”(hhh]”hÛ)”}”(hŒ’Copy the currently enabled features to the address passed in addr. The features are described using the bits passed into the others in 'features'.”h]”hŒ–Copy the currently enabled features to the address passed in addr. The features are described using the bits passed into the others in ‘features’.”…””}”(hj‘hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÚhŸh³h KShjŽubah}”(h]”h ]”h"]”h$]”h&]”uh1jÐhj|ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jºhŸh³h KUhj·hžhubeh}”(h]”h ]”h"]”h$]”h&]”uh1jµhj–hžhhŸh³h NubhÛ)”}”(hŒPThe return values are as follows. On success, return 0. On error, errno can be::”h]”hŒOThe return values are as follows. On success, return 0. On error, errno can be:”…””}”(hj±hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÚhŸh³h KWhj–hžhubjq)”}”(hŒÛ-EPERM if any of the passed feature are locked. -ENOTSUPP if the feature is not supported by the hardware or kernel. -EINVAL arguments (non existing feature, etc) -EFAULT if could not copy information back to userspace”h]”hŒÛ-EPERM if any of the passed feature are locked. -ENOTSUPP if the feature is not supported by the hardware or kernel. -EINVAL arguments (non existing feature, etc) -EFAULT if could not copy information back to userspace”…””}”hj¿sbah}”(h]”h ]”h"]”h$]”h&]”h±h²uh1jphŸh³h KZhj–hžhubhÛ)”}”(hŒ"The feature's bits supported are::”h]”hŒ#The feature’s bits supported are:”…””}”(hjÍhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÚhŸh³h K`hj–hžhubjq)”}”(hŒ7ARCH_SHSTK_SHSTK - Shadow stack ARCH_SHSTK_WRSS - WRSS”h]”hŒ7ARCH_SHSTK_SHSTK - Shadow stack ARCH_SHSTK_WRSS - WRSS”…””}”hjÛsbah}”(h]”h ]”h"]”h$]”h&]”h±h²uh1jphŸh³h Kbhj–hžhubhÛ)”}”(hŒ¨Currently shadow stack and WRSS are supported via this interface. WRSS can only be enabled with shadow stack, and is automatically disabled if shadow stack is disabled.”h]”hŒ¨Currently shadow stack and WRSS are supported via this interface. WRSS can only be enabled with shadow stack, and is automatically disabled if shadow stack is disabled.”…””}”(hjéhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÚhŸh³h Kehj–hžhubeh}”(h]”Œenabling-arch-prctl-s”ah ]”h"]”Œenabling arch_prctl()'s”ah$]”h&]”uh1h´hh¶hžhhŸh³h K8ubhµ)”}”(hhh]”(hº)”}”(hŒ Proc Status”h]”hŒ Proc Status”…””}”(hjhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h¹hjÿhžhhŸh³h KjubhÛ)”}”(hŒÄTo check if an application is actually running with shadow stack, the user can read the /proc/$PID/status. It will report "wrss" or "shstk" depending on what is enabled. The lines look like this::”h]”hŒËTo check if an application is actually running with shadow stack, the user can read the /proc/$PID/status. It will report “wrss†or “shstk†depending on what is enabled. The lines look like this:”…””}”(hjhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÚhŸh³h Kkhjÿhžhubjq)”}”(hŒFx86_Thread_features: shstk wrss x86_Thread_features_locked: shstk wrss”h]”hŒFx86_Thread_features: shstk wrss x86_Thread_features_locked: shstk wrss”…””}”hjsbah}”(h]”h ]”h"]”h$]”h&]”h±h²uh1jphŸh³h Kohjÿhžhubeh}”(h]”Œ proc-status”ah ]”h"]”Œ proc status”ah$]”h&]”uh1h´hh¶hžhhŸh³h Kjubhµ)”}”(hhh]”(hº)”}”(hŒ"Implementation of the Shadow Stack”h]”hŒ"Implementation of the Shadow Stack”…””}”(hj7hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h¹hj4hžhhŸh³h Ksubhµ)”}”(hhh]”(hº)”}”(hŒShadow Stack Size”h]”hŒShadow Stack Size”…””}”(hjHhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h¹hjEhžhhŸh³h KvubhÛ)”}”(hX:A task's shadow stack is allocated from memory to a fixed size of MIN(RLIMIT_STACK, 4 GB). In other words, the shadow stack is allocated to the maximum size of the normal stack, but capped to 4 GB. In the case of the clone3 syscall, there is a stack size passed in and shadow stack uses this instead of the rlimit.”h]”hX<A task’s shadow stack is allocated from memory to a fixed size of MIN(RLIMIT_STACK, 4 GB). In other words, the shadow stack is allocated to the maximum size of the normal stack, but capped to 4 GB. In the case of the clone3 syscall, there is a stack size passed in and shadow stack uses this instead of the rlimit.”…””}”(hjVhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÚhŸh³h KxhjEhžhubeh}”(h]”Œshadow-stack-size”ah ]”h"]”Œshadow stack size”ah$]”h&]”uh1h´hj4hžhhŸh³h Kvubhµ)”}”(hhh]”(hº)”}”(hŒSignal”h]”hŒSignal”…””}”(hjohžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h¹hjlhžhhŸh³h KubhÛ)”}”(hŒèThe main program and its signal handlers use the same shadow stack. Because the shadow stack stores only return addresses, a large shadow stack covers the condition that both the program stack and the signal alternate stack run out.”h]”hŒèThe main program and its signal handlers use the same shadow stack. Because the shadow stack stores only return addresses, a large shadow stack covers the condition that both the program stack and the signal alternate stack run out.”…””}”(hj}hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÚhŸh³h KhjlhžhubhÛ)”}”(hXWhen a signal happens, the old pre-signal state is pushed on the stack. When shadow stack is enabled, the shadow stack specific state is pushed onto the shadow stack. Today this is only the old SSP (shadow stack pointer), pushed in a special format with bit 63 set. On sigreturn this old SSP token is verified and restored by the kernel. The kernel will also push the normal restorer address to the shadow stack to help userspace avoid a shadow stack violation on the sigreturn path that goes through the restorer.”h]”hXWhen a signal happens, the old pre-signal state is pushed on the stack. When shadow stack is enabled, the shadow stack specific state is pushed onto the shadow stack. Today this is only the old SSP (shadow stack pointer), pushed in a special format with bit 63 set. On sigreturn this old SSP token is verified and restored by the kernel. The kernel will also push the normal restorer address to the shadow stack to help userspace avoid a shadow stack violation on the sigreturn path that goes through the restorer.”…””}”(hj‹hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÚhŸh³h K†hjlhžhubhÛ)”}”(hŒ7So the shadow stack signal frame format is as follows::”h]”hŒ6So the shadow stack signal frame format is as follows:”…””}”(hj™hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÚhŸh³h KŽhjlhžhubjq)”}”(hŒŸ|1...old SSP| - Pointer to old pre-signal ssp in sigframe token format (bit 63 set to 1) | ...| - Other state may be added in the future”h]”hŒŸ|1...old SSP| - Pointer to old pre-signal ssp in sigframe token format (bit 63 set to 1) | ...| - Other state may be added in the future”…””}”hj§sbah}”(h]”h ]”h"]”h$]”h&]”h±h²uh1jphŸh³h KhjlhžhubhÛ)”}”(hXé32 bit ABI signals are not supported in shadow stack processes. Linux prevents 32 bit execution while shadow stack is enabled by the allocating shadow stacks outside of the 32 bit address space. When execution enters 32 bit mode, either via far call or returning to userspace, a #GP is generated by the hardware which, will be delivered to the process as a segfault. When transitioning to userspace the register's state will be as if the userspace ip being returned to caused the segfault.”h]”hXë32 bit ABI signals are not supported in shadow stack processes. Linux prevents 32 bit execution while shadow stack is enabled by the allocating shadow stacks outside of the 32 bit address space. When execution enters 32 bit mode, either via far call or returning to userspace, a #GP is generated by the hardware which, will be delivered to the process as a segfault. When transitioning to userspace the register’s state will be as if the userspace ip being returned to caused the segfault.”…””}”(hjµhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÚhŸh³h K•hjlhžhubeh}”(h]”Œsignal”ah ]”h"]”Œsignal”ah$]”h&]”uh1h´hj4hžhhŸh³h Kubhµ)”}”(hhh]”(hº)”}”(hŒFork”h]”hŒFork”…””}”(hjÎhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h¹hjËhžhhŸh³h KžubhÛ)”}”(hŒûThe shadow stack's vma has VM_SHADOW_STACK flag set; its PTEs are required to be read-only and dirty. When a shadow stack PTE is not RO and dirty, a shadow access triggers a page fault with the shadow stack access bit set in the page fault error code.”h]”hŒýThe shadow stack’s vma has VM_SHADOW_STACK flag set; its PTEs are required to be read-only and dirty. When a shadow stack PTE is not RO and dirty, a shadow access triggers a page fault with the shadow stack access bit set in the page fault error code.”…””}”(hjÜhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÚhŸh³h K hjËhžhubhÛ)”}”(hŒúWhen a task forks a child, its shadow stack PTEs are copied and both the parent's and the child's shadow stack PTEs are cleared of the dirty bit. Upon the next shadow stack access, the resulting shadow stack page fault is handled by page copy/re-use.”h]”hŒþWhen a task forks a child, its shadow stack PTEs are copied and both the parent’s and the child’s shadow stack PTEs are cleared of the dirty bit. Upon the next shadow stack access, the resulting shadow stack page fault is handled by page copy/re-use.”…””}”(hjêhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÚhŸh³h K¥hjËhžhubhÛ)”}”(hŒêWhen a pthread child is created, the kernel allocates a new shadow stack for the new thread. New shadow stack creation behaves like mmap() with respect to ASLR behavior. Similarly, on thread exit the thread's shadow stack is disabled.”h]”hŒìWhen a pthread child is created, the kernel allocates a new shadow stack for the new thread. New shadow stack creation behaves like mmap() with respect to ASLR behavior. Similarly, on thread exit the thread’s shadow stack is disabled.”…””}”(hjøhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÚhŸh³h KªhjËhžhubeh}”(h]”Œfork”ah ]”h"]”Œfork”ah$]”h&]”uh1h´hj4hžhhŸh³h Kžubhµ)”}”(hhh]”(hº)”}”(hŒExec”h]”hŒExec”…””}”(hjhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h¹hjhžhhŸh³h K°ubhÛ)”}”(hŒ{On exec, shadow stack features are disabled by the kernel. At which point, userspace can choose to re-enable, or lock them.”h]”hŒ{On exec, shadow stack features are disabled by the kernel. At which point, userspace can choose to re-enable, or lock them.”…””}”(hjhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÚhŸh³h K²hjhžhubeh}”(h]”Œexec”ah ]”h"]”Œexec”ah$]”h&]”uh1h´hj4hžhhŸh³h K°ubeh}”(h]”Œ"implementation-of-the-shadow-stack”ah ]”h"]”Œ"implementation of the shadow stack”ah$]”h&]”uh1h´hh¶hžhhŸh³h Ksubeh}”(h]”Œ4control-flow-enforcement-technology-cet-shadow-stack”ah ]”h"]”Œ6control-flow enforcement technology (cet) shadow stack”ah$]”h&]”uh1h´hhhžhhŸh³h Kubeh}”(h]”h ]”h"]”h$]”h&]”Œsource”h³uh1hŒcurrent_source”NŒ current_line”NŒsettings”Œdocutils.frontend”ŒValues”“”)”}”(h¹NŒ generator”NŒ datestamp”NŒ source_link”NŒ source_url”NŒ toc_backlinks”Œentry”Œfootnote_backlinks”KŒ sectnum_xform”KŒstrip_comments”NŒstrip_elements_with_classes”NŒ strip_classes”NŒ report_level”KŒ halt_level”KŒexit_status_level”KŒdebug”NŒwarning_stream”NŒ traceback”ˆŒinput_encoding”Œ utf-8-sig”Œinput_encoding_error_handler”Œstrict”Œoutput_encoding”Œutf-8”Œoutput_encoding_error_handler”jhŒerror_encoding”Œutf-8”Œerror_encoding_error_handler”Œbackslashreplace”Œ language_code”Œen”Œrecord_dependencies”NŒconfig”NŒ id_prefix”hŒauto_id_prefix”Œid”Œ dump_settings”NŒdump_internals”NŒdump_transforms”NŒdump_pseudo_xml”NŒexpose_internals”NŒstrict_visitor”NŒ_disable_config”NŒ_source”h³Œ _destination”NŒ _config_files”]”Œ7/var/lib/git/docbuild/linux/Documentation/docutils.conf”aŒfile_insertion_enabled”ˆŒ raw_enabled”KŒline_length_limit”M'Œpep_references”NŒ pep_base_url”Œhttps://peps.python.org/”Œpep_file_url_template”Œpep-%04d”Œrfc_references”NŒ rfc_base_url”Œ&https://datatracker.ietf.org/doc/html/”Œ tab_width”KŒtrim_footnote_reference_space”‰Œsyntax_highlight”Œlong”Œ smart_quotes”ˆŒsmartquotes_locales”]”Œcharacter_level_inline_markup”‰Œdoctitle_xform”‰Œ docinfo_xform”KŒsectsubtitle_xform”‰Œ image_loading”Œlink”Œembed_stylesheet”‰Œcloak_email_addresses”ˆŒsection_self_link”‰Œenv”NubŒreporter”NŒindirect_targets”]”Œsubstitution_defs”}”Œsubstitution_names”}”Œrefnames”}”Œrefids”}”Œnameids”}”(jBj?hýhújNjKj“jjüjùj1j.j:j7jijfjÈjÅj jj2j/uŒ nametypes”}”(jB‰hý‰jN‰j“‰jü‰j1‰j:‰ji‰jȉj ‰j2‰uh}”(j?h¶húhÉjKjjjQjùj–j.jÿj7j4jfjEjÅjljjËj/juŒ footnote_refs”}”Œ citation_refs”}”Œ autofootnotes”]”Œautofootnote_refs”]”Œsymbol_footnotes”]”Œsymbol_footnote_refs”]”Œ footnotes”]”Œ citations”]”Œautofootnote_start”KŒsymbol_footnote_start”KŒ id_counter”Œ collections”ŒCounter”“”}”…”R”Œparse_messages”]”Œtransform_messages”]”Œ transformer”NŒ include_log”]”Œ decoration”Nhžhub.