Skip to content

Commit ee1438c

Browse files
ubifs: Check link count of inodes when killing orphans.
O_TMPFILE files can change their link count back to non-zero. This corner case needs to get addressed in the orphans subsystem too. Fixes: 474b937 ("ubifs: Implement O_TMPFILE") Reported-by: Lars Persson <[email protected]> Signed-off-by: Richard Weinberger <[email protected]>
1 parent eeabb98 commit ee1438c

File tree

1 file changed

+35
-9
lines changed

1 file changed

+35
-9
lines changed

fs/ubifs/orphan.c

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -630,6 +630,7 @@ static int do_kill_orphans(struct ubifs_info *c, struct ubifs_scan_leb *sleb,
630630
{
631631
struct ubifs_scan_node *snod;
632632
struct ubifs_orph_node *orph;
633+
struct ubifs_ino_node *ino = NULL;
633634
unsigned long long cmt_no;
634635
ino_t inum;
635636
int i, n, err, first = 1;
@@ -676,23 +677,40 @@ static int do_kill_orphans(struct ubifs_info *c, struct ubifs_scan_leb *sleb,
676677
if (first)
677678
first = 0;
678679

680+
ino = kmalloc(UBIFS_MAX_INO_NODE_SZ, GFP_NOFS);
681+
if (!ino)
682+
return -ENOMEM;
683+
679684
n = (le32_to_cpu(orph->ch.len) - UBIFS_ORPH_NODE_SZ) >> 3;
680685
for (i = 0; i < n; i++) {
681686
union ubifs_key key1, key2;
682687

683688
inum = le64_to_cpu(orph->inos[i]);
684-
dbg_rcvry("deleting orphaned inode %lu",
685-
(unsigned long)inum);
686-
687-
lowest_ino_key(c, &key1, inum);
688-
highest_ino_key(c, &key2, inum);
689689

690-
err = ubifs_tnc_remove_range(c, &key1, &key2);
690+
ino_key_init(c, &key1, inum);
691+
err = ubifs_tnc_lookup(c, &key1, ino);
691692
if (err)
692-
return err;
693+
goto out_free;
694+
695+
/*
696+
* Check whether an inode can really get deleted.
697+
* linkat() with O_TMPFILE allows rebirth of an inode.
698+
*/
699+
if (ino->nlink == 0) {
700+
dbg_rcvry("deleting orphaned inode %lu",
701+
(unsigned long)inum);
702+
703+
lowest_ino_key(c, &key1, inum);
704+
highest_ino_key(c, &key2, inum);
705+
706+
err = ubifs_tnc_remove_range(c, &key1, &key2);
707+
if (err)
708+
goto out_ro;
709+
}
710+
693711
err = insert_dead_orphan(c, inum);
694712
if (err)
695-
return err;
713+
goto out_free;
696714
}
697715

698716
*last_cmt_no = cmt_no;
@@ -704,7 +722,15 @@ static int do_kill_orphans(struct ubifs_info *c, struct ubifs_scan_leb *sleb,
704722
*last_flagged = 0;
705723
}
706724

707-
return 0;
725+
err = 0;
726+
out_free:
727+
kfree(ino);
728+
return err;
729+
730+
out_ro:
731+
ubifs_ro_mode(c, err);
732+
kfree(ino);
733+
return err;
708734
}
709735

710736
/**

0 commit comments

Comments
 (0)