

The security hole in sudo - casca
http://nakedsecurity.sophos.com/2012/05/21/anatomy-of-a-security-hole-the-break-that-broke-sudo/

======
EvanAnderson
I've always felt like the switch statement's "break" behavior should have been
the implicit case, with a statement to trigger fallthrough if you really
wanted it. I wonder what percentage of the time fallthrough is actually
desired in switch statements. I would assume it's wildly in the minority.

~~~
natesm
C# doesn't have fallthrough at all, but it won't compile without "break;". I'm
really not sure what they were going for there.

~~~
pcwalton
You can "goto" any case label in C#, which works like fallthrough but is more
flexible (since you can jump anywhere). At the same time, it avoids the
refactoring hazard associated with fallthrough, in which changing the order of
the switch labels can change the behavior of the code. Of the languages that
have "switch" (not counting ML/Haskell-style pattern matching here), C#'s
approach seems ideal.

~~~
kstenerud
The C# approach sounds like a recipe for abuse:

    
    
        switch(something)
        {
            case 1:
                // Do stuff
                goto case 4;
            case 2:
                // Do stuff
                goto case 1;
            case 3:
                // Do stuff
                goto case 5;
            case 4:
                // Do stuff
                goto case 3;
            case 5:
                // Do stuff
                break;
        }

~~~
PotatoEngineer
That's quite horrible! Fortunately, it's _obviously_ horrible, and since
"goto" has such a stigma attached to it, programmers will only use it when
it's necessary. (Cross your fingers.)

~~~
mkr-hn
register_globals would like to have a word with you.

------
klez
The missing break has been the sort of bug that haunts me at least twice a
month at my current job.

We do car diagnostics and we code in C. Endless time I would not understand
why a particular path was not taken, and a missing break was the answer.

Now, I can see the utility of fall-thru switch construct, but this is a kind
of bug that could be avoided at the syntax level. Just don't require a break
and develop another syntax for fall-thru cases.

~~~
ajross
Or just don't use switch. If it's a small expression, an if/else chain takes
no more lines of code and is not less efficient. If it's a large expression,
it might be better expressed with a function pointer table.

I'm not a zealot on this stuff, and write switch statements regularly (though
I do strongly prefer if chains for most stuff) but if you're really hitting
this regularly I think a change in process might be in order.

~~~
DHowett
It can be slightly less efficient when (on supporting architectures) the
compiler could automatically generate a jump table in place of stacked
conditionals, which it cannot do for a chain of ifs.

~~~
ajross
This is a myth that won't die. Jump tables can't be branch predicted, so
they're generally significantly slower unless the number of cases is very
high. And it's not true that the compiler "cannot" emit a jump table for an if
chain anyway. A bunch of if/else-if expressions of the form "some_var ==
constant" can certainly be detected (though again, it probably isn't).

------
pnathan
Yet another avoidable bug.

Over time, I've come to believe C is deadly flawed, and greenfield projects
should seriously investigate languages that are better designed.

Trivial errors in C like dangling elses, fallthroughs in switches, and easy
buffer-overruns by default say to me that C's broken, has been broken, and
will continue being broken.

For non-realtime apps, I would recommend pretty much _anything_ but C; for
realtime apps, I would be looking into things like SystemC or D and choose
appropriately.

This class of avoidable bug should not be happening in 2012.

~~~
JoachimSchipper
C _does_ have issues, but lots of people are complaining about things that are
easily solved by using the proper tools. Turn on compiler warnings and/or use
a lint tool.

(For reference, a project I have at hand is compiled with -std=c99 -pedantic
-W -Wall -Wno-sign-compare -Wno-unused-parameter -Wbad-function-cast -Wcast-
align -Wchar-subscripts -Wfloat-equal -Wmissing-declarations -Wmissing-format-
attribute -Wmissing-noreturn -Wmissing-prototypes -Wnested-externs -Wpointer-
arith -Wshadow -Wstrict-prototypes -Wwrite-strings -Wundef -Werror and uses
lint to check for improper conversion between types.)

~~~
hesselink
So it's not broken, only broken by default. Because having to add three lines
of command line flags to get sane behavior doesn't seem like a good default to
me.

~~~
figglesonrails
Truthfully, C does what you tell it to do. As it turns out, most people don't
want it to do what they tell it to do, they want it to do what is in their
head. Those warnings are "did you really mean what you just told me to do?".
For some people, the answer is "no, what, wait!" -- those are what they are
for. Not that the behavior is insane, just "less common". I don't think people
fully grasp the idea that C does what you tell it to do when they first start
using it.

If you told C "make me a sandwich", it'd give a warning about not having
enough mustard to cover your entire body and an error about not have a large
enough bun type to fit you in.

~~~
JoachimSchipper
This is facile; there is no good reason why C couldn't have a less-dangerous
switch statement, or why compilers don't have nicer defaults. (If you run gcc
without -W -Wall -O2, you either really know what you're doing or you're doing
it wrong; in either case, having those options as defaults makes sense.)

