Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8afd500c authored by Adam Thomas's avatar Adam Thomas Committed by Artem Bityutskiy
Browse files

UBIFS: fix double free of ubifs_orphan objects



The last orphan in the dnext list has its dnext set to NULL. Because
of that, ubifs_delete_orphan assumes that it is not on the dnext list
and frees it immediately instead ignoring it as a second delete. The
orphan is later freed again by erase_deleted.

This change adds an explicit flag to ubifs_orphan indicating whether
it is pending delete.

Signed-off-by: default avatarAdam Thomas <adamthomas1111@gmail.com>
Signed-off-by: default avatarArtem Bityutskiy <artem.bityutskiy@linux.intel.com>
Cc: stable@vger.kernel.org
parent 2928f0d0
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -126,13 +126,14 @@ void ubifs_delete_orphan(struct ubifs_info *c, ino_t inum)
		else if (inum > o->inum)
			p = p->rb_right;
		else {
			if (o->dnext) {
			if (o->del) {
				spin_unlock(&c->orphan_lock);
				dbg_gen("deleted twice ino %lu",
					(unsigned long)inum);
				return;
			}
			if (o->cmt) {
				o->del = 1;
				o->dnext = c->orph_dnext;
				c->orph_dnext = o;
				spin_unlock(&c->orphan_lock);
@@ -447,6 +448,7 @@ static void erase_deleted(struct ubifs_info *c)
		orphan = dnext;
		dnext = orphan->dnext;
		ubifs_assert(!orphan->new);
		ubifs_assert(orphan->del);
		rb_erase(&orphan->rb, &c->orph_tree);
		list_del(&orphan->list);
		c->tot_orphans -= 1;
@@ -536,6 +538,7 @@ static int insert_dead_orphan(struct ubifs_info *c, ino_t inum)
	rb_link_node(&orphan->rb, parent, p);
	rb_insert_color(&orphan->rb, &c->orph_tree);
	list_add_tail(&orphan->list, &c->orph_list);
	orphan->del = 1;
	orphan->dnext = c->orph_dnext;
	c->orph_dnext = orphan;
	dbg_mnt("ino %lu, new %d, tot %d", (unsigned long)inum,
+2 −0
Original line number Diff line number Diff line
@@ -905,6 +905,7 @@ struct ubifs_budget_req {
 * @inum: inode number
 * @new: %1 => added since the last commit, otherwise %0
 * @cmt: %1 => commit pending, otherwise %0
 * @del: %1 => delete pending, otherwise %0
 */
struct ubifs_orphan {
	struct rb_node rb;
@@ -915,6 +916,7 @@ struct ubifs_orphan {
	ino_t inum;
	unsigned new:1;
	unsigned cmt:1;
	unsigned del:1;
};

/**