Re: [PATCH v12 00/11] Application Data Integrity feature introduced by SPARC M7
On 03/18/2018 09:08 AM, David Miller wrote: In uapi/asm/auxvec.h you conditionalize the ADI aux vectors on CONFIG_SPARC64. That's not correct, you should never control user facing definitions based upon kernel configuration. Also, both 32-bit and 64-bit applications running on ADI capable machines want to compile against and use this informaiton. So please remove these CPP checks. Hi Dave, That makes sense. I will send a patch to remove these. Thanks, Khalid -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v12 10/11] sparc64: Add support for ADI (Application Data Integrity)
On 03/05/2018 02:31 PM, Dave Hansen wrote: On 03/05/2018 01:14 PM, Khalid Aziz wrote: Are you suggesting that vma returned by find_vma() could be split or merged underneath me if I do not hold mmap_sem and thus make the flag check invalid? If so, that is a good point. This part does make me think that this code hasn't been tested very thoroughly. Could you describe the testing that you have done? For MPX and protection keys, I added something to tools/testing/selftests/x86, for instance. This code was tested by a QA team and I ran a number of tests myself. I wrote tests to exercise all of the API, induce exceptions for invalid/illegal accesses and swapping was tested by allocating memory 2-4 times of the system RAM available across 4-8 threads and reading/writing to this memory with ADI enabled. QA team wrote unit tests to test each API with valid and invalid combinations of arguments to the API. Stress tests that allocate and free ADI tagged memory were also run. A version of database server was created that uses ADI tagged memory for in-memory copy of database to test database workload. 100's of hours of tests were run across these tests over the last 1+ year these patches have been under review for. Cover letter includes description of most of these tests. This code has held up through all of these tests. It is entirely feasible some race conditions have not been uncovered yet, just like any other piece of software. Pulling this code into mainline kernel and having lot more people exercise this code will help shake out any remaining issues. Thanks, Khalid -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v12 10/11] sparc64: Add support for ADI (Application Data Integrity)
On 03/05/2018 02:26 PM, Dave Hansen wrote: On 02/21/2018 09:15 AM, Khalid Aziz wrote: +tag_storage_desc_t *alloc_tag_store(struct mm_struct *mm, + struct vm_area_struct *vma, + unsigned long addr) ... + tags = kzalloc(size, GFP_NOWAIT|__GFP_NOWARN); + if (tags == NULL) { + tag_desc->tag_users = 0; + tag_desc = NULL; + goto out; + } + tag_desc->start = addr; + tag_desc->tags = tags; + tag_desc->end = end_addr; + +out: + spin_unlock_irqrestore(&mm->context.tag_lock, flags); + return tag_desc; +} OK, sorry, I missed this. I do see that you now have per-ADI-block tag storage and it is not per-page. How big can this storage get, btw? Superficially it seems like it might be able to be gigantic for a large, sparse VMA. Tags are stored only for the pages being swapped out, not for the pages in entire vma. Each tag storage page can hold tags for 128 pages (each page has 128 4-bit tags, hence 64 bytes are needed to store tags for an entire page allowing each page to store tags for 128 pages). Sparse VMA does not cause any problems since holes do not have corresponding pages that will be swapped out. Tag storage pages are freed once all the pages they store tags for have been swapped back in, except for a small number of pages (maximum of 8) marked for emergency tag storage. -- Khalid -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v12 10/11] sparc64: Add support for ADI (Application Data Integrity)
On 03/05/2018 12:22 PM, Dave Hansen wrote: On 02/21/2018 09:15 AM, Khalid Aziz wrote: +#define arch_validate_prot(prot, addr) sparc_validate_prot(prot, addr) +static inline int sparc_validate_prot(unsigned long prot, unsigned long addr) +{ + if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC | PROT_SEM | PROT_ADI)) + return 0; + if (prot & PROT_ADI) { + if (!adi_capable()) + return 0; + + if (addr) { + struct vm_area_struct *vma; + + vma = find_vma(current->mm, addr); + if (vma) { + /* ADI can not be enabled on PFN +* mapped pages +*/ + if (vma->vm_flags & (VM_PFNMAP | VM_MIXEDMAP)) + return 0; You don't hold mmap_sem here. How can this work? Are you suggesting that vma returned by find_vma() could be split or merged underneath me if I do not hold mmap_sem and thus make the flag check invalid? If so, that is a good point. Thanks, Khalid -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v13 10/11] sparc64: Add support for ADI (Application Data Integrity)
ADI is a new feature supported on SPARC M7 and newer processors to allow hardware to catch rogue accesses to memory. ADI is supported for data fetches only and not instruction fetches. An app can enable ADI on its data pages, set version tags on them and use versioned addresses to access the data pages. Upper bits of the address contain the version tag. On M7 processors, upper four bits (bits 63-60) contain the version tag. If a rogue app attempts to access ADI enabled data pages, its access is blocked and processor generates an exception. Please see Documentation/sparc/adi.txt for further details. This patch extends mprotect to enable ADI (TSTATE.mcde), enable/disable MCD (Memory Corruption Detection) on selected memory ranges, enable TTE.mcd in PTEs, return ADI parameters to userspace and save/restore ADI version tags on page swap out/in or migration. ADI is not enabled by default for any task. A task must explicitly enable ADI on a memory range and set version tag for ADI to be effective for the task. Signed-off-by: Khalid Aziz Cc: Khalid Aziz Reviewed-by: Anthony Yznaga --- v13: - Fixed a build error for AMD GPU DRM driver on sparc reported by kbuild bot v10: - Added code to return from kernel path to set PSTATE.mcde if kernel continues execution in another thread (Suggested by Anthony Yznaga) v9: - Added code to migrate ADI tags to copy_highpage() to ensure tags get copied on page migration - Improved code to detect underflow and overflow when allocating tag storage v8: - Added note to doc about non-faulting loads not triggering ADI tag mismatch and more details on special tag values of 0x0 and 0xf, as suggested by Anthony Yznaga) - Added an IPI on mprotect(...PROT_ADI...) call to set TSTATE.MCDE on threads running on other processors and restore of TSTATE.MCDE on context switch (suggested by David Miller) - Removed restriction on enabling ADI on read-only memory (suggested by Anthony Yznaga) - Changed kzalloc() for tag storage to use GFP_NOWAIT - Added code to handle overflow and underflow when allocating tag storage, as suggested by Anthony Yznaga - Replaced sun_m7_patch_1insn_range() with sun4v_patch_1insn_range() which is functionally identical (suggested by Anthony Yznaga) - Added membar after restoring ADI tags in copy_user_highpage(), as suggested by David Miller v7: - Enhanced arch_validate_prot() to enable ADI only on writable addresses backed by physical RAM - Added support for saving/restoring ADI tags for each ADI block size address range on a page on swap in/out - Added code to copy ADI tags on COW - Updated values for auxiliary vectors to not conflict with values on other architectures to avoid conflict in glibc. glibc consolidates all auxiliary vectors into its headers and duplicate values in consolidated header are problematic - Disable same page merging on ADI enabled pages since ADI tags may not match on pages with identical data - Broke the patch up further into smaller patches v6: - Eliminated instructions to read and write PSTATE as well as MCDPER and PMCDPER on every access to userspace addresses by setting PSTATE and PMCDPER correctly upon entry into kernel. PSTATE.mcde and PMCDPER are set upon entry into kernel when running on an M7 processor. PSTATE.mcde being set only affects memory accesses that have TTE.mcd set. PMCDPER being set only affects writes to memory addresses that have TTE.mcd set. This ensures any faults caused by ADI tag mismatch on a write are exposed before kernel returns to userspace. v5: - Fixed indentation issues and instrcuctions in assembly code - Removed CONFIG_SPARC64 from mdesc.c - Changed to maintain state of MCDPER register in thread info flags as opposed to in mm context. MCDPER is a per-thread state and belongs in thread info flag as opposed to mm context which is shared across threads. Added comments to clarify this is a lazily maintained state and must be updated on context switch and copy_process() - Updated code to use the new arch_do_swap_page() and arch_unmap_one() functions v4: - Broke patch up into smaller patches v3: - Removed CONFIG_SPARC_ADI - Replaced prctl commands with mprotect - Added auxiliary vectors for ADI parameters - Enabled ADI for swappable pages v2: - Fixed a build error Documentation/sparc/adi.txt | 278 + arch/sparc/include/asm/mman.h | 84 - arch/sparc/include/asm/mmu_64.h | 17
Re: [PATCH v12 10/11] sparc64: Add support for ADI (Application Data Integrity)
On 02/23/2018 11:57 AM, David Miller wrote: From: Khalid Aziz Date: Fri, 23 Feb 2018 11:51:25 -0700 On 02/22/2018 07:50 PM, kbuild test robot wrote: Hi Khalid, I love your patch! Yet something to improve: [auto build test ERROR on sparc-next/master] [also build test ERROR on v4.16-rc2] [cannot apply to next-20180222] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system] url: https://github.com/0day-ci/linux/commits/Khalid-Aziz/Application-Data-Integrity-feature-introduced-by-SPARC-M7/20180223-071725 base: https://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-next.git master config: sparc64-allyesconfig (attached as .config) compiler: sparc64-linux-gnu-gcc (Debian 7.2.0-11) 7.2.0 reproduce: wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # save the attached .config to linux build tree make.cross ARCH=sparc64 All error/warnings (new ones prefixed by >>): Hi Dave, Including linux/sched.h in arch/sparc/include/asm/mmu_context.h should eliminate these build warnings. My gcc version 6.2.1 does not report these errors. Build bot is using 7.2.0. I can add a patch 12 to add the include, revise patch 10 or you can add the include in your tree. Let me know how you would prefer to resolve this. You need to update patch #10 so that your patch series is fully bisectable. Hi Dave, That sounds like the right thing to do. I am updating patch 10 and will send out v13 for patch 10/11. Rest of the series is unchanged but I can send the whole series if you prefer that. Thanks, Khalid -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v12 10/11] sparc64: Add support for ADI (Application Data Integrity)
On 02/22/2018 07:50 PM, kbuild test robot wrote: Hi Khalid, I love your patch! Yet something to improve: [auto build test ERROR on sparc-next/master] [also build test ERROR on v4.16-rc2] [cannot apply to next-20180222] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system] url: https://github.com/0day-ci/linux/commits/Khalid-Aziz/Application-Data-Integrity-feature-introduced-by-SPARC-M7/20180223-071725 base: https://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-next.git master config: sparc64-allyesconfig (attached as .config) compiler: sparc64-linux-gnu-gcc (Debian 7.2.0-11) 7.2.0 reproduce: wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # save the attached .config to linux build tree make.cross ARCH=sparc64 All error/warnings (new ones prefixed by >>): Hi Dave, Including linux/sched.h in arch/sparc/include/asm/mmu_context.h should eliminate these build warnings. My gcc version 6.2.1 does not report these errors. Build bot is using 7.2.0. I can add a patch 12 to add the include, revise patch 10 or you can add the include in your tree. Let me know how you would prefer to resolve this. Thanks, Khalid In file included from arch/sparc/include/asm/mmu_context.h:5:0, from include/linux/mmu_context.h:5, from drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h:29, from drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c:23: arch/sparc/include/asm/mmu_context_64.h: In function 'arch_start_context_switch': arch/sparc/include/asm/mmu_context_64.h:157:4: error: implicit declaration of function 'set_tsk_thread_flag'; did you mean 'set_ti_thread_flag'? [-Werror=implicit-function-declaration] set_tsk_thread_flag(prev, TIF_MCDPER); ^~~ set_ti_thread_flag arch/sparc/include/asm/mmu_context_64.h:159:4: error: implicit declaration of function 'clear_tsk_thread_flag'; did you mean 'clear_ti_thread_flag'? [-Werror=implicit-function-declaration] clear_tsk_thread_flag(prev, TIF_MCDPER); ^ clear_ti_thread_flag arch/sparc/include/asm/mmu_context_64.h: In function 'finish_arch_post_lock_switch': arch/sparc/include/asm/mmu_context_64.h:180:25: error: dereferencing pointer to incomplete type 'struct task_struct' if (current && current->mm && current->mm->context.adi) { ^~ In file included from arch/sparc/include/asm/processor.h:5:0, from arch/sparc/include/asm/spinlock_64.h:12, from arch/sparc/include/asm/spinlock.h:5, from include/linux/spinlock.h:88, from arch/sparc/include/asm/mmu_context_64.h:9, from arch/sparc/include/asm/mmu_context.h:5, from include/linux/mmu_context.h:5, from drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h:29, from drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c:23: arch/sparc/include/asm/processor_64.h:194:28: error: implicit declaration of function 'task_thread_info'; did you mean 'test_thread_flag'? [-Werror=implicit-function-declaration] #define task_pt_regs(tsk) (task_thread_info(tsk)->kregs) ^ arch/sparc/include/asm/mmu_context_64.h:183:11: note: in expansion of macro 'task_pt_regs' regs = task_pt_regs(current); ^~~~ arch/sparc/include/asm/processor_64.h:194:49: error: invalid type argument of '->' (have 'int') #define task_pt_regs(tsk) (task_thread_info(tsk)->kregs) ^ arch/sparc/include/asm/mmu_context_64.h:183:11: note: in expansion of macro 'task_pt_regs' regs = task_pt_regs(current); ^~~~ In file included from include/linux/cred.h:21:0, from include/linux/seq_file.h:12, from include/linux/pinctrl/consumer.h:17, from include/linux/pinctrl/devinfo.h:21, from include/linux/device.h:23, from include/linux/cdev.h:8, from include/drm/drmP.h:36, from drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c:25: include/linux/sched.h: At top level: include/linux/sched.h:1530:20: warning: conflicting types for 'set_tsk_thread_flag' static inline void set_tsk_thread_flag(struct task_struct *tsk, int flag) ^~~ include/linux/sched.h:1530:20: error: static declaration of 'set_tsk_thread_flag' follows non-static declaration In
[PATCH v12 10/11] sparc64: Add support for ADI (Application Data Integrity)
ADI is a new feature supported on SPARC M7 and newer processors to allow hardware to catch rogue accesses to memory. ADI is supported for data fetches only and not instruction fetches. An app can enable ADI on its data pages, set version tags on them and use versioned addresses to access the data pages. Upper bits of the address contain the version tag. On M7 processors, upper four bits (bits 63-60) contain the version tag. If a rogue app attempts to access ADI enabled data pages, its access is blocked and processor generates an exception. Please see Documentation/sparc/adi.txt for further details. This patch extends mprotect to enable ADI (TSTATE.mcde), enable/disable MCD (Memory Corruption Detection) on selected memory ranges, enable TTE.mcd in PTEs, return ADI parameters to userspace and save/restore ADI version tags on page swap out/in or migration. ADI is not enabled by default for any task. A task must explicitly enable ADI on a memory range and set version tag for ADI to be effective for the task. Signed-off-by: Khalid Aziz Cc: Khalid Aziz Reviewed-by: Anthony Yznaga --- v10: - Added code to return from kernel path to set PSTATE.mcde if kernel continues execution in another thread (Suggested by Anthony Yznaga) v9: - Added code to migrate ADI tags to copy_highpage() to ensure tags get copied on page migration - Improved code to detect underflow and overflow when allocating tag storage v8: - Added note to doc about non-faulting loads not triggering ADI tag mismatch and more details on special tag values of 0x0 and 0xf, as suggested by Anthony Yznaga) - Added an IPI on mprotect(...PROT_ADI...) call to set TSTATE.MCDE on threads running on other processors and restore of TSTATE.MCDE on context switch (suggested by David Miller) - Removed restriction on enabling ADI on read-only memory (suggested by Anthony Yznaga) - Changed kzalloc() for tag storage to use GFP_NOWAIT - Added code to handle overflow and underflow when allocating tag storage, as suggested by Anthony Yznaga - Replaced sun_m7_patch_1insn_range() with sun4v_patch_1insn_range() which is functionally identical (suggested by Anthony Yznaga) - Added membar after restoring ADI tags in copy_user_highpage(), as suggested by David Miller v7: - Enhanced arch_validate_prot() to enable ADI only on writable addresses backed by physical RAM - Added support for saving/restoring ADI tags for each ADI block size address range on a page on swap in/out - Added code to copy ADI tags on COW - Updated values for auxiliary vectors to not conflict with values on other architectures to avoid conflict in glibc. glibc consolidates all auxiliary vectors into its headers and duplicate values in consolidated header are problematic - Disable same page merging on ADI enabled pages since ADI tags may not match on pages with identical data - Broke the patch up further into smaller patches v6: - Eliminated instructions to read and write PSTATE as well as MCDPER and PMCDPER on every access to userspace addresses by setting PSTATE and PMCDPER correctly upon entry into kernel. PSTATE.mcde and PMCDPER are set upon entry into kernel when running on an M7 processor. PSTATE.mcde being set only affects memory accesses that have TTE.mcd set. PMCDPER being set only affects writes to memory addresses that have TTE.mcd set. This ensures any faults caused by ADI tag mismatch on a write are exposed before kernel returns to userspace. v5: - Fixed indentation issues and instrcuctions in assembly code - Removed CONFIG_SPARC64 from mdesc.c - Changed to maintain state of MCDPER register in thread info flags as opposed to in mm context. MCDPER is a per-thread state and belongs in thread info flag as opposed to mm context which is shared across threads. Added comments to clarify this is a lazily maintained state and must be updated on context switch and copy_process() - Updated code to use the new arch_do_swap_page() and arch_unmap_one() functions v4: - Broke patch up into smaller patches v3: - Removed CONFIG_SPARC_ADI - Replaced prctl commands with mprotect - Added auxiliary vectors for ADI parameters - Enabled ADI for swappable pages v2: - Fixed a build error Documentation/sparc/adi.txt | 278 + arch/sparc/include/asm/mman.h | 84 - arch/sparc/include/asm/mmu_64.h | 17 ++ arch/sparc/include/asm/mmu_context_64.h | 50 ++ arch/sparc/include/asm/page_64.h
[PATCH v12 00/11] Application Data Integrity feature introduced by SPARC M7
ff from patch 4/4 in v6 - Patch 5/9: new patch split off from patch 4/4 in v6 - Patch 6/9: new patch split off from patch 4/4 in v6 - Patch 7/9: new patch - Patch 8/9: new patch - Patch 9/9: - Enhanced arch_validate_prot() to enable ADI only on writable addresses backed by physical RAM - Added support for saving/restoring ADI tags for each ADI block size address range on a page on swap in/out - copy ADI tags on COW - Updated values for auxiliary vectors to not conflict with values on other architectures to avoid conflict in glibc - Disable same page merging on ADI enabled pages - Enable ADI only on writable addresses backed by physical RAM - Split parts of patch off into separate patches Changelog v6: - Patch 1/4: No changes - Patch 2/4: No changes - Patch 3/4: Added missing nop in the delay slot in sun4v_mcd_detect_precise - Patch 4/4: Eliminated instructions to read and write PSTATE as well as MCDPER and PMCDPER on every access to userspace addresses by setting PSTATE and PMCDPER correctly upon entry into kernel Changelog v5: - Patch 1/4: No changes - Patch 2/4: Replaced set_swp_pte_at() with new architecture functions arch_do_swap_page() and arch_unmap_one() that suppoprt architecture specific actions to be taken on page swap and migration - Patch 3/4: Fixed indentation issues in assembly code - Patch 4/4: - Fixed indentation issues and instrcuctions in assembly code - Removed CONFIG_SPARC64 from mdesc.c - Changed to maintain state of MCDPER register in thread info flags as opposed to in mm context. MCDPER is a per-thread state and belongs in thread info flag as opposed to mm context which is shared across threads. Added comments to clarify this is a lazily maintained state and must be updated on context switch and copy_process() - Updated code to use the new arch_do_swap_page() and arch_unmap_one() functions Testing: - All functionality was tested with 8K normal pages as well as hugepages using malloc, mmap and shm. - Multiple long duration stress tests were run using hugepages over 2+ months. Normal pages were tested with shorter duration stress tests. - Tested swapping with malloc and shm by reducing max memory and allocating three times the available system memory by active processes using ADI on allocated memory. Ran through multiple hours long runs of this test. - Tested page migration with malloc and shm by migrating data pages of active ADI test process using migratepages, back and forth between two nodes every few seconds over an hour long run. Verified page migration through /proc//numa_maps. - Tested COW support using test that forks children that read from ADI enabled pages shared with parent and other children and write to them as well forcing COW. - Khalid Aziz (11): signals, sparc: Add signal codes for ADI violations mm, swap: Add infrastructure for saving page metadata on swap sparc64: Add support for ADI register fields, ASIs and traps sparc64: Add HV fault type handlers for ADI related faults sparc64: Add handler for "Memory Corruption Detected" trap sparc64: Add auxiliary vectors to report platform ADI properties mm: Add address parameter to arch_validate_prot() mm: Clear arch specific VM flags on protection change mm: Allow arch code to override copy_highpage() sparc64: Add support for ADI (Application Data Integrity) sparc64: Update signal delivery to use new helper functions Documentation/sparc/adi.txt | 278 ++ arch/powerpc/include/asm/mman.h | 4 +- arch/powerpc/kernel/syscalls.c | 2 +- arch/sparc/include/asm/adi.h| 6 + arch/sparc/include/asm/adi_64.h | 47 arch/sparc/include/asm/elf_64.h | 5 + arch/sparc/include/asm/hypervisor.h | 2 + arch/sparc/include/asm/mman.h | 84 ++- arch/sparc/include/asm/mmu_64.h | 17 ++ arch/sparc/include/asm/mmu_context_64.h | 50 arch/sparc/include/asm/page_64.h| 6 + arch/sparc/include/asm/pgtable_64.h | 48 arch/sparc/include/asm/thread_info_64.h | 2 +- arch/sparc/include/asm/trap_block.h | 2 + arch/sparc/include/asm/ttable.h | 10 + arch/sparc/include/uapi/asm/asi.h | 5 + arch/sparc/include/uapi/asm/auxvec.h| 11 + arch/sparc/include/uapi/asm/mman.h | 2 + arch/sparc/include/uapi/asm/pstate.h| 10 + arch/sparc/ke
Re: [PATCH v11 00/10] Application Data Integrity feature introduced by SPARC M7
On 02/07/2018 12:38 AM, ebied...@xmission.com wrote: Khalid Aziz writes: On 02/01/2018 07:29 PM, ebied...@xmission.com wrote: Khalid Aziz writes: V11 changes: This series is same as v10 and was simply rebased on 4.15 kernel. Can mm maintainers please review patches 2, 7, 8 and 9 which are arch independent, and include/linux/mm.h and mm/ksm.c changes in patch 10 and ack these if everything looks good? I am a bit puzzled how this differs from the pkey's that other architectures are implementing to achieve a similar result. I am a bit mystified why you don't store the tag in a vma instead of inventing a new way to store data on page out. Hello Eric, As Steven pointed out, sparc sets tags per cacheline unlike pkey. This results in much finer granularity for tags that pkey and hence requires larger tag storage than what we can do in a vma. *Nod* I am a bit mystified where you keep the information in memory. I would think the tags would need to be stored per cacheline or per tlb entry, in some kind of cache that could overflow. So I would be surprised if swapping is the only time this information needs stored in memory. Which makes me wonder if you have the proper data structures. I would think an array per vma or something in the page tables would tend to make sense. But perhaps I am missing something. The ADI tags are stored in spare bits in the RAM. ADI tag storage is managed entirely by memory controller which maintains these tags per ADI block. An ADI block is the same size as cacheline on M7. Tags for each ADI block are associated with the physical ADI block, not the virtual address. When a physical page is reused, the physical ADI tag storage for that page is overwritten with new ADI tags, hence we need to store away the tags when we swap out a page. Kernel updates the ADI tags for physical page when it swaps a new page in. Each vma can cover variable number of pages so it is best to store a pointer to the tag storage in vma as opposed to actual tags in an array. Each 8K page can have 128 tags on it. Since each tag is 4 bits, we need 64 bytes per page to store the tags. That can add up for a large vma. Can you please use force_sig_fault to send these signals instead of force_sig_info. Emperically I have found that it is very error prone to generate siginfo's by hand, especially on code paths where several different si_codes may apply. So it helps to go through a helper function to ensure the fiddly bits are all correct. AKA the unused bits all need to be set to zero before struct siginfo is copied to userspace. What you say makes sense. I followed the same code as other fault handlers for sparc. I could change just the fault handlers for ADI related faults. Would it make more sense to change all the fault handlers in a separate patch and keep the code in arch/sparc/kernel/traps_64.c consistent? Dave M, do you have a preference? It is my intention post -rc1 to start sending out patches to get the rest of not just sparc but all of the architectures using the new helpers. I have the code I just ran out of time befor the merge window opened to ensure everything had a good thorough review. So if you can handle the your new changes I expect I will handle the rest. I can add a patch at the end of my series to update all force_sig_info() in my patchset to force_sig_fault(). That will sync my patches up with your changes cleanly. Does that work for you? I can send an updated series with this change. Can you review and ack the patches after this change. Thanks, Khalid -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v11 00/10] Application Data Integrity feature introduced by SPARC M7
On 02/01/2018 07:29 PM, ebied...@xmission.com wrote: Khalid Aziz writes: V11 changes: This series is same as v10 and was simply rebased on 4.15 kernel. Can mm maintainers please review patches 2, 7, 8 and 9 which are arch independent, and include/linux/mm.h and mm/ksm.c changes in patch 10 and ack these if everything looks good? I am a bit puzzled how this differs from the pkey's that other architectures are implementing to achieve a similar result. I am a bit mystified why you don't store the tag in a vma instead of inventing a new way to store data on page out. Hello Eric, As Steven pointed out, sparc sets tags per cacheline unlike pkey. This results in much finer granularity for tags that pkey and hence requires larger tag storage than what we can do in a vma. Can you please use force_sig_fault to send these signals instead of force_sig_info. Emperically I have found that it is very error prone to generate siginfo's by hand, especially on code paths where several different si_codes may apply. So it helps to go through a helper function to ensure the fiddly bits are all correct. AKA the unused bits all need to be set to zero before struct siginfo is copied to userspace. What you say makes sense. I followed the same code as other fault handlers for sparc. I could change just the fault handlers for ADI related faults. Would it make more sense to change all the fault handlers in a separate patch and keep the code in arch/sparc/kernel/traps_64.c consistent? Dave M, do you have a preference? Thanks, Khalid -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v11 10/10] sparc64: Add support for ADI (Application Data Integrity)
ADI is a new feature supported on SPARC M7 and newer processors to allow hardware to catch rogue accesses to memory. ADI is supported for data fetches only and not instruction fetches. An app can enable ADI on its data pages, set version tags on them and use versioned addresses to access the data pages. Upper bits of the address contain the version tag. On M7 processors, upper four bits (bits 63-60) contain the version tag. If a rogue app attempts to access ADI enabled data pages, its access is blocked and processor generates an exception. Please see Documentation/sparc/adi.txt for further details. This patch extends mprotect to enable ADI (TSTATE.mcde), enable/disable MCD (Memory Corruption Detection) on selected memory ranges, enable TTE.mcd in PTEs, return ADI parameters to userspace and save/restore ADI version tags on page swap out/in or migration. ADI is not enabled by default for any task. A task must explicitly enable ADI on a memory range and set version tag for ADI to be effective for the task. Signed-off-by: Khalid Aziz Cc: Khalid Aziz Reviewed-by: Anthony Yznaga --- v10: - Added code to return from kernel path to set PSTATE.mcde if kernel continues execution in another thread (Suggested by Anthony Yznaga) v9: - Added code to migrate ADI tags to copy_highpage() to ensure tags get copied on page migration - Improved code to detect underflow and overflow when allocating tag storage v8: - Added note to doc about non-faulting loads not triggering ADI tag mismatch and more details on special tag values of 0x0 and 0xf, as suggested by Anthony Yznaga) - Added an IPI on mprotect(...PROT_ADI...) call to set TSTATE.MCDE on threads running on other processors and restore of TSTATE.MCDE on context switch (suggested by David Miller) - Removed restriction on enabling ADI on read-only memory (suggested by Anthony Yznaga) - Changed kzalloc() for tag storage to use GFP_NOWAIT - Added code to handle overflow and underflow when allocating tag storage, as suggested by Anthony Yznaga - Replaced sun_m7_patch_1insn_range() with sun4v_patch_1insn_range() which is functionally identical (suggested by Anthony Yznaga) - Added membar after restoring ADI tags in copy_user_highpage(), as suggested by David Miller v7: - Enhanced arch_validate_prot() to enable ADI only on writable addresses backed by physical RAM - Added support for saving/restoring ADI tags for each ADI block size address range on a page on swap in/out - Added code to copy ADI tags on COW - Updated values for auxiliary vectors to not conflict with values on other architectures to avoid conflict in glibc. glibc consolidates all auxiliary vectors into its headers and duplicate values in consolidated header are problematic - Disable same page merging on ADI enabled pages since ADI tags may not match on pages with identical data - Broke the patch up further into smaller patches v6: - Eliminated instructions to read and write PSTATE as well as MCDPER and PMCDPER on every access to userspace addresses by setting PSTATE and PMCDPER correctly upon entry into kernel. PSTATE.mcde and PMCDPER are set upon entry into kernel when running on an M7 processor. PSTATE.mcde being set only affects memory accesses that have TTE.mcd set. PMCDPER being set only affects writes to memory addresses that have TTE.mcd set. This ensures any faults caused by ADI tag mismatch on a write are exposed before kernel returns to userspace. v5: - Fixed indentation issues and instrcuctions in assembly code - Removed CONFIG_SPARC64 from mdesc.c - Changed to maintain state of MCDPER register in thread info flags as opposed to in mm context. MCDPER is a per-thread state and belongs in thread info flag as opposed to mm context which is shared across threads. Added comments to clarify this is a lazily maintained state and must be updated on context switch and copy_process() - Updated code to use the new arch_do_swap_page() and arch_unmap_one() functions v4: - Broke patch up into smaller patches v3: - Removed CONFIG_SPARC_ADI - Replaced prctl commands with mprotect - Added auxiliary vectors for ADI parameters - Enabled ADI for swappable pages v2: - Fixed a build error Documentation/sparc/adi.txt | 278 + arch/sparc/include/asm/mman.h | 84 - arch/sparc/include/asm/mmu_64.h | 17 ++ arch/sparc/include/asm/mmu_context_64.h | 50 ++ arch/sparc/include/asm/page_64.h
[PATCH v11 00/10] Application Data Integrity feature introduced by SPARC M7
ADI block size address range on a page on swap in/out - copy ADI tags on COW - Updated values for auxiliary vectors to not conflict with values on other architectures to avoid conflict in glibc - Disable same page merging on ADI enabled pages - Enable ADI only on writable addresses backed by physical RAM - Split parts of patch off into separate patches Changelog v6: - Patch 1/4: No changes - Patch 2/4: No changes - Patch 3/4: Added missing nop in the delay slot in sun4v_mcd_detect_precise - Patch 4/4: Eliminated instructions to read and write PSTATE as well as MCDPER and PMCDPER on every access to userspace addresses by setting PSTATE and PMCDPER correctly upon entry into kernel Changelog v5: - Patch 1/4: No changes - Patch 2/4: Replaced set_swp_pte_at() with new architecture functions arch_do_swap_page() and arch_unmap_one() that suppoprt architecture specific actions to be taken on page swap and migration - Patch 3/4: Fixed indentation issues in assembly code - Patch 4/4: - Fixed indentation issues and instrcuctions in assembly code - Removed CONFIG_SPARC64 from mdesc.c - Changed to maintain state of MCDPER register in thread info flags as opposed to in mm context. MCDPER is a per-thread state and belongs in thread info flag as opposed to mm context which is shared across threads. Added comments to clarify this is a lazily maintained state and must be updated on context switch and copy_process() - Updated code to use the new arch_do_swap_page() and arch_unmap_one() functions Testing: - All functionality was tested with 8K normal pages as well as hugepages using malloc, mmap and shm. - Multiple long duration stress tests were run using hugepages over 2+ months. Normal pages were tested with shorter duration stress tests. - Tested swapping with malloc and shm by reducing max memory and allocating three times the available system memory by active processes using ADI on allocated memory. Ran through multiple hours long runs of this test. - Tested page migration with malloc and shm by migrating data pages of active ADI test process using migratepages, back and forth between two nodes every few seconds over an hour long run. Verified page migration through /proc//numa_maps. - Tested COW support using test that forks children that read from ADI enabled pages shared with parent and other children and write to them as well forcing COW. - Khalid Aziz (10): signals, sparc: Add signal codes for ADI violations mm, swap: Add infrastructure for saving page metadata on swap sparc64: Add support for ADI register fields, ASIs and traps sparc64: Add HV fault type handlers for ADI related faults sparc64: Add handler for "Memory Corruption Detected" trap sparc64: Add auxiliary vectors to report platform ADI properties mm: Add address parameter to arch_validate_prot() mm: Clear arch specific VM flags on protection change mm: Allow arch code to override copy_highpage() sparc64: Add support for ADI (Application Data Integrity) Documentation/sparc/adi.txt | 278 ++ arch/powerpc/include/asm/mman.h | 4 +- arch/powerpc/kernel/syscalls.c | 2 +- arch/sparc/include/asm/adi.h| 6 + arch/sparc/include/asm/adi_64.h | 47 arch/sparc/include/asm/elf_64.h | 5 + arch/sparc/include/asm/hypervisor.h | 2 + arch/sparc/include/asm/mman.h | 84 ++- arch/sparc/include/asm/mmu_64.h | 17 ++ arch/sparc/include/asm/mmu_context_64.h | 50 arch/sparc/include/asm/page_64.h| 6 + arch/sparc/include/asm/pgtable_64.h | 48 arch/sparc/include/asm/thread_info_64.h | 2 +- arch/sparc/include/asm/trap_block.h | 2 + arch/sparc/include/asm/ttable.h | 10 + arch/sparc/include/uapi/asm/asi.h | 5 + arch/sparc/include/uapi/asm/auxvec.h| 11 + arch/sparc/include/uapi/asm/mman.h | 2 + arch/sparc/include/uapi/asm/pstate.h| 10 + arch/sparc/kernel/Makefile | 1 + arch/sparc/kernel/adi_64.c | 397 arch/sparc/kernel/entry.h | 3 + arch/sparc/kernel/etrap_64.S| 27 ++- arch/sparc/kernel/head_64.S | 1 + arch/sparc/kernel/mdesc.c | 2 + arch/sparc/kernel/process_64.c | 25 ++ arch/sparc/kernel/rtrap_64.S| 33 ++- arch/sparc/kernel/setup_64.c| 2 + arch/sparc/kernel/sun4v_mcd.S
[PATCH v10 00/10] Application Data Integrity feature introduced by SPARC M7
page merging on ADI enabled pages - Enable ADI only on writable addresses backed by physical RAM - Split parts of patch off into separate patches Changelog v6: - Patch 1/4: No changes - Patch 2/4: No changes - Patch 3/4: Added missing nop in the delay slot in sun4v_mcd_detect_precise - Patch 4/4: Eliminated instructions to read and write PSTATE as well as MCDPER and PMCDPER on every access to userspace addresses by setting PSTATE and PMCDPER correctly upon entry into kernel Changelog v5: - Patch 1/4: No changes - Patch 2/4: Replaced set_swp_pte_at() with new architecture functions arch_do_swap_page() and arch_unmap_one() that suppoprt architecture specific actions to be taken on page swap and migration - Patch 3/4: Fixed indentation issues in assembly code - Patch 4/4: - Fixed indentation issues and instrcuctions in assembly code - Removed CONFIG_SPARC64 from mdesc.c - Changed to maintain state of MCDPER register in thread info flags as opposed to in mm context. MCDPER is a per-thread state and belongs in thread info flag as opposed to mm context which is shared across threads. Added comments to clarify this is a lazily maintained state and must be updated on context switch and copy_process() - Updated code to use the new arch_do_swap_page() and arch_unmap_one() functions Testing: - All functionality was tested with 8K normal pages as well as hugepages using malloc, mmap and shm. - Multiple long duration stress tests were run using hugepages over 2+ months. Normal pages were tested with shorter duration stress tests. - Tested swapping with malloc and shm by reducing max memory and allocating three times the available system memory by active processes using ADI on allocated memory. Ran through multiple hours long runs of this test. - Tested page migration with malloc and shm by migrating data pages of active ADI test process using migratepages, back and forth between two nodes every few seconds over an hour long run. Verified page migration through /proc//numa_maps. - Tested COW support using test that forks children that read from ADI enabled pages shared with parent and other children and write to them as well forcing COW. - Khalid Aziz (10): signals, sparc: Add signal codes for ADI violations mm, swap: Add infrastructure for saving page metadata as well on swap sparc64: Add support for ADI register fields, ASIs and traps sparc64: Add HV fault type handlers for ADI related faults sparc64: Add handler for "Memory Corruption Detected" trap sparc64: Add auxiliary vectors to report platform ADI properties mm: Add address parameter to arch_validate_prot() mm: Clear arch specific VM flags on protection change mm: Allow arch code to override copy_highpage() sparc64: Add support for ADI (Application Data Integrity) Documentation/sparc/adi.txt | 278 ++ arch/powerpc/include/asm/mman.h | 4 +- arch/powerpc/kernel/syscalls.c | 2 +- arch/sparc/include/asm/adi.h| 6 + arch/sparc/include/asm/adi_64.h | 47 arch/sparc/include/asm/elf_64.h | 9 + arch/sparc/include/asm/hypervisor.h | 2 + arch/sparc/include/asm/mman.h | 84 ++- arch/sparc/include/asm/mmu_64.h | 17 ++ arch/sparc/include/asm/mmu_context_64.h | 50 arch/sparc/include/asm/page_64.h| 6 + arch/sparc/include/asm/pgtable_64.h | 48 arch/sparc/include/asm/thread_info_64.h | 2 +- arch/sparc/include/asm/trap_block.h | 2 + arch/sparc/include/asm/ttable.h | 10 + arch/sparc/include/uapi/asm/asi.h | 5 + arch/sparc/include/uapi/asm/auxvec.h| 11 + arch/sparc/include/uapi/asm/mman.h | 2 + arch/sparc/include/uapi/asm/pstate.h| 10 + arch/sparc/kernel/Makefile | 1 + arch/sparc/kernel/adi_64.c | 397 arch/sparc/kernel/entry.h | 3 + arch/sparc/kernel/etrap_64.S| 27 ++- arch/sparc/kernel/head_64.S | 1 + arch/sparc/kernel/mdesc.c | 2 + arch/sparc/kernel/process_64.c | 25 ++ arch/sparc/kernel/rtrap_64.S| 33 ++- arch/sparc/kernel/setup_64.c| 2 + arch/sparc/kernel/sun4v_mcd.S | 18 ++ arch/sparc/kernel/traps_64.c| 142 +++- arch/sparc/kernel/ttable_64.S | 6 +- arch/sparc/kernel/urtt_fill.S | 7 +- arch/sparc/kernel/vmlinux.lds.S | 5 + arch/sparc/mm/gup.c | 37 +++ arch/sparc/mm/hugetlbpage.c
[PATCH v10 10/10] sparc64: Add support for ADI (Application Data Integrity)
ADI is a new feature supported on SPARC M7 and newer processors to allow hardware to catch rogue accesses to memory. ADI is supported for data fetches only and not instruction fetches. An app can enable ADI on its data pages, set version tags on them and use versioned addresses to access the data pages. Upper bits of the address contain the version tag. On M7 processors, upper four bits (bits 63-60) contain the version tag. If a rogue app attempts to access ADI enabled data pages, its access is blocked and processor generates an exception. Please see Documentation/sparc/adi.txt for further details. This patch extends mprotect to enable ADI (TSTATE.mcde), enable/disable MCD (Memory Corruption Detection) on selected memory ranges, enable TTE.mcd in PTEs, return ADI parameters to userspace and save/restore ADI version tags on page swap out/in or migration. ADI is not enabled by default for any task. A task must explicitly enable ADI on a memory range and set version tag for ADI to be effective for the task. Signed-off-by: Khalid Aziz Cc: Khalid Aziz --- v10: - Added code to return from kernel path to set PSTATE.mcde if kernel continues execution in another thread (Suggested by Anthony Yznaga) v9: - Added code to migrate ADI tags to copy_highpage() to ensure tags get copied on page migration - Improved code to detect underflow and overflow when allocating tag storage v8: - Added note to doc about non-faulting loads not triggering ADI tag mismatch and more details on special tag values of 0x0 and 0xf, as suggested by Anthony Yznaga) - Added an IPI on mprotect(...PROT_ADI...) call to set TSTATE.MCDE on threads running on other processors and restore of TSTATE.MCDE on context switch (suggested by David Miller) - Removed restriction on enabling ADI on read-only memory (suggested by Anthony Yznaga) - Changed kzalloc() for tag storage to use GFP_NOWAIT - Added code to handle overflow and underflow when allocating tag storage, as suggested by Anthony Yznaga - Replaced sun_m7_patch_1insn_range() with sun4v_patch_1insn_range() which is functionally identical (suggested by Anthony Yznaga) - Added membar after restoring ADI tags in copy_user_highpage(), as suggested by David Miller v7: - Enhanced arch_validate_prot() to enable ADI only on writable addresses backed by physical RAM - Added support for saving/restoring ADI tags for each ADI block size address range on a page on swap in/out - Added code to copy ADI tags on COW - Updated values for auxiliary vectors to not conflict with values on other architectures to avoid conflict in glibc. glibc consolidates all auxiliary vectors into its headers and duplicate values in consolidated header are problematic - Disable same page merging on ADI enabled pages since ADI tags may not match on pages with identical data - Broke the patch up further into smaller patches v6: - Eliminated instructions to read and write PSTATE as well as MCDPER and PMCDPER on every access to userspace addresses by setting PSTATE and PMCDPER correctly upon entry into kernel. PSTATE.mcde and PMCDPER are set upon entry into kernel when running on an M7 processor. PSTATE.mcde being set only affects memory accesses that have TTE.mcd set. PMCDPER being set only affects writes to memory addresses that have TTE.mcd set. This ensures any faults caused by ADI tag mismatch on a write are exposed before kernel returns to userspace. v5: - Fixed indentation issues and instrcuctions in assembly code - Removed CONFIG_SPARC64 from mdesc.c - Changed to maintain state of MCDPER register in thread info flags as opposed to in mm context. MCDPER is a per-thread state and belongs in thread info flag as opposed to mm context which is shared across threads. Added comments to clarify this is a lazily maintained state and must be updated on context switch and copy_process() - Updated code to use the new arch_do_swap_page() and arch_unmap_one() functions v4: - Broke patch up into smaller patches v3: - Removed CONFIG_SPARC_ADI - Replaced prctl commands with mprotect - Added auxiliary vectors for ADI parameters - Enabled ADI for swappable pages v2: - Fixed a build error Documentation/sparc/adi.txt | 278 + arch/sparc/include/asm/mman.h | 84 - arch/sparc/include/asm/mmu_64.h | 17 ++ arch/sparc/include/asm/mmu_context_64.h | 50 ++ arch/sparc/include/asm/page_64.h| 6 + arch/sparc/include
[PATCH v9 10/10] sparc64: Add support for ADI (Application Data Integrity)
ADI is a new feature supported on SPARC M7 and newer processors to allow hardware to catch rogue accesses to memory. ADI is supported for data fetches only and not instruction fetches. An app can enable ADI on its data pages, set version tags on them and use versioned addresses to access the data pages. Upper bits of the address contain the version tag. On M7 processors, upper four bits (bits 63-60) contain the version tag. If a rogue app attempts to access ADI enabled data pages, its access is blocked and processor generates an exception. Please see Documentation/sparc/adi.txt for further details. This patch extends mprotect to enable ADI (TSTATE.mcde), enable/disable MCD (Memory Corruption Detection) on selected memory ranges, enable TTE.mcd in PTEs, return ADI parameters to userspace and save/restore ADI version tags on page swap out/in or migration. ADI is not enabled by default for any task. A task must explicitly enable ADI on a memory range and set version tag for ADI to be effective for the task. Signed-off-by: Khalid Aziz Cc: Khalid Aziz --- v9: - Added code to migrate ADI tags to copy_highpage() to ensure tags get copied on page migration - Improved code to detect underflow and overflow when allocating tag storage v8: - Added note to doc about non-faulting loads not triggering ADI tag mismatch and more details on special tag values of 0x0 and 0xf, as suggested by Anthony Yznaga) - Added an IPI on mprotect(...PROT_ADI...) call to set TSTATE.MCDE on threads running on other processors and restore of TSTATE.MCDE on context switch (suggested by David Miller) - Removed restriction on enabling ADI on read-only memory (suggested by Anthony Yznaga) - Changed kzalloc() for tag storage to use GFP_NOWAIT - Added code to handle overflow and underflow when allocating tag storage, as suggested by Anthony Yznaga - Replaced sun_m7_patch_1insn_range() with sun4v_patch_1insn_range() which is functionally identical (suggested by Anthony Yznaga) - Added membar after restoring ADI tags in copy_user_highpage(), as suggested by David Miller v7: - Enhanced arch_validate_prot() to enable ADI only on writable addresses backed by physical RAM - Added support for saving/restoring ADI tags for each ADI block size address range on a page on swap in/out - Added code to copy ADI tags on COW - Updated values for auxiliary vectors to not conflict with values on other architectures to avoid conflict in glibc. glibc consolidates all auxiliary vectors into its headers and duplicate values in consolidated header are problematic - Disable same page merging on ADI enabled pages since ADI tags may not match on pages with identical data - Broke the patch up further into smaller patches v6: - Eliminated instructions to read and write PSTATE as well as MCDPER and PMCDPER on every access to userspace addresses by setting PSTATE and PMCDPER correctly upon entry into kernel. PSTATE.mcde and PMCDPER are set upon entry into kernel when running on an M7 processor. PSTATE.mcde being set only affects memory accesses that have TTE.mcd set. PMCDPER being set only affects writes to memory addresses that have TTE.mcd set. This ensures any faults caused by ADI tag mismatch on a write are exposed before kernel returns to userspace. v5: - Fixed indentation issues and instrcuctions in assembly code - Removed CONFIG_SPARC64 from mdesc.c - Changed to maintain state of MCDPER register in thread info flags as opposed to in mm context. MCDPER is a per-thread state and belongs in thread info flag as opposed to mm context which is shared across threads. Added comments to clarify this is a lazily maintained state and must be updated on context switch and copy_process() - Updated code to use the new arch_do_swap_page() and arch_unmap_one() functions v4: - Broke patch up into smaller patches v3: - Removed CONFIG_SPARC_ADI - Replaced prctl commands with mprotect - Added auxiliary vectors for ADI parameters - Enabled ADI for swappable pages v2: - Fixed a build error Documentation/sparc/adi.txt | 278 + arch/sparc/include/asm/mman.h | 84 - arch/sparc/include/asm/mmu_64.h | 17 ++ arch/sparc/include/asm/mmu_context_64.h | 50 ++ arch/sparc/include/asm/page_64.h| 6 + arch/sparc/include/asm/pgtable_64.h | 46 + arch/sparc/include/asm/thread_info_64.h | 2 +- arch/sparc/include/asm/trap_block.h | 2 + arch/sparc/include/uapi/asm/mman.h
[PATCH v9 00/10] Application Data Integrity feature introduced by SPARC M7
and PMCDPER correctly upon entry into kernel Changelog v5: - Patch 1/4: No changes - Patch 2/4: Replaced set_swp_pte_at() with new architecture functions arch_do_swap_page() and arch_unmap_one() that suppoprt architecture specific actions to be taken on page swap and migration - Patch 3/4: Fixed indentation issues in assembly code - Patch 4/4: - Fixed indentation issues and instrcuctions in assembly code - Removed CONFIG_SPARC64 from mdesc.c - Changed to maintain state of MCDPER register in thread info flags as opposed to in mm context. MCDPER is a per-thread state and belongs in thread info flag as opposed to mm context which is shared across threads. Added comments to clarify this is a lazily maintained state and must be updated on context switch and copy_process() - Updated code to use the new arch_do_swap_page() and arch_unmap_one() functions Testing: - All functionality was tested with 8K normal pages as well as hugepages using malloc, mmap and shm. - Multiple long duration stress tests were run using hugepages over 2+ months. Normal pages were tested with shorter duration stress tests. - Tested swapping with malloc and shm by reducing max memory and allocating three times the available system memory by active processes using ADI on allocated memory. Ran through multiple hours long runs of this test. - Tested page migration with malloc and shm by migrating data pages of active ADI test process using migratepages, back and forth between two nodes every few seconds over an hour long run. Verified page migration through /proc//numa_maps. - Tested COW support using test that forks children that read from ADI enabled pages shared with parent and other children and write to them as well forcing COW. - Khalid Aziz (10): signals, sparc: Add signal codes for ADI violations mm, swap: Add infrastructure for saving page metadata as well on swap sparc64: Add support for ADI register fields, ASIs and traps sparc64: Add HV fault type handlers for ADI related faults sparc64: Add handler for "Memory Corruption Detected" trap sparc64: Add auxiliary vectors to report platform ADI properties mm: Add address parameter to arch_validate_prot() mm: Clear arch specific VM flags on protection change mm: Allow arch code to override copy_highpage() sparc64: Add support for ADI (Application Data Integrity) Documentation/sparc/adi.txt | 278 ++ arch/powerpc/include/asm/mman.h | 4 +- arch/powerpc/kernel/syscalls.c | 2 +- arch/sparc/include/asm/adi.h| 6 + arch/sparc/include/asm/adi_64.h | 46 arch/sparc/include/asm/elf_64.h | 9 + arch/sparc/include/asm/hypervisor.h | 2 + arch/sparc/include/asm/mman.h | 84 ++- arch/sparc/include/asm/mmu_64.h | 17 ++ arch/sparc/include/asm/mmu_context_64.h | 50 arch/sparc/include/asm/page_64.h| 6 + arch/sparc/include/asm/pgtable_64.h | 48 arch/sparc/include/asm/thread_info_64.h | 2 +- arch/sparc/include/asm/trap_block.h | 2 + arch/sparc/include/asm/ttable.h | 10 + arch/sparc/include/uapi/asm/asi.h | 5 + arch/sparc/include/uapi/asm/auxvec.h| 11 + arch/sparc/include/uapi/asm/mman.h | 2 + arch/sparc/include/uapi/asm/pstate.h| 10 + arch/sparc/kernel/Makefile | 1 + arch/sparc/kernel/adi_64.c | 396 arch/sparc/kernel/entry.h | 3 + arch/sparc/kernel/etrap_64.S| 28 ++- arch/sparc/kernel/head_64.S | 1 + arch/sparc/kernel/mdesc.c | 2 + arch/sparc/kernel/process_64.c | 25 ++ arch/sparc/kernel/setup_64.c| 2 + arch/sparc/kernel/sun4v_mcd.S | 17 ++ arch/sparc/kernel/traps_64.c| 142 +++- arch/sparc/kernel/ttable_64.S | 6 +- arch/sparc/kernel/vmlinux.lds.S | 5 + arch/sparc/mm/gup.c | 37 +++ arch/sparc/mm/hugetlbpage.c | 14 +- arch/sparc/mm/init_64.c | 69 ++ arch/sparc/mm/tsb.c | 21 ++ arch/x86/kernel/signal_compat.c | 2 +- include/asm-generic/pgtable.h | 36 +++ include/linux/highmem.h | 4 + include/linux/mm.h | 9 + include/linux/mman.h| 2 +- include/uapi/asm-generic/siginfo.h | 5 +- mm/ksm.c| 4 + mm/memory.c | 1 + mm/mprotect.c | 4 +- mm/rmap.c | 14 ++ 45 files changed, 1427
Re: [PATCH v8 9/9] sparc64: Add support for ADI (Application Data Integrity)
On 10/13/2017 08:14 AM, Khalid Aziz wrote: On 10/12/2017 02:27 PM, Anthony Yznaga wrote: On Oct 12, 2017, at 7:44 AM, Khalid Aziz wrote: On 10/06/2017 04:12 PM, Anthony Yznaga wrote: On Sep 25, 2017, at 9:49 AM, Khalid Aziz wrote: This patch extends mprotect to enable ADI (TSTATE.mcde), enable/disable MCD (Memory Corruption Detection) on selected memory ranges, enable TTE.mcd in PTEs, return ADI parameters to userspace and save/restore ADI version tags on page swap out/in or migration. ADI is not enabled by I still don't believe migration is properly supported. Your implementation is relying on a fault happening on a page while its migration is in progress so that do_swap_page() will be called, but I don't see how do_swap_page() will be called if a fault does not happen until after the migration has completed. User pages are on LRU list and for the mapped pages on LRU list, migrate_pages() ultimately calls try_to_unmap_one and makes a migration swap entry for the page being migrated. This forces a page fault upon access on the destination node and the page is swapped back in from swap cache. The fault is forced by the migration swap entry, rather than fault being an accidental event. If page fault happens on the destination node while migration is in progress, do_swap_page() waits until migration is done. Please take a look at the code in __unmap_and_move(). I looked at the code again, and I now believe ADI tags are never restored for migrated pages. Here's why: I will take a look at it again. I have run extensive tests migrating pages of a process across multiple NUMA nodes over and over again and ADI tags were never lost, so this does work. I won't rule out the possibility of having missed a code path where tags are not restored and I will look for it. Anthony, I just ran my migration test again which: - malloc's 16 GB of memory - Assigns a rotating ADI tag every 64 bytes to the malloc'd buffer - Writes a pattern to the entire buffer - Verifies the pattern it wrote using ADI tagged addresses. While this test was running, I had a script migrate test program pages across two NUMA nodes every 30 seconds using migratepages command. I did not see an ADI tag mismatch over multiple runs of this test. This test shows migration is working. Can you give me a test that shows the failure you think we should see and I will debug it. Thanks, Khalid -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v8 9/9] sparc64: Add support for ADI (Application Data Integrity)
On 10/12/2017 02:27 PM, Anthony Yznaga wrote: On Oct 12, 2017, at 7:44 AM, Khalid Aziz wrote: On 10/06/2017 04:12 PM, Anthony Yznaga wrote: On Sep 25, 2017, at 9:49 AM, Khalid Aziz wrote: This patch extends mprotect to enable ADI (TSTATE.mcde), enable/disable MCD (Memory Corruption Detection) on selected memory ranges, enable TTE.mcd in PTEs, return ADI parameters to userspace and save/restore ADI version tags on page swap out/in or migration. ADI is not enabled by I still don't believe migration is properly supported. Your implementation is relying on a fault happening on a page while its migration is in progress so that do_swap_page() will be called, but I don't see how do_swap_page() will be called if a fault does not happen until after the migration has completed. User pages are on LRU list and for the mapped pages on LRU list, migrate_pages() ultimately calls try_to_unmap_one and makes a migration swap entry for the page being migrated. This forces a page fault upon access on the destination node and the page is swapped back in from swap cache. The fault is forced by the migration swap entry, rather than fault being an accidental event. If page fault happens on the destination node while migration is in progress, do_swap_page() waits until migration is done. Please take a look at the code in __unmap_and_move(). I looked at the code again, and I now believe ADI tags are never restored for migrated pages. Here's why: I will take a look at it again. I have run extensive tests migrating pages of a process across multiple NUMA nodes over and over again and ADI tags were never lost, so this does work. I won't rule out the possibility of having missed a code path where tags are not restored and I will look for it. Thanks, Khalid -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v8 9/9] sparc64: Add support for ADI (Application Data Integrity)
Hi Anthony, Please quote only the relevant parts of the patch with comments. That makes it much easier to find the comments. On 10/06/2017 04:12 PM, Anthony Yznaga wrote: On Sep 25, 2017, at 9:49 AM, Khalid Aziz wrote: This patch extends mprotect to enable ADI (TSTATE.mcde), enable/disable MCD (Memory Corruption Detection) on selected memory ranges, enable TTE.mcd in PTEs, return ADI parameters to userspace and save/restore ADI version tags on page swap out/in or migration. ADI is not enabled by I still don't believe migration is properly supported. Your implementation is relying on a fault happening on a page while its migration is in progress so that do_swap_page() will be called, but I don't see how do_swap_page() will be called if a fault does not happen until after the migration has completed. User pages are on LRU list and for the mapped pages on LRU list, migrate_pages() ultimately calls try_to_unmap_one and makes a migration swap entry for the page being migrated. This forces a page fault upon access on the destination node and the page is swapped back in from swap cache. The fault is forced by the migration swap entry, rather than fault being an accidental event. If page fault happens on the destination node while migration is in progress, do_swap_page() waits until migration is done. Please take a look at the code in __unmap_and_move(). +#define finish_arch_post_lock_switch finish_arch_post_lock_switch +static inline void finish_arch_post_lock_switch(void) +{ + /* Restore the state of MCDPER register for the new process +* just switched to. +*/ + if (adi_capable()) { + register unsigned long tmp_mcdper; + + tmp_mcdper = test_thread_flag(TIF_MCDPER); + __asm__ __volatile__( + "mov %0, %%g1\n\t" + ".word 0x9d81\n\t"/* wr %g0, %g1, %mcdper" */ + ".word 0xaf902001\n\t"/* wrpr %g0, 1, %pmcdper */ + : + : "ir" (tmp_mcdper) + : "g1"); + if (current && current->mm && current->mm->context.adi) { + struct pt_regs *regs; + + regs = task_pt_regs(current); + regs->tstate |= TSTATE_MCDE; This works, but it costs additional cycles on every context switch to keep setting TSTATE_MCDE. PSTATE.mcde=1 only affects loads and stores to memory mapped with TTE.mcd=1 so there is no impact if it is set and no memory is mapped with TTE.mcd=1. That is why I suggested just setting TSTATE_MCDE once when a process thread is initialized. This change was suggested by David Miller. I believe there is merit to that suggestion. + /* Tag storage has not been allocated for this vma and space +* is available in tag storage descriptor. Since this page is +* being swapped out, there is high probability subsequent pages +* in the VMA will be swapped out as well. Allocate pages to +* store tags for as many pages in this vma as possible but not +* more than TAG_STORAGE_PAGES. Each byte in tag space holds +* two ADI tags since each ADI tag is 4 bits. Each ADI tag +* covers adi_blksize() worth of addresses. Check if the hole is +* big enough to accommodate full address range for using +* TAG_STORAGE_PAGES number of tag pages. +*/ + size = TAG_STORAGE_PAGES * PAGE_SIZE; + end_addr = addr + (size*2*adi_blksize()) - 1; + /* Check for overflow. If overflow occurs, allocate only one page */ + if (end_addr < addr) { + size = PAGE_SIZE; + end_addr = addr + (size*2*adi_blksize()) - 1; end_addr could still overflow even with size = PAGE_SIZE. Maybe you could just set end_addr to (unsigned long)-1 and recalculate the size based on that. I agree at theoretical level. The number of VA bits is already limited by the max implemented VA bit in hardware plus with ADI in use, top 4 bits are not available as well either, so there is lot of unused room at the upper end of VA and end_addr is not going to roll over. Nevertheless, I can fix this as well for completeness sake. + } + if (hole_end < end_addr) { + /* Available hole is too small on the upper end of +* address. Can we expand the range towards the lower +* address and maximize use of this slot? +*/ + unsigned long tmp_addr; + + end_addr = hole_end - 1; + tmp_addr = end_addr - (size*2*adi_blksize()) + 1; + /* Check for underflow. If underflow occurs, allocate +* only one page for storing ADI tags +*/ + if (tmp_addr > addr) { Should compare t
[PATCH v8 0/9] Application Data Integrity feature introduced by SPARC M7
ments to clarify this is a lazily maintained state and must be updated on context switch and copy_process() - Updated code to use the new arch_do_swap_page() and arch_unmap_one() functions Testing: - All functionality was tested with 8K normal pages as well as hugepages using malloc, mmap and shm. - Multiple long duration stress tests were run using hugepages over 2+ months. Normal pages were tested with shorter duration stress tests. - Tested swapping with malloc and shm by reducing max memory and allocating three times the available system memory by active processes using ADI on allocated memory. Ran through multiple hours long runs of this test. - Tested page migration with malloc and shm by migrating data pages of active ADI test process using migratepages, back and forth between two nodes every few seconds over an hour long run. Verified page migration through /proc//numa_maps. - Tested COW support using test that forks children that read from ADI enabled pages shared with parent and other children and write to them as well forcing COW. - Khalid Aziz (9): signals, sparc: Add signal codes for ADI violations mm, swap: Add infrastructure for saving page metadata as well on swap sparc64: Add support for ADI register fields, ASIs and traps sparc64: Add HV fault type handlers for ADI related faults sparc64: Add handler for "Memory Corruption Detected" trap sparc64: Add auxiliary vectors to report platform ADI properties mm: Add address parameter to arch_validate_prot() mm: Clear arch specific VM flags on protection change sparc64: Add support for ADI (Application Data Integrity) Documentation/sparc/adi.txt | 278 +++ arch/powerpc/include/asm/mman.h | 4 +- arch/powerpc/kernel/syscalls.c | 2 +- arch/sparc/include/asm/adi.h| 6 + arch/sparc/include/asm/adi_64.h | 46 arch/sparc/include/asm/elf_64.h | 9 + arch/sparc/include/asm/hypervisor.h | 2 + arch/sparc/include/asm/mman.h | 84 ++- arch/sparc/include/asm/mmu_64.h | 17 ++ arch/sparc/include/asm/mmu_context_64.h | 50 + arch/sparc/include/asm/page_64.h| 4 + arch/sparc/include/asm/pgtable_64.h | 48 arch/sparc/include/asm/thread_info_64.h | 2 +- arch/sparc/include/asm/trap_block.h | 2 + arch/sparc/include/asm/ttable.h | 10 + arch/sparc/include/uapi/asm/asi.h | 5 + arch/sparc/include/uapi/asm/auxvec.h| 11 + arch/sparc/include/uapi/asm/mman.h | 2 + arch/sparc/include/uapi/asm/pstate.h| 10 + arch/sparc/kernel/Makefile | 1 + arch/sparc/kernel/adi_64.c | 384 arch/sparc/kernel/entry.h | 3 + arch/sparc/kernel/etrap_64.S| 28 ++- arch/sparc/kernel/head_64.S | 1 + arch/sparc/kernel/mdesc.c | 2 + arch/sparc/kernel/process_64.c | 25 +++ arch/sparc/kernel/setup_64.c| 2 + arch/sparc/kernel/sun4v_mcd.S | 17 ++ arch/sparc/kernel/traps_64.c| 142 +++- arch/sparc/kernel/ttable_64.S | 6 +- arch/sparc/kernel/vmlinux.lds.S | 5 + arch/sparc/mm/gup.c | 37 +++ arch/sparc/mm/hugetlbpage.c | 14 +- arch/sparc/mm/init_64.c | 34 +++ arch/sparc/mm/tsb.c | 21 ++ arch/x86/kernel/signal_compat.c | 2 +- include/asm-generic/pgtable.h | 36 +++ include/linux/mm.h | 9 + include/linux/mman.h| 2 +- include/uapi/asm-generic/siginfo.h | 5 +- mm/ksm.c| 4 + mm/memory.c | 1 + mm/mprotect.c | 4 +- mm/rmap.c | 14 ++ 44 files changed, 1374 insertions(+), 17 deletions(-) create mode 100644 Documentation/sparc/adi.txt create mode 100644 arch/sparc/include/asm/adi.h create mode 100644 arch/sparc/include/asm/adi_64.h create mode 100644 arch/sparc/kernel/adi_64.c create mode 100644 arch/sparc/kernel/sun4v_mcd.S -- 2.11.0 -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v8 9/9] sparc64: Add support for ADI (Application Data Integrity)
ADI is a new feature supported on SPARC M7 and newer processors to allow hardware to catch rogue accesses to memory. ADI is supported for data fetches only and not instruction fetches. An app can enable ADI on its data pages, set version tags on them and use versioned addresses to access the data pages. Upper bits of the address contain the version tag. On M7 processors, upper four bits (bits 63-60) contain the version tag. If a rogue app attempts to access ADI enabled data pages, its access is blocked and processor generates an exception. Please see Documentation/sparc/adi.txt for further details. This patch extends mprotect to enable ADI (TSTATE.mcde), enable/disable MCD (Memory Corruption Detection) on selected memory ranges, enable TTE.mcd in PTEs, return ADI parameters to userspace and save/restore ADI version tags on page swap out/in or migration. ADI is not enabled by default for any task. A task must explicitly enable ADI on a memory range and set version tag for ADI to be effective for the task. Signed-off-by: Khalid Aziz Cc: Khalid Aziz --- v8: - Added note to doc about non-faulting loads not triggering ADI tag mismatch and more details on special tag values of 0x0 and 0xf, as suggested by Anthony Yznaga) - Added an IPI on mprotect(...PROT_ADI...) call to set TSTATE.MCDE on threads running on other processors and restore of TSTATE.MCDE on context switch (suggested by David Miller) - Removed restriction on enabling ADI on read-only memory (suggested by Anthony Yznaga) - Changed kzalloc() for tag storage to use GFP_NOWAIT - Added code to handle overflow and underflow when allocating tag storage, as suggested by Anthony Yznaga - Replaced sun_m7_patch_1insn_range() with sun4v_patch_1insn_range() which is functionally identical (suggested by Anthony Yznaga) - Added membar after restoring ADI tags in copy_user_highpage(), as suggested by David Miller v7: - Enhanced arch_validate_prot() to enable ADI only on writable addresses backed by physical RAM - Added support for saving/restoring ADI tags for each ADI block size address range on a page on swap in/out - Added code to copy ADI tags on COW - Updated values for auxiliary vectors to not conflict with values on other architectures to avoid conflict in glibc. glibc consolidates all auxiliary vectors into its headers and duplicate values in consolidated header are problematic - Disable same page merging on ADI enabled pages since ADI tags may not match on pages with identical data - Broke the patch up further into smaller patches v6: - Eliminated instructions to read and write PSTATE as well as MCDPER and PMCDPER on every access to userspace addresses by setting PSTATE and PMCDPER correctly upon entry into kernel. PSTATE.mcde and PMCDPER are set upon entry into kernel when running on an M7 processor. PSTATE.mcde being set only affects memory accesses that have TTE.mcd set. PMCDPER being set only affects writes to memory addresses that have TTE.mcd set. This ensures any faults caused by ADI tag mismatch on a write are exposed before kernel returns to userspace. v5: - Fixed indentation issues and instrcuctions in assembly code - Removed CONFIG_SPARC64 from mdesc.c - Changed to maintain state of MCDPER register in thread info flags as opposed to in mm context. MCDPER is a per-thread state and belongs in thread info flag as opposed to mm context which is shared across threads. Added comments to clarify this is a lazily maintained state and must be updated on context switch and copy_process() - Updated code to use the new arch_do_swap_page() and arch_unmap_one() functions v4: - Broke patch up into smaller patches v3: - Removed CONFIG_SPARC_ADI - Replaced prctl commands with mprotect - Added auxiliary vectors for ADI parameters - Enabled ADI for swappable pages v2: - Fixed a build error Documentation/sparc/adi.txt | 278 ++ arch/sparc/include/asm/mman.h | 84 +- arch/sparc/include/asm/mmu_64.h | 17 ++ arch/sparc/include/asm/mmu_context_64.h | 50 ++ arch/sparc/include/asm/page_64.h| 4 + arch/sparc/include/asm/pgtable_64.h | 46 + arch/sparc/include/asm/thread_info_64.h | 2 +- arch/sparc/include/asm/trap_block.h | 2 + arch/sparc/include/uapi/asm/mman.h | 2 + arch/sparc/kernel/adi_64.c | 289 arch/sparc/kernel/etrap_64.S| 28 +++- arch/sparc/kernel/process_64.c | 25 +++ arch/sparc/kernel
Re: [PATCH v7 9/9] sparc64: Add support for ADI (Application Data Integrity)
On 09/04/2017 10:25 AM, Pavel Machek wrote: Hi! ADI is a new feature supported on SPARC M7 and newer processors to allow hardware to catch rogue accesses to memory. ADI is supported for data fetches only and not instruction fetches. An app can enable ADI on its data pages, set version tags on them and use versioned addresses to access the data pages. Upper bits of the address contain the version tag. On M7 processors, upper four bits (bits 63-60) contain the version tag. If a rogue app attempts to access ADI enabled data pages, its access is blocked and processor generates an exception. Please see Documentation/sparc/adi.txt for further details. I'm afraid I still don't understand what this is meant to prevent. IOMMU ignores these, so this is not to prevent rogue DMA from doing bad stuff. Will gcc be able to compile code that uses these automatically? That does not sound easy to me. Can libc automatically use this in malloc() to prevent accessing freed data when buffers are overrun? Is this for benefit of JITs? David explained it well. Yes, preventing buffer overflow is one of the uses of ADI. Protecting critical data from wild writes caused by programming errors is another use. ADI can be used for debugging as well during development. Thanks, Khalid -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v7 9/9] sparc64: Add support for ADI (Application Data Integrity)
On 08/30/2017 06:09 PM, David Miller wrote: From: Khalid Aziz Date: Wed, 30 Aug 2017 17:23:37 -0600 That is an interesting idea. This would enable TSTATE_MCDE on all threads of a process as soon as one thread enables it. If we consider the case where the parent creates a shared memory area and spawns a bunch of threads. These threads access the shared memory without ADI enabled. Now one of the threads decides to enable ADI on the shared memory. As soon as it does that, we enable TSTATE_MCDE across all threads and since threads are all using the same TTE for the shared memory, every thread becomes subject to ADI verification. If one of the other threads was in the middle of accessing the shared memory, it will get a sigsegv. If we did not enable TSTATE_MCDE across all threads, it could have continued execution without fault. In other words, updating TSTATE_MCDE across all threads will eliminate the option of running some threads with ADI enabled and some not while accessing the same shared memory. This could be necessary at least for short periods of time before threads can communicate with each other and all switch to accessing shared memory with ADI enabled using same tag. Does that sound like a valid use case or am I off in the weeds here? A threaded application needs to synchronize and properly orchestrate access to shared memory. When a change is made to a mappping, in this case setting ADI attributes, it's being done for the address space not the thread. And the address space is shared amongst threads. Therefore ADI is not really a per-thread property but rather a per-address-space property. That does make sense. Thanks, Khalid -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v7 9/9] sparc64: Add support for ADI (Application Data Integrity)
On 08/30/2017 04:38 PM, David Miller wrote: From: Khalid Aziz Date: Wed, 30 Aug 2017 16:27:54 -0600 +#define arch_calc_vm_prot_bits(prot, pkey) sparc_calc_vm_prot_bits(prot) +static inline unsigned long sparc_calc_vm_prot_bits(unsigned long prot) +{ + if (prot & PROT_ADI) { + struct pt_regs *regs; + + if (!current->mm->context.adi) { + regs = task_pt_regs(current); + regs->tstate |= TSTATE_MCDE; + current->mm->context.adi = true; If a process is multi-threaded when it enables ADI on some memory for the first time, TSTATE_MCDE will only be set for the calling thread and it will not be possible to enable it for the other threads. One possible way to handle this is to enable TSTATE_MCDE for all user threads when they are initialized if adi_capable() returns true. Or set TSTATE_MCDE unconditionally here by removing "if (!current->mm->context.adi)"? I think you have to make "ADI enabled" a property of the mm_struct. Then you can broadcast to mm->cpu_vm_mask a per-cpu interrupt that updates regs->tstate of a thread using 'mm' is currently executing. And in the context switch code you set TSTATE_MCDE if it's not set already. That should cover all threaded case. That is an interesting idea. This would enable TSTATE_MCDE on all threads of a process as soon as one thread enables it. If we consider the case where the parent creates a shared memory area and spawns a bunch of threads. These threads access the shared memory without ADI enabled. Now one of the threads decides to enable ADI on the shared memory. As soon as it does that, we enable TSTATE_MCDE across all threads and since threads are all using the same TTE for the shared memory, every thread becomes subject to ADI verification. If one of the other threads was in the middle of accessing the shared memory, it will get a sigsegv. If we did not enable TSTATE_MCDE across all threads, it could have continued execution without fault. In other words, updating TSTATE_MCDE across all threads will eliminate the option of running some threads with ADI enabled and some not while accessing the same shared memory. This could be necessary at least for short periods of time before threads can communicate with each other and all switch to accessing shared memory with ADI enabled using same tag. Does that sound like a valid use case or am I off in the weeds here? Thanks, Khalid -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v7 9/9] sparc64: Add support for ADI (Application Data Integrity)
Hi Anthony, Thanks for taking the time to provide feedback. My comments inline below. On 08/25/2017 04:31 PM, Anthony Yznaga wrote: On Aug 9, 2017, at 2:26 PM, Khalid Aziz wrote: ..deleted.. +provided by the hypervisor to the kernel. Kernel returns the value of +ADI block size to userspace using auxiliary vector along with other ADI +info. Following auxiliary vectors are provided by the kernel: + + AT_ADI_BLKSZADI block size. This is the granularity and + alignment, in bytes, of ADI versioning. + AT_ADI_NBITSNumber of ADI version bits in the VA The previous patch series also defined AT_ADI_UEONADI. Why was that removed? This was based upon a conversation we had when you mentioned future processors may not implement this or change the way this is interpreted and any applications depending upon this value would break at that point. I removed it to eliminate building an unreliable dependency. If I misunderstood what you said, please let me know. + + +IMPORTANT NOTES: + +- Version tag values of 0x0 and 0xf are reserved. The documentation should probably state more specifically that an in-memory tag value of 0x0 or 0xf is treated as "match all" by the HW meaning that a mismatch exception will never be generated regardless of the tag bits set in the VA accessing the memory. Will do. + +- Version tags are set on virtual addresses from userspace even though + tags are stored in physical memory. Tags are set on a physical page + after it has been allocated to a task and a pte has been created for + it. + +- When a task frees a memory page it had set version tags on, the page + goes back to free page pool. When this page is re-allocated to a task, + kernel clears the page using block initialization ASI which clears the + version tags as well for the page. If a page allocated to a task is + freed and allocated back to the same task, old version tags set by the + task on that page will no longer be present. The specifics should be included here, too, so someone doesn't have to guess what's going on if they make changes and the tags are no longer cleared. The HW clears the tag for a cacheline for block initializing stores to 64-byte aligned addresses if PSTATE.mcde=0 or TTE.mcd=0. PSTATE.mce is set when executing in the kernel, but pages are cleared using kernel physical mapping VAs which are mapped with TTE.mcd=0. Another HW behavior that should be mentioned is that tag mismatches are not detected for non-faulting loads. Sure, I can add that. + +- Kernel does not set any tags for user pages and it is entirely a + task's responsibility to set any version tags. Kernel does ensure the + version tags are preserved if a page is swapped out to the disk and + swapped back in. It also preserves that version tags if a page is + migrated. I only have a cursory understanding of how page migration works, but I could not see how the tags would be preserved if a page were migrated. I figured the place to copy the tags would be migrate_page_copy(), but I don't see changes there. For migrating user pages, the way I understand the code works is if the page is mapped (which is the only time ADI tags are even in place), try_to_unmap() is called with TTU_MIGRATION flag set. try_to_unmap() will call arch_unmap_one() which saves the tags from currently mapped page. When the new page has been allocated, contents of the old page are faulted in through do_swap_page() which will call arch_do_swap_page(). arch_do_swap_page() then restores the ADI tags. diff --git a/arch/sparc/include/asm/mman.h b/arch/sparc/include/asm/mman.h index 59bb5938d852..b799796ad963 100644 --- a/arch/sparc/include/asm/mman.h +++ b/arch/sparc/include/asm/mman.h @@ -6,5 +6,75 @@ #ifndef __ASSEMBLY__ #define arch_mmap_check(addr,len,flags) sparc_mmap_check(addr,len) int sparc_mmap_check(unsigned long addr, unsigned long len); -#endif + +#ifdef CONFIG_SPARC64 +#include + +#define arch_calc_vm_prot_bits(prot, pkey) sparc_calc_vm_prot_bits(prot) +static inline unsigned long sparc_calc_vm_prot_bits(unsigned long prot) +{ + if (prot & PROT_ADI) { + struct pt_regs *regs; + + if (!current->mm->context.adi) { + regs = task_pt_regs(current); + regs->tstate |= TSTATE_MCDE; + current->mm->context.adi = true; If a process is multi-threaded when it enables ADI on some memory for the first time, TSTATE_MCDE will only be set for the calling thread and it will not be possible to enable it for the other threads. One possible way to handle this is to enable TSTATE_MCDE for all user threads when they are initialized if adi_capable() returns true. Or set TSTATE_MCDE unconditionally here by removing "if (!current->mm->context.adi)"? + } + return VM_SPARC_ADI; +
Re: [PATCH v7 9/9] sparc64: Add support for ADI (Application Data Integrity)
On 08/15/2017 10:58 PM, David Miller wrote: From: Khalid Aziz Date: Wed, 9 Aug 2017 15:26:02 -0600 +void adi_restore_tags(struct mm_struct *mm, struct vm_area_struct *vma, + unsigned long addr, pte_t pte) +{ ... + tag = tag_start(addr, tag_desc); + paddr = pte_val(pte) & _PAGE_PADDR_4V; + for (tmp = paddr; tmp < (paddr+PAGE_SIZE); tmp += adi_blksize()) { + version1 = (*tag) >> 4; + version2 = (*tag) & 0x0f; + *tag++ = 0; + asm volatile("stxa %0, [%1] %2\n\t" + : + : "r" (version1), "r" (tmp), + "i" (ASI_MCD_REAL)); + tmp += adi_blksize(); + asm volatile("stxa %0, [%1] %2\n\t" + : + : "r" (version2), "r" (tmp), + "i" (ASI_MCD_REAL)); + } + asm volatile("membar #Sync\n\t"); You do a membar here. + for (i = pfrom; i < (pfrom + PAGE_SIZE); i += adi_blksize()) { + asm volatile("ldxa [%1] %2, %0\n\t" + : "=r" (adi_tag) + : "r" (i), "i" (ASI_MCD_REAL)); + asm volatile("stxa %0, [%1] %2\n\t" + : + : "r" (adi_tag), "r" (pto), + "i" (ASI_MCD_REAL)); But not here. Is this OK? I suspect you need to add a membar this this second piece of MCD tag storing code. Hi Dave, You are right. This tag storing code needs membar as well. I will add that. Thanks, Khalid -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v7 9/9] sparc64: Add support for ADI (Application Data Integrity)
ADI is a new feature supported on SPARC M7 and newer processors to allow hardware to catch rogue accesses to memory. ADI is supported for data fetches only and not instruction fetches. An app can enable ADI on its data pages, set version tags on them and use versioned addresses to access the data pages. Upper bits of the address contain the version tag. On M7 processors, upper four bits (bits 63-60) contain the version tag. If a rogue app attempts to access ADI enabled data pages, its access is blocked and processor generates an exception. Please see Documentation/sparc/adi.txt for further details. This patch extends mprotect to enable ADI (TSTATE.mcde), enable/disable MCD (Memory Corruption Detection) on selected memory ranges, enable TTE.mcd in PTEs, return ADI parameters to userspace and save/restore ADI version tags on page swap out/in or migration. ADI is not enabled by default for any task. A task must explicitly enable ADI on a memory range and set version tag for ADI to be effective for the task. Signed-off-by: Khalid Aziz Cc: Khalid Aziz --- v7: - Enhanced arch_validate_prot() to enable ADI only on writable addresses backed by physical RAM - Added support for saving/restoring ADI tags for each ADI block size address range on a page on swap in/out - Added code to copy ADI tags on COW - Updated values for auxiliary vectors to not conflict with values on other architectures to avoid conflict in glibc. glibc consolidates all auxiliary vectors into its headers and duplicate values in consolidated header are problematic - Disable same page merging on ADI enabled pages since ADI tags may not match on pages with identical data - Broke the patch up further into smaller patches v6: - Eliminated instructions to read and write PSTATE as well as MCDPER and PMCDPER on every access to userspace addresses by setting PSTATE and PMCDPER correctly upon entry into kernel. PSTATE.mcde and PMCDPER are set upon entry into kernel when running on an M7 processor. PSTATE.mcde being set only affects memory accesses that have TTE.mcd set. PMCDPER being set only affects writes to memory addresses that have TTE.mcd set. This ensures any faults caused by ADI tag mismatch on a write are exposed before kernel returns to userspace. v5: - Fixed indentation issues and instrcuctions in assembly code - Removed CONFIG_SPARC64 from mdesc.c - Changed to maintain state of MCDPER register in thread info flags as opposed to in mm context. MCDPER is a per-thread state and belongs in thread info flag as opposed to mm context which is shared across threads. Added comments to clarify this is a lazily maintained state and must be updated on context switch and copy_process() - Updated code to use the new arch_do_swap_page() and arch_unmap_one() functions v4: - Broke patch up into smaller patches v3: - Removed CONFIG_SPARC_ADI - Replaced prctl commands with mprotect - Added auxiliary vectors for ADI parameters - Enabled ADI for swappable pages v2: - Fixed a build error Documentation/sparc/adi.txt | 272 +++ arch/sparc/include/asm/mman.h | 72 - arch/sparc/include/asm/mmu_64.h | 17 ++ arch/sparc/include/asm/mmu_context_64.h | 43 + arch/sparc/include/asm/page_64.h| 4 + arch/sparc/include/asm/pgtable_64.h | 46 ++ arch/sparc/include/asm/thread_info_64.h | 2 +- arch/sparc/include/asm/trap_block.h | 2 + arch/sparc/include/uapi/asm/mman.h | 2 + arch/sparc/kernel/adi_64.c | 277 arch/sparc/kernel/etrap_64.S| 28 +++- arch/sparc/kernel/process_64.c | 25 +++ arch/sparc/kernel/setup_64.c| 11 +- arch/sparc/kernel/vmlinux.lds.S | 5 + arch/sparc/mm/gup.c | 37 + arch/sparc/mm/hugetlbpage.c | 14 +- arch/sparc/mm/init_64.c | 33 arch/sparc/mm/tsb.c | 21 +++ include/linux/mm.h | 3 + mm/ksm.c| 4 + 20 files changed, 913 insertions(+), 5 deletions(-) create mode 100644 Documentation/sparc/adi.txt diff --git a/Documentation/sparc/adi.txt b/Documentation/sparc/adi.txt new file mode 100644 index ..383bc65fec1e --- /dev/null +++ b/Documentation/sparc/adi.txt @@ -0,0 +1,272 @@ +Application Data Integrity (ADI) + + +SPARC M7 processor adds the Application Data Integrity (ADI) feature. +ADI allows a task to set version tags on any subset of its address +space. Once ADI is enabled and version tags are set for ranges of +address space
[PATCH v7 0/9] Application Data Integrity feature introduced by SPARC M7
en that read from ADI enabled pages shared with parent and other children and write to them as well forcing COW. - Khalid Aziz (9): signals, sparc: Add signal codes for ADI violations mm, swap: Add infrastructure for saving page metadata as well on swap sparc64: Add support for ADI register fields, ASIs and traps sparc64: Add HV fault type handlers for ADI related faults sparc64: Add handler for "Memory Corruption Detected" trap sparc64: Add auxiliary vectors to report platform ADI properties mm: Add address parameter to arch_validate_prot() mm: Clear arch specific VM flags on protection change sparc64: Add support for ADI (Application Data Integrity) Documentation/sparc/adi.txt | 272 +++ arch/powerpc/include/asm/mman.h | 2 +- arch/powerpc/kernel/syscalls.c | 2 +- arch/sparc/include/asm/adi.h| 6 + arch/sparc/include/asm/adi_64.h | 45 arch/sparc/include/asm/elf_64.h | 8 + arch/sparc/include/asm/hypervisor.h | 2 + arch/sparc/include/asm/mman.h | 72 ++- arch/sparc/include/asm/mmu_64.h | 17 ++ arch/sparc/include/asm/mmu_context_64.h | 43 arch/sparc/include/asm/page_64.h| 4 + arch/sparc/include/asm/pgtable_64.h | 48 + arch/sparc/include/asm/thread_info_64.h | 2 +- arch/sparc/include/asm/trap_block.h | 2 + arch/sparc/include/asm/ttable.h | 10 + arch/sparc/include/uapi/asm/asi.h | 5 + arch/sparc/include/uapi/asm/auxvec.h| 10 + arch/sparc/include/uapi/asm/mman.h | 2 + arch/sparc/include/uapi/asm/pstate.h| 10 + arch/sparc/kernel/Makefile | 1 + arch/sparc/kernel/adi_64.c | 367 arch/sparc/kernel/entry.h | 3 + arch/sparc/kernel/etrap_64.S| 28 ++- arch/sparc/kernel/head_64.S | 1 + arch/sparc/kernel/mdesc.c | 2 + arch/sparc/kernel/process_64.c | 25 +++ arch/sparc/kernel/setup_64.c| 11 +- arch/sparc/kernel/sun4v_mcd.S | 17 ++ arch/sparc/kernel/traps_64.c| 142 +++- arch/sparc/kernel/ttable_64.S | 6 +- arch/sparc/kernel/vmlinux.lds.S | 5 + arch/sparc/mm/gup.c | 37 arch/sparc/mm/hugetlbpage.c | 14 +- arch/sparc/mm/init_64.c | 33 +++ arch/sparc/mm/tsb.c | 21 ++ arch/x86/kernel/signal_compat.c | 2 +- include/asm-generic/pgtable.h | 36 include/linux/mm.h | 9 + include/linux/mman.h| 2 +- include/uapi/asm-generic/siginfo.h | 5 +- mm/ksm.c| 4 + mm/memory.c | 1 + mm/mprotect.c | 4 +- mm/rmap.c | 13 ++ 44 files changed, 1334 insertions(+), 17 deletions(-) create mode 100644 Documentation/sparc/adi.txt create mode 100644 arch/sparc/include/asm/adi.h create mode 100644 arch/sparc/include/asm/adi_64.h create mode 100644 arch/sparc/kernel/adi_64.c create mode 100644 arch/sparc/kernel/sun4v_mcd.S -- 2.11.0 -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v6 4/4] sparc64: Add support for ADI (Application Data Integrity)
On 03/06/2017 06:25 PM, Anthony Yznaga wrote: > >> On Mar 6, 2017, at 4:31 PM, Khalid Aziz wrote: >> >> On 03/06/2017 05:13 PM, Anthony Yznaga wrote: >>> >>>> On Feb 28, 2017, at 10:35 AM, Khalid Aziz wrote: >>>> >>>> diff --git a/arch/sparc/kernel/etrap_64.S b/arch/sparc/kernel/etrap_64.S >>>> index 1276ca2..7be33bf 100644 >>>> --- a/arch/sparc/kernel/etrap_64.S >>>> +++ b/arch/sparc/kernel/etrap_64.S >>>> @@ -132,7 +132,33 @@ etrap_save: save%g2, -STACK_BIAS, %sp >>>>stx %g6, [%sp + PTREGS_OFF + PT_V9_G6] >>>>stx %g7, [%sp + PTREGS_OFF + PT_V9_G7] >>>>or %l7, %l0, %l7 >>>> - sethi %hi(TSTATE_TSO | TSTATE_PEF), %l0 >>>> +661: sethi %hi(TSTATE_TSO | TSTATE_PEF), %l0 >>>> + /* >>>> + * If userspace is using ADI, it could potentially pass >>>> + * a pointer with version tag embedded in it. To maintain >>>> + * the ADI security, we must enable PSTATE.mcde. Userspace >>>> + * would have already set TTE.mcd in an earlier call to >>>> + * kernel and set the version tag for the address being >>>> + * dereferenced. Setting PSTATE.mcde would ensure any >>>> + * access to userspace data through a system call honors >>>> + * ADI and does not allow a rogue app to bypass ADI by >>>> + * using system calls. Setting PSTATE.mcde only affects >>>> + * accesses to virtual addresses that have TTE.mcd set. >>>> + * Set PMCDPER to ensure any exceptions caused by ADI >>>> + * version tag mismatch are exposed before system call >>>> + * returns to userspace. Setting PMCDPER affects only >>>> + * writes to virtual addresses that have TTE.mcd set and >>>> + * have a version tag set as well. >>>> + */ >>>> + .section .sun_m7_1insn_patch, "ax" >>>> + .word 661b >>>> + sethi %hi(TSTATE_TSO | TSTATE_PEF | TSTATE_MCDE), %l0 >>>> + .previous >>>> +661: nop >>>> + .section .sun_m7_1insn_patch, "ax" >>>> + .word 661b >>>> + .word 0xaf902001/* wrpr %g0, 1, %pmcdper */ >>> >>> Since PMCDPER is never cleared, setting it here is quickly going to set it >>> on all CPUs and then become an expensive "nop" that burns ~50 cycles each >>> time through etrap. Consider setting it at boot time and when a CPU is >>> DR'd into the system. >>> >>> Anthony >>> >> >> I considered that possibility. What made me uncomfortable with that is there >> is no way to prevent a driver/module or future code elsewhere in kernel from >> clearing PMCDPER with possibly good reason. If that were to happen, setting >> PMCDPER here ensures kernel will always see consistent behavior with system >> calls. It does come at a cost. Is that cost unacceptable to ensure >> consistent behavior? > > Aren't you still at risk if the thread relinquishes the CPU while in the > kernel and is then rescheduled on a CPU where PMCDPER has erroneously been > left cleared? You may need to save and restore PMCDPER as well as MCDPER on > context switch, but I don't know if that will cover you completely. > You mean something like this? --- arch/sparc/include/asm/mmu_context_64.h 2017-03-03 14:05:30.398573081 -0700 +++ /tmp/mmu_context_64.h 2017-03-07 08:26:20.582124798 -0700 @@ -193,6 +193,7 @@ __asm__ __volatile__( "mov %0, %%g1\n\t" ".word 0x9d81\n\t" /* wr %g0, %g1, %mcdper" */ + ".word 0xaf902001\n\t" /* wrpr %g0, 1, %pmcdper */ : : "ir" (tmp_mcdper) : "g1"); > Alternatively you can avoid problems from buggy code and avoid the > performance hit when storing to ADI enabled memory with precise mode enabled > (e.g. when reading from a file into an ADI-enabled buffer) by handling > disrupting mismatches that happen in copy_to_user() or put_user(). That does > require adding error barriers and appropriate exception table entries, > though, to deal with the nature of disrupting exceptions. > put_user() can be called for writing just one word of da
Re: [PATCH v6 4/4] sparc64: Add support for ADI (Application Data Integrity)
On 03/06/2017 05:13 PM, Anthony Yznaga wrote: On Feb 28, 2017, at 10:35 AM, Khalid Aziz wrote: diff --git a/arch/sparc/kernel/etrap_64.S b/arch/sparc/kernel/etrap_64.S index 1276ca2..7be33bf 100644 --- a/arch/sparc/kernel/etrap_64.S +++ b/arch/sparc/kernel/etrap_64.S @@ -132,7 +132,33 @@ etrap_save:save%g2, -STACK_BIAS, %sp stx %g6, [%sp + PTREGS_OFF + PT_V9_G6] stx %g7, [%sp + PTREGS_OFF + PT_V9_G7] or %l7, %l0, %l7 - sethi %hi(TSTATE_TSO | TSTATE_PEF), %l0 +661: sethi %hi(TSTATE_TSO | TSTATE_PEF), %l0 + /* +* If userspace is using ADI, it could potentially pass +* a pointer with version tag embedded in it. To maintain +* the ADI security, we must enable PSTATE.mcde. Userspace +* would have already set TTE.mcd in an earlier call to +* kernel and set the version tag for the address being +* dereferenced. Setting PSTATE.mcde would ensure any +* access to userspace data through a system call honors +* ADI and does not allow a rogue app to bypass ADI by +* using system calls. Setting PSTATE.mcde only affects +* accesses to virtual addresses that have TTE.mcd set. +* Set PMCDPER to ensure any exceptions caused by ADI +* version tag mismatch are exposed before system call +* returns to userspace. Setting PMCDPER affects only +* writes to virtual addresses that have TTE.mcd set and +* have a version tag set as well. +*/ + .section .sun_m7_1insn_patch, "ax" + .word 661b + sethi %hi(TSTATE_TSO | TSTATE_PEF | TSTATE_MCDE), %l0 + .previous +661: nop + .section .sun_m7_1insn_patch, "ax" + .word 661b + .word 0xaf902001/* wrpr %g0, 1, %pmcdper */ Since PMCDPER is never cleared, setting it here is quickly going to set it on all CPUs and then become an expensive "nop" that burns ~50 cycles each time through etrap. Consider setting it at boot time and when a CPU is DR'd into the system. Anthony I considered that possibility. What made me uncomfortable with that is there is no way to prevent a driver/module or future code elsewhere in kernel from clearing PMCDPER with possibly good reason. If that were to happen, setting PMCDPER here ensures kernel will always see consistent behavior with system calls. It does come at a cost. Is that cost unacceptable to ensure consistent behavior? -- Khalid -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v6 0/4] Application Data Integrity feature introduced by SPARC M7
No changes - Patch 2/4: No changes - Patch 3/4: Added missing nop in the delay slot in sun4v_mcd_detect_precise - Patch 4/4: Eliminated instructions to read and write PSTATE as well as MCDPER and PMCDPER on every access to userspace addresses by setting PSTATE and PMCDPER correctly upon entry into kernel Changelog v5: - Patch 1/4: No changes - Patch 2/4: Replaced set_swp_pte_at() with new architecture functions arch_do_swap_page() and arch_unmap_one() that suppoprt architecture specific actions to be taken on page swap and migration - Patch 3/4: Fixed indentation issues in assembly code - Patch 4/4: - Fixed indentation issues and instrcuctions in assembly code - Removed CONFIG_SPARC64 from mdesc.c - Changed to maintain state of MCDPER register in thread info flags as opposed to in mm context. MCDPER is a per-thread state and belongs in thread info flag as opposed to mm context which is shared across threads. Added comments to clarify this is a lazily maintained state and must be updated on context switch and copy_process() - Updated code to use the new arch_do_swap_page() and arch_unmap_one() functions Testing: - All functionality was tested with 8K normal pages as well as hugepages using malloc, mmap and shm. - Multiple long duration stress tests were run using hugepages over 2+ months. Normal pages were tested with shorter duration stress tests. - Tested swapping with malloc and shm by reducing max memory and allocating three times the available system memory by active processes using ADI on allocated memory. Ran through multiple hour long runs of this test. - Tested page migration with malloc and shm by migrating data pages of active ADI test process using migratepages, back and forth between two nodes every few seconds over an hour long run. Verified page migration through /proc//numa_maps. Outstanding issues: - When sharing mmap'd ADI enabled areas with MAP_PRIVATE, copy-on-write results in a copy that does not have ADI enabled and ADI tags set. - Two processes sharing a mmap's ADI enabled area with MAP_SHARED must coordinate setting of ADI tags or else one process can cause the other to get SIGSEGV. I am working to solve these issues in subsequent patches. First issue can be resolved by mapping the new COW pages with ADI enabled and copy the ADI tags over to the new pages. This will increase the COW time since tags must be copied over one cacheline at a time. Second issue can possibly be solved by allowing only one task to mmap with write permission when the memory pages are ADI enabled. All subsequent mmap of this shared file would then be read-only mappings, or mprotect() with PROT_ADI would be denied for subsequent mappings if mapped pages have write permission. This would allow only one process to change ADI tags but that process can still cause the processes that have mmap'd read-only to crash if it changes ADI tags without coordinating the change with other processes. These ideas need to be explored more before implementing a fix. There are potential race conditions as well in the solution for second issue that will need to be evaluated and addressed. --- Khalid Aziz (4): signals, sparc: Add signal codes for ADI violations mm: Add functions to support extra actions on swap in/out sparc64: Add support for ADI register fields, ASIs and traps sparc64: Add support for ADI (Application Data Integrity) Documentation/sparc/adi.txt | 288 arch/sparc/include/asm/adi.h| 6 + arch/sparc/include/asm/adi_64.h | 46 + arch/sparc/include/asm/elf_64.h | 8 + arch/sparc/include/asm/hugetlb.h| 13 ++ arch/sparc/include/asm/hypervisor.h | 2 + arch/sparc/include/asm/mman.h | 40 - arch/sparc/include/asm/mmu_64.h | 1 + arch/sparc/include/asm/mmu_context_64.h | 42 + arch/sparc/include/asm/pgtable_64.h | 87 +- arch/sparc/include/asm/thread_info_64.h | 2 +- arch/sparc/include/asm/trap_block.h | 2 + arch/sparc/include/asm/ttable.h | 10 ++ arch/sparc/include/uapi/asm/asi.h | 5 + arch/sparc/include/uapi/asm/auxvec.h| 8 + arch/sparc/include/uapi/asm/mman.h | 2 + arch/sparc/include/uapi/asm/pstate.h| 10 ++ arch/sparc/kernel/Makefile | 1 + arch/sparc/kernel/adi_64.c | 93 +++ arch/sparc/kernel/entry.h | 3 + arch/sparc/kernel/etrap_64.S| 28 +++- arch/sparc/kernel/head_64.S | 1 + arch/sparc/kernel/mdesc.c | 2 + arch/sparc/kernel/process_64.c
[PATCH v6 4/4] sparc64: Add support for ADI (Application Data Integrity)
ADI is a new feature supported on SPARC M7 and newer processors to allow hardware to catch rogue accesses to memory. ADI is supported for data fetches only and not instruction fetches. An app can enable ADI on its data pages, set version tags on them and use versioned addresses to access the data pages. Upper bits of the address contain the version tag. On M7 processors, upper four bits (bits 63-60) contain the version tag. If a rogue app attempts to access ADI enabled data pages, its access is blocked and processor generates an exception. Please see Documentation/sparc/adi.txt for further details. This patch extends mprotect to enable ADI (TSTATE.mcde), enable/disable MCD (Memory Corruption Detection) on selected memory ranges, enable TTE.mcd in PTEs, return ADI parameters to userspace and save/restore ADI version tags on page swap out/in or migration. It also adds handlers for traps related to MCD. ADI is not enabled by default for any task. A task must explicitly enable ADI on a memory range and set version tag for ADI to be effective for the task. This initial implementation supports saving and restoring one tag per page. A page must use same version tag across the entire page for the tag to survive swap and migration. Swap swupport infrastructure in this patch allows for this capability to be expanded to store/restore more than one tag per page in future. Signed-off-by: Khalid Aziz Cc: Khalid Aziz --- v6: - Eliminated instructions to read and write PSTATE as well as MCDPER and PMCDPER on every access to userspace addresses by setting PSTATE and PMCDPER correctly upon entry into kernel. PSTATE.mcde and PMCDPER are set upon entry into kernel when running on an M7 processor. PSTATE.mcde being set only affects memory accesses that have TTE.mcd set. PMCDPER being set only affects writes to memory addresses that have TTE.mcd set. This ensures any faults caused by ADI tag mismatch on a write are exposed before kernel returns to userspace. v5: - Fixed indentation issues and instrcuctions in assembly code - Removed CONFIG_SPARC64 from mdesc.c - Changed to maintain state of MCDPER register in thread info flags as opposed to in mm context. MCDPER is a per-thread state and belongs in thread info flag as opposed to mm context which is shared across threads. Added comments to clarify this is a lazily maintained state and must be updated on context switch and copy_process() - Updated code to use the new arch_do_swap_page() and arch_unmap_one() functions v4: - Broke patch up into smaller patches v3: - Removed CONFIG_SPARC_ADI - Replaced prctl commands with mprotect - Added auxiliary vectors for ADI parameters - Enabled ADI for swappable pages v2: - Fixed a build error Documentation/sparc/adi.txt | 292 arch/sparc/include/asm/adi.h| 6 + arch/sparc/include/asm/adi_64.h | 46 + arch/sparc/include/asm/elf_64.h | 8 + arch/sparc/include/asm/hugetlb.h| 13 ++ arch/sparc/include/asm/mman.h | 40 - arch/sparc/include/asm/mmu_64.h | 1 + arch/sparc/include/asm/mmu_context_64.h | 42 + arch/sparc/include/asm/pgtable_64.h | 85 +- arch/sparc/include/asm/thread_info_64.h | 2 +- arch/sparc/include/asm/trap_block.h | 2 + arch/sparc/include/uapi/asm/auxvec.h| 8 + arch/sparc/include/uapi/asm/mman.h | 2 + arch/sparc/kernel/Makefile | 1 + arch/sparc/kernel/adi_64.c | 93 ++ arch/sparc/kernel/etrap_64.S| 28 ++- arch/sparc/kernel/mdesc.c | 2 + arch/sparc/kernel/process_64.c | 25 +++ arch/sparc/kernel/setup_64.c| 11 +- arch/sparc/kernel/traps_64.c| 83 - arch/sparc/kernel/vmlinux.lds.S | 5 + arch/sparc/mm/gup.c | 37 include/linux/mm.h | 2 + 23 files changed, 825 insertions(+), 9 deletions(-) create mode 100644 Documentation/sparc/adi.txt create mode 100644 arch/sparc/include/asm/adi.h create mode 100644 arch/sparc/include/asm/adi_64.h create mode 100644 arch/sparc/kernel/adi_64.c diff --git a/Documentation/sparc/adi.txt b/Documentation/sparc/adi.txt new file mode 100644 index 000..93fb97e --- /dev/null +++ b/Documentation/sparc/adi.txt @@ -0,0 +1,292 @@ +Application Data Integrity (ADI) + + +SPARC M7 processor adds the Application Data Integrity (ADI) feature. +ADI allows a task to set version tags on any subset of its address +space. Once ADI is enabled and version tags are set for ranges of +address space of a task, the processor will compare the tag in pointers +to memory in these ranges to the version set by the
Re: [PATCH v5 4/4] sparc64: Add support for ADI (Application Data Integrity)
On 01/30/2017 03:15 PM, David Miller wrote: From: Khalid Aziz Date: Wed, 25 Jan 2017 12:57:16 -0700 +static inline void enable_adi(void) +{ ... + __asm__ __volatile__( + "rdpr %%pstate, %%g1\n\t" + "or %%g1, %0, %%g1\n\t" + "wrpr %%g1, %%g0, %%pstate\n\t" + ".word 0x83438000\n\t"/* rd %mcdper, %g1 */ + ".word 0xaf91\n\t"/* wrpr %g0, %g1, %pmcdper */ + : + : "i" (PSTATE_MCDE) + : "g1"); +} This is _crazy_ expensive. This is 4 privileged register operations, every single one incurs a full pipline flush and virtual cpu thread yield. And we do this around _every_ single userspace access from the kernel when the thread has ADI enabled. Hi Dave, Thanks for the feedback. This is very helpful. I checked and it indeed can cost 50+ cycles even on M7 processor for PSTATE accesses. I think if the kernel manages the ADI metadata properly, you can get rid of all of this. On etrap, you change ESTATE_PSTATE{1,2} to have the MCDE bit enabled. Then the kernel always runs with ADI enabled. Running the kernel with PSTATE.mcde=1 can possibly be problematic as we had discussed earlier in this thread where keeping PSTATE.mcde enabled might mean kernel having to keep track of which pages still have tags set on them or flush tags on every page on free. I will go through the code again to see if it PSTATE.mcde can be turned on in kernel all the time, which might be the case if we can ensure kernel accesses pages with TTE.mcd cleared. Furthermore, since the %mcdper register should be set to whatever the current task has asked for, you should be able to avoid touching it as well assuming that traps do not change %mcdper's value. When running in privileged mode, it is the value of %pmcdper that matter, not %mcdper, hence I added code to sync %pmcdper with %mcdper when entering privileged mode. Nevertheless, one of the HW designers has suggested I might be able to get away without having to futz with %pmcdper by using membar before exiting privileged mode which might still get me the same effect I am looking for without the cost. -- Khalid Then you don't need to do anything special during userspace accesses which seems to be the way this was designed to be used. -- To unsubscribe from this list: send the line "unsubscribe sparclinux" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v5 4/4] sparc64: Add support for ADI (Application Data Integrity)
On 01/25/2017 03:50 PM, Rob Gardner wrote: On 01/25/2017 03:20 PM, Khalid Aziz wrote: On 01/25/2017 03:00 PM, Rob Gardner wrote: On 01/25/2017 12:57 PM, Khalid Aziz wrote: @@ -157,6 +158,24 @@ int __get_user_pages_fast(unsigned long start, int nr_pages, int write, pgd_t *pgdp; int nr = 0; +#ifdef CONFIG_SPARC64 +if (adi_capable()) { +long addr = start; + +/* If userspace has passed a versioned address, kernel + * will not find it in the VMAs since it does not store + * the version tags in the list of VMAs. Storing version + * tags in list of VMAs is impractical since they can be + * changed any time from userspace without dropping into + * kernel. Any address search in VMAs will be done with + * non-versioned addresses. Ensure the ADI version bits + * are dropped here by sign extending the last bit before + * ADI bits. IOMMU does not implement version tags. + */ +addr = (addr << (long)adi_nbits()) >> (long)adi_nbits(); So you are depending on the sign extension to clear the ADI bits... but this only happens if there is a zero in that "last bit before ADI bits". If the last bit is a 1, then the ADI bits will be set instead of cleared. That seems like an unintended consequence given the comment. I am aware of the value of adi_nbits() and of the number of valid bits in a virtual address on the M7 processor, but wouldn't using 'unsigned long' for everything here guarantee the ADI bits get cleared regardless of the state of the last non-adi bit? Sign extension is the right thing to do. MMU considers values of 0 and 15 for bits 63-60 to be untagged addresses and expects bit 59 to be sign-extended for untagged virtual addresses. The code I added is explicitly meant to sign-extend, not zero out the top 4 bits. OK, that wasn't perfectly clear from the comment, which said "version bits are dropped". So sign extending will produce an address that the MMU can use, but will it produce an address that will allow a successful search in the page tables? ie, was this same sign extending done when first handing out that virtual address to the user? Yes to both your questions. When virtual addresses are handed out, the last implemented virtual address bit is sign-extended. Sign-extending when dropping version bits preserves that original sign-extension. This is why MMU considers tag values of 0 as well as 15 to be invalid because they both represent sign-extension of the last implemented virtual address. -- Khalid -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v5 4/4] sparc64: Add support for ADI (Application Data Integrity)
On 01/25/2017 03:00 PM, Rob Gardner wrote: On 01/25/2017 12:57 PM, Khalid Aziz wrote: @@ -157,6 +158,24 @@ int __get_user_pages_fast(unsigned long start, int nr_pages, int write, pgd_t *pgdp; int nr = 0; +#ifdef CONFIG_SPARC64 +if (adi_capable()) { +long addr = start; + +/* If userspace has passed a versioned address, kernel + * will not find it in the VMAs since it does not store + * the version tags in the list of VMAs. Storing version + * tags in list of VMAs is impractical since they can be + * changed any time from userspace without dropping into + * kernel. Any address search in VMAs will be done with + * non-versioned addresses. Ensure the ADI version bits + * are dropped here by sign extending the last bit before + * ADI bits. IOMMU does not implement version tags. + */ +addr = (addr << (long)adi_nbits()) >> (long)adi_nbits(); So you are depending on the sign extension to clear the ADI bits... but this only happens if there is a zero in that "last bit before ADI bits". If the last bit is a 1, then the ADI bits will be set instead of cleared. That seems like an unintended consequence given the comment. I am aware of the value of adi_nbits() and of the number of valid bits in a virtual address on the M7 processor, but wouldn't using 'unsigned long' for everything here guarantee the ADI bits get cleared regardless of the state of the last non-adi bit? Sign extension is the right thing to do. MMU considers values of 0 and 15 for bits 63-60 to be untagged addresses and expects bit 59 to be sign-extended for untagged virtual addresses. The code I added is explicitly meant to sign-extend, not zero out the top 4 bits. -- Khalid -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v5 0/4] Application Data Integrity feature introduced by SPARC M7
No changes - Patch 2/4: Replaced set_swp_pte_at() with new architecture functions arch_do_swap_page() and arch_unmap_one() that suppoprt architecture specific actions to be taken on page swap and migration - Patch 3/4: Fixed indentation issues in assembly code - Patch 4/4: - Fixed indentation issues and instrcuctions in assembly code - Removed CONFIG_SPARC64 from mdesc.c - Changed to maintain state of MCDPER register in thread info flags as opposed to in mm context. MCDPER is a per-thread state and belongs in thread info flag as opposed to mm context which is shared across threads. Added comments to clarify this is a lazily maintained state and must be updated on context switch and copy_process() - Updated code to use the new arch_do_swap_page() and arch_unmap_one() functions Testing: - All functionality was tested with 8K normal pages as well as hugepages using malloc, mmap and shm. - Multiple long duration stress tests were run using hugepages over 2+ months. Normal pages were tested with shorter duration stress tests. - Tested swapping with malloc and shm by reducing max memory and allocating three times the available system memory by active processes using ADI on allocated memory. Ran through multiple hour long runs of this test. - Tested page migration with malloc and shm by migrating data pages of active ADI test process using migratepages, back and forth between two nodes every few seconds over an hour long run. Verified page migration through /proc//numa_maps. Outstanding issues: - When sharing mmap'd ADI enabled areas with MAP_PRIVATE, copy-on-write results in a copy that does not have ADI enabled and ADI tags set. - Two processes sharing a mmap's ADI enabled area with MAP_SHARED must coordinate setting of ADI tags or else one process can cause the other to get SIGSEGV. I am working to solve these issues in subsequent patches. First issue can be resolved by mapping the new COW pages with ADI enabled and copy the ADI tags over to the new pages. This will increase the COW time since tags must be copied over one cacheline at a time. Second issue can possibly be solved by allowing only one task to mmap with write permission when the memory pages are ADI enabled. All subsequent mmap of this shared file would then be read-only mappings, or mprotect() with PROT_ADI would be denied for subsequent mappings if mapped pages have write permission. This would allow only one process to change ADI tags but that process can still cause the processes that have mmap'd read-only to crash if it changes ADI tags without coordinating the change with other processes. These ideas need to be explored more before implementing a fix. There are potential race conditions as well in the solution for second issue that will need to be evaluated and addressed. --- Khalid Aziz (4): signals, sparc: Add signal codes for ADI violations mm: Add functions to support extra actions on swap in/out sparc64: Add support for ADI register fields, ASIs and traps sparc64: Add support for ADI (Application Data Integrity) Documentation/sparc/adi.txt | 288 arch/sparc/include/asm/adi.h| 6 + arch/sparc/include/asm/adi_64.h | 46 + arch/sparc/include/asm/elf_64.h | 8 + arch/sparc/include/asm/hugetlb.h| 13 ++ arch/sparc/include/asm/hypervisor.h | 2 + arch/sparc/include/asm/mman.h | 40 - arch/sparc/include/asm/mmu_64.h | 1 + arch/sparc/include/asm/mmu_context_64.h | 43 + arch/sparc/include/asm/pgtable_64.h | 87 +- arch/sparc/include/asm/thread_info_64.h | 1 + arch/sparc/include/asm/ttable.h | 10 ++ arch/sparc/include/asm/uaccess_64.h | 120 - arch/sparc/include/uapi/asm/asi.h | 5 + arch/sparc/include/uapi/asm/auxvec.h| 8 + arch/sparc/include/uapi/asm/mman.h | 2 + arch/sparc/include/uapi/asm/pstate.h| 10 ++ arch/sparc/kernel/Makefile | 1 + arch/sparc/kernel/adi_64.c | 93 +++ arch/sparc/kernel/entry.h | 3 + arch/sparc/kernel/head_64.S | 1 + arch/sparc/kernel/mdesc.c | 2 + arch/sparc/kernel/process_64.c | 25 +++ arch/sparc/kernel/sun4v_mcd.S | 16 ++ arch/sparc/kernel/traps_64.c| 142 +++- arch/sparc/kernel/ttable_64.S | 6 +- arch/sparc/mm/gup.c | 37 arch/x86/kernel/signal_compat.c | 2 +- include/asm-generic/pgtable.h | 16 ++ include/linux/mm.h | 2 + include/uapi/asm-generic/siginfo.h |
[PATCH v5 4/4] sparc64: Add support for ADI (Application Data Integrity)
ADI is a new feature supported on SPARC M7 and newer processors to allow hardware to catch rogue accesses to memory. ADI is supported for data fetches only and not instruction fetches. An app can enable ADI on its data pages, set version tags on them and use versioned addresses to access the data pages. Upper bits of the address contain the version tag. On M7 processors, upper four bits (bits 63-60) contain the version tag. If a rogue app attempts to access ADI enabled data pages, its access is blocked and processor generates an exception. Please see Documentation/sparc/adi.txt for further details. This patch extends mprotect to enable ADI (TSTATE.mcde), enable/disable MCD (Memory Corruption Detection) on selected memory ranges, enable TTE.mcd in PTEs, return ADI parameters to userspace and save/restore ADI version tags on page swap out/in or migration. It also adds handlers for traps related to MCD. ADI is not enabled by default for any task. A task must explicitly enable ADI on a memory range and set version tag for ADI to be effective for the task. This initial implementation supports saving and restoring one tag per page. A page must use same version tag across the entire page for the tag to survive swap and migration. Swap swupport infrastructure in this patch allows for this capability to be expanded to store/restore more than one tag per page in future. Signed-off-by: Khalid Aziz Cc: Khalid Aziz --- v5: - Fixed indentation issues and instrcuctions in assembly code - Removed CONFIG_SPARC64 from mdesc.c - Changed to maintain state of MCDPER register in thread info flags as opposed to in mm context. MCDPER is a per-thread state and belongs in thread info flag as opposed to mm context which is shared across threads. Added comments to clarify this is a lazily maintained state and must be updated on context switch and copy_process() - Updated code to use the new arch_do_swap_page() and arch_unmap_one() functions v4: - Broke patch up into smaller patches v3: - Removed CONFIG_SPARC_ADI - Replaced prctl commands with mprotect - Added auxiliary vectors for ADI parameters - Enabled ADI for swappable pages v2: - Fixed a build error Documentation/sparc/adi.txt | 288 arch/sparc/include/asm/adi.h| 6 + arch/sparc/include/asm/adi_64.h | 46 + arch/sparc/include/asm/elf_64.h | 8 + arch/sparc/include/asm/hugetlb.h| 13 ++ arch/sparc/include/asm/mman.h | 40 - arch/sparc/include/asm/mmu_64.h | 1 + arch/sparc/include/asm/mmu_context_64.h | 43 + arch/sparc/include/asm/pgtable_64.h | 85 +- arch/sparc/include/asm/thread_info_64.h | 1 + arch/sparc/include/asm/uaccess_64.h | 120 - arch/sparc/include/uapi/asm/auxvec.h| 8 + arch/sparc/include/uapi/asm/mman.h | 2 + arch/sparc/kernel/Makefile | 1 + arch/sparc/kernel/adi_64.c | 93 +++ arch/sparc/kernel/mdesc.c | 2 + arch/sparc/kernel/process_64.c | 25 +++ arch/sparc/kernel/traps_64.c| 88 +- arch/sparc/mm/gup.c | 37 include/linux/mm.h | 2 + 20 files changed, 897 insertions(+), 12 deletions(-) create mode 100644 Documentation/sparc/adi.txt create mode 100644 arch/sparc/include/asm/adi.h create mode 100644 arch/sparc/include/asm/adi_64.h create mode 100644 arch/sparc/kernel/adi_64.c diff --git a/Documentation/sparc/adi.txt b/Documentation/sparc/adi.txt new file mode 100644 index 000..1740f8a --- /dev/null +++ b/Documentation/sparc/adi.txt @@ -0,0 +1,288 @@ +Application Data Integrity (ADI) + + +SPARC M7 processor adds the Application Data Integrity (ADI) feature. +ADI allows a task to set version tags on any subset of its address +space. Once ADI is enabled and version tags are set for ranges of +address space of a task, the processor will compare the tag in pointers +to memory in these ranges to the version set by the application +previously. Access to memory is granted only if the tag in given +pointer matches the tag set by the application. In case of mismatch, +processor raises an exception. + +Following steps must be taken by a task to enable ADI fully: + +1. Set the user mode PSTATE.mcde bit. This acts as master switch for + the task's entire address space to enable/disable ADI for the task. + +2. Set TTE.mcd bit on any TLB entries that correspond to the range of + addresses ADI is being enabled on. MMU checks the version tag only + on the pages that have TTE.mcd bit set. + +3. Set the version tag for virtual addresses using stxa instruction + and one of the MCD specific ASIs. Each stxa instruction sets the + given tag for one ADI block size number of bytes. This
Re: [PATCH v4 4/4] sparc64: Add support for ADI (Application Data Integrity)
On 01/16/2017 09:39 PM, David Miller wrote: From: Khalid Aziz Date: Wed, 11 Jan 2017 09:12:54 -0700 diff --git a/arch/sparc/kernel/mdesc.c b/arch/sparc/kernel/mdesc.c index 8a6982d..68b03bf 100644 --- a/arch/sparc/kernel/mdesc.c +++ b/arch/sparc/kernel/mdesc.c @@ -20,6 +20,7 @@ #include #include #include +#include /* Unlike the OBP device tree, the machine description is a full-on * DAG. An arbitrary number of ARCs are possible from one @@ -1104,5 +1105,8 @@ void __init sun4v_mdesc_init(void) cur_mdesc = hp; +#ifdef CONFIG_SPARC64 mdesc.c is only built on sparc64, this ifdef is superfluous. Good point. I will fix it. +/* Update the state of MCDPER register in current task's mm context before + * dup so the dup'd task will inherit flags in this register correctly. + * Current task may have updated flags since it started running. + */ +int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) +{ + if (adi_capable() && src->mm) { + register unsigned long tmp_mcdper; + + __asm__ __volatile__( + ".word 0x83438000\n\t"/* rd %mcdper, %g1 */ + "mov %%g1, %0\n\t" + : "=r" (tmp_mcdper) + : + : "g1"); + src->mm->context.mcdper = tmp_mcdper; I don't like the idea of duplicating 'mm' state using the task struct copy. Why do not the MM handling interfaces handle this properly? Maybe it means you've abstracted the ADI register handling in the wrong place. Maybe it's a thread property which is "pushed" from the MM context. I see what you are saying. This code updates mm->context.mcdper for the source thread with the current state of MCDPER since MCDPER can be changed by a userspace process any time. When userspace changes MCDPER, it is not saved into mm->context.mcdper until a context switch happens. This means during the timeslice for a thread, its mm->context.mcdper may not reflect the current value of MCDPER. Updating it ensures dup_mm() will copy the real current value of MCDPER into the newly forked thread. arch_dup_mmap() looks like a more appropriate place to do this. Do you agree? Thanks, Khalid -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v4 0/4] Application Data Integrity feature introduced by SPARC M7
On 01/16/2017 09:47 PM, David Miller wrote: From: Dave Hansen Date: Wed, 11 Jan 2017 10:13:54 -0800 For memory shared by two different processes, do they have to agree on what the tags are, or can they differ? Whoever allocates the memory (does the mmap()+mprotect() or whatever), decides on the tag. They set it, and this determines which virtual address is valid to access that mapping. It's like kmalloc() returns pointers with some weird bits set in the upper bits of the address. Behind the scenes kmalloc() sets the TAG bits appropriately. It doesn't, in that sense, matter where in the non-tagged virtual address space the memory is mapped. All that matters is that, for a given page, the TAG bits in the virtual address used for loads and stores to that mapping are set properly. I think the fundamental thing being missed is that the TAG bits in the virtual address are not interpreted by the TLB. They are chopped off before virtual address translation occurs. The TAG bits of the virtual address serve only to indicate what ADI value the load or store thinks is valid to use for access to that piece of memory. Or something like that... :-) Hi David, Your explanation is spot on. MMU looks at the tag bits only to determine if the process has permission to access the memory address. Tag bits are not part of VA->PA translation. The tags are stored in physical memory though and MMU compares the tag stored at physical address obtained from TLB translation to the tag embedded in VA. What that means is if two processes map the same physical page in their address space, they both must embed the same tag in the VA they present to MMU irrespective of where in each process' address space the page is mapped in. If one process changes the tag, stored in physical memory, the other process must also embed the new tag in its VA when accessing this shared mapped page. This is something to consider because a tag can be set and changed entirely from userspace with no kernel involvement as long as the process has write access to memory. -- Khalid -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v4 4/4] sparc64: Add support for ADI (Application Data Integrity)
On 01/17/2017 12:42 PM, David Miller wrote: From: Khalid Aziz Date: Tue, 17 Jan 2017 12:32:46 -0700 On 01/16/2017 09:39 PM, David Miller wrote: From: Khalid Aziz Date: Wed, 11 Jan 2017 09:12:54 -0700 + __asm__ __volatile__( + ".word 0xa1438000\n\t"/* rd %mcdper, %l0 */ Just use "rd %%asr14, %0" this way you don't have to play all of these fixed register games which kill the code generated by gcc. If you forcefully clobber a windowed register like %l0 it means the function being emitted can never be a leaf function, tail calls are no longer allowed, etc. Hi David, "rd %%asr14, %0" should work but does not due to bugs in assembler - <https://sourceware.org/ml/binutils/2016-03/msg00302.html>, and <https://sourceware.org/ml/binutils/2016-03/msg00303.html>. These bugs were fixed in binutils 2.27 but older assemblers will cause kernel build to fail. Using byte coded equivalent is the safest option. Fair enough. Then please at least use %g1 or another usable global register to avoid at least some of the problems I mentioned. Sure, I will do that. Thanks for the review and feedback. -- Khalid -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v4 4/4] sparc64: Add support for ADI (Application Data Integrity)
On 01/16/2017 09:39 PM, David Miller wrote: From: Khalid Aziz Date: Wed, 11 Jan 2017 09:12:54 -0700 + __asm__ __volatile__( + ".word 0xa1438000\n\t"/* rd %mcdper, %l0 */ Just use "rd %%asr14, %0" this way you don't have to play all of these fixed register games which kill the code generated by gcc. If you forcefully clobber a windowed register like %l0 it means the function being emitted can never be a leaf function, tail calls are no longer allowed, etc. Hi David, "rd %%asr14, %0" should work but does not due to bugs in assembler - <https://sourceware.org/ml/binutils/2016-03/msg00302.html>, and <https://sourceware.org/ml/binutils/2016-03/msg00303.html>. These bugs were fixed in binutils 2.27 but older assemblers will cause kernel build to fail. Using byte coded equivalent is the safest option. + ".word 0x9d800011\n\t"/* wr %g0, %l1, %mcdper */ Likewise use "wr %%g0, %0, %%asr14" + ".word 0xaf91\n\t"/* wrpr %g0, %g1, %pmcdper */ Hmmm, which %asr encodes %pmcdper? %pmcdper is not an asr, rather a privileged register (pr23). Thanks, Khalid diff --git a/arch/sparc/kernel/mdesc.c b/arch/sparc/kernel/mdesc.c index 8a6982d..68b03bf 100644 --- a/arch/sparc/kernel/mdesc.c +++ b/arch/sparc/kernel/mdesc.c @@ -20,6 +20,7 @@ #include #include #include +#include /* Unlike the OBP device tree, the machine description is a full-on * DAG. An arbitrary number of ARCs are possible from one @@ -1104,5 +1105,8 @@ void __init sun4v_mdesc_init(void) cur_mdesc = hp; +#ifdef CONFIG_SPARC64 mdesc.c is only built on sparc64, this ifdef is superfluous. +/* Update the state of MCDPER register in current task's mm context before + * dup so the dup'd task will inherit flags in this register correctly. + * Current task may have updated flags since it started running. + */ +int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) +{ + if (adi_capable() && src->mm) { + register unsigned long tmp_mcdper; + + __asm__ __volatile__( + ".word 0x83438000\n\t"/* rd %mcdper, %g1 */ + "mov %%g1, %0\n\t" + : "=r" (tmp_mcdper) + : + : "g1"); + src->mm->context.mcdper = tmp_mcdper; I don't like the idea of duplicating 'mm' state using the task struct copy. Why do not the MM handling interfaces handle this properly? Maybe it means you've abstracted the ADI register handling in the wrong place. Maybe it's a thread property which is "pushed" from the MM context. -- To unsubscribe from this list: send the line "unsubscribe sparclinux" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v4 0/4] Application Data Integrity feature introduced by SPARC M7
On 01/13/2017 08:29 AM, Rob Gardner wrote: On 01/13/2017 07:48 AM, Khalid Aziz wrote: On 01/12/2017 06:31 PM, Rob Gardner wrote: On 01/12/2017 05:22 PM, Khalid Aziz wrote: On 01/12/2017 10:53 AM, Dave Hansen wrote: On 01/12/2017 08:50 AM, Khalid Aziz wrote: 2. Any shared page that has ADI protection enabled on it, must stay ADI protected across all processes sharing it. Is that true? What happens if a page with ADI tags set is accessed via a PTE without the ADI enablement bit set? ADI protection applies across all processes in terms of all of them must use the same tag to access the shared memory, but if a process accesses a shared page with TTE.mcde bit cleared, access will be granted. COW creates an intersection of the two. It creates a new copy of the shared data. It is a new data page and hence the process creating it must be the one responsible for enabling ADI protection on it. Do you mean that the application must be responsible? Or the kernel running in the context of the new process must be responsible? It is also a copy of what was ADI protected data, so should it inherit the protection instead? I think the COW'd copy must inherit the VMA bit, the PTE bits, and the tags on the cachelines. I misspoke earlier. I had misinterpreted the results of test I ran. Changing the tag on shared memory is allowed by memory controller. The requirement is every one sharing the page must switch to the new tag or else they get SIGSEGV. I asked this in the last mail, but I guess I'll ask it again. Please answer this directly. If we require that everyone coordinate their tags on the backing physical memory, and we allow a lower-privileged program to access the same data as a more-privileged one, then the lower-privilege app can cause arbitrary crashes in the privileged application. For instance, say sudo mmap()'s /etc/passwd and uses ADI tags to protect the mapping. Couldn't any other app in the system prevent sudo from working? How can we *EVER* allow tags to be set on non-writable mappings? I don't think you can write a tag to memory if you don't have write access in the TTE. Writing a tag requires a store instruction, and if the machine is at all sane, this will fault if you don't have write access. But could you have mmap'd the file writable, set the tags and then changed the protection on memory to read-only? That would be the logical way to ADI protect a memory being used to mmap a file. Right? Sure, if you have write access to begin with, you can set memory versions, then remove write access to the page. But I think the point is that if a process doesn't have write access, and cannot get it, then it will not ever be able to change memory versions. So in the example of a non-root process opening /etc/passwd (read only), and mmaping it, the mapping would be read-only as well. Personally I don't really see a use case for ADI on memory mapped to a file. In an abstract sense, the "backing store" for a memory mapped file is the file itself on disk, not physical memory. And there is already a way to restrict access to files, so perhaps ADI should simply be disallowed for memory mapped to files, and this particular complication can be avoided. Thoughts? Hi Rob, That is a good way to look at it. Memory mapped files already have a protection mechanism in place. Incidentally, I see ADI as primarily a way to protect memory from improper access within a process or group of cooperating processes. There is already a way to protect memory from unrelated processes, and if that is circumvented somehow, then ADI won't help at all. Perhaps we should stop talking about ADI as a "security" feature; It does add a layer of protection against buffer overflow attacks, but this attack only exists when there is a bug in the underlying application. If an attacker gains access to the virtual memory for a process, then nothing can help you. That does make sense. Looking at ADI as a mechanism to prevent unintended improper access to memory through buffer overflow or other mechanism, would it still make sense to support ADI tags on mmap'd files within the group of cooperating processes? Say we have a process that mmap's a large file and then forks off a bunch of children that process smaller segments of that file. We would want to make sure these children do not step over each other's segments of the file due to programming flaw or compromise. Parent process could tag each segment with a different tag and give one tag to each child process. I want to be sure we are not shutting down potential useful applications of ADI before we choose to not support ADI with memory mapped files. I appreciate your input. Thanks, Khalid Rob -- Khalid Rob I understand your quetion better now. That is a very valid concern. Using ADI tags to prevent an unauthorized process from just reading data
Re: [PATCH v4 0/4] Application Data Integrity feature introduced by SPARC M7
On 01/12/2017 06:31 PM, Rob Gardner wrote: On 01/12/2017 05:22 PM, Khalid Aziz wrote: On 01/12/2017 10:53 AM, Dave Hansen wrote: On 01/12/2017 08:50 AM, Khalid Aziz wrote: 2. Any shared page that has ADI protection enabled on it, must stay ADI protected across all processes sharing it. Is that true? What happens if a page with ADI tags set is accessed via a PTE without the ADI enablement bit set? ADI protection applies across all processes in terms of all of them must use the same tag to access the shared memory, but if a process accesses a shared page with TTE.mcde bit cleared, access will be granted. COW creates an intersection of the two. It creates a new copy of the shared data. It is a new data page and hence the process creating it must be the one responsible for enabling ADI protection on it. Do you mean that the application must be responsible? Or the kernel running in the context of the new process must be responsible? It is also a copy of what was ADI protected data, so should it inherit the protection instead? I think the COW'd copy must inherit the VMA bit, the PTE bits, and the tags on the cachelines. I misspoke earlier. I had misinterpreted the results of test I ran. Changing the tag on shared memory is allowed by memory controller. The requirement is every one sharing the page must switch to the new tag or else they get SIGSEGV. I asked this in the last mail, but I guess I'll ask it again. Please answer this directly. If we require that everyone coordinate their tags on the backing physical memory, and we allow a lower-privileged program to access the same data as a more-privileged one, then the lower-privilege app can cause arbitrary crashes in the privileged application. For instance, say sudo mmap()'s /etc/passwd and uses ADI tags to protect the mapping. Couldn't any other app in the system prevent sudo from working? How can we *EVER* allow tags to be set on non-writable mappings? I don't think you can write a tag to memory if you don't have write access in the TTE. Writing a tag requires a store instruction, and if the machine is at all sane, this will fault if you don't have write access. But could you have mmap'd the file writable, set the tags and then changed the protection on memory to read-only? That would be the logical way to ADI protect a memory being used to mmap a file. Right? -- Khalid Rob I understand your quetion better now. That is a very valid concern. Using ADI tags to prevent an unauthorized process from just reading data in memory, say an in-memory copy of database, is one of the use cases for ADI. This means there is a reasonable case to allow enabling ADI and setting tags even on non-writable mappings. On the other hand, if an unauthorized process manages to map the right memory pages in its address space, it can read them any way by not setting TTE.mcd. Userspace app can set tag on any memory it has mapped in without requiring assistance from kernel. Can this problem be solved by not allowing setting TTE.mcd on non-writable mappings? Doesn't the same problem occur on writable mappings? If a privileged process mmap()'s a writable file with MAP_SHARED, enables ADI and sets tag on the mmap'd memory region, then another lower privilege process mmap's the same file writable (assuming file permissions allow it to), enables ADI and sets a different tag on it, the privileged process would get SIGSEGV when it tries to access the mmap'd file. Right? -- To unsubscribe from this list: send the line "unsubscribe sparclinux" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v4 0/4] Application Data Integrity feature introduced by SPARC M7
On 01/12/2017 10:53 AM, Dave Hansen wrote: On 01/12/2017 08:50 AM, Khalid Aziz wrote: 2. Any shared page that has ADI protection enabled on it, must stay ADI protected across all processes sharing it. Is that true? What happens if a page with ADI tags set is accessed via a PTE without the ADI enablement bit set? ADI protection applies across all processes in terms of all of them must use the same tag to access the shared memory, but if a process accesses a shared page with TTE.mcde bit cleared, access will be granted. COW creates an intersection of the two. It creates a new copy of the shared data. It is a new data page and hence the process creating it must be the one responsible for enabling ADI protection on it. Do you mean that the application must be responsible? Or the kernel running in the context of the new process must be responsible? It is also a copy of what was ADI protected data, so should it inherit the protection instead? I think the COW'd copy must inherit the VMA bit, the PTE bits, and the tags on the cachelines. I misspoke earlier. I had misinterpreted the results of test I ran. Changing the tag on shared memory is allowed by memory controller. The requirement is every one sharing the page must switch to the new tag or else they get SIGSEGV. I asked this in the last mail, but I guess I'll ask it again. Please answer this directly. If we require that everyone coordinate their tags on the backing physical memory, and we allow a lower-privileged program to access the same data as a more-privileged one, then the lower-privilege app can cause arbitrary crashes in the privileged application. For instance, say sudo mmap()'s /etc/passwd and uses ADI tags to protect the mapping. Couldn't any other app in the system prevent sudo from working? How can we *EVER* allow tags to be set on non-writable mappings? I understand your quetion better now. That is a very valid concern. Using ADI tags to prevent an unauthorized process from just reading data in memory, say an in-memory copy of database, is one of the use cases for ADI. This means there is a reasonable case to allow enabling ADI and setting tags even on non-writable mappings. On the other hand, if an unauthorized process manages to map the right memory pages in its address space, it can read them any way by not setting TTE.mcd. Userspace app can set tag on any memory it has mapped in without requiring assistance from kernel. Can this problem be solved by not allowing setting TTE.mcd on non-writable mappings? Doesn't the same problem occur on writable mappings? If a privileged process mmap()'s a writable file with MAP_SHARED, enables ADI and sets tag on the mmap'd memory region, then another lower privilege process mmap's the same file writable (assuming file permissions allow it to), enables ADI and sets a different tag on it, the privileged process would get SIGSEGV when it tries to access the mmap'd file. Right? Thanks, Khalid -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v4 0/4] Application Data Integrity feature introduced by SPARC M7
On 01/11/2017 05:49 PM, Dave Hansen wrote: On 01/11/2017 04:22 PM, Khalid Aziz wrote: ... All of the tag coordination can happen in userspace. Once a process sets a tag on a physical page mapped in its address space, another process that has mapped the same physical page in its address space can only set the tag to exact same value. Attempts to set a different tag are caught by memory controller and result in MCD trap and kernel sends SIGSEGV to the process trying to set a different tag. Again, I don't think these semantics will work for anything other than explicitly shared memory. This behavior ensures that it is *entirely* unsafe to use ADI on any data that any process you do not control might be able to mmap(). That's a *HUGE* caveat for the feature and can't imagine ever seeing this get merged without addressing it. I think it's fairly simple to address, though a bit expensive. First, you can't allow the VMA bit to get set on non-writable mappings. Second, you'll have to force COW to occur on read-only pages in writable mappings before the PTE bit can get set. I think you can probably even do this in the faults that presumably occur when you try to set ADI tags on memory mapped with non-ADI PTEs. Hi Dave, You have brought up an interesting scenario with COW pages. I had started out with the following policies regarding ADI that made sense: 1. New data pages do not get full ADI protection by default, i.e. TTE.mcd is not set and tags are not set on the new pages. A task that creates a new data page must make decision to protect these new pages or not. 2. Any shared page that has ADI protection enabled on it, must stay ADI protected across all processes sharing it. COW creates an intersection of the two. It creates a new copy of the shared data. It is a new data page and hence the process creating it must be the one responsible for enabling ADI protection on it. It is also a copy of what was ADI protected data, so should it inherit the protection instead? I misspoke earlier. I had misinterpreted the results of test I ran. Changing the tag on shared memory is allowed by memory controller. The requirement is every one sharing the page must switch to the new tag or else they get SIGSEGV. I am inclined to suggest we copy the tags to the new data page on COW and that will continue to enforce ADI on the COW'd pages even though COW'd pages are new data pages. This is the logically consistent behavior. Does that make sense? Thanks, Khalid -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v4 0/4] Application Data Integrity feature introduced by SPARC M7
On 01/11/2017 12:11 PM, Dave Hansen wrote: On 01/11/2017 10:50 AM, Khalid Aziz wrote: On 01/11/2017 11:13 AM, Dave Hansen wrote: On 01/11/2017 08:56 AM, Khalid Aziz wrote: For memory shared by two different processes, do they have to agree on what the tags are, or can they differ? The two processes have to agree on the tag. This is part of the security design to prevent other processes from accessing pages belonging to another process unless they know the tag set on those pages. So what do you do with static data, say from a shared executable? You need to ensure that two different processes from two different privilege domains can't set different tags on the same physical memory. That would seem to mean that you must not allow tags to be set of memory unless you have write access to it. Or, you have to ensure that any file that you might want to use this feature on is entirely unreadable (well, un-mmap()-able really) by anybody that you are not coordinating with. All of the tag coordination can happen in userspace. Once a process sets a tag on a physical page mapped in its address space, another process that has mapped the same physical page in its address space can only set the tag to exact same value. Attempts to set a different tag are caught by memory controller and result in MCD trap and kernel sends SIGSEGV to the process trying to set a different tag. If you want to use it on copy-on-write'able data, you've got to ensure that you've got entirely private copies. I'm not sure we even have an interface to guarantee that. How could this work after a fork() on un-COW'd, but COW'able data? On COW, kernel maps the the source and destination pages with kmap_atomic() and copies the data over to the new page and the new page wouldn't be ADI protected unless the child process chooses to do so. This wouldn't change with ADI as far as private copies are concerned. Please do correct me if I get something wrong here. Quick tests with COW data show everything working as expected but your asking about COW has raised a few questions in my own mind. I am researching through docs and running experiments to validate my thinking and I will give you more definite information on whether COW would mess ADI up. Thanks, Khalid -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v4 0/4] Application Data Integrity feature introduced by SPARC M7
On 01/11/2017 11:13 AM, Dave Hansen wrote: On 01/11/2017 08:56 AM, Khalid Aziz wrote: On 01/11/2017 09:33 AM, Dave Hansen wrote: On 01/11/2017 08:12 AM, Khalid Aziz wrote: A userspace task enables ADI through mprotect(). This patch series adds a page protection bit PROT_ADI and a corresponding VMA flag VM_SPARC_ADI. VM_SPARC_ADI is used to trigger setting TTE.mcd bit in the sparc pte that enables ADI checking on the corresponding page. Is there a cost in the hardware associated with doing this "ADI checking"? For instance, instead of having this new mprotect() interface, why not just always set TTE.mcd on all PTEs? There is no performance penalty in the MMU to check tags, but if PSTATE.mcd bit is set and TTE.mcde is set, the tag in VA must match what was set on the physical page for all memory accesses. OK, then I'm misunderstanding the architecture again. For memory shared by two different processes, do they have to agree on what the tags are, or can they differ? The two processes have to agree on the tag. This is part of the security design to prevent other processes from accessing pages belonging to another process unless they know the tag set on those pages. Potential for side effects is too high in such case and would require kernel to either track tags for every page as they are re-allocated or migrated, or scrub pages constantly to ensure we do not get spurious tag mismatches. Unless there is a very strong reason to blindly set TTE.mcd on every PTE, I think the risk of instability is too high without lot of extra code. Ahh, ok. That makes sense. Clearing the tags is expensive. We must either clear tags or know the previous tags of the memory before we access it. Are any of the tags special? Do any of them mean "don't do any checking", or similar? Tag values of 0 and 15 can be considered special. Setting tag to 15 on memory range is disallowed. Accessing a memory location whose tag is cleared (means set to 0) with any tag value in the VA is allowed. Once a tag is set on a memory, and PSTATE.mcde and TTE.mcd are set, there isn't a tag that can be used to bypass version check by MMU. Thanks, Khalid -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v4 0/4] Application Data Integrity feature introduced by SPARC M7
On 01/11/2017 09:33 AM, Dave Hansen wrote: On 01/11/2017 08:12 AM, Khalid Aziz wrote: A userspace task enables ADI through mprotect(). This patch series adds a page protection bit PROT_ADI and a corresponding VMA flag VM_SPARC_ADI. VM_SPARC_ADI is used to trigger setting TTE.mcd bit in the sparc pte that enables ADI checking on the corresponding page. Is there a cost in the hardware associated with doing this "ADI checking"? For instance, instead of having this new mprotect() interface, why not just always set TTE.mcd on all PTEs? There is no performance penalty in the MMU to check tags, but if PSTATE.mcd bit is set and TTE.mcde is set, the tag in VA must match what was set on the physical page for all memory accesses. Potential for side effects is too high in such case and would require kernel to either track tags for every page as they are re-allocated or migrated, or scrub pages constantly to ensure we do not get spurious tag mismatches. Unless there is a very strong reason to blindly set TTE.mcd on every PTE, I think the risk of instability is too high without lot of extra code. Also, should this be a privileged interface in some way? The hardware is storing these tags *somewhere* and that storage is consuming resources *somewhere*. What stops a crafty attacker from mmap()'ing a 128TB chunk of the zero pages and storing ADI tags for all of it? That'll be 128TB/64*4bits = 1TB worth of 4-bit tags. Page tables, for instance, consume a comparable amount of storage, but the OS *knows* about those and can factor them into OOM decisions. Hardware resources used to store tags are managed entirely by MMU and invisible to the kernel. Tags are stored in spare bits in memory. The only tag resource consumption visible to OS will be the space it allocates to store tags as pages are swapped in/out or migrated. If we choose to implement subpage granularity for tags in future, resource consumption will be a concern. You are right, each n pages of tagged memory requires n/128 pages to store tags. Since each tag is just 4 bits, there are good possibilities to compress this data but that is for future. Thanks, Khalid -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v4 4/4] sparc64: Add support for ADI (Application Data Integrity)
ADI is a new feature supported on SPARC M7 and newer processors to allow hardware to catch rogue accesses to memory. ADI is supported for data fetches only and not instruction fetches. An app can enable ADI on its data pages, set version tags on them and use versioned addresses to access the data pages. Upper bits of the address contain the version tag. On M7 processors, upper four bits (bits 63-60) contain the version tag. If a rogue app attempts to access ADI enabled data pages, its access is blocked and processor generates an exception. Please see Documentation/sparc/adi.txt for further details. This patch extends mprotect to enable ADI (TSTATE.mcde), enable/disable MCD (Memory Corruption Detection) on selected memory ranges, enable TTE.mcd in PTEs, return ADI parameters to userspace and save/restore ADI version tags on page swap out/in or migration. It also adds handlers for traps related to MCD. ADI is not enabled by default for any task. A task must explicitly enable ADI on a memory range and set version tag for ADI to be effective for the task. This initial implementation supports saving and restoring one tag per page. A page must use same version tag across the entire page for the tag to survive swap and migration. Swap swupport infrastructure in this patch allows for this capability to be expanded to store/restore more than one tag per page in future. Signed-off-by: Khalid Aziz Cc: Khalid Aziz --- v2: - Fixed a build error v3: - Removed CONFIG_SPARC_ADI - Replaced prctl commands with mprotect - Added auxiliary vectors for ADI parameters - Enabled ADI for swappable pages Documentation/sparc/adi.txt | 288 arch/sparc/include/asm/adi.h| 6 + arch/sparc/include/asm/adi_64.h | 46 + arch/sparc/include/asm/elf_64.h | 8 + arch/sparc/include/asm/hugetlb.h| 13 ++ arch/sparc/include/asm/mman.h | 40 - arch/sparc/include/asm/mmu_64.h | 2 + arch/sparc/include/asm/mmu_context_64.h | 32 arch/sparc/include/asm/pgtable_64.h | 94 ++- arch/sparc/include/asm/uaccess_64.h | 120 - arch/sparc/include/uapi/asm/auxvec.h| 8 + arch/sparc/include/uapi/asm/mman.h | 2 + arch/sparc/kernel/Makefile | 1 + arch/sparc/kernel/adi_64.c | 93 +++ arch/sparc/kernel/mdesc.c | 4 + arch/sparc/kernel/process_64.c | 21 +++ arch/sparc/kernel/traps_64.c| 88 +- arch/sparc/mm/gup.c | 37 arch/sparc/mm/tlb.c | 28 include/linux/mm.h | 2 + 20 files changed, 921 insertions(+), 12 deletions(-) create mode 100644 Documentation/sparc/adi.txt create mode 100644 arch/sparc/include/asm/adi.h create mode 100644 arch/sparc/include/asm/adi_64.h create mode 100644 arch/sparc/kernel/adi_64.c diff --git a/Documentation/sparc/adi.txt b/Documentation/sparc/adi.txt new file mode 100644 index 000..ab3cd7f --- /dev/null +++ b/Documentation/sparc/adi.txt @@ -0,0 +1,288 @@ +Application Data Integrity (ADI) + + +SPARC M7 processor adds the Application Data Integrity (ADI) feature. +ADI allows a task to set version tags on any subset of its address +space. Once ADI is enabled and version tags are set for ranges of +address space of a task, the processor will compare the tag in pointers +to memory in these ranges to the version set by the application +previously. Access to memory is granted only if the tag in given +pointer matches the tag set by the application. In case of mismatch, +processor raises an exception. + +Following steps must be taken by a task to enable ADI fully: + +1. Set the user mode PSTATE.mcde bit. This acts as master switch for + the task's entire address space to enable/disable ADI for the task. + +2. Set TTE.mcd bit on any TLB entries that correspond to the range of + addresses ADI is being enabled on. MMU checks the version tag only + on the pages that have TTE.mcd bit set. + +3. Set the version tag for virtual addresses using stxa instruction + and one of the MCD specific ASIs. Each stxa instruction sets the + given tag for one ADI block size number of bytes. This step must + be repeated for entire page to set tags for entire page. + +ADI block size for the platform is provided by the hypervisor to the +kernel in machine description tables. Hypervisor also provides the +number of top bits in the virtual address that specify the version tag. +Once version tag has been set for a memory location, the tag is stored +in the physical memory and the same tag must be present in the ADI +version tag bits of the virtual address being presented to the MMU. For +example on SPARC M7 processor, MMU uses bits 63-60 for version tags and +ADI block size is same as cacheline size which is 64 bytes. A task that +sets ADI versi
[PATCH v4 0/4] Application Data Integrity feature introduced by SPARC M7
was tested with 8K normal pages as well as hugepages using malloc, mmap and shm. - Multiple long duration stress tests were run using hugepages over 2+ months. Normal pages were tested with shorter duration stress tests. - Tested swapping with malloc and shm by reducing max memory and allocating three times the available system memory by active processes using ADI on allocated memory. Ran through multiple hour long runs of this test. - Tested page migration with malloc and shm by migrating data pages of active ADI test process using migratepages, back and forth between two nodes every few seconds over an hour long run. Verified page migration through /proc//numa_maps. --- Khalid Aziz (4): signals, sparc: Add signal codes for ADI violations mm: Add function to support extra actions on swap in/out sparc64: Add support for ADI register fields, ASIs and traps sparc64: Add support for ADI (Application Data Integrity) Documentation/sparc/adi.txt | 288 arch/sparc/include/asm/adi.h| 6 + arch/sparc/include/asm/adi_64.h | 46 + arch/sparc/include/asm/elf_64.h | 8 + arch/sparc/include/asm/hugetlb.h| 13 ++ arch/sparc/include/asm/hypervisor.h | 2 + arch/sparc/include/asm/mman.h | 40 - arch/sparc/include/asm/mmu_64.h | 2 + arch/sparc/include/asm/mmu_context_64.h | 32 arch/sparc/include/asm/pgtable_64.h | 96 ++- arch/sparc/include/asm/ttable.h | 10 ++ arch/sparc/include/asm/uaccess_64.h | 120 - arch/sparc/include/uapi/asm/asi.h | 5 + arch/sparc/include/uapi/asm/auxvec.h| 8 + arch/sparc/include/uapi/asm/mman.h | 2 + arch/sparc/include/uapi/asm/pstate.h| 10 ++ arch/sparc/kernel/Makefile | 1 + arch/sparc/kernel/adi_64.c | 93 +++ arch/sparc/kernel/entry.h | 3 + arch/sparc/kernel/head_64.S | 1 + arch/sparc/kernel/mdesc.c | 4 + arch/sparc/kernel/process_64.c | 21 +++ arch/sparc/kernel/sun4v_mcd.S | 16 ++ arch/sparc/kernel/traps_64.c| 142 +++- arch/sparc/kernel/ttable_64.S | 6 +- arch/sparc/mm/gup.c | 37 arch/sparc/mm/tlb.c | 28 arch/x86/kernel/signal_compat.c | 2 +- include/asm-generic/pgtable.h | 5 + include/linux/mm.h | 2 + include/uapi/asm-generic/siginfo.h | 5 +- mm/memory.c | 2 +- mm/rmap.c | 4 +- 33 files changed, 1041 insertions(+), 19 deletions(-) create mode 100644 Documentation/sparc/adi.txt create mode 100644 arch/sparc/include/asm/adi.h create mode 100644 arch/sparc/include/asm/adi_64.h create mode 100644 arch/sparc/kernel/adi_64.c create mode 100644 arch/sparc/kernel/sun4v_mcd.S -- 2.7.4 -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC PATCH v3] sparc64: Add support for Application Data Integrity (ADI)
On 01/06/2017 10:54 AM, Rob Gardner wrote: On 01/06/2017 09:10 AM, Khalid Aziz wrote: On 01/06/2017 10:02 AM, David Miller wrote: From: Dave Hansen Date: Fri, 6 Jan 2017 08:55:03 -0800 Actually, that reminds me... How does your code interface with ksm? Or is there no interaction needed since you're always working on virtual addresses? This reminds me, I consider this feature potentially extremely useful for kernel debugging. So I would like to make sure we don't implement anything in a way which would preclude that in the long term. I agree and please do point out if I have made any implementation decisions that could preclude that. Thanks, Khalid Khalid, I have already pointed out an implementation decision that interferes with the potential for kernel debugging with ADI: lazy clearing of version tags. This does not preclude kernel debugging. If kernel debugging ends up requiring tags be cleared whenever a page is freed, we can add that code as part of kernel debugging support code and enable it conditionally only when kernel is being debugged. Forcing every task to incur the large cost of clearing tags on every "free" all the time is just not an acceptable cost only to support kernel debugging. It should be a dynamic switch to be toggled on only when debugging kernel. PSTATE.mcde being set is not enough to trigger a trap. It is easy enough to clear TTE.mcd before block initialization of a page and avoid a trap due to tag mismatch, or just use physical address with block initialization. We can evaluate all of these options when we get to implementing kernel debugging using ADI. Thanks, Khalid Details: when memory is "freed" the version tags are left alone, as it is an expensive operation to go through the memory and clear the tag for each cache line. So this is done lazily whenever memory is "allocated". More specifically, the first time a user process touches freshly allocated memory, a fault occurs and the kernel then clears the page. In the NG4 and M7 variants of clear_user_page, the block init store ASI is used to optimize, and it has the side effect of clearing the ADI tag for the cache line. BUT only if pstate.mcde is clear. If pstate.mcde is set, then instead of the ADI tag being cleared, the tag is *checked*, and if there is a mismatch between the version in the virtual address and the version in memory, then you'll get a trap and panic. Therefore, with this design, you cannot have pstate.mcde enabled while in the kernel (in general). To solve this you have to check the state of pstate.mcde (or just turn it off) before doing any block init store in clear_user_page, memset, memcpy, etc. Rob -- To unsubscribe from this list: send the line "unsubscribe sparclinux" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC PATCH v3] sparc64: Add support for Application Data Integrity (ADI)
On 01/06/2017 10:02 AM, David Miller wrote: From: Dave Hansen Date: Fri, 6 Jan 2017 08:55:03 -0800 Actually, that reminds me... How does your code interface with ksm? Or is there no interaction needed since you're always working on virtual addresses? This reminds me, I consider this feature potentially extremely useful for kernel debugging. So I would like to make sure we don't implement anything in a way which would preclude that in the long term. I agree and please do point out if I have made any implementation decisions that could preclude that. Thanks, Khalid -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC PATCH v3] sparc64: Add support for Application Data Integrity (ADI)
On 01/06/2017 09:55 AM, Dave Hansen wrote: On 01/06/2017 08:22 AM, Khalid Aziz wrote: On 01/06/2017 08:36 AM, Dave Hansen wrote: On 01/06/2017 07:32 AM, Khalid Aziz wrote: I agree with you on simplicity first. Subpage granularity is complex, but the architecture allows for subpage granularity. Maybe the right approach is to support this at page granularity first for swappable pages and then expand to subpage granularity in a subsequent patch? Pages locked in memory can already use subpage granularity with my patch. What do you mean by "locked in memory"? mlock()'d memory can still be migrated around and still requires "swap" ptes, for instance. You are right. Page migration can invalidate subpage granularity even for locked pages. Is it possible to use cpusets to keep a task and its memory locked on a single node? It's going to be hard to impossible to guarantee. mlock() doesn't guarantee that things won't change physical addresses. You'd have to change that guarantee or chase all the things in the kernel that might change physical addresses (compaction, ksm, etc...). Actually, that reminds me... How does your code interface with ksm? Or is there no interaction needed since you're always working on virtual addresses? Yes, version tags are interpreted at virtual address level. -- Khalid -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC PATCH v3] sparc64: Add support for Application Data Integrity (ADI)
On 01/06/2017 08:36 AM, Dave Hansen wrote: On 01/06/2017 07:32 AM, Khalid Aziz wrote: I agree with you on simplicity first. Subpage granularity is complex, but the architecture allows for subpage granularity. Maybe the right approach is to support this at page granularity first for swappable pages and then expand to subpage granularity in a subsequent patch? Pages locked in memory can already use subpage granularity with my patch. What do you mean by "locked in memory"? mlock()'d memory can still be migrated around and still requires "swap" ptes, for instance. You are right. Page migration can invalidate subpage granularity even for locked pages. Is it possible to use cpusets to keep a task and its memory locked on a single node? Just wondering if there are limited cases where subpage granularity could work without supporting subpage granularity for tags in swap. It still sounds like the right thing to do is to get a reliable implementation in place with page size granularity and then add the complexity of subpage granularity. Thanks, Khalid -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC PATCH v3] sparc64: Add support for Application Data Integrity (ADI)
On 01/06/2017 02:19 AM, Michal Hocko wrote: On Thu 05-01-17 13:30:10, Khalid Aziz wrote: [...] It is very tempting to restrict tags to PAGE_SIZE granularity since it makes code noticeably simpler and that is indeed going to be the majority of cases. Sooner or later somebody would want to use multiple tags per page though. I didn't get to read the patch throughly yet but I am really confused by this statement. The api is mprotect based which makes it ineherently PAGE_SIZE granular. How do you want to achieve cache line granularity with this API? And I would really vote for simplicity first... Subpage granularity sounds way too tricky... Hi Michal, ADI can be enabled for subsets of a task's address space. It takes three steps to enable ADI completely: 1. Enable the task to use ADI by setting PSTATE.mcde bit. This is the master switch for ADI. mprotect() does this in my patch. Granularity for this operation is entire address space for the task. 2. Set TTE.mcd bit for each page translation for the pages one wants ADI enabled on. mprotect() does this as well in my patch. Granularity for this operation is per page. 3. Set version tag for the addresses task wants to enable ADI on using "stxa" instruction. This is done entirely in userspace with no assistance or intervention needed from the kernel. Granularity for this operation is cache line size which is 64 bytes on Sparc M7. I agree with you on simplicity first. Subpage granularity is complex, but the architecture allows for subpage granularity. Maybe the right approach is to support this at page granularity first for swappable pages and then expand to subpage granularity in a subsequent patch? Pages locked in memory can already use subpage granularity with my patch. Thanks, Khalid -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC PATCH v3] sparc64: Add support for Application Data Integrity (ADI)
On 01/05/2017 12:22 PM, Dave Hansen wrote: On 01/04/2017 04:26 PM, Khalid Aziz wrote: ... No, we do not have space to stuff PAGE_SIZE/64 version tags in swap pte. There is enough space for just one tag per page. DaveM had suggested doing this since the usual case is for a task to set one tag per page even though MMU does not require it. I have implemented this as first pass to start a discussion and get feedback on whether rest of the swapping implementation and other changes look right, hence the patch is "RFC". If this all looks good, I can expand swapping support in a subsequent patch or iteration of this patch to allocate space in mm_context_t possibly to store per cacheline tags. I am open to any other ideas on storing this larger number of version tags. FWIW, This is the kind of thing that would be really useful to point out to reviewers instead of requiring them to ferret it out of the code. It has huge implications for how applications use this feature. Hi Dave, Thanks for taking the time to review this. I appreciate your patience. I will add more details. As for where to store the tags... It's potentially a *lot* of data, so I think it'll be a pain any way you do it. If you, instead, can live with doing things on a PAGE_SIZE granularity like pkeys does, you could just store it in the VMA and have the kernel tag the data at the same time it zeroes the pages. It is very tempting to restrict tags to PAGE_SIZE granularity since it makes code noticeably simpler and that is indeed going to be the majority of cases. Sooner or later somebody would want to use multiple tags per page though. There can be 128 4-bit tags per 8K page which requires 64 bytes of tag storage for each page. This can add up. What I am considering doing is store the tag in swp pte if I find only one tag on the page. A VMA can cover multiple pages and we have unused bits in swp pte. It makes more sense to store the tags in swp pte. If I find more than one tag on the page, I can allocate memory, attach it to a data structure in mm_context_t and store the tags there. I will need to use an rb tree or some other way to keep the data sorted to make it quick to retrieve the tags for one of the millions of pages a task might have. As I said, it gets complex trying to store tags per cacheline as opposed to per page :) -- Khalid -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC PATCH v3] sparc64: Add support for Application Data Integrity (ADI)
On 01/05/2017 02:37 AM, Jerome Marchand wrote: On 01/04/2017 11:46 PM, Khalid Aziz wrote: ADI is a new feature supported on sparc M7 and newer processors to allow hardware to catch rogue accesses to memory. ADI is supported for data fetches only and not instruction fetches. An app can enable ADI on its data pages, set version tags on them and use versioned addresses to access the data pages. Upper bits of the address contain the version tag. On M7 processors, upper four bits (bits 63-60) contain the version tag. If a rogue app attempts to access ADI enabled data pages, its access is blocked and processor generates an exception. This patch extends mprotect to enable ADI (TSTATE.mcde), enable/disable MCD (Memory Corruption Detection) on selected memory ranges, enable TTE.mcd in PTEs, return ADI parameters to userspace and save/restore ADI version tags on page swap out/in. It also adds handlers for all traps related to MCD. ADI is not enabled by default for any task. A task must explicitly enable ADI on a memory range and set version tag for ADI to be effective for the task. Signed-off-by: Khalid Aziz Cc: Khalid Aziz --- v2: - Fixed a build error v3: - Removed CONFIG_SPARC_ADI - Replaced prctl commands with mprotect - Added auxiliary vectors for ADI parameters - Enabled ADI for swappable pages Documentation/sparc/adi.txt | 239 arch/sparc/include/asm/adi.h| 6 + arch/sparc/include/asm/adi_64.h | 46 ++ arch/sparc/include/asm/elf_64.h | 8 ++ arch/sparc/include/asm/hugetlb.h| 13 ++ arch/sparc/include/asm/hypervisor.h | 2 + arch/sparc/include/asm/mman.h | 40 +- arch/sparc/include/asm/mmu_64.h | 2 + arch/sparc/include/asm/mmu_context_64.h | 32 + arch/sparc/include/asm/pgtable_64.h | 97 - arch/sparc/include/asm/ttable.h | 10 ++ arch/sparc/include/asm/uaccess_64.h | 120 +++- arch/sparc/include/uapi/asm/asi.h | 5 + arch/sparc/include/uapi/asm/auxvec.h| 8 ++ arch/sparc/include/uapi/asm/mman.h | 2 + arch/sparc/include/uapi/asm/pstate.h| 10 ++ arch/sparc/kernel/Makefile | 1 + arch/sparc/kernel/adi_64.c | 93 + arch/sparc/kernel/entry.h | 3 + arch/sparc/kernel/head_64.S | 1 + arch/sparc/kernel/mdesc.c | 4 + arch/sparc/kernel/process_64.c | 21 +++ arch/sparc/kernel/sun4v_mcd.S | 16 +++ arch/sparc/kernel/traps_64.c| 142 ++- arch/sparc/kernel/ttable_64.S | 6 +- arch/sparc/mm/gup.c | 37 + arch/sparc/mm/tlb.c | 28 arch/x86/kernel/signal_compat.c | 2 +- include/asm-generic/pgtable.h | 5 + include/linux/mm.h | 2 + include/uapi/asm-generic/siginfo.h | 5 +- mm/memory.c | 2 +- mm/rmap.c | 4 +- I haven't actually reviewed the code and looked at why you need set_swp_pte_at() function, but the code that add the generic version of this function need to be separated from the rest of the patch. Also, given the size of this patch, I suspect the rest also need to be broken into more patches. Jerome Sure, I can do that. Code to add new signal codes can be one patch, generic changes to swap infrastructure can be another and I can look for logical breaks for the rest of the sparc specific code. -- Khalid -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC PATCH v3] sparc64: Add support for Application Data Integrity (ADI)
On 01/04/2017 05:14 PM, Dave Hansen wrote: On 01/04/2017 04:05 PM, Rob Gardner wrote: What if two different small pages have different tags and khugepaged comes along and tries to collapse them? Will the page be split if a user attempts to set two different tags inside two different small-page portions of a single THP? The MCD tags operate at a resolution of cache lines (64 bytes). Page sizes don't matter except that each virtual page must have a bit set in its TTE to allow MCD to be enabled on the page. Any page can have many different tags, one for each cache line. Is an "MCD tag" the same thing as a "ADI version tag"? The thing that confused me here is that we're taking an entire page of "ADI version tags" and stuffing them into a swap pte (in set_swp_pte_at()). Do we somehow have enough space in a swap pte on sparc to fit PAGE_SIZE/64 "ADI version tag"s in there? No, we do not have space to stuff PAGE_SIZE/64 version tags in swap pte. There is enough space for just one tag per page. DaveM had suggested doing this since the usual case is for a task to set one tag per page even though MMU does not require it. I have implemented this as first pass to start a discussion and get feedback on whether rest of the swapping implementation and other changes look right, hence the patch is "RFC". If this all looks good, I can expand swapping support in a subsequent patch or iteration of this patch to allocate space in mm_context_t possibly to store per cacheline tags. I am open to any other ideas on storing this larger number of version tags. Thanks, Khalid -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC PATCH v3] sparc64: Add support for Application Data Integrity (ADI)
On 01/04/2017 04:49 PM, Dave Hansen wrote: On 01/04/2017 03:44 PM, Rob Gardner wrote: On 01/04/2017 03:40 PM, Dave Hansen wrote: On 01/04/2017 03:35 PM, Rob Gardner wrote: Tags are not cleared at all when memory is freed, but rather, lazily (and automatically) cleared when memory is allocated. What does "allocated" mean in this context? Physical or virtual? What does this do, for instance? The first time a virtual page is touched by a process after the malloc, the kernel does clear_user_page() or something similar, which zeroes the memory. At the same time, the memory tags are cleared. OK, so the tags can't survive a MADV_FREE. That's definitely something for apps to understand that use MADV_FREE as a substitute for memset(). It also means that tags can't be set for physically unallocated memory. Neither of those are deal killers, but it would be nice to document it. This can go into the adi.txt doc file. How does this all work with large pages? It works with large pages the same way as normal sized pages. The TTE for a large page also will have the mcd bit set in it and tags are set and referenced the same way. -- Khalid -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC PATCH v3] sparc64: Add support for Application Data Integrity (ADI)
On 01/04/2017 04:31 PM, Dave Hansen wrote: One other high-level comment: It would be nice to see the arch-independent and x86 portions broken out and explained in their own right, even if they're small patches. It's a bit cruel to make us scroll through a thousand lines of sparc code to see the bits interesting to us. Sure, that is very reasonable. I will do that. It would also be really nice to see a high-level breakdown explaining what you had to modify, especially since this affects all of the system calls that take a PROT_* argument. The sample code is nice, but it's no substitute for writing it down. I will expand the explanation in Documentation/sparc/adi.txt. Thanks! -- Khalid -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC PATCH v3] sparc64: Add support for Application Data Integrity (ADI)
On 01/04/2017 04:27 PM, Dave Hansen wrote: On 01/04/2017 02:46 PM, Khalid Aziz wrote: This patch extends mprotect to enable ADI (TSTATE.mcde), enable/disable MCD (Memory Corruption Detection) on selected memory ranges, enable TTE.mcd in PTEs, return ADI parameters to userspace and save/restore ADI version tags on page swap out/in. I'm a bit confused why we need all the mechanics with set_swp_pte_at(). For pkeys, for instance, all of the PTEs under a given VMA share a pkey. When swapping something in, we just get the pkey out of the VMA and populate the PTE. ADI doesn't seem to have a similar restriction. The feature is turned on or off at a VMA granularity, but we do not (or can enforce that all pages under a given VMA must share a tag. But this leads to an interesting question: is the tag associated with the (populated?) pte, or the virtual address? Can you have tags associated with non-present addresses? What's the mechanism that clears the tags at munmap() or MADV_FREE time? Hi Dave, Tag is associated with virtual address and all pages in a singular VMA do not share the same tag. When a page is swapped out, we need to save the tag that was set on it so we can restore it when we bring the page back in. When MMU translates a vitrtual address into physical address, it expects to see the same tag set on the physical page as is set in the VA before it will allow access. Tags are cleared on a page by NG4clear_page() and NG4clear_user_page() when a page is allocated to a task. Is the tag storage a precious resource? Can it be exhausted? There is a metadata area in RAM that stores the tags and it has enough space to cover all the tags for the RAM size. -- Khalid -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC PATCH v3] sparc64: Add support for Application Data Integrity (ADI)
ADI is a new feature supported on sparc M7 and newer processors to allow hardware to catch rogue accesses to memory. ADI is supported for data fetches only and not instruction fetches. An app can enable ADI on its data pages, set version tags on them and use versioned addresses to access the data pages. Upper bits of the address contain the version tag. On M7 processors, upper four bits (bits 63-60) contain the version tag. If a rogue app attempts to access ADI enabled data pages, its access is blocked and processor generates an exception. This patch extends mprotect to enable ADI (TSTATE.mcde), enable/disable MCD (Memory Corruption Detection) on selected memory ranges, enable TTE.mcd in PTEs, return ADI parameters to userspace and save/restore ADI version tags on page swap out/in. It also adds handlers for all traps related to MCD. ADI is not enabled by default for any task. A task must explicitly enable ADI on a memory range and set version tag for ADI to be effective for the task. Signed-off-by: Khalid Aziz Cc: Khalid Aziz --- v2: - Fixed a build error v3: - Removed CONFIG_SPARC_ADI - Replaced prctl commands with mprotect - Added auxiliary vectors for ADI parameters - Enabled ADI for swappable pages Documentation/sparc/adi.txt | 239 arch/sparc/include/asm/adi.h| 6 + arch/sparc/include/asm/adi_64.h | 46 ++ arch/sparc/include/asm/elf_64.h | 8 ++ arch/sparc/include/asm/hugetlb.h| 13 ++ arch/sparc/include/asm/hypervisor.h | 2 + arch/sparc/include/asm/mman.h | 40 +- arch/sparc/include/asm/mmu_64.h | 2 + arch/sparc/include/asm/mmu_context_64.h | 32 + arch/sparc/include/asm/pgtable_64.h | 97 - arch/sparc/include/asm/ttable.h | 10 ++ arch/sparc/include/asm/uaccess_64.h | 120 +++- arch/sparc/include/uapi/asm/asi.h | 5 + arch/sparc/include/uapi/asm/auxvec.h| 8 ++ arch/sparc/include/uapi/asm/mman.h | 2 + arch/sparc/include/uapi/asm/pstate.h| 10 ++ arch/sparc/kernel/Makefile | 1 + arch/sparc/kernel/adi_64.c | 93 + arch/sparc/kernel/entry.h | 3 + arch/sparc/kernel/head_64.S | 1 + arch/sparc/kernel/mdesc.c | 4 + arch/sparc/kernel/process_64.c | 21 +++ arch/sparc/kernel/sun4v_mcd.S | 16 +++ arch/sparc/kernel/traps_64.c| 142 ++- arch/sparc/kernel/ttable_64.S | 6 +- arch/sparc/mm/gup.c | 37 + arch/sparc/mm/tlb.c | 28 arch/x86/kernel/signal_compat.c | 2 +- include/asm-generic/pgtable.h | 5 + include/linux/mm.h | 2 + include/uapi/asm-generic/siginfo.h | 5 +- mm/memory.c | 2 +- mm/rmap.c | 4 +- 33 files changed, 993 insertions(+), 19 deletions(-) create mode 100644 Documentation/sparc/adi.txt create mode 100644 arch/sparc/include/asm/adi.h create mode 100644 arch/sparc/include/asm/adi_64.h create mode 100644 arch/sparc/kernel/adi_64.c create mode 100644 arch/sparc/kernel/sun4v_mcd.S diff --git a/Documentation/sparc/adi.txt b/Documentation/sparc/adi.txt new file mode 100644 index 000..18aa6d0 --- /dev/null +++ b/Documentation/sparc/adi.txt @@ -0,0 +1,239 @@ +Application Data Integrity (ADI) + + +Sparc M7 processor adds the Application Data Integrity (ADI) feature. +ADI allows a task to set version tags on any subset of its address +space. Once ADI is enabled and version tags are set for ranges of +address space of a task, the processor will compare the tag in pointers +to memory in these ranges to the version set by the application +previously. Access to memory is granted only if the tag in given +pointer matches the tag set by the application. In case of mismatch, +processor raises an exception. + +Following steps must be taken by a task to enable ADI fully: + +1. Set the user mode PSTATE.mcde bit + +2. Set TTE.mcd bit on any TLB entries that correspond to the range of +addresses ADI is being enabled on. + +3. Set the version tag for memory addresses. + +ADI is enabled on a set of pages using mprotect() with PROT_ADI flag. +When ADI is enabled on a set of pages by a task for the first time, +kernel sets the PSTATE.mcde bit fot the task. Version tags for memory +addresses are set with an stxa instruction on the addresses using +ASI_MCD_PRIMARY or ASI_MCD_ST_BLKINIT_PRIMARY. Version tags are +specified in bits 63-60 of address and are set on memory the size of ADI +block size. ADI block size is provided by the hypervisor to the kernel. +Kernel returns the value of ADI block size to userspace using auxiliary +vector along with other ADI info. Following auxiliary vectors are +provided by the kernel
Re: [PATCH v2] sparc64: Add support for Application Data Integrity (ADI)
On 03/08/2016 01:27 PM, David Miller wrote: From: Khalid Aziz Date: Tue, 8 Mar 2016 13:16:11 -0700 On 03/08/2016 12:57 PM, David Miller wrote: From: Khalid Aziz Date: Mon, 7 Mar 2016 14:06:43 -0700 Good questions. Isn't set of valid VAs already constrained by VA_BITS (set to 44 in arch/sparc/include/asm/processor_64.h)? As I see it we are already not using the top 4 bits. Please correct me if I am wrong. Another limiting constraint is the number of address bits coverable by the 4-level page tables we use. And this is sign extended so we have a top-half and a bottom-half with a "hole" in the center of the VA space. I want some clarification on the top bits during ADI accesses. If ADI is enabled, then the top bits of the virtual address are intepreted as tag bits. Once "verified" with the ADI settings, what happense to these tag bits? Are they dropped from the virtual address before being passed down the TLB et al. for translations? Bits 63-60 (tag bits) are dropped from the virtual address before being passed down the TLB for translation when PSTATE.mcde = 1. Ok and you said that values 15 and 0 are special. I'm just wondering if this means you can't really use ADI mappings in the top half of the 64-bit address space. If the bits are dropped, they will be zero, but they need to be all 1's for the top-half of the VA space since it's sign extended. According to the manual when PSTATE.mcde=1, bits 63:60 of the virtual address of any load or store (using virtual address) are masked before being sent to memory system which includes MMU. Hardware TSB walker masks bits 63:60 and then sign extends from bit 59 before generating TSB pointer and before comparison to TSB TTE VAs but the virtual address in the TTE tag that is written to DTLB is masked and not sign extended. Manual also states that for implementations that fully support 60 bits or more of virtual address, they must sign-extend virtual address in TSB TTE tag. -- Khalid -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2] sparc64: Add support for Application Data Integrity (ADI)
On 03/08/2016 12:57 PM, David Miller wrote: From: Khalid Aziz Date: Mon, 7 Mar 2016 14:06:43 -0700 Good questions. Isn't set of valid VAs already constrained by VA_BITS (set to 44 in arch/sparc/include/asm/processor_64.h)? As I see it we are already not using the top 4 bits. Please correct me if I am wrong. Another limiting constraint is the number of address bits coverable by the 4-level page tables we use. And this is sign extended so we have a top-half and a bottom-half with a "hole" in the center of the VA space. I want some clarification on the top bits during ADI accesses. If ADI is enabled, then the top bits of the virtual address are intepreted as tag bits. Once "verified" with the ADI settings, what happense to these tag bits? Are they dropped from the virtual address before being passed down the TLB et al. for translations? Bits 63-60 (tag bits) are dropped from the virtual address before being passed down the TLB for translation when PSTATE.mcde = 1. -- Khalid If not, then this means you have to map ADI memory to the correct location so that the tags match up. And if that's the case, if you really wanted to mix tags within a single page, you'd have to map that page several times, once for each and every cacheline granular tag you'd like to use within that page. -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2] sparc64: Add support for Application Data Integrity (ADI)
On 03/07/2016 12:16 PM, David Miller wrote: From: Khalid Aziz Date: Mon, 7 Mar 2016 11:24:54 -0700 Tags can be cleared by user by setting tag to 0. Tags are automatically cleared by the hardware when the mapping for a virtual address is removed from TSB (which is why swappable pages are a problem), so kernel does not have to do it as part of clean up. You might be able to crib some bits for the Tag in the swp_entry_t, it's 64-bit and you can therefore steal bits from the offset field. That way you'll have the ADI tag in the page tables, ready to re-install at swapin time. Hi Dave, Can we enable ADI support for swappable pages in a subsequent update after the core functionality is stable on mlock'd pages? Thanks, Khalid -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2] sparc64: Add support for Application Data Integrity (ADI)
On 03/07/2016 04:12 PM, Rob Gardner wrote: On 03/07/2016 01:33 PM, Khalid Aziz wrote: That is a possibility but limited in scope. An address range covered by a single TTE can have large number of tags. Version tags are set on cacheline. In extreme case, one could set a tag for each set of 64-bytes in a page. Also tags are set completely in userspace and no transition occurs to kernel space, so kernel has no idea of what tags have been set. ... I have not found a way to query the MMU on tags. To query the tag for a cache line, you just read it back with ldxa and ASI_MCD_PRIMARY (ie, asi 0x90), basically the same way you stored the tag in the first place. Thanks, Rob. I just saw it while reading through the manual. -- Khalid -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2] sparc64: Add support for Application Data Integrity (ADI)
On 03/07/2016 02:34 PM, David Miller wrote: From: Khalid Aziz Date: Mon, 7 Mar 2016 14:27:09 -0700 I agree with your point of view. PSTATE.mcde and TTE.mcd are set in response to request from userspace. If userspace asked for them to be set, they already know but it was the database guys that asked for these two functions and they are the primary customers for the ADI feature. I am not crazy about this idea since this extends the mprotect API even further but would you consider using the return value from mprotect to indicate if PSTATE.mcde or TTE.mcd were already set on the given address? Well, that's the idea. If the mprotect using MAP_ADI or whatever succeeds, then ADI is enabled. Users can thus also pass MAP_ADI as a flag to mmap() to get ADI protection from the very beginning. MAP_ADI has been sitting in my backlog for some time. Looks like you just raised its priority ;) -- Khalid -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2] sparc64: Add support for Application Data Integrity (ADI)
On 03/07/2016 12:16 PM, David Miller wrote: From: Khalid Aziz Date: Mon, 7 Mar 2016 11:24:54 -0700 Tags can be cleared by user by setting tag to 0. Tags are automatically cleared by the hardware when the mapping for a virtual address is removed from TSB (which is why swappable pages are a problem), so kernel does not have to do it as part of clean up. You might be able to crib some bits for the Tag in the swp_entry_t, it's 64-bit and you can therefore steal bits from the offset field. That way you'll have the ADI tag in the page tables, ready to re-install at swapin time. That is a possibility but limited in scope. An address range covered by a single TTE can have large number of tags. Version tags are set on cacheline. In extreme case, one could set a tag for each set of 64-bytes in a page. Also tags are set completely in userspace and no transition occurs to kernel space, so kernel has no idea of what tags have been set. I have not found a way to query the MMU on tags. I will think some more about it. Thanks, Khalid -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2] sparc64: Add support for Application Data Integrity (ADI)
On 03/07/2016 12:09 PM, David Miller wrote: From: Khalid Aziz Date: Mon, 7 Mar 2016 11:04:38 -0700 On 03/07/2016 09:56 AM, David Miller wrote: From: Khalid Aziz Date: Mon, 7 Mar 2016 08:07:53 -0700 PR_GET_SPARC_ADICAPS Put this into a new ELF auxiliary vector entry via ARCH_DLINFO. So now all that's left is supposedly the TAG stuff, please explain that to me so I can direct you to the correct existing interface to provide that as well. Really, try to avoid prtctl, it's poorly typed and almost worse than ioctl(). The two remaining operations I am looking at are: 1. Is PSTATE.mcde bit set for the process? PR_SET_SPARC_ADI provides this in its return value in the patch I sent. Unnecessary. If any ADI mappings exist then mcde is set, otherwise it is clear. This is internal state and the application has no need to every set nor query it. It is implicit from the mprotect() calls the user makes to enable ADI regions. 2. Is TTE.mcd set for a given virtual address? PR_GET_SPARC_ADI_STATUS provides this function in the patch I sent. Again, implied by the mprotect() calls. Hi Dave, I agree with your point of view. PSTATE.mcde and TTE.mcd are set in response to request from userspace. If userspace asked for them to be set, they already know but it was the database guys that asked for these two functions and they are the primary customers for the ADI feature. I am not crazy about this idea since this extends the mprotect API even further but would you consider using the return value from mprotect to indicate if PSTATE.mcde or TTE.mcd were already set on the given address? Thanks, Khalid -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2] sparc64: Add support for Application Data Integrity (ADI)
On 03/07/2016 01:58 PM, David Miller wrote: From: Khalid Aziz Date: Mon, 7 Mar 2016 13:41:39 -0700 Shared data may not always be backed by a file. My understanding is one of the use cases is for in-memory databases. This shared space could also be used to hand off transactions in flight to other processes. These transactions in flight would not be backed by a file. Some of these use cases might not use shmfs even. Setting ADI bits at virtual address level catches all these cases since what backs the tagged virtual address can be anything - a mapped file, mmio space, just plain chunk of memory. Frankly the most interesting use case to me is simply finding bugs and memory scribbles, and for that we're want to be able to ADI arbitrary memory returned from malloc() and friends. I personally see ADI more as a debugging than a security feature, but that's just my view. I think that is a very strong use case. It can be a very effective tool for debugging especially when it comes to catching wild writes. -- Khalid -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2] sparc64: Add support for Application Data Integrity (ADI)
On 03/07/2016 10:46 AM, Dave Hansen wrote: On 03/07/2016 08:06 AM, Khalid Aziz wrote: Top 4-bits of sparc64 virtual address are used for version tag only when a process has its PSTATE.mcde bit set and it is accessing a memory region that has ADI enabled on it (TTE.mcd set) and a version tag was set on the virtual address being accessed. These 4-bits retain their original semantics in all other cases. OK, so this effectively reduces the address space of a process using the feature. Do we need to do anything explicit to keep an app from using that address space? Do we make sure the kernel doesn't place VMAs there? Do we respect mmap() hints that try to place memory there? Good questions. Isn't set of valid VAs already constrained by VA_BITS (set to 44 in arch/sparc/include/asm/processor_64.h)? As I see it we are already not using the top 4 bits. Please correct me if I am wrong. Thanks, Khalid -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2] sparc64: Add support for Application Data Integrity (ADI)
On 03/07/2016 12:54 PM, Andy Lutomirski wrote: On Mon, Mar 7, 2016 at 11:44 AM, Khalid Aziz wrote: Consider this scenario: 1. Process A creates a shm and attaches to it. 2. Process A fills shm with data it wants to share with only known processes. It enables ADI and sets tags on the shm. 3. Hacker triggers something like stack overflow on process A, exec's a new rogue binary and manages to attach to this shm. MMU knows tags were set on the virtual address mapping to the physical pages hosting the shm. If MMU does not require the rogue process to set the exact same tags on its mapping of the same shm, rogue process has defeated the ADI protection easily. Does this make sense? This makes sense, but I still think the design is poor. If the hacker gets code execution, then they can trivially brute force the ADI bits. True, with only 16 possible tag values (actually only 14 since 0 and 15 are reserved values), it is entirely possible to brute force the ADI tag. ADI is just another tool one can use to mitigate attacks. A process that accesses an ADI enabled memory with invalid tag gets a SIGBUS and is terminated. This can trigger alerts on the system and system policies could block the next attack. If a daemon is compromised and is forced to hand out data from memory it should not be reading (similar to heartbleed bug). the daemon itself is terminated with SIGBUS which should be enough to alert system admins. A rotating set of tags would reduce the risk from brute force attacks. Tags are set on cacheline (which is 64 bytes on M7). A single regular sized page can have 128 sets of tags. Allowing for 14 possible values for each set, that is a lot of possible combinations of tags making it very hard to brute force tags for more than a cacheline at a time. There are probably other better ways to make the tags harder to crack. Also, if this is the use case in mind, shouldn't the ADI bits bet set on the file, not the mapping? E.g. have an ioctl on the shmfs file that sets its ADI bits? Shared data may not always be backed by a file. My understanding is one of the use cases is for in-memory databases. This shared space could also be used to hand off transactions in flight to other processes. These transactions in flight would not be backed by a file. Some of these use cases might not use shmfs even. Setting ADI bits at virtual address level catches all these cases since what backs the tagged virtual address can be anything - a mapped file, mmio space, just plain chunk of memory. A process can not just write version tags and make the file inaccessible to others. It takes three steps to enable ADI: 1. Set PSTATE.mcde for the process. 2. Set TTE.mcd on all PTEs for the virtual addresses ADI is being enabled on. 3. Set version tags. Unless all three steps are taken, tag checking will not be done. stxa will fail unless step 2 is completed. In your example, the step of setting TTE.mcd will force sharing to stop for the process through change_protection(), right? OK, that makes some sense. Can a shared page ever have TTE.mcd set? How does one share a page, even deliberately, between two processes with cmd set? For two processes to share a page, their VMAs have to be identical as I understand it. If one process has TTE.mcd set (which means vma->vm_flags is different) while the other does not, they do not share a page. Thanks, Khalid -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2] sparc64: Add support for Application Data Integrity (ADI)
On 03/07/2016 11:49 AM, Andy Lutomirski wrote: On Mon, Mar 7, 2016 at 10:22 AM, Khalid Aziz wrote: No, it changes the tag associated with the virtual address for the caller. Physical page backing this virtual address is unaffected. Tag checking is done for virtual addresses. The one restriction where physical address is relevant is when two processes map the same physical page, they both have to use the same tag for the virtual addresses that map on to the shared physical pages. Slow down, please. *Why* do the tags for two different VAs that map to the same PA have to match? What goes wrong if they don't, and why is requiring them to be the same a good idea? Consider this scenario: 1. Process A creates a shm and attaches to it. 2. Process A fills shm with data it wants to share with only known processes. It enables ADI and sets tags on the shm. 3. Hacker triggers something like stack overflow on process A, exec's a new rogue binary and manages to attach to this shm. MMU knows tags were set on the virtual address mapping to the physical pages hosting the shm. If MMU does not require the rogue process to set the exact same tags on its mapping of the same shm, rogue process has defeated the ADI protection easily. Does this make sense? I sense DoS issues in your future. Are you concerned about DoS even if the tag is associated with virtual address, not physical address? Yes, absolutely. fd = open("/lib/ld.so"); mmap(fd) stxa to write the tag *boom*, presumably, because the tags apparently have to match for all mappings. A process can not just write version tags and make the file inaccessible to others. It takes three steps to enable ADI: 1. Set PSTATE.mcde for the process. 2. Set TTE.mcd on all PTEs for the virtual addresses ADI is being enabled on. 3. Set version tags. Unless all three steps are taken, tag checking will not be done. stxa will fail unless step 2 is completed. In your example, the step of setting TTE.mcd will force sharing to stop for the process through change_protection(), right? Thanks for asking these tough questions. These are very helpful in refining my implementation and avoiding silly bugs. -- Khalid -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2] sparc64: Add support for Application Data Integrity (ADI)
On 03/07/2016 12:22 PM, David Miller wrote: Khalid, maybe you should share notes with the folks working on x86 protection keys. Good idea. Sparc ADI feature is indeed similar to x86 protection keys sounds like. Thanks, Khalid -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2] sparc64: Add support for Application Data Integrity (ADI)
On 03/07/2016 11:12 AM, Dave Hansen wrote: On 03/07/2016 09:53 AM, Andy Lutomirski wrote: Also, what am I missing? Tying these tags to the physical page seems like a poor design to me. This seems really awkward to use. Yeah, can you describe the structures that store these things? Surely the hardware has some kind of lookup tables for them and stores them in memory _somewhere_. Version tags are tied to virtual addresses, not physical pages. Where exactly are the tags stored is part of processor architecture and I am not privy to that. MMU stores these lookup tables somewhere and uses it to authenticate access to virtual addresses. It really is irrelevant to kernel how MMU implements access controls as long as we have access to the knowledge of how to use it. Thanks, Khalid -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2] sparc64: Add support for Application Data Integrity (ADI)
On 03/07/2016 11:09 AM, Rob Gardner wrote: On 03/07/2016 10:04 AM, Khalid Aziz wrote: On 03/07/2016 09:56 AM, David Miller wrote: From: Khalid Aziz Date: Mon, 7 Mar 2016 08:07:53 -0700 PR_GET_SPARC_ADICAPS Put this into a new ELF auxiliary vector entry via ARCH_DLINFO. So now all that's left is supposedly the TAG stuff, please explain that to me so I can direct you to the correct existing interface to provide that as well. Really, try to avoid prtctl, it's poorly typed and almost worse than ioctl(). The two remaining operations I am looking at are: 1. Is PSTATE.mcde bit set for the process? PR_SET_SPARC_ADI provides this in its return value in the patch I sent. 2. Is TTE.mcd set for a given virtual address? PR_GET_SPARC_ADI_STATUS provides this function in the patch I sent. Setting and clearing version tags can be done entirely from userspace: while (addr < end) { asm volatile( "stxa %1, [%0]ASI_MCD_PRIMARY\n\t" : : "r" (addr), "r" (version)); addr += adicap.blksz; } so I do not have to add any kernel code for tags. What about clearing the tags when the user is done with the memory? You can't count on the user to do that, so doesn't the kernel have to do it someplace? Tags can be cleared by user by setting tag to 0. Tags are automatically cleared by the hardware when the mapping for a virtual address is removed from TSB (which is why swappable pages are a problem), so kernel does not have to do it as part of clean up. Thanks, Khalid -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2] sparc64: Add support for Application Data Integrity (ADI)
On 03/07/2016 11:08 AM, Andy Lutomirski wrote: On Mon, Mar 7, 2016 at 10:04 AM, Khalid Aziz wrote: On 03/07/2016 09:56 AM, David Miller wrote: From: Khalid Aziz Date: Mon, 7 Mar 2016 08:07:53 -0700 PR_GET_SPARC_ADICAPS Put this into a new ELF auxiliary vector entry via ARCH_DLINFO. So now all that's left is supposedly the TAG stuff, please explain that to me so I can direct you to the correct existing interface to provide that as well. Really, try to avoid prtctl, it's poorly typed and almost worse than ioctl(). The two remaining operations I am looking at are: 1. Is PSTATE.mcde bit set for the process? PR_SET_SPARC_ADI provides this in its return value in the patch I sent. 2. Is TTE.mcd set for a given virtual address? PR_GET_SPARC_ADI_STATUS provides this function in the patch I sent. Setting and clearing version tags can be done entirely from userspace: while (addr < end) { asm volatile( "stxa %1, [%0]ASI_MCD_PRIMARY\n\t" : : "r" (addr), "r" (version)); addr += adicap.blksz; } so I do not have to add any kernel code for tags. Is the effect of that to change the tag associated with a page to which the caller has write access? No, it changes the tag associated with the virtual address for the caller. Physical page backing this virtual address is unaffected. Tag checking is done for virtual addresses. The one restriction where physical address is relevant is when two processes map the same physical page, they both have to use the same tag for the virtual addresses that map on to the shared physical pages. I sense DoS issues in your future. Are you concerned about DoS even if the tag is associated with virtual address, not physical address? Thanks, Khalid -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2] sparc64: Add support for Application Data Integrity (ADI)
On 03/07/2016 10:35 AM, Dave Hansen wrote: On 03/02/2016 12:39 PM, Khalid Aziz wrote: +long enable_sparc_adi(unsigned long addr, unsigned long len) +{ + unsigned long end, pagemask; + int error; + struct vm_area_struct *vma, *vma2; + struct mm_struct *mm; + + if (!ADI_CAPABLE()) + return -EINVAL; ... This whole thing with the VMA splitting and so forth looks pretty darn arch-independent. Are you sure you need that much arch-specific code for it, or can you share more of the generic VMA management code? All of the VMA splitting/merging code is rather generic and is very similar to the code for mbind, mlock, madavise and mprotect. Currently there is no code sharing across all of these implementations. Maybe that should change. In any case, I am looking at changing the interface to go through mprotect instead as Dave suggested. I can share the code in mprotect in that case. The only arch dependent part will be to set the VM_SPARC_ADI flag on the VMA. Thanks, Khalid -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2] sparc64: Add support for Application Data Integrity (ADI)
On 03/07/2016 09:56 AM, David Miller wrote: From: Khalid Aziz Date: Mon, 7 Mar 2016 08:07:53 -0700 PR_GET_SPARC_ADICAPS Put this into a new ELF auxiliary vector entry via ARCH_DLINFO. So now all that's left is supposedly the TAG stuff, please explain that to me so I can direct you to the correct existing interface to provide that as well. Really, try to avoid prtctl, it's poorly typed and almost worse than ioctl(). The two remaining operations I am looking at are: 1. Is PSTATE.mcde bit set for the process? PR_SET_SPARC_ADI provides this in its return value in the patch I sent. 2. Is TTE.mcd set for a given virtual address? PR_GET_SPARC_ADI_STATUS provides this function in the patch I sent. Setting and clearing version tags can be done entirely from userspace: while (addr < end) { asm volatile( "stxa %1, [%0]ASI_MCD_PRIMARY\n\t" : : "r" (addr), "r" (version)); addr += adicap.blksz; } so I do not have to add any kernel code for tags. Thanks, Khalid -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2] sparc64: Add support for Application Data Integrity (ADI)
On 03/07/2016 09:45 AM, David Miller wrote: From: Khalid Aziz Date: Mon, 7 Mar 2016 08:07:53 -0700 I can remove CONFIG_SPARC_ADI. It does mean this code will be built into 32-bit kernels as well but it will be inactive code. The code should be built only into obj-$(CONFIG_SPARC64) just like the rest of the 64-bit specific code. I don't know why in the world you would build it into the 32-bit kernel. You are right. I did not understand you correctly the first time. Thanks, Khalid -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2] sparc64: Add support for Application Data Integrity (ADI)
On 03/07/2016 08:43 AM, Andy Lutomirski wrote: On Mon, Mar 7, 2016 at 7:30 AM, Rob Gardner wrote: On 03/07/2016 07:07 AM, Khalid Aziz wrote: On 03/05/2016 09:07 PM, David Miller wrote: From: Khalid Aziz Date: Wed, 2 Mar 2016 13:39:37 -0700 In this first implementation I am enabling ADI for hugepages only since these pages are locked in memory and hence avoid the issue of saving and restoring tags. This makes the feature almost entire useless. Non-hugepages must be in the initial implementation. Hi David, Thanks for the feedback. I will get this working for non-hugepages as well. ADI state of each VMA region is already stored in the VMA itself in my first implementation, so I do not lose it when the page is swapped out. The trouble is ADI version tags for each VMA region have to be stored on the swapped out pages since the ADI version tags are flushed when TLB entry for a page is flushed. Khalid, Are you sure about that last statement? My understanding is that the tags are stored in physical memory, and remain there until explicitly changed or removed, and so flushing a TLB entry has no effect on the ADI tags. If it worked the way you think, then somebody would have to potentially reload a long list of ADI tags on every TLB miss. I'll bite, since this was sent to linux-api: Can someone explain what this feature does for the benefit of people who haven't read the manual (and who don't even know where to find the manual)? Are the top few bits of a sparc64 virtual address currently must-be-zero? Does this feature change the semantics so that those bits are ignored for address resolution and instead must match whatever the ADI tag is determined to be during address resolution? Is this enforced for both user and kernel accesses? Is the actual ADI tag associated with a "page" associated with the page of physical memory or is it associated with a mapping? That is, if there are two virtual aliases of the same physical page (in the same process or otherwise), does the hardware require them to have the same ADI tag? If the answer is no, then IMO this is definitely something that should use mprotect and you should seriously consider using something like mprotect_key (new syscall, not in Linus' tree yet) for it. In fact, you might consider a possible extra parameter to that syscall for this purpose. Cc: Dave Hansen. It seems to be the zeitgeist to throw tag bits at PTEs these days. Hi Andy, The primary purpose of this feature is to prevent rogue accesses to memory regions. If a database were to allocate memory pages to cache database, it can enable ADI on those pages and set version tags. Version tag for a memory address is encoded in bits 63-60 in the virtual address. When accessing an ADI enabled memory region, top 4 bits of the virtual address presented to the MMU must match the version tag set earlier. When these bits do not match a tag, an MCD (Memory Corruption Detected) exception is raised. Kernel sends a SIGBUS to the offending process in response. There is some more info on ADI at <https://swisdev.oracle.com/_files/What-Is-ADI.html>. Top 4-bits of sparc64 virtual address are used for version tag only when a process has its PSTATE.mcde bit set and it is accessing a memory region that has ADI enabled on it (TTE.mcd set) and a version tag was set on the virtual address being accessed. These 4-bits retain their original semantics in all other cases. ADI version tags are checked for data fetches only. My implementation enforces this for userspace addresses only. Expanding this to include kernel data addresses as well will be a good thing to do to protect kernel data but I want to try to do this incrementally - (1) ADI for userspace addresses only for mlock'd pages, (2) expand support to swappable pages, (3) ADI for kernel data pages, (4)..whatever else makes sense... ADI version tag applies to virtual addresses only. If two processes have virtual addresses mapping to the same physical page, they must use the same tag. Hardware will send MCD exception if the tags do not match. This was done to ensure a hack does not bypass ADI protection by simply inserting another VA-to-PA mapping. I do like the idea of mprotect() as David suggested and it can be done with existing mprotect() call. I will have to add a new key PROT_ADI to support this. Thanks, Khalid -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2] sparc64: Add support for Application Data Integrity (ADI)
On 03/07/2016 08:30 AM, Rob Gardner wrote: On 03/07/2016 07:07 AM, Khalid Aziz wrote: On 03/05/2016 09:07 PM, David Miller wrote: From: Khalid Aziz Date: Wed, 2 Mar 2016 13:39:37 -0700 In this first implementation I am enabling ADI for hugepages only since these pages are locked in memory and hence avoid the issue of saving and restoring tags. This makes the feature almost entire useless. Non-hugepages must be in the initial implementation. Hi David, Thanks for the feedback. I will get this working for non-hugepages as well. ADI state of each VMA region is already stored in the VMA itself in my first implementation, so I do not lose it when the page is swapped out. The trouble is ADI version tags for each VMA region have to be stored on the swapped out pages since the ADI version tags are flushed when TLB entry for a page is flushed. Khalid, Are you sure about that last statement? My understanding is that the tags are stored in physical memory, and remain there until explicitly changed or removed, and so flushing a TLB entry has no effect on the ADI tags. If it worked the way you think, then somebody would have to potentially reload a long list of ADI tags on every TLB miss. Rob Hi Rob, I am fairly sure that is the case. This is what I found from the processor guys and others working on ADI. I tested it out by setting up ADI on normal malloc'd pages that got swapped out and I got MCD exceptions when those pages were swapped back in on access. I mis-spoke when I said "ADI version tags are flushed when TLB entry for a page is flushed". I meant ADI version tags are flushed when mapping for a virtual address is removed from TSB, not when TLB entry is flushed. Yes, ADI tags are stored in physical memory and removed when mapping is removed. Thanks, Khalid -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2] sparc64: Add support for Application Data Integrity (ADI)
On 03/05/2016 09:07 PM, David Miller wrote: From: Khalid Aziz Date: Wed, 2 Mar 2016 13:39:37 -0700 In this first implementation I am enabling ADI for hugepages only since these pages are locked in memory and hence avoid the issue of saving and restoring tags. This makes the feature almost entire useless. Non-hugepages must be in the initial implementation. Hi David, Thanks for the feedback. I will get this working for non-hugepages as well. ADI state of each VMA region is already stored in the VMA itself in my first implementation, so I do not lose it when the page is swapped out. The trouble is ADI version tags for each VMA region have to be stored on the swapped out pages since the ADI version tags are flushed when TLB entry for a page is flushed. When that page is brought back in, its version tags have to be set up again. Version tags are set on cacheline boundary and hence there can be multiple version tags for a single page. Version tags have to be stored in the swap space somehow along with the page. I can start out with allowing ADI to be enabled only on pages locked in memory. + PR_ENABLE_SPARC_ADI - Enable ADI checking in all pages in the address + range specified. The pages in the range must be already + locked. This operation enables the TTE.mcd bit for the + pages specified. arg2 is the starting address for address + range and must be page aligned. arg3 is the length of + memory address range and must be a multiple of page size. I strongly dislike this interface, and it makes the prtctl cases look extremely ugly and hide to the casual reader what the code is actually doing. This is an mprotect() operation, so add a new flag bit and implement this via mprotect please. That is an interesting idea. Adding a PROT_ADI protection to mprotect() sounds cleaner. There are three steps to enabling ADI - (1) set PSTATE.mcde bit which is not tied to any VMA, (2) set TTE.mcd for each VMA, and (3) set the version tag on cacheline using MCD ASI. I can combine steps 1 and 2 in one mprotect() call. That will leave PR_GET_SPARC_ADICAPS and PR_GET_SPARC_ADI_STATUS prctl commands still to be implemented. PR_SET_SPARC_ADI is also used to check if the process has PSTATE.mcde bit set. I could use PR_GET_SPARC_ADI_STATUS to do that where return values of 0 and 1 mean the same as before and possibly add return value of 2 to mean PSTATE.mcde is not set? Then since you are guarenteed to have a consistent ADI setting for every single VMA region, you never "lose" the ADI state when you swap out. It's implicit in the VMA itself, because you'll store in the VMA that this is an ADI region. I also want this enabled unconditionally, without any Kconfig knobs. I can remove CONFIG_SPARC_ADI. It does mean this code will be built into 32-bit kernels as well but it will be inactive code. Thanks, Khalid -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] sparc64: Add support for Application Data Integrity (ADI)
On 03/03/2016 03:26 PM, Julian Calaby wrote: Hi Khalid, On Fri, Mar 4, 2016 at 4:42 AM, Khalid Aziz wrote: On 03/02/2016 06:33 PM, Julian Calaby wrote: Hi Khalid, A couple of other comments: On Thu, Mar 3, 2016 at 5:54 AM, Khalid Aziz wrote: Enable Application Data Integrity (ADI) support in the sparc kernel for applications to use ADI in userspace. ADI is a new feature supported on sparc M7 and newer processors. ADI is supported for data fetches only and not instruction fetches. This patch adds prctl commands to enable and disable ADI (TSTATE.mcde), return ADI parameters to userspace, enable/disable MCD (Memory Corruption Detection) on selected memory ranges and enable TTE.mcd in PTEs. It also adds handlers for all traps related to MCD. ADI is not enabled by default for any task and a task must explicitly enable ADI (TSTATE.mcde), turn MCD on on a memory range and set version tag for ADI to be effective for the task. This patch adds support for ADI for hugepages only. Addresses passed into system calls must be non-ADI tagged addresses. Signed-off-by: Khalid Aziz --- NOTES: ADI is a new feature added to M7 processor to allow hardware to catch rogue accesses to memory. An app can enable ADI on its data pages, set version tags on them and use versioned addresses (bits 63-60 of the address contain a version tag) to access the data pages. If a rogue app attempts to access ADI enabled data pages, its access is blocked and processor generates an exception. Enabling this functionality for all data pages of an app requires adding infrastructure to save version tags for any data pages that get swapped out and restoring those tags when pages are swapped back in. In this first implementation I am enabling ADI for hugepages only since these pages are locked in memory and hence avoid the issue of saving and restoring tags. Once this core functionality is stable, ADI for other memory pages can be enabled more easily. Documentation/prctl/sparc_adi.txt | 62 ++ Documentation/sparc/adi.txt | 206 +++ arch/sparc/Kconfig| 12 ++ arch/sparc/include/asm/hugetlb.h | 14 +++ arch/sparc/include/asm/hypervisor.h | 2 + arch/sparc/include/asm/mmu_64.h | 1 + arch/sparc/include/asm/pgtable_64.h | 15 +++ arch/sparc/include/asm/processor_64.h | 19 +++ arch/sparc/include/asm/ttable.h | 10 ++ arch/sparc/include/uapi/asm/asi.h | 3 + arch/sparc/include/uapi/asm/pstate.h | 10 ++ arch/sparc/kernel/entry.h | 3 + arch/sparc/kernel/head_64.S | 1 + arch/sparc/kernel/mdesc.c | 81 + arch/sparc/kernel/process_64.c| 221 ++ arch/sparc/kernel/sun4v_mcd.S | 16 +++ arch/sparc/kernel/traps_64.c | 96 ++- arch/sparc/kernel/ttable_64.S | 6 +- include/linux/mm.h| 2 + include/uapi/asm-generic/siginfo.h| 5 +- include/uapi/linux/prctl.h| 16 +++ kernel/sys.c | 30 + 22 files changed, 825 insertions(+), 6 deletions(-) create mode 100644 Documentation/prctl/sparc_adi.txt create mode 100644 Documentation/sparc/adi.txt create mode 100644 arch/sparc/kernel/sun4v_mcd.S diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h index 131d36f..cddea30 100644 --- a/arch/sparc/include/asm/pgtable_64.h +++ b/arch/sparc/include/asm/pgtable_64.h @@ -162,6 +162,9 @@ bool kern_addr_valid(unsigned long addr); #define _PAGE_E_4V _AC(0x0800,UL) /* side-Effect */ #define _PAGE_CP_4V _AC(0x0400,UL) /* Cacheable in P-Cache */ #define _PAGE_CV_4V _AC(0x0200,UL) /* Cacheable in V-Cache */ +/* Bit 9 is used to enable MCD corruption detection instead on M7 + */ +#define _PAGE_MCD_4V _AC(0x0200,UL) /* Memory Corruption */ I'm not sure that everywhere _PAGE_CV_4V is used is guarded against setting it on M7, could someone who knows the code better than I do please check that? It looks like the tests around it's use are essentially "is it sun4v". I'm probably being paranoid, but reused values like this make me worry. I took care of this issue in an earlier patch (commit 494e5b6faeda1d1e830a13e10b3c7bc323f35d97 - "sparc: Resolve conflict between sparc v9 and M7 on usage of bit 9 of TTE"), so I think we are ok here. Ah, I remember those changes, however I didn't recall which processor they were for, so that's awesome. #define _PAGE_P_4V _AC(0x0100,UL) /* Privileged Page */ #define _PAGE_EXEC_4V_AC(0x0080,UL) /* Executable Page */ #define _PAGE_W_4V _
Re: [PATCH] sparc64: Add support for Application Data Integrity (ADI)
On 03/02/2016 06:33 PM, Julian Calaby wrote: Hi Khalid, A couple of other comments: On Thu, Mar 3, 2016 at 5:54 AM, Khalid Aziz wrote: Enable Application Data Integrity (ADI) support in the sparc kernel for applications to use ADI in userspace. ADI is a new feature supported on sparc M7 and newer processors. ADI is supported for data fetches only and not instruction fetches. This patch adds prctl commands to enable and disable ADI (TSTATE.mcde), return ADI parameters to userspace, enable/disable MCD (Memory Corruption Detection) on selected memory ranges and enable TTE.mcd in PTEs. It also adds handlers for all traps related to MCD. ADI is not enabled by default for any task and a task must explicitly enable ADI (TSTATE.mcde), turn MCD on on a memory range and set version tag for ADI to be effective for the task. This patch adds support for ADI for hugepages only. Addresses passed into system calls must be non-ADI tagged addresses. Signed-off-by: Khalid Aziz --- NOTES: ADI is a new feature added to M7 processor to allow hardware to catch rogue accesses to memory. An app can enable ADI on its data pages, set version tags on them and use versioned addresses (bits 63-60 of the address contain a version tag) to access the data pages. If a rogue app attempts to access ADI enabled data pages, its access is blocked and processor generates an exception. Enabling this functionality for all data pages of an app requires adding infrastructure to save version tags for any data pages that get swapped out and restoring those tags when pages are swapped back in. In this first implementation I am enabling ADI for hugepages only since these pages are locked in memory and hence avoid the issue of saving and restoring tags. Once this core functionality is stable, ADI for other memory pages can be enabled more easily. Documentation/prctl/sparc_adi.txt | 62 ++ Documentation/sparc/adi.txt | 206 +++ arch/sparc/Kconfig| 12 ++ arch/sparc/include/asm/hugetlb.h | 14 +++ arch/sparc/include/asm/hypervisor.h | 2 + arch/sparc/include/asm/mmu_64.h | 1 + arch/sparc/include/asm/pgtable_64.h | 15 +++ arch/sparc/include/asm/processor_64.h | 19 +++ arch/sparc/include/asm/ttable.h | 10 ++ arch/sparc/include/uapi/asm/asi.h | 3 + arch/sparc/include/uapi/asm/pstate.h | 10 ++ arch/sparc/kernel/entry.h | 3 + arch/sparc/kernel/head_64.S | 1 + arch/sparc/kernel/mdesc.c | 81 + arch/sparc/kernel/process_64.c| 221 ++ arch/sparc/kernel/sun4v_mcd.S | 16 +++ arch/sparc/kernel/traps_64.c | 96 ++- arch/sparc/kernel/ttable_64.S | 6 +- include/linux/mm.h| 2 + include/uapi/asm-generic/siginfo.h| 5 +- include/uapi/linux/prctl.h| 16 +++ kernel/sys.c | 30 + 22 files changed, 825 insertions(+), 6 deletions(-) create mode 100644 Documentation/prctl/sparc_adi.txt create mode 100644 Documentation/sparc/adi.txt create mode 100644 arch/sparc/kernel/sun4v_mcd.S diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h index 131d36f..cddea30 100644 --- a/arch/sparc/include/asm/pgtable_64.h +++ b/arch/sparc/include/asm/pgtable_64.h @@ -162,6 +162,9 @@ bool kern_addr_valid(unsigned long addr); #define _PAGE_E_4V _AC(0x0800,UL) /* side-Effect */ #define _PAGE_CP_4V _AC(0x0400,UL) /* Cacheable in P-Cache */ #define _PAGE_CV_4V _AC(0x0200,UL) /* Cacheable in V-Cache */ +/* Bit 9 is used to enable MCD corruption detection instead on M7 + */ +#define _PAGE_MCD_4V _AC(0x0200,UL) /* Memory Corruption*/ I'm not sure that everywhere _PAGE_CV_4V is used is guarded against setting it on M7, could someone who knows the code better than I do please check that? It looks like the tests around it's use are essentially "is it sun4v". I'm probably being paranoid, but reused values like this make me worry. I took care of this issue in an earlier patch (commit 494e5b6faeda1d1e830a13e10b3c7bc323f35d97 - "sparc: Resolve conflict between sparc v9 and M7 on usage of bit 9 of TTE"), so I think we are ok here. #define _PAGE_P_4V _AC(0x0100,UL) /* Privileged Page */ #define _PAGE_EXEC_4V_AC(0x0080,UL) /* Executable Page */ #define _PAGE_W_4V _AC(0x0040,UL) /* Writable */ diff --git a/arch/sparc/include/uapi/asm/pstate.h b/arch/sparc/include/uapi/asm/pstate.h index cf832e1..d0521db 100644 --- a/arch/sparc/include/uapi/asm/pstate.h +++ b/arch/sparc/includ
Re: [PATCH v2] sparc64: Add support for Application Data Integrity (ADI)
On 03/02/2016 05:48 PM, Julian Calaby wrote: Hi Khalid, On Thu, Mar 3, 2016 at 11:25 AM, Khalid Aziz wrote: Thanks, Julian! I really appreciate your feedback. No problem! My comments below. On 03/02/2016 04:08 PM, Julian Calaby wrote: Hi Khalid, On Thu, Mar 3, 2016 at 7:39 AM, Khalid Aziz wrote: Enable Application Data Integrity (ADI) support in the sparc kernel for applications to use ADI in userspace. ADI is a new feature supported on sparc M7 and newer processors. ADI is supported for data fetches only and not instruction fetches. This patch adds prctl commands to enable and disable ADI (TSTATE.mcde), return ADI parameters to userspace, enable/disable MCD (Memory Corruption Detection) on selected memory ranges and enable TTE.mcd in PTEs. It also adds handlers for all traps related to MCD. ADI is not enabled by default for any task and a task must explicitly enable ADI (TSTATE.mcde), turn MCD on on a memory range and set version tag for ADI to be effective for the task. This patch adds support for ADI for hugepages only. Addresses passed into system calls must be non-ADI tagged addresses. I can't comment on the actual functionality here, but I do see a few minor style issues in your patch. My big concern is that you're defining a lot of new code that is ADI specific but isn't inside a CONFIG_SPARC_ADI ifdef. (That said, handling ADI specific traps if ADI isn't enabled looks like a good idea to me, however most of the other stuff is just dead code if CONFIG_SPARC_ADI isn't enabled.) Some of the code will be executed when CONFIG_SPARC_ADI is not enabled, for instance init_adi() which will parse machine description to determine if platform supports ADI. On the other hand, it might still make sense to enclose this code in #ifdef. More on that below. Signed-off-by: Khalid Aziz --- NOTES: ADI is a new feature added to M7 processor to allow hardware to catch rogue accesses to memory. An app can enable ADI on its data pages, set version tags on them and use versioned addresses (bits 63-60 of the address contain a version tag) to access the data pages. If a rogue app attempts to access ADI enabled data pages, its access is blocked and processor generates an exception. Enabling this functionality for all data pages of an app requires adding infrastructure to save version tags for any data pages that get swapped out and restoring those tags when pages are swapped back in. In this first implementation I am enabling ADI for hugepages only since these pages are locked in memory and hence avoid the issue of saving and restoring tags. Once this core functionality is stable, ADI for other memory pages can be enabled more easily. v2: - Fixed a build error Documentation/prctl/sparc_adi.txt | 62 ++ Documentation/sparc/adi.txt | 206 +++ arch/sparc/Kconfig| 12 ++ arch/sparc/include/asm/hugetlb.h | 14 +++ arch/sparc/include/asm/hypervisor.h | 2 + arch/sparc/include/asm/mmu_64.h | 1 + arch/sparc/include/asm/pgtable_64.h | 15 +++ arch/sparc/include/asm/processor_64.h | 19 +++ arch/sparc/include/asm/ttable.h | 10 ++ arch/sparc/include/uapi/asm/asi.h | 3 + arch/sparc/include/uapi/asm/pstate.h | 10 ++ arch/sparc/kernel/entry.h | 3 + arch/sparc/kernel/head_64.S | 1 + arch/sparc/kernel/mdesc.c | 81 + arch/sparc/kernel/process_64.c| 222 ++ arch/sparc/kernel/sun4v_mcd.S | 16 +++ arch/sparc/kernel/traps_64.c | 96 ++- arch/sparc/kernel/ttable_64.S | 6 +- include/linux/mm.h| 2 + include/uapi/asm-generic/siginfo.h| 5 +- include/uapi/linux/prctl.h| 16 +++ kernel/sys.c | 30 + 22 files changed, 826 insertions(+), 6 deletions(-) create mode 100644 Documentation/prctl/sparc_adi.txt create mode 100644 Documentation/sparc/adi.txt create mode 100644 arch/sparc/kernel/sun4v_mcd.S I must admit that I'm slightly impressed that the documentation is over a quarter of the lines added. =) diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index 56442d2..0aac0ae 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -80,6 +80,7 @@ config SPARC64 select NO_BOOTMEM select HAVE_ARCH_AUDITSYSCALL select ARCH_SUPPORTS_ATOMIC_RMW + select SPARC_ADI This doesn't look right. config ARCH_DEFCONFIG string @@ -314,6 +315,17 @@ if SPARC64 source "kernel/power/Kconfig" endif +config SPARC_ADI + bool "Application Data Integrity support" + def_bool y if SPARC64 def_bo
Re: [PATCH v2] sparc64: Add support for Application Data Integrity (ADI)
Thanks, Julian! I really appreciate your feedback. My comments below. On 03/02/2016 04:08 PM, Julian Calaby wrote: Hi Khalid, On Thu, Mar 3, 2016 at 7:39 AM, Khalid Aziz wrote: Enable Application Data Integrity (ADI) support in the sparc kernel for applications to use ADI in userspace. ADI is a new feature supported on sparc M7 and newer processors. ADI is supported for data fetches only and not instruction fetches. This patch adds prctl commands to enable and disable ADI (TSTATE.mcde), return ADI parameters to userspace, enable/disable MCD (Memory Corruption Detection) on selected memory ranges and enable TTE.mcd in PTEs. It also adds handlers for all traps related to MCD. ADI is not enabled by default for any task and a task must explicitly enable ADI (TSTATE.mcde), turn MCD on on a memory range and set version tag for ADI to be effective for the task. This patch adds support for ADI for hugepages only. Addresses passed into system calls must be non-ADI tagged addresses. I can't comment on the actual functionality here, but I do see a few minor style issues in your patch. My big concern is that you're defining a lot of new code that is ADI specific but isn't inside a CONFIG_SPARC_ADI ifdef. (That said, handling ADI specific traps if ADI isn't enabled looks like a good idea to me, however most of the other stuff is just dead code if CONFIG_SPARC_ADI isn't enabled.) Some of the code will be executed when CONFIG_SPARC_ADI is not enabled, for instance init_adi() which will parse machine description to determine if platform supports ADI. On the other hand, it might still make sense to enclose this code in #ifdef. More on that below. Signed-off-by: Khalid Aziz --- NOTES: ADI is a new feature added to M7 processor to allow hardware to catch rogue accesses to memory. An app can enable ADI on its data pages, set version tags on them and use versioned addresses (bits 63-60 of the address contain a version tag) to access the data pages. If a rogue app attempts to access ADI enabled data pages, its access is blocked and processor generates an exception. Enabling this functionality for all data pages of an app requires adding infrastructure to save version tags for any data pages that get swapped out and restoring those tags when pages are swapped back in. In this first implementation I am enabling ADI for hugepages only since these pages are locked in memory and hence avoid the issue of saving and restoring tags. Once this core functionality is stable, ADI for other memory pages can be enabled more easily. v2: - Fixed a build error Documentation/prctl/sparc_adi.txt | 62 ++ Documentation/sparc/adi.txt | 206 +++ arch/sparc/Kconfig| 12 ++ arch/sparc/include/asm/hugetlb.h | 14 +++ arch/sparc/include/asm/hypervisor.h | 2 + arch/sparc/include/asm/mmu_64.h | 1 + arch/sparc/include/asm/pgtable_64.h | 15 +++ arch/sparc/include/asm/processor_64.h | 19 +++ arch/sparc/include/asm/ttable.h | 10 ++ arch/sparc/include/uapi/asm/asi.h | 3 + arch/sparc/include/uapi/asm/pstate.h | 10 ++ arch/sparc/kernel/entry.h | 3 + arch/sparc/kernel/head_64.S | 1 + arch/sparc/kernel/mdesc.c | 81 + arch/sparc/kernel/process_64.c| 222 ++ arch/sparc/kernel/sun4v_mcd.S | 16 +++ arch/sparc/kernel/traps_64.c | 96 ++- arch/sparc/kernel/ttable_64.S | 6 +- include/linux/mm.h| 2 + include/uapi/asm-generic/siginfo.h| 5 +- include/uapi/linux/prctl.h| 16 +++ kernel/sys.c | 30 + 22 files changed, 826 insertions(+), 6 deletions(-) create mode 100644 Documentation/prctl/sparc_adi.txt create mode 100644 Documentation/sparc/adi.txt create mode 100644 arch/sparc/kernel/sun4v_mcd.S I must admit that I'm slightly impressed that the documentation is over a quarter of the lines added. =) diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index 56442d2..0aac0ae 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -80,6 +80,7 @@ config SPARC64 select NO_BOOTMEM select HAVE_ARCH_AUDITSYSCALL select ARCH_SUPPORTS_ATOMIC_RMW + select SPARC_ADI This doesn't look right. config ARCH_DEFCONFIG string @@ -314,6 +315,17 @@ if SPARC64 source "kernel/power/Kconfig" endif +config SPARC_ADI + bool "Application Data Integrity support" + def_bool y if SPARC64 def_bool is for config options without names (i.e. "this is a boolean value and it's default is...") So if you want people to be able to disable this option, then you
[PATCH v2] sparc64: Add support for Application Data Integrity (ADI)
Enable Application Data Integrity (ADI) support in the sparc kernel for applications to use ADI in userspace. ADI is a new feature supported on sparc M7 and newer processors. ADI is supported for data fetches only and not instruction fetches. This patch adds prctl commands to enable and disable ADI (TSTATE.mcde), return ADI parameters to userspace, enable/disable MCD (Memory Corruption Detection) on selected memory ranges and enable TTE.mcd in PTEs. It also adds handlers for all traps related to MCD. ADI is not enabled by default for any task and a task must explicitly enable ADI (TSTATE.mcde), turn MCD on on a memory range and set version tag for ADI to be effective for the task. This patch adds support for ADI for hugepages only. Addresses passed into system calls must be non-ADI tagged addresses. Signed-off-by: Khalid Aziz --- NOTES: ADI is a new feature added to M7 processor to allow hardware to catch rogue accesses to memory. An app can enable ADI on its data pages, set version tags on them and use versioned addresses (bits 63-60 of the address contain a version tag) to access the data pages. If a rogue app attempts to access ADI enabled data pages, its access is blocked and processor generates an exception. Enabling this functionality for all data pages of an app requires adding infrastructure to save version tags for any data pages that get swapped out and restoring those tags when pages are swapped back in. In this first implementation I am enabling ADI for hugepages only since these pages are locked in memory and hence avoid the issue of saving and restoring tags. Once this core functionality is stable, ADI for other memory pages can be enabled more easily. v2: - Fixed a build error Documentation/prctl/sparc_adi.txt | 62 ++ Documentation/sparc/adi.txt | 206 +++ arch/sparc/Kconfig| 12 ++ arch/sparc/include/asm/hugetlb.h | 14 +++ arch/sparc/include/asm/hypervisor.h | 2 + arch/sparc/include/asm/mmu_64.h | 1 + arch/sparc/include/asm/pgtable_64.h | 15 +++ arch/sparc/include/asm/processor_64.h | 19 +++ arch/sparc/include/asm/ttable.h | 10 ++ arch/sparc/include/uapi/asm/asi.h | 3 + arch/sparc/include/uapi/asm/pstate.h | 10 ++ arch/sparc/kernel/entry.h | 3 + arch/sparc/kernel/head_64.S | 1 + arch/sparc/kernel/mdesc.c | 81 + arch/sparc/kernel/process_64.c| 222 ++ arch/sparc/kernel/sun4v_mcd.S | 16 +++ arch/sparc/kernel/traps_64.c | 96 ++- arch/sparc/kernel/ttable_64.S | 6 +- include/linux/mm.h| 2 + include/uapi/asm-generic/siginfo.h| 5 +- include/uapi/linux/prctl.h| 16 +++ kernel/sys.c | 30 + 22 files changed, 826 insertions(+), 6 deletions(-) create mode 100644 Documentation/prctl/sparc_adi.txt create mode 100644 Documentation/sparc/adi.txt create mode 100644 arch/sparc/kernel/sun4v_mcd.S diff --git a/Documentation/prctl/sparc_adi.txt b/Documentation/prctl/sparc_adi.txt new file mode 100644 index 000..9cbdcae --- /dev/null +++ b/Documentation/prctl/sparc_adi.txt @@ -0,0 +1,62 @@ + +Overview + + +SPARC M7 processor includes the feature Application Data Integrity (ADI). +ADI allows a tag to be associated with a virtual memory address range +and a process must access that memory range with the correct tag. ADI +tag is embedded in bits 63-60 of virtual address. Once ADI is enabled +on a range of memory addresses, the process can set a tag for blocks +in this memory range n the cache using ASI_MCD_PRIMARY or +ASI_MCD_ST_BLKINIT_PRIMARY. This tag is set for ADI block sized blocks +which is provided to the kernel by machine description table. + +Linux kernel supports an application enabling and setting the ADI tag +for a subset of its data pages. Those data pages have to be locked in +memory since saving ADI tags to swap is not supported. + + +New prctl options for ADI +- + +Following new options to prctl() have been added to support ADI. + + PR_GET_SPARC_ADICAPS - Get ADI capabilities for the processor. + These capabilities are used to set up ADI correctly + from userspace. Machine description table provides all + of the ADI capabilities information. arg2 to prctl() is + a pointer to struct adi_caps which is defined in + linux/prctl.h. + + + PR_SET_SPARC_ADI - Set the state of ADI in a user thread by + setting PSTATE.mcde bit in the user mode PSTATE register + of the calling thread based on the value passed in arg2: + 1 == enable, 0 == disable, other == no change
Re: [PATCH] sparc64: Add support for Application Data Integrity (ADI)
On 03/02/2016 01:26 PM, kbuild test robot wrote: Hi Khalid, [auto build test ERROR on sparc/master] [also build test ERROR on v4.5-rc6] [cannot apply to next-20160302] [if your patch is applied to the wrong git tree, please drop us a note to help improving the system] url: https://github.com/0day-ci/linux/commits/Khalid-Aziz/sparc64-Add-support-for-Application-Data-Integrity-ADI/20160303-025709 base: https://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc.git master config: sparc64-allnoconfig (attached as .config) reproduce: wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # save the attached .config to linux build tree make.cross ARCH=sparc64 All errors (new ones prefixed by >>): arch/sparc/kernel/process_64.c: In function 'disable_sparc_adi': arch/sparc/kernel/process_64.c:961:6: error: implicit declaration of function 'vma_policy' [-Werror=implicit-function-declaration] vma_policy(vma), vma->vm_userfaultfd_ctx); ^ arch/sparc/kernel/process_64.c:959:10: error: passing argument 9 of 'vma_merge' makes pointer from integer without a cast [-Werror] prev = vma_merge(mm, prev, addr, end, vma->vm_flags, ^ In file included from arch/sparc/kernel/process_64.c:18:0: include/linux/mm.h:1922:31: note: expected 'struct mempolicy *' but argument is of type 'int' extern struct vm_area_struct *vma_merge(struct mm_struct *, ^ Not sure why it built without errors on my system. I will #include and send updated patch. -- Khalid -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] sparc64: Add support for Application Data Integrity (ADI)
Enable Application Data Integrity (ADI) support in the sparc kernel for applications to use ADI in userspace. ADI is a new feature supported on sparc M7 and newer processors. ADI is supported for data fetches only and not instruction fetches. This patch adds prctl commands to enable and disable ADI (TSTATE.mcde), return ADI parameters to userspace, enable/disable MCD (Memory Corruption Detection) on selected memory ranges and enable TTE.mcd in PTEs. It also adds handlers for all traps related to MCD. ADI is not enabled by default for any task and a task must explicitly enable ADI (TSTATE.mcde), turn MCD on on a memory range and set version tag for ADI to be effective for the task. This patch adds support for ADI for hugepages only. Addresses passed into system calls must be non-ADI tagged addresses. Signed-off-by: Khalid Aziz --- NOTES: ADI is a new feature added to M7 processor to allow hardware to catch rogue accesses to memory. An app can enable ADI on its data pages, set version tags on them and use versioned addresses (bits 63-60 of the address contain a version tag) to access the data pages. If a rogue app attempts to access ADI enabled data pages, its access is blocked and processor generates an exception. Enabling this functionality for all data pages of an app requires adding infrastructure to save version tags for any data pages that get swapped out and restoring those tags when pages are swapped back in. In this first implementation I am enabling ADI for hugepages only since these pages are locked in memory and hence avoid the issue of saving and restoring tags. Once this core functionality is stable, ADI for other memory pages can be enabled more easily. Documentation/prctl/sparc_adi.txt | 62 ++ Documentation/sparc/adi.txt | 206 +++ arch/sparc/Kconfig| 12 ++ arch/sparc/include/asm/hugetlb.h | 14 +++ arch/sparc/include/asm/hypervisor.h | 2 + arch/sparc/include/asm/mmu_64.h | 1 + arch/sparc/include/asm/pgtable_64.h | 15 +++ arch/sparc/include/asm/processor_64.h | 19 +++ arch/sparc/include/asm/ttable.h | 10 ++ arch/sparc/include/uapi/asm/asi.h | 3 + arch/sparc/include/uapi/asm/pstate.h | 10 ++ arch/sparc/kernel/entry.h | 3 + arch/sparc/kernel/head_64.S | 1 + arch/sparc/kernel/mdesc.c | 81 + arch/sparc/kernel/process_64.c| 221 ++ arch/sparc/kernel/sun4v_mcd.S | 16 +++ arch/sparc/kernel/traps_64.c | 96 ++- arch/sparc/kernel/ttable_64.S | 6 +- include/linux/mm.h| 2 + include/uapi/asm-generic/siginfo.h| 5 +- include/uapi/linux/prctl.h| 16 +++ kernel/sys.c | 30 + 22 files changed, 825 insertions(+), 6 deletions(-) create mode 100644 Documentation/prctl/sparc_adi.txt create mode 100644 Documentation/sparc/adi.txt create mode 100644 arch/sparc/kernel/sun4v_mcd.S diff --git a/Documentation/prctl/sparc_adi.txt b/Documentation/prctl/sparc_adi.txt new file mode 100644 index 000..9cbdcae --- /dev/null +++ b/Documentation/prctl/sparc_adi.txt @@ -0,0 +1,62 @@ + +Overview + + +SPARC M7 processor includes the feature Application Data Integrity (ADI). +ADI allows a tag to be associated with a virtual memory address range +and a process must access that memory range with the correct tag. ADI +tag is embedded in bits 63-60 of virtual address. Once ADI is enabled +on a range of memory addresses, the process can set a tag for blocks +in this memory range n the cache using ASI_MCD_PRIMARY or +ASI_MCD_ST_BLKINIT_PRIMARY. This tag is set for ADI block sized blocks +which is provided to the kernel by machine description table. + +Linux kernel supports an application enabling and setting the ADI tag +for a subset of its data pages. Those data pages have to be locked in +memory since saving ADI tags to swap is not supported. + + +New prctl options for ADI +- + +Following new options to prctl() have been added to support ADI. + + PR_GET_SPARC_ADICAPS - Get ADI capabilities for the processor. + These capabilities are used to set up ADI correctly + from userspace. Machine description table provides all + of the ADI capabilities information. arg2 to prctl() is + a pointer to struct adi_caps which is defined in + linux/prctl.h. + + + PR_SET_SPARC_ADI - Set the state of ADI in a user thread by + setting PSTATE.mcde bit in the user mode PSTATE register + of the calling thread based on the value passed in arg2: + 1 == enable, 0 == disable, other == no change + Return the previous state of the