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.

Reply via email to