Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add cheribsdtest_vm_tag_mprotect_none_and_back #1034

Open
wants to merge 1 commit into
base: dev
Choose a base branch
from

Conversation

nwf
Copy link
Member

@nwf nwf commented Jun 30, 2021

I believe this test should pass, but at present it does not. It appears the page is left without capability read permission after the second mprotect call:

root@:/ # cheribsdtest-purecap cheribsdtest_vm_tag_mprotect_none_and_back                                  
TEST: cheribsdtest_vm_tag_mprotect_none_and_back: check that mmap/mprotect(NONE)/mprotect(RW) still permits cap RW
FAIL: cheribsdtest_vm_tag_mprotect_none_and_back: 'cheri_gettag(arena[1])' is FALSE!

It's possible that this is because of the "funny" nature of tag-clearing PTEs: because they don't trap, they must be eagerly corrected unlike other permission upgrades (e.g., pages springing into existence or becoming writeable).

@nwf nwf requested review from qwattash and brooksdavis June 30, 2021 01:48
@nwf nwf requested a review from bsdjhb July 23, 2021 00:04
@nwf
Copy link
Member Author

nwf commented Jul 23, 2021

This is failing due to the logic at

cheribsd/sys/vm/vm_map.c

Lines 3037 to 3043 in 4ea9e6b

if (keep_cap &&
((set_max && (entry->max_protection & VM_PROT_CAP) != 0) ||
(!set_max && (entry->protection & VM_PROT_CAP) != 0))) {
new_prot = VM_PROT_ADD_CAP(new_prot);
keep_cap = FALSE;
goto restart_checks;
}

After mprotect(PROT_NONE), entry->max_protection retains VM_PROT_READ_CAP|VM_PROT_WRITE_CAP but entry->protection is 0. The subsequent mprotect(PROT_READ|PROT_WRITE) then fails to VM_PROT_ADD_CAP because set_max is false, so we only look to entry->protection for justification, and we find none.

I'm not quite sure what the right move is, and so am quite open to suggestion. Perhaps we shouldn't VM_PROT_ADD_CAP(new_prot) here, which always copies VM_PROT_READ to VM_PROT_READ_CAP, but should rather add VM_PROT_READ_CAP to new_prot if both new_prot & VM_PROT_READ and entry->max_protection & VM_PROT_READ_CAP (and similarly for VM_PROT_WRITE_CAP).

There's room to add PROT_READ_CAP and PROT_WRITE_CAP to the sys/sys/mman.h definitions, too, so we could expose those explicitly to userland, too, but that seems like a deeper change.

@jrtc27
Copy link
Member

jrtc27 commented Jul 23, 2021

There's room to add PROT_READ_CAP and PROT_WRITE_CAP to the sys/sys/mman.h definitions, too, so we could expose those explicitly to userland, too, but that seems like a deeper change.

That's #884 :)

@brooksdavis
Copy link
Member

There's room to add PROT_READ_CAP and PROT_WRITE_CAP to the sys/sys/mman.h definitions, too, so we could expose those explicitly to userland, too, but that seems like a deeper change.

That's #884 :)

Unfortunately #884 needs a complete rewrite. I realized I was inferring cap permissions inappropriately and haven't figured out the right model yet.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants