aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-01-10 17:57:19 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2012-01-10 17:57:19 -0500
commit5c395ae7033099fc657114ea997858aa622f08b2 (patch)
treef714c8d8db528274de2da4f8aa64b69af0d2aa5e
parent49d41bae46f15da528ef9848fd7c9d38582aa8e9 (diff)
parente57e0d8e818512047fe379157c3f77f1b9fabffb (diff)
Merge branch 'linux-next' of git://git.infradead.org/ubifs-2.6
* 'linux-next' of git://git.infradead.org/ubifs-2.6: UBI: fix use-after-free on error path UBI: fix missing scrub when there is a bit-flip UBIFS: Use kmemdup rather than duplicating its implementation
-rw-r--r--drivers/mtd/ubi/eba.c6
-rw-r--r--drivers/mtd/ubi/ubi.h2
-rw-r--r--drivers/mtd/ubi/wl.c12
-rw-r--r--fs/ubifs/lpt.c6
-rw-r--r--fs/ubifs/tnc.c3
-rw-r--r--fs/ubifs/xattr.c6
6 files changed, 19 insertions, 16 deletions
diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c
index fb7f19b62d9..cd26da8ad22 100644
--- a/drivers/mtd/ubi/eba.c
+++ b/drivers/mtd/ubi/eba.c
@@ -1028,12 +1028,14 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
1028 * 'ubi_wl_put_peb()' function on the @ubi->move_mutex. In turn, we are 1028 * 'ubi_wl_put_peb()' function on the @ubi->move_mutex. In turn, we are
1029 * holding @ubi->move_mutex and go sleep on the LEB lock. So, if the 1029 * holding @ubi->move_mutex and go sleep on the LEB lock. So, if the
1030 * LEB is already locked, we just do not move it and return 1030 * LEB is already locked, we just do not move it and return
1031 * %MOVE_CANCEL_RACE, which means that UBI will re-try, but later. 1031 * %MOVE_RETRY. Note, we do not return %MOVE_CANCEL_RACE here because
1032 * we do not know the reasons of the contention - it may be just a
1033 * normal I/O on this LEB, so we want to re-try.
1032 */ 1034 */
1033 err = leb_write_trylock(ubi, vol_id, lnum); 1035 err = leb_write_trylock(ubi, vol_id, lnum);
1034 if (err) { 1036 if (err) {
1035 dbg_wl("contention on LEB %d:%d, cancel", vol_id, lnum); 1037 dbg_wl("contention on LEB %d:%d, cancel", vol_id, lnum);
1036 return MOVE_CANCEL_RACE; 1038 return MOVE_RETRY;
1037 } 1039 }
1038 1040
1039 /* 1041 /*
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
index dc64c767fd2..d51d75d3444 100644
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
@@ -120,6 +120,7 @@ enum {
120 * PEB 120 * PEB
121 * MOVE_CANCEL_BITFLIPS: canceled because a bit-flip was detected in the 121 * MOVE_CANCEL_BITFLIPS: canceled because a bit-flip was detected in the
122 * target PEB 122 * target PEB
123 * MOVE_RETRY: retry scrubbing the PEB
123 */ 124 */
124enum { 125enum {
125 MOVE_CANCEL_RACE = 1, 126 MOVE_CANCEL_RACE = 1,
@@ -127,6 +128,7 @@ enum {
127 MOVE_TARGET_RD_ERR, 128 MOVE_TARGET_RD_ERR,
128 MOVE_TARGET_WR_ERR, 129 MOVE_TARGET_WR_ERR,
129 MOVE_CANCEL_BITFLIPS, 130 MOVE_CANCEL_BITFLIPS,
131 MOVE_RETRY,
130}; 132};
131 133
132/** 134/**
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index 42c684cf368..0696e36b053 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -795,7 +795,10 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
795 protect = 1; 795 protect = 1;
796 goto out_not_moved; 796 goto out_not_moved;
797 } 797 }
798 798 if (err == MOVE_RETRY) {
799 scrubbing = 1;
800 goto out_not_moved;
801 }
799 if (err == MOVE_CANCEL_BITFLIPS || err == MOVE_TARGET_WR_ERR || 802 if (err == MOVE_CANCEL_BITFLIPS || err == MOVE_TARGET_WR_ERR ||
800 err == MOVE_TARGET_RD_ERR) { 803 err == MOVE_TARGET_RD_ERR) {
801 /* 804 /*
@@ -1049,7 +1052,6 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk,
1049 1052
1050 ubi_err("failed to erase PEB %d, error %d", pnum, err); 1053 ubi_err("failed to erase PEB %d, error %d", pnum, err);
1051 kfree(wl_wrk); 1054 kfree(wl_wrk);
1052 kmem_cache_free(ubi_wl_entry_slab, e);
1053 1055
1054 if (err == -EINTR || err == -ENOMEM || err == -EAGAIN || 1056 if (err == -EINTR || err == -ENOMEM || err == -EAGAIN ||
1055 err == -EBUSY) { 1057 err == -EBUSY) {
@@ -1062,14 +1064,16 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk,
1062 goto out_ro; 1064 goto out_ro;
1063 } 1065 }
1064 return err; 1066 return err;
1065 } else if (err != -EIO) { 1067 }
1068
1069 kmem_cache_free(ubi_wl_entry_slab, e);
1070 if (err != -EIO)
1066 /* 1071 /*
1067 * If this is not %-EIO, we have no idea what to do. Scheduling 1072 * If this is not %-EIO, we have no idea what to do. Scheduling
1068 * this physical eraseblock for erasure again would cause 1073 * this physical eraseblock for erasure again would cause
1069 * errors again and again. Well, lets switch to R/O mode. 1074 * errors again and again. Well, lets switch to R/O mode.
1070 */ 1075 */
1071 goto out_ro; 1076 goto out_ro;
1072 }
1073 1077
1074 /* It is %-EIO, the PEB went bad */ 1078 /* It is %-EIO, the PEB went bad */
1075 1079
diff --git a/fs/ubifs/lpt.c b/fs/ubifs/lpt.c
index 6189c74d97f..66d59d0a140 100644
--- a/fs/ubifs/lpt.c
+++ b/fs/ubifs/lpt.c
@@ -1986,12 +1986,11 @@ again:
1986 1986
1987 if (path[h].in_tree) 1987 if (path[h].in_tree)
1988 continue; 1988 continue;
1989 nnode = kmalloc(sz, GFP_NOFS); 1989 nnode = kmemdup(&path[h].nnode, sz, GFP_NOFS);
1990 if (!nnode) { 1990 if (!nnode) {
1991 err = -ENOMEM; 1991 err = -ENOMEM;
1992 goto out; 1992 goto out;
1993 } 1993 }
1994 memcpy(nnode, &path[h].nnode, sz);
1995 parent = nnode->parent; 1994 parent = nnode->parent;
1996 parent->nbranch[nnode->iip].nnode = nnode; 1995 parent->nbranch[nnode->iip].nnode = nnode;
1997 path[h].ptr.nnode = nnode; 1996 path[h].ptr.nnode = nnode;
@@ -2004,12 +2003,11 @@ again:
2004 const size_t sz = sizeof(struct ubifs_pnode); 2003 const size_t sz = sizeof(struct ubifs_pnode);
2005 struct ubifs_nnode *parent; 2004 struct ubifs_nnode *parent;
2006 2005
2007 pnode = kmalloc(sz, GFP_NOFS); 2006 pnode = kmemdup(&path[h].pnode, sz, GFP_NOFS);
2008 if (!pnode) { 2007 if (!pnode) {
2009 err = -ENOMEM; 2008 err = -ENOMEM;
2010 goto out; 2009 goto out;
2011 } 2010 }
2012 memcpy(pnode, &path[h].pnode, sz);
2013 parent = pnode->parent; 2011 parent = pnode->parent;
2014 parent->nbranch[pnode->iip].pnode = pnode; 2012 parent->nbranch[pnode->iip].pnode = pnode;
2015 path[h].ptr.pnode = pnode; 2013 path[h].ptr.pnode = pnode;
diff --git a/fs/ubifs/tnc.c b/fs/ubifs/tnc.c
index 06673864768..e14ee53159d 100644
--- a/fs/ubifs/tnc.c
+++ b/fs/ubifs/tnc.c
@@ -344,12 +344,11 @@ static int lnc_add(struct ubifs_info *c, struct ubifs_zbranch *zbr,
344 return err; 344 return err;
345 } 345 }
346 346
347 lnc_node = kmalloc(zbr->len, GFP_NOFS); 347 lnc_node = kmemdup(node, zbr->len, GFP_NOFS);
348 if (!lnc_node) 348 if (!lnc_node)
349 /* We don't have to have the cache, so no error */ 349 /* We don't have to have the cache, so no error */
350 return 0; 350 return 0;
351 351
352 memcpy(lnc_node, node, zbr->len);
353 zbr->leaf = lnc_node; 352 zbr->leaf = lnc_node;
354 return 0; 353 return 0;
355} 354}
diff --git a/fs/ubifs/xattr.c b/fs/ubifs/xattr.c
index bf18f7a0454..85b27226875 100644
--- a/fs/ubifs/xattr.c
+++ b/fs/ubifs/xattr.c
@@ -138,12 +138,11 @@ static int create_xattr(struct ubifs_info *c, struct inode *host,
138 ui = ubifs_inode(inode); 138 ui = ubifs_inode(inode);
139 ui->xattr = 1; 139 ui->xattr = 1;
140 ui->flags |= UBIFS_XATTR_FL; 140 ui->flags |= UBIFS_XATTR_FL;
141 ui->data = kmalloc(size, GFP_NOFS); 141 ui->data = kmemdup(value, size, GFP_NOFS);
142 if (!ui->data) { 142 if (!ui->data) {
143 err = -ENOMEM; 143 err = -ENOMEM;
144 goto out_free; 144 goto out_free;
145 } 145 }
146 memcpy(ui->data, value, size);
147 inode->i_size = ui->ui_size = size; 146 inode->i_size = ui->ui_size = size;
148 ui->data_len = size; 147 ui->data_len = size;
149 148
@@ -204,12 +203,11 @@ static int change_xattr(struct ubifs_info *c, struct inode *host,
204 return err; 203 return err;
205 204
206 kfree(ui->data); 205 kfree(ui->data);
207 ui->data = kmalloc(size, GFP_NOFS); 206 ui->data = kmemdup(value, size, GFP_NOFS);
208 if (!ui->data) { 207 if (!ui->data) {
209 err = -ENOMEM; 208 err = -ENOMEM;
210 goto out_free; 209 goto out_free;
211 } 210 }
212 memcpy(ui->data, value, size);
213 inode->i_size = ui->ui_size = size; 211 inode->i_size = ui->ui_size = size;
214 ui->data_len = size; 212 ui->data_len = size;
215 213