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

Wrap all functions accessing /etc/passwd, /etc/group and /etc/shadow for glibc >= 2.34 #98

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

josch
Copy link

@josch josch commented Sep 9, 2021

closes: #97

Starting with glibc 2.32 the compat nss module for getpwnam calls
__nss_files_fopen (which is a GLIBC_PRIVATE symbol provided by glibc)
instead of fopen (see 299210c1fa67e2dfb564475986fce11cd33db9ad). This
leads to getpwnam calls accessing /etc/passwd from outside the chroot
and as a result programs like adduser do not work correctly anymore
under fakechroot.

Starting with glibc 2.34 the __nss_files_fopen was moved from nss to
libc.so and thus wrapping it with LD_PRELOAD has no affect anymore
(see 6212bb67f4695962748a5981e1b9fea105af74f6).

So now we also wrap all the functions accessing /etc/passwd, /etc/group
and /etc/shadow. This solution will ignore NIS, LDAP or other local files
as potentially configured in /etc/nsswitch.conf.

@josch
Copy link
Author

josch commented Aug 16, 2022

Starting with glibc 2.34, getpwnam and friends fail again. Probably the modules changed again in a subtle way which makes wrapping __nss_files_fopen not effective anymore. But so far I fail to figure out the root of the problem because a backtrace of gdb at the point when /etc/passwd is opened doesn't show a different call stack compared to glibc 2.33:

#0  __GI___open64_nocancel (file=0x7ffff7f73dc5 "/etc/passwd", oflag=524288)
    at ../sysdeps/unix/sysv/linux/open64_nocancel.c:45
#1  0x00007ffff7e3f265 in __GI__IO_file_open (fp=fp@entry=0x555555559790, 
    filename=filename@entry=0x7ffff7f73dc5 "/etc/passwd", posix_mode=<optimized out>, 
    prot=prot@entry=438, read_write=8, is32not64=<optimized out>) at ./libio/fileops.c:186
#2  0x00007ffff7e3f38b in _IO_new_file_fopen (fp=fp@entry=0x555555559790, 
    filename=filename@entry=0x7ffff7f73dc5 "/etc/passwd", mode=<optimized out>, 
    mode@entry=0x7ffff7f6fb14 "rce", is32not64=is32not64@entry=1) at ./libio/fileops.c:281
#3  0x00007ffff7e33a09 in __fopen_internal (filename=filename@entry=0x7ffff7f73dc5 "/etc/passwd", 
    mode=mode@entry=0x7ffff7f6fb14 "rce", is32=is32@entry=1) at ./libio/iofopen.c:75
#4  0x00007ffff7e33a8a in _IO_new_fopen (filename=filename@entry=0x7ffff7f73dc5 "/etc/passwd", 
    mode=mode@entry=0x7ffff7f6fb14 "rce") at ./libio/iofopen.c:86
#5  0x00007ffff7ef305e in __GI___nss_files_fopen (path=path@entry=0x7ffff7f73dc5 "/etc/passwd")
    at ./nss/nss_files_fopen.c:27
#6  0x00007ffff7ef8229 in internal_setent (stream=<synthetic pointer>) at nss_files/files-XXX.c:76
#7  __GI__nss_files_getpwnam_r (name=0x7fffffffe85b "user", result=0x7ffff7fb8a00 <resbuf>, 
    buffer=0x5555555592a0 "", buflen=1024, errnop=0x7ffff7dbc6c0) at nss_files/files-pwd.c:33
#8  0x00007ffff7e93bf8 in __getpwnam_r (name=name@entry=0x7fffffffe85b "user", 
    resbuf=resbuf@entry=0x7ffff7fb8a00 <resbuf>, buffer=<optimized out>, buflen=buflen@entry=1024, 
    result=result@entry=0x7fffffffe4b0) at ../nss/getXXbyYY_r.c:274
