LWN.net Logo

Advertisement

E-Commerce & credit card processing - the Open Source way!

Advertise here

Pedantry

Pedantry

Posted Apr 5, 2008 9:46 UTC (Sat) by tialaramex (subscriber, #21167)
In reply to: What If I Don't Actually Like My Users? by JoeBuck
Parent article: What If I Don't Actually Like My Users?

It's not /impossible/ to get right although I agree that it provides no functionality you
would otherwise want that's not better implemented elsewhere in a modern POSIX API.

It's not impossible for the same reason that the non-thread safe functions aren't impossible
to get right, and the temporary file functions that aren't protected against races aren't
impossible to use safely. So long as you don't need that safety, they're fine. Similarly
gets() is fine so long as you don't need any protection against over-long strings.

e.g. suppose you have a socket, over which you receive instructions from a device driver in
the kernel, in this case gets() can be appropriate because the inverted privilege separation
means that crashing you with a buffer overflow achieves nothing - as a userspace process you
actually have less privileges than the kernel driver calling you. So long as there's an agreed
rule about buffer size (e.g. each instruction is the name of a file, so max pathname plus a
newline) and a mechanism ensuring that you are connected to that kernel driver as intended,
then gets() adds no new danger to your code.

Still, this is such a corner case, and there are so many better ways to approach this problem,
that the compiler/ linker is justified in complaining if you use this function in new code.

I've never found a sensible use for gets() in my own code, but I have used various other
"non-safe" functions, like tmpnam in contexts where the newer "safer" function didn't do what
I needed, and I judged that the safety issue was something I could cope with after reading
about it. I think I had to roll my own mkdtemp() some years ago for example, using "unsafe"
tmpnam and lots of careful reading of a treatise on race conditions in the filesystem.

A good example of an API that's _really_ impossible to use is one that Raymond Chen rants
about regularly, a Windows API call which purports to tell you whether a pointer is "valid" ie
whether you'd take a page fault if you tried to access it. This is simultaneously useless (it
doesn't do anything a userspace programmer should be trying to do) and dangerous (it will
itself inadvertently page in RAM if you call it on the edge of the stack for example) and
unreliable (the page may appear or vanish before control returns to your program with the
result). But having been foolishly offered to programmers in the past, Windows continues to
provide it for compatibility.


(Log in to post comments)

Pedantry

Posted Apr 5, 2008 10:05 UTC (Sat) by tialaramex (subscriber, #21167) [Link]

Ah, I got part of that last example wrong. It's dangerous because it will disable the stack
extension, ie it doesn't cause a new page to be mapped at the edge of the stack, but rather
overrides the runtime's automatic mapping of that page, returns to you an result that it isn't
yet mapped, but doesn't restore the stack extension behaviour. So suddenly, and without
explanation, your stack can't grow.

For a POSIX example that's less dangerous but just as unreliable/ useless, try access(2) which
attempts to guess whether you'd be allowed to do something, but can't assure you whether you
will or will not be able to do it if you actually try. It's not even useful for checks like
those in ssh which wants to see if you obeyed the rules for your own safety, since ssh needs
to check access permissions for /other users/.

Copyright © 2008, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds