LinuxQuestions.org
LinuxAnswers - the LQ Linux tutorial section.
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Networking
User Name
Password
Linux - Networking This forum is for any issue related to networks or networking.
Routing, network cards, OSI, etc. Anything is fair game.

Notices

Reply
 
Search this Thread
Old 08-05-2005, 08:07 PM   #1
MWTJ
LQ Newbie
 
Registered: Aug 2005
Posts: 6

Rep: Reputation: 0
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
 
Old 08-05-2005, 09:07 PM   #2
Matir
Moderator
 
Registered: Nov 2004
Location: San Jose, CA
Distribution: Ubuntu
Posts: 8,507

Rep: Reputation: 118Reputation: 118
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?
 
Old 08-05-2005, 09:25 PM   #3
MWTJ
LQ Newbie
 
Registered: Aug 2005
Posts: 6

Original Poster
Rep: Reputation: 0
Quote:
Originally posted by Matir
As far as I know, that's hardcoded.
That's what I feared. This has been Unix/Linux's #1 security mis-design for the past twenty years. Someday it will be fixed, I hope.
Quote:
Might be possible with some selinux hack, but I'm not aware of that either.
I'm almost certain SELinux can do it. It's exactly the kind of thing capabilites are for. You have a capability for each port, and then you take an unprivileged process, and give it just the capability it needs to bind to its port. Then if that process gets OWN3RD the worst thing the intruder can do is take over the website, but the rest of the machine is protected. Regular Linux could do almost the same thing if it would finally get rid of this privileged ports stupidity.
Quote:
Any particular reason the app can't start as root, drop privs, and (if neccessary) fork to a child?
Yes, there's no setuid() or fork() in Java!

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 */
#define PROT_SOCK       1024
Changing that one line to
Code:
#define PROT_SOCK 0
would do the trick and be the Linux security triumph of the year, I think.

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.

Last edited by MWTJ; 08-05-2005 at 09:32 PM.
 
Old 08-05-2005, 09:49 PM   #4
Matir
Moderator
 
Registered: Nov 2004
Location: San Jose, CA
Distribution: Ubuntu
Posts: 8,507

Rep: Reputation: 118Reputation: 118
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.
 
Old 08-11-2011, 08:56 AM   #5
pquiring
LQ Newbie
 
Registered: Aug 2011
Posts: 3

Rep: Reputation: Disabled
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!
 
Old 08-11-2011, 09:40 AM   #6
pquiring
LQ Newbie
 
Registered: Aug 2011
Posts: 3

Rep: Reputation: Disabled
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

#install the source and what ever else you need
apt-get install linux-source fakeroot

mkdir ~/src
cd ~/src
tar xjvf /usr/src/linux-source-<version>.tar.bz2
cd linux-source-<version>

#edit /include/net/sock.h find PROT_SOCK and change from 1024 to 0

#copy config that you are using now
cp -vi /boot/config-`uname -r` .config

#if you want to run menuconfig you need libncurses
apt-get install libncurses5 libncurses5-dev

#run menuconfig if you want (optional)
make menuconfig

#define number threads to use when compiling (should be +1 number cpu cores)
export CONCURRENCY_LEVEL=3
#compile the custom kernel
fakeroot make-kpkg --initrd --append-to-version=custom kernel-image kernel-headers

#wait a long time

cd ..

#install your new images and reboot

dpkg -i linux-image<version>custom.deb
dpkg -i linux-headers<version>custom.deb

reboot
Enjoy!

Last edited by pquiring; 08-11-2011 at 09:41 AM. Reason: typo
 
Old 08-12-2011, 10:24 AM   #7
Nominal Animal
Senior Member
 
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
Blog Entries: 3

Rep: Reputation: 942Reputation: 942Reputation: 942Reputation: 942Reputation: 942Reputation: 942Reputation: 942Reputation: 942
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
but obviously any Java program can then bind to any port. I have not tested if using binfmt_misc and marking a specific .jar file works, but it should. Even if it does, everything running in that runtime environment will be able to bind to any port, though.

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.)
 
Old 08-12-2011, 10:35 AM   #8
pquiring
LQ Newbie
 
Registered: Aug 2011
Posts: 3

Rep: Reputation: Disabled
thanks

Thanks for that info.

I was trying to understand those CAP_... flags but didn't understand them.
 
Old 08-12-2011, 07:06 PM   #9
Nominal Animal
Senior Member
 
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
Blog Entries: 3

Rep: Reputation: 942Reputation: 942Reputation: 942Reputation: 942Reputation: 942Reputation: 942Reputation: 942Reputation: 942
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:
  • Capabilities are reset whenever a new binary is exec'd.
    Capabilities do not change when a new process is forked or a new thread is started.
  • When a process/thread acquires privileges (changes to root successfully), it gets all capabilities.
  • When a process/thread drops privileges (changes to a non-root user and group), it drops all capabilities.
    (This happens when a real, effective, or filesystem user or group ID changes from zero to non-zero, with all others either set or being set non-zero. In other words, when the "last trace" of superuser privileges is dropped.)
    A process can set the PR_SET_KEEPCAPS control using prctl() to keep capabilities when dropping privileges. It does not affect exec'ing a binary, though, and the control is always unset at exec.

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
or, if you want to set multiple capabilities,
Code:
setcap "cap_first=pe cap_second=pe cap_third=pe" binary-file
You'll obviously need superuser privileges, so run the command as root or via sudo. Afterwards, whenever that binary-file is exec'd by an unprivileged user, it will have those capabilities and those capabilities only. (If it is exec'd by superuser/root, it will of course have all capabilities.)

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,

Last edited by Nominal Animal; 08-12-2011 at 07:21 PM.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Need Java program to listen on ports < 1024 w/o being root - possible brenan99 Linux - General 2 02-22-2005 02:12 PM
using privileged ports below 1024 not possible AS ROOT??? flipper333 Slackware 2 01-23-2004 07:35 PM
opening ports below 1024 without being root? meks Linux - Networking 2 12-25-2003 06:05 PM
binding <1024 ports with non root account? linuxlouis Linux - Networking 2 08-11-2003 05:55 PM
how to bind a <1024 port number with a non root users linuxlouis Linux - Networking 0 08-11-2003 11:10 AM


All times are GMT -5. The time now is 02:21 AM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration