Follow Slashdot blog updates by subscribing to our blog RSS feed

 



Forgot your password?
typodupeerror
×
Programming

How Linux's Kernel Developers 'Make C Less Dangerous' (hpe.com) 509

Hewlett-Packard's Enterprise blog summarizes a talk by Linux kernel developer Kees Cook at the North America edition of the 2018 Linux Security Summit. Its title? "Making C Less Dangerous." "C is a fancy assembler. It's almost machine code," said Cook, speaking to an audience of several hundred peers, who understood and appreciated the application speed resulting from C... Over time, Cook and the people he worked with discovered numerous native C problems. To deal with these weaknesses, the Kernel Self Protection Project has worked slowly and steadily on protecting the Linux kernel from attack. In the process, it has worked to remove troublesome code from Linux....

With its operational baggage and weak standard libraries, C contains a great deal of undefined behavior. Cook cited -- and agreed with -- Raph Levien's blog post "With Undefined Behavior, Anything Is Possible." Cook gave concrete examples. "What are the contents of 'uninitialized' variables? Whatever was in memory from before! Void pointers have no type, yet we can call typed functions through them? Sure! Assembly doesn't care: Everything can be an address to call! Why does memcpy() have no 'max destination length' argument? Just do what I say; memory areas are all the same!" Some of these idiosyncracies are relatively easy to deal with. Cook commented, "Linus [Torvalds] likes the idea of always initializing local variables. So, you should 'just do it....'"

The long-term solution? More security-savvy open source developers... While at times, the idea of coming up with a Linux C dialect has been attractive, that's not going to happen. The real issue behind the problem of dangerous code is "people don't want to do the work to clean up code -- not just bad code, but C itself," he said. As with all open source projects, "we need more dedicated developers, reviewers, testers, and backporters."

LWN.net has its own run-down of Cook's talk, as well as a link to a PDF file of his slides.

"Sound good," posted one of their commenters, "though ultimately I'd like kernel devs to adopt Rust as their main Linux kernel development language. Beats the crap out of C and C++ combined."
This discussion has been archived. No new comments can be posted.

How Linux's Kernel Developers 'Make C Less Dangerous'

