linux process with any capabilities will fail when invoke getenv() system call

This is a copy of code9016 at https://unix.stackexchange.com/questions/588572/linux-capabilities-to-read-environment-variables.

copy here to avoid it was droped. 

Thank code9016's research.

 

 Question:

I'd like to run a service as a non-privileged user, but it needs to bind to a system port number (i.e. less than 1024), so I give it setcap 'cap_net_bind_service=+ep' <path for service>, all good.

Problem is, on startup, the service reads environment vars and for some reason it can't do that when it has cap_net_bind_service. So, with two copies of the executable, one with cap_net_bind_service, one without, only the one without can read environment vars.

It's as though there's a default set of capabilities that allows reading env vars, but the exe loses that capability when I give it cap_net_bind_service. Is that right, or is something else going on? What additional capability might I need to give to the service so that it can read env vars? There's nothing in capability.h that jumps out as being "allow env var reading"?

Answer:

In brief, the binary is using secure_getenv to access environment variables. This returns null, instead of accessing the variables, when the binary is run in "secure execution" mode (AT_SECURE=1). Having any capability set, causes it to run in this mode.

Confirm that the binary is using secure_getenv using readelf:

readelf -a <path for service> | grep getenv
00000040ac28  004b00000007 R_X86_64_JUMP_SLO 0000000000000000 secure_getenv@GLIBC_2.17 + 0
00000040ad90  007a00000007 R_X86_64_JUMP_SLO 0000000000000000 getenv@GLIBC_2.2.5 + 0
    75: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND secure_getenv@GLIBC_2.17 (6)
   122: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND getenv@GLIBC_2.2.5 (2)

Confirm that it's running in secure execution mode with environment variables (how ironic!) LD_DEBUG=all and/or LD_SHOW_AUXV (see man ld.so).

If it isn't then LD_SHOW_AUXV produces output with AT_SECURE set to 0. There is no output from LD_SHOW_AUXV when it is running in secure execution mode.

Normally, there is/isn't output from LD_DEBUG too when it is/isn't running in secure execution mode. However, if /etc/suid-debug is present (empty file, create with touch), then LD_DEBUG will produce output when running in secure execution mode.

See man getauxval for more information about AT_SECURE and secure execution mode.

posted @ 2022-06-24 17:15  耕读编码  阅读(32)  评论(0编辑  收藏  举报