Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Probable buffer overflow in systemd-249 when reaching _nss_systemd_getpwuid_r() #20931

Closed
ju1m opened this issue Oct 4, 2021 · 4 comments
Closed

Comments

@ju1m
Copy link

ju1m commented Oct 4, 2021

Please see Chet Ramey's analysis of the problem on the bug-bash@ mailing-list:

I suspect this is a buffer overflow introduced between systemd-247 and
systemd-249. It's not caught when building bash without the bash malloc
because the default libc malloc probably doesn't do the bounds checking
the bash malloc does, even without malloc debugging turned on.
[...]
The important thing looks to be that bash is linked against systemd-249's
version of the nss library, and goes through systemd for the password
library functions. Non-systemd versions of the getpw functions don't
seem to exhibit this problem. systemd-247 doesn't exhibit this problem.

systemd version the issue has been seen with

$ systemctl --version
systemd 249 (249.4)
+PAM +AUDIT -SELINUX +APPARMOR +IMA +SMACK +SECCOMP +GCRYPT -GNUTLS +OPENSSL 
+ACL +BLKID +CURL -ELFUTILS +FIDO2 +IDN2 -IDN +IPTC +KMOD +LIBCRYPTSETUP 
+LIBFDISK +PCRE2 -PWQUALITY -P11KIT -QRENCODE +BZIP2 +LZ4 +XZ +ZLIB -ZSTD 
-XKBCOMMON +UTMP -SYSVINIT default-hierarchy=unified

Used distribution

NixOS https://github.com/NixOS/nixpkgs/blob/62ca4a425ab112e5d8a75682ee76c069cdb42d4b

Linux kernel version used (uname -a)

Linux losurdo 5.10.69-hardened1 #1-NixOS SMP Sun Sep 26 12:09:02 UTC 2021 x86_64 GNU/Linux

CPU architecture issue was seen on

x86_64

Expected behaviour you didn't see

# systemd-run --pipe -p DynamicUser=1 -E LD_LIBRARY_PATH=$(nix-store -q $(which systemctl))/lib \
  -pBindReadOnlyPaths={/etc,/nix,/run} -p RootDirectory=/run/bash -- \
  $(readlink -e bash5-with-bash-malloc/bin/bash) --norc -c $(readlink $(which id))
Running as unit: run-u2961.service
uid=63383(run-u2961) gid=63383(run-u2961) groups=63383(run-u2961)

Unexpected behaviour you saw

# systemd-run --pipe -p DynamicUser=1 -E LD_LIBRARY_PATH=$(nix-store -q $(which systemctl))/lib \
  -pBindReadOnlyPaths={/etc,/nix,/run} -p RootDirectory=/run/bash -- \
  $(readlink -e bash5-with-bash-malloc/bin/bash) --norc -c $(readlink $(which id))
Running as unit: run-u2961.service
malloc: unknown:0: assertion botched
realloc: start and end chunk sizes differ
Aborting...

Steps to reproduce the problem
Here's a flake.nix to build bash with debug symbols and --with-bash-malloc (enabled by default under NixOS):

{
inputs.nixpkgs.url = "github:NixOS/nixpkgs/62ca4a425ab112e5d8a75682ee76c069cdb42d4b";
outputs = inputs:
  let system = "x86_64-linux";
      pkgs = inputs.nixpkgs.legacyPackages.${system};
  in
  {
    packages.${system} = {
      bash5-with-bash-malloc = (pkgs.bash
        .override { stdenv = pkgs.keepDebugInfo pkgs.stdenv; })
        .overrideAttrs (old: {
          configureFlags = old.configureFlags ++ ["--with-bash-malloc"];
          CFLAGS = "-DDEBUG -DMALLOC_DEBUG -DDISABLE_MALLOC_WRAPPERS";
      });
      bash5-without-bash-malloc = (pkgs.bash
        .override { stdenv = pkgs.keepDebugInfo pkgs.stdenv; })
        .overrideAttrs (old: {
          configureFlags = old.configureFlags ++ ["--without-bash-malloc"];
          CFLAGS = "-DDEBUG -DMALLOC_DEBUG -DDISABLE_MALLOC_WRAPPERS";
      });
    };
  };
}
$ nix -L build .#bash5-with-bash-malloc -o bash5-with-bash-malloc

Additional program output to the terminal or log subsystem illustrating the issue

