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

RISC-V write-only page mappings #1119

Closed
Ivan-Velickovic opened this issue Oct 25, 2023 · 11 comments
Closed

RISC-V write-only page mappings #1119

Ivan-Velickovic opened this issue Oct 25, 2023 · 11 comments

Comments

@Ivan-Velickovic
Copy link
Contributor

Ivan-Velickovic commented Oct 25, 2023

The creation of write-only page mappings on RISC-V does not seem correct to me.

I believe if I create a mapping with only write permissions, the value of vmRights becomes 0x1 based on putting debug logging in the kernel.

A vmRights of 0x1 means that is the VMKernelOnly entry of the vm_rights enum. This means that in makeUserPte, the value of RISCVGetWriteFromVMRights(vm_rights) is 0, when it should actually be one. Hence, a mapping with write access does not get created.

What's more confusing is that the kernel code also has this comment: /* Write-only frame cap rights not currently supported. */. However it does not seem to be preventing the user from creating write-only mappings, unlike on ARM.

I don't know if I'm reading the code right, so I decided to make an sel4test test to try confirm my suspicions. You can find the patch here: Ivan-Velickovic/sel4test@169f157.

I ran on the HiFive Unleashed and QEMU RISC-V virt and observed a memory fault on both. The following log is from the HiFive Unleashed run:

SEL4TEST: vaddr is 0x10fb3000
SEL4TEST: attempting to write
Pagefault from [VSPACE0015]: write fault at PC: 0x590e8 vaddr: 0x10fb3000, FSR 0x7
Register of root thread in test (may not be the thread that faulted)
Register dump:
pc:	0x590e8
ra:	0x590e2
sp:	0x10011a30
gp:	0xbd3a0
s0:	0x10011a90
s1:	0x10011af0
s2:	0x0
s3:	0x0
s4:	0x0
s5:	0x0
s6:	0x0
s7:	0x0
s8:	0x0
s9:	0x0
s10:	0x0
s11:	0x0
a0:	0x0
a1:	0x0
a2:	0x0
a3:	0x0
a4:	0x3
a5:	0x10fb3000
a6:	0x0
a7:	0xfffffffffffffff7
t0:	0x59a6a
t1:	0xa9f95
t2:	0x0
t3:	0xfffffffffffffff6
t4:	0x8
t5:	0x39
t6:	0xe
tp:	0xe7850
	Failure: result == SUCCESS at line 296 of file /home/ivanv/ts/sel4test/projects/sel4test/apps/sel4test-driver/src/testtypes.c
	Error: result == SUCCESS at line 217 of file /home/ivanv/ts/sel4test/projects/sel4test/apps/sel4test-driver/src/main.c
Starting test 3: Test all tests ran
Test suite failed. 2/3 tests passed.
*** FAILURES DETECTED ***

If we look at the objdump we find the following instructions:

    *((char *)vaddr) = 3;
   590e2:	fb843783          	ld	a5,-72(s0)
   590e6:	470d                	li	a4,3
   590e8:	00e78023          	sb	a4,0(a5)

The program counter that caused the fault is at 0x590e8, which is indeed doing a write.

@lsf37
Copy link
Member

lsf37 commented Oct 25, 2023

Yes, I don't think write-only is supported on any of our architectures. You can provide the combination as input, but you can only actually create read, read-write, or kernel-only.

@Ivan-Velickovic
Copy link
Contributor Author

In that case I think we should make all the page mapping invocations consistent with ARM and report an error if the user tries to make a write-only mapping.

@axel-h
Copy link
Member

axel-h commented Oct 25, 2023

The RISC-V privileged spec explicitly says "Writable pages must also be marked readable; the contrary combinations are reserved for future use.". And in the table "Encoding of PTE R/W/X fields":

  • X=0, W=1, R=0: reserved for future use
  • X=1, W=1, R=0: reserved for future use

@lsf37
Copy link
Member

lsf37 commented Feb 7, 2024

In that case I think we should make all the page mapping invocations consistent with ARM and report an error if the user tries to make a write-only mapping.

That does make perfect sense and would not be a big change to verify (should affect the relevant decode functions only).

Do we have a volunteer for implementing it?

@kent-mcleod
Copy link
Member

It's already consistent with Arm. The behavior on arm if you request write only mapping is that it degrades to VMKernelOnly without returning an error. Systems may rely on silent downgrading of a request to read+write to read only if the underlying cap doesn't have write privileges. I guess what happens when requesting write only was unspecified as it's not a valid final request. But it's possible to have caps with write permissions and so should the kernel also return an error if someone requests a mapping with a cap that only has write rights?

@Ivan-Velickovic
Copy link
Contributor Author

When I made this issue I mistakenly thought that the kernel was returning an error on ARM for write-only mappings due to the kernel printing an error.

userError("Attempted to make unsupported write only mapping");

I guess I find the print confusing - is it trying to hint that user-space has potentially done something wrong or is it supposed to return an actual error?

@lsf37
Copy link
Member

lsf37 commented Feb 7, 2024

When I made this issue I mistakenly thought that the kernel was returning an error on ARM for write-only mappings due to the kernel printing an error.

seL4/src/arch/arm/64/kernel/vspace.c

Line 155 in 76eee24

userError("Attempted to make unsupported write only mapping");
I guess I find the print confusing - is it trying to hint that user-space has potentially done something wrong or is it supposed to return an actual error?

This generates just a warning, but I agree that it is a bit weird and should be consistent across architectures if we want the warning.

Actually making it an error would require an RFC, because it's a breaking API change. That doesn't mean we can't do it, but the question is if this is really worth a breaking change.

Maybe the only thing that is needed is to document this properly in the manual.

@Ivan-Velickovic
Copy link
Contributor Author

I guess we can start with having consistent error messages making it clear in the manual.

Are there any other cases in the kernel where a cap needs to have certain permissions for an invocation to be successful?

@lsf37
Copy link
Member

lsf37 commented Feb 8, 2024

I guess we can start with having consistent error messages making it clear in the manual.

Are there any other cases in the kernel where a cap needs to have certain permissions for an invocation to be successful?

Yes that is a normal kind of check. Whether it's wanted or not depends on each case.

@Ivan-Velickovic
Copy link
Contributor Author

I made #1261 and #1260 to try minimise future confusion.

I'm not the one who should decide whether the policy change is worth it, so I'm happy to close the issue or leave it up to someone else.

@lsf37
Copy link
Member

lsf37 commented Jun 11, 2024

With the behaviour specified in the manual, I'd be happy to close this. So far there does not seem to be any need for a policy change.

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

No branches or pull requests

4 participants