linux-ext4.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/3 v2] ext2: Cleanup ext2_xattr_set()
@ 2019-05-16 10:03 Jan Kara
  2019-05-16 10:03 ` [PATCH 1/3] ext2: introduce helper for xattr entry validation Jan Kara
                   ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: Jan Kara @ 2019-05-16 10:03 UTC (permalink / raw)
  To: linux-ext4; +Cc: cgxu519, Jan Kara

Hello,

this series contains updated patch from Chengguang and two additional cleanups
to xattr code in ext2_xattr_set() to remove some duplicated code and useless
checks.

Changes since v1:
* fixed patch 2 to maintain sorting of xattrs in ext2_xattr_set
* made loops in ext2_xattr_get() and ext2_xattr_list() also check all seen
  xattr entries

								Honza

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 1/3] ext2: introduce helper for xattr entry validation
  2019-05-16 10:03 [PATCH 0/3 v2] ext2: Cleanup ext2_xattr_set() Jan Kara
@ 2019-05-16 10:03 ` Jan Kara
  2019-05-16 10:03 ` [PATCH 2/3] ext2: Merge loops in ext2_xattr_set() Jan Kara
  2019-05-16 10:03 ` [PATCH 3/3] ext2: Strengthen xattr block checks Jan Kara
  2 siblings, 0 replies; 9+ messages in thread
From: Jan Kara @ 2019-05-16 10:03 UTC (permalink / raw)
  To: linux-ext4; +Cc: cgxu519, Jan Kara

From: Chengguang Xu <cgxu519@zoho.com.cn>

Introduce helper function ext2_xattr_entry_valid()
for xattr entry validation and clean up the entry
check related code.

Reviewed-by: Andreas Dilger <adilger@dilger.ca>
Signed-off-by: Chengguang Xu <cgxu519@zoho.com.cn>
Signed-off-by: Jan Kara <jack@suse.cz>
---
 fs/ext2/xattr.c | 32 +++++++++++++++++++++-----------
 1 file changed, 21 insertions(+), 11 deletions(-)

diff --git a/fs/ext2/xattr.c b/fs/ext2/xattr.c
index db27260d6a5b..fb2e008d4406 100644
--- a/fs/ext2/xattr.c
+++ b/fs/ext2/xattr.c
@@ -144,6 +144,22 @@ ext2_xattr_header_valid(struct ext2_xattr_header *header)
 	return true;
 }
 
+static bool
+ext2_xattr_entry_valid(struct ext2_xattr_entry *entry, size_t end_offs)
+{
+	size_t size;
+
+	if (entry->e_value_block != 0)
+		return false;
+
+	size = le32_to_cpu(entry->e_value_size);
+	if (size > end_offs ||
+	    le16_to_cpu(entry->e_value_offs) + size > end_offs)
+		return false;
+
+	return true;
+}
+
 /*
  * ext2_xattr_get()
  *
@@ -213,14 +229,10 @@ ext2_xattr_get(struct inode *inode, int name_index, const char *name,
 	error = -ENODATA;
 	goto cleanup;
 found:
-	/* check the buffer size */
-	if (entry->e_value_block != 0)
-		goto bad_block;
-	size = le32_to_cpu(entry->e_value_size);
-	if (size > inode->i_sb->s_blocksize ||
-	    le16_to_cpu(entry->e_value_offs) + size > inode->i_sb->s_blocksize)
+	if (!ext2_xattr_entry_valid(entry, inode->i_sb->s_blocksize))
 		goto bad_block;
 
