Journal jd's Journal: How to improve C/C++ code quality, random thoughts 1
I am thinking about the following concept. Take doxygen comments and extend them as follows.
1. Permit identification of pre-conditions for functions (what has to be true when the function is called)
2. Permit identification of post-conditions for functions (what is intended to be true when the function exits)
3. Permit identification of hints about what kernel operations are being used by that function
A static checker can run through a library or program and determine if the pre- and post-conditions all balance out (so that you can't call something with out-of-range parameters).
A kernel operations compiler can run through the hints and clarify them through code inspection, building up for that file what kernel permissions the functions inside claim they need. If you then link files to make a library, it can assemble the permissions for the whole library by performing a set union on the permissions needed. If you link to make a program, it can likewise assemble the permissions for the whole program. If a function needs kernel operations but no relevant hint is given, it can give an error and tell you what class of permissions is needed for that function.
The idea is that, for a given function, the requirements of that function will be (general kernel capabilities
This needs a little more clarification. A function needs all of the permissions required by itself AND all of the functions that it calls. If a third-party library is used which doesn't have the corresponding map provided, then the programmer would need to include in the markup which areas are needed to support the functions that are called. With no further information, this will lead to more permissions than absolutely needed, but only in very confined areas. If the third-party library ever gets such markup added, then you're back to the absolute minimal set of permissions needed.
This permissions map would let you inspect to see if the program needed to do something you weren't expecting, but it would also permit a policy compiler to take those permissions and compile an actual SELinux policy specific to that program that you knew contained everything the program definitely needed and nothing more.
This would solve most of the SELinux problems, because the programmer and compiler would collaborate to define the requirements, but the programmer would be free to loosen them up if there are hidden requirements that only get detected during testing.
The practical upshot is that nobody would be obliged to apply these features, but if they did, they'd be able to apply them to the degree suitable for what they were doing, thus creating a level of assurance the programmer could determine rather than one that was imposed.
To implement this, we'd need the following tags added in doxygen:
For the validation:
@precondition (what must be true when the function is called)
@postcondition (what must be true when the function ends)
@modifies (any shared resource that is modified by the code)
For the security labelling:
@krequires (hints detailing the high-level kernel requirements, stuff that can be directly narrowed down from source inspection by a validator)
@kinvokes (hints detailing the low-level kernel requirements - these can't be optimised away and you'd only give them if you knew in fine detail what was needed through to the system calls)
@kneeds (hints detailing what high-level kernel requirements a library is going to need )
How much safety does this give? (Score:2)
It obviously gives us guarantees in terms of what the source will do and what the compiled code should need.
These do not provide memory safety, so memory bugs would not be solved by these. They will find unexpected behavioural issues, though.
The precondition and postcondition statements are not cunningly-disguised assert statements because they're not asserted at runtime. They're enforced at static check and/or compile time.
The policy hints mean that if the kernel is doing something you're not expecting, yo