Skip to content

Commit 5111711

Browse files
committed
Merge branch 'for-2.6.37' of git://linux-nfs.org/~bfields/linux
* 'for-2.6.37' of git://linux-nfs.org/~bfields/linux: nfsd: Fix possible BUG_ON firing in set_change_info sunrpc: prevent use-after-free on clearing XPT_BUSY
2 parents e13cf63 + c1ac3ff commit 5111711

File tree

3 files changed

+22
-14
lines changed

3 files changed

+22
-14
lines changed

fs/nfsd/nfs3xdr.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -260,9 +260,11 @@ void fill_post_wcc(struct svc_fh *fhp)
260260
err = vfs_getattr(fhp->fh_export->ex_path.mnt, fhp->fh_dentry,
261261
&fhp->fh_post_attr);
262262
fhp->fh_post_change = fhp->fh_dentry->d_inode->i_version;
263-
if (err)
263+
if (err) {
264264
fhp->fh_post_saved = 0;
265-
else
265+
/* Grab the ctime anyway - set_change_info might use it */
266+
fhp->fh_post_attr.ctime = fhp->fh_dentry->d_inode->i_ctime;
267+
} else
266268
fhp->fh_post_saved = 1;
267269
}
268270

fs/nfsd/xdr4.h

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -484,18 +484,17 @@ static inline bool nfsd4_not_cached(struct nfsd4_compoundres *resp)
484484
static inline void
485485
set_change_info(struct nfsd4_change_info *cinfo, struct svc_fh *fhp)
486486
{
487-
BUG_ON(!fhp->fh_pre_saved || !fhp->fh_post_saved);
488-
cinfo->atomic = 1;
487+
BUG_ON(!fhp->fh_pre_saved);
488+
cinfo->atomic = fhp->fh_post_saved;
489489
cinfo->change_supported = IS_I_VERSION(fhp->fh_dentry->d_inode);
490-
if (cinfo->change_supported) {
491-
cinfo->before_change = fhp->fh_pre_change;
492-
cinfo->after_change = fhp->fh_post_change;
493-
} else {
494-
cinfo->before_ctime_sec = fhp->fh_pre_ctime.tv_sec;
495-
cinfo->before_ctime_nsec = fhp->fh_pre_ctime.tv_nsec;
496-
cinfo->after_ctime_sec = fhp->fh_post_attr.ctime.tv_sec;
497-
cinfo->after_ctime_nsec = fhp->fh_post_attr.ctime.tv_nsec;
498-
}
490+
491+
cinfo->before_change = fhp->fh_pre_change;
492+
cinfo->after_change = fhp->fh_post_change;
493+
cinfo->before_ctime_sec = fhp->fh_pre_ctime.tv_sec;
494+
cinfo->before_ctime_nsec = fhp->fh_pre_ctime.tv_nsec;
495+
cinfo->after_ctime_sec = fhp->fh_post_attr.ctime.tv_sec;
496+
cinfo->after_ctime_nsec = fhp->fh_post_attr.ctime.tv_nsec;
497+
499498
}
500499

501500
int nfs4svc_encode_voidres(struct svc_rqst *, __be32 *, void *);

net/sunrpc/svc_xprt.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@ int svc_create_xprt(struct svc_serv *serv, const char *xprt_name,
212212
spin_lock(&svc_xprt_class_lock);
213213
list_for_each_entry(xcl, &svc_xprt_class_list, xcl_list) {
214214
struct svc_xprt *newxprt;
215+
unsigned short newport;
215216

216217
if (strcmp(xprt_name, xcl->xcl_name))
217218
continue;
@@ -230,8 +231,9 @@ int svc_create_xprt(struct svc_serv *serv, const char *xprt_name,
230231
spin_lock_bh(&serv->sv_lock);
231232
list_add(&newxprt->xpt_list, &serv->sv_permsocks);
232233
spin_unlock_bh(&serv->sv_lock);
234+
newport = svc_xprt_local_port(newxprt);
233235
clear_bit(XPT_BUSY, &newxprt->xpt_flags);
234-
return svc_xprt_local_port(newxprt);
236+
return newport;
235237
}
236238
err:
237239
spin_unlock(&svc_xprt_class_lock);
@@ -425,8 +427,13 @@ void svc_xprt_received(struct svc_xprt *xprt)
425427
{
426428
BUG_ON(!test_bit(XPT_BUSY, &xprt->xpt_flags));
427429
xprt->xpt_pool = NULL;
430+
/* As soon as we clear busy, the xprt could be closed and
431+
* 'put', so we need a reference to call svc_xprt_enqueue with:
432+
*/
433+
svc_xprt_get(xprt);
428434
clear_bit(XPT_BUSY, &xprt->xpt_flags);
429435
svc_xprt_enqueue(xprt);
436+
svc_xprt_put(xprt);
430437
}
431438
EXPORT_SYMBOL_GPL(svc_xprt_received);
432439

0 commit comments

Comments
 (0)