$ sudo coredumpctl debug
>            PID: 229855 (bash)
>            UID: 65483 (65483)
>            GID: 65483 (65483)
>         Signal: 6 (ABRT)
>      Timestamp: Mon 2021-10-04 04:09:08 CEST (3s ago)
>   Command Line: 
> /nix/store/acnfapqyd414vrzhhgclgqn37ll0rdr3-bash-5.1-p8/bin/bash --norc
>     Executable: 
> /nix/store/acnfapqyd414vrzhhgclgqn37ll0rdr3-bash-5.1-p8/bin/bash
>  Control Group: /system.slice/run-u534.service
>           Unit: run-u534.service
>          Slice: system.slice
>        Boot ID: 8f9583b087c14b5c813501bbccb1ef11
>     Machine ID: d434cb63c21e4dd193a3203059583bb3
>       Hostname: losurdo
>        Storage: 
> /var/lib/systemd/coredump/core.bash.65483.8f9583b087c14b5c813501bbccb1ef11.229855.1633313348000000.lz4
>  (present)
>      Disk Size: 69.2K
>        Message: Process 229855 (bash) of user 65483 dumped core.
> 
> GNU gdb (GDB) 10.2
> Copyright (C) 2021 Free Software Foundation, Inc.
> License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
> This is free software: you are free to change and redistribute it.
> There is NO WARRANTY, to the extent permitted by law.
> Type "show copying" and "show warranty" for details.
> This GDB was configured as "x86_64-unknown-linux-gnu".
> Type "show configuration" for configuration details.
> For bug reporting instructions, please see:
> <https://www.gnu.org/software/gdb/bugs/>.
> Find the GDB manual and other documentation resources online at:
>     <http://www.gnu.org/software/gdb/documentation/>.
> 
> For help, type "help".
> Type "apropos word" to search for commands related to "word"...
> Reading symbols from 
> /nix/store/acnfapqyd414vrzhhgclgqn37ll0rdr3-bash-5.1-p8/bin/bash...
> [New LWP 229855]
> [Thread debugging using libthread_db enabled]
> Using host libthread_db library 
> "/nix/store/2jfn3d7vyj7h0h6lmh510rz31db68l1i-glibc-2.33-50/lib/libthread_db.so.1".
> Core was generated by 
> `/nix/store/acnfapqyd414vrzhhgclgqn37ll0rdr3-bash-5.1-p8/bin/bash --norc'.
> Program terminated with signal SIGABRT, Aborted.
> #0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:49
> 49      ../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
> (gdb) bt
> #0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:49
> #1  0x0000619871e455d3 in __GI_abort () at abort.c:100
> #2  0x0000000000440d49 in programming_error (format=format@entry=0x4b9708 
> "realloc: start and end chunk sizes differ")
>     at error.c:175
> #3  0x000000000049e408 in xbotch (mem=mem@entry=0x37c8fa10, e=e@entry=8, 
>     s=0x4b9708 "realloc: start and end chunk sizes differ", 
> file=file@entry=0x0, line=line@entry=0) at malloc.c:376
> #4  0x000000000049f5c3 in internal_realloc (mem=0x37c8fa10, n=218, 
> file=file@entry=0x0, line=line@entry=0, 
>     flags=flags@entry=0) at malloc.c:1150
> #5  0x000000000049f867 in realloc (mem=<optimized out>, nbytes=<optimized 
> out>) at malloc.c:1440
> #6  0x0000619871c02526 in greedy_realloc ()
>    from 
> /nix/store/5iw38x4l9nyp2srnlxfi9l1q9np0pchq-systemd-249.4/lib/libnss_systemd.so.2
> #7  0x0000619871c04c44 in read_line_full ()
>    from 
> /nix/store/5iw38x4l9nyp2srnlxfi9l1q9np0pchq-systemd-249.4/lib/libnss_systemd.so.2
> #8  0x0000619871c04eb6 in read_one_line_file ()
>    from 
> /nix/store/5iw38x4l9nyp2srnlxfi9l1q9np0pchq-systemd-249.4/lib/libnss_systemd.so.2
> #9  0x0000619871bfd1b8 in proc_cmdline_parse ()
>    from 
> /nix/store/5iw38x4l9nyp2srnlxfi9l1q9np0pchq-systemd-249.4/lib/libnss_systemd.so.2
> #10 0x0000619871bfa939 in log_parse_environment ()
>    from 
> /nix/store/5iw38x4l9nyp2srnlxfi9l1q9np0pchq-systemd-249.4/lib/libnss_systemd.so.2
> #11 0x0000619871b965a7 in __pthread_once_slow (once_control=0x619871c490a4 
> <once>, 
>     init_routine=0x619871bf3b20 <setup_logging>) at pthread_once.c:116
> #12 0x0000619871bf40ff in _nss_systemd_getpwuid_r ()
>    from 
> /nix/store/5iw38x4l9nyp2srnlxfi9l1q9np0pchq-systemd-249.4/lib/libnss_systemd.so.2
> #13 0x0000619871ee7b46 in __getpwuid_r (uid=uid@entry=65483, 
> resbuf=resbuf@entry=0x619871fdbf40 <resbuf>, 
>     buffer=<optimized out>, buflen=buflen@entry=1024, 
> result=result@entry=0x7b3c23e18658) at ../nss/getXXbyYY_r.c:274
> #14 0x0000619871ee7378 in getpwuid (uid=65483) at ../nss/getXXbyYY.c:135
> #15 0x000000000041c9d2 in get_current_user_info () at shell.c:1869
> #16 0x000000000041cc8a in shell_initialize () at shell.c:1932
> #17 0x000000000041d1e8 in main (argc=2, argv=0x7b3c23e18918, 
> env=0x7b3c23e18930) at shell.c:572
@martinetd
Copy link
Contributor

martinetd commented Oct 5, 2021

Before someone spends time on this, it's likely because systemd's libnss_systemd started using reallocarray() in v247, but that is not handled by bash's malloc wrapper. (not sure why v247 doesn't crash but could be some behaviour change that makes it using reallocarray when it wasn't)

Not much else to do here than extend the wrapper (or stop using reallocarray and go back to realloc?), I've replied to the bug bash mailing list thread with relevant infos. https://lists.gnu.org/archive/html/bug-bash/2021-10/msg00044.html

@martinetd
Copy link
Contributor

meh, actually tried implementing reallocarray and that wasn't it. Sorry for the noise, will dig a bit more later™

@martinetd
Copy link
Contributor

Ok, this time I got it -- this comes from 319a4f4 which makes nss-systemd use malloc_usable_size more, and bash implementation is not correct (it returns a size bigger than the size requested on alloc, but then fails on free as a buffer overflow check)

Pretty sure this is correct this time...

@ju1m
Copy link
Author

ju1m commented Oct 5, 2021

Closing since Bash's maintainer acknowledged it's Bash which needs fixing.
Thank you very much @martinetd for tracking this down!

@ju1m ju1m closed this as completed Oct 5, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

3 participants