瀏覽代碼

NFSv4: Fix an oopsable condition in nfs_free_seqid

 Storing a pointer to the struct rpc_task in the nfs_seqid is broken
 since the nfs_seqid may be freed well after the task has been destroyed.

 Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Trond Myklebust 19 年之前
父節點
當前提交
7f709a48fa
共有 2 個文件被更改,包括 1 次插入9 次删除
  1. 0 1
      fs/nfs/nfs4_fs.h
  2. 1 8
      fs/nfs/nfs4state.c

+ 0 - 1
fs/nfs/nfs4_fs.h

@@ -112,7 +112,6 @@ struct nfs_seqid_counter {
 struct nfs_seqid {
 	struct list_head list;
 	struct nfs_seqid_counter *sequence;
-	struct rpc_task *task;
 };
 
 static inline void nfs_confirm_seqid(struct nfs_seqid_counter *seqid, int status)

+ 1 - 8
fs/nfs/nfs4state.c

@@ -676,7 +676,6 @@ struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter)
 	new = kmalloc(sizeof(*new), GFP_KERNEL);
 	if (new != NULL) {
 		new->sequence = counter;
-		new->task = NULL;
 		spin_lock(&sequence->lock);
 		list_add_tail(&new->list, &sequence->list);
 		spin_unlock(&sequence->lock);
@@ -687,15 +686,10 @@ struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter)
 void nfs_free_seqid(struct nfs_seqid *seqid)
 {
 	struct rpc_sequence *sequence = seqid->sequence->sequence;
-	struct rpc_task *next = NULL;
 
 	spin_lock(&sequence->lock);
 	list_del(&seqid->list);
-	if (!list_empty(&sequence->list)) {
-		next = list_entry(sequence->list.next, struct nfs_seqid, list)->task;
-		if (next)
-			rpc_wake_up_task(next);
-	}
+	rpc_wake_up(&sequence->wait);
 	spin_unlock(&sequence->lock);
 	kfree(seqid);
 }
@@ -754,7 +748,6 @@ int nfs_wait_on_sequence(struct nfs_seqid *seqid, struct rpc_task *task)
 
 	spin_lock(&sequence->lock);
 	if (sequence->list.next != &seqid->list) {
-		seqid->task = task;
 		rpc_sleep_on(&sequence->wait, task, NULL, NULL);
 		status = -EAGAIN;
 	}