Slashdot Mirror


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

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

20 of 509 comments (clear)

  1. Don't be lazy programmers by Rick+Schumann · · Score: 5, Insightful

    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.

    1. Re:Don't be lazy programmers by Zontar+The+Mindless · · Score: 4, Funny

      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.

      --
      Il n'y a pas de Planet B.
    2. Re:Don't be lazy programmers by jma05 · · Score: 3, Insightful

      Dude, just search any software engineering journal. Unsafe languages make for more bugs. The design of the tool determines safety and performance as much as training, if not more.

      > Now go back to play with VB or JavaScript.

      Unfortunately people who happen to do unsafe code have this "eliteness" delusion. You are not smarter than anyone else. Write a large enough codebase and you will miss that buffer overflow somewhere, even though you know exactly what it is and have been on the lookout. Time and again, audits of well known software, written by very experienced programmers, show this.

      People are not machines and make mistakes. The only solution is to design tools and paradigms where entire classes of mistakes are not likely to occur in the first place. The checks need not be runtime checks with performance penalties, but if you want safety and security in the end product, the machine checks must be quite robust. Don't ever rely on humans for that, pretending you have "competent" programmers. Prove, don't assert.

      If programmers can't design languages that have safety features (with low costs) that everyone knows they need, how can anyone trust them to solve other domain problems?

    3. Re:Don't be lazy programmers by hey! · · Score: 4, Insightful

      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.

      --
      Post may contain irony: discontinue use if experiencing mood swings, nausea or elevated blood pressure.
    4. Re:Don't be lazy programmers by phantomfive · · Score: 3, Interesting

      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.

      --
      "First they came for the slanderers and i said nothing."
  2. Flummox the interviewer by Snotnose · · Score: 4, Interesting

    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.

  3. Don't give professional tools to amateurs by gweihir · · Score: 4, Insightful

    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.

    --
    Most ACs are not even worth the keystrokes to insult them. Be generically insulted by this and ignored otherwise.
    1. Re:Don't give professional tools to amateurs by gweihir · · Score: 3, Insightful

      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.

      --
      Most ACs are not even worth the keystrokes to insult them. Be generically insulted by this and ignored otherwise.
  4. Re:Here's why...Not invented here syndrome by Aighearach · · Score: 3, Insightful

    The exact same thing could be said about them wanting to switch to something new instead of learning C! In fact, if you're infected with NIHS you'd never be able to use an older generation of tools, you'd always need to adopt a new tool even when the old tools are better.

    Like people who need to use an app from some company so they can communicate, because email is "old."

  5. Re:Why not use Rust? by hackus · · Score: 5, Insightful

    Because the statement is hollow: "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."

    You have no scientific proof. It is your opinion.

    People have been attempting to replace C since it was conceived.

    Sort of like the idiocy in configuration management systems I see today.

    Lets throw RPM and well know configuration management tools we have used for the past 20 plus years like bash shell scripting and invent a way to configure boxes by adding not required additional daemons, Oh lets also throw in different languages and screwy config formats like YAML. That way we can boost the requirements on our resumes for higher salaries so we can make things incredibly overly complicated, to even updated a single .conf file in etc.

    I call BULLSHIT on you CF Engine, Puppet and Chef admins.

    Like these management systems such as puppet..etc....you have no proof these systems like rpm and C should be replaced for build, configuration or programming.

    Other than the fact it wasn't invented by a very naive generation of idiots out of college who like to pretend the last 20 years of the computing industry was a mistake and really doesn't exist.

    Just my opinion, but everyday I manage thousands of boxes with bash and rpms for config management. I also patch using the C language.

    Works great, and I don't need to learn Ruby, YAML, or create daemons for clients, or secure their firewalls...or...

    Well, you get the idea.

    --
    Got Geometrodynamics? Awe, too hard to figure out? Too bad.
  6. Re:Here's why...Not invented here syndrome by gweihir · · Score: 5, Insightful

    Nonsense. It is "if it is not broken, do not fix it." C is not broken and the majority of the kernel is already written in it. It is just a tool that requires you to know what you are doing. But that applies to kernel development anyways. Rust is for morons with delusions that do not have what it takes but think they can write advanced code anyways. They cannot. The language is not the main difficulty here.

    Incidentally, the believers in "just use this great new tool and all your problems will be solved" have been around forever, and they have been just as stupid way back as they are today. Brooks already had a chapter on it: "There is no silver bullet." Yet time and again, some people with little understanding of what matters claim that their pet-tool is that silver bullet.

    --
    Most ACs are not even worth the keystrokes to insult them. Be generically insulted by this and ignored otherwise.
  7. Never Ignore Warnings/Have Strong Coding Rules by mykepredko · · Score: 4, Insightful

    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.

    1. Re:Never Ignore Warnings/Have Strong Coding Rules by Tom · · Score: 4, Insightful

      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.

      --
      Assorted stuff I do sometimes: Lemuria.org
  8. Re:Why not use Rust? by russotto · · Score: 5, Insightful

    For one, Linux is written in C already. For another, Rust comes with an ideology. C doesn't care.

  9. Re:Why not use Rust? by zieroh · · Score: 4, Insightful

    For another, Rust comes with an ideology. C doesn't care.

    Oh, C definitely has an ideology: Do anything you want, but beware the consequences.

    Mind you, I'm quite comfortable with that. It's the kids raised on Java that shit their pants when they realize that C won't protect them from themselves. Since you can't (or at least shouldn't write an operating system in Java, they keep casting about for a suitable language that isn't C. But since nearly every operating system of note is written in C or a C derivative, I think we can safely assume for now that they're just chasing their own tales.

    --
    People who say "sheeple" have about as much sophistication as an AOL user, and in fact are probably actually AOL users.
  10. Re:Here's why...Not invented here syndrome by mikael · · Score: 3, Insightful

    At the level of kernel programming, you want a direct mapping of source code to assembly language, with no surprises or unexpected compiler optimisations - some early day compilers would pad out variables in C structures or even rearrange the order so it didn't match the source code.

    With Rust, something like macro overloading would be a code obfuscatory dream.

    --
    Vintage computer adverts: http://www.vintageadbrowser.com/computers-and-software-ads
  11. Re:C is dangerous... by jma05 · · Score: 4, Insightful

    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.

  12. C is beautiful by Tom · · Score: 4, Insightful

    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.

    --
    Assorted stuff I do sometimes: Lemuria.org
  13. Local variable initialisation by lyakh · · Score: 3, Informative

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

  14. Re:Have you ever stuck a fork under your fingernai by serviscope_minor · · Score: 4, Insightful

    The only way you get buffer overflows these days is if you turn OFF the standard warnings, and use deprecated functions, while writing C.

    That's bullshit. All you have to do is access an array with an incorrect index. You won't get a warning for that. And you won't even get it flagged with a run-time check until you feed it the wrong data. You know like heartbleed.

    IOW your claim is flat out false and implies you either don't program C or you're so misinformed about it that you're a menace if you do program it.

    Like almost all languages, Rust won't normally have buffer overflows. They've hyped that so much it would make PT Barnum blush, acting like that's something special.

    It's really not the most important thing about Rust. Though in fairness it seems that so many C hackers are so misinformed about their own language and still struggling that it apparently matters.

    the borrow checker actually prevents a wide class of memory errors and data races. The former are interesting enough, though not common in C++ (I occasionally have some). The latter is much more interesting though. If I was writing high performance (multithreaded) software with irregular structure then I'd be very seriously considering Rust since it seems to be the only language up to the task.

    I'm not though, so I'll stick to C++. I'm not naive enough though to think my language is perfect just because I learned it 20 years ago.

    every modern language is safe from buffer overruns assuming a competent programmer.

    That's a foolish claim because it's tautologically true while being misleading. Assembly language is free from buffer overrnus with a sufficiently competent programmer. In practice however everyone makes mistakes.

    --
    SJW n. One who posts facts.