--- a/mm/mmap.c 2006-01-25 15:02:24.000000000 +0300
+++ b/mm/mmap.c 2006-09-21 13:19:15.000000000 +0400
@@ -899,10 +899,6 @@
if (!file->f_op || !file->f_op->mmap)
return -ENODEV;
-
- if ((prot & PROT_EXEC) &&
- (file->f_vfsmnt->mnt_flags & MNT_NOEXEC))
- return -EPERM;
}
/*
* Does the application expect PROT_READ to imply PROT_EXEC?
@@ -911,8 +907,7 @@
* mounted, in which case we dont add PROT_EXEC.)
*/
if ((prot & PROT_READ) && (current->personality & READ_IMPLIES_EXEC))
- if (!(file && (file->f_vfsmnt->mnt_flags & MNT_NOEXEC)))
- prot |= PROT_EXEC;
+ prot |= PROT_EXEC;
if (!len)
return -EINVAL;
--- a/mm/nommu.c 2006-04-12 09:37:34.000000000 +0400
+++ b/mm/nommu.c 2006-09-21 13:21:32.000000000 +0400
@@ -493,13 +493,7 @@
capabilities &= ~BDI_CAP_MAP_DIRECT;
}
- /* handle executable mappings and implied executable
- * mappings */
- if (file->f_vfsmnt->mnt_flags & MNT_NOEXEC) {
- if (prot & PROT_EXEC)
- return -EPERM;
- }
- else if ((prot & PROT_READ) && !(prot & PROT_EXEC)) {
+ if ((prot & PROT_READ) && !(prot & PROT_EXEC)) {
/* handle implication of PROT_EXEC by PROT_READ */
if (current->personality & READ_IMPLIES_EXEC) {
if (capabilities & BDI_CAP_EXEC_MAP)
On Sat, 23 Sep 2006, Stas Sergeev wrote:
> Hi Andrew.
>
> I am not sure at all whether this patch is appreciated
> or not. The on-list query yielded no results, but I have
> to try. :)
Probably not appreciated :) I agree with your earlier mail, that
those mmap MNT_NOEXEC checks don't give any watertight protection:
they're more a heuristic to prevent the wrong thing happening
automatically. But they were put in for good reason, have been
in for nearly three years, I doubt they should come out now.
It's hardly any surprise, is it, that if a distro chooses now
to mount something "noexec", a problem is then found with a few
things which want otherwise? And it seems unlikely that the answer
is then to modify the kernel, to weaken the very protection they're
wanting to add?
The original 2.6.0 patch (later backported into 2.4.25) was
<[email protected]>
[PATCH] Fix 'noexec' behaviour
We should not allow mmap() with PROT_EXEC on mounts marked "noexec",
since otherwise there is no way for user-supplied executable loaders
(like ld.so and emulator environments) to properly honour the
"noexec"ness of the target.
so let's CC Ulrich Drepper in case he's changed his mind on it.
Hugh
>
> This patch removes the MNT_NOEXEC check for the PROT_EXEC
> mappings. That allows to mount tmpfs with "noexec" option
> without breaking the existing apps, which is what debian
> wants to do for sequrity reasons:
> http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=386945
> More details here:
> http://uwsg.ucs.indiana.edu/hypermail/linux/kernel/0609.2/1537.html
>
> Signed-off-by: Stas Sergeev <[email protected]>
>
> --- a/mm/mmap.c 2006-01-25 15:02:24.000000000 +0300
> +++ b/mm/mmap.c 2006-09-21 13:19:15.000000000 +0400
> @@ -899,10 +899,6 @@
>
> if (!file->f_op || !file->f_op->mmap)
> return -ENODEV;
> -
> - if ((prot & PROT_EXEC) &&
> - (file->f_vfsmnt->mnt_flags & MNT_NOEXEC))
> - return -EPERM;
> }
> /*
> * Does the application expect PROT_READ to imply PROT_EXEC?
> @@ -911,8 +907,7 @@
> * mounted, in which case we dont add PROT_EXEC.)
> */
> if ((prot & PROT_READ) && (current->personality & READ_IMPLIES_EXEC))
> - if (!(file && (file->f_vfsmnt->mnt_flags & MNT_NOEXEC)))
> - prot |= PROT_EXEC;
> + prot |= PROT_EXEC;
>
> if (!len)
> return -EINVAL;
> --- a/mm/nommu.c 2006-04-12 09:37:34.000000000 +0400
> +++ b/mm/nommu.c 2006-09-21 13:21:32.000000000 +0400
> @@ -493,13 +493,7 @@
> capabilities &= ~BDI_CAP_MAP_DIRECT;
> }
>
> - /* handle executable mappings and implied executable
> - * mappings */
> - if (file->f_vfsmnt->mnt_flags & MNT_NOEXEC) {
> - if (prot & PROT_EXEC)
> - return -EPERM;
> - }
> - else if ((prot & PROT_READ) && !(prot & PROT_EXEC)) {
> + if ((prot & PROT_READ) && !(prot & PROT_EXEC)) {
> /* handle implication of PROT_EXEC by PROT_READ */
> if (current->personality & READ_IMPLIES_EXEC) {
> if (capabilities & BDI_CAP_EXEC_MAP)
Hugh Dickins wrote:
> so let's CC Ulrich Drepper in case he's changed his mind on it.
Definitely not. The test should stay. It does the right thing. Yes,
some applications might break, but this is the fault of the application.
--
➧ Ulrich Drepper ➧ Red Hat, Inc. ➧ 444 Castro St ➧ Mountain View, CA ❖
Hi.
Hugh Dickins wrote:
> automatically. But they were put in for good reason, have been
> in for nearly three years, I doubt they should come out now.
I know they won't. I only thought I have to try, after seeing
the debian problem and googling out a few negative posts about
these checks.
> It's hardly any surprise, is it, that if a distro chooses now
> to mount something "noexec", a problem is then found with a few
> things which want otherwise?
They do not "want otherwise". They do the right thing - use
shm_open() and then mmap(), but mmap() suddenly fails. The apps
are not guilty. Neither I think the debian guys are.
> And it seems unlikely that the answer
> is then to modify the kernel, to weaken the very protection they're
> wanting to add?
I don't think they want to prevent PROT_EXEC mmaps. Almost
certainly not. Maybe they thought they would only block mere
execve() calls and the like, I don't know. My point is that
this change (use of "noexec") should not break the properly
written apps, but right now it does. Is it stated anywhere
in the shm_open() manpage or elsewhere that you must not use
"noexec" on tmpfs or you'll get troubles with mmap?
> The original 2.6.0 patch (later backported into 2.4.25) was
> <[email protected]>
> [PATCH] Fix 'noexec' behaviour
> We should not allow mmap() with PROT_EXEC on mounts marked "noexec",
> since otherwise there is no way for user-supplied executable loaders
> (like ld.so and emulator environments) to properly honour the
> "noexec"ness of the target.
Thanks for the pointer, but that looks like the user-space
issue to me. Why ld.so can't figure out the "noexecness" and
do the right thing itself? Or does it figure out the "noexecness"
exactly by trying the PROT_EXEC mmap and see if it fails?
Hi.
Ulrich Drepper wrote:
> Definitely not. The test should stay. It does the right thing. Yes,
> some applications might break, but this is the fault of the application.
But why exactly? They do:
shm_open();
mmap(PROT_READ|PROT_WRITE|PROT_EXEC);
and mmap fails.
Where is the fault of an app here?
On Sat, 23 Sep 2006, Stas Sergeev wrote:
> Hugh Dickins wrote:
>
> > It's hardly any surprise, is it, that if a distro chooses now
> > to mount something "noexec", a problem is then found with a few
> > things which want otherwise?
> They do not "want otherwise". They do the right thing - use
> shm_open() and then mmap(), but mmap() suddenly fails. The apps
> are not guilty. Neither I think the debian guys are.
Debian wants /dev/shm mounted "noexec" for whatever reason,
these apps want otherwise: to be able to mmap PROT_EXEC on it.
>
> > And it seems unlikely that the answer
> > is then to modify the kernel, to weaken the very protection they're
> > wanting to add?
> I don't think they want to prevent PROT_EXEC mmaps. Almost
> certainly not. Maybe they thought they would only block mere
> execve() calls and the like, I don't know. My point is that
> this change (use of "noexec") should not break the properly
> written apps, but right now it does. Is it stated anywhere
> in the shm_open() manpage or elsewhere that you must not use
> "noexec" on tmpfs or you'll get troubles with mmap?
No, it's not. But this doesn't have much to do with tmpfs,
nor with shm_open. It's just that the kernel is not allowing
mmap PROT_EXEC on a MNT_NOEXEC mount. Which seems reasonable
(though you can argue that mprotect ought to disallow it too).
If that's a problem for something, don't mount "noexec"
(but I'm not the one to recommend a secure configuration).
>
> > The original 2.6.0 patch (later backported into 2.4.25) was
> > <[email protected]>
> > [PATCH] Fix 'noexec' behaviour
> > We should not allow mmap() with PROT_EXEC on mounts marked "noexec",
> > since otherwise there is no way for user-supplied executable loaders
> > (like ld.so and emulator environments) to properly honour the
> > "noexec"ness of the target.
> Thanks for the pointer, but that looks like the user-space
> issue to me. Why ld.so can't figure out the "noexecness" and
> do the right thing itself?
That would be tiresome work.
> Or does it figure out the "noexecness"
> exactly by trying the PROT_EXEC mmap and see if it fails?
Exactly.
Hugh
Hi.
Hugh Dickins wrote:
> nor with shm_open. It's just that the kernel is not allowing
> mmap PROT_EXEC on a MNT_NOEXEC mount. Which seems reasonable
Even for the MAP_PRIVATE mmaps? But what does that solve?
Even if you restrict mprotect() too, the malicious app will
simply read() the code in the anonymously mapped region,
while the properly-written code just breaks.
Is it documented in any spec or done in any other system?
> If that's a problem for something, don't mount "noexec"
Yes, I myself think "noexec" is rather useless and can always
be bypassed. But whether that particular handling is correct,
doesn't look obvious to me.
>> Thanks for the pointer, but that looks like the user-space
>> issue to me. Why ld.so can't figure out the "noexecness" and
>> do the right thing itself?
> That would be tiresome work.
>> Or does it figure out the "noexecness"
>> exactly by trying the PROT_EXEC mmap and see if it fails?
> Exactly.
So do you mean such a checks were added as a quick hack till
the proper solution is implemented? That may explain the issue,
at least partially...
Ar Sad, 2006-09-23 am 17:04 +0100, ysgrifennodd Hugh Dickins:
> No, it's not. But this doesn't have much to do with tmpfs,
> nor with shm_open. It's just that the kernel is not allowing
> mmap PROT_EXEC on a MNT_NOEXEC mount. Which seems reasonable
> (though you can argue that mprotect ought to disallow it too).
Agreed mprotect should also be fixed.
Hello.
Alan Cox wrote:
> Agreed mprotect should also be fixed.
Since "noexec" was already rendered useless - yes.
Before, people could use it and hope the binaries
won't get executed (and if it was possible to execute
them by invoking ld.so directly, then ld.so could have
been fixed). Now the only possibility is to not use the
"noexec" at all.
So does that add to security or substract?..
On Sun, 24 Sep 2006, Stas Sergeev wrote:
> Alan Cox wrote:
> > Agreed mprotect should also be fixed.
> Since "noexec" was already rendered useless - yes.
> Before, people could use it and hope the binaries
> won't get executed (and if it was possible to execute
> them by invoking ld.so directly, then ld.so could have
> been fixed). Now the only possibility is to not use the
> "noexec" at all.
> So does that add to security or substract?..
I'm very puzzled. The intention of "noexec" is to prevent execution
of files on that mount. You're saying it's useless because it's
preventing execution of files on that mount? It seems to me that
you simply have a mount where "noexec" presents more problems than
it solves: so don't use it there. That doesn't mean it's useless:
not every mmap involves PROT_EXEC, not every mount demands execution.
Hugh
Hi.
Hugh Dickins wrote:
>> Since "noexec" was already rendered useless - yes.
> I'm very puzzled. The intention of "noexec" is to prevent execution
> of files on that mount. You're saying it's useless because it's
That was actually a bad english on my side, sorry
(English is not my native lang). Instead of "useless"
I meant to say "changed to the point where it cannot be
effectively used any more".
> preventing execution of files on that mount?
What exactly the "execution" consist of here? You are
not going to prevent an execution of some perl scripts
etc, dont you? So IMHO that applies to only the execution
of the native binaries, ie, similair to just removing the
exec permission from all the files on that partition. Or
at least that's how I understand it. And clearing an exec
permission doesn't disable PROT_EXEC, AFAIK.
> It seems to me that
> you simply have a mount where "noexec" presents more problems than
> it solves: so don't use it there.
I am not at all an expert in a security but I think the point
of "noexecing" the partitions was to make it difficult for an
attacker to put his own binaries somewhere and execute them.
In this case (but I may be wrong) leaving tmpfs without noexec
prevents that goal from being achieved even if all the other
writeable partitions are noexeced, because an attacker will
use /dev/shm for his binaries then. Just my guesses though.
> That doesn't mean it's useless:
> not every mmap involves PROT_EXEC, not every mount demands execution.
I think it is now more useless than before because that
restriction breaks *only* the properly written apps, while
the malicious ones are completely unaffected. That forces
the people to use it rarely than before (not on tmpfs), and
so it looses its use almost completely, leaving at least that
partition executable.
Why only the properly-written apps breaks is because they use
MAP_SHARED - that you *can* effectively protect from PROT_EXEC,
provided you restrict also mprotect(). The malicious apps are
unaffected because they will not use MAP_SHARED, but instead
just read() the binary into the anonymously mapped area with
PROT_EXEC set. ld.so could certainly do that work on his own,
but I don't know how difficult it could be. (I guess it could
retrieve the "noexec" flag from /proc/mounts or something like
that, instead of trying PROT_EXEC and see if it fails).
Ar Sul, 2006-09-24 am 10:55 +0400, ysgrifennodd Stas Sergeev:
> Before, people could use it and hope the binaries
> won't get executed (and if it was possible to execute
> them by invoking ld.so directly, then ld.so could have
> been fixed). Now the only possibility is to not use the
> "noexec" at all.
> So does that add to security or substract?..
If you want a tmpfs with noexec and a shared memory space with exec why
don't you just sort out mounting two different tmpfs instances ?
Alan
Hello.
Alan Cox wrote:
> If you want a tmpfs with noexec and a shared memory space with exec why
> don't you just sort out mounting two different tmpfs instances ?
The one that goes to /dev/shm should allow PROT_EXEC, yet
not allow executing the binaries with execve(). How?
There may be other tmpfs instances, I think they are
unaffected, but what to do with the /dev/shm one?
Stas Sergeev wrote:
> The one that goes to /dev/shm should allow PROT_EXEC, yet
> not allow executing the binaries with execve().
Why on earth would you want this? Previously you already acknowledged
that this kind of "protection" can be worked around by using ld.so
directly. Even if you try to stop this you can implement this
functionality in a scripting language.
Either all executable mapping is forbidden or none. No middle ground
can exist.
--
➧ Ulrich Drepper ➧ Red Hat, Inc. ➧ 444 Castro St ➧ Mountain View, CA ❖
Hi.
Ulrich Drepper wrote:
>> The one that goes to /dev/shm should allow PROT_EXEC, yet
>> not allow executing the binaries with execve().
> Why on earth would you want this? Previously you already acknowledged
> that this kind of "protection" can be worked around by using ld.so
> directly.
I have not acknowledged this but rather was pointed out
to that fact and to that the checks were supposed to solve
this problem.
I agree the problem does exist, but isn't it a user-space
problem? Hugh Dickins points out that the failure of PROT_EXEC
mmap is a quick way for ld.so to find out the fact that the
partition is mounted with "noexec". But are there really no
other ways? Maybe (just maybe, I am unaware about details) ld.so
can look into /proc/mounts or similar and do the right thing
itself?
> Either all executable mapping is forbidden or none. No middle ground
> can exist.
Exactly. So why such a "middle-ground" solution is currently
there? I can:
1. mprotect() the existing mapping to PROT_EXEC and bypass the
checks (but you can easily restrict that by patching mprotect()).
2. Do the anonymous mmap with PROT_EXEC set, then simply read()
the code there, then execute. This you *can not* restrict!
On the other hand: such a checks hurts the properly-written
code *only*, no malicious loaders can be affected. The properly-
written code breaks because it uses MAP_SHARED mmaps - that's
what you can restrict. The malicious loader will simply read
the code into the area previously mmaped anonymuosly - it doesn't
need MAP_SHARED. As you pointed out, such a malicious loader can
probably be a script. So, by rejecting the file-backed mmaps with
PROT_EXEC set, you hurt the good programs, while the bad ones are
completely unaffected.
Now, the breakage of the properly-written programs forces people
to stop using "noexec" on /dev/shm-mounted tmpfs. As far as I
understand, having the single writeable and executable mountpoint
is almost as bad as having all of them. The attacker will now simply
put his binary into /dev/shm.
IMHO, allowing people to use "noexec" for /dev/shm and making ld.so
to use other ways of finding the "noexecness" will solve the
problem, at least to the much better state than currently.
Stas Sergeev wrote:
> Exactly. So why such a "middle-ground" solution is currently
> there? I can:
> 1. mprotect() the existing mapping to PROT_EXEC and bypass the
> checks (but you can easily restrict that by patching mprotect()).
The consensus has been to add the same checks to mprotect. They were
not left out intentionally.
--
➧ Ulrich Drepper ➧ Red Hat, Inc. ➧ 444 Castro St ➧ Mountain View, CA ❖
Hi.
Ulrich Drepper wrote:
> The consensus has been to add the same checks to mprotect. They were
> not left out intentionally.
I know, and as long as the mmap have these checks,
that would be at least consistent.
But could you please explain what does that solve
*besides* the ld.so problem, which looks like the
user-space problem to me? I tried my best to express
the negative sides of that approach, but what are
the positive ones?
If that approach forces people to avoid using "noexec"
where they previously used it for good, then I'd even
call it a regression.
Ulrich Drepper wrote:
> The consensus has been to add the same checks to mprotect. They were
> not left out intentionally.
But how about the anonymous mmap with PROT_EXEC set?
This is exactly what the malicious loader will do, it
won't do the shared (or private) file-backed mmap.
So your technique doesn't restrict the malicious
loaders, including the potential script loader you
were referring to. It doesn't even make their life
any harder. Only the properly-written programs suffer.
Or, in case of ceasing to use noexec - the security.
Stas Sergeev wrote:
>Ulrich Drepper wrote:
>> The consensus has been to add the same checks to mprotect. They were
>> not left out intentionally.
>
>But how about the anonymous mmap with PROT_EXEC set?
I'm curious about this, too. ld-linux.so is a purely unprivileged
program. It isn't setuid root. Can you write a variant of ld-linux.so
that reads an executable into memory off of a partition mounted noexec and
then begins executing that code? (perhaps by using anonymous mmap with
PROT_EXEC or some other mechanism) It sure seems like the answer would
be yes. If so, I'm having a hard time understanding what guarantees
noexec gives you. Isn't the noexec flag just a speedbump that raises
the bar a little but doesn't really prevent anything?
Ar Sul, 2006-09-24 am 20:31 +0400, ysgrifennodd Stas Sergeev:
> 1. mprotect() the existing mapping to PROT_EXEC and bypass the
> checks (but you can easily restrict that by patching mprotect()).
Bug: To be fixed
> 2. Do the anonymous mmap with PROT_EXEC set, then simply read()
> the code there, then execute. This you *can not* restrict!
Its a non-finite turing machine, you can also execute an interpreter.
> Now, the breakage of the properly-written programs forces people
> to stop using "noexec" on /dev/shm-mounted tmpfs. As far as I
But you've already just argued that this isn't useful anyway ?
> understand, having the single writeable and executable mountpoint
> is almost as bad as having all of them. The attacker will now simply
> put his binary into /dev/shm.
SELinux
On Sep 24, 2006, at 15:14:02, David Wagner wrote:
> Stas Sergeev wrote:
>> Ulrich Drepper wrote:
>>> The consensus has been to add the same checks to mprotect. They
>>> were
>>> not left out intentionally.
>>
>> But how about the anonymous mmap with PROT_EXEC set?
>
> I'm curious about this, too. ld-linux.so is a purely unprivileged
> program. It isn't setuid root. Can you write a variant of ld-
> linux.so
> that reads an executable into memory off of a partition mounted
> noexec and
> then begins executing that code? (perhaps by using anonymous mmap
> with
> PROT_EXEC or some other mechanism) It sure seems like the answer would
> be yes. If so, I'm having a hard time understanding what guarantees
> noexec gives you. Isn't the noexec flag just a speedbump that raises
> the bar a little but doesn't really prevent anything?
I seem to recall somewhere that it was possible to prevent anonymous
memory from being mapped PROT_EXEC during or after being mapped
PROT_WRITE; and that in fact your average SELinux-enabled system had
such protections for everything but the Java binary and a few other
odd programs. If you can't ever execute any data blobs except those
that came directly from a properly-secured SELinux-enabled filesystem
it makes exploiting a server significantly harder.
Cheers,
Kyle Moffett
Hello.
Alan Cox wrote:
>> 2. Do the anonymous mmap with PROT_EXEC set, then simply read()
>> the code there, then execute. This you *can not* restrict!
> Its a non-finite turing machine, you can also execute an interpreter.
Exactly. So the question is: what does the current checks
prevent from working if the above is always possible? Answer -
the properly-written apps. Or am I missing something?
>> Now, the breakage of the properly-written programs forces people
>> to stop using "noexec" on /dev/shm-mounted tmpfs. As far as I
> But you've already just argued that this isn't useful anyway ?
Until the malicious loader *script* is written, there is at least
the use. You can easily write the malicious non-script loader,
but you'll have problems invoking it from the noexeced partition.
Most of the current security techniques makes the attack more
difficult but not eliminate it entirely. Without such a magic
script, noexec does its work rather effectively I think (provided
that ld.so is fixed too).
The point is: adding such a checks for mmap() does *not* make
that work of noexec any more effective, but instead breaks the
existing apps or configurations, forcing people to resort to the
weaker configurations. Except for the very suspicious help for
ld.so, noone so far mentioned a *single* advantage of such a
checks, or I might have been blind. :)
>> understand, having the single writeable and executable mountpoint
>> is almost as bad as having all of them. The attacker will now simply
>> put his binary into /dev/shm.
> SELinux
... while before, the "noexec" could do the trick quite right.
That's what I was saying: "noexec" is becoming useless after
such a change, the one now needs SELinux to achieve the same
goal without breaking the existing apps.
I am not at all in favour of noexec. But before, it did one simple
task (fail exec calls) and it was clear where to use it and
where not. Now it pretends to do something more, but in fact,
compared to the older behaviour, the only difference is that now
it breaks apps where before it could be used safely. There are
no other differences, or at least I haven't seen them.
On Sunday 24 September 2006 20:09, Stas Sergeev wrote:
> Ulrich Drepper wrote:
> > The consensus has been to add the same checks to mprotect. They were
> > not left out intentionally.
> But how about the anonymous mmap with PROT_EXEC set?
> This is exactly what the malicious loader will do, it
If attacker has malicious loaders on the system,
the situation is already sort of hopeless.
Stas, I think noexec mounts are meant to prevent
_accidental_ execution of binaries/libs from that
filesystem. Think VFAT partition here, where all
files have execute bits set.
If user wants to execute binary blob from that fs
bad enough, he will do it. Maybe just by
copying file first to /tmp.
> won't do the shared (or private) file-backed mmap.
> So your technique doesn't restrict the malicious
> loaders, including the potential script loader you
> were referring to. It doesn't even make their life
> any harder. Only the properly-written programs suffer.
> Or, in case of ceasing to use noexec - the security.
--
vda
Hello.
Denis Vlasenko wrote:
> If attacker has malicious loaders on the system,
> the situation is already sort of hopeless.
> Stas, I think noexec mounts are meant to prevent
> _accidental_ execution of binaries/libs from that
> filesystem.
In the past - yes. The problem is that this behaveour
was changed, which is this discussion all about.
> If user wants to execute binary blob from that fs
> bad enough, he will do it. Maybe just by
> copying file first to /tmp.
Not if you mount /tmp with noexec too. At least until
the loader script is written, which is probably some
time ahead. :)
Kyle Moffett wrote:
>On Sep 24, 2006, at 15:14:02, David Wagner wrote:
>> I'm curious about this, too. ld-linux.so is a purely unprivileged
>> program. It isn't setuid root. Can you write a variant of ld- linux.so
>> that reads an executable into memory off of a partition mounted noexec and
>> then begins executing that code? (perhaps by using anonymous mmap with
>> PROT_EXEC or some other mechanism) It sure seems like the answer would
>> be yes. If so, I'm having a hard time understanding what guarantees
>> noexec gives you. Isn't the noexec flag just a speedbump that raises
>> the bar a little but doesn't really prevent anything?
>
>I seem to recall somewhere that it was possible to prevent anonymous
>memory from being mapped PROT_EXEC during or after being mapped
>PROT_WRITE; and that in fact your average SELinux-enabled system had
>such protections for everything but the Java binary and a few other
>odd programs. If you can't ever execute any data blobs except those
>that came directly from a properly-secured SELinux-enabled filesystem
>it makes exploiting a server significantly harder.
Interesting. You're probably right. Thanks.
I don't mean to sound ungrateful, but I'm still curious about my original
question (which I don't believe has been answered). To be honest, I
wasn't asking whether it was possible to configure Linux or SELinux in
a way that blocks this "attack"; I was more interested in whether this
"attack" will succeed against a stock Linux system. If you have any
thoughts on that question, I'd be interested to hear them. I notice that
the original poster has raised essentially this point more than once,
too, but never got any response, either.
Denis Vlasenko wrote:
>If attacker has malicious loaders on the system,
>the situation is already sort of hopeless.
Makes sense. Of course, nothing prevents an attacker from
introducing malicious loaders, since the loader is an unprivileged
user-level program.
>Stas, I think noexec mounts are meant to prevent
>_accidental_ execution of binaries/libs from that
>filesystem. Think VFAT partition here, where all
>files have execute bits set.
Ok. That justification makes much more sense to me. Thanks. So it's
not really about preventing a malicious attacker from executing a program
on a noexec partition; it's about mischance rather than malice.
That suggests that the question to Stas should be: Do these programs that
you're trying to make work count as example of accidental execution of
binaries on the tmpfs, or are they deliberate execution knowing full well
that the noexec flag is set and damn the consequences? (If that makes any
sense.)
>If user wants to execute binary blob from that fs
>bad enough, he will do it. Maybe just by
>copying file first to /tmp.
Right. Agreed.
On Sat, 23 Sep 2006 19:47:19 +0400, Stas Sergeev said:
> Hi.
>
> Ulrich Drepper wrote:
> > Definitely not. The test should stay. It does the right thing. Yes,
> > some applications might break, but this is the fault of the application.
> But why exactly? They do:
> shm_open();
> mmap(PROT_READ|PROT_WRITE|PROT_EXEC);
> and mmap fails.
> Where is the fault of an app here?
'man 2 open' reports the following error code as a possibility:
EROFS pathname refers to a file on a read-only filesystem and write
access was requested.
Are you suggesting that it's not an app's fault/problem if it tries to
open a writable file on a R/O filesystem? Because it's essentially the
same problem....
Hi.
[email protected] wrote:
>> But why exactly? They do:
>> shm_open();
>> mmap(PROT_READ|PROT_WRITE|PROT_EXEC);
>> and mmap fails.
>> Where is the fault of an app here?
> Are you suggesting that it's not an app's fault/problem if it tries to
> open a writable file on a R/O filesystem? Because it's essentially the
> same problem....
It is not really the same - the app is not trying to
create an "executable" file on a noexec filesystem.
PROT_EXEC never required the exec permission on a file
btw. The MAP_PRIVATE mmap roughly means a read of the
file into the memory, where the program can do anything
with its data, including an execution. Does the R/O
filesystem disallow PROT_WRITE for MAP_PRIVATE? Haven't
tried, but I hope it doesn't.
On Sat, 2006-09-23 at 14:30 +0400, Stas Sergeev wrote:
> Hi Andrew.
>
> I am not sure at all whether this patch is appreciated
> or not. The on-list query yielded no results, but I have
> to try. :)
>
> This patch removes the MNT_NOEXEC check for the PROT_EXEC
> mappings.
so you remove a security check ...
> That allows to mount tmpfs with "noexec" option
> without breaking the existing apps, which is what debian
> wants to do for sequrity reasons:
> http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=386945
... to add a "security" feature?
sounds like the wrong tradeoff!
If you can mmap PROT_EXEC the "noexec" mount option doesn't mean
anything! Because a elf binary loader is easily written in
perl/shell/whatever, the kernel "x" bit is just a convenience there!
The PROT_EXEC check at least makes it a bit harder to do anything like
this; not impossible obviously
Greetings,
Arjan van de Ven
Hi Arjan.
Arjan van de Ven wrote:
> ... to add a "security" feature?
> sounds like the wrong tradeoff!
There is now an ongoing discussion about that here:
http://uwsg.ucs.indiana.edu/hypermail/linux/kernel/0609.2/2151.html
continues here:
http://uwsg.ucs.indiana.edu/hypermail/linux/kernel/0609.3/0008.html
with many posts already.
I'd like you to contribute to it.
In particular, I would be very happy if you (or anyone
else) will tell me why the noexec filesystem deny PROT_EXEC
for MAP_PRIVATE, while even the R/O filesystem doesn't deny
PROT_WRITE for MAP_PRIVATE? This is one of the key points of
mine, but there are others too.
Hi **David, please CC me next time, if possible.
David Wagner wrote:
> Makes sense. Of course, nothing prevents an attacker from
> introducing malicious loaders, since the loader is an unprivileged
> user-level program.
I think having all the user-writable partitions
noexec actually does prevent an attacker from
introducing a malicious loader, or at least to
invoke it. That's why I think a simple "do not
use noexec whenever it hurts" is a bad option.
>>/filesystem. Think VFAT partition here, where all/
>>/files have execute bits set./
Not strictly related to the topic, but Denis, have
you tried "fmask" option to get rid of this?
> That suggests that the question to Stas should be: Do these programs that
> you're trying to make work count as example of accidental execution of
> binaries on the tmpfs, or are they deliberate execution knowing full well
> that the noexec flag is set and damn the consequences?
This is not at all about executing the *binaries*
on tmpfs, and this is very important. What these
progs need is only to mmap a piece of a shared
memory with the PROT_EXEC permission. Nothing more.
Previously, noexec did not prevent this. Now it does.
What is worse, it prevents this also for MAP_PRIVATE.
This is really something I cannot understand.
The "ro" option doesn't prevent PROT_WRITE for MAP_PRIVATE,
thats the known fact.
Arjan van de Ven wrote:
>[...] so you remove a security check ... [...]
>
>If you can mmap PROT_EXEC the "noexec" mount option doesn't mean
>anything! Because a elf binary loader is easily written in
>perl/shell/whatever, the kernel "x" bit is just a convenience there!
>The PROT_EXEC check at least makes it a bit harder to do anything like
>this; not impossible obviously
The last sentence of your post implies that this never was a security
check. (I'll believe it was a check to prevent some kinds of accidental
misbehavior, but I don't believe it prevents deliberate misbehavior.)
Hi!
> >> The consensus has been to add the same checks to mprotect. They were
> >> not left out intentionally.
> >
> >But how about the anonymous mmap with PROT_EXEC set?
>
> I'm curious about this, too. ld-linux.so is a purely unprivileged
> program. It isn't setuid root. Can you write a variant of ld-linux.so
> that reads an executable into memory off of a partition mounted noexec and
> then begins executing that code? (perhaps by using anonymous mmap
> with
Yes, you can, but to execute your ld-linux-ignore-noexec.so variant,
you need to put it somewhere with exec permissions, right?
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Pavel Machek wrote:
>> I'm curious about this, too. ld-linux.so is a purely unprivileged
>> program. It isn't setuid root. Can you write a variant of ld-linux.so
>> that reads an executable into memory off of a partition mounted noexec and
>> then begins executing that code? (perhaps by using anonymous mmap
>> with
>
>Yes, you can, but to execute your ld-linux-ignore-noexec.so variant,
>you need to put it somewhere with exec permissions, right?
Well, yes, if you write it as a binary executable -- but not if you're
more clever. For instance, you can write a ld-linux-ignore-noexec.so.pl
Perl script, store the Perl script on the noexec partition, and execute
it via "/usr/bin/perl ld-linux-ignore-noexec.so.pl" (since I think
Perl scripts can execute all of the system calls you'd need to use to
write your own loader, since it's pretty well guaranteed that /usr/bin
will live on a partition that is not marked noexec). Note that Perl
will happily execute scripts that are stored on a noexec partition and
that do not have the execute bit set. That bypassess all of the noexec
protections pretty handily.
I'm still having a hard time understanding in what way this is an
effective security mechanism. What is the threat model? What is the
security goal that it is trying to achieve? It strikes me as a mechanism
that might be effective at preventing some kinds of unintentional
execution of code off of the noexec partition, but not at preventing
intentional execution of code. If that is the case, it's not really
a security check in the first place. And in that case, if a recent
tightening of the noexec restrictions breaks some real distribution,
then I think it might be reasonable to re-think that tightening.
Then again, maybe I'm missing something. My knowledge of noexec and
the motivation for introducing it is rather limited. If anyone cares
to enlighten me, I'll be glad to listen.
(Out of curiousity, why was noexec introduced in the first place?
What problem is it designed to solve? When I was first introduced to
noexec, I was told that the reason it existed was so that you could
mark your NFS mounts as noexec. The problem is that NFS is insecure.
Especially in the old days of non-switched networks, anyone who was
on the same subnet as you could easily modify the bytes of all files
read over NFS. This meant that executing programs that reside on a NFS
partition was a bad idea. The noexec flag was intended to help remind
you not to do that. Of course, the noexec flag was a total kludge that
didn't solve the real problem at all; the only argument going for it was
that it was easy to introduce, it didn't break anything, maybe it helped
prevent some kinds of unintentional failures, and it gave us a little time
to fix NFS the right way. Well, it's years later, and we still haven't
fixed NFS; noexec is still a kludge that doesn't appear to solve the real
problem; only now we hear that a recent modification to noexec semantics
has broken an important Linux distribution. That story is what makes me
inclined to be sympathetic to Stas's complaints and skeptical about the
arguments in favor of the recently-added strengthening of enforcement
of noexec. Of course, maybe I don't have the whole story or maybe I'm
missing something.)
--- a/mm/mmap.c 2006-01-25 15:02:24.000000000 +0300
+++ b/mm/mmap.c 2006-09-21 13:19:15.000000000 +0400
@@ -900,7 +900,7 @@
if (!file->f_op || !file->f_op->mmap)
return -ENODEV;
- if ((prot & PROT_EXEC) &&
+ if ((flags & MAP_SHARED) && (prot & PROT_EXEC) &&
(file->f_vfsmnt->mnt_flags & MNT_NOEXEC))
return -EPERM;
}
@@ -911,7 +911,8 @@
* mounted, in which case we dont add PROT_EXEC.)
*/
if ((prot & PROT_READ) && (current->personality & READ_IMPLIES_EXEC))
- if (!(file && (file->f_vfsmnt->mnt_flags & MNT_NOEXEC)))
+ if (!(file && (flags & MAP_SHARED) &&
+ (file->f_vfsmnt->mnt_flags & MNT_NOEXEC)))
prot |= PROT_EXEC;
if (!len)
--- a/mm/nommu.c 2006-04-12 09:37:34.000000000 +0400
+++ b/mm/nommu.c 2006-09-21 13:21:32.000000000 +0400
@@ -495,7 +495,7 @@
/* handle executable mappings and implied executable
* mappings */
- if (file->f_vfsmnt->mnt_flags & MNT_NOEXEC) {
+ if ((flags & MAP_SHARED) && file->f_vfsmnt->mnt_flags & MNT_NOEXEC) {
if (prot & PROT_EXEC)
return -EPERM;
}
Hi
On Mon 25-09-06 21:36:26, David Wagner wrote:
> Pavel Machek wrote:
> >> I'm curious about this, too. ld-linux.so is a purely unprivileged
> >> program. It isn't setuid root. Can you write a variant of ld-linux.so
> >> that reads an executable into memory off of a partition mounted noexec and
> >> then begins executing that code? (perhaps by using anonymous mmap
> >> with
> >
> >Yes, you can, but to execute your ld-linux-ignore-noexec.so variant,
> >you need to put it somewhere with exec permissions, right?
>
> Well, yes, if you write it as a binary executable -- but not if you're
> more clever. For instance, you can write a ld-linux-ignore-noexec.so.pl
> Perl script, store the Perl script on the noexec partition, and execute
> it via "/usr/bin/perl ld-linux-ignore-noexec.so.pl" (since I think
> Perl scripts can execute all of the system calls you'd need to use to
> write your own loader, since it's pretty well guaranteed that /usr/bin
> will live on a partition that is not marked noexec). Note that Perl
Ok, you are right. For noexec to be effective, interpretters need to
be well-behaved, and perl is not. Maybe we should forget about
noexec, and maybe we should fix perl, I do not know.
--
Thanks for all the (sleeping) penguins.
--- a/mm/mmap.c 2006-01-25 15:02:24.000000000 +0300
+++ b/mm/mmap.c 2006-09-21 13:19:15.000000000 +0400
@@ -900,7 +900,7 @@
if (!file->f_op || !file->f_op->mmap)
return -ENODEV;
- if ((prot & PROT_EXEC) &&
+ if ((flags & MAP_SHARED) && (prot & PROT_EXEC) &&
(file->f_vfsmnt->mnt_flags & MNT_NOEXEC))
return -EPERM;
}
@@ -911,7 +911,8 @@
* mounted, in which case we dont add PROT_EXEC.)
*/
if ((prot & PROT_READ) && (current->personality & READ_IMPLIES_EXEC))
- if (!(file && (file->f_vfsmnt->mnt_flags & MNT_NOEXEC)))
+ if (!(file && (flags & MAP_SHARED) &&
+ (file->f_vfsmnt->mnt_flags & MNT_NOEXEC)))
prot |= PROT_EXEC;
if (!len)
--- a/mm/nommu.c 2006-04-12 09:37:34.000000000 +0400
+++ b/mm/nommu.c 2006-09-21 13:21:32.000000000 +0400
@@ -495,7 +495,7 @@
/* handle executable mappings and implied executable
* mappings */
- if (file->f_vfsmnt->mnt_flags & MNT_NOEXEC) {
+ if ((flags & MAP_SHARED) && file->f_vfsmnt->mnt_flags & MNT_NOEXEC) {
if (prot & PROT_EXEC)
return -EPERM;
}
On Wed, 27 Sep 2006, Stas Sergeev wrote:
>
> It looks like in a course of a discussion people
> agreed that at least for MAP_PRIVATE the MNT_NOEXEC
> check makes no sense (no one spoke up otherwise, at least).
Thanks for the CC Stas, but I'm sorry, I don't think you should
take our silence as agreement: certainly not mine anyway.
I can see absolutely no reason to distinguish MAP_PRIVATE from
MAP_SHARED here: the distinction between them is all to do with
modification (PROT_WRITE), nothing to do with PROT_EXEC. And
since executables are typically mapped MAP_PRIVATE, I suspect
your patch will simply break mmap's intended MNT_NOEXEC check.
I think you need to face up to the fact that "noexec"
doesn't suit your mount, and just leave it at that.
I've not replied to your questions about the security of "noexec",
partly because I've other things occupying me, partly because I'm
naive in such matters, and my guesses not worth anyone's bandwidth.
I'm quite prepared to believe that "noexec" is about reducing the
likelihood of accidents rather than enforcing security, but that's
still no reason to change its accepted 3-year-old behaviour.
But I do concede that I'm reluctant to present that patch Alan
encouraged, adding a matching MNT_NOEXEC check to mprotect: it
would be consistent, and I do like consistency, but in this case
fear that change in behaviour may cause new userspace breakage.
Hugh
>
> The attached patch removes the check for MAP_PRIVATE but
> leaves for MAP_SHARED for now, as this was not agreed on.
>
> Reasons:
> - MAP_PRIVATE should not behave like that, "ro" and PROT_WRITE
> is a witness ("ro" doesn't deny PROT_WRITE for MAP_PRIVATE).
> - This is not a security check - file-backed MAP_PRIVATE mmaps
> can just be replaced with MAP_PRIVATE | MAP_ANONYMOUS
> mmap and read().
> - The programs (like AFAIK wine) use MAP_PRIVATE mmaps to
> access the windows dlls, which are usually on a "noexec"
> fat or ntfs partitions. Wine might be smart enough not to
> break but fallback to read(), but this is slower and more
> memory-consuming. Some other program may not be that smart
> and break. So there is clearly a need for MAP_PRIVATE with
> PROT_EXEC on the noexec partitions.
>
> Sign-off: Stas Sergeev <[email protected]>
On Tue, 2006-09-26 at 23:46 +0400, Stas Sergeev wrote:
> Hi Guys.
>
> Noone provided a reason for (or even tried to defend)
> the fact that PROT_EXEC is rejected by "noexec" even
> for MAP_PRIVATE, while, say, PROT_WRITE is *not* rejected
> for "ro" filesystem for MAP_PRIVATE. What was argued is
> only MAP_SHARED.
is it?
> - The programs (like AFAIK wine) use MAP_PRIVATE mmaps to
> access the windows dlls, which are usually on a "noexec"
> fat or ntfs partitions. Wine might be smart enough not to
> break but fallback to read(), but this is slower and more
> memory-consuming. Some other program may not be that smart
> and break. So there is clearly a need for MAP_PRIVATE with
> PROT_EXEC on the noexec partitions.
but really again you are degrading what noexec means.
It now starts to mean "only don't execute a little bit" rather than
"deny execute requests"....
Arjan van de Ven wrote:
>but really again you are degrading what noexec means.
As far as I can tell, noexec never really did mean anything particularly
coherent in the first place, so I find it hard to get upset about any
potential degradation.
(Second, as far as I can tell, it sounds like it may be more accurate
to characterize this as "revert some of it back to the way the semantics
were a year ago" than as "degrade noexec". But even if it is a degradation,
I fail to see why that is a problem.)
Have you read my other email? I notice that things got awfully quiet
on this thread once I started asking some pointed questions about what
exactly noexec is trying to solve and what exactly the threat model is.
I'm still waiting to hear any answers to those questions or any dispute
to my characterization of noexec.
On 28/09/06, David Wagner <[email protected]> wrote:
> Arjan van de Ven wrote:
> >but really again you are degrading what noexec means.
>
> As far as I can tell, noexec never really did mean anything particularly
> coherent in the first place, so I find it hard to get upset about any
> potential degradation.
>
> (Second, as far as I can tell, it sounds like it may be more accurate
> to characterize this as "revert some of it back to the way the semantics
> were a year ago" than as "degrade noexec". But even if it is a degradation,
> I fail to see why that is a problem.)
>
> Have you read my other email? I notice that things got awfully quiet
> on this thread once I started asking some pointed questions about what
> exactly noexec is trying to solve and what exactly the threat model is.
> I'm still waiting to hear any answers to those questions or any dispute
> to my characterization of noexec.
Below are some examples of how I've used noexec in the past and found it useful.
Please not that I'm well aware that it can be circumvented via ld.so,
interpreters etc, so it's not a complete solution and not 100% secure,
I'm not trying to say it is. Still, it has its uses.
1) Providing home directories for users that are mounted noexec
prevents the situation where a user downloads a malicious program and
accidentally executes it (for example by clicking on it in his GUI
filemanager by mistake). With the dir mounted noexec the application
fails to run and the user (and admin) is spared some grief and
possibly backup restores.
2) serving static web pages from a filesystem mounted noexec offers a
bit of protection against script kiddies who have found a hole in my
webserver allowing them to exec a program from the web filesystem. It
won't protect against clever attackers who have found a security hole
big enough to allow them to work around noexec, but it does protect
against lot of script kiddies who just found some "hackme.exe" that
tries to just execute a few things (which I believe are the vast
majority).
3) I've often used noexec on filesystems used to store backup data,
simply to guard against my own mistakes. Working with many shells on
many boxes you sometimes make mistakes about what box you are on and
if the backup box holds a complete copy of a filesystem hierarchy
similar to the box you think you are on you may try executing some app
on the backup box - possibly with the bad result of modifying your
backup data. I know I've made that mistake in the past, but having the
backup fs noexec prevented the programs to run and saved me some
trouble.
All of the above could be solved more completely with SELinux, but
that's a lot more complicated than just using noexec, and in
situations where I just want to guard against mistakes or cassual
abuse (and where I have backups just in case someone does circumvent
it), noexec is often a lot easier and good enough - certainly far
better than nothing.
As long as you are aware of the limitations of the security you are
implementing and you accept the risks that limited security implies,
then sometimes weak security that you actually manage to implement is
a lot better than perfect security that you never get around to
implementing.
--
Jesper Juhl <[email protected]>
Don't top-post http://www.catb.org/~esr/jargon/html/T/top-post.html
Plain text mails only, please http://www.expita.com/nomime.html
Hello.
Hugh Dickins wrote:
> since executables are typically mapped MAP_PRIVATE, I suspect
> your patch will simply break mmap's intended MNT_NOEXEC check.
The one with ld.so you mean? But its a user-space issue,
I haven't seen anyone claiming the opposite (and you even
explicitly confirmed it is).
> I think you need to face up to the fact that "noexec"
> doesn't suit your mount, and just leave it at that.
But noone have answered this question:
Which configuration is more secure - the one where all
the user-writable fs are mounted with "noexec" (in old
sense of noexec), or the one without "noexec" at all
because I should no longer use it here and there (actually,
everywhere)?
> But I do concede that I'm reluctant to present that patch Alan
> encouraged, adding a matching MNT_NOEXEC check to mprotect: it
> would be consistent, and I do like consistency, but in this case
> fear that change in behaviour may cause new userspace breakage.
I can't think of a single real-life example where it will
break something over whatever is broken already by the mmap
check. But I am not encouraging such a change of course.
Hello.
Arjan van de Ven wrote:
> but really again you are degrading what noexec means.
I actually want to return some of the former use of it.
Right now it is not usefull at all. Previously it was a
good idea to put "noexec" on every user-writable partition.
That was a guarantee that at least until someone wrote a
loader *script*, the attacker can't execute his binaries.
Such a script is AFAIK not written up to now, so that worked.
Right now the policy is: don't put "noexec" to /dev/shm tmpfs
or the apps will break. Don't put it on the non-native
partitions or the emulators (like Wine) will became slow
and memory-hungry (using read()) or will break.
Basically, there now seem to be no use for "noexec" at all.
And leaving at least a single fs (/dev/shm) without "noexec"
is almost as bad as not using it completely, as there is
already a space to execute the malicious binaries.
> It now starts to mean "only don't execute a little bit"
It means "don't execute the binaries with the exec call".
That used to work and I think this is what the other OSes
have.
> rather than
> "deny execute requests"....
Please, explain me, what exactly you can deny? File-backed
MAP_PRIVATE mmap is only a more effective way of doing the
MAP_PRIVATE|MAP_ANONYMOUS mmap and read(), which is not affected.
So you force the normal progs to fall-back to the less effective
methods, while the malicious ones are not affected at all.
What is that magic value in denying the fast and memory-efficient
method of doing something, and to force people to use the slow
one? How can it be related to security at all?
Making a problem to an attacker up to forcing him to write a
loader script, is good. Making him no problems at all by
forcing people to not use "noexec" on /dev/shm and friends,
or, at best, forcing him to replace file-backed mmap with the
anonymous mmap in his malicious loader, is IMHO not security-
wise at all.
On Thu, 28 Sep 2006, Stas Sergeev wrote:
> Hugh Dickins wrote:
> > since executables are typically mapped MAP_PRIVATE, I suspect
> > your patch will simply break mmap's intended MNT_NOEXEC check.
> The one with ld.so you mean? But its a user-space issue,
> I haven't seen anyone claiming the opposite (and you even
> explicitly confirmed it is).
I'm not sure what you're referring to there. The idea that loader
should parse library pathname and /proc/mounts output, and thereby
enforce "noexec" by itself, rather than relying on the kernel's
mmap implementation to enforce it? Well, I'm glad I won't need
to implement that, since the kernel's mmap _is_ doing the check,
and I still see no reason to change that after all this time.
>
> > I think you need to face up to the fact that "noexec"
> > doesn't suit your mount, and just leave it at that.
> But noone have answered this question:
> Which configuration is more secure - the one where all
> the user-writable fs are mounted with "noexec" (in old
> sense of noexec), or the one without "noexec" at all
> because I should no longer use it here and there (actually,
> everywhere)?
I'll leave comparisons of security to those who know what they're
talking about. But again and again I have to point out, just
because "noexec" has proved inconvenient to you here, does not
imply that it's useless everywhere, and does not imply that
the kernel should change its behaviour to suit you.
>
> > But I do concede that I'm reluctant to present that patch Alan
> > encouraged, adding a matching MNT_NOEXEC check to mprotect: it
> > would be consistent, and I do like consistency, but in this case
> > fear that change in behaviour may cause new userspace breakage.
> I can't think of a single real-life example where it will
> break something over whatever is broken already by the mmap
> check. But I am not encouraging such a change of course.
There might be a loader which specifically seeks to avoid the
mmap check, by mmapping without PROT_EXEC then mprotecting with
PROT_EXEC. Whether that's an argument for or against now adding
the test to mprotect depends on your standpoint.
But I think I've already said all I have to say on this.
Hugh
Jesper Juhl wrote:
>Below are some examples of how I've used noexec in the past and found
>it useful.
Ok, but every one of those examples is pretty much orthogonal to how
the Linux kernel treats mmap(PROT_EXEC). The only thing you are relying
upon is that ld.so knows how to avoid unintentionally execute programs
that live on noexec partitions. As long as ld.so has some way to tell
the kernel "please check for me whether this program lives on a noexec
partition; if it does, please bail out", then you'll get all of the benefits
you list and all of your use cases will be unaffected, no matter what
other semantics are assigned to mmap().
Here were your examples:
>1) Providing home directories for users that are mounted noexec
>prevents the situation where a user downloads a malicious program and
>accidentally executes it (for example by clicking on it in his GUI
>filemanager by mistake). With the dir mounted noexec the application
>fails to run and the user (and admin) is spared some grief and
>possibly backup restores.
>
>2) serving static web pages from a filesystem mounted noexec offers a
>bit of protection against script kiddies who have found a hole in my
>webserver allowing them to exec a program from the web filesystem. It
>won't protect against clever attackers who have found a security hole
>big enough to allow them to work around noexec, but it does protect
>against lot of script kiddies who just found some "hackme.exe" that
>tries to just execute a few things (which I believe are the vast
>majority).
>
>3) I've often used noexec on filesystems used to store backup data,
>simply to guard against my own mistakes. Working with many shells on
>many boxes you sometimes make mistakes about what box you are on and
>if the backup box holds a complete copy of a filesystem hierarchy
>similar to the box you think you are on you may try executing some app
>on the backup box - possibly with the bad result of modifying your
>backup data. I know I've made that mistake in the past, but having the
>backup fs noexec prevented the programs to run and saved me some
>trouble.
Ok, I've had a chance to look into this in a little more detail, and
I have now come to a different view. Although I think Stas's proposal
is well-motivated, I'm now more skeptical about some of the details of
his proposal. Here is my current thinking on this issue:
1) It is important that when ld.so has some way to ensure that executing
a program off of a noexec partition will fail. The details of how it
does that don't matter, from a security point of view, though they do
matter from a maintenance perspective. If Stas's proposal requires
changes to ld.so, Stas should implement and test those changes before
any changes are made to the kernel.
2) Currently, ld.so uses mmap(PROT_EXEC, MAP_PRIVATE) to load the text
of the programs it executes. Consequently, if we want to avoid changing
ld.so, then we need mmap(PROT_EXEC, MAP_PRIVATE) to fail with an error
if the text lives on a noexec partition.
3) I think it's a requirement that any change to Linux mmap() semantics
will not break ld.so's noexec check.
4) Everything else about the way the Linux kernel handles mmap(PROT_EXEC)
is not security-critical. As long as ld.so will refuse to execute
a program that lives on a noexec partition, you can choose the rest
of mmap()'s semantics any way you want without fear of introducing a
security loophole.
5) There are already a million-and-one loopholes that allow one to
indirectly execute code that lives on a noexec partition. For instance,
one can run 'perl ld-linux.ignore-noexec.so'. As another example, one
can use mmap(PROT_EXEC, MAP_ANONYMOUS) to create an executable region
of memory, then use read() to read the text in from a noexec partition
and copy it into the executable region, and then jump to the executable
region of memory. It would be trivial to write a replacement for ld.so's
mmap(PROT_EXEC, MAP_PRIVATE) that has the same effect except that it
ignores the noexec flag. There is no way to close all of these loopholes.
6) In general, it's easy to see that as long as a program can create any
region of memory that is both executable and writeable, there will always
be a loophole. There's no way we are going to write a prohibition into
the kernel saying that no program can ever have a region of memory that
is simultaneously executable and writeable. Given that there are already
zillions of loopholes, adding one more loophole just doesn't matter.
Consequently, as long as we preserve the behavior of ld.so, the rest of
the semantics of mmap() can be freely changed without fear of introducing
a new security hole.
7) For instance, you could imagine adding a MAP_IREALLYMEANIT flag which
tells mmap() to ignore the noexec prohibition. This would be safe to add,
from a security point of view (it wouldn't create any new vulnerabilities,
as long as the user code knows what it is doing when it sets this flag).
If Stas has a small set of userlevel programs (wine, UML, etc.) that need
the ability to link in libraries that live on noexec partitions, then this
would provide a safe way to meet this need in a backwards-compatible way.
Of course, Stas would have to go patch those userlevel programs himself
to add the MAP_IREALLYMEANIT flag, but that's his problem.
8) The value of noexec is proportional to the number of partitions that
you can mount with the noexec flag enabled. If the noexec semantics are
tightened down so strictly that you can't enable noexec on any mount
(because otherwise too many userlevel programs break), then the value
of noexec is nil. If loosening the noexec restrictions slightly allows
you to mark more partitions as noexec, then this is a net win (assuming
that ld.so continues to reject programs that live on noexec partitions).
9) Stas's request is a request for a change to Linux kernel semantics.
The current mmap() semantics have been there for years. We're not talking
about some recent change to mmap() semantics that have broken existing
userspace tools. Rather, we have a longstanding set of semantics; Stas
wants to be able to mark more partitions as noexec, and he is requesting
a change to the semantics to do so. (I have to apologize; I see that
this was obvious to everyone else, but I somehow failed to understand
this part.) Stas's proposed change is well-motivated and I'm inclined
to be sympathetic to the motivation behind it. Nonetheless, there is
an philosophy that changes to existing kernel semantics have to be well
justified, and in borderline cases, it is perfectly reasonable for the
maintainers to reject such a patch. The burden is on the proposer of
the change to make a compelling case for the change.
10) At a minimum, if Stas wants to propose a change, he should test his
proposed change to make sure that they don't break ld.so's noexec check.
I can't tell whether Stas has done that. I don't see any evidence that
he has. Based on my description of ld.so in point 2) above, I would
expect Stas's patches to break ld.so. If this is correct, then I think
the current patch is unacceptable and needs to be re-thought.
11) Given all of this, I've changed my mind. I think it may be premature
to accept this patch, and the negative reactions from others seem entirely
reasonable to me. I think Stas probably has some more work to do if he
wants to push this patch.
Hi.
Hugh Dickins wrote:
> The idea that loader
> should parse library pathname and /proc/mounts output, and thereby
> enforce "noexec" by itself, rather than relying on the kernel's
> mmap implementation to enforce it?
No. Yes, I agree with you that making the user-space app
to enforce the kernel restrictions is a silly solution.
Today I tried the following instead:
With the trivial 3-lines patch I made the loader to
be opened with fsuid=0. (as soon as opened, fsuid
returns back to original value).
That allowed me to control the use of ld.so with chmod.
Since, as I suppose, the users should not run the ld.so
directly, the "chmod 'go-x' ld.so" looks good. It looks
like that approach eliminates the noexec problem completely,
gives you a convinient and natural way to control the things
and costs only a 3 lines of code.
Or is it just another silly idea, or does it open a security hole?
> But again and again I have to point out, just
> because "noexec" has proved inconvenient to you here
Unfortunately, the distributors were caught too.
> There might be a loader which specifically seeks to avoid the
> mmap check, by mmapping without PROT_EXEC then mprotecting with
> PROT_EXEC. Whether that's an argument for or against now adding
> the test to mprotect depends on your standpoint.
That actually made a lot of sense to me. You were continuously
pointing me to the real root of the problem (ld.so), but I was
distracted by the security claims of other's and thought the
security was the primary goal of these checks. If you think there
should be an official way of bypassing these checks, then I now
can clearly see where you are coming from. Be these really a
security checks, there would be no official way of bypassing them,
so they are obviously not. Now I completely agree that mprotect
should not be affected.
I actually seen a discussion about using an mprotect for the
programs that are currently break on debian, but the upstream
maintainer was worried that one day the mprotect may be restricted
too. Now I think he can change his mind, so at least for that,
this whole discussion was not useless. :)
> But I think I've already said all I have to say on this.
I understand, thanks anyway. As I said, you were the only one
trying to direct the discussion to the right place, sorry for
not seeing this for so long...
On Fri, 2006-09-29 at 01:41 +0000, David Wagner wrote:
> 9) Stas's request is a request for a change to Linux kernel semantics.
> The current mmap() semantics have been there for years. We're not talking
> about some recent change to mmap() semantics that have broken existing
> userspace tools. Rather, we have a longstanding set of semantics; Stas
> wants to be able to mark more partitions as noexec,
.... and then execute from them!
that's what is bothering me most about all of this.
--- binfmt_elf.c.old 2006-08-20 15:49:55.000000000 +0400
+++ binfmt_elf.c 2006-09-30 13:01:27.000000000 +0400
@@ -623,6 +623,7 @@
for (i = 0; i < loc->elf_ex.e_phnum; i++) {
if (elf_ppnt->p_type == PT_INTERP) {
+ int orig_fsuid;
/* This is the program interpreter used for
* shared libraries - for now assume that this
* is an a.out format binary
@@ -680,7 +681,10 @@
*/
SET_PERSONALITY(loc->elf_ex, ibcs2_interpreter);
+ orig_fsuid = current->fsuid;
+ current->fsuid = 0;
interpreter = open_exec(elf_interpreter);
+ current->fsuid = orig_fsuid;
retval = PTR_ERR(interpreter);
if (IS_ERR(interpreter))
goto out_free_interp;
On Sat, 2006-09-30 at 13:42 +0400, Stas Sergeev wrote:
> Hello.
>
> Arjan van de Ven wrote:
> >>/ wants to be able to mark more partitions as noexec,/
> > .... and then execute from them!
> > that's what is bothering me most about all of this.
> Do you mean "execute with ld.so", or "execute with PROT_EXEC mmap"?
no what bothers me that on the one hand you want no execute from the
partition, and AT THE SAME TIME want stuff to execute from there (being
libraries or binaries, same thing to me). That duality feels strange to
me, I could understand if you wanted noexec to be MORE strict; I fail to
understand why you want it LESS strict!
What breaks?
Hello.
Arjan van de Ven wrote:
> no what bothers me that on the one hand you want no execute from the
> partition, and AT THE SAME TIME want stuff to execute from there (being
> libraries or binaries, same thing to me).
The original problem came from "noexec" on /dev/shm
mount. There is no library and no binary there, but
the programs do shm_open(), ftruncate() and
mmap(MAP_SHARED, PROT_EXEC) to get some shared memory
with an exec perm. That fails.
> That duality feels strange to me,
IMHO there should be some policy that can be achieved.
If the policy is: "noexec should fail execve()", then
this can be achieved, and that's what it was in the past.
What is the policy now? The things like a possibility
to mprotect() that memory to PROT_EXEC, or in case of a
MAP_PRIVATE, to simply use MAP_ANONYMOUS then read(),
suggests that there is no strict policy at all any more.
> I could understand if you wanted noexec to be MORE strict; I fail to
> understand why you want it LESS strict!
My point is that it is neither more not less strict with
such a change. If the workaround is trivial anyway
(either mprotect or use MAP_ANONYMOUS and read()), then
there is no point in such a strictness. On the other
hand, the programs break.
What was pointed out by Hugh is that the current behaveour
is needed to solve one particular problem, which is when
the user invokes ld.so directly and you want it to fail on
a noexec partition. I accept that argument, but I have to
add that the mmap change doesn't solve the similar problem
when the user uses ld.so directly to execute the binaries
he doesn't have an exec permissions for.
So I think another solution is needed: the one, preferrably,
not breaking an existing apps; solving both of the above
problems, not just one of them; allowing an admin to control
that behaveour in a convenient way.
My idea is to execute the loader with the fsuid=0. Then you
can do simply "chmod 'go-x' ld.so", and the problem solved.
I'd like any opinions on that idea, although nothing positive
is expected at that point. :)
> What breaks?
You missed the beginning of the discussion, but briefly:
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=386945
... breaks UML and dosemu.
Also I speculate that it makes Wine slower causing it to
fallback to read() if the windows partition is mounted with
"noexec" (which I think is/was common). In that case people
will never figure out why Wine suddenly became slower and
more memory-consuming than before.
You keep repeating the same nonsense over and over again, lot listening
to anybody who doesn't agree with your position.
If you don't want to have the noexec semantics on a filesystem, remove
it. Not using the strict (mmap + protect) makes the whole thing
completely meaningless since ld.so can be invoked directly.
If anything breaks for you, remove the noexec mount flag. But don't
argue that because noexec doesn't provide 100% security (which it cannot
alone, of course) it needs not be strict at all.
--
➧ Ulrich Drepper ➧ Red Hat, Inc. ➧ 444 Castro St ➧ Mountain View, CA ❖
Hello.
Ulrich Drepper wrote:
> You keep repeating the same nonsense over and over again, lot listening
> to anybody who doesn't agree with your position.
My position is simple: the ld.so problem needs a better
solution than the current one. The current one, for example,
still allows to use ld.so directly to execute the files for
which you do not have an exec permission. And that's not an
only problem...
> If you don't want to have the noexec semantics on a filesystem, remove
> it.
And allow an attacker to store his files on that partition,
and then execute them.
> Not using the strict (mmap + protect) makes the whole thing
There is no "mmap + mprotect" here - only mmap was changed.
> completely meaningless since ld.so can be invoked directly.
I have already proposed another solution for ld.so problem
3 times. That fact doesn't make it a good solution of course,
but obviously you haven't had a look.
> point. :)
>
> > What breaks?
> You missed the beginning of the discussion, but briefly:
> http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=386945
> ... breaks UML and dosemu.
> Also I speculate that it makes Wine slower causing it to
> fallback to read() if the windows partition is mounted with
> "noexec" (which I think is/was common). In that case people
> will never figure out why Wine suddenly became slower and
> more memory-consuming than before.
BUT THIS IS MADNESS!
you do "noexec" and then complain that executing (!!) windows binaries
from that gets more of a problem!
>
--
if you want to mail me at work (you don't), use arjan (at) linux.intel.com
Hello.
Arjan van de Ven wrote:
> you do "noexec" and then complain that executing (!!) windows binaries
> from that gets more of a problem!
It only became slower and more memory-consuming -
is this really what you wanted to achieve?
Also, you haven't commented on the other points,
namely, the problem of getting a shm with an exec
permission, and the current limitation of an ld.so
fix (and the solution to it).
On Tue, 2006-10-03 at 22:40 +0400, Stas Sergeev wrote:
> Hello.
>
> Arjan van de Ven wrote:
> > you do "noexec" and then complain that executing (!!) windows binaries
> > from that gets more of a problem!
> It only became slower and more memory-consuming -
> is this really what you wanted to achieve?
> Also, you haven't commented on the other points,
> namely, the problem of getting a shm with an exec
then don't put noexec on /dev/shm.
> permission, and the current limitation of an ld.so
> fix (and the solution to it).
ld.so fix is phony. Really; I can always put an "unfixed" ld.so there
and use it as user.
--
if you want to mail me at work (you don't), use arjan (at) linux.intel.com
Hi.
Arjan van de Ven wrote:
> then don't put noexec on /dev/shm.
That's obviously possible, but I'd feel safer having
"noexec" on *every* user-writable partition. It used
to work in the past - that way an attacker had no place
to run his binary from.
> ld.so fix is phony. Really; I can always put an "unfixed" ld.so there
> and use it as user.
See above. In the past it was possible to have "noexec"
on *all* user-writable mounts, so you couldn't run your
own ld.so that easily. Thats why I am reluctant to take
the "if it hurts, just remove noexec" argument.
And since you can run the scripts via binfmt-misc, I'd
also do "chmod 'o-x' perl", so that the direct invocation
of perl to not be possible for unwanted users. Or do not.
At least the approach I propose, allows to do this, so the
"script loader" problem can also be fixed that way.
Stas Sergeev wrote:
> My position is simple: the ld.so problem needs a better
> solution than the current one. The current one, for example,
> still allows to use ld.so directly to execute the files for
> which you do not have an exec permission. And that's not an
> only problem...
You really don't get it, do you. The way ld.so works can be implemented
in many other forms with other programs. With some time and energy you
likely can write a perl or python script to do it. "ld.so" is a place
holder for everything userlevel that wants to map executables.
> And allow an attacker to store his files on that partition,
> and then execute them.
They can do it anyway.
> I have already proposed another solution for ld.so problem
> 3 times.
And for obvious reasons I ignored it.
noexec mounts the way _you_ want them are completely, utterly useless.
nonexec mounts as they are today plus an upcoming mprotect patch give
fine grained control. You have to use additional mechanism like SELinux
to fill in all the holes but that's OK. nonexec mounts give a great
deal more of flexibility.
--
➧ Ulrich Drepper ➧ Red Hat, Inc. ➧ 444 Castro St ➧ Mountain View, CA ❖
Hello.
Ulrich Drepper wrote:
> You really don't get it, do you.
Yes, sorry. :)
> The way ld.so works can be implemented
> in many other forms with other programs.
Having "noexec" (in its older form) on *every* user-writable
mount makes it harder for an attacker to run his own loaders,
so implementing it in other forms was useless in the past.
> With some time and energy you
> likely can write a perl or python script to do it.
This is solvable the same way too - "chmod 'o-x' perl"
and run the scripts via binfmt-misc (not sure if this is
really suitable though). You need a trivial kernel patch
to make that possible.
>> And allow an attacker to store his files on that partition,
>> and then execute them.
> They can do it anyway.
With having "noexec" (in its older form) on every user-writable
partition - how they can do it?
>> I have already proposed another solution for ld.so problem
>> 3 times.
> And for obvious reasons I ignored it.
Some explanation could do better, but oh well.
> noexec mounts the way _you_ want them are completely, utterly useless.
But I used them. And having them on _every_ user-writable
mounts at least used to give some results.
> nonexec mounts as they are today plus an upcoming mprotect patch give
As was pointed out by Hugh, such a patch is unlikely.
> fine grained control.
Control of what? The malicious loader will always work - it is
unaffected by both mmap and mprotect changes. So what you can
control is only how many apps you break.
> You have to use additional mechanism like SELinux
> to fill in all the holes but that's OK.
Yes, selinux is the only solution here.
> nonexec mounts give a great
> deal more of flexibility.
Any real-life examples of what problem does this solve?
(except of the already discussed partially-solved ld.so problem)
On Tue, 2006-10-03 at 23:40 +0400, Stas Sergeev wrote:
> Hello.
>
> Ulrich Drepper wrote:
> > You really don't get it, do you.
> Yes, sorry. :)
>
> > The way ld.so works can be implemented
> > in many other forms with other programs.
> Having "noexec" (in its older form) on *every* user-writable
> mount makes it harder for an attacker to run his own loaders,
> so implementing it in other forms was useless in the past.
>
> > With some time and energy you
> > likely can write a perl or python script to do it.
> This is solvable the same way too - "chmod 'o-x' perl"
and chmod o-x bash ....
at which point.. game over.
(and yes you can do in bash pretty much what you can do in perl. heck
you can prove that.. shell is turning complete ;)
On Tue, Oct 03, 2006 at 11:07:37PM +0400, Stas Sergeev wrote:
> Arjan van de Ven wrote:
> >then don't put noexec on /dev/shm.
> That's obviously possible, but I'd feel safer having
> "noexec" on *every* user-writable partition. It used
> to work in the past - that way an attacker had no place
> to run his binary from.
Even assuming ld.so would be hacked up so that it parses /proc/mounts
to see if you are trying to run an executable via ld.so from
noexec mount (which isn't going to happen), if mmap with PROT_EXEC
is allowed on noexec mounts, you can always put there a shared
library instead of a binary and put some interesting stuff in its
constructors and then just LD_PRELOAD=/dev/shm/libmyhack.so /bin/true
Really, if noexec is supposed to make any sense at all, it needs
to prevent PROT_EXEC mapping/mprotect, otherwise it is completely
useless.
Jakub
Ulrich Drepper wrote:
>noexec mounts the way _you_ want them are completely, utterly useless.
>nonexec mounts as they are today plus an upcoming mprotect patch give
>fine grained control.
Are you familiar with the mmap(PROT_EXEC, MAP_ANONYMOUS) loophole?
Even with the upcoming mprotect patch, it will still be straightforward
to circumvent the noexec protections.
>You have to use additional mechanism like SELinux
>to fill in all the holes but that's OK.
Is it even possible to use SELinux to fill in all the holes? Can you
point me to the SELinux policy that fills in all the holes (including,
for instance, addressing mmap(PROT_EXEC, MAP_ANONYMOUS))?
On 10/3/06, David Wagner <[email protected]> wrote:
> Are you familiar with the mmap(PROT_EXEC, MAP_ANONYMOUS) loophole?
Another person who doesn't know about SELinux. Read
http://people.redhat.com/drepper/selinux-mem.html
Stas Sergeev wrote:
>Arjan van de Ven wrote:
>> then don't put noexec on /dev/shm.
>
>That's obviously possible, but I'd feel safer having
>"noexec" on *every* user-writable partition.
But why would you "feel" safer? And why should the Linux kernel care
about how people "feel"? The purpose of these mechanisms is not to make
people feel safer; it is to make them actually be safer. If it isn't
actually making people safer -- if it is just to provide "warm fuzzies"
and a perception of safety -- then I don't see what business it has
going into the Linux kernel. What threat, exactly, are you trying to
defend against? What's your threat model?
Stas Sergeev wrote:
>Arjan van de Ven wrote:
>> no what bothers me that on the one hand you want no execute from the
>> partition, and AT THE SAME TIME want stuff to execute from there (being
>> libraries or binaries, same thing to me).
>
>The original problem came from "noexec" on /dev/shm
>mount. There is no library and no binary there, but
>the programs do shm_open(), ftruncate() and
>mmap(MAP_SHARED, PROT_EXEC) to get some shared memory
>with an exec perm. That fails.
To be honest, I still don't think you've answered Arjan's question. Ok,
so you say it is not a library and not a binary. So what is it that you
are maping in as executable, and why do you think it is reasonable to
ask the Linux kernel to allow you to execute it, if it lives on a noexec
partition? Whatever it is, you are executing it, and the goal of noexec
is to prevent execution of code that lives on a noexec partition, so
what you want to do seems in direct opposition to the goal of noexec.
Arjan's point is that what you want to do is take code that lives on a
noexec partition and execute it. Isn't that exactly against the whole
point of noexec?
Or, to put it another way, if you want to execute code off of some
partition, why do you want to be able to mark it as noexec? What is
the point of marking it noexec, when you're going to be executing code
off of it? Why not just mark it exec and be done with it? What are
your goals here? Or, to put it yet another way, what problem are you
trying to solve (and why isn't marking the partition exec a satisfactory
solution to that problem)?
I think Arjan's question is a fair one and I think he deserves a straight
answer to his question. I don't think he should have to ask it three
times.
Ulrich Drepper wrote:
>On 10/3/06, David Wagner <[email protected]> wrote:
>> Are you familiar with the mmap(PROT_EXEC, MAP_ANONYMOUS) loophole?
>
>Another person who doesn't know about SELinux. Read
>
>http://people.redhat.com/drepper/selinux-mem.html
You're right, I didn't know about that one. Thanks for the
education and for taking the time to respond.
I wonder whether it is feasible to run with allow_exec{heap,mem,mod,stack}
all set to false, on a real system. Is there any example of a fully
worked out SELinux policy that has these set to false? FC5 has
allow_execheap set to false and all others set to true in its default
SELinux policy, so it looks like the mmap(PROT_EXEC, MAP_ANONYMOUS)
loophole remains open in FC5 by default. My concern would be that setting
all of the exec-related booleans to false might break so much code that
setting them all to false wouldn't be feasible in practice. If so,
the theoretical possibility to close the mmap(PROT_EXEC, MAP_ANONYMOUS)
loophole may be one of these things that is possible in theory but not
in practice.
On Oct 04, 2006, at 00:21:27, David Wagner wrote:
> Ulrich Drepper wrote:
>> On 10/3/06, David Wagner <[email protected]> wrote:
>>> Are you familiar with the mmap(PROT_EXEC, MAP_ANONYMOUS) loophole?
>>
>> Another person who doesn't know about SELinux. Read
>>
>> http://people.redhat.com/drepper/selinux-mem.html
>
> You're right, I didn't know about that one. Thanks for the
> education and for taking the time to respond.
>
> I wonder whether it is feasible to run with allow_exec
> {heap,mem,mod,stack} all set to false, on a real system.
Yes it is; I have done so with a custom SELinux policy before
although it was a company-proprietary policy and I can't share it on
the LKML. It does fairly severely restrict certain binaries,
especially ones like the Java VM or anything else with a Just-in-Time
compiler. You can make it completely impossible for any non-admin-
originated executable or library to ever make it out to any kind of
storage from which it could be run. It's still possible to
compromise a currently-running instance of a binary; but it's
impossible to maintain that compromise across a restart of the
appropriate server process. With appropriate restrictions and
compliant hardware it's even easy to make it impossible to write to
any PROT_EXEC memory or remap any writable memory as PROT_EXEC.
Such protections require a fair amount of tinkering with userspace
and SELinux security policy, but in combination with address-space
randomization makes it extremely difficult or impossible to exploit a
stack-smash or buffer-overflow bug beyond a DoS.
It also conveniently lets you lock down a box to the point where even
root is a meaningless concept. I've helped architect one box where
you have to log in as a rootstaff user with your PKI keycard on the
local console and then enter a second password to transition to the
rootadmin role and from _there_ you have what's considered "ordinary"
root privs, but you don't even have to have that access.
> Is there any example of a fully worked out SELinux policy that has
> these set to false? FC5 has allow_execheap set to false and all
> others set to true in its default SELinux policy, so it looks like
> the mmap(PROT_EXEC, MAP_ANONYMOUS) loophole remains open in FC5 by
> default. My concern would be that setting
> all of the exec-related booleans to false might break so much code
> that
> setting them all to false wouldn't be feasible in practice.
No, it's doable but it breaks Java and WINE and a number of other
programs where you _want_ to allow modifiable code.
> If so, the theoretical possibility to close the mmap(PROT_EXEC,
> MAP_ANONYMOUS) loophole may be one of these things that is
> possible in theory but not in practice.
Oh, it's very possible in practice; but for an average distro it's
not useful to prohibit writable code. There's too many insecure
things that users want to do that require it. Just please don't
break the extra security for those of us who don't need Java or WINE
and are willing to fix the odd broken program.
Cheers,
Kyle Moffett
On Wed, Oct 04, 2006 at 03:17:59AM +0000, David Wagner wrote:
> To be honest, I still don't think you've answered Arjan's question. Ok,
> so you say it is not a library and not a binary. So what is it that you
> are maping in as executable, and why do you think it is reasonable to
> ask the Linux kernel to allow you to execute it, if it lives on a noexec
> partition?
He mentioned UML as being one thing affected by this. In this case, you
can think of it as generating code in a piece of shared memory and
then executing it. In reality, the code is read from disk rather than
being generated internally, and it's executed in a different process,
so it needs to be MAP_SHARED.
Jeff
On 10/3/06, David Wagner <[email protected]> wrote:
> I wonder whether it is feasible to run with allow_exec{heap,mem,mod,stack}
> all set to false, on a real system. Is there any example of a fully
> worked out SELinux policy that has these set to false? FC5 has
> allow_execheap set to false and all others set to true in its default
> SELinux policy,
This is the default setting to minimize breakage. And it has been set
like this (in the FC6 devel cycle) only in the last minute. For most
of the devel cycle all were off. For the distribution as a hole there
is simply too much of a chance for something to break and make the
system appear unusable. This is mostly code in 3rd party apps.
Reason enough, unfortunately, for us to default on the safe side.
But I run my machines with everything turned off. We cleaned up the
code we ship so that this is possible.
On 03/10/06, Stas Sergeev <[email protected]> wrote:
> Hello.
>
> Arjan van de Ven wrote:
> > no what bothers me that on the one hand you want no execute from the
> > partition, and AT THE SAME TIME want stuff to execute from there (being
> > libraries or binaries, same thing to me).
> The original problem came from "noexec" on /dev/shm
> mount. There is no library and no binary there, but
> the programs do shm_open(), ftruncate() and
> mmap(MAP_SHARED, PROT_EXEC) to get some shared memory
> with an exec perm. That fails.
>
So first you mount /dev/shm with 'noexec', thereby telling the system
"please make shared memory non executable".
Then an application goes and asks for executable shared memory, gets
denied and thus fails. And that's a problem? It's exactely what you
asked for.
Either you want non-executable shared memory, so you mount /dev/shm
'noexec' or you want shared memory to be executable, in which case you
don't mount it 'noexec'.
As I see it, that's really all there is to it.
--
Jesper Juhl <[email protected]>
Don't top-post http://www.catb.org/~esr/jargon/html/T/top-post.html
Plain text mails only, please http://www.expita.com/nomime.html
--- a/fs/namei.c 2006-08-29 14:15:47.000000000 +0400
+++ b/fs/namei.c 2006-10-04 11:28:52.000000000 +0400
@@ -249,9 +249,11 @@
/*
* MAY_EXEC on regular files requires special handling: We override
- * filesystem execute permissions if the mode bits aren't set.
+ * filesystem execute permissions if the mode bits aren't set or
+ * the fs is mounted with the "noexec" flag.
*/
- if ((mask & MAY_EXEC) && S_ISREG(mode) && !(mode & S_IXUGO))
+ if ((mask & MAY_EXEC) && S_ISREG(mode) && (!(mode & S_IXUGO) ||
+ (nd && nd->mnt && (nd->mnt->mnt_flags & MNT_NOEXEC))))
return -EACCES;
/* Ordinary permission routines do not understand MAY_APPEND. */
Hello.
David Wagner wrote:
>>/That's obviously possible, but I'd feel safer having/
>>/"noexec" on *every* user-writable partition./
> But why would you "feel" safer? And why should the Linux kernel care
> about how people "feel"?
I am more wondering why should I answer this,
esp. since you do not even care to CC me.
> What threat, exactly, are you trying to
> defend against? What's your threat model?
Am I supposed to explain why I want to prevent an
attacker from executing the exploit he happened to
copy to one of the user-writable mounts of mine?
> so you say it is not a library and not a binary. So what is it that you
> are maping in as executable, and why do you think it is reasonable to
> ask the Linux kernel to allow you to execute it, if it lives on a noexec
> partition?
Quick answer is: because not having the exec permission
(chmod -x file) doesn't prevent you from mapping that
file "noexec", and that's correct, not bug. The more
detailed discussion have already happened, and I'd like
to leave MAP_SHARED aside for a time.
Please tell me how your logic applies to MAP_PRIVATE instead,
because right now MAP_PRIVATE is affected the same way the
MAP_SHARED is.
Hi.
Arjan van de Ven wrote:
> and chmod o-x bash ....
> at which point.. game over.
> (and yes you can do in bash pretty much what you can do in perl. heck
> you can prove that.. shell is turning complete ;)
Can I do a syscalls from a bash script?
But in any case, I am not going to suggest any
solution against a script-loader - the mmap change
doesn't prevent that too.
Instead I'd like to evaluate a few ideas about an
ld.so problem. One of which is to _enforce_ the "noexec",
just as you asked for. :)
Please have a look at this patch:
http://uwsg.ucs.indiana.edu/hypermail/linux/kernel/0610.0/1402.html
The primary goal is to make access() to respect the "noexec".
Hi.
Jesper Juhl wrote:
> So first you mount /dev/shm with 'noexec', thereby telling the system
> "please make shared memory non executable".
Well, what do I want to tell to the system when
mounting /dev/shm with "noexec" is a difficult
point to discuss. In my opinion (and it was so
for ages) I only tell it to not execute the
binaries from there. In your opinion I am saying
to make the shared memory not executable, but on
the other hand I am just mmaping some file, and
mmaping a file with PROT_EXEC never required an
exec perm for that file, so I wonder why "noexec"
is different here.
But as I said, this is a bit difficult to discuss,
so I was trying to avoid touching MAP_SHARED for now.
Please tell me how your logic applies to MAP_PRIVATE
instead, which is affected the same way. (considering
mprotect, MAP_ANONYMOUS then read(), "ro" not denying
PROT_WRITE, etc)
Stas Sergeev wrote:
>The primary goal is to make access() to respect the "noexec".
Unfortunately, access() is insecure by design -- it is inherently
susceptible to race conditions (TOCTTOU attacks). Therefore, I don't
think it is useful for enforcing security restrictions (such as
enforcing noexec in ld.so).
--- a/fs/namei.c 2006-08-29 14:15:47.000000000 +0400
+++ b/fs/namei.c 2006-10-04 11:28:52.000000000 +0400
@@ -249,9 +249,11 @@
/*
* MAY_EXEC on regular files requires special handling: We override
- * filesystem execute permissions if the mode bits aren't set.
+ * filesystem execute permissions if the mode bits aren't set or
+ * the fs is mounted with the "noexec" flag.
*/
- if ((mask & MAY_EXEC) && S_ISREG(mode) && !(mode & S_IXUGO))
+ if ((mask & MAY_EXEC) && S_ISREG(mode) && (!(mode & S_IXUGO) ||
+ (nd && nd->mnt && (nd->mnt->mnt_flags & MNT_NOEXEC))))
return -EACCES;
/* Ordinary permission routines do not understand MAY_APPEND. */
Ar Gwe, 2006-10-06 am 22:09 +0400, ysgrifennodd Stas Sergeev:
> Hi Andrew.
>
> The attached patch makes the access(X_OK) to take the
> "noexec" mount option into an account.
>
> Signed-off-by: Stas Sergeev <[email protected]>
> CC: Jakub Jelinek <[email protected]>
> CC: Arjan van de Ven <[email protected]>
> CC: Alan Cox <[email protected]>
I doubt anyone uses access() any more for anything but this doesn't seem
to conflict with the POSIX spec.
Alan Cox wrote:
> I doubt anyone uses access() any more for anything but this doesn't seem
> to conflict with the POSIX spec.
Well, there are cases where access is used (libc, for instance, uses it
instead of an open for files which most likely don't exist since access
if faster than a failed open call).
The change itself is conceptually correct. I haven't looked at the
technical details but it looks OK.
--
➧ Ulrich Drepper ➧ Red Hat, Inc. ➧ 444 Castro St ➧ Mountain View, CA ❖
On 06/10/06, Stas Sergeev <[email protected]> wrote:
> Hi Andrew.
>
> The attached patch makes the access(X_OK) to take the
> "noexec" mount option into an account.
>
Makes sense to me.
--
Jesper Juhl <[email protected]>
Don't top-post http://www.catb.org/~esr/jargon/html/T/top-post.html
Plain text mails only, please http://www.expita.com/nomime.html
Hello.
Ulrich Drepper пишет:
> The change itself is conceptually correct. I haven't looked at the
> technical details but it looks OK.
Thankyou. Finally this seemingly hopeless thread
started to yield the positive results. :)
Now, as the access(X_OK) is fixed, would it be
feasible for ld.so to start using it?
Hello.
Alan Cox wrote:
> I doubt anyone uses access() any more for anything but this doesn't seem
Even though the access(X_OK) is mostly not needed
as the execve() would fail anyway, this is not the
case for ld.so. I think it would be a good idea for
ld.so to start using the access(R_OK | X_OK) before
open().
Stas Sergeev wrote:
>Now, as the access(X_OK) is fixed, would it be
>feasible for ld.so to start using it?
access() has TOCTTOU vulnerabilities, and should not be used for
any security-critical purpose...
Stas Sergeev wrote:
> Now, as the access(X_OK) is fixed, would it be
> feasible for ld.so to start using it?
Just must be kidding. No access control can be reliably implemented at
userlevel. There is no point starting something as stupid as this.
--
➧ Ulrich Drepper ➧ Red Hat, Inc. ➧ 444 Castro St ➧ Mountain View, CA ❖
Hello.
Ulrich Drepper wrote:
>> Now, as the access(X_OK) is fixed, would it be
>> feasible for ld.so to start using it?
> Just must be kidding. No access control can be reliably implemented at
> userlevel. There is no point starting something as stupid as this.
But in this case how can you ever solve the
problem of ld.so executing the binaries for which
the user does not have an exec permission?
Yes, the userspace apps usually should not enforce
the kernel's access control, but ld.so seems to be
the special case - it is a kernel helper after all,
so it have to be carefull and check what it does.
Stas Sergeev wrote:
>Ulrich Drepper wrote:
>>> Now, as the access(X_OK) is fixed, would it be
>>> feasible for ld.so to start using it?
>> Just must be kidding. No access control can be reliably implemented at
>> userlevel. There is no point starting something as stupid as this.
>But in this case how can you ever solve the
>problem of ld.so executing the binaries for which
>the user does not have an exec permission?
By using the kernel's existing access control -- not trying to roll
your own access control at the user level. This is a standard recommendation
in the security world, and it is good advice.
For instance, in this case, this advice might mean that you just call
execve() and check whether it succeeded or failed, and let the kernel
do the access control check on whether the exec is permitted. That tends
to be more fool-proof (or at least fool-resistant) than the alternatives.
>Yes, the userspace apps usually should not enforce
>the kernel's access control, but ld.so seems to be
>the special case - it is a kernel helper after all,
>so it have to be carefull and check what it does.
Perhaps. But it seems to me that there would need to be a persuasive
argument before it makes sense to violate the general advice listed above.
Stas Sergeev wrote:
> Even though the access(X_OK) is mostly not needed
> as the execve() would fail anyway, this is not the
> case for ld.so. I think it would be a good idea for
> ld.so to start using the access(R_OK | X_OK) before
> open().
Not really. If you want to do something along those lines it would be
better to add a new open flag called something like O_RDEXONLY which
would require r-x effective file permissions, and allow
PROT_READ|PROT_EXEC mmaps (though for that to be really useful, you'd
need to make an O_RDONLY fd not allow PROT_EXEC mmaps, which would break
a few things).
access() is just plain racy, and can't be used safely for any kind of
permission/security check.
J
On Sat, 2006-10-07 at 23:14 +0400, Stas Sergeev wrote:
> Hello.
>
> Ulrich Drepper wrote:
> >> Now, as the access(X_OK) is fixed, would it be
> >> feasible for ld.so to start using it?
> > Just must be kidding. No access control can be reliably implemented at
> > userlevel. There is no point starting something as stupid as this.
> But in this case how can you ever solve the
> problem of ld.so executing the binaries for which
> the user does not have an exec permission?
> Yes, the userspace apps usually should not enforce
> the kernel's access control,
correct
> but ld.so seems to be
> the special case - it is a kernel helper after all,
in what way is ld.so special in ANY way?
--
if you want to mail me at work (you don't), use arjan (at) linux.intel.com
Hi.
Jeremy Fitzhardinge wrote:
>> ld.so to start using the access(R_OK | X_OK) before
>> open().
> Not really. If you want to do something along those lines it would be
> better to add a new open flag called something like O_RDEXONLY which
> would require r-x effective file permissions, and allow
> PROT_READ|PROT_EXEC mmaps (though for that to be really useful, you'd
> need to make an O_RDONLY fd not allow PROT_EXEC mmaps, which would break
> a few things).
It will break _many_ things - my intention is to find a
solution for ld.so that won't break things at all. The
current solution (the hack that makes mmap(PROT_EXEC) to
fail on a "noexec" mounts) breaks just too much and doesn't
solve the problem of executing the files without an exec perm.
But your idea about playing with the flags is interesting.
What if the currently-unused MAP_EXECUTABLE flag became a
way for the program to express that it needs an exec perm,
and so the mmap should fail if there is none? I think ld.so
will be happy using such a flag...
Hello.
Arjan van de Ven wrote:
>> but ld.so seems to be
>> the special case - it is a kernel helper after all,
> in what way is ld.so special in ANY way?
It is a kernel helper. Kernel does all the security
checks before invoking it. However, when invoked
directly, it have to do these checks itself. So it is
special in a way that it have to do the security checks
which otherwise only the kernel should do.
Otherwise, please tell me, how can you solve the problem
of ld.so started directly, can execute the files you do
not have an exec permission for? The MNT_NOEXEC hack of
mmap doesn't solve that.
Jeremy proposed playing with flags - interesting.
What if the MAP_EXECUTABLE flag, which is currently unused,
will be used for the program to explicitly specify that it
needs an exec permission on the file, and fail otherwise?
Then ld.so can just use that to solve all those permission
problems.
Stas Sergeev wrote:
>> Not really. If you want to do something along those lines it would
>> be better to add a new open flag called something like O_RDEXONLY
>> which would require r-x effective file permissions, and allow
>> PROT_READ|PROT_EXEC mmaps (though for that to be really useful, you'd
>> need to make an O_RDONLY fd not allow PROT_EXEC mmaps, which would
>> break a few things).
> It will break _many_ things - my intention is to find a
> solution for ld.so that won't break things at all.
Yeah, sorry about that. I was using ironic understatement, but it's not
something that comes across well in email.
> But your idea about playing with the flags is interesting.
> What if the currently-unused MAP_EXECUTABLE flag became a
> way for the program to express that it needs an exec perm,
> and so the mmap should fail if there is none? I think ld.so
> will be happy using such a flag...
Yes, but it doesn't solve the fact that there isn't really anything
special about ld.so, so putting special checks into it doesn't really
solve the overall problem.
Also, I guess there's the general question of what the noexec mount flag
really means? Does it mean "make the execve syscall fail", or does it
mean "no bits on this filesystem may be interpreted as instructions".
The former is simple to implement, but probably not very useful; the
latter is not possible to implement in general.
J
Hi.
Jeremy Fitzhardinge wrote:
>> What if the currently-unused MAP_EXECUTABLE flag became a
>> way for the program to express that it needs an exec perm,
>> and so the mmap should fail if there is none? I think ld.so
>> will be happy using such a flag...
> Yes, but it doesn't solve the fact that there isn't really anything
> special about ld.so, so putting special checks into it doesn't really
But this is not the checks - just a flag, MAP_EXECUTABLE, which
may mean that the exec perms are required.
Currently there is no way for the program to express that
explicitly (if only by the use of the mprotect call), so
why not to add one?
> Also, I guess there's the general question of what the noexec mount flag
> really means? Does it mean "make the execve syscall fail", or does it
> mean "no bits on this filesystem may be interpreted as instructions".
Since PROT_EXEC doesn't require an exec perm on file, I don't
see why "noexec" should be special.
> The former is simple to implement, but probably not very useful; the
It can be usefull if you put it on all the user-writable
mounts of yours - then someone can't easily exec his exploit.
> latter is not possible to implement in general.
At least without selinux - yes, so my question was why to
even add the hacks.
On 08/10/06, Jeremy Fitzhardinge <[email protected]> wrote:
[snip]
> Also, I guess there's the general question of what the noexec mount flag
> really means? Does it mean "make the execve syscall fail", or does it
> mean "no bits on this filesystem may be interpreted as instructions".
> The former is simple to implement, but probably not very useful; the
> latter is not possible to implement in general.
>
As I see it, what we can resonably do with 'noexec' is
- make execve() fail.
- make access(), faccessat() return EACCESS for files stored on
'noexec' filesystems.
- make mmap(...PROT_EXEC...) fail for files stored on 'noexec' filesystems.
For things like /dev/shm we can additionally let 'noexec' mean "don't
allow executable shared memory".
Since we can't really prevent things like perl/php/bash/tcl/whatever
scripts from being executed/interpreted from there with this
mechanism, let's not worry about that. Leave that for things like
SELinux to deal with.
I don't think we can do much more with 'noexec'.
--
Jesper Juhl <[email protected]>
Don't top-post http://www.catb.org/~esr/jargon/html/T/top-post.html
Plain text mails only, please http://www.expita.com/nomime.html
On Sun, 2006-10-08 at 13:11 +0400, Stas Sergeev wrote:
> Hello.
>
> Arjan van de Ven wrote:
> >> but ld.so seems to be
> >> the special case - it is a kernel helper after all,
> > in what way is ld.so special in ANY way?
> It is a kernel helper. Kernel does all the security
> checks before invoking it. However, when invoked
> directly, it have to do these checks itself. So it is
> special in a way that it have to do the security checks
> which otherwise only the kernel should do.
wrong.
It's "special" only a little bit when the kernel invokes it, but not
really. The *application* is what decides to use which file. And for
example LSB application use another ld.so than the normal one.
(So that the LSB ld.so can translate from the LSB abi to what is on the
system).
But when invoked manually.. there is even LESS special about it... it
could be ANY file on the system. And it's no different from any other
file in /bin, /usr/bin etc etc
> Otherwise, please tell me, how can you solve the problem
> of ld.so started directly, can execute the files you do
> not have an exec permission for?
> The MNT_NOEXEC hack of
> mmap doesn't solve that.
denying PROT_EXEC of non-"x" files does (somewhat). It's never fool
proof obviously, as long as you need to allow jits.
> Then ld.so can just use that to solve all those permission
> problems.
this is just entirely a wrong assumption; one based on the assumption
that ld.so is something special, that it isn't.
--
if you want to mail me at work (you don't), use arjan (at) linux.intel.com
Hello.
Jesper Juhl wrote:
> As I see it, what we can resonably do with 'noexec' is
> - make execve() fail.
Done.
> - make access(), faccessat() return EACCESS for files stored on
> 'noexec' filesystems.
Done now in -mm.
> - make mmap(...PROT_EXEC...) fail for files stored on 'noexec' filesystems.
Even for MAP_PRIVATE?
But in what way the "noexec" is better than "chmod -x",
which does _not_ make the PROT_EXEC to fail?
> Since we can't really prevent things like perl/php/bash/tcl/whatever
> scripts from being executed/interpreted from there with this
> mechanism, let's not worry about that. Leave that for things like
> SELinux to deal with.
Exactly, but isn't it the same with mmap? (MAP_PRIVATE at least)
Since you can't prevent the prog to simply read() the data into
an anonymously mapped space, you can just as well leave that to
selinux too.
Hello.
Arjan van de Ven wrote:
> But when invoked manually.. there is even LESS special about it... it
> could be ANY file on the system. And it's no different from any other
> file in /bin, /usr/bin etc etc
I agree with that completely, but it was not me
who started adding the ld.so-specific tricks to
the kernel, making it special.
The assumptions of the current mmap check are:
1. The program does mmap with PROT_EXEC, not mmap/mprotect
(it was explicitly pointed out that this is unlikely to change).
2. The program does the file-backed mmap, not the anon
mmap then read.
That suits ld.so very well because it happened to work that
way, but it is not very usefull for pretty much anything else
(unless someone can show the real-life examples).
So this is what makes ld.so special. Right now it checks
exec/noexec by trying mmap(PROT_EXEC) and see if that fails.
But there can be other ways to check that, including the ones
that will not break the other progs/configurations.
And I don't see any harm in having a way for the program
to explicitly say whether it wants an exec perm or not.
(access() suits exactly for that, but it is racey)
>> Otherwise, please tell me, how can you solve the problem
>> of ld.so started directly, can execute the files you do
>> not have an exec permission for?
> denying PROT_EXEC of non-"x" files does (somewhat).
But you can't do that - lets be realistic. Also I wonder
whether it will violate the posix specs or not.
> It's never fool
> proof obviously, as long as you need to allow jits.
Certainly.
>> Then ld.so can just use that to solve all those permission
>> problems.
> this is just entirely a wrong assumption; one based on the assumption
> that ld.so is something special, that it isn't.
Yes, that assumption is wrong, but it was not me who
invented it. I only want to move the ld.so-specific
stuff to ld.so itself, nothing more.
Stas Sergeev <[email protected]> wrote:
> Arjan van de Ven wrote:
> >> but ld.so seems to be
> >> the special case - it is a kernel helper after all,
> > in what way is ld.so special in ANY way?
> It is a kernel helper.
Right. But what prevents anybody to have a hacked, non-testing, ld.so lying
around?
> Kernel does all the security
> checks before invoking it. However, when invoked
> directly, it have to do these checks itself. So it is
> special in a way that it have to do the security checks
> which otherwise only the kernel should do.
It just can't do them (reliably at least) in general. Call it a Unix/POSIX
design failure...
--
Dr. Horst H. von Brand User #22616 counter.li.org
Departamento de Informatica Fono: +56 32 2654431
Universidad Tecnica Federico Santa Maria +56 32 2654239
Casilla 110-V, Valparaiso, Chile Fax: +56 32 2797513
Hello.
Horst H. von Brand wrote:
> Right. But what prevents anybody to have a hacked, non-testing, ld.so lying
> around?
Having "noexec" on every user-writable mount can
kind of make that difficult - you can't easily run
the ld.so you just copied in.
> It just can't do them (reliably at least) in general.
Certainly it can't, now and then.
Right now the check is to see whether the mmap(PROT_EXEC)
fails. I wanted to change that to something that at least
won't break other apps, but of course without adding any
extra reliability.