Linux Kernel Capabilities Explained
Linux Kernel Capabilities Explained
In this article, we take a quick look at Linux Kernel's permission processes and show you how to use them to keep your web page or app secure.
Join the DZone community and get the full member experience.Join For Free
Traditionally, Linux Kernel distinguishes its processes with the following two categories:
Privileged Processes: These processes allow the user to bypass all Kernel permission checks.
Unprivileged Processes: These processes are subject to full permission checks, such as the effective UID, GID, and supplementary group list.
Granting full privileged access to a user process might induce system abuse, like unauthorized changes of data, backdoors, changing ACL, etc.
Linux 2.2 shipped with a solution called Capabilities. Capabilities allows the developer to grant binaries/files specific permissions.
Let's say we want to start a Simple HTTP Server module of Python on port 80 with a non-privileged user. If we try to start the process without granting any capabilities, we will get the following error:
anshulp@dzone-vagrant-box:$ python -m SimpleHTTPServer 80 Traceback (most recent call last): File "/usr/lib/python2.7/runpy.py", line 174, in _run_module_as_main "__main__", fname, loader, pkg_name) File "/usr/lib/python2.7/runpy.py", line 72, in _run_code exec code in run_globals File "/usr/lib/python2.7/SimpleHTTPServer.py", line 235, in <module> test() File "/usr/lib/python2.7/SimpleHTTPServer.py", line 231, in test BaseHTTPServer.test(HandlerClass, ServerClass) File "/usr/lib/python2.7/BaseHTTPServer.py", line 606, in test httpd = ServerClass(server_address, HandlerClass) File "/usr/lib/python2.7/SocketServer.py", line 417, in __init__ self.server_bind() File "/usr/lib/python2.7/BaseHTTPServer.py", line 108, in server_bind SocketServer.TCPServer.server_bind(self) File "/usr/lib/python2.7/SocketServer.py", line 431, in server_bind self.socket.bind(self.server_address) File "/usr/lib/python2.7/socket.py", line 228, in meth return getattr(self._sock,name)(*args) socket.error: [Errno 13] Permission denied
Let's add the
CAP_NET_BIND_SERVICE capability to our Python binary.
sudo setcap 'CAP_NET_BIND_SERVICE+ep' /usr/bin/python2.7
The above command states that we are adding the
CAP_NET_BIND_SERVICE capability to our
+ep indicates that the file is Effective and Permitted (
"-" would remove it).
Now let's try to run the Python Simple HTTP Server module again on port 80:
anshulp@dzone-vagrant-box:$ python -m SimpleHTTPServer 80 Serving HTTP on 0.0.0.0 port 80 ... 172.28.128.1 - - [06/Jul/2017 11:30:13] "GET / HTTP/1.1" 200 - 172.28.128.1 - - [06/Jul/2017 11:30:13] code 404, message File not found 172.28.128.1 - - [06/Jul/2017 11:30:13] "GET /favicon.ico HTTP/1.1" 404 - 172.28.128.1 - - [06/Jul/2017 11:30:13] code 404, message File not found 172.28.128.1 - - [06/Jul/2017 11:30:13] "GET /favicon.ico HTTP/1.1" 404 -
We are now able to serve traffic over privileged port 80 with a non-privileged user.
At the time of writing this article, there are over 40 capabilities which can be assigned per requirement.
There are 3 modes for Capabilities:
e: Effective - This indicates that the capability is "activated."
p: Permitted - This indicates that the capability can be used.
i: Inherited - This indicates that the capability is inherited by child elements/subprocesses.
Capabilities provide a concise and efficient way to assign privileged permissions to non-privileged users.
Opinions expressed by DZone contributors are their own.