+	size = le32_to_cpu(entry->e_value_size);
 	if (ext2_xattr_cache_insert(ea_block_cache, bh))
 		ea_idebug(inode, "cache insert failed");
 	if (buffer) {
@@ -481,12 +493,10 @@ ext2_xattr_set(struct inode *inode, int name_index, const char *name,
 		if (flags & XATTR_CREATE)
 			goto cleanup;
 		if (!here->e_value_block && here->e_value_size) {
-			size_t size = le32_to_cpu(here->e_value_size);
-
-			if (le16_to_cpu(here->e_value_offs) + size > 
-			    sb->s_blocksize || size > sb->s_blocksize)
+			if (!ext2_xattr_entry_valid(here, sb->s_blocksize))
 				goto bad_block;
-			free += EXT2_XATTR_SIZE(size);
+			free += EXT2_XATTR_SIZE(
+					le32_to_cpu(here->e_value_size));
 		}
 		free += EXT2_XATTR_LEN(name_len);
 	}
-- 
2.16.4


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 2/3] ext2: Merge loops in ext2_xattr_set()
  2019-05-16 10:03 [PATCH 0/3 v2] ext2: Cleanup ext2_xattr_set() Jan Kara
  2019-05-16 10:03 ` [PATCH 1/3] ext2: introduce helper for xattr entry validation Jan Kara
@ 2019-05-16 10:03 ` Jan Kara
  2019-05-16 11:11   ` cgxu519
  2019-05-16 10:03 ` [PATCH 3/3] ext2: Strengthen xattr block checks Jan Kara
  2 siblings, 1 reply; 9+ messages in thread
From: Jan Kara @ 2019-05-16 10:03 UTC (permalink / raw)
  To: linux-ext4; +Cc: cgxu519, Jan Kara

There are two very similar loops when searching xattr to set. Just merge
them.

Signed-off-by: Jan Kara <jack@suse.cz>
---
 fs/ext2/xattr.c | 41 +++++++++++++++++++----------------------
 1 file changed, 19 insertions(+), 22 deletions(-)

diff --git a/fs/ext2/xattr.c b/fs/ext2/xattr.c
index fb2e008d4406..f9fda6d16d78 100644
--- a/fs/ext2/xattr.c
+++ b/fs/ext2/xattr.c
@@ -436,28 +436,12 @@ ext2_xattr_set(struct inode *inode, int name_index, const char *name,
 			error = -EIO;
 			goto cleanup;
 		}
-		/* Find the named attribute. */
-		here = FIRST_ENTRY(bh);
-		while (!IS_LAST_ENTRY(here)) {
-			struct ext2_xattr_entry *next = EXT2_XATTR_NEXT(here);
-			if ((char *)next >= end)
-				goto bad_block;
-			if (!here->e_value_block && here->e_value_size) {
-				size_t offs = le16_to_cpu(here->e_value_offs);
-				if (offs < min_offs)
-					min_offs = offs;
-			}
-			not_found = name_index - here->e_name_index;
-			if (!not_found)
-				not_found = name_len - here->e_name_len;
-			if (!not_found)
-				not_found = memcmp(name, here->e_name,name_len);
-			if (not_found <= 0)
-				break;
-			here = next;
-		}
-		last = here;
-		/* We still need to compute min_offs and last. */
+		/*
+		 * Find the named attribute. If not found, 'here' will point
+		 * to entry where the new attribute should be inserted to
+		 * maintain sorting.
+		 */
+		last = FIRST_ENTRY(bh);
 		while (!IS_LAST_ENTRY(last)) {
 			struct ext2_xattr_entry *next = EXT2_XATTR_NEXT(last);
 			if ((char *)next >= end)
@@ -467,8 +451,21 @@ ext2_xattr_set(struct inode *inode, int name_index, const char *name,
 				if (offs < min_offs)
 					min_offs = offs;
 			}
+			if (not_found > 0) {
+				not_found = name_index - last->e_name_index;
+				if (!not_found)
+					not_found = name_len - last->e_name_len;
+				if (!not_found) {
+					not_found = memcmp(name, last->e_name,
+							   name_len);
+				}
+				if (not_found <= 0)
+					here = last;
+			}
 			last = next;
 		}
+		if (not_found > 0)
+			here = last;
 
 		/* Check whether we have enough space left. */
 		free = min_offs - ((char*)last - (char*)header) - sizeof(__u32);
-- 
2.16.4


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 3/3] ext2: Strengthen xattr block checks
  2019-05-16 10:03 [PATCH 0/3 v2] ext2: Cleanup ext2_xattr_set() Jan Kara
  2019-05-16 10:03 ` [PATCH 1/3] ext2: introduce helper for xattr entry validation Jan Kara
  2019-05-16 10:03 ` [PATCH 2/3] ext2: Merge loops in ext2_xattr_set() Jan Kara
