[Ocfs2-tools-devel] [PATCH] libocfs2: Prevent endian swapping from scribbling over memory.

Sunil Mushran sunil.mushran at oracle.com
Thu Jul 23 15:33:33 PDT 2009


So other than the xattr bit, it looks good.

It would be good if Tao or Tiger can sign off on the xattr bits.

Joel Becker wrote:
> On Fri, Jun 26, 2009 at 01:50:02AM -0700, Joel Becker wrote:
>   
>>>> +		} else if (ocfs2_swap_barrier(&fake_fs, obj, value,
>>>> +					      xe->xe_value_size))
>>>>         
>>> here we may need to use OCFS2_XATTR_SIZE(xe->xe_value_size) since
>>> actually it is aligned. The same goes for
>>> ocfs2_swap_xattr_entries_from_cpu.
>>>       
>> 	good catch.  I'll fix it up.
>>     
>
> 	Eek, dropped the ball.  Here's the patch.  Please review.
>
> >From 2a13d61073e7f4c7bffe4825afd42cc52739cdb8 Mon Sep 17 00:00:00 2001
> From: Joel Becker <joel.becker at oracle.com>
> Date: Wed, 3 Jun 2009 10:54:19 -0700
> Subject: [PATCH] libocfs2: Prevent endian swapping from scribbling over memory.
>
> Some ocfs2 disk structures, such as our btree extent lists, are variable
> in size.  They live inside another disk structure, and one of their
> fields describes how big they are.  When we read the structure into RAM
> and swap it to the local CPU, we rely on that field to make sure we only
> swap what is necessary.
>
> However, if that field gets corrupted, our endian swapping code will
> happily keep scribbling past the end of the block buffer until it his
> the corrupted limit or segfaults.  If you're lucky, it segfaults.
>
> This change modifies all the impacted swapping functions.  They now take
> the ocfs2_filesys as an argument so that they know the blocksize.  A new
> function, ocfs2_swap_barrier(), is introduced.  It uses the
> ocfs2_filesys and the current location in the block buffer to determine
> when the swapping code is about to walk off the end.
>
> Some of our list structures can live inside multiple containing
> blocks.  Those swap functions require an additional argument, the
> address of the containing object.  That way, ocfs2_swap_barrier() knows
> what address to start at.
>
> This is ocfs2 bugzilla #1109.
>
> Signed-off-by: Joel Becker <joel.becker at oracle.com>
> ---
>  debugfs.ocfs2/dump.c             |    6 +-
>  debugfs.ocfs2/find_block_inode.c |    2 +-
>  extras/find_dup_extents.c        |    2 +-
>  fsck.ocfs2/pass1.c               |    2 +-
>  include/ocfs2/ocfs2.h            |   57 ++++++++++++++---
>  libocfs2/extents.c               |   31 ++++++---
>  libocfs2/inode.c                 |   55 +++++++++++-----
>  libocfs2/openfs.c                |    4 +-
>  libocfs2/xattr.c                 |  128 ++++++++++++++++++++++++++++----------
>  mkfs.ocfs2/mkfs.c                |   13 +++-
>  tunefs.ocfs2/libocfs2ne.c        |    2 +-
>  11 files changed, 221 insertions(+), 81 deletions(-)
>
> diff --git a/debugfs.ocfs2/dump.c b/debugfs.ocfs2/dump.c
> index 4c1157c..17f58e9 100644
> --- a/debugfs.ocfs2/dump.c
> +++ b/debugfs.ocfs2/dump.c
> @@ -682,14 +682,14 @@ void dump_jbd_metadata (FILE *out, enum dump_block_type type, char *buf,
>  	switch (type) {
>  	case DUMP_BLOCK_INODE:
>  		fprintf(out, "Inode\n");
> -		ocfs2_swap_inode_to_cpu((struct ocfs2_dinode *)buf,
> -					gbls.fs->fs_blocksize);
> +		ocfs2_swap_inode_to_cpu(gbls.fs, (struct ocfs2_dinode *)buf);
>  		dump_inode (out, (struct ocfs2_dinode *)buf);
>  		fprintf (out, "\n");
>  		break;
>  	case DUMP_BLOCK_EXTENT_BLOCK:
>  		fprintf(out, "Extent\n");
> -		ocfs2_swap_extent_block_to_cpu((struct ocfs2_extent_block *)buf);
> +		ocfs2_swap_extent_block_to_cpu(gbls.fs,
> +					       (struct ocfs2_extent_block *)buf);
>  		dump_extent_block (out, (struct ocfs2_extent_block *)buf);
>  		fprintf (out, "\n");
>  		break;
> diff --git a/debugfs.ocfs2/find_block_inode.c b/debugfs.ocfs2/find_block_inode.c
> index 1291afb..293ce09 100644
> --- a/debugfs.ocfs2/find_block_inode.c
> +++ b/debugfs.ocfs2/find_block_inode.c
> @@ -378,7 +378,7 @@ errcode_t find_block_inode(ocfs2_filesys *fs, uint64_t *blkno, int count,
>  			   strlen(OCFS2_INODE_SIGNATURE)))
>  			continue;
>  
> -		ocfs2_swap_inode_to_cpu(di, fs->fs_blocksize);
> +		ocfs2_swap_inode_to_cpu(fs, di);
>  
>  		if (di->i_fs_generation != fs->fs_super->i_fs_generation)
>  			continue;
> diff --git a/extras/find_dup_extents.c b/extras/find_dup_extents.c
> index 9263891..1f8fdcc 100644
> --- a/extras/find_dup_extents.c
> +++ b/extras/find_dup_extents.c
> @@ -184,7 +184,7 @@ static errcode_t run_scan(struct walk_extents *we, int test)
>  				   strlen(OCFS2_INODE_SIGNATURE)))
>  				continue;
>  
> -			ocfs2_swap_inode_to_cpu(di, we->fs->fs_blocksize);
> +			ocfs2_swap_inode_to_cpu(we->fs, di);
>  
>  			if (!(di->i_flags & OCFS2_VALID_FL))
>  				continue;
> diff --git a/fsck.ocfs2/pass1.c b/fsck.ocfs2/pass1.c
> index 15880bc..4aeba8c 100644
> --- a/fsck.ocfs2/pass1.c
> +++ b/fsck.ocfs2/pass1.c
> @@ -1377,7 +1377,7 @@ errcode_t o2fsck_pass1(o2fsck_state *ost)
>  		if (!memcmp(di->i_signature, OCFS2_INODE_SIGNATURE,
>  			    strlen(OCFS2_INODE_SIGNATURE))) {
>  
> -			ocfs2_swap_inode_to_cpu(di, fs->fs_blocksize);
> +			ocfs2_swap_inode_to_cpu(fs, di);
>  
>  			 /* We only consider inodes whose generations don't
>  			  * match if the user has asked us to */
> diff --git a/include/ocfs2/ocfs2.h b/include/ocfs2/ocfs2.h
> index 4dbbf43..fca35d7 100644
> --- a/include/ocfs2/ocfs2.h
> +++ b/include/ocfs2/ocfs2.h
> @@ -251,8 +251,8 @@ errcode_t ocfs2_flush(ocfs2_filesys *fs);
>  errcode_t ocfs2_close(ocfs2_filesys *fs);
>  void ocfs2_freefs(ocfs2_filesys *fs);
>  
> -void ocfs2_swap_inode_from_cpu(struct ocfs2_dinode *di, size_t blocksize);
> -void ocfs2_swap_inode_to_cpu(struct ocfs2_dinode *di, size_t blocksize);
> +void ocfs2_swap_inode_from_cpu(ocfs2_filesys *fs, struct ocfs2_dinode *di);
> +void ocfs2_swap_inode_to_cpu(ocfs2_filesys *fs, struct ocfs2_dinode *di);
>  errcode_t ocfs2_read_inode(ocfs2_filesys *fs, uint64_t blkno,
>  			   char *inode_buf);
>  errcode_t ocfs2_write_inode(ocfs2_filesys *fs, uint64_t blkno,
> @@ -266,8 +266,17 @@ errcode_t ocfs2_write_cached_inode(ocfs2_filesys *fs,
>  errcode_t ocfs2_free_cached_inode(ocfs2_filesys *fs,
>  				  ocfs2_cached_inode *cinode);
>  
> -void ocfs2_swap_extent_list_from_cpu(struct ocfs2_extent_list *el);
> -void ocfs2_swap_extent_list_to_cpu(struct ocfs2_extent_list *el);
> +/*
> + * obj is the object containing the extent list.  eg, if you are swapping
> + * an inode's extent list, you're passing 'di' for the obj and
> + * '&di->id2.i_list' for the el.  obj is needed to make sure the
> + * byte swapping code doesn't walk off the end of the buffer in the
> + * presence of corruption.
> + */
> +void ocfs2_swap_extent_list_from_cpu(ocfs2_filesys *fs, void *obj,
> +				     struct ocfs2_extent_list *el);
> +void ocfs2_swap_extent_list_to_cpu(ocfs2_filesys *fs, void *obj,
> +				   struct ocfs2_extent_list *el);
>  errcode_t ocfs2_extent_map_get_blocks(ocfs2_cached_inode *cinode,
>  				      uint64_t v_blkno, int count,
>  				      uint64_t *p_blkno,
> @@ -298,8 +307,10 @@ extern size_t ocfs2_journal_tag_bytes(journal_superblock_t *jsb);
>  extern uint64_t ocfs2_journal_tag_block(journal_block_tag_t *tag,
>  					size_t tag_bytes);
>  
> -void ocfs2_swap_extent_block_to_cpu(struct ocfs2_extent_block *eb);
> -void ocfs2_swap_extent_block_from_cpu(struct ocfs2_extent_block *eb);
> +void ocfs2_swap_extent_block_to_cpu(ocfs2_filesys *fs,
> +				    struct ocfs2_extent_block *eb);
> +void ocfs2_swap_extent_block_from_cpu(ocfs2_filesys *fs,
> +				      struct ocfs2_extent_block *eb);
>  errcode_t ocfs2_read_extent_block(ocfs2_filesys *fs, uint64_t blkno,
>         				  char *eb_buf);
>  errcode_t ocfs2_read_extent_block_nocheck(ocfs2_filesys *fs, uint64_t blkno,
> @@ -974,6 +985,27 @@ static inline int ocfs2_support_xattr(struct ocfs2_super_block *osb)
>  }
>  
>  /*
> + * When we're swapping some of our disk structures, a garbage count
> + * can send us past the edge of a block buffer.  This function guards
> + * against that.  It returns true if the element would walk off then end
> + * of the block buffer.
> + */
> +static inline int ocfs2_swap_barrier(ocfs2_filesys *fs, void *block_buffer,
> +				     void *element, size_t element_size)
> +{
> +	char *limit, *end;
> +
> +	limit = block_buffer;
> +	limit += fs->fs_blocksize;
> +
> +	end = element;
> +	end += element_size;
> +
> +	return end > limit;
> +}
> +
> +
> +/*
>   * shamelessly lifted from the kernel
>   *
>   * min()/max() macros that also do
> @@ -1098,10 +1130,15 @@ int ocfs2_xattr_find_leaf(ocfs2_filesys *fs, struct ocfs2_xattr_block *xb,
>  			  uint32_t cpos, char **leaf_buf);
>  uint16_t ocfs2_xattr_buckets_per_cluster(ocfs2_filesys *fs);
>  uint16_t ocfs2_blocks_per_xattr_bucket(ocfs2_filesys *fs);
> -void ocfs2_swap_xattrs_to_cpu(struct ocfs2_xattr_header *xh);
> -void ocfs2_swap_xattrs_from_cpu(struct ocfs2_xattr_header *xh);
> -void ocfs2_swap_xattr_block_to_cpu(struct ocfs2_xattr_block *xb);
> -void ocfs2_swap_xattr_block_from_cpu(struct ocfs2_xattr_block *xb);
> +/* See ocfs2_swap_extent_list() for a discussion of obj */
> +void ocfs2_swap_xattrs_to_cpu(ocfs2_filesys *fs, void *obj,
> +			      struct ocfs2_xattr_header *xh);
> +void ocfs2_swap_xattrs_from_cpu(ocfs2_filesys *fs, void *obj,
> +				struct ocfs2_xattr_header *xh);
> +void ocfs2_swap_xattr_block_to_cpu(ocfs2_filesys *fs,
> +				   struct ocfs2_xattr_block *xb);
> +void ocfs2_swap_xattr_block_from_cpu(ocfs2_filesys *fs,
> +				     struct ocfs2_xattr_block *xb);
>  errcode_t ocfs2_read_xattr_block(ocfs2_filesys *fs,
>  				 uint64_t blkno,
>  				 char *xb_buf);
> diff --git a/libocfs2/extents.c b/libocfs2/extents.c
> index 4b6808a..ee7ef93 100644
> --- a/libocfs2/extents.c
> +++ b/libocfs2/extents.c
> @@ -42,13 +42,18 @@ static void ocfs2_swap_extent_list_primary(struct ocfs2_extent_list *el)
>  	el->l_next_free_rec = bswap_16(el->l_next_free_rec);
>  }
>  
> -static void ocfs2_swap_extent_list_secondary(struct ocfs2_extent_list *el)
> +static void ocfs2_swap_extent_list_secondary(ocfs2_filesys *fs, void *obj,
> +					     struct ocfs2_extent_list *el)
>  {
>  	uint16_t i;
>  
>  	for(i = 0; i < el->l_next_free_rec; i++) {
>  		struct ocfs2_extent_rec *rec = &el->l_recs[i];
>  
> +		if (ocfs2_swap_barrier(fs, obj, rec,
> +				       sizeof(struct ocfs2_extent_rec)))
> +			break;
> +
>  		rec->e_cpos = bswap_32(rec->e_cpos);
>  		if (el->l_tree_depth)
>  			rec->e_int_clusters = bswap_32(rec->e_int_clusters);
> @@ -58,21 +63,23 @@ static void ocfs2_swap_extent_list_secondary(struct ocfs2_extent_list *el)
>  	}
>  }
>  
> -void ocfs2_swap_extent_list_from_cpu(struct ocfs2_extent_list *el)
> +void ocfs2_swap_extent_list_from_cpu(ocfs2_filesys *fs, void *obj,
> +				     struct ocfs2_extent_list *el)
>  {
>  	if (cpu_is_little_endian)
>  		return;
>  
> -	ocfs2_swap_extent_list_secondary(el);
> +	ocfs2_swap_extent_list_secondary(fs, obj, el);
>  	ocfs2_swap_extent_list_primary(el);
>  }
> -void ocfs2_swap_extent_list_to_cpu(struct ocfs2_extent_list *el)
> +void ocfs2_swap_extent_list_to_cpu(ocfs2_filesys *fs, void *obj,
> +				   struct ocfs2_extent_list *el)
>  {
>  	if (cpu_is_little_endian)
>  		return;
>  
>  	ocfs2_swap_extent_list_primary(el);
> -	ocfs2_swap_extent_list_secondary(el);
> +	ocfs2_swap_extent_list_secondary(fs, obj, el);
>  }
>  
>  static void ocfs2_swap_extent_block_header(struct ocfs2_extent_block *eb)
> @@ -85,22 +92,24 @@ static void ocfs2_swap_extent_block_header(struct ocfs2_extent_block *eb)
>  	eb->h_next_leaf_blk = bswap_64(eb->h_next_leaf_blk);
>  }
>  
> -void ocfs2_swap_extent_block_from_cpu(struct ocfs2_extent_block *eb)
> +void ocfs2_swap_extent_block_from_cpu(ocfs2_filesys *fs,
> +				      struct ocfs2_extent_block *eb)
>  {
>  	if (cpu_is_little_endian)
>  		return;
>  
>  	ocfs2_swap_extent_block_header(eb);
> -	ocfs2_swap_extent_list_from_cpu(&eb->h_list);
> +	ocfs2_swap_extent_list_from_cpu(fs, eb, &eb->h_list);
>  }
>  
> -void ocfs2_swap_extent_block_to_cpu(struct ocfs2_extent_block *eb)
> +void ocfs2_swap_extent_block_to_cpu(ocfs2_filesys *fs,
> +				    struct ocfs2_extent_block *eb)
>  {
>  	if (cpu_is_little_endian)
>  		return;
>  
>  	ocfs2_swap_extent_block_header(eb);
> -	ocfs2_swap_extent_list_to_cpu(&eb->h_list);
> +	ocfs2_swap_extent_list_to_cpu(fs, eb, &eb->h_list);
>  }
>  
>  errcode_t ocfs2_read_extent_block_nocheck(ocfs2_filesys *fs,
> @@ -138,7 +147,7 @@ errcode_t ocfs2_read_extent_block_nocheck(ocfs2_filesys *fs,
>  	memcpy(eb_buf, blk, fs->fs_blocksize);
>  
>  	eb = (struct ocfs2_extent_block *) eb_buf;
> -	ocfs2_swap_extent_block_to_cpu(eb);
> +	ocfs2_swap_extent_block_to_cpu(fs, eb);
>  
>  out:
>  	ocfs2_free(&blk);
> @@ -182,7 +191,7 @@ errcode_t ocfs2_write_extent_block(ocfs2_filesys *fs, uint64_t blkno,
>  	memcpy(blk, eb_buf, fs->fs_blocksize);
>  
>  	eb = (struct ocfs2_extent_block *) blk;
> -	ocfs2_swap_extent_block_from_cpu(eb);
> +	ocfs2_swap_extent_block_from_cpu(fs, eb);
>  
>  	ocfs2_compute_meta_ecc(fs, blk, &eb->h_check);
>  	ret = io_write_block(fs->fs_io, blkno, 1, blk);
> diff --git a/libocfs2/inode.c b/libocfs2/inode.c
> index e786f5e..1abda69 100644
> --- a/libocfs2/inode.c
> +++ b/libocfs2/inode.c
> @@ -63,7 +63,7 @@ out_buf:
>  	return ret;
>  }
>  
> -static void ocfs2_swap_inode_third(struct ocfs2_dinode *di)
> +static void ocfs2_swap_inode_third(ocfs2_filesys *fs, struct ocfs2_dinode *di)
>  {
>  
>  	if (di->i_flags & OCFS2_CHAIN_FL) {
> @@ -73,6 +73,10 @@ static void ocfs2_swap_inode_third(struct ocfs2_dinode *di)
>  		for (i = 0; i < cl->cl_next_free_rec; i++) {
>  			struct ocfs2_chain_rec *rec = &cl->cl_recs[i];
>  
> +			if (ocfs2_swap_barrier(fs, di, rec,
> +					       sizeof(struct ocfs2_chain_rec)))
> +				break;
> +
>  			rec->c_free  = bswap_32(rec->c_free);
>  			rec->c_total = bswap_32(rec->c_total);
>  			rec->c_blkno = bswap_64(rec->c_blkno);
> @@ -86,6 +90,10 @@ static void ocfs2_swap_inode_third(struct ocfs2_dinode *di)
>  			struct ocfs2_truncate_rec *rec =
>  				&tl->tl_recs[i];
>  
> +			if (ocfs2_swap_barrier(fs, di, rec,
> +					     sizeof(struct ocfs2_truncate_rec)))
> +				break;
> +
>  			rec->t_start    = bswap_32(rec->t_start);
>  			rec->t_clusters = bswap_32(rec->t_clusters);
>  		}
> @@ -202,11 +210,22 @@ static int has_extents(struct ocfs2_dinode *di)
>  	return 1;
>  }
>  
> -static inline void ocfs2_swap_inline_dir(struct ocfs2_dinode *di,
> -					 int to_cpu)
> +static inline void ocfs2_swap_inline_dir(ocfs2_filesys *fs,
> +					 struct ocfs2_dinode *di, int to_cpu)
>  {
>  	void *de_buf = di->id2.i_data.id_data;
>  	uint64_t bytes = di->id2.i_data.id_count;
> +	int max_inline = ocfs2_max_inline_data(fs->fs_blocksize);
> +
> +	if (di->i_dyn_features & OCFS2_INLINE_XATTR_FL)
> +		max_inline -= di->i_xattr_inline_size;
> +
> +	/* Just in case i_xattr_inline_size is garbage */
> +	if (max_inline < 0)
> +		max_inline = 0;
> +
> +	if (bytes > max_inline)
> +	    bytes = max_inline;
>  
>  	if (to_cpu)
>  		ocfs2_swap_dir_entries_to_cpu(de_buf, bytes);
> @@ -214,41 +233,43 @@ static inline void ocfs2_swap_inline_dir(struct ocfs2_dinode *di,
>  		ocfs2_swap_dir_entries_from_cpu(de_buf, bytes);
>  }
>  
> -void ocfs2_swap_inode_from_cpu(struct ocfs2_dinode *di, size_t blocksize)
> +void ocfs2_swap_inode_from_cpu(ocfs2_filesys *fs, struct ocfs2_dinode *di)
>  {
>  	if (cpu_is_little_endian)
>  		return;
>  
>  	if (di->i_dyn_features & OCFS2_INLINE_XATTR_FL) {
>  		struct ocfs2_xattr_header *xh = (struct ocfs2_xattr_header *)
> -			((void *)di + blocksize - di->i_xattr_inline_size);
> -		ocfs2_swap_xattrs_from_cpu(xh);
> +			((void *)di + fs->fs_blocksize -
> +			 di->i_xattr_inline_size);
> +		ocfs2_swap_xattrs_from_cpu(fs, di, xh);
>  	}
>  	if (has_extents(di))
> -		ocfs2_swap_extent_list_from_cpu(&di->id2.i_list);
> +		ocfs2_swap_extent_list_from_cpu(fs, di, &di->id2.i_list);
>  	if (di->i_dyn_features & OCFS2_INLINE_DATA_FL && S_ISDIR(di->i_mode))
> -		ocfs2_swap_inline_dir(di, 0);
> -	ocfs2_swap_inode_third(di);
> +		ocfs2_swap_inline_dir(fs, di, 0);
> +	ocfs2_swap_inode_third(fs, di);
>  	ocfs2_swap_inode_second(di);
>  	ocfs2_swap_inode_first(di);
>  }
>  
> -void ocfs2_swap_inode_to_cpu(struct ocfs2_dinode *di, size_t blocksize)
> +void ocfs2_swap_inode_to_cpu(ocfs2_filesys *fs, struct ocfs2_dinode *di)
>  {
>  	if (cpu_is_little_endian)
>  		return;
>  
>  	ocfs2_swap_inode_first(di);
>  	ocfs2_swap_inode_second(di);
> -	ocfs2_swap_inode_third(di);
> +	ocfs2_swap_inode_third(fs, di);
>  	if (di->i_dyn_features & OCFS2_INLINE_DATA_FL && S_ISDIR(di->i_mode))
> -		ocfs2_swap_inline_dir(di, 1);
> +		ocfs2_swap_inline_dir(fs, di, 1);
>  	if (has_extents(di))
> -		ocfs2_swap_extent_list_to_cpu(&di->id2.i_list);
> +		ocfs2_swap_extent_list_to_cpu(fs, di, &di->id2.i_list);
>  	if (di->i_dyn_features & OCFS2_INLINE_XATTR_FL) {
>  		struct ocfs2_xattr_header *xh = (struct ocfs2_xattr_header *)
> -			((void *)di + blocksize - di->i_xattr_inline_size);
> -		ocfs2_swap_xattrs_to_cpu(xh);
> +			((void *)di + fs->fs_blocksize -
> +			 di->i_xattr_inline_size);
> +		ocfs2_swap_xattrs_to_cpu(fs, di, xh);
>  	}
>  }
>  
> @@ -284,7 +305,7 @@ errcode_t ocfs2_read_inode(ocfs2_filesys *fs, uint64_t blkno,
>  	memcpy(inode_buf, blk, fs->fs_blocksize);
>  
>  	di = (struct ocfs2_dinode *) inode_buf;
> -	ocfs2_swap_inode_to_cpu(di, fs->fs_blocksize);
> +	ocfs2_swap_inode_to_cpu(fs, di);
>  
>  	ret = 0;
>  out:
> @@ -314,7 +335,7 @@ errcode_t ocfs2_write_inode(ocfs2_filesys *fs, uint64_t blkno,
>  	memcpy(blk, inode_buf, fs->fs_blocksize);
>  
>  	di = (struct ocfs2_dinode *)blk;
> -	ocfs2_swap_inode_from_cpu(di, fs->fs_blocksize);
> +	ocfs2_swap_inode_from_cpu(fs, di);
>  
>  	ocfs2_compute_meta_ecc(fs, blk, &di->i_check);
>  	ret = io_write_block(fs->fs_io, blkno, 1, blk);
> diff --git a/libocfs2/openfs.c b/libocfs2/openfs.c
> index 538d859..156ea47 100644
> --- a/libocfs2/openfs.c
> +++ b/libocfs2/openfs.c
> @@ -137,7 +137,7 @@ errcode_t ocfs2_read_super(ocfs2_filesys *fs, uint64_t superblock, char *sb)
>  	orig_blocksize = fs->fs_blocksize;
>  	fs->fs_super = (struct ocfs2_dinode *)swapblk;
>  	fs->fs_blocksize = blocksize;
> -	ocfs2_swap_inode_to_cpu(fs->fs_super, fs->fs_blocksize);
> +	ocfs2_swap_inode_to_cpu(fs, fs->fs_super);
>  
>  	ret = ocfs2_validate_meta_ecc(fs, blk, &di->i_check);
>  
> @@ -148,7 +148,7 @@ errcode_t ocfs2_read_super(ocfs2_filesys *fs, uint64_t superblock, char *sb)
>  	if (ret)
>  		goto out_blk;
>  
> -	ocfs2_swap_inode_to_cpu(di, fs->fs_blocksize);
> +	ocfs2_swap_inode_to_cpu(fs, di);
>  	if (!sb)
>  		fs->fs_super = di;
>  	else {
> diff --git a/libocfs2/xattr.c b/libocfs2/xattr.c
> index bffdfd9..69b31e6 100644
> --- a/libocfs2/xattr.c
> +++ b/libocfs2/xattr.c
> @@ -106,9 +106,26 @@ static void ocfs2_swap_xattr_header(struct ocfs2_xattr_header *xh)
>  	xh->xh_num_buckets	= bswap_16(xh->xh_num_buckets);
>  }
>  
> -static void ocfs2_swap_xattr_entries_to_cpu(struct ocfs2_xattr_header *xh)
> +/*
> + * The swap barriers for xattrs are the hardest.  The ocfs2_xattr_header
> + * can be at the start of a bucket, inside an xattr block, or at the end
> + * of an inode.  Thus, we need to pass obj for the containing object.
> + * On top of that, buckets are always 4K, regardless of blocksize.  Thus,
> + * we take objsize as an argument and fake the ocfs2_filesys we pass to
> + * ocfs2_swap_barrier().
> + *
> + * Much of this is internal to xattr.c, thankfully.  The callers of the
> + * pubic ocfs2_swap_xattr*() APIs don't have to worry about objsize!
> + */
> +static void ocfs2_swap_xattr_entries_to_cpu(ocfs2_filesys *fs, void *obj,
> +					    size_t objsize,
> +					    struct ocfs2_xattr_header *xh)
>  {
>  	uint16_t i;
> +	char *value;
> +	ocfs2_filesys fake_fs = {
> +		.fs_blocksize = objsize,
> +	};
>  
>  	if (cpu_is_little_endian)
>  		return;
> @@ -116,23 +133,40 @@ static void ocfs2_swap_xattr_entries_to_cpu(struct ocfs2_xattr_header *xh)
>  	for (i = 0; i < xh->xh_count; i++) {
>  		struct ocfs2_xattr_entry *xe = &xh->xh_entries[i];
>  
> +		if (ocfs2_swap_barrier(&fake_fs, obj, xe,
> +				       sizeof(struct ocfs2_xattr_entry)))
> +			break;
> +
>  		ocfs2_swap_xattr_entry(xe);
>  
> +		value = (char *)xh + xe->xe_name_offset +
> +			OCFS2_XATTR_SIZE(xe->xe_name_len);
> +
>  		if (!ocfs2_xattr_is_local(xe)) {
>  			struct ocfs2_xattr_value_root *xr =
> -				(struct ocfs2_xattr_value_root *)
> -				((char *)xh + xe->xe_name_offset +
> -				OCFS2_XATTR_SIZE(xe->xe_name_len));
> +				(struct ocfs2_xattr_value_root *)value;
> +
> +			if (ocfs2_swap_barrier(&fake_fs, obj, xr,
> +					       OCFS2_XATTR_ROOT_SIZE))
> +				break;
>  
>  			ocfs2_swap_xattr_value_root(xr);
> -			ocfs2_swap_extent_list_to_cpu(&xr->xr_list);
> -		}
> +			ocfs2_swap_extent_list_to_cpu(fs, xh, &xr->xr_list);
> +		} else if (ocfs2_swap_barrier(&fake_fs, obj, value,
> +					      OCFS2_XATTR_SIZE(xe->xe_value_size)))
> +			break;
>  	}
>  }
>  
> -static void ocfs2_swap_xattr_entries_from_cpu(struct ocfs2_xattr_header *xh)
> +static void ocfs2_swap_xattr_entries_from_cpu(ocfs2_filesys *fs, void *obj,
> +					      size_t objsize,
> +					      struct ocfs2_xattr_header *xh)
>  {
>  	uint16_t i;
> +	char *value;
> +	ocfs2_filesys fake_fs = {
> +		.fs_blocksize = objsize,
> +	};
>  
>  	if (cpu_is_little_endian)
>  		return;
> @@ -140,56 +174,86 @@ static void ocfs2_swap_xattr_entries_from_cpu(struct ocfs2_xattr_header *xh)
>  	for (i = 0; i < xh->xh_count; i++) {
>  		struct ocfs2_xattr_entry *xe = &xh->xh_entries[i];
>  
> +		if (ocfs2_swap_barrier(&fake_fs, obj, xe,
> +				       sizeof(struct ocfs2_xattr_entry)))
> +			break;
> +
> +		value = (char *)xh + xe->xe_name_offset +
> +			OCFS2_XATTR_SIZE(xe->xe_name_len);
> +
>  		if (!ocfs2_xattr_is_local(xe)) {
>  			struct ocfs2_xattr_value_root *xr =
> -				(struct ocfs2_xattr_value_root *)
> -				((char *)xh + xe->xe_name_offset +
> -				OCFS2_XATTR_SIZE(xe->xe_name_len));
> +				(struct ocfs2_xattr_value_root *)value;
> +
> +			if (ocfs2_swap_barrier(&fake_fs, obj, xr,
> +					       OCFS2_XATTR_ROOT_SIZE))
> +				break;
>  
> -			ocfs2_swap_extent_list_from_cpu(&xr->xr_list);
> +			ocfs2_swap_extent_list_from_cpu(fs, xh, &xr->xr_list);
>  			ocfs2_swap_xattr_value_root(xr);
> -		}
> +		} else if (ocfs2_swap_barrier(&fake_fs, obj, value,
> +					      OCFS2_XATTR_SIZE(xe->xe_value_size)))
> +			break;
> +
>  		ocfs2_swap_xattr_entry(xe);
>  	}
>  }
>  
> -void ocfs2_swap_xattrs_to_cpu(struct ocfs2_xattr_header *xh)
> +static void __ocfs2_swap_xattrs_to_cpu(ocfs2_filesys *fs, void *obj,
> +				       size_t objsize,
> +				       struct ocfs2_xattr_header *xh)
>  {
>  	ocfs2_swap_xattr_header(xh);
> -	ocfs2_swap_xattr_entries_to_cpu(xh);
> +	ocfs2_swap_xattr_entries_to_cpu(fs, obj, objsize, xh);
> +}
> +
> +void ocfs2_swap_xattrs_to_cpu(ocfs2_filesys *fs, void *obj,
> +			      struct ocfs2_xattr_header *xh)
> +{
> +	return __ocfs2_swap_xattrs_to_cpu(fs, obj, fs->fs_blocksize, xh);
>  }
>  
> -void ocfs2_swap_xattrs_from_cpu(struct ocfs2_xattr_header *xh)
> +static void __ocfs2_swap_xattrs_from_cpu(ocfs2_filesys *fs, void *obj,
> +					 size_t objsize,
> +					 struct ocfs2_xattr_header *xh)
>  {
> -	ocfs2_swap_xattr_entries_from_cpu(xh);
> +	ocfs2_swap_xattr_entries_from_cpu(fs, obj, objsize, xh);
>  	ocfs2_swap_xattr_header(xh);
>  }
>  
> -void ocfs2_swap_xattr_block_to_cpu(struct ocfs2_xattr_block *xb)
> +void ocfs2_swap_xattrs_from_cpu(ocfs2_filesys *fs, void *obj,
> +				struct ocfs2_xattr_header *xh)
> +{
> +	return __ocfs2_swap_xattrs_from_cpu(fs, obj, fs->fs_blocksize, xh);
> +}
> +
> +void ocfs2_swap_xattr_block_to_cpu(ocfs2_filesys *fs,
> +				   struct ocfs2_xattr_block *xb)
>  {
>  	if (cpu_is_little_endian)
>  		return;
>  
>  	ocfs2_swap_xattr_block_header(xb);
> -	if (!(xb->xb_flags & OCFS2_XATTR_INDEXED)) {
> -		ocfs2_swap_xattr_header(&xb->xb_attrs.xb_header);
> -		ocfs2_swap_xattr_entries_to_cpu(&xb->xb_attrs.xb_header);
> -	} else {
> +	if (!(xb->xb_flags & OCFS2_XATTR_INDEXED))
> +		ocfs2_swap_xattrs_to_cpu(fs, xb, &xb->xb_attrs.xb_header);
> +	else {
>  		ocfs2_swap_xattr_tree_root(&xb->xb_attrs.xb_root);
> -		ocfs2_swap_extent_list_to_cpu(&xb->xb_attrs.xb_root.xt_list);
> +		ocfs2_swap_extent_list_to_cpu(fs, xb,
> +					      &xb->xb_attrs.xb_root.xt_list);
>  	}
>  }
>  
> -void ocfs2_swap_xattr_block_from_cpu(struct ocfs2_xattr_block *xb)
> +void ocfs2_swap_xattr_block_from_cpu(ocfs2_filesys *fs,
> +				     struct ocfs2_xattr_block *xb)
>  {
>  	if (cpu_is_little_endian)
>  		return;
>  
> -	if (!(xb->xb_flags & OCFS2_XATTR_INDEXED)) {
> -		ocfs2_swap_xattr_entries_from_cpu(&xb->xb_attrs.xb_header);
> -		ocfs2_swap_xattr_header(&xb->xb_attrs.xb_header);
> -	} else {
> -		ocfs2_swap_extent_list_from_cpu(&xb->xb_attrs.xb_root.xt_list);
> +	if (!(xb->xb_flags & OCFS2_XATTR_INDEXED))
> +		ocfs2_swap_xattrs_from_cpu(fs, xb, &xb->xb_attrs.xb_header);
> +	else {
> +		ocfs2_swap_extent_list_from_cpu(fs, xb,
> +						&xb->xb_attrs.xb_root.xt_list);
>  		ocfs2_swap_xattr_tree_root(&xb->xb_attrs.xb_root);
>  	}
>  
> @@ -230,7 +294,7 @@ errcode_t ocfs2_read_xattr_block(ocfs2_filesys *fs,
>  
>  	memcpy(xb_buf, blk, fs->fs_blocksize);
>  	xb = (struct ocfs2_xattr_block *)xb_buf;
> -	ocfs2_swap_xattr_block_to_cpu(xb);
> +	ocfs2_swap_xattr_block_to_cpu(fs, xb);
>  out:
>  	ocfs2_free(&blk);
>  	return ret;
> @@ -258,7 +322,7 @@ errcode_t ocfs2_write_xattr_block(ocfs2_filesys *fs,
>  	memcpy(blk, xb_buf, fs->fs_blocksize);
>  
>  	xb = (struct ocfs2_xattr_block *)blk;
> -	ocfs2_swap_xattr_block_from_cpu(xb);
> +	ocfs2_swap_xattr_block_from_cpu(fs, xb);
>  
>  	ocfs2_compute_meta_ecc(fs, blk, &xb->xb_check);
>  	ret = io_write_block(fs->fs_io, blkno, 1, blk);
> @@ -395,7 +459,7 @@ errcode_t ocfs2_read_xattr_bucket(ocfs2_filesys *fs,
>  
>  	memcpy(bucket_buf, bucket, OCFS2_XATTR_BUCKET_SIZE);
>  	xh = (struct ocfs2_xattr_header *)bucket_buf;
> -	ocfs2_swap_xattrs_to_cpu(xh);
> +	__ocfs2_swap_xattrs_to_cpu(fs, xh, OCFS2_XATTR_BUCKET_SIZE, xh);
>  out:
>  	ocfs2_free(&bucket);
>  	return ret;
> @@ -425,7 +489,7 @@ errcode_t ocfs2_write_xattr_bucket(ocfs2_filesys *fs,
>  	memcpy(bucket, bucket_buf, OCFS2_XATTR_BUCKET_SIZE);
>  
>  	xh = (struct ocfs2_xattr_header *)bucket;
> -	ocfs2_swap_xattrs_from_cpu(xh);
> +	__ocfs2_swap_xattrs_from_cpu(fs, xh, OCFS2_XATTR_BUCKET_SIZE, xh);
>  
>  	if (ocfs2_meta_ecc(OCFS2_RAW_SB(fs->fs_super)))
>  		ocfs2_block_check_compute(bucket, OCFS2_XATTR_BUCKET_SIZE,
> diff --git a/mkfs.ocfs2/mkfs.c b/mkfs.ocfs2/mkfs.c
> index 048f70f..d6151cf 100644
> --- a/mkfs.ocfs2/mkfs.c
> +++ b/mkfs.ocfs2/mkfs.c
> @@ -1945,6 +1945,15 @@ check_32bit_blocks(State *s)
>  	exit(1);
>  }
>  
> +static void mkfs_swap_inode_from_cpu(State *s, struct ocfs2_dinode *di)
> +{
> +	ocfs2_filesys fake_fs;
> +	char super_buf[OCFS2_MAX_BLOCKSIZE];
> +
> +	fill_fake_fs(s, &fake_fs, super_buf);
> +	ocfs2_swap_inode_from_cpu(&fake_fs, di);
> +}
> +
>  static void
>  format_superblock(State *s, SystemFileDiskRecord *rec,
>  		  SystemFileDiskRecord *root_rec, SystemFileDiskRecord *sys_rec)
> @@ -2025,7 +2034,7 @@ format_superblock(State *s, SystemFileDiskRecord *rec,
>  	strcpy((char *)di->id2.i_super.s_label, s->vol_label);
>  	memcpy(di->id2.i_super.s_uuid, s->uuid, 16);
>  
> -	ocfs2_swap_inode_from_cpu(di, s->blocksize);
> +	mkfs_swap_inode_from_cpu(s, di);
>  	mkfs_compute_meta_ecc(s, di, &di->i_check);
>  	do_pwrite(s, di, s->blocksize, super_off);
>  	free(di);
> @@ -2191,7 +2200,7 @@ format_file(State *s, SystemFileDiskRecord *rec)
>  	}
>  
>  write_out:
> -	ocfs2_swap_inode_from_cpu(di, s->blocksize);
> +	mkfs_swap_inode_from_cpu(s, di);
>  	mkfs_compute_meta_ecc(s, di, &di->i_check);
>  	do_pwrite(s, di, s->blocksize, rec->fe_off);
>  	free(di);
> diff --git a/tunefs.ocfs2/libocfs2ne.c b/tunefs.ocfs2/libocfs2ne.c
> index c5362db..6f89175 100644
> --- a/tunefs.ocfs2/libocfs2ne.c
> +++ b/tunefs.ocfs2/libocfs2ne.c
> @@ -498,7 +498,7 @@ static errcode_t tunefs_validate_inode(ocfs2_filesys *fs,
>  		    strlen(OCFS2_INODE_SIGNATURE)))
>  		return OCFS2_ET_BAD_INODE_MAGIC;
>  
> -	ocfs2_swap_inode_to_cpu(di, fs->fs_blocksize);
> +	ocfs2_swap_inode_to_cpu(fs, di);
>  
>  	if (di->i_fs_generation != fs->fs_super->i_fs_generation)
>  		return OCFS2_ET_INODE_NOT_VALID;
>   




More information about the Ocfs2-tools-devel mailing list