Comments Filter:
  • by Rick Schumann ( 4662797 ) on Saturday September 01, 2018 @08:49PM (#57239582) Journal
    C/C++ is not an 'amateur night' programming language, it's not 'child proofed', it doesn't hold your hand like you're a child, you can write entire operating systems in it, and as such it's supposed to have access to anything and everything, and that just so happens to include mucking up the OS of the machine you happen to be testing your code on. 'Sanitizing' it, 'child proofing' it would take away that power and make it useless. At that point you may as well just be writing things in BASIC or some other interpreted language that doesn't allow you access to anything terribly powerful or important. I've never heard anyone refer to C/C++ (or languages of similar power) as 'dangerous' before. I think it more likely that programmers have become lazy, or just aren't educated enough to be responsible with a powerful programming language, and as a result we end up seeing code that's sloppy, ill-behaved, and 'dangerous' because of it. Just like people complaining about how bad drivers are (and that we should ban humans from driving and make them use automation instead, which is stupid), someone wants to take the power away, when the real, rational solution is better education/training/testing. Have schools become lazy in how prospective programmers are educated and how their knowledge is tested? Then lets fix that problem rather than making decent programmers (and drivers) live in a world where the ability to really be behind the wheel and in control of the machine is taken away from them, because some people can't cut it.
    • by Zontar The Mindless ( 9002 ) <plasticfish@info.gmail@com> on Saturday September 01, 2018 @09:02PM (#57239634) Homepage

      I've never heard anyone refer to C/C++ (or languages of similar power) as 'dangerous' before.

      I took a Numerical Linear Algebra class in which you were expected to use C. First thing the instructor said was, "This is not a class for children, and so you will write your assignments using C. If you can't be trusted with a pair of scissors, you definitely cannot be trusted with a chainsaw. C is a chainsaw. Deal with it, or come back next semester when the other guy will let you use the blunt scissors known as 'Pascal'." This was in 1986, BTW.

      • by jma05 ( 897351 )

        Yeah, in the 80s, they were having silly holy wars between C and Pascal. Fortran was the better tool for linear algebra code then.

        • by novakyu ( 636495 )

          Back then? There are linear algebra libraries still in use which is written in Fortran. Other languages just link to it, rather than re-implementing it natively.

        • by mikael ( 484 )

          That brings back memories. Our database theory lecturer absolutely hated any language with pointers or had to be compiled (C, C++, Fortran, Modula-2) and would constantly state that 4GL's like SQL, Prolog and Microsoft Basic were the future

          • Apropos of nothing: yours is the lowest user ID I've ever had comment on one of my comments before; hail, Centurion! :-)

            I remember the first time I ever heard that some actual high-end commercial application software was written in BASIC; I think I almost fell on the floor laughing, thinking it was some sort of crude joke. Then imagine my face when I found out it wasn't a joke. :-/
      • Well, you sure as heck don't want to use something like R for that, the class would be too easy. With the code in C, you'd have to actually implement the whole algorithm!

      • Sounds like one hell of an asshole professor. Reminds me of those managers who insist on using whatever JS trend is in vogue rather then what's actually appropriate for the job, just trades out the willful ignorance for self-centered edginess. Honestly, the amount of selfishness it takes to potentially screw over his student's academic schedules just to fulfill his own self-importance about a programming language, which isn't even fundamentally part of the course, is just astounding to me.
    • Re: (Score:3, Insightful)

      by jma05 ( 897351 )

      > it's not 'child proofed'

      Programming languages, in general, need to be human proofed. We have a ton of empirical data to support this for decades.

      > 'Sanitizing' it, 'child proofing' it would take away that power and make it useless.

      No, it does not. Programming languages like Rust allow you to do all the unsafe stuff you want. It is just that they are safe by default, but you can step out anytime you need to.

      > I think it more likely that programmers have become lazy, or just aren't educated enough

      • Not going to help with a project like an OS kernel. Almost everything needs to be "unsafe".
        • by jma05 ( 897351 )

          Yes, there is a case for C in kernels, drivers etc.

          But most of the C in the wild is for things that should never have been written in C in the first place - hence a lot of avoidable security holes.

          • IME nothing creates a security hole faster than the programmer thinking that just choosing Virtuous tools will somehow protect them from making mistakes.

            The reality is that mistakes flee the light, but you still make just as many, being human. Like trying to reduce crime by increasing the policing of places with the most reports; it is easy to push the criminals from one street to another street, but much harder to reduce the crime rate.

            Only an approach where the programmer has increased knowledge at both h

            • by jma05 ( 897351 )

              > IME nothing creates a security hole faster than the programmer thinking that just choosing Virtuous tools will somehow protect them from making mistakes.

              To me, that would be like arguing that we should not have guard rails because they will make people complacent or that seat belts might make people drive recklessly or that if we make smoking expensive or inconvenient, people will still get cancers by other means.

              Of course, there will always be the case of automation complacency and there will be other

        • by gweihir ( 88907 )

          And that is just the point. Kernels, drivers, high-performance software all are inherently unsafe. The only thing that can make them save is coders that really know what they are doing. These seem to be slowly dying out and the mediocre ones that follow want their safe space instead.

          • by jma05 ( 897351 )

            Unfortunately, C and C++ are used heavily beyond the kernels and drivers.

            • Back when my non-work-hours hobby was sitting there all night long writing software for one project or another of mine, everything I did was in C, and I managed to not melt the computer into a heap of slag on the desk in the process. Guess I lucked out. xD
              • by jma05 ( 897351 )

                Who is talking about melting computers?
                I am talking about bugs and security holes.

      • by zieroh ( 307208 )

        Programming languages, in general, need to be human proofed.

        I call bullshit, and I'll put my decades of industry experience on that. Programmers need to fucking pay attention to what they're doing. There are no languages in the world that prevent the programmer from making serious structural mistakes. It's up to the programmer to know what the fuck they're doing.

        Fuck Rust. Seriously.

        • by mikael ( 484 )

          The one thing that could be done (and was done in the past), was to allow each thread to sandbox the areas of memory that it was working with. You could use a couple of instructions that the programmer could use to instruct the virtual memory manager to lock out and unlock regions of memory that shouldn't be touched, so only the memory used by class objects could be accessed. Or it could be done intrinsically.
          Any memory access errors would be trapped.

        • by jma05 ( 897351 )

          > I call bullshit, and I'll put my decades of industry experience on that.

          I don't care for your claims of experience. I have been programming for decades as well.

          > Programmers need to fucking pay attention to what they're doing.

          Of course they do. "Attention" however has very weak reliability. This is a very well established fact by psychology studies.

          > There are no languages in the world that prevent the programmer from making serious structural mistakes.

          There are however programming languages that

      • If I already knew how to use C properly, already know better than to use uninitiallized pointers, not return heap space when I'm done with it, etc etc etc then why would I even need it?
    • by gweihir ( 88907 )

      Unfortunately, the believers in silver bullets will not die out.

    • > I've never heard anyone refer to C/C++ (or languages of similar power) as 'dangerous' before.

      It is obvious you haven't been using C/C++ very long, Bjarne Stroustrup said this [stroustrup.com] about C and C++

      C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off.

      There is even a famous book:

      Enough Rope to Shoot Yourself in the Foot: Rules for C and C++ Programming [amazon.com]

    • by zieroh ( 307208 )

      I think it more likely that programmers have become lazy

      This. I've spent the last five years hiring software engineers. I've phone screened more than I can count. The Java programmers being churned out by university CS programs today are atrocious.

      Pro Tip: If you mostly studied Java in college, you should go back to your alma mater and ask for a refund. No, seriously.

    • This is a ridiculous and terrible argument. The rest of the world advances both the tools and the education to make better systems that are more fault tolerant. The infrastructure in this world is built using better tools with what we learned from doing it the old way. You're asking for airplanes to be built only using hammers and screwdrivers instead of power tools and robots. C has it's place in this world. It will always be a great teaching language or for people that like to tinker close to assembly, bu

      • This is a ridiculous and terrible argument. The rest of the world advances both the tools and the education to make better systems that are more fault tolerant. The infrastructure in this world is built using better tools with what we learned from doing it the old way. You're asking for airplanes to be built only using hammers and screwdrivers instead of power tools and robots

        The problem I have with this line of thought is lack of apparent outcomes commensurate with claims.

        Obviously airplanes are built with modern technology using complex tooling. Some of the major assembly plants offer public tours where you can witness a small portion of it in action with your own eyes.

        If "C" is just hammers and screwdrivers where is the equivalent of the modern plant maximally leveraging technology to churn out airplanes that couldn't possibly be done with hammers and screwdrivers? It seems

      • Gee I wonder what this 'Rust' everyone keeps mentioning was written in? xD
    • by Tablizer ( 95088 )

      The "be a big boy" argument dodges the real question here: can a programming language be efficient (stay close to the metal) yet have sufficient checks and balances on itself? Would making it safer automatically make it more resource intensive*?

      If there is an inherent and fundamental trade-off, and C (as it is) merely chooses the close-to-metal far spot on this spectrum, then the be-a-big-boy argument makes sense (assuming you want Linux "fast"). However, I've yet to see anyone make a strong argument that t

      • by phantomfive ( 622387 ) on Sunday September 02, 2018 @05:24AM (#57240912) Journal

        I wonder if C or another language could not rely on API's or API-like expansion macros. A given shop would select the API's that fit its trade-off profile. If you wanted to skip pre-initialization for speed, you'd use the skipping version of an initializer API. And on the flip side, don't include the non-init API in the shop stack if you don't want accidental naked bits.

        I worked for a company that did something similar......they wrote their own version of malloc() etc to avoid memory leaks. About a year after I started working there, the Javascript coders had to spend several weeks fixing all the memory leaks in their code. The C coders had none. Ignoring the problem doesn't make it go away.

    • by hey! ( 33014 ) on Saturday September 01, 2018 @11:02PM (#57239984) Homepage Journal

      You know what really sets mature adults apart from wet-behind-the-ears kids? They accept that they're fallible.

      Language safety got a bad reputation back in the 70s when I learned to program because language designers didn't know how to do it without getting in the way of ordinary work. So back then given a choice of K&R C or the Pascal dialects available, I'd have chosen K&R C because Pascal's strict type checking made common use-cases awkward. But there's absolutely no question that modern ANSI C's stricter type-safety makes it far better than K&R C.

      You can't rely on a language to do your job for you, but you can certainly rely on a language to make your job easier.

    • you can write entire operating systems in it

      You can write entire operating systems in many languages. C\C++ isn't special in this regard.

    • by Durrik ( 80651 )
      I blame Moore's Law and smaller transistors. And that might end sooner rather than later.

      Most coders get to deal with fast processors, fast ram, and its always getting faster and faster. So sloppy programming can be covered with more overhead provided in more recent languages. Java & C# don't really have the concepts of memory allocation and clean up, that's all handled by the overhead. Python & Perl and other similar languages don't even need to worry about what types are passing through the sy
  • by Snotnose ( 212196 ) on Saturday September 01, 2018 @08:51PM (#57239594)
    Some 20 years ago I was consulting for a company that needed $BigCompay approval to release software. While at $BigCompany I ran across an old boss, who flat out said "interview with us, you're in". I did.

    One guy asked the standard string reversal question, in C. I put a pointer at each end of the string and walked them together. The guy was completely flummoxed, it was like he'd never encountered an answer he hadn't thought of. This was like the second question he asked me, we spent the rest of the interview me explaining my solution, he never understood it.

    Guy turned out to be my sorta boss (matrix management means the guy you report to has no say in your performance review). He was a good guy, one of the early employees of the company, but as time went on I realized he did not understand C pointer arithmetic.

    Mind you, this guy was smarter than me, and more driven. But he had never done assembly programming, hence he never really understood C pointers.

    Me? Started with Z-80 assembly, moved to 8080, 8086, then 80386, which is when I learned C. Took to C pointers like a duck to water.

    FWIW, the company I was consulting for never paid me for my last month (2 bi-weekly paychecks). Lots of phone calls, meetings, and fights. Huge reason I quit consulting and went back to working for companies.
    • I use C pointers every day.

      And I try hard not to accidentally learn to understand them. I've seen the code those people write.

  • by gweihir ( 88907 ) on Saturday September 01, 2018 @09:13PM (#57239654)

    That is basically the thing that applies to C code and has applied to it from the beginning. In the hands of somebody that knows what they are doing, C is not more dangerous than any other language.

    • by jma05 ( 897351 )

      They are all "professional" tools by definition. Don't use unsafe tools unless absolutely necessary is the lesson.

      > In the hands of somebody that knows what they are doing, C is not more dangerous than any other language.

      Completely wrong. Even people who "know what they are doing" (most think they do, but really don't. C enables entire classes of problems that simply don't exist elsewhere), still make avoidable errors with C because they are only human. This is not really an opinion. We know matter-of-fa

      • by gweihir ( 88907 )

        You overlook that the language brings in a very small part of the difficulty of any software project. And, incidentally, depending on the application pretty much every tool is "unsafe". The advantage of C is that the incompetent coders fail early and obviously.

        • by jma05 ( 897351 )

          > The advantage of C is that the incompetent coders fail early and obviously.

          Actually, it is the opposite. With C, bugs exist silently without generating either compile time errors or obvious runtime errors.

    • by dfghjk ( 711126 )

      Yes, and C is neither a "fancy assembler" nor "almost machine code". These are statements of an ignorant person.

      Yes, "we can call typed functions through" "void pointers" but we do so by declaring what that the pointer type is, and this is not possible because "Assembly doesn't care" but because it is useful. Seriously, this guy is an idiot. While I have no doubt "Cook and the people he worked with discovered numerous native C problems", I also have no doubt that countless programmers discovered them lo

      • by gweihir ( 88907 ) on Saturday September 01, 2018 @09:57PM (#57239796)

        Having used a fancy assembler, I agree. C is in a whole different class, because with that fancy assembler, most of what you do is find out about the target CPU and and low-level I/O. And you do that again for every hardware architecture. With C you just need to know the coding model of the language and the language itself is way more powerful than even the most souped-up assembler. Sure, there are a few fine details in C where being able to do any assembler variant is really helpful in understanding then, but that does not make C some kind of assembler at all.

        I do agree that this guy is an idiot. He carters to all the coders that fancy them bad-ass but that cannot write solid C code and blame the tool for that.

  • So treat it like one. JavaScript coders should go work on Atom or something.

  • by mykepredko ( 40154 ) on Saturday September 01, 2018 @09:23PM (#57239700) Homepage

    Before I read TFA, I was expecting to learn something about C coding that I didn't before.

    I learned years before to NEVER, NEVER, NEVER ignore warnings. Very smart people put in those warnings and you should take heed of them. The example given (initializing a local variable in a switch) is something that you should never do - initialization must always be done outside of conditional code. If the initialization value changes according to conditions, then initialize the variable at the define with an invalid value and then test for it when you use the value outside the switch statement.

    Demanding that there must be a clean build with no warnings before code goes to QA is a great way of minimizing unexpected problems down the road (I have found that before QA tests any code, they build it and send it back if any warnings come back). It doesn't take a lot of work to fix warnings and if the coder doesn't understand the reason for the warning, then they should be educated as to the reasons why it is a problem.

    There are a number of APIs and constructs (like strncpy, memcpy and VLAs) mentioned in the article that never be used as a matter of course. Their use should be laid out clearly in the coding rules/guidelines and it only takes a few seconds to add grep statement to a make file to look for specific APIs and terminate the build if they're found. I've done this for years for teams that I've lead and there's usually a bit of grumbling but when you explain the reasons why you should always get compliance.

    From my experience, inadvertent coding (security) issues comes from not having a strong set of build (acceptance) and coding rules right from the beginning of a project.

    • by gweihir ( 88907 )

      Yes. At least "-Wall" and when some warning is really not an error (it happens), tell the compiler explicitly to ignore the thing at the specific place where it happens.

    • I can't count the number of times I downloaded some open source that didn't work out of the box, or had some bug, and when I went to fix it the compiler spit out pages of warnings... well, I don't roll like that, so I usually resolve all of those first. And the original bug is gone, like 85% of the time.

      Of course, that means sending in a patch would be useless, but that is a whole different ball of earwax.

    • by Tom ( 822 ) on Sunday September 02, 2018 @01:22AM (#57240346) Homepage Journal

      I learned years before to NEVER, NEVER, NEVER ignore warnings.

      This.

      Amateurs fix their code until all errors are gone.
      Professionals fix it until all warnings are done.

      • Professionals fix it until all warnings are done.
        By writing

        #pragma ignore warning 101

        above every offending line ;D

  • by 0100010001010011 ( 652467 ) on Saturday September 01, 2018 @10:16PM (#57239866)

    We have MISRA [wikipedia.org] and the Barr Group Embedded C Coding Standard [barrgroup.com]

    Start producing code that passes those checks and I bet a lot of the 'issues' go away.

  • by GerryGilmore ( 663905 ) on Saturday September 01, 2018 @11:10PM (#57240010)
    ....kernel developers actually know how to use C.
    Seriously...C is an extremely efficient and powerful language, but it must be wielded by thos who know how to use its power.
    Every time I thought I knew a little C, one of my programmers - who really knew his shit - would just blow my mind with some of his routines. Function calls that returned pointers to the next function (state-machine type stuff) just blew my mind first time I saw it used. Blindingly fast, but damned difficult to debug.
    Even with my background in assembler, some of their stuff was just amaizing.
    OTOH, I would never consider writing, say, an ERP app in C, but for kernel work, interface routines, etc. it just cannot be beat.
    • Re: (Score:3, Insightful)

      by jma05 ( 897351 )

      > Function calls that returned pointers to the next function (state-machine type stuff) just blew my mind first time I saw it used. Blindingly fast, but damned difficult to debug.

      The article is partly about avoiding such cleverness.

      From the article: "You can do almost anything with C, but that doesn't mean you should. "

      C is a "dangerous language" (in the words of the kernel developer) as is. The last thing one should be doing is to make it worse with black magic like this. If you want to get clever with

  • If only... (Score:2, Informative)

    C could be a lot better at being closer to the machine. It actually lacks several features in order to placate defunct architectures.

    * stdint-style types for size_t, ptrdiff_t, etc...
    . - allows better portability for embedded
    . . 1. ex. size8_t for indices that won't exceed 255
    * lacks largest integer register type
    * vector types and extensions - use arm's naming (optional?)
    * only single word tokens (ex. unsigned long long double complex)
    * ascii only (ebcdic et.al are defunct) => 'z
  • by magzteel ( 5013587 ) on Saturday September 01, 2018 @11:41PM (#57240104)

    There's nothing new here.

    Different languages have their strengths and weaknesses. I've coded professionally in assembly, Plus, Pl/1, C, C++, C#, Perl, Python, Basic, Visual Basic, Java, Javascript, Bash, TCL, TK, and probably a few more I've long forgotten. Right now Java is a great fit for the problem domain I'm working in. Fortunately I can express myself well in it and the Java developer tools and ecosystem are great.

    When C is the appropriate tool I don't hesitate to use it. But I don't hesitate to use my chainsaw when I'm cutting up trees either.
    You just have to know what you are doing before you start the engine.

  • ...to the incompetent.
    • by jma05 ( 897351 ) on Sunday September 02, 2018 @12:53AM (#57240274)

      RTFA: "Even if you're a C expert, as are most of the Linux kernel developers, you can still make killer blunders."

      If you think you are immune to C dangers, you aren't an experienced programmer at all.

      • If you think you are immune to C dangers

        Never said that. Would be more like "If you pretend to be immune to C dangers...". Of course C has its dangers, but even more so when people think they can program in C because they're used to Java or another high level language.

  • C is beautiful (Score:5, Insightful)

    by Tom ( 822 ) on Sunday September 02, 2018 @01:20AM (#57240336) Homepage Journal

    Oh, I love C. In my mind, you cannot call yourself a programmer unless you have delivered at least one non-trivial piece of software in C.

    Why?

    Because C is the no-training-wheels programming language. It is the "I'm not saving you from yourself" language. And more importantly, it is the "I will do what you say, not what my compiler writers think that you maybe meant" language. C will do what you tell it to do, it is the original embodiment of the Unix philosophy. It doesn't second-guess the programmer. If I do that, the computers job is to execute, not to think I'm an idiot and can't write code. I probably meant to dereference that pointer, I probably somehow made sure that it's safe and if the compiler can't see it then it assumes that it is wrong, not me.

    Such beauty.

    Of course, like professional tools in the physical world, in the hands of amateurs they instantly become dangerous. Don't give a chainsaw to a five year old, ok? Not a good idea. And don't give dynamite to a teenager, or something will get blown up and you don't know what.

    So is it dangerous? You bet it is. Does it produce insecure code? Almost certainly because very, very few people can actually handle that stuff safely. And no, I don't count myself among them, it's been way too long since I actually wrote code in C.

    But there is something to the beauty and the immediacy of having a computer not trying to think for you.

  • by lyakh ( 1659815 ) on Sunday September 02, 2018 @02:49AM (#57240568)
    "Linus [Torvalds] likes the idea of always initializing local variables." That's new to me. I've seen and often requested myself many cases of redundant local automatic variable initialisation, don't remember seen any backlash against them.

Think of it! With VLSI we can pack 100 ENIACs in 1 sq. cm.!

Working...