[patch] Adding Secure Deletion to UBIFS

Joel Reardon joel at clambassador.com
Thu Feb 23 09:59:51 EST 2012


>
> Could you make a separate patch which adds new on-flash format and make
> sure that new ubifs binaries can mount the old formats and work with
> them. And that old ubifs binaries gracefully reject the new format.
>

This patch provides a new version of two on-flash data structures for 
UBIFS:
ubifs_branch and ubifs_data_node have been grown by 8 bytes to include a 
64-bit reference
to a key position, which is needed by a proposed ubifs secure deletion 
addition. This patch is generated
against linux-3.2.1.

Because both data structures use C99 flexible arrays, it is not possible 
to add the new field as
the last member of the structure. Thus, it was added one before last, the 
last was renamed, and in a
handful of places where it was used, a macro accessor is used to get the 
version-correct position.

The new/modified macros are the following:
FMT_VERSION_DATA_NODE_HAS_CRYPTO_LOOKUP(c)
FMT_VERSION_BRANCH_HAS_CRYPTO_LOOKUP(c)
These take the ubifs_context and return true if the version defined in 
fmt_version has a crypto_lookup field.

FMT_VERSION_BRANCH_POS_KEY(c, br)
FMT_VERSION_DATA_NODE_POS_DATA(c, dn)
These take the ubifs_context and the data_node / branch and return the 
address of the key / data field
that is correct for the version defined in fmt_version. key and data are 
renamed to __key / __data to
prevent any accidental version incapible usage.

UBIFS_DATA_NODE_SZ(c)
UBIFS_BRANCH_SZ(c)
These now take the ubifs_context and return the data structure's size 
according to the format version.

In create_default_filesystem, the fmt_version is set earlier so these 
macros behave correctly.


This was tested as follows:
1) A vanilla and modified module were both created. An empty drive was 
mounted under the vanilla
module to create a version 4 drive. Data was written to it
and integck was run (always a hundred times followed by powercut tests).
2) The module was switched to modified and it was mounted again. The data 
was read correctly and the
integck was run.
3) New data was written and it was mounted again under the vanilla 
modules. Both data was read again
and integck was run.
4) Finally, it was remounted under version 5 and the data correctly read 
and integck was run.

Additionally, an empty drive was mounted under the modified modules to 
create a version 5 drive.
1) Data was written to it and integck was run.
2) It was attempted to be mounted under the vanilla driver, but it did not 
succeed. Dmesg reports
version mismatch as the reason. A mounting attempted as read-only 
continued, but it failed when trying to read
the superblock.
3) It was remounted under the modified module where the data was correctly 
read back.


----------

Signed-off-by: Joel Reardon <reardonj at inf.ethz.ch>
diff -uprN -X linux-3.2.1-vanilla/Documentation/dontdiff 
linux-3.2.1-vanilla/fs/ubifs/commit.c 
linux-3.2.1-ubifsec/fs/ubifs/commit.c
--- linux-3.2.1-vanilla/fs/ubifs/commit.c	2012-01-12 
20:42:45.000000000 +0100
+++ linux-3.2.1-ubifsec/fs/ubifs/commit.c	2012-02-23 
15:06:49.107957279 +0100
@@ -650,7 +650,7 @@ int dbg_check_old_index(struct ubifs_inf
  		/* Check key range */
  		key_read(c, ubifs_idx_key(c, idx), &l_key);
  		br = ubifs_idx_branch(c, idx, child_cnt - 1);
-		key_read(c, &br->key, &u_key);
+		key_read(c, FMT_VERSION_BRANCH_POS_KEY(c, br), &u_key);
  		if (keys_cmp(c, &lower_key, &l_key) > 0) {
  			err = 5;
  			goto out_dump;
@@ -699,10 +699,11 @@ int dbg_check_old_index(struct ubifs_inf
  		lnum = le32_to_cpu(br->lnum);
  		offs = le32_to_cpu(br->offs);
  		len = le32_to_cpu(br->len);
-		key_read(c, &br->key, &lower_key);
+		key_read(c, FMT_VERSION_BRANCH_POS_KEY(c, br), 
&lower_key);
  		if (iip + 1 < le16_to_cpu(idx->child_cnt)) {
  			br = ubifs_idx_branch(c, idx, iip + 1);
-			key_read(c, &br->key, &upper_key);
+			key_read(c, FMT_VERSION_BRANCH_POS_KEY(c, br),
+				 &upper_key);
  		} else
  			key_copy(c, &i->upper_key, &upper_key);
  	}
diff -uprN -X linux-3.2.1-vanilla/Documentation/dontdiff 
linux-3.2.1-vanilla/fs/ubifs/debug.c linux-3.2.1-ubifsec/fs/ubifs/debug.c
--- linux-3.2.1-vanilla/fs/ubifs/debug.c	2012-01-12 
20:42:45.000000000 +0100
+++ linux-3.2.1-ubifsec/fs/ubifs/debug.c	2012-02-21 
22:27:01.222462655 +0100
@@ -538,7 +538,7 @@ void dbg_dump_node(const struct ubifs_in
  	case UBIFS_DATA_NODE:
  	{
  		const struct ubifs_data_node *dn = node;
-		int dlen = le32_to_cpu(ch->len) - UBIFS_DATA_NODE_SZ;
+		int dlen = le32_to_cpu(ch->len) - UBIFS_DATA_NODE_SZ(c);

  		key_read(c, &dn->key, &key);
  		printk(KERN_DEBUG "\tkey            %s\n", DBGKEY(&key));
@@ -550,7 +550,7 @@ void dbg_dump_node(const struct ubifs_in
  		       dlen);
  		printk(KERN_DEBUG "\tdata:\n");
  		print_hex_dump(KERN_DEBUG, "\t", DUMP_PREFIX_OFFSET, 32, 
1,
-			       (void *)&dn->data, dlen, 0);
+			       FMT_VERSION_DATA_NODE_POS_DATA(c, dn), 
dlen, 0);
  		break;
  	}
  	case UBIFS_TRUN_NODE:
@@ -579,7 +579,7 @@ void dbg_dump_node(const struct ubifs_in
  			const struct ubifs_branch *br;

  			br = ubifs_idx_branch(c, idx, i);
-			key_read(c, &br->key, &key);
+			key_read(c, FMT_VERSION_BRANCH_POS_KEY(c, br), 
&key);
  			printk(KERN_DEBUG "\t%d: LEB %d:%d len %d key 
%s\n",
  			       i, le32_to_cpu(br->lnum), 
le32_to_cpu(br->offs),
  			       le32_to_cpu(br->len), DBGKEY(&key));
diff -uprN -X linux-3.2.1-vanilla/Documentation/dontdiff 
linux-3.2.1-vanilla/fs/ubifs/file.c linux-3.2.1-ubifsec/fs/ubifs/file.c
--- linux-3.2.1-vanilla/fs/ubifs/file.c	2012-01-12 20:42:45.000000000 
+0100
+++ linux-3.2.1-ubifsec/fs/ubifs/file.c	2012-02-23 15:07:01.695957886 
+0100
@@ -77,10 +77,12 @@ static int read_block(struct inode *inod
  	if (len <= 0 || len > UBIFS_BLOCK_SIZE)
  		goto dump;

-	dlen = le32_to_cpu(dn->ch.len) - UBIFS_DATA_NODE_SZ;
+	dlen = le32_to_cpu(dn->ch.len) - UBIFS_DATA_NODE_SZ(c);
  	out_len = UBIFS_BLOCK_SIZE;
-	err = ubifs_decompress(&dn->data, dlen, addr, &out_len,
-			       le16_to_cpu(dn->compr_type));
+	err = ubifs_decompress(FMT_VERSION_DATA_NODE_POS_DATA(c, dn), 
dlen,
+			       addr, &out_len, 
le16_to_cpu(dn->compr_type));
+	if (FMT_VERSION_DATA_NODE_HAS_CRYPTO_LOOKUP(c))
+		ubifs_assert(le64_to_cpu(dn->crypto_lookup) == 0);
  	if (err || len != out_len)
  		goto dump;

@@ -646,10 +648,13 @@ static int populate_page(struct ubifs_in
  			if (len <= 0 || len > UBIFS_BLOCK_SIZE)
  				goto out_err;

-			dlen = le32_to_cpu(dn->ch.len) - 
UBIFS_DATA_NODE_SZ;
+			dlen = le32_to_cpu(dn->ch.len) - 
UBIFS_DATA_NODE_SZ(c);
  			out_len = UBIFS_BLOCK_SIZE;
-			err = ubifs_decompress(&dn->data, dlen, addr, 
&out_len,
- 
le16_to_cpu(dn->compr_type));
+			err =
+			ubifs_decompress(
+				FMT_VERSION_DATA_NODE_POS_DATA(c, dn),
+				dlen, addr, &out_len,
+				le16_to_cpu(dn->compr_type));
  			if (err || len != out_len)
  				goto out_err;

diff -uprN -X linux-3.2.1-vanilla/Documentation/dontdiff 
linux-3.2.1-vanilla/fs/ubifs/journal.c 
linux-3.2.1-ubifsec/fs/ubifs/journal.c
--- linux-3.2.1-vanilla/fs/ubifs/journal.c	2012-01-12 
20:42:45.000000000 +0100
+++ linux-3.2.1-ubifsec/fs/ubifs/journal.c	2012-02-23 
15:07:31.835959345 +0100
@@ -720,6 +720,8 @@ int ubifs_jnl_write_data(struct ubifs_in
  	key_write(c, key, &data->key);
  	data->size = cpu_to_le32(len);
  	zero_data_node_unused(data);
+	if (FMT_VERSION_DATA_NODE_HAS_CRYPTO_LOOKUP(c))
+		data->crypto_lookup = cpu_to_le64(0);

  	if (!(ui->flags & UBIFS_COMPR_FL))
  		/* Compression is disabled for this inode */
@@ -727,11 +729,12 @@ int ubifs_jnl_write_data(struct ubifs_in
  	else
  		compr_type = ui->compr_type;

-	out_len = dlen - UBIFS_DATA_NODE_SZ;
-	ubifs_compress(buf, len, &data->data, &out_len, &compr_type);
+	out_len = dlen - UBIFS_DATA_NODE_SZ(c);
+	ubifs_compress(buf, len, FMT_VERSION_DATA_NODE_POS_DATA(c, data),
+		       &out_len, &compr_type);
  	ubifs_assert(out_len <= UBIFS_BLOCK_SIZE);

-	dlen = UBIFS_DATA_NODE_SZ + out_len;
+	dlen = UBIFS_DATA_NODE_SZ(c) + out_len;
  	data->compr_type = cpu_to_le16(compr_type);

  	/* Make reservation before allocating sequence numbers */
@@ -1093,13 +1096,16 @@ out_free:

  /**
   * recomp_data_node - re-compress a truncated data node.
+ * @c: UBIFS file-system description object
   * @dn: data node to re-compress
   * @new_len: new length
   *
   * This function is used when an inode is truncated and the last data 
node of
   * the inode has to be re-compressed and re-written.
   */
-static int recomp_data_node(struct ubifs_data_node *dn, int *new_len)
+static int recomp_data_node(struct ubifs_info *c,
+			    struct ubifs_data_node *dn,
+			    int *new_len)
  {
  	void *buf;
  	int err, len, compr_type, out_len;
@@ -1109,17 +1115,20 @@ static int recomp_data_node(struct ubifs
  	if (!buf)
  		return -ENOMEM;

-	len = le32_to_cpu(dn->ch.len) - UBIFS_DATA_NODE_SZ;
+	len = le32_to_cpu(dn->ch.len) - UBIFS_DATA_NODE_SZ(c);
  	compr_type = le16_to_cpu(dn->compr_type);
-	err = ubifs_decompress(&dn->data, len, buf, &out_len, compr_type);
+	err = ubifs_decompress(FMT_VERSION_DATA_NODE_POS_DATA(c, dn),
+			       len, buf, &out_len, compr_type);
  	if (err)
  		goto out;

-	ubifs_compress(buf, *new_len, &dn->data, &out_len, &compr_type);
+	ubifs_compress(buf, *new_len, FMT_VERSION_DATA_NODE_POS_DATA(c, 
dn),
+		       &out_len, &compr_type);
+
  	ubifs_assert(out_len <= UBIFS_BLOCK_SIZE);
  	dn->compr_type = cpu_to_le16(compr_type);
  	dn->size = cpu_to_le32(*new_len);
-	*new_len = UBIFS_DATA_NODE_SZ + out_len;
+	*new_len = UBIFS_DATA_NODE_SZ(c) + out_len;
  out:
  	kfree(buf);
  	return err;
@@ -1190,12 +1199,12 @@ int ubifs_jnl_truncate(struct ubifs_info
  				int compr_type = 
le16_to_cpu(dn->compr_type);

  				if (compr_type != UBIFS_COMPR_NONE) {
-					err = recomp_data_node(dn, &dlen);
+					err = recomp_data_node(c, dn, 
&dlen);
  					if (err)
  						goto out_free;
  				} else {
  					dn->size = cpu_to_le32(dlen);
-					dlen += UBIFS_DATA_NODE_SZ;
+					dlen += UBIFS_DATA_NODE_SZ(c);
  				}
  				zero_data_node_unused(dn);
  			}
diff -uprN -X linux-3.2.1-vanilla/Documentation/dontdiff 
linux-3.2.1-vanilla/fs/ubifs/misc.h linux-3.2.1-ubifsec/fs/ubifs/misc.h
--- linux-3.2.1-vanilla/fs/ubifs/misc.h	2012-02-20 19:36:00.670753551 
+0100
+++ linux-3.2.1-ubifsec/fs/ubifs/misc.h	2012-02-23 15:09:47.899965933 
+0100
@@ -200,7 +200,8 @@ static inline int ubifs_return_leb(struc
   */
  static inline int ubifs_idx_node_sz(const struct ubifs_info *c, int 
child_cnt)
  {
-	return UBIFS_IDX_NODE_SZ + (UBIFS_BRANCH_SZ + c->key_len) * 
child_cnt;
+	return UBIFS_IDX_NODE_SZ
+	       + (UBIFS_BRANCH_SZ(c) + c->key_len) * child_cnt;
  }

  /**
@@ -214,8 +215,9 @@ struct ubifs_branch *ubifs_idx_branch(co
  				      const struct ubifs_idx_node *idx,
  				      int bnum)
  {
-	return (struct ubifs_branch *)((void *)idx->branches +
-				       (UBIFS_BRANCH_SZ + c->key_len) * 
bnum);
+	return (struct ubifs_branch *)
+		((void *)idx->branches + (UBIFS_BRANCH_SZ(c) + c->key_len)
+		* bnum);
  }

  /**
@@ -226,7 +228,8 @@ struct ubifs_branch *ubifs_idx_branch(co
  static inline void *ubifs_idx_key(const struct ubifs_info *c,
  				  const struct ubifs_idx_node *idx)
  {
-	return (void *)((struct ubifs_branch *)idx->branches)->key;
+	return (void *) FMT_VERSION_BRANCH_POS_KEY(
+		c, (struct ubifs_branch *)idx->branches);
  }

  /**
diff -uprN -X linux-3.2.1-vanilla/Documentation/dontdiff 
linux-3.2.1-vanilla/fs/ubifs/sb.c linux-3.2.1-ubifsec/fs/ubifs/sb.c
--- linux-3.2.1-vanilla/fs/ubifs/sb.c	2012-01-12 20:42:45.000000000 
+0100
+++ linux-3.2.1-ubifsec/fs/ubifs/sb.c	2012-02-22 11:39:51.480718000 
+0100
@@ -84,7 +84,7 @@ static int create_default_filesystem(str
  	int min_leb_cnt = UBIFS_MIN_LEB_CNT;
  	long long tmp64, main_bytes;
  	__le64 tmp_le64;
-
+	c->fmt_version = UBIFS_FORMAT_VERSION;
  	/* Some functions called from here depend on the @c->key_len filed 
*/
  	c->key_len = UBIFS_SK_LEN;

@@ -175,6 +175,7 @@ static int create_default_filesystem(str
  	sup->max_leb_cnt   = cpu_to_le32(c->max_leb_cnt);
  	sup->max_bud_bytes = cpu_to_le64(tmp64);
  	sup->log_lebs      = cpu_to_le32(log_lebs);
+	sup->crypto_lebs   = cpu_to_le32(0);
  	sup->lpt_lebs      = cpu_to_le32(lpt_lebs);
  	sup->orph_lebs     = cpu_to_le32(orph_lebs);
  	sup->jhead_cnt     = cpu_to_le32(DEFAULT_JHEADS_CNT);
@@ -182,6 +183,7 @@ static int create_default_filesystem(str
  	sup->lsave_cnt     = cpu_to_le32(c->lsave_cnt);
  	sup->fmt_version   = cpu_to_le32(UBIFS_FORMAT_VERSION);
  	sup->time_gran     = cpu_to_le32(DEFAULT_TIME_GRAN);
+	sup->use_ubifsec   = cpu_to_le32(0);
  	if (c->mount_opts.override_compr)
  		sup->default_compr = 
cpu_to_le16(c->mount_opts.compr_type);
  	else
@@ -279,7 +281,7 @@ static int create_default_filesystem(str
  	idx->child_cnt = cpu_to_le16(1);
  	ino_key_init(c, &key, UBIFS_ROOT_INO);
  	br = ubifs_idx_branch(c, idx, 0);
-	key_write_idx(c, &key, &br->key);
+	key_write_idx(c, &key, FMT_VERSION_BRANCH_POS_KEY(c, br));
  	br->lnum = cpu_to_le32(main_first + DEFAULT_DATA_LEB);
  	br->len  = cpu_to_le32(UBIFS_INO_NODE_SZ);
  	err = ubifs_write_node(c, idx, tmp, main_first + DEFAULT_IDX_LEB, 
0,
@@ -610,6 +612,10 @@ int ubifs_read_superblock(struct ubifs_i
  	c->rp_size       = le64_to_cpu(sup->rp_size);
  	c->rp_uid        = le32_to_cpu(sup->rp_uid);
  	c->rp_gid        = le32_to_cpu(sup->rp_gid);
+	if (c->fmt_version > 4) {
+		ubifs_assert(le32_to_cpu(sup->crypto_lebs) == 0);
+		ubifs_assert(le32_to_cpu(sup->use_ubifsec) == 0);
+	}
  	sup_flags        = le32_to_cpu(sup->flags);
  	if (!c->mount_opts.override_compr)
  		c->default_compr = le16_to_cpu(sup->default_compr);
diff -uprN -X linux-3.2.1-vanilla/Documentation/dontdiff 
linux-3.2.1-vanilla/fs/ubifs/super.c linux-3.2.1-ubifsec/fs/ubifs/super.c
--- linux-3.2.1-vanilla/fs/ubifs/super.c	2012-02-20 
19:36:03.478753687 +0100
+++ linux-3.2.1-ubifsec/fs/ubifs/super.c	2012-02-21 
22:20:04.478442495 +0100
@@ -585,13 +585,14 @@ static int init_constants_early(struct u
  	c->ranges[UBIFS_DENT_NODE].max_len = UBIFS_MAX_DENT_NODE_SZ;
  	c->ranges[UBIFS_XENT_NODE].min_len = UBIFS_XENT_NODE_SZ;
  	c->ranges[UBIFS_XENT_NODE].max_len = UBIFS_MAX_XENT_NODE_SZ;
-	c->ranges[UBIFS_DATA_NODE].min_len = UBIFS_DATA_NODE_SZ;
+	c->ranges[UBIFS_DATA_NODE].min_len = UBIFS_DATA_NODE_VMIN_SZ;
  	c->ranges[UBIFS_DATA_NODE].max_len = UBIFS_MAX_DATA_NODE_SZ;
  	/*
  	 * Minimum indexing node size is amended later when superblock is
  	 * read and the key length is known.
  	 */
-	c->ranges[UBIFS_IDX_NODE].min_len = UBIFS_IDX_NODE_SZ + 
UBIFS_BRANCH_SZ;
+	c->ranges[UBIFS_IDX_NODE].min_len = UBIFS_IDX_NODE_SZ +
+					    UBIFS_BRANCH_SZ(c);
  	/*
  	 * Maximum indexing node size is amended later when superblock is
  	 * read and the fanout is known.
@@ -1463,7 +1464,7 @@ static int mount_ubifs(struct ubifs_info
  	dbg_msg("max. znode size      %d", c->max_znode_sz);
  	dbg_msg("max. index node size %d", c->max_idx_node_sz);
  	dbg_msg("node sizes:          data %zu, inode %zu, dentry %zu",
-		UBIFS_DATA_NODE_SZ, UBIFS_INO_NODE_SZ, 
UBIFS_DENT_NODE_SZ);
+		UBIFS_DATA_NODE_SZ(c), UBIFS_INO_NODE_SZ, 
UBIFS_DENT_NODE_SZ);
  	dbg_msg("node sizes:          trun %zu, sb %zu, master %zu",
  		UBIFS_TRUN_NODE_SZ, UBIFS_SB_NODE_SZ, UBIFS_MST_NODE_SZ);
  	dbg_msg("node sizes:          ref %zu, cmt. start %zu, orph %zu",
@@ -2213,7 +2214,8 @@ static int __init ubifs_init(void)
  	BUILD_BUG_ON(UBIFS_INO_NODE_SZ  & 7);
  	BUILD_BUG_ON(UBIFS_DENT_NODE_SZ & 7);
  	BUILD_BUG_ON(UBIFS_XENT_NODE_SZ & 7);
-	BUILD_BUG_ON(UBIFS_DATA_NODE_SZ & 7);
+	BUILD_BUG_ON(UBIFS_DATA_NODE_V4_SZ & 7);
+	BUILD_BUG_ON(UBIFS_DATA_NODE_V5_SZ & 7);
  	BUILD_BUG_ON(UBIFS_TRUN_NODE_SZ & 7);
  	BUILD_BUG_ON(UBIFS_SB_NODE_SZ   & 7);
  	BUILD_BUG_ON(UBIFS_MST_NODE_SZ  & 7);
diff -uprN -X linux-3.2.1-vanilla/Documentation/dontdiff 
linux-3.2.1-vanilla/fs/ubifs/tnc_commit.c 
linux-3.2.1-ubifsec/fs/ubifs/tnc_commit.c
--- linux-3.2.1-vanilla/fs/ubifs/tnc_commit.c	2012-01-12 
20:42:45.000000000 +0100
+++ linux-3.2.1-ubifsec/fs/ubifs/tnc_commit.c	2012-02-23 
15:09:27.295964938 +0100
@@ -48,9 +48,13 @@ static int make_idx_node(struct ubifs_in
  		struct ubifs_branch *br = ubifs_idx_branch(c, idx, i);
  		struct ubifs_zbranch *zbr = &znode->zbranch[i];

-		key_write_idx(c, &zbr->key, &br->key);
+		key_write_idx(c, &zbr->key, FMT_VERSION_BRANCH_POS_KEY(c, 
br));
  		br->lnum = cpu_to_le32(zbr->lnum);
  		br->offs = cpu_to_le32(zbr->offs);
+		if (key_type(c, &zbr->key) == UBIFS_DATA_KEY) {
+			if (FMT_VERSION_BRANCH_HAS_CRYPTO_LOOKUP(c))
+				br->crypto_lookup = cpu_to_le64(0);
+		}
  		br->len = cpu_to_le32(zbr->len);
  		if (!zbr->lnum || !zbr->len) {
  			ubifs_err("bad ref in znode");
@@ -858,7 +862,12 @@ static int write_index(struct ubifs_info
  			struct ubifs_branch *br = ubifs_idx_branch(c, idx, 
i);
  			struct ubifs_zbranch *zbr = &znode->zbranch[i];

-			key_write_idx(c, &zbr->key, &br->key);
+			key_write_idx(c, &zbr->key,
+				      FMT_VERSION_BRANCH_POS_KEY(c, br));
+			if (key_type(c, &zbr->key) == UBIFS_DATA_KEY) {
+				if 
(FMT_VERSION_BRANCH_HAS_CRYPTO_LOOKUP(c))
+					br->crypto_lookup = 
cpu_to_le64(0);
+			}
  			br->lnum = cpu_to_le32(zbr->lnum);
  			br->offs = cpu_to_le32(zbr->offs);
  			br->len = cpu_to_le32(zbr->len);
diff -uprN -X linux-3.2.1-vanilla/Documentation/dontdiff 
linux-3.2.1-vanilla/fs/ubifs/tnc_misc.c 
linux-3.2.1-ubifsec/fs/ubifs/tnc_misc.c
--- linux-3.2.1-vanilla/fs/ubifs/tnc_misc.c	2012-01-12 
20:42:45.000000000 +0100
+++ linux-3.2.1-ubifsec/fs/ubifs/tnc_misc.c	2012-02-21 
13:13:01.775280827 +0100
@@ -305,7 +305,7 @@ static int read_znode(struct ubifs_info
  		const struct ubifs_branch *br = ubifs_idx_branch(c, idx, 
i);
  		struct ubifs_zbranch *zbr = &znode->zbranch[i];

-		key_read(c, &br->key, &zbr->key);
+		key_read(c, FMT_VERSION_BRANCH_POS_KEY(c, br), &zbr->key);
  		zbr->lnum = le32_to_cpu(br->lnum);
  		zbr->offs = le32_to_cpu(br->offs);
  		zbr->len  = le32_to_cpu(br->len);
diff -uprN -X linux-3.2.1-vanilla/Documentation/dontdiff 
linux-3.2.1-vanilla/fs/ubifs/ubifs.h linux-3.2.1-ubifsec/fs/ubifs/ubifs.h
--- linux-3.2.1-vanilla/fs/ubifs/ubifs.h	2012-01-12 
20:42:45.000000000 +0100
+++ linux-3.2.1-ubifsec/fs/ubifs/ubifs.h	2012-02-21 
22:07:55.582407209 +0100
@@ -73,7 +73,7 @@
  #define MIN_INDEX_LEBS 2

  /* Minimum amount of data UBIFS writes to the flash */
-#define MIN_WRITE_SZ (UBIFS_DATA_NODE_SZ + 8)
+#define MIN_WRITE_SZ (UBIFS_DATA_NODE_VMIN_SZ + 8)

  /*
   * Currently we do not support inode number overlapping and re-using, so 
this
@@ -155,7 +155,7 @@
   * How much memory is needed for a buffer where we comress a data node.
   */
  #define COMPRESSED_DATA_NODE_BUF_SZ \
-	(UBIFS_DATA_NODE_SZ + UBIFS_BLOCK_SIZE * WORST_COMPR_FACTOR)
+	(UBIFS_DATA_NODE_VMAX_SZ + UBIFS_BLOCK_SIZE * WORST_COMPR_FACTOR)

  /* Maximum expected tree height for use by bottom_up_buf */
  #define BOTTOM_UP_HEIGHT 64
diff -uprN -X linux-3.2.1-vanilla/Documentation/dontdiff 
linux-3.2.1-vanilla/fs/ubifs/ubifs-media.h 
linux-3.2.1-ubifsec/fs/ubifs/ubifs-media.h
--- linux-3.2.1-vanilla/fs/ubifs/ubifs-media.h	2012-01-12 
20:42:45.000000000 +0100
+++ linux-3.2.1-ubifsec/fs/ubifs/ubifs-media.h	2012-02-23 
15:12:45.971974550 +0100
@@ -44,9 +44,23 @@
   * a new feature.
   *
   * UBIFS went into mainline kernel with format version 4. The older 
formats
- * were development formats.
- */
-#define UBIFS_FORMAT_VERSION 4
+ * were development formats.  Version 5 is then used for secure deletion
+ * enhancement. N.B.: when adding new versions that also have this field,
+ * include the version in the data_struct_has_field defines below.
+ */
+#define UBIFS_FORMAT_VERSION 5
+#define FMT_VERSION_BRANCH_HAS_CRYPTO_LOOKUP(c) ((c)->fmt_version == 5)
+#define FMT_VERSION_DATA_NODE_HAS_CRYPTO_LOOKUP(c) ((c)->fmt_version == 
5)
+#define FMT_VERSION_DATA_NODE_POS_DATA(c, dn)				\
+	(FMT_VERSION_DATA_NODE_HAS_CRYPTO_LOOKUP(c) ?			\
+	((void *) (&((dn)->__data))) :					\
+	((void *) (&((dn)->crypto_lookup))))
+
+#define FMT_VERSION_BRANCH_POS_KEY(c, br)				\
+	(FMT_VERSION_BRANCH_HAS_CRYPTO_LOOKUP(c) ?			\
+	((void *) (&((br)->__key))) :					\
+	((void *) (&((br)->crypto_lookup))))
+

  /*
   * Read-only compatibility version. If the UBIFS format is changed, older 
UBIFS
@@ -274,25 +288,33 @@ enum {
  			   UBIFS_MIN_ORPH_LEBS + UBIFS_MIN_MAIN_LEBS)

  /* Node sizes (N.B. these are guaranteed to be multiples of 8) */
-#define UBIFS_CH_SZ        sizeof(struct ubifs_ch)
-#define UBIFS_INO_NODE_SZ  sizeof(struct ubifs_ino_node)
-#define UBIFS_DATA_NODE_SZ sizeof(struct ubifs_data_node)
-#define UBIFS_DENT_NODE_SZ sizeof(struct ubifs_dent_node)
-#define UBIFS_TRUN_NODE_SZ sizeof(struct ubifs_trun_node)
-#define UBIFS_PAD_NODE_SZ  sizeof(struct ubifs_pad_node)
-#define UBIFS_SB_NODE_SZ   sizeof(struct ubifs_sb_node)
-#define UBIFS_MST_NODE_SZ  sizeof(struct ubifs_mst_node)
-#define UBIFS_REF_NODE_SZ  sizeof(struct ubifs_ref_node)
-#define UBIFS_IDX_NODE_SZ  sizeof(struct ubifs_idx_node)
-#define UBIFS_CS_NODE_SZ   sizeof(struct ubifs_cs_node)
-#define UBIFS_ORPH_NODE_SZ sizeof(struct ubifs_orph_node)
+#define UBIFS_CH_SZ            sizeof(struct ubifs_ch)
+#define UBIFS_INO_NODE_SZ      sizeof(struct ubifs_ino_node)
+#define UBIFS_DATA_NODE_SZ(c)   (sizeof(struct ubifs_data_node) \
+	- (FMT_VERSION_BRANCH_HAS_CRYPTO_LOOKUP(c) ? 0 : sizeof(__u64)))
+/* The min and max data node header size across all version */
+#define UBIFS_DATA_NODE_V4_SZ (sizeof(struct ubifs_data_node) - 
sizeof(__u64))
+#define UBIFS_DATA_NODE_V5_SZ (sizeof(struct ubifs_data_node))
+#define UBIFS_DATA_NODE_VMIN_SZ UBIFS_DATA_NODE_V4_SZ
+#define UBIFS_DATA_NODE_VMAX_SZ UBIFS_DATA_NODE_V5_SZ
+
+#define UBIFS_DENT_NODE_SZ     sizeof(struct ubifs_dent_node)
+#define UBIFS_TRUN_NODE_SZ     sizeof(struct ubifs_trun_node)
+#define UBIFS_PAD_NODE_SZ      sizeof(struct ubifs_pad_node)
+#define UBIFS_SB_NODE_SZ       sizeof(struct ubifs_sb_node)
+#define UBIFS_MST_NODE_SZ      sizeof(struct ubifs_mst_node)
+#define UBIFS_REF_NODE_SZ      sizeof(struct ubifs_ref_node)
+#define UBIFS_IDX_NODE_SZ      sizeof(struct ubifs_idx_node)
+#define UBIFS_CS_NODE_SZ       sizeof(struct ubifs_cs_node)
+#define UBIFS_ORPH_NODE_SZ     sizeof(struct ubifs_orph_node)
  /* Extended attribute entry nodes are identical to directory entry nodes 
*/
  #define UBIFS_XENT_NODE_SZ UBIFS_DENT_NODE_SZ
  /* Only this does not have to be multiple of 8 bytes */
-#define UBIFS_BRANCH_SZ    sizeof(struct ubifs_branch)
+#define UBIFS_BRANCH_SZ(c)    (sizeof(struct ubifs_branch)  \
+	- (FMT_VERSION_BRANCH_HAS_CRYPTO_LOOKUP(c) ? 0 : sizeof(__u64)))

  /* Maximum node sizes (N.B. these are guaranteed to be multiples of 8) */
-#define UBIFS_MAX_DATA_NODE_SZ  (UBIFS_DATA_NODE_SZ + UBIFS_BLOCK_SIZE)
+#define UBIFS_MAX_DATA_NODE_SZ  (UBIFS_DATA_NODE_VMAX_SZ + 
UBIFS_BLOCK_SIZE)
  #define UBIFS_MAX_INO_NODE_SZ   (UBIFS_INO_NODE_SZ + UBIFS_MAX_INO_DATA)
  #define UBIFS_MAX_DENT_NODE_SZ  (UBIFS_DENT_NODE_SZ + UBIFS_MAX_NLEN + 1)
  #define UBIFS_MAX_XENT_NODE_SZ  UBIFS_MAX_DENT_NODE_SZ
@@ -549,6 +571,18 @@ struct ubifs_dent_node {
   *
   * Note, do not forget to amend 'zero_data_node_unused()' function when
   * changing the padding fields.
+ *
+ * This data structure format is version 5, which includes the 
@crypto_lookup
+ * field. Since @data is unbounded, the new field must be before it.
+ * Compatibility macros:
+ * FMT_VERSION_DATA_NODE_POS_DATA: returns a pointer to the appropriate 
place
+ *				   where the key begins for the current
+ *				   mounted version.
+ * FMT_VERSION_DATA_NODE_HAS_CRYPTO_LOOKUP: true if the current mounted
+ *					    version contains the
+ *					    @crypto_lookup field.
+ * UBIFS_DATA_NODE_SZ: now returns the appropriate size for this data 
structure
+ *		       depending on the version.
   */
  struct ubifs_data_node {
  	struct ubifs_ch ch;
@@ -556,7 +590,8 @@ struct ubifs_data_node {
  	__le32 size;
  	__le16 compr_type;
  	__u8 padding[2]; /* Watch 'zero_data_node_unused()' if changing! 
*/
-	__u8 data[];
+	__u64 crypto_lookup;
+	__u8 __data[];
  } __packed;

  /**
@@ -614,10 +649,12 @@ struct ubifs_pad_node {
   * @rp_uid: reserve pool UID
   * @rp_gid: reserve pool GID
   * @rp_size: size of the reserved pool in bytes
- * @padding2: reserved for future, zeroes
   * @time_gran: time granularity in nanoseconds
   * @uuid: UUID generated when the file system image was created
   * @ro_compat_version: UBIFS R/O compatibility version
+ * @crypto_lebs: number of LEBS being used to store keys
+ * @use_ubifsec: whether the file system should use ubifsec secure 
deletion
+ * @padding2: reserved for future, zeroes
   */
  struct ubifs_sb_node {
  	struct ubifs_ch ch;
@@ -645,7 +682,9 @@ struct ubifs_sb_node {
  	__le32 time_gran;
  	__u8 uuid[16];
  	__le32 ro_compat_version;
-	__u8 padding2[3968];
+	__le32 crypto_lebs;
+	__u8 use_ubifsec;
+	__u8 padding2[3963];
  } __packed;

  /**
@@ -736,13 +775,25 @@ struct ubifs_ref_node {
   * @lnum: LEB number of the target node
   * @offs: offset within @lnum
   * @len: target node length
- * @key: key
+ * @__key: key.
+ *
+ * This data structure format is version 5, which includes the 
crypto_lookup
+ * field. Since key is unbounded, the new field must be before it.
+ * Compatibility macros:
+ * FMT_VERSION_BRANCH_POS_KEY: returns a pointer to the appropriate place
+ *			       where the key begins for the current 
mounted
+ *			       version.
+ * FMT_VERSION_BRANCH_HAS_CRYPTO_LOOKUP: true if the current mounted 
version
+ *					 contains the crypto_lookup field.
+ * UBIFS_BRANCH_SZ: now returns the appropriate size for this data 
structure
+ *		    depending on the version.
   */
  struct ubifs_branch {
  	__le32 lnum;
  	__le32 offs;
  	__le32 len;
-	__u8 key[];
+	__le64 crypto_lookup;
+	__u8 __key[];
  } __packed;

  /**
@@ -750,7 +801,7 @@ struct ubifs_branch {
   * @ch: common header
   * @child_cnt: number of child index nodes
   * @level: tree level
- * @branches: LEB number / offset / length / key branches
+ * @branches: LEB number / offset / length / crypto_lookup / key branches
   */
  struct ubifs_idx_node {
  	struct ubifs_ch ch;




More information about the linux-mtd mailing list