Allowing non-root to bind to ports < 1024?
Hello,
Is there a kernel option that would allow any user (not just root) to bind processes to ports < 1024? I know that I can recompile the kernel and change PROT_SOCK in include/net/sock.h, but I'm wondering if there is a way to remove this constraint by changing something in /proc or an IOCTL or any other run-time thing. Suggestions? I realize that i can use iptables to map port 80 to port 8080, for example, but that doesn't work on the localhost interface. This is on Suse 9.3, btw. Thanks |
As far as I know, that's hardcoded. :) Might be possible with some selinux hack, but I'm not aware of that either. Any particular reason the app can't start as root, drop privs, and (if neccessary) fork to a child?
|
Quote:
Quote:
Quote:
I'm trying to get all this to run from my Ant script. One thing I could do is write a three-line C program which would simply do the fork, etc, and make that C program setuid. But it would be nice to just have a way of turning off this nonsense. I guess on production machines I could have a home-made secure kernel where I just make the one-line patch to the include/net/sock.h to remove this. From /usr/src/linux-2.6.11.4-21.7/include/net/sock.h: Code:
/* Sockets 0-1023 can't be bound to unless you are superuser */ Code:
#define PROT_SOCK 0 Due to this "security feature" (privileged ports) it means that instead of running my application 100% in a sandbox (the JVM) as an untrusted user (nobody) 100% of the time, I have to start messing around with a less-safe language (C), using "risky" calls (setuid) and running as the system's most privileged user (root) to handle the most dangerous data (raw connections from anyone on the net). If the privileged ports thing weren't so well-established I'm sure it would make a good posting on TheDailyWTF.com. |
Sorry, I didn't know it was in Java. That does pose an interesting set of problems... I agree some sort of capabilities need to be added, but I don't like the full set of SELinux. I wish we could just associate a group with ports<1024 and have it run setgid for that group. So, the worst it could do would be to bind to those ports... big deal. :)
|
custom kernel
There is one way of doing this which I'm trying now: build a custom kernel.
You need to edit /include/net/sock.h find and change PROT_SOCK from 1024 to 0. Then compile and install your own kernel. Ubuntu has some helpful pages on doing this: https://help.ubuntu.com/community/Kernel/Compile Enjoy! |
It works!
Yup, built my own custom kernel, installed it and now tomcat is running on port 80, without using jsvc.
This means other java apps can use port < 1024 (like webapps - you can't start webapps with jsvc). Here is how I did it: Code:
https://help.ubuntu.com/community/Kernel/Compile |
You do not need to rebuild your kernels to achieve this. All you need to do is to add the cap_net_bind capability to both the permitted and effective sets for the actual program file, in your case the Java interpreter. (Actual program file means the final binary, not a symlink or a shell script.)
On say Ubuntu 10.10 using OpenJDK 6 runtime, the command to do that (once) is Code:
sudo /sbin/setcap 'cap_net_bind_service=ep' /usr/lib/jvm/java-6-openjdk/jre/bin/java You will need to have libcap-bin (Debian/Ubuntu) or libcap-progs (OpenSUSE) or libcap (RHEL/Fedora/CentOS) package installed. On some distributions the program is /sbin/setcap but /usr/sbin/setcap in others. Finally, do note that you have to run the command after updates have been applied, because the capability flags are stored in the file (inode). When rewritten, the capabilities are lost. If you use a service script to run the Java program, you can add the setcap command to the start sequence, before dropping privileges. (Since the service scripts are run with superuser privileges, no sudo is needed, and the script can unconditionally set the capability flag before running the binary.) |
thanks
Thanks for that info.
I was trying to understand those CAP_... flags but didn't understand them. |
Well, Linux capability flags describe what a thread or a process is allowed to do. Each flag is pretty well described in man 7 capabilities.
The basic principles are pretty simple:
The exact definition of reset (i.e. what happens to capabilities at exec time) is described in the capabilities man page. The rules may be confusing, so only worry about the rules if the typical use case below does not fit your needs. The main thing to note is that by default, reset means all capabilities are dropped for unprivileged users, i.e. everybody except root; and that you can give unprivileged users exec'ing some binary extra capabilities by adding them to the permitted and effective sets for that binary. So, the typical use case -- when run as an unprivileged user (non-root), allow the program to do these additional things -- is simple. Just add the desired capability flags to both the effective and permitted sets for that binary, by running either Code:
setcap cap_something=pe binary-file Code:
setcap "cap_first=pe cap_second=pe cap_third=pe" binary-file This does not work for symbolic links or scripts, however; it only works for actual program binaries. I recommend using first which program to locate the program file, then file /path/to/program to trace the symlink chain and detect possible scripts. You may need to read the scripts to find out where the actual program binary is located. Note that when upgrading a package, the package manager may replace a binary with a new file. This means that the capability flags are lost. I am not sure which package managers, if any, retain the capability flags. They are rarely used, after all. You can limit the groups that can a binary with extra capabilities, by copying the binary to a new directory, limiting access to that directory to the desired group only, and then setting the file capabilities as above. This also means you don't need to worry about updates breaking the file capabilities. (If you want to limit access to a specific user, you'd better use POSIX ACLs, with the directory owned by root, and grant access to the user via an ACL. If you let the user own the directory, the user can always replace the binary with something else.) Hope this helps, |
All times are GMT -5. The time now is 10:33 PM. |