Hacker News new | past | comments | ask | show | jobs | submit login
Linux Capabilities in a nutshell (2019) (k3a.me)
118 points by todsacerdoti on Feb 25, 2021 | hide | past | favorite | 31 comments



Nice article. I'd like to make 2 additions:

#1: I disagree with the very first sentence ("Capabilities are being use more and more, mainly thanks to SystemD, Docker and orchestrators like Kubernetes.") - a lot of old-fashioned daemons already use capabilities to limit their privileges and/or raise and lower them as needed.

#2: pspax from pax-utils is a great tool to show process capabilities:

  # pspax
  USER     PID    PAX    MAPS ETYPE      NAME             CAPS ATTR  
  root     1      ---    w^x  ET_DYN     init             =ep  system_u:system_r:init_t:s0  
  root     2575   ---    w^x  ET_DYN     udevd            =ep  system_u:system_r:kernel_t:s0  
  root     2752   ---    w^x  ET_DYN     dmeventd         =ep  system_u:system_r:kernel_t:s0  
  root     60844  ---    w^x  ET_DYN     auditd           =ep  system_u:system_r:kernel_t:s0  
  root     60879  ---    w^x  ET_DYN     crond            =ep  system_u:system_r:kernel_t:s0  
  root     60910  ---    w^x  ET_DYN     ntpd             cap_net_bind_service,cap_ipc_lock,cap_sys_time=ep system_u:system_r:kernel_t:s0  
  root     61532  ---    w^x  ET_DYN     lxc-start        =ep  system_u:system_r:kernel_t:s0  
  -------- 61542  ---    w^x  ET_EXEC    init             =eip system_u:system_r:kernel_t:s0  
  root     66327  ---    w^x  ET_DYN     lxc-start        =ep  system_u:system_r:kernel_t:s0  
  -------- 66328  ---    w^x  ET_EXEC    init             =eip system_u:system_r:kernel_t:s0  
  root     70543  ---    w^x  ET_DYN     zebra            cap_net_admin,cap_net_raw,cap_sys_admin=p system_u:system_r:kernel_t:s0  
  root     70785  ---    w^x  ET_DYN     ospfd            cap_net_bind_service,cap_net_admin,cap_net_raw,cap_sys_admin=p system_u:system_r:kernel_t:s0  
  root     70794  ---    w^x  ET_DYN     ospf6d           cap_net_bind_service,cap_net_raw=p system_u:system_r:kernel_t:s0  
  root     71529  ---    w^x  ET_DYN     bgpd             cap_net_bind_service,cap_net_admin,cap_net_raw,cap_sys_admin=p system_u:system_r:kernel_t:s0  
  root     71770  ---    w^x  ET_DYN     syslog-ng        =ep  system_u:system_r:kernel_t:s0  
  root     71771  ---    w^x  ET_DYN     syslog-ng        cap_syslog=ep cap_chown,cap_dac_override,cap_dac_read_search,cap_fowner,cap_net_bind_service,cap_net_broadcast,cap_net_raw+p system_u:system_r:kernel_t:s0
  [...]
