[PATCH] nfsuserd: Preserve requested names in name-to-ID cache entries

Emanuel HelmsEmanuel Helms <[email protected]> Fri, 10 Jul 2026 20:16:07 +0200
Newsgroups gmane.os.freebsd.devel.file-systems
Message-ID <[email protected]>
This is a multi-part message in MIME format.
--------------gheQTAFiUdZofpHpGMZhALP1
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 8bit

Hello Rick,

I found an NFSv4 name-to-ID caching issue in nfsuserd on FreeBSD 15.1 and
would appreciate your review of the attached patch.

The setup in which I reproduced the issue consists of:

- a FreeBSD 15.1 NFSv4 client;
- Winbind as the passwd/group NSS backend;
- an Active Directory domain provided by Samba on Rocky Linux 9;
- RFC2307 uidNumber and gidNumber attributes in AD;
- a Synology DSM 7.4 NFS server; and
- a Kerberos-protected NFSv4.1 mount using sec=krb5i.

An equivalent fstab entry is:

nfs.example.org:/volume2/share  /mnt/share  nfs 
rw,nfsv4,minorversion=1,sec=krb5i  0  0

The corresponding manual mount command is:

mount -t nfs -o nfsv4,minorversion=1,sec=krb5i \
     nfs.example.org:/volume2/share /mnt/share

The DSM server returns owner and owner_group attributes in a
domain-qualified form, for example:

EXAMPLE\[email protected]
EXAMPLE\Domain [email protected]

The configured NFSv4 domain is example.org. FreeBSD correctly removes the
matching @example.org suffix before making the nfsuserd upcall. The 
resulting
lookup names are therefore "EXAMPLE\alice" and "EXAMPLE\Domain Users".

Winbind successfully resolves these names to the RFC2307 IDs. However, with
"winbind use default domain = yes", getpwnam("EXAMPLE\alice") returns a
passwd structure whose pw_name is the canonical short name "alice". The same
canonicalization occurs for group lookups.

RPCNFSUSERD_GETUSER currently inserts the successful mapping into the kernel
cache using pwd->pw_name. The cache entry is therefore created for "alice",
while nfsv4_strtouid() retries its lookup for the originally requested name
"EXAMPLE\alice". That cache lookup misses and the owner is ultimately mapped
to the default UID. RPCNFSUSERD_GETGROUP has the same behavior with
grp->gr_name.

This produces the following symptoms:

- getent passwd 'EXAMPLE\alice' returns the correct RFC2307 UID;
- getent group 'EXAMPLE\Domain Users' returns the correct RFC2307 GID;
- Kerberos authentication and access to the export work;
- nfsuserd -verbose logs that it found and added the correct numeric ID, but
   logs the canonical short name; and
- stat(2) and ls(1) report 65534/65533 and nobody:nogroup for the NFS 
object.

The attached patch changes only the two successful name-to-ID paths. The UID
or GID still comes from the NSS result, but nid_name remains the exact name
that caused the upcall. This lets the retry in nfsv4_strtouid() or
nfsv4_strtogid() find the newly inserted entry.

The ID-to-name paths, failed lookup behavior, timeout handling, group-list
handling, Kerberos processing, and domain validation are unchanged. In the
usual case where the requested and canonical NSS names are identical, the
resulting cache key is also identical to the current one.

After applying the patch and rebuilding nfsuserd, newly fetched attributes
map to the expected RFC2307 UID and GID on the first lookup and on 
subsequent
cached lookups. Short Winbind login names continue to work. I also verified
that the source builds with the FreeBSD 15.1 build flags and warnings 
enabled.

There is a possible broader benefit beyond Winbind: any NSS backend that
successfully resolves an alias but returns a different canonical pw_name or
gr_name can trigger the same mismatch. Caching the result under the name 
that
was actually requested appears to match the semantics of NFSID_ADDUSERNAME
and NFSID_ADDGROUPNAME.

Please let me know if you would prefer the change in a different form or 
want
additional diagnostics or testing.

Best regards,

Emanuel Helms

--------------gheQTAFiUdZofpHpGMZhALP1
Content-Type: text/plain; charset=UTF-8;
 name="0001-nfsuserd-preserve-requested-name-cache-keys.patch"
Content-Disposition: attachment;
 filename="0001-nfsuserd-preserve-requested-name-cache-keys.patch"
Content-Transfer-Encoding: base64

RnJvbSAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwIE1vbiBTZXAg
MTcgMDA6MDA6MDAgMjAwMQpGcm9tOiBFbWFudWVsIEhlbG1zIDxlbWFudWVsQG5ydi5jYz4K
RGF0ZTogRnJpLCAxMCBKdWwgMjAyNiAxOTo0NTowMCArMDIwMApTdWJqZWN0OiBbUEFUQ0hd
IG5mc3VzZXJkOiBQcmVzZXJ2ZSByZXF1ZXN0ZWQgbmFtZXMgaW4gbmFtZS10by1JRCBjYWNo
ZSBlbnRyaWVzCgpBbiBOU1MgYmFja2VuZCBjYW4gcmVzb2x2ZSBhIHJlcXVlc3RlZCB1c2Vy
IG9yIGdyb3VwIGFsaWFzIHdoaWxlIHJldHVybmluZyBhCmRpZmZlcmVudCBjYW5vbmljYWwg
cHdfbmFtZSBvciBncl9uYW1lLiAgV2luYmluZCBkb2VzIHRoaXMgZm9yIGRvbWFpbi1xdWFs
aWZpZWQKbmFtZXMgd2hlbiAid2luYmluZCB1c2UgZGVmYXVsdCBkb21haW4iIGlzIGVuYWJs
ZWQuCgpUaGUgTkZTIGtlcm5lbCByZXRyaWVzIHRoZSBsb29rdXAgdXNpbmcgdGhlIG5hbWUg
c2VudCBpbiB0aGUgdXBjYWxsLiAgQ2FjaGluZwp0aGUgcmVzdWx0IHVuZGVyIHRoZSBjYW5v
bmljYWwgTlNTIG5hbWUgdGhlcmVmb3JlIGxlYXZlcyB0aGUgcmVxdWVzdGVkIG5hbWUKdW5t
YXBwZWQsIGNhdXNpbmcgaXQgdG8gZmFsbCBiYWNrIHRvIG5vYm9keSBvciBub2dyb3VwLgoK
Rm9yIHN1Y2Nlc3NmdWwgbmFtZS10by1JRCBsb29rdXBzLCByZXRhaW4gdGhlIGV4YWN0IHJl
cXVlc3RlZCBuYW1lIGFzIHRoZQpjYWNoZSBrZXkuICBDb250aW51ZSB0byBvYnRhaW4gdGhl
IG51bWVyaWMgVUlEIG9yIEdJRCBmcm9tIE5TUy4gIFRoZSByZXZlcnNlCklELXRvLW5hbWUg
cGF0aHMgYW5kIGZhaWxlZCBsb29rdXAgYmVoYXZpb3IgcmVtYWluIHVuY2hhbmdlZC4KLS0t
CiB1c3Iuc2Jpbi9uZnN1c2VyZC9uZnN1c2VyZC5jIHwgNiArKysrLS0KIDEgZmlsZSBjaGFu
Z2VkLCA0IGluc2VydGlvbnMoKyksIDIgZGVsZXRpb25zKC0pCgpkaWZmIC0tZ2l0IGEvdXNy
LnNiaW4vbmZzdXNlcmQvbmZzdXNlcmQuYyBiL3Vzci5zYmluL25mc3VzZXJkL25mc3VzZXJk
LmMKaW5kZXggOTMyNmRkOWE2ZDRmLi40N2M0YmE0OWIwZTEgMTAwNjQ0Ci0tLSBhL3Vzci5z
YmluL25mc3VzZXJkL25mc3VzZXJkLmMKKysrIGIvdXNyLnNiaW4vbmZzdXNlcmQvbmZzdXNl
cmQuYwpAQCAtNzA0LDcgKzcwNCw4IEBAIG5mc3VzZXJkc3J2KHN0cnVjdCBzdmNfcmVxICpy
cXN0cCwgU1ZDWFBSVCAqdHJhbnNwKQogCQlpZiAocHdkICE9IE5VTEwpIHsKIAkJCW5pZC5u
aWRfdXNlcnRpbWVvdXQgPSBkZWZ1c2VydGltZW91dDsKIAkJCW5pZC5uaWRfdWlkID0gcHdk
LT5wd191aWQ7Ci0JCQluaWQubmlkX25hbWUgPSBwd2QtPnB3X25hbWU7CisJCQkvKiBOU1Mg
bWF5IGNhbm9uaWNhbGl6ZSB0aGUgbmFtZSB1c2VkIGZvciB0aGUgbG9va3VwLiAqLworCQkJ
bmlkLm5pZF9uYW1lID0gaW5mby5uYW1lOwogCQl9IGVsc2UgewogCQkJbmlkLm5pZF91c2Vy
dGltZW91dCA9IDU7CiAJCQluaWQubmlkX3VpZCA9IGRlZmF1bHR1aWQ7CkBAIC03MzcsNyAr
NzM4LDggQEAgbmZzdXNlcmRzcnYoc3RydWN0IHN2Y19yZXEgKnJxc3RwLCBTVkNYUFJUICp0
cmFuc3ApCiAJCWlmIChncnAgIT0gTlVMTCkgewogCQkJbmlkLm5pZF91c2VydGltZW91dCA9
IGRlZnVzZXJ0aW1lb3V0OwogCQkJbmlkLm5pZF9naWQgPSBncnAtPmdyX2dpZDsKLQkJCW5p
ZC5uaWRfbmFtZSA9IGdycC0+Z3JfbmFtZTsKKwkJCS8qIE5TUyBtYXkgY2Fub25pY2FsaXpl
IHRoZSBuYW1lIHVzZWQgZm9yIHRoZSBsb29rdXAuICovCisJCQluaWQubmlkX25hbWUgPSBp
bmZvLm5hbWU7CiAJCX0gZWxzZSB7CiAJCQluaWQubmlkX3VzZXJ0aW1lb3V0ID0gNTsKIAkJ
CW5pZC5uaWRfZ2lkID0gZGVmYXVsdGdpZDsKLS0gCjIuNTMuMAo=

--------------gheQTAFiUdZofpHpGMZhALP1--