KPortReserve and the multi-LSM problem
Network port numbers are a finite resource, and each port number can only be used by one application at a time. Ensuring that the "right" application gets a particular port number is important because that number is required by remote programs trying to connect to the program. Various methods exist to reserve specific ports, but there are still ways for an application to lose "its" port. Enter KPortReserve, a Linux Security Module (LSM) that allows an administrator to ensure that a program gets its reservation.
One could argue that KPortReserve does not really make sense as an LSM—in fact, Tetsuo Handa asked just that question in his RFC post proposing it. So far, no one has argued that way, and Casey Schaufler took the opposite view, but the RFC has only been posted to the LSM and kernel hardening mailing lists. The level of opposition might rise if and when the patch set heads toward the mainline.
But KPortReserve does solve a real problem. Administrators can ensure that automatic port assignments (i.e. those chosen when the bind() port number is zero) adhere to specific ranges by setting a range or ranges of ports in the /proc/sys/net/ipv4/ip_local_reserved_ports file. But that solution only works for applications that do not choose a specific port number. Programs that do choose a particular port will be allowed to grab it—possibly at the expense of the administrator's choice. Furthermore, if the port number is not in the privileged range (<= 1024), even unprivileged programs can allocate it.
There is at least one existing user-space solution using portreserve, but it still suffers from race conditions. Systemd has a race-free way to reserve ports, but it requires changes to programs that will listen on those ports and is not available everywhere, which is why Handa turned to a kernel-based solution.
The solution itself is fairly straightforward. It provides a socket_bind() method in its struct security_operations to intercept bind() calls, which checks the reserved list. An administrator can write some values to a control file (where, exactly, that control file would live and the syntax it would use were being discussed in the thread) to determine which ports are reserved and what program should be allowed to allocate them. For example:
echo '10000 /path/to/server' >/path/to/control/fileThat would restrict port 10,000 to only being used by the server program indicated by the path. A special "<kernel>" string could be used to specify that the port is reserved for kernel threads.
Vasily Kulikov
objected to
specifying that certain programs could bind the port, rather a user ID
or some LSM security context, but Schaufler disagreed, calling it "very 21st century
thinking
". His argument is that using unrelated attributes to
govern port reservation could interfere with the normal uses of those
attributes:
What Tetsuo is proposing is using the information he really cares about (the program) rather than an attribute (UID, SELinux context, Smack label) that can be associated with the program. Further, he is using it in a way that does not interfere with the intended use of UIDs, labels or any other existing security attribute.
Beyond that, Handa noted that all of the programs he is interested in for this feature are likely running as root. While it would seem that root-controlled processes could be coordinated so that they didn't step on each other's ports, there are, evidently, situations where that is not so easy to arrange.
In his initial RFC, Handa wondered if the KPortReserve functionality should simply be added to the Yama LSM. At the 2011 Linux Security Summit, Yama was targeted as an LSM to hold discretionary access control (DAC) enhancements, which port reservations might be shoehorned into—maybe. But, then and since, there has been a concern that Yama not become a "dumping ground" for unrelated security patches. Thus, Schaufler argued, Yama is not the right place for KPortReserve.
However, there is the well-known problem for smaller, targeted LSMs: there is currently no way to have more than one LSM active on any given boot of the system. Handa's interest in Yama may partly be because it has, over time, changed from a "normal" LSM to one that can be unconditionally stacked, which means that it will be called regardless of which LSM is currently active. Obviously, if KPortReserve were added to Yama, it would likewise evade the single-LSM restriction.
But, of course, Schaufler has been working on another way around that restriction for some time now. There have been attempts to stack (or chain or compose) LSMs for nearly as long as they have existed, but none has ever reached the mainline. The latest entrant, Schaufler's "multiple concurrent LSMs" patch set, is now up to version 14. Unlike some earlier versions, any of the existing LSMs (SELinux, AppArmor, TOMOYO, or Smack) can now be arbitrarily combined using the technique. One would guess it wouldn't be difficult to incorporate a single-hook LSM like KPortReserve into the mix.
While there was some discussion of Schaufler's patches when they were posted at the end of July—and no objections to the idea—it still is unclear when (or if) we will see this capability in a mainline kernel. One senses that we are getting closer to that point, and new single-purpose LSM ideas crop up fairly regularly, but we aren't there yet. Schaufler will be presenting his ideas at the Linux Security Summit in September. Perhaps the discussion there will help clarify the future of this feature.
Index entries for this article | |
---|---|
Kernel | Security/Security modules |
Security | Linux Security Modules (LSM) |
Posted Aug 15, 2013 22:25 UTC (Thu)
by jwarnica (subscriber, #27492)
[Link] (2 responses)
<=1024 is reserved, based on historical reasons, for root-executed processes. Allegedly, this is because important things run <=1024 and non-important things don't, and this hysterical, er, historical, conclusion fails to pass any sniff test of sanity. There are lots of hosts out their with out any meaningful concept of users; with more granularity in their admin/not distinctions than unix; or less (including Linux appliances that run everything as root)
So taking some widely used apps, with their own user id's, why _isn't_ there a file thus:
/etc/portsec
i.e. given users can bind to low ports. Mail servers, web server, dns server, need not run as root even for an instant. Just startup and bind to their standard port. No dropping permissions, no master socket listener waiting to pass things off to a low privilege thread. Just run as whoever and bind to what you are allowed to (at least for <=1024).
Posted Aug 16, 2013 22:28 UTC (Fri)
by giraffedata (guest, #1954)
[Link]
I suppose it's because people think something based on a superuser process is more consistent with Unix overall, more flexible, less work, etc. I do.
Other operating systems were designed to have a variety of permission lists, for a variety of fixed kinds of permissions, which is what you're describing, but Unix designers thought it was superior just to have one basic permission: superuser. Coupled with the setuid flag, that meant application developers could implement an unimaginable variety of permission schemes just by writing code.
In retrospect, we know that that flexibility creates no end of opportunity for accidentally granting too much permission, but the engineering simplicity of it is still appealing.
I personally don't like having a server program drop permissions because it means I have to trust the program to drop the permissions, and have duplicate code in every server program. But I do a similar thing where a single program dedicated to binding ports binds the port, drops permissions, then execs the server program (actually, teh binder execs a program that sets permissions and that program execs the server program).
That port binder program could easily be setuid superuser and consult a file such as you propose, but I haven't found that maintaining such a file would be preferable to maintaining the scripts that invoke it, which contain the same information.
Posted Aug 21, 2013 15:58 UTC (Wed)
by mstone_ (subscriber, #66309)
[Link]
Obviously, in the modern world you'd want to depend on some sort of strong authentication rather than origin port, especially if you're on a trusted network which mixes traditional unix systems with other systems which don't enforce privileged ports or any untrusted network. Nevertheless, as long as people use linux to interoperate with legacy environments it's useful to retain this now-obsolete functionality. It's also useful to understand this model if you run a legacy NFS environment--I've even seen some vendors who have forgotten, and shipped NFS configurations which permitted any user on an NFS client to read any file on an NFS server (scary, and exploited). And if you create any new protocol which depends on this property, you're an idiot. :)
Posted Aug 16, 2013 22:34 UTC (Fri)
by giraffedata (guest, #1954)
[Link]
He sure didn't make his point that making permissions based on the program is better than making them based on the uid (or anything else).
I should be able to run 10 web servers all running Apache, with each entitled to its own unique port. If I have to vary some attribute to give them different port permissions, I'd much rather give the processes different uids than give Apache different names.
I find altogether too much conflating of programs with services.
And I especially didn't get why being 21st century thinking makes it bad.
KPortReserve and the multi-LSM problem
25:smtp
53:named
80:wwwrun
631:cups
unprivileged access to reserved network ports
i.e. given users can bind to low ports. Mail servers, web server, dns server, need not run as root even for an instant. Just startup and bind to their standard port. No dropping permissions, ...
KPortReserve and the multi-LSM problem
KPortReserve and program-name based port assignments