(Note: in some versions of pspax, this is unfortunately broken; if you see everything with only "=ep", that's probably not right.)


Interesting, pax-utils-v1.2.5 on Arch Linux 5.10.9-arch1-1:

  > pspax   
  USER     PID    PAX    MAPS ETYPE      NAME             CAPS ATTR  
  [1]    3209832 invalid system call (core dumped)  pspax

  Stack trace of thread 3209832:
  #0  0x00007fbdb92d89ab __socket (libc.so.6 + 0x1019ab)
  #1  0x00007fbdb930dce0 open_socket (libc.so.6 + 0x136ce0)
  #2  0x00007fbdb930e1de __nscd_get_mapping (libc.so.6 + 0x1371de)
  #3  0x00007fbdb930e62f __nscd_get_map_ref (libc.so.6 + 0x13762f)
  #4  0x00007fbdb930ac47 nscd_getpw_r (libc.so.6 + 0x133c47)
  #5  0x00007fbdb930b0b6 __nscd_getpwuid_r (libc.so.6 + 0x1340b6)
  #6  0x00007fbdb92a3895 getpwuid_r@@GLIBC_2.2.5 (libc.so.6 + 0xcc895)
  #7  0x00007fbdb92a2eeb getpwuid (libc.so.6 + 0xcbeeb)
  #8  0x0000558995732566 n/a (pspax + 0x4566)
  #9  0x00007fbdb91ff152 __libc_start_main (libc.so.6 + 0x28152)
  #10 0x0000558995732e8e n/a (pspax + 0x4e8e)

  Dump of assembler code for function socket:
     0x00007fb1d04139a0 <+0>:     endbr64 
     0x00007fb1d04139a4 <+4>:     mov    $0x29,%eax
     0x00007fb1d04139a9 <+9>:     syscall 
  => 0x00007fb1d04139ab <+11>:    cmp    $0xfffffffffffff001,%rax
     0x00007fb1d04139b1 <+17>:    jae    0x7fb1d04139b4 <socket+20>
     0x00007fb1d04139b3 <+19>:    ret    
     0x00007fb1d04139b4 <+20>:    mov    0xc0495(%rip),%rcx        # 0x7fb1d04d3e50
     
This can be a system library incompatibility though as don't have all system packages up-to-date.

The code compiled from https://github.com/gentoo/pax-utils runs but displays just = under CAPS for every process.

So I am not sure it is generally usable outside of Gentoo (yet).


Took a quick look... can you try this diff?

  --- pspax.c 2021-02-26 09:46:14.304092510 +0100
  +++ pspax.c 2021-02-25 11:25:42.439550015 +0100
  @@ -413,7 +413,7 @@
   
     /* this is a non-POSIX function */
     caps = NULL;
  -  WRAP_SYSCAP(capgetp(pfd, cap_d));
  +  WRAP_SYSCAP(cap_d = cap_get_pid(pid));
     WRAP_SYSCAP(caps = cap_to_text(cap_d, &length));
   
     if (pwd && strlen(pwd->pw_name) >= 8)


The problem was I didn't compile it with pcap support initially (it is not enabled by default). It needs:

make USE_CAP=yes

Then it showed "=ep" for every process BUT your patch fixed it and now it correctly lists process capabilities.

According to man, capgetp() is deprecated and cap_get_pid() should be used instead anyway.

EDIT: I can see your patch merged upstream, good work! :)


An interesting page, yet the font has text-shadow enabled -- which on my monitor/desktop/browser, just makes it look blurry.

To me, it's barely legible.

It may appear different to others, for example when I looked on my phone, the effect was not as prominent. I'll pass.


Author here, sorry about the text-shadow. I added it there many years ago and it seemed like a good idea back then. After webs started over-using various shadows and animations, I installed Stylus Firefox extension with rules disabling shadows and animations and completely forgot that the rule is still there! Removed now.


As others have mentioned Reader-Mode in Firefox bypasses this, but Dark-Reader extension (atleast on Firefox) brings back the legibility too.

This style habit (along with grey text on white/light-grey) is downright hostile to end-users and needs to stop.


Yeah the text is uncomfortable, thankfully Firefox's Reader mode worked well.


Did Firefox reader mode on Linux loose its TTS feature or was it never present on Linux? It was quite useful feature on macOS but I miss it on Linux now. I guess it has something to do with Pocket.


Mine has it. I'm guessing it is checking for a library and if it exists then it shows the icon because it showed up after a few seconds.

There are about a 100 different voices that I can choose from and they all suck.

A few months ago we trained a pretty nice DNN TTS engine and I wish I had the permission to release as a free software for Linux. I feel Linux has been in need of a good TTS forever.


I think you're correct, it seems speech-dispatcher was made an optional dependency for firefox build and that Arch requires 'festival-freebsoft-utils'[1] along with 'speech-dispatcher' for narrator but the former hasn't been updated in a long time. Not sure whether that's the reason, but narrator doesn't work even after installing those packages although the speech-dispatcher gets triggered in the firewall when the reader mode is accessed.

Interestingly, this is a closed bug in Arch. Guess it's time to reopen it.

[1]https://aur.archlinux.org/packages/festival-freebsoft-utils/

[2]https://bugs.archlinux.org/task/50886


Reader mode is available (at least on FF version 85). There is a headphone icon appears on the upper left of the page and allows you to set the reading speed and choose from a bunch of different voices.


On Linux? I'm on FF 85 as well and all I see is the Font & Pocket button on the left panel in reader more and the headphone which was available on macOS is missing.


Yes, working here on Linux. Maybe go into about:config and look for "narrate" options, perhaps your "narrate.enable" is set to false?


narrate.enable is true, only narrate.test was false and making it true didn't help. I'll try digging deeper, thanks.


Thanks. I'm alternating between computer screens and I honestly though something was wrong with my eyes when I saw that article.


