forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-01-31 f70575805708cabdedea7498aaa3f710fde4d920
kernel/fs/quota/quota_tree.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * vfsv0 quota IO operations on file
34 */
....@@ -79,6 +80,35 @@
7980 return ret;
8081 }
8182
83
+static inline int do_check_range(struct super_block *sb, const char *val_name,
84
+ uint val, uint min_val, uint max_val)
85
+{
86
+ if (val < min_val || val > max_val) {
87
+ quota_error(sb, "Getting %s %u out of range %u-%u",
88
+ val_name, val, min_val, max_val);
89
+ return -EUCLEAN;
90
+ }
91
+
92
+ return 0;
93
+}
94
+
95
+static int check_dquot_block_header(struct qtree_mem_dqinfo *info,
96
+ struct qt_disk_dqdbheader *dh)
97
+{
98
+ int err = 0;
99
+
100
+ err = do_check_range(info->dqi_sb, "dqdh_next_free",
101
+ le32_to_cpu(dh->dqdh_next_free), 0,
102
+ info->dqi_blocks - 1);
103
+ if (err)
104
+ return err;
105
+ err = do_check_range(info->dqi_sb, "dqdh_prev_free",
106
+ le32_to_cpu(dh->dqdh_prev_free), 0,
107
+ info->dqi_blocks - 1);
108
+
109
+ return err;
110
+}
111
+
82112 /* Remove empty block from list and return it */
83113 static int get_free_dqblk(struct qtree_mem_dqinfo *info)
84114 {
....@@ -92,6 +122,9 @@
92122 blk = info->dqi_free_blk;
93123 ret = read_blk(info, blk, buf);
94124 if (ret < 0)
125
+ goto out_buf;
126
+ ret = check_dquot_block_header(info, dh);
127
+ if (ret)
95128 goto out_buf;
96129 info->dqi_free_blk = le32_to_cpu(dh->dqdh_next_free);
97130 }
....@@ -239,6 +272,9 @@
239272 blk = info->dqi_free_entry;
240273 *err = read_blk(info, blk, buf);
241274 if (*err < 0)
275
+ goto out_buf;
276
+ *err = check_dquot_block_header(info, dh);
277
+ if (*err)
242278 goto out_buf;
243279 } else {
244280 blk = get_free_dqblk(info);
....@@ -432,6 +468,9 @@
432468 goto out_buf;
433469 }
434470 dh = (struct qt_disk_dqdbheader *)buf;
471
+ ret = check_dquot_block_header(info, dh);
472
+ if (ret)
473
+ goto out_buf;
435474 le16_add_cpu(&dh->dqdh_entries, -1);
436475 if (!le16_to_cpu(dh->dqdh_entries)) { /* Block got free? */
437476 ret = remove_free_dqentry(info, buf, blk);