[PATCH] UBIFS: compute KSA size and store in superblock

Joel Reardon joel at clambassador.com
Fri May 25 09:10:48 EDT 2012


This patch makes the super block reserve space for the KSA. It computes the
number of KSA LEBs and adds the ksa_lebs to on-medium superblock. The value is
read off the media. The decision to use a KSA is controlled by use_ubifsec
switch, also added to the superblock, ubifs_info, and is controlled as a mount
option.

This is tested by creating a drive and checking the mount debug output. The
number of LEBS assigned during create_default_filesystem was changed to ensure
that remounting does infact read the old value. When the use_ubifsec option
was not enabled, no LEBs were assigned. Integck was run and the drive was
filled to capacity. The LEBs in the KSA were not used when filled.

Signed-off-by: Joel Reardon <reardonj at inf.ethz.ch>
---
 fs/ubifs/sb.c          |   29 ++++++++++++++++++++++++++---
 fs/ubifs/super.c       |   15 +++++++++++++++
 fs/ubifs/ubifs-media.h |    8 ++++++--
 fs/ubifs/ubifs.h       |   23 ++++++++++++++++++++++-
 4 files changed, 69 insertions(+), 6 deletions(-)

diff --git a/fs/ubifs/sb.c b/fs/ubifs/sb.c
index f98d284..5583f2e 100644
--- a/fs/ubifs/sb.c
+++ b/fs/ubifs/sb.c
@@ -82,6 +82,7 @@ static int create_default_filesystem(struct ubifs_info *c)
 	int err, tmp, jnl_lebs, log_lebs, max_buds, main_lebs, main_first;
 	int lpt_lebs, lpt_first, orph_lebs, big_lpt, ino_waste, sup_flags = 0;
 	int min_leb_cnt = UBIFS_MIN_LEB_CNT;
+	int ksa_lebs = 0, ksa_first;
 	long long tmp64, main_bytes;
 	__le64 tmp_le64;

@@ -138,7 +139,21 @@ static int create_default_filesystem(struct ubifs_info *c)
 		 */
 		orph_lebs += 1;

-	main_lebs = c->leb_cnt - UBIFS_SB_LEBS - UBIFS_MST_LEBS - log_lebs;
+	if (c->use_ubifsec) {
+		/*
+		 * Compute the size of the key space area based on partition
+		 * geometry. The following calculation is equivalant to:
+		 * LEBS * LEB_SIZE / DATANODE_SIZE / KEYS_PER_KSA_LEB, because
+		 * KEYS_PER_KSA_LEB = LEB_SIZE / KEY_SIZE.
+		 */
+		ksa_lebs = (c->leb_cnt * UBIFS_CRYPTO_KEYSIZE)
+			>> UBIFS_BLOCK_SHIFT;
+		ksa_lebs += ksa_lebs >> UBIFS_KSA_LEBS_SCALE_SHIFT;
+		ksa_lebs += UBIFS_KSA_ADD_LEBS;
+	}
+
+	main_lebs = c->leb_cnt - UBIFS_SB_LEBS - UBIFS_MST_LEBS
+		    - log_lebs - ksa_lebs;
 	main_lebs -= orph_lebs;

 	lpt_first = UBIFS_LOG_LNUM + log_lebs;
@@ -153,6 +168,7 @@ static int create_default_filesystem(struct ubifs_info *c)
 		lpt_first + lpt_lebs - 1);

 	main_first = c->leb_cnt - main_lebs;
+	ksa_first = c->leb_cnt - main_lebs - ksa_lebs;

 	/* Create default superblock */
 	tmp = ALIGN(UBIFS_SB_NODE_SZ, c->min_io_size);
@@ -173,6 +189,7 @@ static int create_default_filesystem(struct ubifs_info *c)
 	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->ksa_lebs	   = cpu_to_le32(ksa_lebs);
 	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);
@@ -180,6 +197,7 @@ static int create_default_filesystem(struct ubifs_info *c)
 	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(c->use_ubifsec);
 	if (c->mount_opts.override_compr)
 		sup->default_compr = cpu_to_le16(c->mount_opts.compr_type);
 	else
@@ -444,7 +462,7 @@ static int validate_sb(struct ubifs_info *c, struct ubifs_sb_node *sup)
 	}

 	if (UBIFS_SB_LEBS + UBIFS_MST_LEBS + c->log_lebs + c->lpt_lebs +
-	    c->orph_lebs + c->main_lebs != c->leb_cnt) {
+	    c->orph_lebs + c->main_lebs + c->ksa_lebs != c->leb_cnt) {
 		err = 12;
 		goto failed;
 	}
