Protecting private structure members
If one browses through the kernel code, it's easy to find comments warning of dire results should outside code touch certain structure fields. The definition of struct irq_desc takes things a bit further, with a field defined as:
unsigned int core_internal_state__do_not_mess_with_it;
Techniques like this work most of the time, but it would still be nice if the computer could catch accesses to structure members by code that should have no business touching them.
Adding that ability is the goal of this patch set from Boqun Feng. It takes advantage of the fact that the venerable sparse utility allows variables to be marked as "not to be referenced." That feature is used primarily to detect kernel code that directly dereferences user-space pointers, but it can also be used to catch code that is messing around with structure members that it has not been invited to touch. Not all developers routinely run sparse, but enough do that new warnings would eventually be noticed.
The patch set adds a new __private marker that can be used to mark private structure members. So the above declaration could become:
unsigned int __private core_internal_state__do_not_mess_with_it;
As far as the normal C compiler is concerned, __private maps to the empty string and changes nothing. But when sparse is run on the code, it notes that the annotated member is not meant to be accessed and will warn when anybody tries.
Of course, some code must be able to access that field, or there is little point in having it there. Doing so without generating a sparse warning requires first removing the __private annotation; that is done by using the ACCESS_PRIVATE() macro. So code that now looks like:
foo = s->private_field;
would have to become:
foo = ACCESS_PRIVATE(s, private_field);
This aspect of the patch could prove to be the sticking point: some code
may require a large number of ACCESS_PRIVATE() casts. Whether
they are added to the code directly or hidden behind helper functions, they
could lead to a fair amount of code churn if this feature is to be widely
used. Given that the honor system works most of the time and that problems
from inappropriate accesses to private data are relatively rare, the
development community may decide that the current system works well
enough.
Index entries for this article | |
---|---|
Kernel | Development tools |
Kernel | sparse |
Posted Jan 7, 2016 6:32 UTC (Thu)
by ashkulz (subscriber, #102382)
[Link] (2 responses)
foo = ACCESS_PRIVATE(s, private_field);
Posted Jan 7, 2016 13:36 UTC (Thu)
by corbet (editor, #1)
[Link]
Posted Jan 7, 2016 17:19 UTC (Thu)
by smurf (subscriber, #17840)
[Link]
Posted Jan 7, 2016 16:11 UTC (Thu)
by tdalman (guest, #41971)
[Link] (4 responses)
Posted Jan 7, 2016 17:41 UTC (Thu)
by JoeBuck (subscriber, #2330)
[Link] (2 responses)
In C++ you need to list friends in the class definition, but for purposes of sparse you could put the directives anywhere, even in an external file used only by sparse.
Posted Jan 11, 2016 9:42 UTC (Mon)
by rvfh (guest, #31018)
[Link] (1 responses)
Not saying I'm right or anything though, feel free to disagree.
Posted Jan 11, 2016 16:42 UTC (Mon)
by nybble41 (subscriber, #55106)
[Link]
The relevant question is "private to whom?" There are various reasonable levels of abstraction for class members, including members accessible to just their own class ("private" in C++ terms), a class and its subclasses ("protected"), a class/subclasses and designated helper ("friend") functions, or all code in the same module ("internal" in C#; no C++ equivalent).
In C, which has no classes or class member functions, the C# "internal" semantics would seem to make the most sense. One source module would declare itself as the implementation of the structure, and direct access to the field from any other source module would be flagged by sparse. The declaration could be placed in the source module itself or in the header file (IMPLEMENTED_BY(foo, "foo.c")).
Posted Jan 11, 2016 21:24 UTC (Mon)
by davidstrauss (guest, #85867)
[Link]
Protecting private structure members
Sigh, yet another silly mistake. Fixed, thanks.
Protecting private structure members
Protecting private structure members
Protecting private structure members
Yes, it's basically C++ private members. But instead of ACCESS_PRIVATE, it would be better to emulate another feature from C++: friends. If the function that accesses foo->private_field is a friend, it could do the access without a warning, no macro required. You could further improve over the C++ usage by telling sparse either that a given function is a friend of a given struct, or that a whole file is (so you could effectively have a module). That could be implemented with far fewer code changes.
Protecting private structure members
Protecting private structure members
Protecting private structure members
Yeah, and I prefer gcc's approach of using a defined subset of C++ rather than bolting the features onto C in a non-standard way.
Protecting private structure members