~~~
joshAg
There are many cases where fall through switch statements are preferable, but
that's almost beside the point. C is basically just portable assembler with
syntactic sugar sprinkled on top. Assembler doesn't have less dangerous switch
statements and switch statments. Assembler has branching and jumping. That
break statement in c is almost literally telling the assembler to jump out of
a chain of branch statements after probably returning from a jal of the
function within the same case block. Adding an extra switch statement just
takes the language farther away from assembler and makes compiling more
complicated, which is silly since the unsafe switch statement with break
statements will/should produce the exact same assembler (this is different
from the difference between using if{}else{ if...} chains and using switch,
which will produce different assembler code).

To make it even more fun, there are many use cases for fall through switch
statements. My personal favorite is duff's device, which is an unwrapped
version of a serial copy that will run faster on certain architectures than a
more typical serial copy will run: send(to, from, count) register short _to,_
from; register count; { register n = (count + 7) / 8; switch(count % 8) { case
0: do { _to =_ from++; //this is for a memory mapped register. case 7: _to =_
from++; // use _to++ for non memory mapped registers case 6:_ to = _from++;
case 5:_ to = _from++; case 4:_ to = _from++; case 3:_ to = _from++; case 2:_
to = _from++; case 1:_ to = *from++; } while(--n > 0); } }

~~~
shurane
I thought duff's device was one of the few examples that use fall through
switch statements. I was taught to use switches with blocks, because otherwise
unexpected things happen.

------
jiggy2011
Sudo has always felt like a bit of a blunt instrument to me.

For example having to type the root password every time I want to run a
vaguely administrative program or install something etc gets old fast.

Not to mention the number of times I've made a bunch of edits to something
like a conf file in nano and then gone to save and got "permission denied"
where the only solution seems to be to exit nano and run it again (and do the
edits again) with sudo. Surely it should be able to prompt me for the password
at save time?

~~~
lubutu
Sudo has authentication timeouts built in, so you don't have to type in your
password ( _your_ password, not root's) every time you want to run an
administrative program. Also, the fact that you have to sudo is one of the
reasons why Unix is more secure than the Windows "administrator by default"
approach.

As for your last point, you're complaining about nano. It would be perfectly
possible for an editor to sudo when writing to disk.

~~~
jiggy2011
This is something that seems to be the case on vi and emacs too, I have never
seen a unix program which prompts me for sudo password at the moment that it
needs to do a privileged operation rather than requiring running via sudo.

~~~
TheCapn
When I vi a read-only file:

    
    
         "/etc/mail/aliases" [Read only] 36 lines, 1023 characters
    

Its simply a matter of remaining keen when doing admin tasks. Sure I have to
close/re-open with sudo but its prompting me up front that I won't be able to
save it.

~~~
anoother
> Sure I have to close/re-open with sudo but its prompting me up front that I
> won't be able to save it.

No, you don't, and yes, you will:

    
    
      :w !sudo tee %

------
kstenerud
Would be nice if compilers offered a warning for missing breaks in a switch
statement, and a pragma to mark fallthrough:

    
    
        switch(something)
        {
            case 1:
                // Do stuff
                break;
            case 2:
                #pragma switch_fallthrough
            case 3:
                // Do stuff
                break;
            #pragma switch_nodefault
        }

~~~
there
lint will warn about those cases unless they are marked in the code with /*
FALLTHROUGH */. I think even if you're not using lint, such comments are good
practice.

------
m_for_monkey
This snippet is ugly anyway. The case-bodies are not indented, the one-liner
if-bodies are missing their brackets, asking for more trouble.

------
joeld42
This is why I always put a "fall through" comment in place of break if I
intend to omit it, and always put a blank line after each case. Once I got in
the habit of this, it makes spotting this bug pretty easy.

------
robertduncan
Why was the incredibly important caveat -- this vulnerability only affects
configurations which are using netmask-based permissions -- left to the last
paragraph?

------
rmoriz
I still wonder why they don't do ATDD. Even when you use a statically typed
language there is plenty of room for failure.

I recommend using:

\- vagrant <http://vagrantup.com/>

\- toft <https://github.com/exceedhl/toft/>

\- cucumber <http://cukes.info/>

\- aruba <https://github.com/cucumber/aruba>

to write/reverse engineer examples/user stories.

~~~
raverbashing
No

Enough with the nonsense. TDD is great for some tools, in some situations.
It's not a "solve all". And now comes "ATDD", people should start working
instead on inventing acronyms.

vagrant? really, REALLY?

Try QEMU. Try chroot

News flash, sudo is not a RoR application. Especially sudo with all the magic
that goes behind executing a process as another user.

~~~
rmoriz
"Especially sudo with all the magic that goes behind executing a process as
another user."

Your last sentence kills your standpoint totally.

Please check out the mentioned "toft". It's lxc inside vagrant and designed to
test complex infrastructure code from the outside in. Nothing web related.

------
vampirechicken
C is fine. C is C. If you want a better C, create one. You could name it
something clever like C+=1, or C++.