@@ -605,6 +623,7 @@ int ubifs_read_superblock(struct ubifs_info *c)
 	c->max_leb_cnt   = le32_to_cpu(sup->max_leb_cnt);
 	c->max_bud_bytes = le64_to_cpu(sup->max_bud_bytes);
 	c->log_lebs      = le32_to_cpu(sup->log_lebs);
+	c->ksa_lebs	 = le32_to_cpu(sup->ksa_lebs);
 	c->lpt_lebs      = le32_to_cpu(sup->lpt_lebs);
 	c->orph_lebs     = le32_to_cpu(sup->orph_lebs);
 	c->jhead_cnt     = le32_to_cpu(sup->jhead_cnt) + NONDATA_JHEADS_CNT;
@@ -613,6 +632,7 @@ int ubifs_read_superblock(struct ubifs_info *c)
 	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);
+	c->use_ubifsec   = le32_to_cpu(sup->use_ubifsec);
 	sup_flags        = le32_to_cpu(sup->flags);
 	if (!c->mount_opts.override_compr)
 		c->default_compr = le16_to_cpu(sup->default_compr);
@@ -646,8 +666,11 @@ int ubifs_read_superblock(struct ubifs_info *c)
 	c->lpt_last = c->lpt_first + c->lpt_lebs - 1;
 	c->orph_first = c->lpt_last + 1;
 	c->orph_last = c->orph_first + c->orph_lebs - 1;
-	c->main_lebs = c->leb_cnt - UBIFS_SB_LEBS - UBIFS_MST_LEBS;
+	c->main_lebs = c->leb_cnt - UBIFS_SB_LEBS - UBIFS_MST_LEBS
+		       - c->ksa_lebs;
 	c->main_lebs -= c->log_lebs + c->lpt_lebs + c->orph_lebs;
+	c->ksa_first = c->leb_cnt - c->main_lebs - c->ksa_lebs;
+	c->ksa_last = c->ksa_first + c->ksa_lebs - 1;
 	c->main_first = c->leb_cnt - c->main_lebs;

 	err = validate_sb(c, sup);
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
index d2fd76f..879ecf5 100644
--- a/fs/ubifs/super.c
+++ b/fs/ubifs/super.c
@@ -438,6 +438,8 @@ static int ubifs_show_options(struct seq_file *s, struct dentry *root)
 	else if (c->mount_opts.chk_data_crc == 1)
 		seq_printf(s, ",no_chk_data_crc");

