|
|
Subscribe / Log in / New account

flink() at last?

By Jonathan Corbet
August 7, 2013
There has long been a desire for an flink() system call in the kernel. It would take a file descriptor and a file name as arguments and cause the name to be a new hard link to the file behind the descriptor. There have been concerns about security, though, that have kept this call out of the kernel; some see it as a way for a process to make a file name for a file descriptor that came from outside — via exec(), for example. That process may not have had a reachable path to the affected file before, so the creation of a new name could be seen as bypassing an existing security policy.

The problem with this reasoning, as noted by Andy Lutomirski in a patch merged for 3.11-rc5, is that this functionality is already available by way of the linkat() system call. All it takes is having the /proc filesystem mounted — and a system without /proc is quite rare. But the incantation needed to make a link in this way is a bit arduous:

    linkat(AT_FDCWD, "/proc/self/fd/N", destdirfd, newname, AT_SYMLINK_FOLLOW);

Where "N" is the number of the relevant file descriptor. It would be a lot nicer, he said, to just allow the use of the AT_EMPTY_PATH option, which causes the link to be made to the file behind the original file descriptor:

    linkat(fd, "", destdirfd, newname, AT_EMPTY_PATH);

In current kernels, though, that option is restricted to processes with the CAP_DAC_READ_SEARCH capability out of the same security concerns as described above. But, as Andy pointed out, the restriction makes no sense given that the desired functionality is available anyway. So his patch removes the check, making the second variant available to all users. This functionality is expected to be useful with files opened with the O_TMPFILE option, but other uses can be imagined as well. It will be generally available in the 3.11 kernel.

Index entries for this article
Kernelflink()


to post comments

flink() at last?

