mirror of
https://github.com/torvalds/linux.git
synced 2024-12-30 14:52:05 +00:00
nfsd-6.2 fixes:
- Nail another UAF in NFSD's filecache -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEKLLlsBKG3yQ88j7+M2qzM29mf5cFAmPPYLoACgkQM2qzM29m f5cFXhAAmSn3h41br0tW0vn3fkDVqJpY5y1GsT31llT833CvxoEG+dERWmfFqwaT rfNAnfFJjJdOmLEos2KmkABP/9HLUHo3ePgqS9MXEDouHPVdnPEKLYNxB+kp/535 +NUDEm7HrcxnctZEcWdGuprmdbSexZeE4ng2lEmbvaiWRQRhBoJS59iM2YfHcN77 7bVz0jrCEYklGSwtfN0wzq9O4VeFPzRhESfycV1LV4ZvUwTNd5vGl1zBWs9ydxWN kBET/222Bd1rGuvoNFEWcK/dQFDtPrz1tiXH06IHthPvd70BP1z25sOmNfcQHrPp 7gfGJD03PnC2CPVg8Uuou2e1/Je3/Ib+3V2cQJwUWWVWw1GDdwWrk3LG4+esRbdv OP2qT0dw5uHOuoECwehc/mDyYv2QIIzkXUjxlMNL2WqCxXlKgxO/4lpcvryMlbw6 WHcMV9miCzkA1bK2d8QNisqkNTIQBsWzfrMbXZ9zeQnahrz981Y25OYdXjYIbRyC itliKYty4L9mS0z2gu5Y6WNBTk9bWItkq2GIIhjWo3K4UAccgfQSn+f6rXX5wNjP M1P2+QTtb3fMyepbYyDH0KM3wOtROA1MycFvWLSt9sobwiIa/Mt/1mMfcxHtdFEB 85rDxB+zeWqXA5xbzowI3KcmkuHta1QLfBXY9f4x5nLKFduGwAM= =1Wj9 -----END PGP SIGNATURE----- Merge tag 'nfsd-6.2-5' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux Pull nfsd fix from Chuck Lever: - Nail another UAF in NFSD's filecache * tag 'nfsd-6.2-5' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux: nfsd: don't free files unconditionally in __nfsd_file_cache_purge
This commit is contained in:
commit
fb6e71db53
@ -661,6 +661,39 @@ static struct shrinker nfsd_file_shrinker = {
|
||||
.seeks = 1,
|
||||
};
|
||||
|
||||
/**
|
||||
* nfsd_file_cond_queue - conditionally unhash and queue a nfsd_file
|
||||
* @nf: nfsd_file to attempt to queue
|
||||
* @dispose: private list to queue successfully-put objects
|
||||
*
|
||||
* Unhash an nfsd_file, try to get a reference to it, and then put that
|
||||
* reference. If it's the last reference, queue it to the dispose list.
|
||||
*/
|
||||
static void
|
||||
nfsd_file_cond_queue(struct nfsd_file *nf, struct list_head *dispose)
|
||||
__must_hold(RCU)
|
||||
{
|
||||
int decrement = 1;
|
||||
|
||||
/* If we raced with someone else unhashing, ignore it */
|
||||
if (!nfsd_file_unhash(nf))
|
||||
return;
|
||||
|
||||
/* If we can't get a reference, ignore it */
|
||||
if (!nfsd_file_get(nf))
|
||||
return;
|
||||
|
||||
/* Extra decrement if we remove from the LRU */
|
||||
if (nfsd_file_lru_remove(nf))
|
||||
++decrement;
|
||||
|
||||
/* If refcount goes to 0, then put on the dispose list */
|
||||
if (refcount_sub_and_test(decrement, &nf->nf_ref)) {
|
||||
list_add(&nf->nf_lru, dispose);
|
||||
trace_nfsd_file_closing(nf);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* nfsd_file_queue_for_close: try to close out any open nfsd_files for an inode
|
||||
* @inode: inode on which to close out nfsd_files
|
||||
@ -688,30 +721,11 @@ nfsd_file_queue_for_close(struct inode *inode, struct list_head *dispose)
|
||||
|
||||
rcu_read_lock();
|
||||
do {
|
||||
int decrement = 1;
|
||||
|
||||
nf = rhashtable_lookup(&nfsd_file_rhash_tbl, &key,
|
||||
nfsd_file_rhash_params);
|
||||
if (!nf)
|
||||
break;
|
||||
|
||||
/* If we raced with someone else unhashing, ignore it */
|
||||
if (!nfsd_file_unhash(nf))
|
||||
continue;
|
||||
|
||||
/* If we can't get a reference, ignore it */
|
||||
if (!nfsd_file_get(nf))
|
||||
continue;
|
||||
|
||||
/* Extra decrement if we remove from the LRU */
|
||||
if (nfsd_file_lru_remove(nf))
|
||||
++decrement;
|
||||
|
||||
/* If refcount goes to 0, then put on the dispose list */
|
||||
if (refcount_sub_and_test(decrement, &nf->nf_ref)) {
|
||||
list_add(&nf->nf_lru, dispose);
|
||||
trace_nfsd_file_closing(nf);
|
||||
}
|
||||
nfsd_file_cond_queue(nf, dispose);
|
||||
} while (1);
|
||||
rcu_read_unlock();
|
||||
}
|
||||
@ -928,11 +942,8 @@ __nfsd_file_cache_purge(struct net *net)
|
||||
|
||||
nf = rhashtable_walk_next(&iter);
|
||||
while (!IS_ERR_OR_NULL(nf)) {
|
||||
if (!net || nf->nf_net == net) {
|
||||
nfsd_file_unhash(nf);
|
||||
nfsd_file_lru_remove(nf);
|
||||
list_add(&nf->nf_lru, &dispose);
|
||||
}
|
||||
if (!net || nf->nf_net == net)
|
||||
nfsd_file_cond_queue(nf, &dispose);
|
||||
nf = rhashtable_walk_next(&iter);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user