#9  0x00007ffff7e9368c in getpwnam (name=0x7fffffffe85b "user") at ../nss/getXXbyYY.c:135
#10 0x00005555555550f4 in main (argc=<optimized out>, argv=<optimized out>)
    at test-nss_files_fopen.c:16

Here is a small test program to illustrate the problem:

#include <stdlib.h>
#include <stdio.h>
#include <pwd.h>
#include <errno.h>
#include <stdint.h>
#include <unistd.h>

int main (int argc, char *argv[]) {
	struct passwd *pwd;

	if (argc != 2) {
		fprintf(stderr, "Usage: %s username\n", argv[0]);
		exit(EXIT_FAILURE);
	}

	pwd = getpwnam(argv[1]);
	if (pwd == NULL) {
		if (errno == 0) {
			printf("Not found\n");
		} else {
			perror("getpwnam");
		}
		exit(EXIT_FAILURE);
	}

	printf("%jd\n", (intmax_t)(pwd->pw_uid));
	exit(EXIT_SUCCESS);
}

Running this inside a fakechroot with FAKECHROOT_DEBUG=1 shows that fakechroot doesn't wrap anything this test program should open (like /etc/passwd). Instead, the uid that this test program will print, will come from the host system and not from inside the chroot.

@sergiomb2: are you seeing the same problems in Fedora?

EDIT:
This glibc commit broke this: https://sourceware.org/git/?p=glibc.git;a=commit;h=6212bb67f4695962748a5981e1b9fea105af74f6
Debian bug: https://bugs.debian.org/1017590

Starting with glibc 2.32 the compat nss module for getpwnam calls
__nss_files_fopen (which is a GLIBC_PRIVATE symbol provided by glibc)
instead of fopen (see 299210c1fa67e2dfb564475986fce11cd33db9ad). This
leads to getpwnam calls accessing /etc/passwd from *outside* the chroot
and as a result programs like adduser do not work correctly anymore
under fakechroot.

Starting with glibc 2.34 the __nss_files_fopen was moved from nss to
libc.so and thus wrapping it with LD_PRELOAD has no affect anymore
(see 6212bb67f4695962748a5981e1b9fea105af74f6).

So now we also wrap all the functions accessing /etc/passwd, /etc/group
and /etc/shadow. This solution will ignore NIS, LDAP or other local files
as potentially configured in /etc/nsswitch.conf.
@josch josch force-pushed the __nss_files_fopen branch from aab47c9 to 66d3212 Compare August 24, 2022 06:18
@josch josch changed the title wrap __nss_files_fopen to support getpwnam in glibc >= 2.32 Wrap all functions accessing /etc/passwd, /etc/group and /etc/shadow for glibc >= 2.34 Aug 24, 2022
@josch
Copy link
Author

josch commented Aug 24, 2022

Since __nss_files_fopen is part of libc6.so, wrapping it with LD_PRELOAD doesn't have an effect anymore. So instead we wrap all functions accessing /etc/passwd, /etc/group and /etc/shadow.

josch added a commit to josch/fakechroot that referenced this pull request Aug 24, 2022
Starting with glibc 2.32 the compat nss module for getpwnam calls
__nss_files_fopen (which is a GLIBC_PRIVATE symbol provided by glibc)
instead of fopen (see 299210c1fa67e2dfb564475986fce11cd33db9ad). This
leads to getpwnam calls accessing /etc/passwd from *outside* the chroot
and as a result programs like adduser do not work correctly anymore
under fakechroot.

Starting with glibc 2.34 the __nss_files_fopen was moved from nss to
libc.so and thus wrapping it with LD_PRELOAD has no affect anymore
(see 6212bb67f4695962748a5981e1b9fea105af74f6).

So now we also wrap all the functions accessing /etc/passwd, /etc/group
and /etc/shadow. This solution will ignore NIS, LDAP or other local files
as potentially configured in /etc/nsswitch.conf.

dex4er#98
@sergiomb2
Copy link

Hi, I don't know , I maintain fakechroot because could be used by pbuilder and debootstrap , but digging today I also don't know if it is required .

josch added a commit to josch/fakechroot that referenced this pull request Aug 24, 2022
Starting with glibc 2.32 the compat nss module for getpwnam calls
__nss_files_fopen (which is a GLIBC_PRIVATE symbol provided by glibc)
instead of fopen (see 299210c1fa67e2dfb564475986fce11cd33db9ad). This
leads to getpwnam calls accessing /etc/passwd from *outside* the chroot
and as a result programs like adduser do not work correctly anymore
under fakechroot.

Starting with glibc 2.34 the __nss_files_fopen was moved from nss to
libc.so and thus wrapping it with LD_PRELOAD has no affect anymore
(see 6212bb67f4695962748a5981e1b9fea105af74f6).

So now we also wrap all the functions accessing /etc/passwd, /etc/group
and /etc/shadow. This solution will ignore NIS, LDAP or other local files
as potentially configured in /etc/nsswitch.conf.

dex4er#98
josch added a commit to josch/fakechroot that referenced this pull request Aug 24, 2022
Starting with glibc 2.32 the compat nss module for getpwnam calls
__nss_files_fopen (which is a GLIBC_PRIVATE symbol provided by glibc)
instead of fopen (see 299210c1fa67e2dfb564475986fce11cd33db9ad). This
leads to getpwnam calls accessing /etc/passwd from *outside* the chroot
and as a result programs like adduser do not work correctly anymore
under fakechroot.

Starting with glibc 2.34 the __nss_files_fopen was moved from nss to
libc.so and thus wrapping it with LD_PRELOAD has no affect anymore
(see 6212bb67f4695962748a5981e1b9fea105af74f6).

So now we also wrap all the functions accessing /etc/passwd, /etc/group
and /etc/shadow. This solution will ignore NIS, LDAP or other local files
as potentially configured in /etc/nsswitch.conf.

dex4er#98
josch added a commit to josch/fakechroot that referenced this pull request Aug 25, 2022
Starting with glibc 2.32 the compat nss module for getpwnam calls
__nss_files_fopen (which is a GLIBC_PRIVATE symbol provided by glibc)
instead of fopen (see 299210c1fa67e2dfb564475986fce11cd33db9ad). This
leads to getpwnam calls accessing /etc/passwd from *outside* the chroot
and as a result programs like adduser do not work correctly anymore
under fakechroot.

Starting with glibc 2.34 the __nss_files_fopen was moved from nss to
libc.so and thus wrapping it with LD_PRELOAD has no affect anymore
(see 6212bb67f4695962748a5981e1b9fea105af74f6).

So now we also wrap all the functions accessing /etc/passwd, /etc/group
and /etc/shadow. This solution will ignore NIS, LDAP or other local files
as potentially configured in /etc/nsswitch.conf.

dex4er#98
josch added a commit to josch/fakechroot that referenced this pull request Oct 28, 2022
Starting with glibc 2.32 the compat nss module for getpwnam calls
__nss_files_fopen (which is a GLIBC_PRIVATE symbol provided by glibc)
instead of fopen (see 299210c1fa67e2dfb564475986fce11cd33db9ad). This
leads to getpwnam calls accessing /etc/passwd from *outside* the chroot
and as a result programs like adduser do not work correctly anymore
under fakechroot.

Starting with glibc 2.34 the __nss_files_fopen was moved from nss to
libc.so and thus wrapping it with LD_PRELOAD has no affect anymore
(see 6212bb67f4695962748a5981e1b9fea105af74f6).

So now we also wrap all the functions accessing /etc/passwd, /etc/group
and /etc/shadow. This solution will ignore NIS, LDAP or other local files
as potentially configured in /etc/nsswitch.conf.

dex4er#98
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

getpwnam (and others) fail with glibc >= 2.32
2 participants