Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

nfsd: initialize i_private before d_add

A process could race in an open and attempt to read one of these files
before i_private is initialized, and get a spurious error.

Reported-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>

+6 -6
+6 -6
fs/nfsd/nfsctl.c
··· 1171 1171 return inode; 1172 1172 } 1173 1173 1174 - static int __nfsd_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) 1174 + static int __nfsd_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode, struct nfsdfs_client *ncl) 1175 1175 { 1176 1176 struct inode *inode; 1177 1177 1178 1178 inode = nfsd_get_inode(dir->i_sb, mode); 1179 1179 if (!inode) 1180 1180 return -ENOMEM; 1181 + if (ncl) { 1182 + inode->i_private = ncl; 1183 + kref_get(&ncl->cl_ref); 1184 + } 1181 1185 d_add(dentry, inode); 1182 1186 inc_nlink(dir); 1183 1187 fsnotify_mkdir(dir, dentry); ··· 1198 1194 dentry = d_alloc_name(parent, name); 1199 1195 if (!dentry) 1200 1196 goto out_err; 1201 - ret = __nfsd_mkdir(d_inode(parent), dentry, S_IFDIR | 0600); 1197 + ret = __nfsd_mkdir(d_inode(parent), dentry, S_IFDIR | 0600, ncl); 1202 1198 if (ret) 1203 1199 goto out_err; 1204 - if (ncl) { 1205 - d_inode(dentry)->i_private = ncl; 1206 - kref_get(&ncl->cl_ref); 1207 - } 1208 1200 out: 1209 1201 inode_unlock(dir); 1210 1202 return dentry;