[Bug 565002] Re: ldopen failing with relative path when linux capability is set

Douglas Leeder 565002 at bugs.launchpad.net
Tue Feb 4 20:13:09 UTC 2020


This is the commit that added the protection:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=800179c9b8a1e796e441674776d11cd4c05d61d7

Ubuntu must turn it on by default.

The risk, without that kernel option turned on, is:

1. High priv (setuid etc) binary with $ORIGIN runpath
2. Low priv user hard-links binary into a directory they control
3. Create malicious shared library that binary will load from $ORIGIN runpath.

I think that the kernel protection prevents 2. And I don't know if
there's any other exploits.

-- 
You received this bug notification because you are a member of Ubuntu
Foundations Bugs, which is subscribed to glibc in Ubuntu.
https://bugs.launchpad.net/bugs/565002

Title:
  ldopen failing with relative path when linux capability is set

Status in glibc package in Ubuntu:
  Confirmed

Bug description:
  Call to ldopen is failing when a POSIX capability is set on the file
  and a $ORIGIN relative path is given.

  Relative path is used in some major tool such as the Java VM when required to grant bind on port less than 1024 without giving the su rights (for obvious security reasons). The impacted applications are : applications server, mail servers, etc ... all running Java.
  See http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6919633

  For capability priviledge port bind, the only work-around are :
   - patch the binary containing the $ORIGIN an replace it with code absolute path (ugly, isn't it?)
   - use a iptable PAT redirection (prevent dynamic bind as you have to know beforehand the port value to create a rule) : make configuration complex and bring some limitations.

  For other capabilities, there might be no workaround but to go with
  the setuid :(

  Here is example of a program helping to reveal the potential bug :

  #include <stdio.h>
  #include <stdlib.h>
  #include <dlfcn.h>
  #include <unistd.h>

  int main(int argc, char *argv[]){
      void *handle;
      double (*cosine)(double);
      char *error;

      printf("UID=%d EffUID=%d\n", getuid(), geteuid());

      handle = dlopen (argv[1], RTLD_LAZY);
      if (!handle) {
          fprintf (stderr, "%s\n", dlerror());
          exit(1);
      }
      dlerror();    /* Clear any existing error */
      cosine = dlsym(handle, argv[2]);
      if ((error = dlerror()) != NULL)  {
          fprintf (stderr, "%s\n", error);
          exit(1);
      }
      printf ("res:%f\n", (*cosine)(2.0));
      dlclose(handle);
      return 0;
  }

  Let's compile that :
  gcc -o bug-cap-origin -ldl bug-cap-origin.c

  cp bug-cap-origin ~
  cd ~

  Step 1 : Initial checkings

  getcap bug-cap-origin
   -> empty result (= no capabilities set at this time)
  ./bug-cap-origin '/usr/lib64/libm.so' sin
   -> OK: display the sin result
  ./bug-cap-origin '$ORIGIN/../../usr/lib64/libm.so' sin
   -> OK: display the sin result
  sudo ./bug-cap-origin '$ORIGIN/../../usr/lib64/libm.so' sin
   -> OK: display the sin result

  Step 2 : Assign a capability to the file and check again ... to get
  the problem

  sudo setcap cap_net_bind_service=+epi bug-cap-origin
   --> empty result (=capability was set)
  ./bug-cap-origin '/usr/lib64/libm.so' sin
   -> OK: display the sin result
  ./bug-cap-origin '$ORIGIN/../../usr/lib64/libm.so' sin
   -> KO !!! : Message displayed = "$ORIGIN/../../usr/lib64/libm.so: cannot open shared object file: No such file or directory"
  sudo ./bug-cap-origin '$ORIGIN/../../usr/lib64/libm.so' sin
   -> OK: display the sin result

  Step 3 : Removing the capability solve the problem

  sudo setcap -r bug-cap-origin
   -> empty result (= capability was removed)
  ./bug-cap-origin '/usr/lib64/libm.so' sin
   -> OK: display the sin result
  ./bug-cap-origin '$ORIGIN/../../usr/lib64/libm.so' sin
   -> OK: display the sin result
  sudo ./bug-cap-origin '$ORIGIN/../../usr/lib64/libm.so' sin
   -> OK: display the sin result

  Am I wrong somewhere or is the ldopen having issues with relative path
  when Linux capabilities are set ?

  Test was done on :
   ld-2.11.1
   gcc 4.3.3
   Linux 2.6.32-20-generic
   Ubuntu 10.04 (latest dev)

To manage notifications about this bug go to:
https://bugs.launchpad.net/ubuntu/+source/glibc/+bug/565002/+subscriptions



More information about the foundations-bugs mailing list