mirror of
https://github.com/kdave/btrfs-progs
synced 2025-05-16 23:08:38 +00:00
btrfs-progs: check: add check for overlong xattr names
While working on my Windows driver, I found that it was inadvertently allowing users to create xattrs with names longer than 255 bytes, which wasn't being picked up by btrfs-check. If the Linux driver encounters a file with an invalid xattr like this, it makes the whole directory it's in inaccessible. If it's the root directory, it'll refuse to mount the filesystem entirely. Pull-request: #456 Signed-off-by: Mark Harmstone <mark@harmstone.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
f9659c7235
commit
ef194732d5
49
check/main.c
49
check/main.c
@ -627,6 +627,8 @@ static void print_inode_error(struct btrfs_root *root, struct inode_record *rec)
|
||||
if (errors & I_ERR_INVALID_NLINK)
|
||||
fprintf(stderr, ", directory has invalid nlink %d",
|
||||
rec->nlink);
|
||||
if (errors & I_ERR_INVALID_XATTR)
|
||||
fprintf(stderr, ", invalid xattr");
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
/* Print the holes if needed */
|
||||
@ -1473,6 +1475,50 @@ next:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int process_xattr_item(struct extent_buffer *eb,
|
||||
int slot, struct btrfs_key *key,
|
||||
struct shared_node *active_node)
|
||||
{
|
||||
u32 total;
|
||||
u32 cur = 0;
|
||||
struct btrfs_dir_item *di;
|
||||
struct inode_record *rec;
|
||||
|
||||
rec = active_node->current;
|
||||
|
||||
di = btrfs_item_ptr(eb, slot, struct btrfs_dir_item);
|
||||
total = btrfs_item_size(eb, slot);
|
||||
while (cur < total) {
|
||||
u32 name_len = btrfs_dir_name_len(eb, di);
|
||||
u32 data_len = btrfs_dir_data_len(eb, di);
|
||||
u32 len;
|
||||
|
||||
if (name_len > BTRFS_NAME_LEN) {
|
||||
char *name = malloc(name_len);
|
||||
|
||||
if (!name)
|
||||
return -ENOMEM;
|
||||
|
||||
read_extent_buffer(eb, name,
|
||||
(unsigned long)(di + 1), name_len);
|
||||
|
||||
fprintf(stderr,
|
||||
"inode %llu has overlong xattr name %.*s\n",
|
||||
key->objectid, name_len, name);
|
||||
|
||||
free(name);
|
||||
|
||||
rec->errors |= I_ERR_INVALID_XATTR;
|
||||
}
|
||||
|
||||
len = sizeof(*di) + name_len + data_len;
|
||||
di = (struct btrfs_dir_item *)((char *)di + len);
|
||||
cur += len;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int process_inode_ref(struct extent_buffer *eb,
|
||||
int slot, struct btrfs_key *key,
|
||||
struct shared_node *active_node)
|
||||
@ -1740,6 +1786,9 @@ static int process_one_leaf(struct btrfs_root *root, struct extent_buffer *eb,
|
||||
ret = process_file_extent(root, eb, i, &key,
|
||||
active_node);
|
||||
break;
|
||||
case BTRFS_XATTR_ITEM_KEY:
|
||||
ret = process_xattr_item(eb, i, &key, active_node);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
|
@ -187,6 +187,7 @@ struct unaligned_extent_rec_t {
|
||||
#define I_ERR_INVALID_IMODE (1 << 19)
|
||||
#define I_ERR_INVALID_GEN (1 << 20)
|
||||
#define I_ERR_INVALID_NLINK (1 << 21)
|
||||
#define I_ERR_INVALID_XATTR (1 << 22)
|
||||
|
||||
struct inode_record {
|
||||
struct list_head backrefs;
|
||||
|
Loading…
Reference in New Issue
Block a user