linux capabilities - iptables as child process - linux

I have a process that fork-execlp "iptables-restore file.rules". It looks like it doesn't have the permission since I don't see some of the rules not listed like INPUT DROP after the process executes. When I run this process as a root, it seems to be fine but not when I run as a user with following capabilities:
parent process - cap_kill,cap_net_bind_service,cap_net_broadcast,cap_net_admin,cap_net_raw+ei
child ( iptables-restore ) - cap_net_admin,cap_net_raw+ei
What is the capability that I am missing?

I just got the same issue. My suspicion is that the issue is not about capabilities, but about simple filesystem permissions. The error I see is:
Fatal: can't open lock file /run/xtables.lock: Permission denied
The file is owned by root:root, and is RW only by the owner. So either change the file ownership to a group and chmod g+rw or use an alternative lock location using The XTABLES_LOCKFILE environment variable (based on iptables manual).
If anyone has a different solution I would love to hear about it.

Related

Can I create a chroot environment with /proc without administrator priviliges?

I am trying to make a chroot'ed, sandboxed build-environement, which creates itself from a Git checkout before proceeding with building the application. One of the requirements is that the developers doing the git checkout and invoking the build should not need admin privileges on the host machine.
unshare -r chroot
works fine - except there is no /proc which again means a lot of standeard stuff wont work.
Various methods to create /proc I have found with mount require sudo rights.
Docker does this but the developers have to be in the "docker" group which effectively gives them uncontrolled root access - then rather give them sudo rights.
I have found the "proot" which does some kind of emulation to do this. This, however, has some performance penalties.
You also need a mount namespace which will give you the ability to perform recursive bind mounts (and plain bind mount where there are no child mounts). pivot_root and the ability to mount tmpfs, so use unshare -rm.
With a pid namesapce you can also mount fresh instances of procfs.
I ended up using bubblewrap (bwrap). For a few things using ttys, I had to let it run with pseudo uid 0 to work.
If I should do it now I would use podman I think.

php5-fpm can't open file for reading

I'm trying to get my php cgi processes to read from a file on my filesystem. Both the file and parent folder have all rwx permissions allowed and the file has the same owner and group id as the php processes, www-data.
No matter how I try to open the file (read(), file_get_contents(), stream_get_contents()) I always get the same error:
failed to open stream: Permission denied
I have no problem opening the file in the php interactive session, using cat on the command line, or with python.
What is going on?
I've seen this problem before on Linux systems with SELinux enabled. The httpd process is typically given its own security context that only allows certain files to be accessed.
You can check to see if SELinux is enabled by running ls --scontext on the file and on the php script. If the two files have the same context or if ls complains about the argument then SELinux is probably not the cause of the problem.
Assuming SELinux is the cause of problem then you could try setting the file in question to have the same security context as your php script with the chcon command. For example:
chcon --reference=/var/www/html/page.php /data/filetoread
where /var/www/html/page.php is your php script and /data/filetoread is the file that you want to access.
It turns out this file was under a FUSE filesystem which had not been mounted with the allow_other option.

pppoe-server log file

I have installed successfully the roar-penguin pppoe-server and trying to use it without success, what I don't understand is that, when I put in my /etc/ppp/pppoe-server-options
debug
logfile /var/log/pppoe-server-log
But that file is not created and I don't understand what happens. It is really hard for me find a solution. Do you know how can I enable the debugging ?
My problem is that I catch every time (Wireshark sniffing) the
RP-PPPoE: Child pppd process terminated
In the PADT message, any help ?
Thanks in advance.
From your question not being formatted, verify that debug and logfile in /var/log/pppoe-server-log are on separate lines in your configuration file. Also, ensure that you've restarted the service to utilize the new configuration. If the service is not running as root, be sure that the user it runs as has ownership over the logfile to write to it. If it is running as root, ensure the file exists and that it's writable.
If it doesn't exist, just run:
# touch /var/log/pppoe-server-log
# chmod 0774 /var/log/pppoe-server-log
I would think this should be done automatically, but you may as well do so just to ensure it's created properly and you can verify ownership/permissions as needed.

raw socket access as normal user on linux 2.4

