Discussion:
Linux capabilities/ permissions brain damage
(too old to reply)
Rainer Weikusat
2020-09-11 13:06:56 UTC
Permalink
Something which just occured to me while coming up with a secure way a
setuid program can use to communicate something to the (unprivileged)
process which executed it:

Due to "Modern !!1"-disease, a setuid program running on Linux cannot
safely use any file descriptors it might have inherited. That's because
file system entities, specifically, /dev/net/tun (at least), exist which
can be opened by any unprivileged user despite said user is not allowed
to perform any operations beyond open/ close on them. This is to be
enforced with capability checks performed at the time of the
operation. And if the file descriptor was inherited by a setuid process,
this process may be able to perform operations the process which
executed it wasn't allowed to perform.

[distant sound of egg smashing into someone's face --- don't believe
your wiser than anybody else as you very probably aren't ...]
Siri Cruise
2020-09-11 15:14:56 UTC
Permalink
In article
Post by Rainer Weikusat
[distant sound of egg smashing into someone's face --- don't believe
your wiser than anybody else as you very probably aren't ...]
I don't know linux except as another unix, but aren't issues like
this supposed to be....wait a sec....

# mkdir /tmp/a
# cd /tmp/a
# echo b>b
# cat b
b
# chmod a-rwx b
# cat b
cat: b: Permission denied
# cat c.c
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
int main (int n, char **p) {
printf("WRONLY %d\n", open("b", O_WRONLY));
printf("RDONLY %d\n", open("b", O_RDONLY));
printf("RDWR %d\n", open("b", O_RDWR));
printf("EVTONLY %d\n", open("b", O_EVTONLY));
return 0;
}
# cc c.c
# ls -l .
total 40
-rwxr-xr-x 1 buffy wheel 8736 Sep 11 08:06 a.out
---------- 1 buffy wheel 2 Sep 11 07:57 b
-rw-r--r-- 1 buffy wheel 278 Sep 11 08:06 c.c
# a.out
WRONLY -1
RDONLY -1
RDWR -1
EVTONLY -1

It sounds to me like this is as safe as townhouses as long as you
have the good permissions on the file (chown root /dev/net/tun;
chmod u=rx,go-rwx /dev/net/tun). Unix security depends on good
file permissions not encoding every file's security concerns into
the kernel.
--
:-<> Siri Seal of Disavowal #000-001. Disavowed. Denied. Deleted. @
'I desire mercy, not sacrifice.' /|\
The first law of discordiamism: The more energy This post / \
to make order is nore energy made into entropy. insults Islam. Mohammed
Rainer Weikusat
2020-09-11 16:11:18 UTC
Permalink
Post by Siri Cruise
Post by Rainer Weikusat
[distant sound of egg smashing into someone's face --- don't believe
your wiser than anybody else as you very probably aren't ...]
I don't know linux except as another unix, but aren't issues like
this supposed to be....wait a sec....
# mkdir /tmp/a
# cd /tmp/a
# echo b>b
# cat b
b
# chmod a-rwx b
# cat b
cat: b: Permission denied
[...]
Post by Siri Cruise
It sounds to me like this is as safe as townhouses as long as you
have the good permissions on the file (chown root /dev/net/tun;
chmod u=rx,go-rwx /dev/net/tun). Unix security depends on good
file permissions not encoding every file's security concerns into
the kernel.
[***@doppelsaurus]/tmp#ls -l /dev/net/tun
crw-rw-rw- 1 root root 10, 200 Sep 11 10:59 /dev/net/tun

This reflects the default policy for this device node (and possibly/
probably others): Access used to be restricted via FS permissions in the
past but this is no longer the case. Instead, capability-based checks
will be performed as part of operations on the file descriptor. But
that's that not an equivalent replacement (or even improvment) because
an unprivileged process could open the file and pass the descriptor to a
privileged one.
Siri Cruise
2020-09-11 16:43:25 UTC
Permalink
In article
Post by Rainer Weikusat
Post by Siri Cruise
It sounds to me like this is as safe as townhouses as long as you
have the good permissions on the file (chown root /dev/net/tun;
chmod u=rx,go-rwx /dev/net/tun). Unix security depends on good
file permissions not encoding every file's security concerns into
the kernel.
crw-rw-rw- 1 root root 10, 200 Sep 11 10:59 /dev/net/tun
BAD SYSADM! NO TREATS FOR YOU!
Post by Rainer Weikusat
This reflects the default policy for this device node (and possibly/
probably others): Access used to be restricted via FS permissions in the
past but this is no longer the case. Instead, capability-based checks
will be performed as part of operations on the file descriptor. But
that's that not an equivalent replacement (or even improvment) because
an unprivileged process could open the file and pass the descriptor to a
privileged one.
I don't know why Linux isn't using the inode permissions. It
sounds effective me with fifty years of history securing systems.
--
:-<> Siri Seal of Disavowal #000-001. Disavowed. Denied. Deleted. @
'I desire mercy, not sacrifice.' /|\
The first law of discordiamism: The more energy This post / \
to make order is nore energy made into entropy. insults Islam. Mohammed
Rainer Weikusat
2020-09-11 17:47:45 UTC
Permalink
Post by Siri Cruise
Post by Rainer Weikusat
Post by Siri Cruise
It sounds to me like this is as safe as townhouses as long as you
have the good permissions on the file (chown root /dev/net/tun;
chmod u=rx,go-rwx /dev/net/tun). Unix security depends on good
file permissions not encoding every file's security concerns into
the kernel.
crw-rw-rw- 1 root root 10, 200 Sep 11 10:59 /dev/net/tun
BAD SYSADM! NO TREATS FOR YOU!
This is an auto-generated device node using the built-in permissions. In
fact, the documentation for this device driver "recommends" that the
permissions should be set in this way:

Set permissions:
e.g. chmod 0666 /dev/net/tun
There's no harm in allowing the device to be accessible by non-root users,
since CAP_NET_ADMIN is required for creating network devices or for
connecting to network devices which aren't owned by the user in
question.

https://www.kernel.org/doc/Documentation/networking/tuntap.txt
Post by Siri Cruise
Post by Rainer Weikusat
This reflects the default policy for this device node (and possibly/
probably others): Access used to be restricted via FS permissions in the
past but this is no longer the case. Instead, capability-based checks
will be performed as part of operations on the file descriptor. But
that's that not an equivalent replacement (or even improvment) because
an unprivileged process could open the file and pass the descriptor to a
privileged one.
I don't know why Linux isn't using the inode permissions. It
sounds effective me with fifty years of history securing systems.
Because "capability checks" are supposed to be "better". Which they
aren't.
Grant Taylor
2020-09-11 18:07:31 UTC
Permalink
Post by Rainer Weikusat
This is an auto-generated device node using the built-in
permissions.
IMHO that doesn't make any difference.

It's not difficult to get udev rules to set non-default permissions.
Post by Rainer Weikusat
In fact, the documentation for this device driver "recommends" that
e.g. chmod 0666 /dev/net/tun
There's no harm in allowing the device to be accessible by non-root
users, since CAP_NET_ADMIN is required for creating network devices
or for connecting to network devices which aren't owned by the user
in question.
IMHO "no harm" ≠ "good idea"
Post by Rainer Weikusat
Because "capability checks" are supposed to be "better". Which
they aren't.
I don't know if capability checks are better or not, but they are
probably going to happen anyway. So applying Occam's Razor & Parsimony
means that (hypothetically) removing the redundant ~> unneeded thing is
(supposedly) better.

But that in no way, shape, or form means that you shouldn't, much less
couldn't, have both checks.
--
Grant. . . .
unix || die
Siri Cruise
2020-09-11 18:21:33 UTC
Permalink
In article
Post by Rainer Weikusat
Post by Siri Cruise
I don't know why Linux isn't using the inode permissions. It
sounds effective me with fifty years of history securing systems.
Because "capability checks" are supposed to be "better". Which they
aren't.
So your argument like mine is a usable existing facility is
abandonned for something flakey?
--
:-<> Siri Seal of Disavowal #000-001. Disavowed. Denied. Deleted. @
'I desire mercy, not sacrifice.' /|\
The first law of discordiamism: The more energy This post / \
to make order is nore energy made into entropy. insults Islam. Mohammed
Rainer Weikusat
2020-09-11 19:28:49 UTC
Permalink
Post by Siri Cruise
Post by Rainer Weikusat
Post by Siri Cruise
I don't know why Linux isn't using the inode permissions. It
sounds effective me with fifty years of history securing systems.
Because "capability checks" are supposed to be "better". Which they
aren't.
So your argument like mine is a usable existing facility is
abandonned for something flakey?
Sort-of flakey. "Not designed for the environment it has to operate in"
is IMHO a better fit: The UNIX check-on-open model implies that a
program running with elevated privileges can safely use inherited file
descriptors as the invoker couldn't have created them if it didn't have
access to whatever they represent already.

This is no longer possible when access control checks are supposed to be
performed as part of "other operations" on an already open file
descriptor: It's possible that the invoking process "maliciously"
passed a descriptor refering to something it would usually be blocked
from using. On Linux, file descriptor inheritance is thus an additional
way someone could use to exploit setuid-programs.

This is mainly a problem when the setuid-program is supposed to pass
something more complicated to its invoker than just an exit status: It
can't just write "to stdout" (or stderr)[*].

[*] The workaround I came up with is "privileged program connects to an
AF_UNIX stream socket with a caller-supplied path and verifies that the
socket it connected to is really owned by the user the original process
runs as".
b***@nuttyella.co.uk
2020-09-14 09:05:06 UTC
Permalink
On Fri, 11 Sep 2020 11:21:33 -0700
Post by Siri Cruise
In article
Post by Rainer Weikusat
Post by Siri Cruise
I don't know why Linux isn't using the inode permissions. It
sounds effective me with fifty years of history securing systems.
Because "capability checks" are supposed to be "better". Which they
aren't.
So your argument like mine is a usable existing facility is
abandonned for something flakey?
systemd anyone?
Scott Lurndal
2020-09-11 23:11:22 UTC
Permalink
Post by Rainer Weikusat
Something which just occured to me while coming up with a secure way a
setuid program can use to communicate something to the (unprivileged)
Due to "Modern !!1"-disease, a setuid program running on Linux cannot
safely use any file descriptors it might have inherited.
A setuid program must not trust any state it inherits, including
file descriptors.
Kaz Kylheku
2020-09-12 01:31:10 UTC
Permalink
Post by Scott Lurndal
Post by Rainer Weikusat
Something which just occured to me while coming up with a secure way a
setuid program can use to communicate something to the (unprivileged)
Due to "Modern !!1"-disease, a setuid program running on Linux cannot
safely use any file descriptors it might have inherited.
A setuid program must not trust any state it inherits, including
file descriptors.
Well, not in modern Linux, anyway.
Rainer Weikusat
2020-09-13 13:57:03 UTC
Permalink
Post by Scott Lurndal
Post by Rainer Weikusat
Something which just occured to me while coming up with a secure way a
setuid program can use to communicate something to the (unprivileged)
Due to "Modern !!1"-disease, a setuid program running on Linux cannot
safely use any file descriptors it might have inherited.
A setuid program must not trust any state it inherits, including
file descriptors.
As explained elsewhere: Assuming UNIX permission semantics, it can
safely do things like "write output to stdout" because the file
descriptor can only refer to something the invoking process had
permission to use.

That this is no longer true on Linux because of "improved permission
checking" is a design defect of this facility (capabilities).
Scott Lurndal
2020-09-13 15:40:50 UTC
Permalink
Post by Rainer Weikusat
Post by Scott Lurndal
Post by Rainer Weikusat
Something which just occured to me while coming up with a secure way a
setuid program can use to communicate something to the (unprivileged)
Due to "Modern !!1"-disease, a setuid program running on Linux cannot
safely use any file descriptors it might have inherited.
A setuid program must not trust any state it inherits, including
file descriptors.
As explained elsewhere: Assuming UNIX permission semantics, it can
safely do things like "write output to stdout" because the file
descriptor can only refer to something the invoking process had
permission to use.
Although writing to a tun/tap file descriptor won't do anything;
one needs to use ioctl's first to setup the device.


"In order to use the driver a program has to open /dev/net/tun and issue a
corresponding ioctl() to register a network device with the kernel. A network
device will appear as tunXX or tapXX, depending on the options chosen. When
the program closes the file descriptor, the network device and all
corresponding routes will disappear."
Rainer Weikusat
2020-09-13 18:56:04 UTC
Permalink
Post by Scott Lurndal
Post by Rainer Weikusat
Post by Scott Lurndal
Post by Rainer Weikusat
Something which just occured to me while coming up with a secure way a
setuid program can use to communicate something to the (unprivileged)
Due to "Modern !!1"-disease, a setuid program running on Linux cannot
safely use any file descriptors it might have inherited.
A setuid program must not trust any state it inherits, including
file descriptors.
As explained elsewhere: Assuming UNIX permission semantics, it can
safely do things like "write output to stdout" because the file
descriptor can only refer to something the invoking process had
permission to use.
Although writing to a tun/tap file descriptor won't do anything;
one needs to use ioctl's first to setup the device.
"In order to use the driver a program has to open /dev/net/tun and issue a
corresponding ioctl() to register a network device with the kernel. A network
device will appear as tunXX or tapXX, depending on the options chosen. When
the program closes the file descriptor, the network device and all
corresponding routes will disappear."
Accidental property of the example. The concept is nevertheless flawed
(or "unsuitable for certain aspects of the environment it resides in").

NB: Presumably, the people who implemented this are convinced that
"setuid is a broken concept, anyway" (aka "Does not exist on Windows").

Aside: After the network device has been created (and configured),
reading or writing to the file descriptor can be used to send or receive
datagrams/ ethernet frames from/ to the interface.
Scott Lurndal
2020-09-13 19:21:20 UTC
Permalink
Post by Rainer Weikusat
Post by Scott Lurndal
Post by Rainer Weikusat
Post by Scott Lurndal
Post by Rainer Weikusat
Something which just occured to me while coming up with a secure way a
setuid program can use to communicate something to the (unprivileged)
Due to "Modern !!1"-disease, a setuid program running on Linux cannot
safely use any file descriptors it might have inherited.
A setuid program must not trust any state it inherits, including
file descriptors.
As explained elsewhere: Assuming UNIX permission semantics, it can
safely do things like "write output to stdout" because the file
descriptor can only refer to something the invoking process had
permission to use.
Although writing to a tun/tap file descriptor won't do anything;
one needs to use ioctl's first to setup the device.
"In order to use the driver a program has to open /dev/net/tun and issue a
corresponding ioctl() to register a network device with the kernel. A network
device will appear as tunXX or tapXX, depending on the options chosen. When
the program closes the file descriptor, the network device and all
corresponding routes will disappear."
Accidental property of the example. The concept is nevertheless flawed
(or "unsuitable for certain aspects of the environment it resides in").
It all returns to basic security principles. Don't trust anything
inherited in a setuid (or setcap) application.
Post by Rainer Weikusat
NB: Presumably, the people who implemented this are convinced that
"setuid is a broken concept, anyway" (aka "Does not exist on Windows").
The security experts who initially implemented capabilities (at SGI)
and who donated much of what is there today (along with NSA's selinux)
would disagree with your rationale. Clearly minimizing the
privilege granted to code is one of the key principles of good
security.

This, of course, long predates Linux (and its implementation in various
unix in the 90's, eg. SVR4 ES/MP); as the HP-3000 security model in
the MPE operating system was based on a capabilities, and the VAX VMS
security model was also based on capabilities.

In both systems, applications could installed with extra capabilities
by the system manager (on the HP, someone with SM privilege). This,
of course, led to security issues for both operating systems (e.g.
the HP-3000 Basic interpreter was installed with "PH" (Process Handling
) capability which allowed code to manipulate process priorities,
queue assignments, etc. Since you could call SPL/3000 functions from
basic, that pretty much allowed anyone to use PH caps). On the VAX,
the debugger was installed with change mode to kernel capability. One
doesn't need a great imagination to see the dangers in that.

In both cases, the holes were easily closed by removing said (and
generally unnecessary) capability from the applications.
Post by Rainer Weikusat
Aside: After the network device has been created (and configured),
reading or writing to the file descriptor can be used to send or receive
datagrams/ ethernet frames from/ to the interface.
My current work project uses tap devices extensively.
Rainer Weikusat
2020-09-13 19:49:57 UTC
Permalink
[...]
Post by Scott Lurndal
Post by Rainer Weikusat
Post by Scott Lurndal
Post by Rainer Weikusat
Post by Scott Lurndal
A setuid program must not trust any state it inherits, including
file descriptors.
As explained elsewhere: Assuming UNIX permission semantics, it can
safely do things like "write output to stdout" because the file
descriptor can only refer to something the invoking process had
permission to use.
Although writing to a tun/tap file descriptor won't do anything;
one needs to use ioctl's first to setup the device.
[...]
Post by Scott Lurndal
Post by Rainer Weikusat
Accidental property of the example. The concept is nevertheless flawed
(or "unsuitable for certain aspects of the environment it resides in").
It all returns to basic security principles. Don't trust anything
inherited in a setuid (or setcap) application.
This "basic principle" doesn't usually extend to inherited file
descriptors. Eg ping is a setuid-application which writes to the stdout
file descriptor it inherited.
Post by Scott Lurndal
Post by Rainer Weikusat
NB: Presumably, the people who implemented this are convinced that
"setuid is a broken concept, anyway" (aka "Does not exist on Windows").
The security experts who initially implemented capabilities (at SGI)
and who donated much of what is there today (along with NSA's selinux)
would disagree with your rationale. Clearly minimizing the
privilege granted to code is one of the key principles of good
security.
These people did not come up with the idea of creating device nodes with
0666 permissions because "capabilities rendered filesystem-based access
control obsolete". That's a fairly recent "Linux invention" (less than
twenty years old because I remember the state before and after).
Scott Lurndal
2020-09-13 20:44:47 UTC
Permalink
Post by Rainer Weikusat
These people did not come up with the idea of creating device nodes with
0666 permissions because "capabilities rendered filesystem-based access
control obsolete". That's a fairly recent "Linux invention" (less than
twenty years old because I remember the state before and after).
The beauty of unix-ish systems is that you're perfectly free to
chmod 700 /dev/net/tun.
Rainer Weikusat
2020-09-13 21:04:57 UTC
Permalink
Post by Scott Lurndal
Post by Rainer Weikusat
These people did not come up with the idea of creating device nodes with
0666 permissions because "capabilities rendered filesystem-based access
control obsolete". That's a fairly recent "Linux invention" (less than
twenty years old because I remember the state before and after).
The beauty of unix-ish systems is that you're perfectly free to
chmod 700 /dev/net/tun.
The beauty of application development is that I'm not necessarily
"perfectly free" to do this on any system an application may run on and
cannot possibly do this for any "special file" which might end up using
the same "access control mechanism" in future.
William Ahern
2020-09-14 19:10:28 UTC
Permalink
<snip>
Post by Scott Lurndal
Post by Rainer Weikusat
NB: Presumably, the people who implemented this are convinced that
"setuid is a broken concept, anyway" (aka "Does not exist on Windows").
The security experts who initially implemented capabilities (at SGI)
and who donated much of what is there today (along with NSA's selinux)
would disagree with your rationale. Clearly minimizing the
privilege granted to code is one of the key principles of good
security.
Linux capabilities are more a bad RBAC scheme. See the paper "Capability
Myths Demolished", https://srl.cs.jhu.edu/pubs/SRL2003-02.pdf.

The modern benefit of SUID is that in complex scenarios its usually the
program/developer with a better idea of the required privileges,
particularly the minimal required privileges. SUID is an escape hatch[1]
that let's the program decide how to drop privileges. SUID programs dropping
privileges may be ahistoric (not common until early 2000s), but it's not
necessarily accidental. Object capability systems are well-suited for
programmatic privilege brokering and dropping. Capsicum is a simple and
obvious refinement of this approach that should be quite familiar to anyone
with Unix programming experience; and it's theoretically rigorous.

The problem with Linux is that there's nobody at the helm. There are people
extending it's horrible "capabilities" scheme while at the same time other
people extend other APIs in a more object capabilility-friendly manner (i.e.
resource as file descriptor).

[1] In classic Unix and C fashion, it's a gigantic "worse is better" escape
hatch.
Barry Margolin
2020-09-14 07:30:10 UTC
Permalink
Post by Rainer Weikusat
NB: Presumably, the people who implemented this are convinced that
"setuid is a broken concept, anyway" (aka "Does not exist on Windows").
Capabilities were designed long before Windows (or even DOS) even
existed. OS researchers were implementing them back in the 70's,
although they never caught on in mainstream operating systems at that
time (maybe they were too expensive for systems of that era).

The problem with setuid is that it's an "all or nothing" mechanism. If a
program is setuid-root, it has access to EVERYTHING. If programmers were
perfect this wouldn't be a problem, but we're human and there are often
bugs that can be exploited for security violations.

Capabilities limits the extra privileges of a process, which minimizes
the danger of security holes.
--
Barry Margolin, ***@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
Scott Lurndal
2020-09-14 15:19:07 UTC
Permalink
Post by Barry Margolin
Post by Rainer Weikusat
NB: Presumably, the people who implemented this are convinced that
"setuid is a broken concept, anyway" (aka "Does not exist on Windows").
Capabilities were designed long before Windows (or even DOS) even
existed. OS researchers were implementing them back in the 70's,
although they never caught on in mainstream operating systems at that
time (maybe they were too expensive for systems of that era).
You mean like VMS and HP-3000 MPE? They were pretty mainstream
in their day, and both supported capabilities.
Rainer Weikusat
2020-09-14 19:01:39 UTC
Permalink
Post by Barry Margolin
Post by Rainer Weikusat
NB: Presumably, the people who implemented this are convinced that
"setuid is a broken concept, anyway" (aka "Does not exist on Windows").
Capabilities were designed long before Windows (or even DOS) even
existed. OS researchers were implementing them back in the 70's,
although they never caught on in mainstream operating systems at that
time (maybe they were too expensive for systems of that era).
The problem with setuid is that it's an "all or nothing" mechanism. If a
program is setuid-root, it has access to EVERYTHING. If programmers were
perfect this wouldn't be a problem, but we're human and there are often
bugs that can be exploited for security violations.
Capabilities limits the extra privileges of a process, which minimizes
the danger of security holes.
I didn't write anything about capabilities in general, just about the
notion that capability checks would render filesystem-based access
control obsolete.
Barry Margolin
2020-09-16 18:28:41 UTC
Permalink
Post by Rainer Weikusat
Post by Barry Margolin
Post by Rainer Weikusat
NB: Presumably, the people who implemented this are convinced that
"setuid is a broken concept, anyway" (aka "Does not exist on Windows").
Capabilities were designed long before Windows (or even DOS) even
existed. OS researchers were implementing them back in the 70's,
although they never caught on in mainstream operating systems at that
time (maybe they were too expensive for systems of that era).
The problem with setuid is that it's an "all or nothing" mechanism. If a
program is setuid-root, it has access to EVERYTHING. If programmers were
perfect this wouldn't be a problem, but we're human and there are often
bugs that can be exploited for security violations.
Capabilities limits the extra privileges of a process, which minimizes
the danger of security holes.
I didn't write anything about capabilities in general, just about the
notion that capability checks would render filesystem-based access
control obsolete.
I doubt there are many who advocate such an extreme view. Capabilities
and permissions are complementary.
--
Barry Margolin, ***@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
Grant Taylor
2020-09-13 19:37:54 UTC
Permalink
When the program closes the file descriptor, the network device and
all corresponding routes will disappear."
That's dependent on if the {TUN,TAP} device is persistent or not.
--
Grant. . . .
unix || die
Scott Lurndal
2020-09-13 20:45:32 UTC
Permalink
Post by Grant Taylor
When the program closes the file descriptor, the network device and
all corresponding routes will disappear."
That's dependent on if the {TUN,TAP} device is persistent or not.
That was a direct quote from the linux kernel Documentation directory.
Grant Taylor
2020-09-14 07:59:03 UTC
Permalink
Post by Scott Lurndal
That was a direct quote from the linux kernel Documentation directory.
The source of the quote doesn't change the accuracy of my statement.
--
Grant. . . .
unix || die
Loading...