Posted Aug 8, 2013 10:13 UTC (Thu) by khim (subscriber, #9252) [Link] (1 responses)

I see kernel developers adopt NASA attitude: We have also found that certification criteria used in flight readiness reviews often develop a gradually decreasing strictness. The argument that the same risk was flown before without failure is often accepted as an argument for the safety of accepting it again. Because of this, obvious weaknesses are accepted again and again—sometimes without a sufficiently serious attempt to remedy them, sometimes without a flight delay because of their continued presence.

We all know what was the end result in NASA's case and I'm afraid results for kernel will be similar.

If some desired-yet-dangerous functionality is available via some backdoor it's not enough justification to enable straightforward use of it! It may be better to close the backdoor…

I wonder what kind of disaster needs to happen before kernel developers accept that fact.

flink() at last?

Posted Aug 8, 2013 20:50 UTC (Thu) by rwmj (subscriber, #5474) [Link]

Hmmm. If there was any kind of rational model behind Linux security — for example a model with a small kernel which could be automatically proved correct — then this would make sense.

But Linux security is all over the place. There are surely many combinations of system calls that allow you to bypass checks and escalate privileges ("backdoors") and this is just one of them. No one has written the clever program to find the others yet, but it's just a matter of time.

Rich.

flink() at last?

Posted Aug 12, 2013 12:33 UTC (Mon) by spender (guest, #23067) [Link] (14 responses)

It would be a big mistake to implement flink based on Andy's false equivalency.

51f7f259cb6a0d5e380dcd2286c64118809d8df19761c1699b60001d55126c0b

Not that that will stop anyone: introduce vulnerabilities that have to be supported forever, ask questions later -- right?

-Brad

flink() at last?

Posted Aug 12, 2013 12:47 UTC (Mon) by johill (subscriber, #25196) [Link] (11 responses)

Care to elaborate on the "false" part of your claim?

flink() at last?

Posted Aug 12, 2013 13:30 UTC (Mon) by spender (guest, #23067) [Link] (10 responses)

Not really, given how upstream handles attribution and disclosure of publicly reported vulnerabilities:
http://seclists.org/oss-sec/2013/q3/279
http://seclists.org/oss-sec/2013/q3/284
http://seclists.org/oss-sec/2013/q3/285

-Brad

flink() at last?

Posted Aug 12, 2013 20:55 UTC (Mon) by luto (guest, #39314) [Link] (9 responses)

I'm not sure who "upstream" is. The advisory came to (at least) me and Oleg via Petr Matousek, citing a tweet that had no meaningful information. (Maybe it was the wrong link? Maybe we were supposed to figure out what "b836010000bb00000010cd80ebf2" meant?) I don't think that the patch should have been delayed while we tried to decipher the message.

I presume that 51f7f259cb6a0d5e380dcd2286c64118809d8df19761c1699b60001d55126c0b is the sha256 hash of something. If so, it will establish that you know something now, but it's not helping me or the other kernel contributors.

In any case, if you can explain what's wrong with my patch and if I fix it, I will certainly attribute it properly.

flink() at last?

Posted Aug 12, 2013 22:33 UTC (Mon) by PaXTeam (guest, #24616) [Link] (8 responses)

> I'm not sure who "upstream" is.

kernel devs who censor security related information from patches. (e.g., what happened to the CVE that was already assigned by the time the patch got written?)

> The advisory came to (at least) me and Oleg via Petr Matousek [...]

and what did his email start with? let's see:

> spender reported [...]

that and the link to his twitter weren't enough to figure out who to credit?

> Maybe we were supposed to figure out what "b836010000bb00000010cd80ebf2" meant?)

not sure who 'we' is, but Petr did that work for you regardless and if you hadn't quoted him selectively you'd have also realized what it meant:

> b836010000bb00000010cd80ebf2 is for(;;)unshare(1<<28);

can't be more concise, can it? one wonders how you were able to pull off that vsyscall change 2 years ago (nice not crediting me there btw) when you seemingly don't even recognize x86 asm.

> If so, it will establish that you know something now, but it's not helping me or the other kernel contributors.

yes, that's kinda the point behind publishing hashes only. as for helping you, we won't disclose such information because it would then be censored (just look at what happened recently with rmk's arm fixes) which is a game we will never play. this is not negotiable.

flink() at last?

Posted Aug 13, 2013 0:50 UTC (Tue) by luto (guest, #39314) [Link]

I didn't write the patch, so I had rather little to do with crediting anyone. And I completely failed to parse Petr's explanation. Sorry.

flink() at last?

Posted Aug 13, 2013 5:05 UTC (Tue) by alonz (subscriber, #815) [Link] (4 responses)

By saying "we won't disclose such information because it would then be censored" you're revealing your true face—helping the community is a minor goal compared to the fame you get by being credited for all the security bugs.

You've joined the dark side. Completely.

flink() at last?

Posted Aug 13, 2013 13:14 UTC (Tue) by spender (guest, #23067) [Link] (3 responses)

It's interesting that you twisted the quote in such a way as to create the straw man you want to demonize.

The main point was the complete absence of any mention of security impact in the commit message (what the "censorship" of disclosure) was referring to. Choosing not to attribute it as well was just the icing on the spite cake.

Here are the facts:
I reported this directly to Petr on IRC
I had already fixed the vulnerability myself in the one affected grsecurity patch the night before, with an unmistakable commit message
Security impact was known at the time the patch was created
A CVE had already been allocated prior to the patch being created

No CVE or impact at all was mentioned in the commit
It seems that despite a bug being a bug (according to Linus) the advice from Andrew Morton (https://lkml.org/lkml/2012/6/13/502) continues to be ignored quite often specifically for security vulnerabilities
https://git.kernel.org/cgit/linux/kernel/git/stable/linux...
Everyone whose name appears on that commit is complicit in the behavior, no matter what they say about how they really feel about the upstream security disclosure policies on private mailing lists or in private mail because they don't want to upset Linus' silent-fix campaign.

Since when does my sphere of responsibility extend beyond my own users? Any direct reporting we've done is not under any kind of obligation (of the kind upstream has to the code they distribute), and you should understand it in that context. We find and fix tons of problems in the upstream kernels, including finding many security fixes that fall through the backporting cracks (due in large part to the active cover-up policy) -- this is but one minor example because I chose to directly report it due to the apparent complete absence of QA regarding the use of unprivileged user namespaces. As I mentioned in my commit message, it's a trivial, 22 character local DoS (which I think may be the smallest ever reported).

Now, try hard to think about this as a smart person would: if some group were consistently finding vulnerabilities in my software, would it not be wise to monitor that code to spot those things, given that they're not being obfuscated at all? Apparently in 13 years, the Linux kernel devs still have not figured this one out. "That's work they shouldn't have to do!" a hypocrite might say. Yes, just as I shouldn't have to be scouring upstream commits (across all developers, not just us two, so there's quite some asymmetry of effort here) to find the silent security fixes falling through the cracks.

I believe in the old adage that actions speak louder than words. I've "joined the dark side" because I refuse to support and enable a system actively engaged in pulling the wool over your eyes as to the security of their code? Apparently as the arbitrator of ethics and morality, do you suggest I continue to piss away one-off vulnerabilities so they can be fixed in a one-off fashion with the associated coverup? Do you not see the long-term ramifications of that in pursuit of some short-term benefit?

-Brad

flink() at last?

Posted Aug 13, 2013 15:07 UTC (Tue) by idle (guest, #5017) [Link] (2 responses)

> The main point was the complete absence of any mention of
> security impact in the commit message

Well, the changelog explains that we leak the memory. Doesn't
this obviously mean the bad impact?

I do not think that the fact it was reported via oss-sec list
does matter, the bug is bug. In fact I didn't even notice this
list in CC.

But. I am really sorry I didn't add Reported-by tag, seriously.
This is only because I didn't know whom should we thank. I sent
the patch for review and I specially asked about the reporter,
but the patch was merged immediately and I could not update the
changelog.

flink() at last?

Posted Aug 13, 2013 15:41 UTC (Tue) by spender (guest, #23067) [Link] (1 responses)

Does it? There are no matches for either "leak" or "memory" in the commit message.

There is only vague mention of unspecified "side effects" that need "taking care of" in response to a function failure. Failures can be of the unfailable kmalloc+GFP_KERNEL kind, after all. I wonder how anyone, not already knowing about the CVE and public disclosure from elsewhere, would have any clue what the impact of that fix is.

Are you really trying to say the commit message was written with clarity and transparency of the impact of the fix in mind, without some Linus-enforced brain filter on what words you're allowed to use to describe the "bug"?

-Brad

flink() at last?

Posted Aug 13, 2013 16:07 UTC (Tue) by idle (guest, #5017) [Link]

> Does it? There are no matches for either "leak" or "memory"
> in the commit message.

I thought that "take care of" should be clear enough, and it
mentions put_cred().

> There is only vague mention of unspecified "side effects"

This just tries to explain why the patch didn't change the
caller instead, the patch would be even simpler.

> Are you really trying to say the commit message was written
> with clarity and transparency of the impact of the fix in mind

OK. When I reread it I agree, it could be more clear. Trust me,
this was not intentional. I did not try to "hide" the fact this
patch fixes the easily triggable memory leak.

It would be just silly, exactly because it was not me who founf
the bug!

> Linus-enforced brain filter on what words you're allowed to
> use to describe the "bug"?

What are you talking about ;) Nobody will ever try to force you
obfuscate the changelog.

flink() at last?

Posted Aug 13, 2013 8:14 UTC (Tue) by mpr22 (subscriber, #60784) [Link] (1 responses)

There's a difference between recognizing x86 machine code and recognizing x86 assembler; it's not like it's a PDP-11 where the octal dump is human-readable with only a modicum of skill.

flink() at last?

Posted Aug 13, 2013 8:41 UTC (Tue) by PaXTeam (guest, #24616) [Link]

> There's a difference between recognizing x86 machine code and recognizing x86 assembler[...]

not the least because an assembler (a tool) is a very different animal from assembly (a language) and my use of 'asm' didn't refer to either ;).

flink() at last?

Posted Aug 22, 2013 22:15 UTC (Thu) by spender (guest, #23067) [Link] (1 responses)

Just to update, so I'm not seen to be making anything up or scaring off strangely urgently-needed "progress" without basis, I've published the plaintext of the above SHA256 hash at http://grsecurity.net/~spender/flink.txt

spender@www:~/public_html$ cat flink.txt
think of a chroot without /proc mounted
process has a file with r/w access opened for read only
process then chroots to place without /proc mounted
flink will allow to hardlink a file outside of the chroot to the inside
allowing r/w access to the file
spender@www:~/public_html$ sha256sum ./flink.txt
51f7f259cb6a0d5e380dcd2286c64118809d8df19761c1699b60001d55126c0b ./flink.txt
spender@www:~/public_html$ ls -al flink.txt
-rw-r--r-- 1 spender spender 252 Aug 12 08:30 flink.txt

There had been some discussion in private I guess but no progress, so Willy contacted me in private (hopefully not as an example of http://www.storyit.com/Classics/Stories/foxcrow.htm). The above matches up with what I explained to Willy in private mail that I believe was then passed on to security@kernel.org that the current /proc/pid/fd behavior is a security problem in the context of the old arguments against flink (from 1998!, 2002, 2003, etc) but that Andy's change made it even worse by extending that problem into chroots where /proc typically is not mounted, resulting in an initial patch some very short time later. See:
https://lkml.org/lkml/1998/3/12/84
https://lkml.org/lkml/2002/1/20/41
https://lkml.org/lkml/2003/4/6/167
https://lkml.org/lkml/2003/4/7/23

Something about those who don't learn from history are doomed to repeat it...

FWIW I strongly urged some kind of comprehensive documentation regarding the "interesting corner cases" and how they're affected by Xat(), AT_EMPTY_PATH, chroot, namespaces, etc, since no single person is going to be able to ramble every combination of ramifications off the top of their head, and there's a very small group of people right now deciding how the interfaces work.

Khim above really nailed the problem of the slippery slope; I'm at least encouraged that this particular problem doesn't seem to be being fixed in a one-off fashion.

You can see the public discussion here:
https://lkml.org/lkml/2013/8/21/492
https://lkml.org/lkml/2013/8/21/519

-Brad

flink() at last?

Posted Aug 31, 2013 18:08 UTC (Sat) by wtarreau (subscriber, #51152) [Link]

Hey Brad,

Concerning "Willy contacted me in private (hopefully not as an example of http://www.storyit.com/Classics/Stories/foxcrow.htm)", I wanted to confirm this was not such an example (it's a bit hurtful), I was sincere and wanted to see progress made after I failed on your challenge for a whole week-end looking in the wrong direction (as you noticed BTW).

Then I passed my understanding of the problem (no single line of your e-mail as you requested) to the sec list, my understanding was not 100% accurate but that was enough for others to guess it and at the same time you corrected me, then Andy replied with you and LKML in Cc so you had the rest of all the thread.

And the thread that started next on how to globally solve the issue goes in the direction you hoped for. It was a good exercise for me but I think that if you had explained your concern to the authors from the start we'd have saved one week (but I wouldn't have learned the *at syscalls :-)).

I still hope to see you one day participate to this list to help fix critical issues faster and/or better.

Cheers,
Willy


Copyright © 2013, 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