Looks okay in links. Oddly I get a 403 using w3m.


Yes, 403 Forbidden in lynx as well. This is a very unfortunate trend I've seen increasing over the last couple years. The answer almost always comes from an nginx server, but my understanding is that it's User-Agent sniffing being done for DDOS protection and the use of nginx (being used as a proxy?) is incidental. I have not been able to find any good discussions about it.


Lynx is also sending HTTP/1.0:

  GET /linux-capabilities-in-a-nutshell/ HTTP/1.0
  Host: k3a.me
  User-Agent: Lynx/2.9.0dev.5 libwww-FM/2.14 SSL-MM/1.4.1 GNUTLS/3.6.13
I am quite surprised actually. It is unfortunate that these clients still haven't been updated to at least HTTP/1.1. :(

Just patch Lynx to send HTTP/1.1 without implementing keep-alive or any other HTTP/1.1 functionality and your troubles will most likely end. :P It is better to have broken 1.1 implementation than broken 1.0.

CURL is using 2.0 for HTTPS and 1.1 for HTTP by default. Someone should upgrade these CLI browsers to use libcurl or something like that...


I think this has more to do with nginx being one of (if not the) most popular *nix web servers, rather than nginx administrators hating lynx users. I run plenty of websites with nginx that you can browse with lynx just fine.


Yes, sorry, I meant to make that more clear: this is NOT an nginx issue. It just HAPPENS that I always see nginx on the 403 page.

It appears somebody doesn't like lynx's User-Agent string and it makes me sad.


Author here. It is Nginx with ModSecurity. It looks like your client uses HTTP/1.0 which I blacklisted as HTTP/1.0 doesn't make sense nowadays as it originally didn't even support Host header for virtual hosts. HTTP/1.0 is often used by badly-written web scrappers.


The web is slowly becoming unusable in modern browsers, a reverse of the earlier trend.


Linux capabilities are an interesting area, with some nuances (like ambient) which can be a bit unobvious at first glance. Adrian Mouat did a good deep dive post about them and some practical examples of using capabilities . https://blog.container-solutions.com/linux-capabilities-in-p...


ambient capabilities will be a whole lot nicer once more userspace stuff (like the pam caps stuff) supports them better.

The idea for them comes from one of my former coworkers, Christoph Lameter, when we were having issues with an app that needed CAP_NET_RAW for tcp sockets that we didn't want to be setuid root. Small world :)


Interesting, I didn't even know this existed. I guess the "old way" of allowing an "inferior users" (like tomcat8 in my example) to bind to a port below 1024 is now out-dated? I've always used authbind:

     # cat /etc/default/tomcat8 | grep AUTHBIND
       AUTHBIND=yes

     # touch /etc/authbind/byport/80
     # chown tomcat8:tomcat8 /etc/authbind/byport/80

I guess instead the capabilities should be added for the start-up script?


cap_net_bind_service is all or nothing: you either get permission to bind all service ports or none of them. So in this case it'd be more relevant for running authbind rootless too.

The actual modern solution here would be to use systemd socket activation (systemd binds the port and lets your process inherit it on startup).


> So in this case it'd be more relevant for running authbind rootless too.

Ahh OK, that makes more sense.

> would be to use systemd socket activation

I have to admit that every time I need one of those systemd scripts for some type of service I have, it's usually just a copy-n-paste from an older one with small modifications of paths/name etc. Perhaps I should actually learn some of that stuff. I guess it is here to stay; even though there was some debate about it a few years ago.


It looks pretty straight forward in Tomcat 8 or later.

* Set useInheritedChannel="true" on one (and only one) connector

* Create tomcat.socket as described in https://bz.apache.org/bugzilla/show_bug.cgi?id=60560#c8

Shame tomcat can only accept one 'inherited' channel, so you can't have Tomcat's :443 _and_ :80 connectors both make use of systemd-created sockets.


> It looks pretty straight forward in Tomcat 8 or later.

Yes, when seeing the examples, it doesn't look too bad. I guess without any example and no idea (at all) on how to set this up, it would still take quite some time to figure out.


https://forums.grsecurity.net/viewtopic.php?t=2522

Capabilities are really sort of a poorly thought out boundary. It's like, yes this is technically better than full root, but ultimately most individual capabilities are still extremely powerful/ can be leveraged for root.

At the end of the day I highly recommend capabilities as a measure of last resort - it's a "may as well", not a goal.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: