* [PATCH 0/2] ocfs2: add checks in ocfs2_xattr_find_entry() to avoid potential out-of-bound access.
@ 2024-05-15 13:29 Ferry Meng
2024-05-15 13:29 ` [PATCH 1/2] ocfs2: add bounds checking to ocfs2_xattr_find_entry() Ferry Meng
2024-05-15 13:29 ` [PATCH 2/2] ocfs2: strict bound check before memcmp in ocfs2_xattr_find_entry() Ferry Meng
0 siblings, 2 replies; 5+ messages in thread
From: Ferry Meng @ 2024-05-15 13:29 UTC (permalink / raw)
To: Mark Fasheh, Joel Becker, Joseph Qi, ocfs2-devel; +Cc: linux-kernel, Ferry Meng
Hi, all:
This patch series attempts to address a scenario where accessing user-defined
xattrs in a carefully crafted image can lead to out-of-bound access.(To speak
truthfully, I do not think this vehavior would occur under proper usage.)
In my testing environment, I constructed an OCFS2 image, created a file with
several user-defined xattrs(long name attributes, this will cause a "Non-INLINE"
xattr, which requires additional space for storage), and then forcibly modified
the xe_name_offset using a binary editing tool (e.g "hexedit"). Upon remounting
the image and running 'getfattr -d /path/to/file', this patchset was able to
detect "partial" malicious modification.
Comments and feedbacks are welcomed.
Ferry Meng (2):
ocfs2: add bounds checking to ocfs2_xattr_find_entry()
ocfs2: strict bound check before memcmp in ocfs2_xattr_find_entry()
fs/ocfs2/xattr.c | 21 +++++++++++++++------
1 file changed, 15 insertions(+), 6 deletions(-)
--
2.32.0.3.g01195cf9f
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 1/2] ocfs2: add bounds checking to ocfs2_xattr_find_entry()
2024-05-15 13:29 [PATCH 0/2] ocfs2: add checks in ocfs2_xattr_find_entry() to avoid potential out-of-bound access Ferry Meng
@ 2024-05-15 13:29 ` Ferry Meng
2024-05-16 1:25 ` Joseph Qi
2024-05-15 13:29 ` [PATCH 2/2] ocfs2: strict bound check before memcmp in ocfs2_xattr_find_entry() Ferry Meng
1 sibling, 1 reply; 5+ messages in thread
From: Ferry Meng @ 2024-05-15 13:29 UTC (permalink / raw)
To: Mark Fasheh, Joel Becker, Joseph Qi, ocfs2-devel; +Cc: linux-kernel, Ferry Meng
Just add redundant (perhaps paranoia) checks to make sure it doesn't
stray beyond valid meory region of ocfs2 xattr entry array during a
single match.
Maybe this patch can prevent some crash caused by crafted poison images.
Signed-off-by: Ferry Meng <mengferry@linux.alibaba.com>
---
fs/ocfs2/xattr.c | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c
index 3b81213ed7b8..37be4a286faf 100644
--- a/fs/ocfs2/xattr.c
+++ b/fs/ocfs2/xattr.c
@@ -1062,8 +1062,8 @@ ssize_t ocfs2_listxattr(struct dentry *dentry,
return i_ret + b_ret;
}
-static int ocfs2_xattr_find_entry(int name_index,
- const char *name,
+static int ocfs2_xattr_find_entry(struct inode *inode, void *end,
+ int name_index, const char *name,
struct ocfs2_xattr_search *xs)
{
struct ocfs2_xattr_entry *entry;
@@ -1076,6 +1076,10 @@ static int ocfs2_xattr_find_entry(int name_index,
name_len = strlen(name);
entry = xs->here;
for (i = 0; i < le16_to_cpu(xs->header->xh_count); i++) {
+ if ((void *)entry >= end) {
+ ocfs2_error(inode->i_sb, "corrupted xattr entries");
+ return -EFSCORRUPTED;
+ }
cmp = name_index - ocfs2_xattr_get_type(entry);
if (!cmp)
cmp = name_len - entry->xe_name_len;
@@ -1166,7 +1170,7 @@ static int ocfs2_xattr_ibody_get(struct inode *inode,
xs->base = (void *)xs->header;
xs->here = xs->header->xh_entries;
- ret = ocfs2_xattr_find_entry(name_index, name, xs);
+ ret = ocfs2_xattr_find_entry(inode, xs->end, name_index, name, xs);
if (ret)
return ret;
size = le64_to_cpu(xs->here->xe_value_size);
@@ -2698,7 +2702,7 @@ static int ocfs2_xattr_ibody_find(struct inode *inode,
/* Find the named attribute. */
if (oi->ip_dyn_features & OCFS2_INLINE_XATTR_FL) {
- ret = ocfs2_xattr_find_entry(name_index, name, xs);
+ ret = ocfs2_xattr_find_entry(inode, xs->end, name_index, name, xs);
if (ret && ret != -ENODATA)
return ret;
xs->not_found = ret;
@@ -2833,7 +2837,7 @@ static int ocfs2_xattr_block_find(struct inode *inode,
xs->end = (void *)(blk_bh->b_data) + blk_bh->b_size;
xs->here = xs->header->xh_entries;
- ret = ocfs2_xattr_find_entry(name_index, name, xs);
+ ret = ocfs2_xattr_find_entry(inode, xs->end, name_index, name, xs);
} else
ret = ocfs2_xattr_index_block_find(inode, blk_bh,
name_index,
--
2.32.0.3.g01195cf9f
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 2/2] ocfs2: strict bound check before memcmp in ocfs2_xattr_find_entry()
2024-05-15 13:29 [PATCH 0/2] ocfs2: add checks in ocfs2_xattr_find_entry() to avoid potential out-of-bound access Ferry Meng
2024-05-15 13:29 ` [PATCH 1/2] ocfs2: add bounds checking to ocfs2_xattr_find_entry() Ferry Meng
@ 2024-05-15 13:29 ` Ferry Meng
2024-05-16 1:41 ` Joseph Qi
1 sibling, 1 reply; 5+ messages in thread
From: Ferry Meng @ 2024-05-15 13:29 UTC (permalink / raw)
To: Mark Fasheh, Joel Becker, Joseph Qi, ocfs2-devel; +Cc: linux-kernel, Ferry Meng
xattr in ocfs2 maybe not INLINE, but saved with additional space
requested. It's better to check if the memory is out of bound before
memcmp, although this possibility mainly comes from custom poisonous
images.
Signed-off-by: Ferry Meng <mengferry@linux.alibaba.com>
---
fs/ocfs2/xattr.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c
index 37be4a286faf..4ceb0cb4cb71 100644
--- a/fs/ocfs2/xattr.c
+++ b/fs/ocfs2/xattr.c
@@ -1083,10 +1083,15 @@ static int ocfs2_xattr_find_entry(struct inode *inode, void *end,
cmp = name_index - ocfs2_xattr_get_type(entry);
if (!cmp)
cmp = name_len - entry->xe_name_len;
- if (!cmp)
+ if (!cmp) {
+ if ((xs->base + le16_to_cpu(entry->xe_name_offset) + name_len) > end) {
+ ocfs2_error(inode->i_sb, "corrupted xattr entries");
+ return -EFSCORRUPTED;
+ }
cmp = memcmp(name, (xs->base +
le16_to_cpu(entry->xe_name_offset)),
name_len);
+ }
if (cmp == 0)
break;
entry += 1;
--
2.32.0.3.g01195cf9f
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH 1/2] ocfs2: add bounds checking to ocfs2_xattr_find_entry()
2024-05-15 13:29 ` [PATCH 1/2] ocfs2: add bounds checking to ocfs2_xattr_find_entry() Ferry Meng
@ 2024-05-16 1:25 ` Joseph Qi
0 siblings, 0 replies; 5+ messages in thread
From: Joseph Qi @ 2024-05-16 1:25 UTC (permalink / raw)
To: Ferry Meng, Mark Fasheh, Joel Becker, ocfs2-devel; +Cc: linux-kernel
On 5/15/24 9:29 PM, Ferry Meng wrote:
> Just add redundant (perhaps paranoia) checks to make sure it doesn't
> stray beyond valid meory region of ocfs2 xattr entry array during a
> single match.
>
> Maybe this patch can prevent some crash caused by crafted poison images.
>
I'd rather restructure the commit message as below:
Add a paranoia check to make sure it doesn't stray beyond valid memory
region containing ocfs2 xattr entries when scanning for a match.
It will prevent out-of-bound access in case of crafted images.
> Signed-off-by: Ferry Meng <mengferry@linux.alibaba.com>
> ---
> fs/ocfs2/xattr.c | 14 +++++++++-----
> 1 file changed, 9 insertions(+), 5 deletions(-)
>
> diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c
> index 3b81213ed7b8..37be4a286faf 100644
> --- a/fs/ocfs2/xattr.c
> +++ b/fs/ocfs2/xattr.c
> @@ -1062,8 +1062,8 @@ ssize_t ocfs2_listxattr(struct dentry *dentry,
> return i_ret + b_ret;
> }
>
> -static int ocfs2_xattr_find_entry(int name_index,
> - const char *name,
> +static int ocfs2_xattr_find_entry(struct inode *inode, void *end,
'end' can be obtained from ocfs2_xattr_search directly.
Thanks,
Joseph
> + int name_index, const char *name,
> struct ocfs2_xattr_search *xs)
> {
> struct ocfs2_xattr_entry *entry;
> @@ -1076,6 +1076,10 @@ static int ocfs2_xattr_find_entry(int name_index,
> name_len = strlen(name);
> entry = xs->here;
> for (i = 0; i < le16_to_cpu(xs->header->xh_count); i++) {
> + if ((void *)entry >= end) {
> + ocfs2_error(inode->i_sb, "corrupted xattr entries");
> + return -EFSCORRUPTED;
> + }
> cmp = name_index - ocfs2_xattr_get_type(entry);
> if (!cmp)
> cmp = name_len - entry->xe_name_len;
> @@ -1166,7 +1170,7 @@ static int ocfs2_xattr_ibody_get(struct inode *inode,
> xs->base = (void *)xs->header;
> xs->here = xs->header->xh_entries;
>
> - ret = ocfs2_xattr_find_entry(name_index, name, xs);
> + ret = ocfs2_xattr_find_entry(inode, xs->end, name_index, name, xs);
> if (ret)
> return ret;
> size = le64_to_cpu(xs->here->xe_value_size);
> @@ -2698,7 +2702,7 @@ static int ocfs2_xattr_ibody_find(struct inode *inode,
>
> /* Find the named attribute. */
> if (oi->ip_dyn_features & OCFS2_INLINE_XATTR_FL) {
> - ret = ocfs2_xattr_find_entry(name_index, name, xs);
> + ret = ocfs2_xattr_find_entry(inode, xs->end, name_index, name, xs);
> if (ret && ret != -ENODATA)
> return ret;
> xs->not_found = ret;
> @@ -2833,7 +2837,7 @@ static int ocfs2_xattr_block_find(struct inode *inode,
> xs->end = (void *)(blk_bh->b_data) + blk_bh->b_size;
> xs->here = xs->header->xh_entries;
>
> - ret = ocfs2_xattr_find_entry(name_index, name, xs);
> + ret = ocfs2_xattr_find_entry(inode, xs->end, name_index, name, xs);
> } else
> ret = ocfs2_xattr_index_block_find(inode, blk_bh,
> name_index,
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH 2/2] ocfs2: strict bound check before memcmp in ocfs2_xattr_find_entry()
2024-05-15 13:29 ` [PATCH 2/2] ocfs2: strict bound check before memcmp in ocfs2_xattr_find_entry() Ferry Meng
@ 2024-05-16 1:41 ` Joseph Qi
0 siblings, 0 replies; 5+ messages in thread
From: Joseph Qi @ 2024-05-16 1:41 UTC (permalink / raw)
To: Ferry Meng, Mark Fasheh, Joel Becker, ocfs2-devel; +Cc: linux-kernel
On 5/15/24 9:29 PM, Ferry Meng wrote:
> xattr in ocfs2 maybe not INLINE, but saved with additional space
> requested. It's better to check if the memory is out of bound before
> memcmp, although this possibility mainly comes from custom poisonous
> images.
Specifically, this only addresses the case non-indexed xattr.
>
> Signed-off-by: Ferry Meng <mengferry@linux.alibaba.com>
> ---
> fs/ocfs2/xattr.c | 7 ++++++-
> 1 file changed, 6 insertions(+), 1 deletion(-)
>
> diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c
> index 37be4a286faf..4ceb0cb4cb71 100644
> --- a/fs/ocfs2/xattr.c
> +++ b/fs/ocfs2/xattr.c
> @@ -1083,10 +1083,15 @@ static int ocfs2_xattr_find_entry(struct inode *inode, void *end,
> cmp = name_index - ocfs2_xattr_get_type(entry);
Or define a local variable 'offset' for le16_to_cpu(entry->xe_name_offset).
Thanks,
Joseph
> if (!cmp)
> cmp = name_len - entry->xe_name_len;
> - if (!cmp)
> + if (!cmp) {
> + if ((xs->base + le16_to_cpu(entry->xe_name_offset) + name_len) > end) {
> + ocfs2_error(inode->i_sb, "corrupted xattr entries");
> + return -EFSCORRUPTED;
> + }
> cmp = memcmp(name, (xs->base +
> le16_to_cpu(entry->xe_name_offset)),
> name_len);
> + }
> if (cmp == 0)
> break;
> entry += 1;
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2024-05-16 1:42 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-05-15 13:29 [PATCH 0/2] ocfs2: add checks in ocfs2_xattr_find_entry() to avoid potential out-of-bound access Ferry Meng
2024-05-15 13:29 ` [PATCH 1/2] ocfs2: add bounds checking to ocfs2_xattr_find_entry() Ferry Meng
2024-05-16 1:25 ` Joseph Qi
2024-05-15 13:29 ` [PATCH 2/2] ocfs2: strict bound check before memcmp in ocfs2_xattr_find_entry() Ferry Meng
2024-05-16 1:41 ` Joseph Qi
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox