Tao Ma
2010-Mar-19 07:04 UTC
[Ocfs2-devel] [PATCH 1/2] ocfs2: Increase name_offset for the removed xattr.
When replacing a xattr's value, in some case we wipe
its name/value first and then adding them. The wipe
is done by ocfs2_xa_block_wipe_namevalue when xattr
is in inode or block. we decrease name_offset for all
the entries which have offset < name_offset. This isn't
enough in case the replaced one has the smallest offset.
So the next time we will find the wrong free_start in
ocfs2_xa_get_free_start and we will overflow finally.
The solution is to increase the name_offset for the
replaced one also so that we can survive.
The following script can trigger a kernel panic easily.
echo 'y'|mkfs.ocfs2 --fs-features=local,xattr -b 4K $DEVICE
mount -t ocfs2 $DEVICE $MNT_DIR
FILE=$MNT_DIR/$RANDOM
for((i=0;i<76;i++))
do
string_76="a$string_76"
done
string_78="aa$string_76"
string_82="aaaa$string_78"
touch $FILE
setfattr -n 'user.test1234567890' -v $string_76 $FILE
setfattr -n 'user.test1234567890' -v $string_78 $FILE
setfattr -n 'user.test1234567890' -v $string_82 $FILE
Signed-off-by: Tao Ma <tao.ma at oracle.com>
---
fs/ocfs2/xattr.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c
index d1b0d38..82c2a0b 100644
--- a/fs/ocfs2/xattr.c
+++ b/fs/ocfs2/xattr.c
@@ -1622,7 +1622,7 @@ static void ocfs2_xa_block_wipe_namevalue(struct
ocfs2_xa_loc *loc)
/* Now tell xh->xh_entries about it */
for (i = 0; i < count; i++) {
offset = le16_to_cpu(xh->xh_entries[i].xe_name_offset);
- if (offset < namevalue_offset)
+ if (offset <= namevalue_offset)
le16_add_cpu(&xh->xh_entries[i].xe_name_offset,
namevalue_size);
}
--
1.5.5
Tao Ma
2010-Mar-19 07:04 UTC
[Ocfs2-devel] [PATCH 2/2] ocfs2: Init meta_ac properly in ocfs2_create_empty_xattr_block.
Init ctxt.meta_ac properly in ocfs2_create_empty_xattr_block.
Signed-off-by: Tao Ma <tao.ma at oracle.com>
---
fs/ocfs2/xattr.c | 10 ++++------
1 files changed, 4 insertions(+), 6 deletions(-)
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c
index 82c2a0b..3e77730 100644
--- a/fs/ocfs2/xattr.c
+++ b/fs/ocfs2/xattr.c
@@ -6528,13 +6528,11 @@ static int ocfs2_create_empty_xattr_block(struct inode
*inode,
int indexed)
{
int ret;
- struct ocfs2_alloc_context *meta_ac;
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
- struct ocfs2_xattr_set_ctxt ctxt = {
- .meta_ac = meta_ac,
- };
+ struct ocfs2_xattr_set_ctxt ctxt;
- ret = ocfs2_reserve_new_metadata_blocks(osb, 1, &meta_ac);
+ memset(&ctxt, 0, sizeof(ctxt));
+ ret = ocfs2_reserve_new_metadata_blocks(osb, 1, &ctxt.meta_ac);
if (ret < 0) {
mlog_errno(ret);
return ret;
@@ -6556,7 +6554,7 @@ static int ocfs2_create_empty_xattr_block(struct inode
*inode,
ocfs2_commit_trans(osb, ctxt.handle);
out:
- ocfs2_free_alloc_context(meta_ac);
+ ocfs2_free_alloc_context(ctxt.meta_ac);
return ret;
}
--
1.5.5
Joel Becker
2010-Mar-19 21:50 UTC
[Ocfs2-devel] [PATCH 1/2] ocfs2: Increase name_offset for the removed xattr.
On Fri, Mar 19, 2010 at 03:04:23PM +0800, Tao Ma wrote:> When replacing a xattr's value, in some case we wipe > its name/value first and then adding them. The wipe > is done by ocfs2_xa_block_wipe_namevalue when xattr > is in inode or block. we decrease name_offset for all > the entries which have offset < name_offset. This isn't > enough in case the replaced one has the smallest offset. > So the next time we will find the wrong free_start in > ocfs2_xa_get_free_start and we will overflow finally. > The solution is to increase the name_offset for the > replaced one also so that we can survive.This patch is now in the fixes branch of ocfs2.git. Good catch! Joel -- Life's Little Instruction Book #464 "Don't miss the magic of the moment by focusing on what's to come." Joel Becker Principal Software Developer Oracle E-mail: joel.becker at oracle.com Phone: (650) 506-8127