In an embedded system (2.4 kernel) I need raw socket access to the eth0 interface from a process not running as root.
I tried to address this problem by setting the CAP_NET_RAW capability from the command line and programmatically using cap_set_proc(), both with no success. It seems that I do not have the permission to do so, in the program I get an EPERM error, on the command line
Failed to set cap's on process `1586': (Operation not permitted)
Is there an easier way to do what I want? If not, what steps are necessary to successfully set the CAP_NET_RAW capability?
EDIT: I have root access, but running the process permanently as root is no option. The version of libcap is 1.10, there is no 'setcap' binary, but a 'setpcaps'.
EDIT - answering George Skoptsov:
If I get you right, your suggestion is to start a process with setuid, then set the CAP_NET_RAW capability and then drop the privileges. I tried this with the following code, but it does not seem to work, even though the caps command do not return errors. With the seteuid() commented out, raw access works, but only since the process is running as root then:
cap_t caps = cap_get_proc();
cap_value_t cap_list[1];
cap_list[0] = CAP_NET_RAW;
if (cap_set_flag(caps, CAP_EFFECTIVE, 1, cap_list, CAP_SET) == -1)
{
printf("cap_set_flag error");
}
if (cap_set_proc(caps) == -1)
{
printf("cap_set_proc error");
}
if (seteuid(getuid()) != 0)
{
printf("seteuid error");
}
function_that_needs_raw_access();
Thanks for your help.
Chris
Generally, you need root permissions to receive raw packets on an interface. This restriction is a security precaution, because a process that receives raw packets gains access to communications of all other processes and users using that interface.
However, if you have access to root on the machine, you can use the setuid flag to give your process root privileges even when the process is executed as a non-root user.
First, ensure that this capability is set successfully when the process is run as root. Then use
sudo chown root process
sudo chmod ugo+s process
to set root as owner of the process and set the setuid flag. Then check that the capability is set when the process is run by other users. Because this process will now have all superuser privileges, you should observe security precautions, and drop the privileges as soon as your code no longer requires it (after enabling the CAP_NET_RAW).
You can follow this method to ensure you're dropping them properly.
You can give an executable program the ability to use the CAP_NET_RAW privilege without giving it other root privileges.
$ setcap cap_net_raw=pe *program*
You cannot give this privilege without having this privilege. Certainly root can give this privilege to programs.
The process must be run as root, or have the CAP_NET_RAW capabilities on the executable.
In order to set CAP_NET_RAW, you need to run the setcap command as root. Once set, you can run the executable as another user, and it'll have access to raw packet capturing.
If you do not have root access in anyway, nor can get anyone with root access to set CAP_NET_RAW or setuid root on the executable, you'll not be able to do packet capturing as a non-root user.
TL;DR IMHO not supported in kernel < 3.0.
There was a discussion about supporting it in kernel netdev mailing list:
https://lwn.net/Articles/420800/ and https://lwn.net/Articles/420801/.
And included it in commit
c319b4d76b9e583a5d88d6bf190e079c4e43213d, released in kernel 3.0:
commit c319b4d76b9e583a5d88d6bf190e079c4e43213d
Author: Vasiliy Kulikov <segoon#openwall.com>
Date: Fri May 13 10:01:00 2011 +0000
net: ipv4: add IPPROTO_ICMP socket kind
Follows: v2.6.39-rc2
Precedes: v3.0-rc1
Running ping without CAP_NET_RAW (i.e. without setting capabilities or without set-uid) was implemented for ping in revision 87dbb3a5db657d5eae6934707beaf0507980a1c3, released in iputils s20150815:
commit 87dbb3a5db657d5eae6934707beaf0507980a1c3
Author: Nikos Mavrogiannopoulos <nmav#redhat.com>
Date: Fri May 29 11:01:00 2015 +0200
This patch allows running ping and ping6 without root privileges on
kernels that support it. Almost identical to Lorenzo
Colitti's original patch except:
...
Follows: s20140519
Precedes: s20150815

Must my pidfile be located in /var/run?

I'm asking in both contexts: technically and stylistically.
Can my application/daemon keep a pidfile in /opt/my_app/run/?
Is it very bad to do so?
My need is this: my daemon runs under a specific user, and the implementor must mkdir a new directory in /var/run, chown, and chgrp it to make my daemon run. Seems easier to just keep the pidfile local (to the daemon).
I wouldn't put a pidfile under an application installation directory such as /opt/my_app/whatever. This directory could be mounted read-only, could be shared between machines, could be watched by a daemon that treats any change there as a possible break-in attempt…
The normal location for pidfiles is /var/run. Most unices will clean this directory on boot; under Ubuntu this is achieved by /var/run an in-memory filesystem (tmpfs).
If you start your daemon from a script that's running as root, have it create a subdirectory /var/run/gmooredaemon and chown it to the daemon-running user before suing to the user and starting the daemon.
On many modern Linux systems, if you start the daemon from a script or launcher that isn't running as root, you can put the pidfile in /run/user/$UID, which is a per-user equivalent of the traditional /var/run. Note that the root part of the launcher, or a boot script running as root, needs to create the directory (for a human user, the directory is created when the user logs in).
Otherwise, pick a location under /tmp or /var/tmp, but this introduces additional complexity because the pidfile's name can't be uniquely determined if it's in a world-writable directory.
In any case, make it easy (command-line option, plus perhaps a compile-time option) for the distributor or administrator to change the pidfile location.
The location of the pid file should be configurable. /var/run is standard for pid files, the same as /var/log is standard for logs. But your daemon should allow you to overwrite this setting in some config file.
/opt is used to install 'self-contained' applications, so nothing wrong here. Using /opt/my_app/etc/ for config files, /opt/my_app/log/ for logs and so on - common practice for this kind of application.
This away you can distribute your applications as a TGZ file instead of maintaining a package for every package manager (at least DEB since you tagged ubuntu). I would recommend this for in-house applications or situations where you have great control over the environment. The reasoning is that it makes no sense if the safe costs more than what you are putting inside (the work required to pack the application should not eclipse the effort required to write the application).
Another convention, if you're not running the script as root, is to put the pidfile in ~/.my_app/my_app.pid. It's simpler this way while still being secure as the home directory is not world-writeable.

Resources