|
|
Subscribe / Log in / New account

KPortReserve and the multi-LSM problem

By Jake Edge
August 14, 2013

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/file
That 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:

[...] Android used (co-opted, hijacked) the UID to accomplish this. Some (but not all) aspects of SELinux policy in Fedora identify the program and its standing within the system. Both of these systems abuse security attributes that are not intended to identify programs to do just that. This limits the legitimate use of those attributes for their original purpose.

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
KernelSecurity/Security modules
SecurityLinux Security Modules (LSM)


to post comments

KPortReserve and the multi-LSM problem

Posted Aug 15, 2013 22:25 UTC (Thu) by jwarnica (subscriber, #27492) [Link] (2 responses)

It isn't entirely related to this, and its not clear if this would solve my oft-pondered "WTF doesn't this exist"?

<=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
25:smtp
53:named
80:wwwrun
631:cups

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).

unprivileged access to reserved network ports

Posted Aug 16, 2013 22:28 UTC (Fri) by giraffedata (guest, #1954) [Link]

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, ...

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.

KPortReserve and the multi-LSM problem

Posted Aug 21, 2013 15:58 UTC (Wed) by mstone_ (subscriber, #66309) [Link]

The reason for the restriction on low numbered ports doesn't have anything to do with "importance", it has to do with a simple mechanism to verify that a particular connection originated from a privileged process (assuming a trusted network). This is extremely important in, e.g., an old-school NFS environment, as the use of the privileged port is the only thing that prevents unprivileged users from making privileged connections to the NFS server. The same sort of model was used for rsh and some other protocols.

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. :)

KPortReserve and program-name based port assignments

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.


Copyright © 2013, Eklektix, Inc.
This article may be redistributed under the terms of the Creative Commons CC BY-SA 4.0 license
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds