Skip to content
This repository has been archived by the owner on Jan 24, 2022. It is now read-only.

Add a section to place the veneers in memory #297

Merged
merged 1 commit into from
Oct 1, 2020

Conversation

hug-dev
Copy link
Contributor

@hug-dev hug-dev commented Oct 1, 2020

The veneers are for now only generated by the Arm GNU linker when it
spots an entry function (one that was decorated with the
cmse_nonsecure_entry attribute).
Adding this section will allow to configure the SAU to make this section
Non-Secure Callable.

Doing tests locally I could not see any warnings if this section was empty so I think this is fine. It is highly specific to the GNU toolchain so maybe you would want some preprocessing directive and cfg options which I am happy to add.

There is documentation for the section name at the end of this page.

It needs to be aligned on 32 bytes as a requirement from the Security Attribute Unit.

@hug-dev hug-dev requested a review from a team as a code owner October 1, 2020 10:52
@rust-highfive
Copy link

Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @adamgreig (or someone else) soon.

If any changes to this PR are deemed necessary, please add them as extra commits. This ensures that the reviewer can see what has changed since they last reviewed the code. Due to the way GitHub handles out-of-date commits, this should also make it reasonably obvious what issues have or haven't been addressed. Large or tricky changes may require several passes of review and changes.

Please see the contribution instructions for more information.

@hug-dev
Copy link
Contributor Author

hug-dev commented Oct 1, 2020

With this then one can do:

let peripherals = Peripherals::take().unwrap();
let mut sau = peripherals.SAU;

// Those symbols come from the linker file.
extern "C" {
    static mut __veneer_base: u32;
    static mut __veneer_limit: u32;
}
let base_nsc = unsafe { core::mem::transmute::<&mut u32, u32>(&mut __veneer_base) };
let limit_nsc = unsafe { core::mem::transmute::<&mut u32, u32>(&mut __veneer_limit) };

// Non-Secure Callable area
sau.set_region(2, SauRegion {
    base_address: base_nsc,
    limit_address: limit_nsc | 0x1F,
    attribute: SauRegionAttribute::NonSecureCallable,
}).unwrap();

sau.enable();

to configure its Non-Secure Callable section 🚀

__veneer_base = .;
*(.gnu.sgstubs*)
__veneer_limit = .;
} > FLASH
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are there any plans to support this in other linkers, like LLD? Presumably those won't use the GNU section, so we should make sure that we can support that without having multiple definitions of the __veneer_ symbols.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are there any plans to support this in other linkers, like LLD?

I am not aware of any plans for LLVM tools.

That's a good point. I think it is possible to have #define in linker scripts and pass preprocessor constants to activate some code or not. We could do something like that in the future to either choose the LLVM or GNU sections, using the link-arg option in .cargo/config.

Alternatively we can prefix those symbols with gnu_ for now (eg __gnu_veneer_base).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it worth putting those symbols immediately outside the .gnu.sgstubs section, for the same reasons we have with the other sections? That way we could define multiple sections within those symbol bounds, or users could define their own in memory.x without needing to change link.x.in.

Should the end symbol be aligned?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it worth putting those symbols immediately outside the .gnu.sgstubs section, for the same reasons we have with the other sections?

Sure that sounds like a good idea! That could solve the problem we were talking just before. Do you mean with "users could define their own in memory.x without needing to change link.x.in" that users will be able to override those symbols to put the ones they want?
If that is the case I would be a little bit worried. The content of what is in between __veneer_base and __veneer_limit can be an entry point to the Secure world, needs to be as small as possible and carefully audited. Although Secure application developpers ultimately need to be trusted that is maybe better to leave those symbols being only maintained here, just to avoid possible errors that could lead to security issues?

Should the end symbol be aligned?

It is fine if it is not, ultimately you would do limit_nsc | 0x1F as in the example above to align it with 32 bytes anyway. Maybe better to keep the information of the real size of the veneers there.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Users (the top-level project, not libraries) can already override anything in link.x.in (by specifying their own link.x). If the symbols are outside the section, then users can put a new section into their memory.x and specify INSERT AFTER .gnu.sgstubs and the section will be 'inside' the start/end symbols but with whatever name they require.

In any event nothing stops any user or library code writing #[link_section=".gnu.sgstubs"], right?

Re alignment, sure, I don't mind too much. Aligning it in the linker means we don't need to OR it in the code, but you lose knowledge of the 'actual size' (does anything need to know that, though?).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In any event nothing stops any user or library code writing #[link_section=".gnu.sgstubs"], right?

😨 oops that is a very valid point and I have just done a test to try putting another function in the .gnu.sgstubs section with that attribute. I will look into it a bit more but if there is no protection from the linker against that it would mean that the Secure application developper needs to trust all of its dependencies. A malicious one could put a backdoor entry function in the veneers section...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Malicious dependencies can already do pretty much whatever they want, so that doesn't seem like an issue to me

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea, you have to trust all your dependencies anyway. They can all run arbitrary code at build time, so...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes you are both absolutely right, it will always come down to the fact that you have to trust your dependencies to not contain security vulnerabilities/be malicious. How a Secure application developper can be sure this is the case is another topic and does not concern this PR.

I will update the PR as discussed but would still like to keep the __veneer_limit symbol unaligned. It could be used as a way to count the number of entry functions declared in all the dependency graph as well (well if no malicious crate modify all of the build system 😰).

The veneers are for now only generated by the Arm GNU linker when it
spots an entry function (one that was decorated with the
cmse_nonsecure_entry attribute).
Adding this section will allow to configure the SAU to make this section
Non-Secure Callable.

Signed-off-by: Hugues de Valon <[email protected]>
@hug-dev hug-dev force-pushed the add-veneers-sections branch from 65e5158 to c599230 Compare October 1, 2020 21:45
@hug-dev
Copy link
Contributor Author

hug-dev commented Oct 1, 2020

Ok I did the change, I hope this is what you were expecting. I think this is fine to align everything to 4 bytes as veneers are 32 bits long (two thumb instructions). Only the start is aligned to 32 bytes because of SAU requirements.

Copy link
Contributor

@jonas-schievink jonas-schievink left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bors r+

@bors
Copy link
Contributor

bors bot commented Oct 1, 2020

@bors bors bot merged commit 96525a6 into rust-embedded:master Oct 1, 2020
@hug-dev hug-dev deleted the add-veneers-sections branch October 2, 2020 08:55
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants