From patchwork Fri Sep 27 07:50:50 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lennart Poettering X-Patchwork-Id: 1990175 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=sourceware.org (client-ip=8.43.85.97; helo=server2.sourceware.org; envelope-from=libc-alpha-bounces~incoming=patchwork.ozlabs.org@sourceware.org; receiver=patchwork.ozlabs.org) Received: from server2.sourceware.org (server2.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4XFN2B1l1hz1xt9 for ; Fri, 27 Sep 2024 17:51:13 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id F086C3858CDA for ; Fri, 27 Sep 2024 07:51:11 +0000 (GMT) X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from gardel.0pointer.net (gardel.0pointer.net [85.214.157.71]) by sourceware.org (Postfix) with ESMTPS id 97AE13858D39 for ; Fri, 27 Sep 2024 07:50:53 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 97AE13858D39 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=poettering.net Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=poettering.net ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 97AE13858D39 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=85.214.157.71 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1727423456; cv=none; b=Zs6F+nL1zsjE2KEeIvzdKUyREFbGJTmVANoLFVmda/vGiqynWT/hTCE4D86Yi8Gpplm56Ax4e/NG/cptzavctpuaUI1i+9Ii4azTTrFOZ+qj5jqubx7l+PdaMfZs1Y1JlKZZWOqUsfpLH+xTQJ9wWT4UgDRK8AA4g6gMoEeTijk= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1727423456; c=relaxed/simple; bh=4ift1EJ6dxQE4/cqTm/BXmF4QVCnsOEvMtIiebLWLdQ=; h=Date:From:To:Subject:Message-ID:MIME-Version; b=IE9Lvfxek1HmORQVOb+MTiNW1Bgs8yuS2NDZy/uTInrDQCx85bj5UneFGIwDwYcZquVzMfOy0DutQB5blm1y7mgwJQqGjjkHqEKKZUwaCp8Jgw5aMH2kouEhVCvHGnR2LGOsT/G052qP736XnekxBhAPBlg3w+yNqE4W5u2+V9U= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from gardel-login.0pointer.net (gardel-mail [85.214.157.71]) by gardel.0pointer.net (Postfix) with ESMTP id 12CC4E80A35; Fri, 27 Sep 2024 09:50:52 +0200 (CEST) Received: by gardel-login.0pointer.net (Postfix, from userid 1000) id 00A631602E7; Fri, 27 Sep 2024 09:50:50 +0200 (CEST) Date: Fri, 27 Sep 2024 09:50:50 +0200 From: Lennart Poettering To: libc-alpha@sourceware.org Cc: Carlos O'Donell Subject: [PATCH] nss: look for databases in /usr/share/ if they don't exist in /etc/ Message-ID: MIME-Version: 1.0 Content-Disposition: inline X-Spam-Status: No, score=-12.8 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, SPF_HELO_PASS, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libc-alpha-bounces~incoming=patchwork.ozlabs.org@sourceware.org In order to improve compatibility with systems that implement a hermetic /usr/, this changes glibc NSS code to always look for its databases files in /usr/share/ too in case they don't exist (ENOENT) in /etc/. This allows distributions to move /etc/protocols and similar data files into /usr/share/. These days various of these files are kinda static anyway, and hence in many cases are better placed below the /usr/ hierarchy than below the configurable /etc/. This change should have zero effect on existing systems, as any database file in /etc/ will be consulted first, and only on ENOENT the matching counterpart in /usr/share/ will be attempted. This also provides a clear path how administrators can still modify the files locally if they want to: just copy them from /usr/share/ to /etc/ and edit them there. In that case the files in /usr/share/ will have no effect anymore. Many systems that want to achieve this behaviour currently work around glibc's behaviour via modules such as nss-altfiles, an excercise that becomes unnecessary if glibc just directly looks at these fallback places. Also see: https://github.com/uapi-group/specifications/issues/76 --- include/nss_files.h | 6 +++--- nss/nss_compat/compat-grp.c | 2 +- nss/nss_compat/compat-initgroups.c | 2 +- nss/nss_compat/compat-pwd.c | 2 +- nss/nss_compat/compat-spwd.c | 2 +- nss/nss_files/files-XXX.c | 9 +++++---- nss/nss_files/files-alias.c | 9 +++++---- nss/nss_files/files-initgroups.c | 2 +- nss/nss_files/files-netgrp.c | 5 +++-- nss/nss_files_data.c | 11 ++++++----- nss/nss_files_fopen.c | 11 +++++++++-- 11 files changed, 36 insertions(+), 25 deletions(-) -- 2.46.0 diff --git a/include/nss_files.h b/include/nss_files.h index adf934f3ea..852c64da99 100644 --- a/include/nss_files.h +++ b/include/nss_files.h @@ -26,7 +26,7 @@ #endif /* Open PATH for reading, as a data source for nss_files. */ -FILE *__nss_files_fopen (const char *path); +FILE *__nss_files_fopen (const char *path, const char *fallback_path); libc_hidden_proto (__nss_files_fopen) /* Read a line from FP, storing it BUF. Strip leading blanks and skip @@ -89,7 +89,7 @@ enum nss_files_file null. */ enum nss_status __nss_files_data_open (struct nss_files_per_file_data **pdata, enum nss_files_file file, - const char *path, + const char *path, const char *fallback_path, int *errnop, int *herrnop); libc_hidden_proto (__nss_files_data_open) @@ -101,7 +101,7 @@ libc_hidden_proto (__nss_files_data_put) /* Performs the set*ent operation for FILE. PATH is the file to open. */ enum nss_status __nss_files_data_setent (enum nss_files_file file, - const char *path); + const char *path, const char *fallback_path); libc_hidden_proto (__nss_files_data_setent) /* Performs the end*ent operation for FILE. */ diff --git a/nss/nss_compat/compat-grp.c b/nss/nss_compat/compat-grp.c index ede7503de7..bacad5b583 100644 --- a/nss/nss_compat/compat-grp.c +++ b/nss/nss_compat/compat-grp.c @@ -108,7 +108,7 @@ internal_setgrent (ent_t *ent, int stayopen, int needent) if (ent->stream == NULL) { - ent->stream = __nss_files_fopen ("/etc/group"); + ent->stream = __nss_files_fopen ("/etc/group", "/usr/share/group"); if (ent->stream == NULL) status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL; diff --git a/nss/nss_compat/compat-initgroups.c b/nss/nss_compat/compat-initgroups.c index 2598cfbc9a..37eb4b17af 100644 --- a/nss/nss_compat/compat-initgroups.c +++ b/nss/nss_compat/compat-initgroups.c @@ -122,7 +122,7 @@ internal_setgrent (ent_t *ent) else ent->blacklist.current = 0; - ent->stream = __nss_files_fopen ("/etc/group"); + ent->stream = __nss_files_fopen ("/etc/group", "/usr/share/group"); if (ent->stream == NULL) status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL; diff --git a/nss/nss_compat/compat-pwd.c b/nss/nss_compat/compat-pwd.c index 2f37e0f621..2a3b012c33 100644 --- a/nss/nss_compat/compat-pwd.c +++ b/nss/nss_compat/compat-pwd.c @@ -223,7 +223,7 @@ internal_setpwent (ent_t *ent, int stayopen, int needent) if (ent->stream == NULL) { - ent->stream = __nss_files_fopen ("/etc/passwd"); + ent->stream = __nss_files_fopen ("/etc/passwd", "/usr/share/passwd"); if (ent->stream == NULL) status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL; diff --git a/nss/nss_compat/compat-spwd.c b/nss/nss_compat/compat-spwd.c index fac1e766cb..fc6984bcb4 100644 --- a/nss/nss_compat/compat-spwd.c +++ b/nss/nss_compat/compat-spwd.c @@ -178,7 +178,7 @@ internal_setspent (ent_t *ent, int stayopen, int needent) if (ent->stream == NULL) { - ent->stream = __nss_files_fopen ("/etc/shadow"); + ent->stream = __nss_files_fopen ("/etc/shadow", "/usr/share/shadow"); if (ent->stream == NULL) status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL; diff --git a/nss/nss_files/files-XXX.c b/nss/nss_files/files-XXX.c index 558b2c364f..fa47dec277 100644 --- a/nss/nss_files/files-XXX.c +++ b/nss/nss_files/files-XXX.c @@ -39,7 +39,8 @@ #define ENTNAME_r CONCAT(ENTNAME,_r) -#define DATAFILE "/etc/" DATABASE +#define DATAFILE "/etc/" DATABASE +#define DATAFILE_FALLBACK "/usr/share/" DATABASE #ifdef NEED_H_ERRNO # include @@ -73,7 +74,7 @@ internal_setent (FILE **stream) if (*stream == NULL) { - *stream = __nss_files_fopen (DATAFILE); + *stream = __nss_files_fopen (DATAFILE, DATAFILE_FALLBACK); if (*stream == NULL) status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL; @@ -89,7 +90,7 @@ internal_setent (FILE **stream) enum nss_status CONCAT(_nss_files_set,ENTNAME) (int stayopen) { - return __nss_files_data_setent (CONCAT (nss_file_, ENTNAME), DATAFILE); + return __nss_files_data_setent (CONCAT (nss_file_, ENTNAME), DATAFILE, DATAFILE_FALLBACK); } libc_hidden_def (CONCAT (_nss_files_set,ENTNAME)) @@ -170,7 +171,7 @@ CONCAT(_nss_files_get,ENTNAME_r) (struct STRUCTURE *result, char *buffer, struct nss_files_per_file_data *data; enum nss_status status = __nss_files_data_open (&data, CONCAT (nss_file_, ENTNAME), - DATAFILE, + DATAFILE, DATAFILE_FALLBACK, errnop, H_ERRNO_ARG_OR_NULL); if (status != NSS_STATUS_SUCCESS) return status; diff --git a/nss/nss_files/files-alias.c b/nss/nss_files/files-alias.c index 14a59b4655..d0b1ce2a8e 100644 --- a/nss/nss_files/files-alias.c +++ b/nss/nss_files/files-alias.c @@ -42,7 +42,7 @@ internal_setent (FILE **stream) if (*stream == NULL) { - *stream = __nss_files_fopen ("/etc/aliases"); + *stream = __nss_files_fopen ("/etc/aliases", "/usr/share/aliases"); if (*stream == NULL) status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL; @@ -58,7 +58,7 @@ internal_setent (FILE **stream) enum nss_status _nss_files_setaliasent (void) { - return __nss_files_data_setent (nss_file_aliasent, "/etc/aliases"); + return __nss_files_data_setent (nss_file_aliasent, "/etc/aliases", "/usr/share/aliases"); } libc_hidden_def (_nss_files_setaliasent) @@ -182,7 +182,7 @@ get_next_alias (FILE *stream, const char *match, struct aliasent *result, first_unused = cp; - listfile = __nss_files_fopen (&cp[9]); + listfile = __nss_files_fopen (&cp[9], NULL); /* If the file does not exist we simply ignore the statement. */ if (listfile != NULL @@ -338,7 +338,8 @@ _nss_files_getaliasent_r (struct aliasent *result, char *buffer, size_t buflen, struct nss_files_per_file_data *data; enum nss_status status = __nss_files_data_open (&data, nss_file_aliasent, - "/etc/aliases", errnop, NULL); + "/etc/aliases", "/usr/share/aliases", + errnop, NULL); if (status != NSS_STATUS_SUCCESS) return status; diff --git a/nss/nss_files/files-initgroups.c b/nss/nss_files/files-initgroups.c index 65189d3929..896fa50c5a 100644 --- a/nss/nss_files/files-initgroups.c +++ b/nss/nss_files/files-initgroups.c @@ -33,7 +33,7 @@ _nss_files_initgroups_dyn (const char *user, gid_t group, long int *start, long int *size, gid_t **groupsp, long int limit, int *errnop) { - FILE *stream = __nss_files_fopen ("/etc/group"); + FILE *stream = __nss_files_fopen ("/etc/group", "/usr/share/group"); if (stream == NULL) { *errnop = errno; diff --git a/nss/nss_files/files-netgrp.c b/nss/nss_files/files-netgrp.c index 92d8062e43..7f71eebf60 100644 --- a/nss/nss_files/files-netgrp.c +++ b/nss/nss_files/files-netgrp.c @@ -27,7 +27,8 @@ #include "netgroup.h" #include -#define DATAFILE "/etc/netgroup" +#define DATAFILE "/etc/netgroup" +#define DATAFILE_FALLBACK "/usr/share/netgroup" libc_hidden_proto (_nss_files_endnetgrent) @@ -62,7 +63,7 @@ _nss_files_setnetgrent (const char *group, struct __netgrent *result) return NSS_STATUS_UNAVAIL; /* Find the netgroups file and open it. */ - fp = __nss_files_fopen (DATAFILE); + fp = __nss_files_fopen (DATAFILE, DATAFILE_FALLBACK); if (fp == NULL) status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL; else diff --git a/nss/nss_files_data.c b/nss/nss_files_data.c index 261a01a775..c6af527e6d 100644 --- a/nss/nss_files_data.c +++ b/nss/nss_files_data.c @@ -74,13 +74,13 @@ __nss_files_data_get (struct nss_files_per_file_data **pdata, /* Helper function for opening the backing file at PATH. */ static enum nss_status __nss_files_data_internal_open (struct nss_files_per_file_data *data, - const char *path) + const char *path, const char *fallback_path) { enum nss_status status = NSS_STATUS_SUCCESS; if (data->stream == NULL) { - data->stream = __nss_files_fopen (path); + data->stream = __nss_files_fopen (path, fallback_path); if (data->stream == NULL) status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL; @@ -93,6 +93,7 @@ __nss_files_data_internal_open (struct nss_files_per_file_data *data, enum nss_status __nss_files_data_open (struct nss_files_per_file_data **pdata, enum nss_files_file file, const char *path, + const char *fallback_path, int *errnop, int *herrnop) { enum nss_status status = __nss_files_data_get (pdata, file, errnop, herrnop); @@ -103,7 +104,7 @@ __nss_files_data_open (struct nss_files_per_file_data **pdata, if ((*pdata)->stream == NULL) { int saved_errno = errno; - status = __nss_files_data_internal_open (*pdata, path); + status = __nss_files_data_internal_open (*pdata, path, fallback_path); __set_errno (saved_errno); if (status != NSS_STATUS_SUCCESS) __nss_files_data_put (*pdata); @@ -122,7 +123,7 @@ __nss_files_data_put (struct nss_files_per_file_data *data) libc_hidden_def (__nss_files_data_put) enum nss_status -__nss_files_data_setent (enum nss_files_file file, const char *path) +__nss_files_data_setent (enum nss_files_file file, const char *path, const char *fallback_path) { struct nss_files_per_file_data *data; enum nss_status status = __nss_files_data_get (&data, file, NULL, NULL); @@ -130,7 +131,7 @@ __nss_files_data_setent (enum nss_files_file file, const char *path) return status; if (data->stream == NULL) - status = __nss_files_data_internal_open (data, path); + status = __nss_files_data_internal_open (data, path, fallback_path); else rewind (data->stream); diff --git a/nss/nss_files_fopen.c b/nss/nss_files_fopen.c index e7c48d7bd8..a2b7affdb4 100644 --- a/nss/nss_files_fopen.c +++ b/nss/nss_files_fopen.c @@ -22,11 +22,18 @@ #include FILE * -__nss_files_fopen (const char *path) +__nss_files_fopen (const char *path, const char *fallback_path) { FILE *fp = fopen (path, "rce"); if (fp == NULL) - return NULL; + { + if (errno != ENOENT || fallback_path == NULL) + return NULL; + + fp = fopen (fallback_path, "rce"); + if (fp == NULL) + return NULL; + } /* The stream is not shared across threads. */ __fsetlocking (fp, FSETLOCKING_BYCALLER);