@ 2019-05-16 10:03 ` Jan Kara
  2019-05-16 11:11   ` cgxu519
  2 siblings, 1 reply; 9+ messages in thread
From: Jan Kara @ 2019-05-16 10:03 UTC (permalink / raw)
  To: linux-ext4; +Cc: cgxu519, Jan Kara

Check every entry in xattr block for validity in ext2_xattr_set() to
detect on disk corruption early. Also since e_value_block field in xattr
entry is never != 0 in a valid filesystem, just remove checks for it
once we have established entries are valid.

Signed-off-by: Jan Kara <jack@suse.cz>
---
 fs/ext2/xattr.c | 22 ++++++++++------------
 1 file changed, 10 insertions(+), 12 deletions(-)

diff --git a/fs/ext2/xattr.c b/fs/ext2/xattr.c
index f9fda6d16d78..d21dbf297b74 100644
--- a/fs/ext2/xattr.c
+++ b/fs/ext2/xattr.c
@@ -218,6 +218,8 @@ ext2_xattr_get(struct inode *inode, int name_index, const char *name,
 			EXT2_XATTR_NEXT(entry);
 		if ((char *)next >= end)
 			goto bad_block;
+		if (!ext2_xattr_entry_valid(entry, inode->i_sb->s_blocksize))
+			goto bad_block;
 		if (name_index == entry->e_name_index &&
 		    name_len == entry->e_name_len &&
 		    memcmp(name, entry->e_name, name_len) == 0)
@@ -229,9 +231,6 @@ ext2_xattr_get(struct inode *inode, int name_index, const char *name,
 	error = -ENODATA;
 	goto cleanup;
 found:
-	if (!ext2_xattr_entry_valid(entry, inode->i_sb->s_blocksize))
-		goto bad_block;
-
 	size = le32_to_cpu(entry->e_value_size);
 	if (ext2_xattr_cache_insert(ea_block_cache, bh))
 		ea_idebug(inode, "cache insert failed");
@@ -304,6 +303,8 @@ ext2_xattr_list(struct dentry *dentry, char *buffer, size_t buffer_size)
 
 		if ((char *)next >= end)
 			goto bad_block;
+		if (!ext2_xattr_entry_valid(entry, inode->i_sb->s_blocksize))
+			goto bad_block;
 		entry = next;
 	}
 	if (ext2_xattr_cache_insert(ea_block_cache, bh))
@@ -446,7 +447,9 @@ ext2_xattr_set(struct inode *inode, int name_index, const char *name,
 			struct ext2_xattr_entry *next = EXT2_XATTR_NEXT(last);
 			if ((char *)next >= end)
 				goto bad_block;
-			if (!last->e_value_block && last->e_value_size) {
+			if (!ext2_xattr_entry_valid(last, sb->s_blocksize))
+				goto bad_block;
+			if (last->e_value_size) {
 				size_t offs = le16_to_cpu(last->e_value_offs);
 				if (offs < min_offs)
 					min_offs = offs;
@@ -489,12 +492,7 @@ ext2_xattr_set(struct inode *inode, int name_index, const char *name,
 		error = -EEXIST;
 		if (flags & XATTR_CREATE)
 			goto cleanup;
-		if (!here->e_value_block && here->e_value_size) {
-			if (!ext2_xattr_entry_valid(here, sb->s_blocksize))
-				goto bad_block;
-			free += EXT2_XATTR_SIZE(
-					le32_to_cpu(here->e_value_size));
-		}
+		free += EXT2_XATTR_SIZE(le32_to_cpu(here->e_value_size));
 		free += EXT2_XATTR_LEN(name_len);
 	}
 	error = -ENOSPC;
@@ -559,7 +557,7 @@ ext2_xattr_set(struct inode *inode, int name_index, const char *name,
 		here->e_name_len = name_len;
 		memcpy(here->e_name, name, name_len);
 	} else {
-		if (!here->e_value_block && here->e_value_size) {
+		if (here->e_value_size) {
 			char *first_val = (char *)header + min_offs;
 			size_t offs = le16_to_cpu(here->e_value_offs);
 			char *val = (char *)header + offs;
@@ -586,7 +584,7 @@ ext2_xattr_set(struct inode *inode, int name_index, const char *name,
 			last = ENTRY(header+1);
 			while (!IS_LAST_ENTRY(last)) {
 				size_t o = le16_to_cpu(last->e_value_offs);
-				if (!last->e_value_block && o < offs)
+				if (o < offs)
 					last->e_value_offs =
 						cpu_to_le16(o + size);
 				last = EXT2_XATTR_NEXT(last);
-- 
2.16.4


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH 2/3] ext2: Merge loops in ext2_xattr_set()
  2019-05-16 10:03 ` [PATCH 2/3] ext2: Merge loops in ext2_xattr_set() Jan Kara
@ 2019-05-16 11:11   ` cgxu519
  0 siblings, 0 replies; 9+ messages in thread
From: cgxu519 @ 2019-05-16 11:11 UTC (permalink / raw)
  To: Jan Kara, linux-ext4

On Thu, 2019-05-16 at 12:03 +0200, Jan Kara wrote:
> There are two very similar loops when searching xattr to set. Just merge
> them.
> 
> Signed-off-by: Jan Kara <jack@suse.cz>

Reviewed-by: Chengguang Xu <cgxu519@zoho.com.cn>


> ---
>  fs/ext2/xattr.c | 41 +++++++++++++++++++----------------------
>  1 file changed, 19 insertions(+), 22 deletions(-)
> 
> diff --git a/fs/ext2/xattr.c b/fs/ext2/xattr.c
> index fb2e008d4406..f9fda6d16d78 100644
> --- a/fs/ext2/xattr.c
> +++ b/fs/ext2/xattr.c
> @@ -436,28 +436,12 @@ ext2_xattr_set(struct inode *inode, int name_index,
> const char *name,
>  			error = -EIO;
>  			goto cleanup;
>  		}
> -		/* Find the named attribute. */
> -		here = FIRST_ENTRY(bh);
> -		while (!IS_LAST_ENTRY(here)) {
> -			struct ext2_xattr_entry *next = EXT2_XATTR_NEXT(here);
> -			if ((char *)next >= end)
> -				goto bad_block;
> -			if (!here->e_value_block && here->e_value_size) {
> -				size_t offs = le16_to_cpu(here->e_value_offs);
> -				if (offs < min_offs)
> -					min_offs = offs;
> -			}
> -			not_found = name_index - here->e_name_index;
> -			if (!not_found)
> -				not_found = name_len - here->e_name_len;
> -			if (!not_found)
> -				not_found = memcmp(name, here->e_name,name_len);
> -			if (not_found <= 0)
> -				break;
> -			here = next;
> -		}
> -		last = here;
> -		/* We still need to compute min_offs and last. */
> +		/*
> +		 * Find the named attribute. If not found, 'here' will point
> +		 * to entry where the new attribute should be inserted to
> +		 * maintain sorting.
> +		 */
> +		last = FIRST_ENTRY(bh);
>  		while (!IS_LAST_ENTRY(last)) {
>  			struct ext2_xattr_entry *next = EXT2_XATTR_NEXT(last);
>  			if ((char *)next >= end)
> @@ -467,8 +451,21 @@ ext2_xattr_set(struct inode *inode, int name_index, const
> char *name,
>  				if (offs < min_offs)
>  					min_offs = offs;
>  			}
> +			if (not_found > 0) {
> +				not_found = name_index - last->e_name_index;
> +				if (!not_found)
> +					not_found = name_len - last->e_name_len;
> +				if (!not_found) {
> +					not_found = memcmp(name, last->e_name,
> +							   name_len);
> +				}
> +				if (not_found <= 0)
> +					here = last;
> +			}
>  			last = next;
>  		}
> +		if (not_found > 0)
> +			here = last;
>  
>  		/* Check whether we have enough space left. */
>  		free = min_offs - ((char*)last - (char*)header) - sizeof(__u32);




^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 3/3] ext2: Strengthen xattr block checks
  2019-05-16 10:03 ` [PATCH 3/3] ext2: Strengthen xattr block checks Jan Kara
@ 2019-05-16 11:11   ` cgxu519
  0 siblings, 0 replies; 9+ messages in thread
From: cgxu519 @ 2019-05-16 11:11 UTC (permalink / raw)
  To: Jan Kara, linux-ext4

On Thu, 2019-05-16 at 12:03 +0200, Jan Kara wrote:
> Check every entry in xattr block for validity in ext2_xattr_set() to
> detect on disk corruption early. Also since e_value_block field in xattr
> entry is never != 0 in a valid filesystem, just remove checks for it
> once we have established entries are valid.
> 
> Signed-off-by: Jan Kara <jack@suse.cz>

Reviewed-by: Chengguang Xu <cgxu519@zoho.com.cn>

> ---
>  fs/ext2/xattr.c | 22 ++++++++++------------
>  1 file changed, 10 insertions(+), 12 deletions(-)
> 
> diff --git a/fs/ext2/xattr.c b/fs/ext2/xattr.c
> index f9fda6d16d78..d21dbf297b74 100644
> --- a/fs/ext2/xattr.c
> +++ b/fs/ext2/xattr.c
> @@ -218,6 +218,8 @@ ext2_xattr_get(struct inode *inode, int name_index, const
> char *name,
>  			EXT2_XATTR_NEXT(entry);
>  		if ((char *)next >= end)
>  			goto bad_block;
> +		if (!ext2_xattr_entry_valid(entry, inode->i_sb->s_blocksize))
> +			goto bad_block;
>  		if (name_index == entry->e_name_index &&
>  		    name_len == entry->e_name_len &&
>  		    memcmp(name, entry->e_name, name_len) == 0)
> @@ -229,9 +231,6 @@ ext2_xattr_get(struct inode *inode, int name_index, const
> char *name,
>  	error = -ENODATA;
>  	goto cleanup;
>  found:
> -	if (!ext2_xattr_entry_valid(entry, inode->i_sb->s_blocksize))
> -		goto bad_block;
> -
>  	size = le32_to_cpu(entry->e_value_size);
>  	if (ext2_xattr_cache_insert(ea_block_cache, bh))
>  		ea_idebug(inode, "cache insert failed");
> @@ -304,6 +303,8 @@ ext2_xattr_list(struct dentry *dentry, char *buffer,
> size_t buffer_size)
>  
>  		if ((char *)next >= end)
>  			goto bad_block;
> +		if (!ext2_xattr_entry_valid(entry, inode->i_sb->s_blocksize))
> +			goto bad_block;
>  		entry = next;
>  	}
>  	if (ext2_xattr_cache_insert(ea_block_cache, bh))
> @@ -446,7 +447,9 @@ ext2_xattr_set(struct inode *inode, int name_index, const
> char *name,
>  			struct ext2_xattr_entry *next = EXT2_XATTR_NEXT(last);
>  			if ((char *)next >= end)
>  				goto bad_block;
> -			if (!last->e_value_block && last->e_value_size) {
> +			if (!ext2_xattr_entry_valid(last, sb->s_blocksize))
> +				goto bad_block;
> +			if (last->e_value_size) {
>  				size_t offs = le16_to_cpu(last->e_value_offs);
>  				if (offs < min_offs)
>  					min_offs = offs;
> @@ -489,12 +492,7 @@ ext2_xattr_set(struct inode *inode, int name_index, const
> char *name,
>  		error = -EEXIST;
>  		if (flags & XATTR_CREATE)
>  			goto cleanup;
> -		if (!here->e_value_block && here->e_value_size) {
> -			if (!ext2_xattr_entry_valid(here, sb->s_blocksize))
> -				goto bad_block;
> -			free += EXT2_XATTR_SIZE(
> -					le32_to_cpu(here->e_value_size));
> -		}
> +		free += EXT2_XATTR_SIZE(le32_to_cpu(here->e_value_size));
>  		free += EXT2_XATTR_LEN(name_len);
>  	}
>  	error = -ENOSPC;
> @@ -559,7 +557,7 @@ ext2_xattr_set(struct inode *inode, int name_index, const
> char *name,
>  		here->e_name_len = name_len;
>  		memcpy(here->e_name, name, name_len);
>  	} else {
> -		if (!here->e_value_block && here->e_value_size) {
> +		if (here->e_value_size) {
>  			char *first_val = (char *)header + min_offs;
>  			size_t offs = le16_to_cpu(here->e_value_offs);
>  			char *val = (char *)header + offs;
> @@ -586,7 +584,7 @@ ext2_xattr_set(struct inode *inode, int name_index, const
> char *name,
>  			last = ENTRY(header+1);
>  			while (!IS_LAST_ENTRY(last)) {
>  				size_t o = le16_to_cpu(last->e_value_offs);
> -				if (!last->e_value_block && o < offs)
> +				if (o < offs)
>  					last->e_value_offs =
>  						cpu_to_le16(o + size);
>  				last = EXT2_XATTR_NEXT(last);




^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 3/3] ext2: Strengthen xattr block checks
  2019-05-16  1:16   ` cgxu519
@ 2019-05-16  8:29     ` Jan Kara
  0 siblings, 0 replies; 9+ messages in thread
From: Jan Kara @ 2019-05-16  8:29 UTC (permalink / raw)
  To: cgxu519; +Cc: Jan Kara, linux-ext4

On Thu 16-05-19 09:16:06, cgxu519@zoho.com.cn wrote:
> On Wed, 2019-05-15 at 16:01 +0200, Jan Kara wrote:
> > Check every entry in xattr block for validity in ext2_xattr_set() to
> > detect on disk corruption early. Also since e_value_block field in xattr
> > entry is never != 0 in a valid filesystem, just remove checks for it
> > once we have established entries are valid.
> > 
> > Signed-off-by: Jan Kara <jack@suse.cz>
> 
> Could we do the entry check in the loop of get/list operation too?

Yes, makes sense. Will add for v2. Thanks for review.

								Honza

> 
> Thanks,
> Chengguang
> 
> > ---
> >  fs/ext2/xattr.c | 15 ++++++---------
> >  1 file changed, 6 insertions(+), 9 deletions(-)
> > 
> > diff --git a/fs/ext2/xattr.c b/fs/ext2/xattr.c
> > index 26a049ca89fb..04a4148d04b3 100644
> > --- a/fs/ext2/xattr.c
> > +++ b/fs/ext2/xattr.c
> > @@ -442,7 +442,9 @@ ext2_xattr_set(struct inode *inode, int name_index, const
> > char *name,
> >  			struct ext2_xattr_entry *next = EXT2_XATTR_NEXT(last);
> >  			if ((char *)next >= end)
> >  				goto bad_block;
> > -			if (!last->e_value_block && last->e_value_size) {
> > +			if (!ext2_xattr_entry_valid(last, sb->s_blocksize))
> > +				goto bad_block;
> > +			if (last->e_value_size) {
> >  				size_t offs = le16_to_cpu(last->e_value_offs);
> >  				if (offs < min_offs)
> >  					min_offs = offs;
> > @@ -482,12 +484,7 @@ ext2_xattr_set(struct inode *inode, int name_index, const
> > char *name,
> >  		error = -EEXIST;
> >  		if (flags & XATTR_CREATE)
> >  			goto cleanup;
> > -		if (!here->e_value_block && here->e_value_size) {
> > -			if (!ext2_xattr_entry_valid(here, sb->s_blocksize))
> > -				goto bad_block;
> > -			free += EXT2_XATTR_SIZE(
> > -					le32_to_cpu(here->e_value_size));
> > -		}
> > +		free += EXT2_XATTR_SIZE(le32_to_cpu(here->e_value_size));
> >  		free += EXT2_XATTR_LEN(name_len);
> >  	}
> >  	error = -ENOSPC;
> > @@ -552,7 +549,7 @@ ext2_xattr_set(struct inode *inode, int name_index, const
> > char *name,
> >  		here->e_name_len = name_len;
> >  		memcpy(here->e_name, name, name_len);
> >  	} else {
> > -		if (!here->e_value_block && here->e_value_size) {
> > +		if (here->e_value_size) {
> >  			char *first_val = (char *)header + min_offs;
> >  			size_t offs = le16_to_cpu(here->e_value_offs);
> >  			char *val = (char *)header + offs;
> > @@ -579,7 +576,7 @@ ext2_xattr_set(struct inode *inode, int name_index, const
> > char *name,
> >  			last = ENTRY(header+1);
> >  			while (!IS_LAST_ENTRY(last)) {
> >  				size_t o = le16_to_cpu(last->e_value_offs);
> > -				if (!last->e_value_block && o < offs)
> > +				if (o < offs)
> >  					last->e_value_offs =
> >  						cpu_to_le16(o + size);
> >  				last = EXT2_XATTR_NEXT(last);
> 
> 
> 
-- 
Jan Kara <jack@suse.com>
SUSE Labs, CR

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 3/3] ext2: Strengthen xattr block checks
  2019-05-15 14:01 ` [PATCH 3/3] ext2: Strengthen xattr block checks Jan Kara
@ 2019-05-16  1:16   ` cgxu519
  2019-05-16  8:29     ` Jan Kara
  0 siblings, 1 reply; 9+ messages in thread
From: cgxu519 @ 2019-05-16  1:16 UTC (permalink / raw)
  To: Jan Kara, linux-ext4

On Wed, 2019-05-15 at 16:01 +0200, Jan Kara wrote:
> Check every entry in xattr block for validity in ext2_xattr_set() to
> detect on disk corruption early. Also since e_value_block field in xattr
> entry is never != 0 in a valid filesystem, just remove checks for it
> once we have established entries are valid.
> 
> Signed-off-by: Jan Kara <jack@suse.cz>

Could we do the entry check in the loop of get/list operation too?

Thanks,
Chengguang

> ---
>  fs/ext2/xattr.c | 15 ++++++---------
>  1 file changed, 6 insertions(+), 9 deletions(-)
> 
> diff --git a/fs/ext2/xattr.c b/fs/ext2/xattr.c
> index 26a049ca89fb..04a4148d04b3 100644
> --- a/fs/ext2/xattr.c
> +++ b/fs/ext2/xattr.c
> @@ -442,7 +442,9 @@ ext2_xattr_set(struct inode *inode, int name_index, const
> char *name,
>  			struct ext2_xattr_entry *next = EXT2_XATTR_NEXT(last);
>  			if ((char *)next >= end)
>  				goto bad_block;
> -			if (!last->e_value_block && last->e_value_size) {
> +			if (!ext2_xattr_entry_valid(last, sb->s_blocksize))
> +				goto bad_block;
> +			if (last->e_value_size) {
>  				size_t offs = le16_to_cpu(last->e_value_offs);
>  				if (offs < min_offs)
>  					min_offs = offs;
> @@ -482,12 +484,7 @@ ext2_xattr_set(struct inode *inode, int name_index, const
> char *name,
>  		error = -EEXIST;
>  		if (flags & XATTR_CREATE)
>  			goto cleanup;
> -		if (!here->e_value_block && here->e_value_size) {
> -			if (!ext2_xattr_entry_valid(here, sb->s_blocksize))
> -				goto bad_block;
> -			free += EXT2_XATTR_SIZE(
> -					le32_to_cpu(here->e_value_size));
> -		}
> +		free += EXT2_XATTR_SIZE(le32_to_cpu(here->e_value_size));
>  		free += EXT2_XATTR_LEN(name_len);
>  	}
>  	error = -ENOSPC;
> @@ -552,7 +549,7 @@ ext2_xattr_set(struct inode *inode, int name_index, const
> char *name,
>  		here->e_name_len = name_len;
>  		memcpy(here->e_name, name, name_len);
>  	} else {
> -		if (!here->e_value_block && here->e_value_size) {
> +		if (here->e_value_size) {
>  			char *first_val = (char *)header + min_offs;
>  			size_t offs = le16_to_cpu(here->e_value_offs);
>  			char *val = (char *)header + offs;
> @@ -579,7 +576,7 @@ ext2_xattr_set(struct inode *inode, int name_index, const
> char *name,
>  			last = ENTRY(header+1);
>  			while (!IS_LAST_ENTRY(last)) {
>  				size_t o = le16_to_cpu(last->e_value_offs);
> -				if (!last->e_value_block && o < offs)
> +				if (o < offs)
>  					last->e_value_offs =
>  						cpu_to_le16(o + size);
>  				last = EXT2_XATTR_NEXT(last);




^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 3/3] ext2: Strengthen xattr block checks
  2019-05-15 14:01 [PATCH 0/3] ext2: Cleanup ext2_xattr_set() Jan Kara
@ 2019-05-15 14:01 ` Jan Kara
  2019-05-16  1:16   ` cgxu519
  0 siblings, 1 reply; 9+ messages in thread
From: Jan Kara @ 2019-05-15 14:01 UTC (permalink / raw)
  To: linux-ext4; +Cc: Chengguang Xu, Jan Kara

Check every entry in xattr block for validity in ext2_xattr_set() to
detect on disk corruption early. Also since e_value_block field in xattr
entry is never != 0 in a valid filesystem, just remove checks for it
once we have established entries are valid.

Signed-off-by: Jan Kara <jack@suse.cz>
---
 fs/ext2/xattr.c | 15 ++++++---------
 1 file changed, 6 insertions(+), 9 deletions(-)

diff --git a/fs/ext2/xattr.c b/fs/ext2/xattr.c
index 26a049ca89fb..04a4148d04b3 100644
--- a/fs/ext2/xattr.c
+++ b/fs/ext2/xattr.c
@@ -442,7 +442,9 @@ ext2_xattr_set(struct inode *inode, int name_index, const char *name,
 			struct ext2_xattr_entry *next = EXT2_XATTR_NEXT(last);
 			if ((char *)next >= end)
 				goto bad_block;
-			if (!last->e_value_block && last->e_value_size) {
+			if (!ext2_xattr_entry_valid(last, sb->s_blocksize))
+				goto bad_block;
+			if (last->e_value_size) {
 				size_t offs = le16_to_cpu(last->e_value_offs);
 				if (offs < min_offs)
 					min_offs = offs;
@@ -482,12 +484,7 @@ ext2_xattr_set(struct inode *inode, int name_index, const char *name,
 		error = -EEXIST;
 		if (flags & XATTR_CREATE)
 			goto cleanup;
-		if (!here->e_value_block && here->e_value_size) {
-			if (!ext2_xattr_entry_valid(here, sb->s_blocksize))
-				goto bad_block;
-			free += EXT2_XATTR_SIZE(
-					le32_to_cpu(here->e_value_size));
-		}
+		free += EXT2_XATTR_SIZE(le32_to_cpu(here->e_value_size));
 		free += EXT2_XATTR_LEN(name_len);
 	}
 	error = -ENOSPC;
@@ -552,7 +549,7 @@ ext2_xattr_set(struct inode *inode, int name_index, const char *name,
 		here->e_name_len = name_len;
 		memcpy(here->e_name, name, name_len);
 	} else {
-		if (!here->e_value_block && here->e_value_size) {
+		if (here->e_value_size) {
 			char *first_val = (char *)header + min_offs;
 			size_t offs = le16_to_cpu(here->e_value_offs);
 			char *val = (char *)header + offs;
@@ -579,7 +576,7 @@ ext2_xattr_set(struct inode *inode, int name_index, const char *name,
 			last = ENTRY(header+1);
 			while (!IS_LAST_ENTRY(last)) {
 				size_t o = le16_to_cpu(last->e_value_offs);
-				if (!last->e_value_block && o < offs)
+				if (o < offs)
 					last->e_value_offs =
 						cpu_to_le16(o + size);
 				last = EXT2_XATTR_NEXT(last);
-- 
2.16.4


^ permalink raw reply related	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2019-05-16 11:12 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-05-16 10:03 [PATCH 0/3 v2] ext2: Cleanup ext2_xattr_set() Jan Kara
2019-05-16 10:03 ` [PATCH 1/3] ext2: introduce helper for xattr entry validation Jan Kara
2019-05-16 10:03 ` [PATCH 2/3] ext2: Merge loops in ext2_xattr_set() Jan Kara
2019-05-16 11:11   ` cgxu519
2019-05-16 10:03 ` [PATCH 3/3] ext2: Strengthen xattr block checks Jan Kara
2019-05-16 11:11   ` cgxu519
  -- strict thread matches above, loose matches on Subject: below --
2019-05-15 14:01 [PATCH 0/3] ext2: Cleanup ext2_xattr_set() Jan Kara
2019-05-15 14:01 ` [PATCH 3/3] ext2: Strengthen xattr block checks Jan Kara
2019-05-16  1:16   ` cgxu519
2019-05-16  8:29     ` Jan Kara

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).