+	if (c->mount_opts.use_ubifsec)
+		seq_printf(s, ",use_ubifsec");
 	if (c->mount_opts.override_compr) {
 		seq_printf(s, ",compr=%s",
 			   ubifs_compr_name(c->mount_opts.compr_type));
@@ -934,6 +936,7 @@ static int check_volume_empty(struct ubifs_info *c)
  * Opt_chk_data_crc: check CRCs when reading data nodes
  * Opt_no_chk_data_crc: do not check CRCs when reading data nodes
  * Opt_override_compr: override default compressor
+ * Opt_use_ubifsec: use ubifsec secure deletion feature
  * Opt_err: just end of array marker
  */
 enum {
@@ -944,6 +947,7 @@ enum {
 	Opt_chk_data_crc,
 	Opt_no_chk_data_crc,
 	Opt_override_compr,
+	Opt_use_ubifsec,
 	Opt_err,
 };

@@ -955,6 +959,7 @@ static const match_table_t tokens = {
 	{Opt_chk_data_crc, "chk_data_crc"},
 	{Opt_no_chk_data_crc, "no_chk_data_crc"},
 	{Opt_override_compr, "compr=%s"},
+	{Opt_use_ubifsec, "use_ubifsec"},
 	{Opt_err, NULL},
 };

@@ -1054,6 +1059,12 @@ static int ubifs_parse_options(struct ubifs_info *c, char *options,
 			c->default_compr = c->mount_opts.compr_type;
 			break;
 		}
+		case Opt_use_ubifsec:
+		{
+			c->mount_opts.use_ubifsec = 1;
+			c->use_ubifsec = 1;
+			break;
+		}
 		default:
 		{
 			unsigned long flag;
@@ -1446,6 +1457,9 @@ static int mount_ubifs(struct ubifs_info *c)
 		c->lpt_lebs, c->lpt_first, c->lpt_last);
 	dbg_msg("orphan area LEBs:    %d (%d - %d)",
 		c->orph_lebs, c->orph_first, c->orph_last);
+	if (c->ksa_lebs)
+		dbg_msg("KSA LEBs:            %d (%d - %d)",
+			c->ksa_lebs, c->ksa_first, c->ksa_last);
 	dbg_msg("main area LEBs:      %d (%d - %d)",
 		c->main_lebs, c->main_first, c->leb_cnt - 1);
 	dbg_msg("index LEBs:          %d", c->lst.idx_lebs);
@@ -1483,6 +1497,7 @@ static int mount_ubifs(struct ubifs_info *c)
 		c->bud_bytes, c->bud_bytes >> 10, c->bud_bytes >> 20);
 	dbg_msg("max. seq. number:    %llu", c->max_sqnum);
 	dbg_msg("commit number:       %llu", c->cmt_no);
+	dbg_msg("use ubifsec:         %d", c->use_ubifsec);

 	return 0;

diff --git a/fs/ubifs/ubifs-media.h b/fs/ubifs/ubifs-media.h
index 90f348c..905608b 100644
--- a/fs/ubifs/ubifs-media.h
+++ b/fs/ubifs/ubifs-media.h
@@ -618,10 +618,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 secure deletion
+ * @padding2: reserved for future, zeroes
  */
 struct ubifs_sb_node {
 	struct ubifs_ch ch;
@@ -649,7 +651,9 @@ struct ubifs_sb_node {
 	__le32 time_gran;
 	__u8 uuid[16];
 	__le32 ro_compat_version;
-	__u8 padding2[3968];
+	__le32 ksa_lebs;
+	__u8 use_ubifsec;
+	__u8 padding2[3963];
 } __packed;

 /**
diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h
index d7f639a..f34ab84 100644
--- a/fs/ubifs/ubifs.h
+++ b/fs/ubifs/ubifs.h
@@ -164,6 +164,16 @@
 #define UBIFS_CRYPTO_KEYSIZE 16
 /* AES in counter mode is the encryption algorithm */
 #define UBIFS_CRYPTO_ALGORITHM "ctr(aes)"
+/*
+ * Constant number of KSA LEBS to add to computed value, ensuring two plus a
+ * checkpoint LEB.
+ */
+#define UBIFS_KSA_ADD_LEBS 3
+/*
+ * KSA LEBS is 1.125 * the computed min to allow unused keys when the drive is
+ * full. This shift is used to compute 0.125 * LEBS.
+ */
+#define UBIFS_KSA_LEBS_SCALE_SHIFT 3

 /*
  * Lockdep classes for UBIFS inode @ui_mutex.
@@ -934,6 +944,7 @@ struct ubifs_orphan {
  *                  specified in @compr_type)
  * @compr_type: compressor type to override the superblock compressor with
  *              (%UBIFS_COMPR_NONE, etc)
+ * @use_ubifsec: use ubifsec secure deletion feature
  */
 struct ubifs_mount_opts {
 	unsigned int unmount_mode:2;
@@ -941,6 +952,7 @@ struct ubifs_mount_opts {
 	unsigned int chk_data_crc:2;
 	unsigned int override_compr:1;
 	unsigned int compr_type:2;
+	unsigned int use_ubifsec:1;
 };

 /**
@@ -1224,7 +1236,11 @@ struct ubifs_debug_info;
  * @size_tree: inode size information for recovery
  * @mount_opts: UBIFS-specific mount options
  *
- * @keymap: cryptographic key store for secure deletion
+ * @km: cryptographic key store for secure deletion
+ * @ksa_lebs: number of LEBS assigned to the KSA
+ * @ksa_first: number of the first LEB assigned to the KSA
+ * @ksa_last: number of the last LEB assigned to the KSA
+ * @use_ubifsec: switch to enable/disable secure deletion for UBIFS
  * @dbg: debugging-related information
  */
 struct ubifs_info {
@@ -1454,6 +1470,11 @@ struct ubifs_info {
 	struct ubifs_mount_opts mount_opts;

 	struct ubifs_keymap *km;
+	int ksa_lebs;
+	int ksa_first;
+	int ksa_last;
+	int use_ubifsec;
+
 	struct ubifs_debug_info *dbg;
 };

-- 
1.7.5.4





More information about the linux-mtd mailing list