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 0/4] Application Data Integrity feature introduced by SPARC M7
From: Dave Hansen Date: Wed, 11 Jan 2017 08:33:30 -0800 > 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? If we did this then for every page mapped into userspace we'd have to explicitly set all of the tags to zero, otherwise we'd get TAG mismatch exceptions. That would be like clearing the every mapped anonymous page twice, or worse. -- 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
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... :-) -- 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 09:08 AM, Dave Hansen wrote: On 01/13/2017 07:29 AM, Rob Gardner wrote: so perhaps ADI should simply be disallowed for memory mapped to files, and this particular complication can be avoided. Thoughts? What's a "file" from your perspective? In Linux, shared memory is a file. hugetlbfs is done with files. Many databases mmap() their data into their address space. Of course I meant a traditional file is the DOS sense, ie, data stored on something magnetic. ;) But it doesn't really matter because I am just trying to envision a use case for any of the mmap scenarios. For instance a very persuasive use case for ADI is to 'color' malloc memory, freed malloc memory, and malloc's metadata with different ADI version tags so as to catch buffer overflows, underflows, use-after-free and use-after-realloc type scenarios. What is an equally compelling or even mildly interesting use case for ADI in shared memory and file mmap situations? Maybe you could mmap a file and immediately tag the entire thing with some version, thus disallowing all access to it, and then hand out access a chunk at a time. And then? Rob -- 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 07:29 AM, Rob Gardner wrote: > so perhaps ADI should simply be disallowed for memory mapped to > files, and this particular complication can be avoided. Thoughts? What's a "file" from your perspective? In Linux, shared memory is a file. hugetlbfs is done with files. Many databases mmap() their data into their address space. -- 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 in memory, say an in-memory copy of database, is one of the use cases for ADI. This means t
Re: [PATCH v4 0/4] Application Data Integrity feature introduced by SPARC M7
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? 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. 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 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 bod
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 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. 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 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/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? > 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 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? Yes, I think this is what you have to do. -- 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 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. >> 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. What do you mean by "ADI protection"? I think of ADI _protection_ as coming from the PTE and/or VMA bits. Those are copied at fork() from the old VMA to the new one. Is there a reason the child won't implicitly inherit these that I missed? Whether the parent or the child does the COW fault is basically random. Whether they get the ADI-tagged page, or the non-ADI-tagged copy is thus effectively random. Assuming that the new page has its tags cleared (and thus is tagged not to be protected), whether your data continues to be protected or not after a fork() is random. That doesn't seem like workable behavior. -- 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 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. 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? >>> 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. Bummer. If the hardware had allowed a special VA tag to bypass checks, then you wouldn't need to worry about clearing the tags, and you wouldn't need the interface to control the PTE bit setting/clearing. -- 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 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? > 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? -- 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
Re: [PATCH v4 0/4] Application Data Integrity feature introduced by SPARC M7
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? 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. -- 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 0/4] Application Data Integrity feature introduced by SPARC M7
SPARC M7 processor adds additional metadata for memory address space that can be used to secure access to regions of memory. This additional metadata is implemented as a 4-bit tag attached to each cacheline size block of memory. A task can set a tag on any number of such blocks. Access to such block is granted only if the virtual address used to access that block of memory has the tag encoded in the uppermost 4 bits of VA. Any mismatch between tag encoded in VA and tag set on the memory block results in a trap. Tags are verified in the VA presented to the MMU and tags are associated with the physical page VA maps on to. If a memory page is swapped out and page frame gets reused for another task, the tags are lost and hence must be saved when swapping or migrating the page. 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. MMU validates the tag embedded in VA for every page that has TTE.mcd bit set in its pte. After enabling ADI on a memory range, the userspace task can set ADI version tags using stxa instruction with ASI_MCD_PRIMARY or ASI_MCD_ST_BLKINIT_PRIMARY ASI. Once userspace task calls mprotect() with PROT_ADI, kernel takes following overall steps: 1. Find the VMAs covering the address range passed in to mprotect and set VM_SPARC_ADI flag. If address range covers a subset of a VMA, the VMA will be split. 2. When a page is allocated for a VA and the VMA covering this VA has VM_SPARC_ADI flag set, set the TTE.mcd bit so MMU will check the vwersion tag. 3. Userspace can now set version tags on the memory it has enabled ADI on. Userspace accesses ADI enabled memory using a virtual address that has the version tag embedded in the high bits. MMU validates this version tag against the actual tag set on the memory. If tag matches, MMU performs the VA->PA translation and access is granted. If there is a mismatch, hypervisor sends a data access exception or precise memory corruption detected exception depending upon whether precise exceptions are enabled or not (controlled by MCDPERR register). Kernel sends SIGSEGV to the task with appropriate si_code. 4. If a page is being swapped out or migrated, kernel builds a swap pte for the page. If the page is ADI enabled and has version tags set on it, set_swp_pte_at() function introduced by this patch series allows kernel to save the version tags. set_swp_pte_at() replaces the calls to set_pte_at() in functions that unmap and map a page. On architectures that do not require special handling on a page being swapped, set_swp_pte_at() defaults to set_pte_at(). In this initial implementation, kernel supports saving one version tag per page and top bits of swap offset in swap pte are used to store the tag. 5. When the page is swapped back in or reinstantiated after migration, set_swp_pte_at() function allows kernel to restore the version tags on the new physical page by retrieving the original tag from swap offset in swap pte. User task can disable ADI by calling mprotect() again on the memory range with PROT_ADI bit unset. Kernel clears the VM_SPARC_ADI flag in VMAs, merges adjacent VMAs if necessary, and clears TTE.mcd bit in the corresponding ptes. IOMMU does not support ADI checking. Any version tags embedded in the top bits of VA meant for IOMMU, are cleared and replaced with sign extension of the first non-version tag bit (bit 59 for SPARC M7) for IOMMU addresses. This patch series adds support for this feature in 4 patches: Patch 1/4 Tag mismatch on access by a task results in a trap from hypervisor as data access exception or a precide memory corruption detected exception. As part of handling these exceptions, kernel sends a SIGSEGV to user process with special si_code to indicate which fault occurred. This patch adds three new si_codes to differentiate between various mismatch errors. Patch 2/4 When a page is swapped or migrated, metadata associated with the page must be saved so it can be restored later. This patch adds a new function that saves/restores this metadata when updating pte upon a swap/migration. Patch 3/4 SPARC M7 processor adds new fields to control registers to support ADI feature. It also adds a new exception for precise traps on tag mismatch. This patch adds definitions for the new control register fields, new ASIs for ADI and an exception handler for the precise trap on tag mismatch. Patch 4/4 This patch adds support for a user space task to enable ADI and enable tag checking for subsets of its address space. As part of enabling this feature, this patch also extends exception handlers to handler tag mismatch exceptions, adds code to save and restore tags on page swap and migration, and adds code to return ADI parameters to userspace. Testing: - All functionality was teste