Content-Length: 20954 | pFad | http://lwn.net/Articles/670237/

Protecting private structure members [LWN.net]
|
|
Subscribe / Log in / New account

Protecting private structure members

By Jonathan Corbet
January 6, 2016
Most languages designed in the last few decades offer a way to restrict access to portions of a data structure, limiting their use to the code that directly implements the object that structure is meant to represent. The C language, initially designed in 1972, lacks any such feature. Most of the time, C (along with the projects using it) muddles along without this kind of protective feature. But that doesn't mean there would not be a use for it.

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
KernelDevelopment tools
Kernelsparse


to post comments

Protecting private structure members

Posted Jan 7, 2016 6:32 UTC (Thu) by ashkulz (subscriber, #102382) [Link] (2 responses)

The last example is incorrect: you have to access it as

foo = ACCESS_PRIVATE(s, private_field);

Protecting private structure members

Posted Jan 7, 2016 13:36 UTC (Thu) by corbet (editor, #1) [Link]

Sigh, yet another silly mistake. Fixed, thanks.

Protecting private structure members

Posted Jan 7, 2016 17:19 UTC (Thu) by smurf (subscriber, #17840) [Link]

… which still is more concise than "s->private_field__do_not_mess_with_it".

Protecting private structure members

Posted Jan 7, 2016 16:11 UTC (Thu) by tdalman (guest, #41971) [Link] (4 responses)

Interesting to see more and more concepts from C++ being introduced in the Linux kernel ...

Protecting private structure members

Posted Jan 7, 2016 17:41 UTC (Thu) by JoeBuck (subscriber, #2330) [Link] (2 responses)

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.

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.

Protecting private structure members

Posted Jan 11, 2016 9:42 UTC (Mon) by rvfh (guest, #31018) [Link] (1 responses)

I'm not very fond of friends which seem to contradict the idea if private members. I'd be more inclined to say that this feature just provides private members (here private_field) and accessors (here ACCESS_PRIVATE) to read the variable. Writing should only be done by the class itself.

Not saying I'm right or anything though, feel free to disagree.

Protecting private structure members

Posted Jan 11, 2016 16:42 UTC (Mon) by nybble41 (subscriber, #55106) [Link]

> I'm not very fond of friends which seem to contradict the idea if private members.

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")).

Protecting private structure members

Posted Jan 11, 2016 21:24 UTC (Mon) by davidstrauss (guest, #85867) [Link]

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.


Copyright © 2016, Eklektix, Inc.
This article may be redistributed under the terms of the Creative Commons CC BY-SA 4.0 license
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds









ApplySandwichStrip

pFad - (p)hone/(F)rame/(a)nonymizer/(d)eclutterfier!      Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

Fetched URL: http://lwn.net/Articles/670237/

Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy