diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-12-14 14:09:05 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-12-14 14:09:05 -0500 |
commit | 5111711d3ed8f4f1012cac3ec3f2b463b549fbfd (patch) | |
tree | dc44d88bc66d3e7ec4d1c9180d6d4289fe7c5901 /net | |
parent | e13cf63f2bbd38721af557f0205da994ea068427 (diff) | |
parent | c1ac3ffcd0bc7e9617f62be8c7043d53ab84deac (diff) |
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
Diffstat (limited to 'net')
-rw-r--r-- | net/sunrpc/svc_xprt.c | 9 |
1 files changed, 8 insertions, 1 deletions
diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c index ea2ff78dcf7b..3f2c5559ca1a 100644 --- a/net/sunrpc/svc_xprt.c +++ b/net/sunrpc/svc_xprt.c | |||
@@ -212,6 +212,7 @@ int svc_create_xprt(struct svc_serv *serv, const char *xprt_name, | |||
212 | spin_lock(&svc_xprt_class_lock); | 212 | spin_lock(&svc_xprt_class_lock); |
213 | list_for_each_entry(xcl, &svc_xprt_class_list, xcl_list) { | 213 | list_for_each_entry(xcl, &svc_xprt_class_list, xcl_list) { |
214 | struct svc_xprt *newxprt; | 214 | struct svc_xprt *newxprt; |
215 | unsigned short newport; | ||
215 | 216 | ||
216 | if (strcmp(xprt_name, xcl->xcl_name)) | 217 | if (strcmp(xprt_name, xcl->xcl_name)) |
217 | continue; | 218 | continue; |
@@ -230,8 +231,9 @@ int svc_create_xprt(struct svc_serv *serv, const char *xprt_name, | |||
230 | spin_lock_bh(&serv->sv_lock); | 231 | spin_lock_bh(&serv->sv_lock); |
231 | list_add(&newxprt->xpt_list, &serv->sv_permsocks); | 232 | list_add(&newxprt->xpt_list, &serv->sv_permsocks); |
232 | spin_unlock_bh(&serv->sv_lock); | 233 | spin_unlock_bh(&serv->sv_lock); |
234 | newport = svc_xprt_local_port(newxprt); | ||
233 | clear_bit(XPT_BUSY, &newxprt->xpt_flags); | 235 | clear_bit(XPT_BUSY, &newxprt->xpt_flags); |
234 | return svc_xprt_local_port(newxprt); | 236 | return newport; |
235 | } | 237 | } |
236 | err: | 238 | err: |
237 | spin_unlock(&svc_xprt_class_lock); | 239 | spin_unlock(&svc_xprt_class_lock); |
@@ -425,8 +427,13 @@ void svc_xprt_received(struct svc_xprt *xprt) | |||
425 | { | 427 | { |
426 | BUG_ON(!test_bit(XPT_BUSY, &xprt->xpt_flags)); | 428 | BUG_ON(!test_bit(XPT_BUSY, &xprt->xpt_flags)); |
427 | xprt->xpt_pool = NULL; | 429 | 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); | ||
428 | clear_bit(XPT_BUSY, &xprt->xpt_flags); | 434 | clear_bit(XPT_BUSY, &xprt->xpt_flags); |
429 | svc_xprt_enqueue(xprt); | 435 | svc_xprt_enqueue(xprt); |
436 | svc_xprt_put(xprt); | ||
430 | } | 437 | } |
431 | EXPORT_SYMBOL_GPL(svc_xprt_received); | 438 | EXPORT_SYMBOL_GPL(svc_xprt_received); |
432 | 439 | ||