ext4: convert from atomic_t to refcount_t on ext4_io_end->count
authorXiyu Yang <xiyuyang19@fudan.edu.cn>
Mon, 19 Jul 2021 05:59:14 +0000 (13:59 +0800)
committerTheodore Ts'o <tytso@mit.edu>
Thu, 4 Nov 2021 14:33:24 +0000 (10:33 -0400)
refcount_t type and corresponding API can protect refcounters from
accidental underflow and overflow and further use-after-free situations.

Signed-off-by: Xiyu Yang <xiyuyang19@fudan.edu.cn>
Signed-off-by: Xin Tan <tanxin.ctf@gmail.com>
Reviewed-by: Jan Kara <jack@suse.cz>
Link: https://lore.kernel.org/r/1626674355-55795-1-git-send-email-xiyuyang19@fudan.edu.cn
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
fs/ext4/ext4.h
fs/ext4/page-io.c

index 3825195539d7438a2db2b112b75e3af50b4ccccd..404dd50856e5d294c38e746c97dd50183d650eb0 100644 (file)
@@ -17,6 +17,7 @@
 #ifndef _EXT4_H
 #define _EXT4_H
 
+#include <linux/refcount.h>
 #include <linux/types.h>
 #include <linux/blkdev.h>
 #include <linux/magic.h>
@@ -241,7 +242,7 @@ typedef struct ext4_io_end {
        struct bio              *bio;           /* Linked list of completed
                                                 * bios covering the extent */
        unsigned int            flag;           /* unwritten or not */
-       atomic_t                count;          /* reference counter */
+       refcount_t              count;          /* reference counter */
        struct list_head        list_vec;       /* list of ext4_io_end_vec */
 } ext4_io_end_t;
 
index f038d578d8d8ff3ab21f260a5fa011cc9150e60b..9cb2617149918faef7adea35906a4cbf3df6d276 100644 (file)
@@ -279,14 +279,14 @@ ext4_io_end_t *ext4_init_io_end(struct inode *inode, gfp_t flags)
                io_end->inode = inode;
                INIT_LIST_HEAD(&io_end->list);
                INIT_LIST_HEAD(&io_end->list_vec);
-               atomic_set(&io_end->count, 1);
+               refcount_set(&io_end->count, 1);
        }
        return io_end;
 }
 
 void ext4_put_io_end_defer(ext4_io_end_t *io_end)
 {
-       if (atomic_dec_and_test(&io_end->count)) {
+       if (refcount_dec_and_test(&io_end->count)) {
                if (!(io_end->flag & EXT4_IO_END_UNWRITTEN) ||
                                list_empty(&io_end->list_vec)) {
                        ext4_release_io_end(io_end);
@@ -300,7 +300,7 @@ int ext4_put_io_end(ext4_io_end_t *io_end)
 {
        int err = 0;
 
-       if (atomic_dec_and_test(&io_end->count)) {
+       if (refcount_dec_and_test(&io_end->count)) {
                if (io_end->flag & EXT4_IO_END_UNWRITTEN) {
                        err = ext4_convert_unwritten_io_end_vec(io_end->handle,
                                                                io_end);
@@ -314,7 +314,7 @@ int ext4_put_io_end(ext4_io_end_t *io_end)
 
 ext4_io_end_t *ext4_get_io_end(ext4_io_end_t *io_end)
 {
-       atomic_inc(&io_end->count);
+       refcount_inc(&io_end->count);
        return io_end;
 }