From: Andreas Gruenbacher * ext[23]_xattr_list(): - Before inserting an xattr block into the cache, make sure that the block is not corrupted. The check got moved after inserting into the cache in the xattr consolidation patches, so corrupted blocks could become visible to cache users. - Take a variable out of the loop that calls the ->list handlers. * A few cosmetical changes. Signed-off-by: Andreas Gruenbacher Signed-off-by: Andrew Morton --- 25-akpm/fs/ext2/acl.c | 4 ++-- 25-akpm/fs/ext2/xattr.c | 35 +++++++++++++++++++---------------- 25-akpm/fs/ext2/xattr_security.c | 2 +- 25-akpm/fs/ext2/xattr_trusted.c | 2 +- 25-akpm/fs/ext2/xattr_user.c | 2 +- 25-akpm/fs/ext3/acl.c | 4 ++-- 25-akpm/fs/ext3/xattr.c | 35 +++++++++++++++++++---------------- 25-akpm/fs/ext3/xattr_security.c | 2 +- 25-akpm/fs/ext3/xattr_trusted.c | 2 +- 25-akpm/fs/ext3/xattr_user.c | 2 +- 25-akpm/fs/xattr.c | 3 ++- 11 files changed, 50 insertions(+), 43 deletions(-) diff -puN fs/ext2/acl.c~xattr-reintroduce-sanity-checks-2 fs/ext2/acl.c --- 25/fs/ext2/acl.c~xattr-reintroduce-sanity-checks-2 2004-09-24 19:50:57.343083216 -0700 +++ 25-akpm/fs/ext2/acl.c 2004-09-24 19:50:57.359080784 -0700 @@ -400,7 +400,7 @@ ext2_xattr_list_acl_access(struct inode if (!test_opt(inode->i_sb, POSIX_ACL)) return 0; - if (list && (size <= list_size)) + if (list && size <= list_size) memcpy(list, XATTR_NAME_ACL_ACCESS, size); return size; } @@ -413,7 +413,7 @@ ext2_xattr_list_acl_default(struct inode if (!test_opt(inode->i_sb, POSIX_ACL)) return 0; - if (list && (size <= list_size)) + if (list && size <= list_size) memcpy(list, XATTR_NAME_ACL_DEFAULT, size); return size; } diff -puN fs/ext2/xattr.c~xattr-reintroduce-sanity-checks-2 fs/ext2/xattr.c --- 25/fs/ext2/xattr.c~xattr-reintroduce-sanity-checks-2 2004-09-24 19:50:57.344083064 -0700 +++ 25-akpm/fs/ext2/xattr.c 2004-09-24 19:50:57.360080632 -0700 @@ -270,8 +270,8 @@ ext2_xattr_list(struct inode *inode, cha { struct buffer_head *bh = NULL; struct ext2_xattr_entry *entry; - size_t total_size = 0; - char *buf, *end; + char *end; + size_t rest = buffer_size; int error; ea_idebug(inode, "buffer=%p, buffer_size=%ld", @@ -298,36 +298,39 @@ bad_block: ext2_error(inode->i_sb, "ext2 goto cleanup; } + /* check the on-disk data structure */ + entry = FIRST_ENTRY(bh); + while (!IS_LAST_ENTRY(entry)) { + struct ext2_xattr_entry *next = EXT2_XATTR_NEXT(entry); + + if ((char *)next >= end) + goto bad_block; + entry = next; + } if (ext2_xattr_cache_insert(bh)) ea_idebug(inode, "cache insert failed"); /* list the attribute names */ - buf = buffer; for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry); entry = EXT2_XATTR_NEXT(entry)) { - struct xattr_handler *handler; - struct ext2_xattr_entry *next = EXT2_XATTR_NEXT(entry); - - if ((char *)next >= end) - goto bad_block; + struct xattr_handler *handler = + ext2_xattr_handler(entry->e_name_index); - handler = ext2_xattr_handler(entry->e_name_index); if (handler) { - size_t size = handler->list(inode, buf, buffer_size, + size_t size = handler->list(inode, buffer, rest, entry->e_name, entry->e_name_len); - if (buf) { - if (size > buffer_size) { + if (buffer) { + if (size > rest) { error = -ERANGE; goto cleanup; } - buf += size; - buffer_size -= size; + buffer += size; } - total_size += size; + rest -= size; } } - error = total_size; + error = buffer_size - rest; /* total size */ cleanup: brelse(bh); diff -puN fs/ext2/xattr_security.c~xattr-reintroduce-sanity-checks-2 fs/ext2/xattr_security.c --- 25/fs/ext2/xattr_security.c~xattr-reintroduce-sanity-checks-2 2004-09-24 19:50:57.346082760 -0700 +++ 25-akpm/fs/ext2/xattr_security.c 2004-09-24 19:50:57.361080480 -0700 @@ -17,7 +17,7 @@ ext2_xattr_security_list(struct inode *i const int prefix_len = sizeof(XATTR_SECURITY_PREFIX)-1; const size_t total_len = prefix_len + name_len + 1; - if (list && (total_len <= list_size)) { + if (list && total_len <= list_size) { memcpy(list, XATTR_SECURITY_PREFIX, prefix_len); memcpy(list+prefix_len, name, name_len); list[prefix_len + name_len] = '\0'; diff -puN fs/ext2/xattr_trusted.c~xattr-reintroduce-sanity-checks-2 fs/ext2/xattr_trusted.c --- 25/fs/ext2/xattr_trusted.c~xattr-reintroduce-sanity-checks-2 2004-09-24 19:50:57.347082608 -0700 +++ 25-akpm/fs/ext2/xattr_trusted.c 2004-09-24 19:50:57.361080480 -0700 @@ -24,7 +24,7 @@ ext2_xattr_trusted_list(struct inode *in if (!capable(CAP_SYS_ADMIN)) return 0; - if (list && (total_len <= list_size)) { + if (list && total_len <= list_size) { memcpy(list, XATTR_TRUSTED_PREFIX, prefix_len); memcpy(list+prefix_len, name, name_len); list[prefix_len + name_len] = '\0'; diff -puN fs/ext2/xattr_user.c~xattr-reintroduce-sanity-checks-2 fs/ext2/xattr_user.c --- 25/fs/ext2/xattr_user.c~xattr-reintroduce-sanity-checks-2 2004-09-24 19:50:57.348082456 -0700 +++ 25-akpm/fs/ext2/xattr_user.c 2004-09-24 19:50:57.361080480 -0700 @@ -23,7 +23,7 @@ ext2_xattr_user_list(struct inode *inode if (!test_opt(inode->i_sb, XATTR_USER)) return 0; - if (list && (total_len <= list_size)) { + if (list && total_len <= list_size) { memcpy(list, XATTR_USER_PREFIX, prefix_len); memcpy(list+prefix_len, name, name_len); list[prefix_len + name_len] = '\0'; diff -puN fs/ext3/acl.c~xattr-reintroduce-sanity-checks-2 fs/ext3/acl.c --- 25/fs/ext3/acl.c~xattr-reintroduce-sanity-checks-2 2004-09-24 19:50:57.349082304 -0700 +++ 25-akpm/fs/ext3/acl.c 2004-09-24 19:50:57.362080328 -0700 @@ -423,7 +423,7 @@ ext3_xattr_list_acl_access(struct inode if (!test_opt(inode->i_sb, POSIX_ACL)) return 0; - if (list && (size <= list_len)) + if (list && size <= list_len) memcpy(list, XATTR_NAME_ACL_ACCESS, size); return size; } @@ -436,7 +436,7 @@ ext3_xattr_list_acl_default(struct inode if (!test_opt(inode->i_sb, POSIX_ACL)) return 0; - if (list && (size <= list_len)) + if (list && size <= list_len) memcpy(list, XATTR_NAME_ACL_DEFAULT, size); return size; } diff -puN fs/ext3/xattr.c~xattr-reintroduce-sanity-checks-2 fs/ext3/xattr.c --- 25/fs/ext3/xattr.c~xattr-reintroduce-sanity-checks-2 2004-09-24 19:50:57.351082000 -0700 +++ 25-akpm/fs/ext3/xattr.c 2004-09-24 19:50:57.363080176 -0700 @@ -267,8 +267,8 @@ ext3_xattr_list(struct inode *inode, cha { struct buffer_head *bh = NULL; struct ext3_xattr_entry *entry; - size_t total_size = 0; - char *buf, *end; + char *end; + size_t rest = buffer_size; int error; ea_idebug(inode, "buffer=%p, buffer_size=%ld", @@ -295,36 +295,39 @@ bad_block: ext3_error(inode->i_sb, "ext3 goto cleanup; } + /* check the on-disk data structure */ + entry = FIRST_ENTRY(bh); + while (!IS_LAST_ENTRY(entry)) { + struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(entry); + + if ((char *)next >= end) + goto bad_block; + entry = next; + } if (ext3_xattr_cache_insert(bh)) ea_idebug(inode, "cache insert failed"); /* list the attribute names */ - buf = buffer; for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry); entry = EXT3_XATTR_NEXT(entry)) { - struct xattr_handler *handler; - struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(entry); - - if ((char *)next >= end) - goto bad_block; + struct xattr_handler *handler = + ext3_xattr_handler(entry->e_name_index); - handler = ext3_xattr_handler(entry->e_name_index); if (handler) { - size_t size = handler->list(inode, buf, buffer_size, + size_t size = handler->list(inode, buffer, rest, entry->e_name, entry->e_name_len); - if (buf) { - if (size > buffer_size) { + if (buffer) { + if (size > rest) { error = -ERANGE; goto cleanup; } - buf += size; - buffer_size -= size; + buffer += size; } - total_size += size; + rest -= size; } } - error = total_size; + error = buffer_size - rest; /* total size */ cleanup: brelse(bh); diff -puN fs/ext3/xattr_security.c~xattr-reintroduce-sanity-checks-2 fs/ext3/xattr_security.c --- 25/fs/ext3/xattr_security.c~xattr-reintroduce-sanity-checks-2 2004-09-24 19:50:57.352081848 -0700 +++ 25-akpm/fs/ext3/xattr_security.c 2004-09-24 19:50:57.363080176 -0700 @@ -19,7 +19,7 @@ ext3_xattr_security_list(struct inode *i const size_t total_len = prefix_len + name_len + 1; - if (list && (total_len <= list_size)) { + if (list && total_len <= list_size) { memcpy(list, XATTR_SECURITY_PREFIX, prefix_len); memcpy(list+prefix_len, name, name_len); list[prefix_len + name_len] = '\0'; diff -puN fs/ext3/xattr_trusted.c~xattr-reintroduce-sanity-checks-2 fs/ext3/xattr_trusted.c --- 25/fs/ext3/xattr_trusted.c~xattr-reintroduce-sanity-checks-2 2004-09-24 19:50:57.353081696 -0700 +++ 25-akpm/fs/ext3/xattr_trusted.c 2004-09-24 19:50:57.364080024 -0700 @@ -25,7 +25,7 @@ ext3_xattr_trusted_list(struct inode *in if (!capable(CAP_SYS_ADMIN)) return 0; - if (list && (total_len <= list_size)) { + if (list && total_len <= list_size) { memcpy(list, XATTR_TRUSTED_PREFIX, prefix_len); memcpy(list+prefix_len, name, name_len); list[prefix_len + name_len] = '\0'; diff -puN fs/ext3/xattr_user.c~xattr-reintroduce-sanity-checks-2 fs/ext3/xattr_user.c --- 25/fs/ext3/xattr_user.c~xattr-reintroduce-sanity-checks-2 2004-09-24 19:50:57.355081392 -0700 +++ 25-akpm/fs/ext3/xattr_user.c 2004-09-24 19:50:57.364080024 -0700 @@ -25,7 +25,7 @@ ext3_xattr_user_list(struct inode *inode if (!test_opt(inode->i_sb, XATTR_USER)) return 0; - if (list && (total_len <= list_size)) { + if (list && total_len <= list_size) { memcpy(list, XATTR_USER_PREFIX, prefix_len); memcpy(list+prefix_len, name, name_len); list[prefix_len + name_len] = '\0'; diff -puN fs/xattr.c~xattr-reintroduce-sanity-checks-2 fs/xattr.c --- 25/fs/xattr.c~xattr-reintroduce-sanity-checks-2 2004-09-24 19:50:57.356081240 -0700 +++ 25-akpm/fs/xattr.c 2004-09-24 19:50:57.365079872 -0700 @@ -352,7 +352,8 @@ sys_fremovexattr(int fd, char __user *na } -static const char *strcmp_prefix(const char *a, const char *a_prefix) +static const char * +strcmp_prefix(const char *a, const char *a_prefix) { while (*a_prefix && *a == *a_prefix) { a++; _