hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/fs/ext4/inline.c
....@@ -33,6 +33,7 @@
3333 struct ext4_xattr_ibody_header *header;
3434 struct ext4_xattr_entry *entry;
3535 struct ext4_inode *raw_inode;
36
+ void *end;
3637 int free, min_offs;
3738
3839 if (!EXT4_INODE_HAS_XATTR_SPACE(inode))
....@@ -56,14 +57,23 @@
5657 raw_inode = ext4_raw_inode(iloc);
5758 header = IHDR(inode, raw_inode);
5859 entry = IFIRST(header);
60
+ end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size;
5961
6062 /* Compute min_offs. */
61
- for (; !IS_LAST_ENTRY(entry); entry = EXT4_XATTR_NEXT(entry)) {
63
+ while (!IS_LAST_ENTRY(entry)) {
64
+ void *next = EXT4_XATTR_NEXT(entry);
65
+
66
+ if (next >= end) {
67
+ EXT4_ERROR_INODE(inode,
68
+ "corrupt xattr in inline inode");
69
+ return 0;
70
+ }
6271 if (!entry->e_value_inum && entry->e_value_size) {
6372 size_t offs = le16_to_cpu(entry->e_value_offs);
6473 if (offs < min_offs)
6574 min_offs = offs;
6675 }
76
+ entry = next;
6777 }
6878 free = min_offs -
6979 ((void *)entry - (void *)IFIRST(header)) - sizeof(__u32);
....@@ -158,7 +168,6 @@
158168 (void *)ext4_raw_inode(&is.iloc));
159169 EXT4_I(inode)->i_inline_size = EXT4_MIN_INLINE_DATA_SIZE +
160170 le32_to_cpu(is.s.here->e_value_size);
161
- ext4_set_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA);
162171 }
163172 out:
164173 brelse(is.iloc.bh);
....@@ -208,7 +217,7 @@
208217 /*
209218 * write the buffer to the inline inode.
210219 * If 'create' is set, we don't need to do the extra copy in the xattr
211
- * value since it is already handled by ext4_xattr_ibody_inline_set.
220
+ * value since it is already handled by ext4_xattr_ibody_set.
212221 * That saves us one memcpy.
213222 */
214223 static void ext4_write_inline_data(struct inode *inode, struct ext4_iloc *iloc,
....@@ -290,7 +299,7 @@
290299
291300 BUG_ON(!is.s.not_found);
292301
293
- error = ext4_xattr_ibody_inline_set(handle, inode, &i, &is);
302
+ error = ext4_xattr_ibody_set(handle, inode, &i, &is);
294303 if (error) {
295304 if (error == -ENOSPC)
296305 ext4_clear_inode_state(inode,
....@@ -350,7 +359,7 @@
350359
351360 error = ext4_xattr_ibody_get(inode, i.name_index, i.name,
352361 value, len);
353
- if (error == -ENODATA)
362
+ if (error < 0)
354363 goto out;
355364
356365 BUFFER_TRACE(is.iloc.bh, "get_write_access");
....@@ -362,7 +371,7 @@
362371 i.value = value;
363372 i.value_len = len;
364373
365
- error = ext4_xattr_ibody_inline_set(handle, inode, &i, &is);
374
+ error = ext4_xattr_ibody_set(handle, inode, &i, &is);
366375 if (error)
367376 goto out;
368377
....@@ -435,7 +444,7 @@
435444 if (error)
436445 goto out;
437446
438
- error = ext4_xattr_ibody_inline_set(handle, inode, &i, &is);
447
+ error = ext4_xattr_ibody_set(handle, inode, &i, &is);
439448 if (error)
440449 goto out;
441450
....@@ -813,7 +822,7 @@
813822 * clear the inode state safely.
814823 * 2. The inode has inline data, then we need to read the data, make it
815824 * update and dirty so that ext4_da_writepages can handle it. We don't
816
- * need to start the journal since the file's metatdata isn't changed now.
825
+ * need to start the journal since the file's metadata isn't changed now.
817826 */
818827 static int ext4_da_convert_inline_data_to_extent(struct address_space *mapping,
819828 struct inode *inode,
....@@ -1187,6 +1196,7 @@
11871196 ext4_initialize_dirent_tail(dir_block,
11881197 inode->i_sb->s_blocksize);
11891198 set_buffer_uptodate(dir_block);
1199
+ unlock_buffer(dir_block);
11901200 err = ext4_handle_dirty_dirblock(handle, inode, dir_block);
11911201 if (err)
11921202 return err;
....@@ -1260,6 +1270,7 @@
12601270 if (!S_ISDIR(inode->i_mode)) {
12611271 memcpy(data_bh->b_data, buf, inline_size);
12621272 set_buffer_uptodate(data_bh);
1273
+ unlock_buffer(data_bh);
12631274 error = ext4_handle_dirty_metadata(handle,
12641275 inode, data_bh);
12651276 } else {
....@@ -1267,7 +1278,6 @@
12671278 buf, inline_size);
12681279 }
12691280
1270
- unlock_buffer(data_bh);
12711281 out_restore:
12721282 if (error)
12731283 ext4_restore_inline_data(handle, inode, iloc, buf, inline_size);
....@@ -1950,8 +1960,7 @@
19501960 i.value = value;
19511961 i.value_len = i_size > EXT4_MIN_INLINE_DATA_SIZE ?
19521962 i_size - EXT4_MIN_INLINE_DATA_SIZE : 0;
1953
- err = ext4_xattr_ibody_inline_set(handle, inode,
1954
- &i, &is);
1963
+ err = ext4_xattr_ibody_set(handle, inode, &i, &is);
19551964 if (err)
19561965 goto out_error;
19571966 }