Thanks for the detailed reproducer. It's weird, as the server is basically just setting the transmitted umask and then calling into the vfs to handle the rest, so it's not much different from any other user. But the same reproducer run just on the ext4 filesystem does give the right permissions....
Oh, but looking at the system call, fs_namei.c:do_mkdirat(), it does: if (!IS_POSIXACL(path.dentry->d_inode)) mode &= ~current_umask(); error = security_path_mkdir(&path, dentry, mode); if (!error) error = vfs_mkdir(path.dentry->d_inode, dentry, mode); whereas nfsd just calls into vfs_mkdir(). And that IS_POSIXACL() check is exactly a check whether the filesystem supports ACLs. So I guess it's the responsibility of the caller of vfs_mkdir() to handle that case. So the obvious fix is something like (untested!) diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 0aa02eb18bd3..dabdcca58969 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -1234,6 +1234,8 @@ nfsd_create_locked(struct svc_rqst *rqstp, struct svc_fh *fhp, nfsd_check_ignore_resizing(iap); break; case S_IFDIR: + if (!IS_POSIXACL(dirp)) + iap->ia_mode &= ~current_umask(); host_err = vfs_mkdir(dirp, dchild, iap->ia_mode); if (!host_err && unlikely(d_unhashed(dchild))) { struct dentry *d; --b.