Re: [PATCH/RFC] Patch to fix uid/gid lookup for NFSv4 filesystems
Lionel Cons <[email protected]>
| Newsgroups | gmane.os.cygwin.patches |
|---|---|
| Message-ID | <CAPJSo4WPqHqcxFS6AL8Cauo4Na6=u14Tw8eennKk_27rnd-rtQ@mail.gmail.com> |
On Sun, 16 Aug 2026 at 19:35, Lionel Cons <[email protected]> wrote: > > Repost with proper [PATCH/RFC] tag. > > I've attached a patch > (cygwin_dll_fix_uidgid4nfsv4_fs_20260709.diff.txt from the > ms-nfs41-client project) that resolves an issue with uid/gid lookups > on Windows NFSv4 filesystems. > > Currently, Cygwin assumes that all Windows NFS clients operate > similarly to the Windows NFSv3 client. It expects that account names > and numeric uid/gid values are identical on both the client and server > sides, with LDAP acting as the sole authority for these numeric > values. > > However, the NFSv4 protocol fundamentally changes this paradigm. As > defined in RFC 7530 (Section 5.9) and expanded upon in RFC 8178 (Rules > for NFSv4 Domain and ID Mapping), NFSv4 deprecates raw numeric uid/gid > protocol representation in favor of string-based identifiers (e.g., > user@domain and group@domain). > > To handle this, all NFSv4 clients implement a local "idmapper" > component that translates these string-based identities from the > network side into local account data (in the case of Windows, mapping > user/group names and uid/gid values via nfs3attr XATTR). Because NFSv4 > clients manage their own uid/gid translation locally, Cygwin's > reliance on raw LDAP data fails in these environments and results in > the dreaded "Unix_User+<1234>" and "Unix_Group+<5678>"-kind of > owner/group output in Cygwin ls -l. > > The attached patch addresses this by detecting whether the underlying > filesystem is NFSv4. If it is, Cygwin bypasses the LDAP assumption and > performs a direct pass-through of the uid/gid values supplied by the > NFSv4 client's idmapper. > > I have successfully tested this fix against several major clients, including: > - Exceed NFSv4 client > - OpenText NFSv4 client > - ms-nfs41-client > - ms-nfs42-client > - Windows NFSv3 client (no change, it continues to use LDAP raw data) > > Please let me know if you have any questions or require modifications > to the patch. ? Lionel
cygwin_dll_fix_uidgid4nfsv4_fs_20260709.diff.txt
(text/plain, 3.3 KB)
# Prototype fix for Cygwin DLL to handle uids/gids correctly on
# NFSv4 filesystems, which usually use an idmapper to map
# Win32 user&group names to NFS server account names.
# Without LDAP the NFSv4 idmappers usually use Cygwin or UWIN to obtain the
# uid/gid for files, which breaks the assumptions in
# |fhandler_base::fstat_by_nfs_ea()| and causes it to map all uid/gid values
# into the Unix_User+<uid>/Unix_Group+<gid> SID range
diff --git a/winsup/cygwin/fhandler/disk_file.cc b/winsup/cygwin/fhandler/disk_file.cc
index d54d3747e..a280ea9c6 100644
--- a/winsup/cygwin/fhandler/disk_file.cc
+++ b/winsup/cygwin/fhandler/disk_file.cc
@@ -214,7 +214,7 @@ fhandler_base::fstat_by_nfs_ea (struct stat *buf)
access through another handle invalidates the caching within the
NFS client. Skip this for Cygwin-created Symlinks playing FIFOs
(this sets the filler1 member to NF3FIFO). */
- if (get_handle () && nfs_attr->filler1 != NF3FIFO)
+ if (get_handle () && pc.fs_is_nfs3() && (nfs_attr->filler1 != NF3FIFO))
{
if (get_access () & GENERIC_WRITE)
FlushFileBuffers (get_handle ());
@@ -236,11 +236,15 @@ fhandler_base::fstat_by_nfs_ea (struct stat *buf)
{
uid_t map_uid = ILLEGAL_UID;
- domain = cygheap->dom.get_rfc2307_domain ();
- if ((ldap_open = (cldap.open (domain) == NO_ERROR)))
- map_uid = cldap.remap_uid (nfs_attr->uid);
- if (map_uid == ILLEGAL_UID)
- map_uid = MAP_UNIX_TO_CYGWIN_ID (nfs_attr->uid);
+ if (pc.fs_is_nfs4())
+ map_uid = nfs_attr->uid;
+ else {
+ domain = cygheap->dom.get_rfc2307_domain ();
+ if ((ldap_open = (cldap.open (domain) == NO_ERROR)))
+ map_uid = cldap.remap_uid (nfs_attr->uid);
+ if (map_uid == ILLEGAL_UID)
+ map_uid = MAP_UNIX_TO_CYGWIN_ID (nfs_attr->uid);
+ }
cygheap->ugid_cache.add_uid (nfs_attr->uid, map_uid);
buf->st_uid = map_uid;
}
@@ -255,11 +259,15 @@ fhandler_base::fstat_by_nfs_ea (struct stat *buf)
{
gid_t map_gid = ILLEGAL_GID;
- domain = cygheap->dom.get_rfc2307_domain ();
- if ((ldap_open || cldap.open (domain) == NO_ERROR))
- map_gid = cldap.remap_gid (nfs_attr->gid);
- if (map_gid == ILLEGAL_GID)
- map_gid = MAP_UNIX_TO_CYGWIN_ID (nfs_attr->gid);
+ if (pc.fs_is_nfs4())
+ map_gid = nfs_attr->gid;
+ else {
+ domain = cygheap->dom.get_rfc2307_domain ();
+ if ((ldap_open || cldap.open (domain) == NO_ERROR))
+ map_gid = cldap.remap_gid (nfs_attr->gid);
+ if (map_gid == ILLEGAL_GID)
+ map_gid = MAP_UNIX_TO_CYGWIN_ID (nfs_attr->gid);
+ }
cygheap->ugid_cache.add_gid (nfs_attr->gid, map_gid);
buf->st_gid = map_gid;
}
diff --git a/winsup/cygwin/local_includes/path.h b/winsup/cygwin/local_includes/path.h
index ad142ddd3..b8550c05c 100644
--- a/winsup/cygwin/local_includes/path.h
+++ b/winsup/cygwin/local_includes/path.h
@@ -423,6 +423,8 @@ class path_conv
bool fs_is_refs () const {return fs.is_refs ();}
bool fs_is_samba () const {return fs.is_samba ();}
bool fs_is_nfs () const {return fs.is_nfs ();}
+ bool fs_is_nfs3 () const {return fs.is_nfs () && !fs.has_acls ();}
+ bool fs_is_nfs4 () const {return fs.is_nfs () && fs.has_acls ();}
bool fs_is_netapp () const {return fs.is_netapp ();}
bool fs_is_cdrom () const {return fs.is_cdrom ();}
bool fs_is_mvfs () const {return fs.is_mvfs ();}