Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8663da2c authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull ext4 fixes from Ted Ts'o:
 "Some miscellaneous bug fixes and some final on-disk and ABI changes
  for ext4 encryption which provide better security and performance"

* tag 'for_linus_stable' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4:
  ext4: fix growing of tiny filesystems
  ext4: move check under lock scope to close a race.
  ext4: fix data corruption caused by unwritten and delayed extents
  ext4 crypto: remove duplicated encryption mode definitions
  ext4 crypto: do not select from EXT4_FS_ENCRYPTION
  ext4 crypto: add padding to filenames before encrypting
  ext4 crypto: simplify and speed up filename encryption
parents 101a6fd3 2c869b26
Loading
Loading
Loading
Loading
+7 −2
Original line number Original line Diff line number Diff line
@@ -64,8 +64,8 @@ config EXT4_FS_SECURITY
	  If you are not using a security module that requires using
	  If you are not using a security module that requires using
	  extended attributes for file security labels, say N.
	  extended attributes for file security labels, say N.


config EXT4_FS_ENCRYPTION
config EXT4_ENCRYPTION
	bool "Ext4 Encryption"
	tristate "Ext4 Encryption"
	depends on EXT4_FS
	depends on EXT4_FS
	select CRYPTO_AES
	select CRYPTO_AES
	select CRYPTO_CBC
	select CRYPTO_CBC
@@ -81,6 +81,11 @@ config EXT4_FS_ENCRYPTION
	  efficient since it avoids caching the encrypted and
	  efficient since it avoids caching the encrypted and
	  decrypted pages in the page cache.
	  decrypted pages in the page cache.


config EXT4_FS_ENCRYPTION
	bool
	default y
	depends on EXT4_ENCRYPTION

config EXT4_DEBUG
config EXT4_DEBUG
	bool "EXT4 debugging support"
	bool "EXT4 debugging support"
	depends on EXT4_FS
	depends on EXT4_FS
+145 −135
Original line number Original line Diff line number Diff line
@@ -66,6 +66,7 @@ static int ext4_fname_encrypt(struct ext4_fname_crypto_ctx *ctx,
	int res = 0;
	int res = 0;
	char iv[EXT4_CRYPTO_BLOCK_SIZE];
	char iv[EXT4_CRYPTO_BLOCK_SIZE];
	struct scatterlist sg[1];
	struct scatterlist sg[1];
	int padding = 4 << (ctx->flags & EXT4_POLICY_FLAGS_PAD_MASK);
	char *workbuf;
	char *workbuf;


	if (iname->len <= 0 || iname->len > ctx->lim)
	if (iname->len <= 0 || iname->len > ctx->lim)
@@ -73,6 +74,7 @@ static int ext4_fname_encrypt(struct ext4_fname_crypto_ctx *ctx,


	ciphertext_len = (iname->len < EXT4_CRYPTO_BLOCK_SIZE) ?
	ciphertext_len = (iname->len < EXT4_CRYPTO_BLOCK_SIZE) ?
		EXT4_CRYPTO_BLOCK_SIZE : iname->len;
		EXT4_CRYPTO_BLOCK_SIZE : iname->len;
	ciphertext_len = ext4_fname_crypto_round_up(ciphertext_len, padding);
	ciphertext_len = (ciphertext_len > ctx->lim)
	ciphertext_len = (ciphertext_len > ctx->lim)
			? ctx->lim : ciphertext_len;
			? ctx->lim : ciphertext_len;


@@ -101,7 +103,7 @@ static int ext4_fname_encrypt(struct ext4_fname_crypto_ctx *ctx,
	/* Create encryption request */
	/* Create encryption request */
	sg_init_table(sg, 1);
	sg_init_table(sg, 1);
	sg_set_page(sg, ctx->workpage, PAGE_SIZE, 0);
	sg_set_page(sg, ctx->workpage, PAGE_SIZE, 0);
	ablkcipher_request_set_crypt(req, sg, sg, iname->len, iv);
	ablkcipher_request_set_crypt(req, sg, sg, ciphertext_len, iv);
	res = crypto_ablkcipher_encrypt(req);
	res = crypto_ablkcipher_encrypt(req);
	if (res == -EINPROGRESS || res == -EBUSY) {
	if (res == -EINPROGRESS || res == -EBUSY) {
		BUG_ON(req->base.data != &ecr);
		BUG_ON(req->base.data != &ecr);
@@ -198,106 +200,57 @@ static int ext4_fname_decrypt(struct ext4_fname_crypto_ctx *ctx,
	return oname->len;
	return oname->len;
}
}


static const char *lookup_table =
	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,";

/**
/**
 * ext4_fname_encode_digest() -
 * ext4_fname_encode_digest() -
 *
 *
 * Encodes the input digest using characters from the set [a-zA-Z0-9_+].
 * Encodes the input digest using characters from the set [a-zA-Z0-9_+].
 * The encoded string is roughly 4/3 times the size of the input string.
 * The encoded string is roughly 4/3 times the size of the input string.
 */
 */
int ext4_fname_encode_digest(char *dst, char *src, u32 len)
static int digest_encode(const char *src, int len, char *dst)
{
{
	static const char *lookup_table =
	int i = 0, bits = 0, ac = 0;
		"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_+";
	char *cp = dst;
	u32 current_chunk, num_chunks, i;

	char tmp_buf[3];
	while (i < len) {
	u32 c0, c1, c2, c3;
		ac += (((unsigned char) src[i]) << bits);

		bits += 8;
	current_chunk = 0;
		do {
	num_chunks = len/3;
			*cp++ = lookup_table[ac & 0x3f];
	for (i = 0; i < num_chunks; i++) {
			ac >>= 6;
		c0 = src[3*i] & 0x3f;
			bits -= 6;
		c1 = (((src[3*i]>>6)&0x3) | ((src[3*i+1] & 0xf)<<2)) & 0x3f;
		} while (bits >= 6);
		c2 = (((src[3*i+1]>>4)&0xf) | ((src[3*i+2] & 0x3)<<4)) & 0x3f;
		c3 = (src[3*i+2]>>2) & 0x3f;
		dst[4*i] = lookup_table[c0];
		dst[4*i+1] = lookup_table[c1];
		dst[4*i+2] = lookup_table[c2];
		dst[4*i+3] = lookup_table[c3];
	}
	if (i*3 < len) {
		memset(tmp_buf, 0, 3);
		memcpy(tmp_buf, &src[3*i], len-3*i);
		c0 = tmp_buf[0] & 0x3f;
		c1 = (((tmp_buf[0]>>6)&0x3) | ((tmp_buf[1] & 0xf)<<2)) & 0x3f;
		c2 = (((tmp_buf[1]>>4)&0xf) | ((tmp_buf[2] & 0x3)<<4)) & 0x3f;
		c3 = (tmp_buf[2]>>2) & 0x3f;
		dst[4*i] = lookup_table[c0];
		dst[4*i+1] = lookup_table[c1];
		dst[4*i+2] = lookup_table[c2];
		dst[4*i+3] = lookup_table[c3];
		i++;
		i++;
	}
	}
	return (i * 4);
	if (bits)
		*cp++ = lookup_table[ac & 0x3f];
	return cp - dst;
}
}


/**
static int digest_decode(const char *src, int len, char *dst)
 * ext4_fname_hash() -
 *
 * This function computes the hash of the input filename, and sets the output
 * buffer to the *encoded* digest.  It returns the length of the digest as its
 * return value.  Errors are returned as negative numbers.  We trust the caller
 * to allocate sufficient memory to oname string.
 */
static int ext4_fname_hash(struct ext4_fname_crypto_ctx *ctx,
			   const struct ext4_str *iname,
			   struct ext4_str *oname)
{
{
	struct scatterlist sg;
	int i = 0, bits = 0, ac = 0;
	struct hash_desc desc = {
	const char *p;
		.tfm = (struct crypto_hash *)ctx->htfm,
	char *cp = dst;
		.flags = CRYPTO_TFM_REQ_MAY_SLEEP

	};
	while (i < len) {
	int res = 0;
		p = strchr(lookup_table, src[i]);

		if (p == NULL || src[i] == 0)
	if (iname->len <= EXT4_FNAME_CRYPTO_DIGEST_SIZE) {
			return -2;
		res = ext4_fname_encode_digest(oname->name, iname->name,
		ac += (p - lookup_table) << bits;
					       iname->len);
		bits += 6;
		oname->len = res;
		if (bits >= 8) {
		return res;
			*cp++ = ac & 0xff;
	}
			ac >>= 8;

			bits -= 8;
	sg_init_one(&sg, iname->name, iname->len);
	res = crypto_hash_init(&desc);
	if (res) {
		printk(KERN_ERR
		       "%s: Error initializing crypto hash; res = [%d]\n",
		       __func__, res);
		goto out;
		}
		}
	res = crypto_hash_update(&desc, &sg, iname->len);
		i++;
	if (res) {
		printk(KERN_ERR
		       "%s: Error updating crypto hash; res = [%d]\n",
		       __func__, res);
		goto out;
	}
	}
	res = crypto_hash_final(&desc,
	if (ac)
		&oname->name[EXT4_FNAME_CRYPTO_DIGEST_SIZE]);
		return -1;
	if (res) {
	return cp - dst;
		printk(KERN_ERR
		       "%s: Error finalizing crypto hash; res = [%d]\n",
		       __func__, res);
		goto out;
	}
	/* Encode the digest as a printable string--this will increase the
	 * size of the digest */
	oname->name[0] = 'I';
	res = ext4_fname_encode_digest(oname->name+1,
		&oname->name[EXT4_FNAME_CRYPTO_DIGEST_SIZE],
		EXT4_FNAME_CRYPTO_DIGEST_SIZE) + 1;
	oname->len = res;
out:
	return res;
}
}


/**
/**
@@ -405,6 +358,7 @@ struct ext4_fname_crypto_ctx *ext4_get_fname_crypto_ctx(
	if (IS_ERR(ctx))
	if (IS_ERR(ctx))
		return ctx;
		return ctx;


	ctx->flags = ei->i_crypt_policy_flags;
	if (ctx->has_valid_key) {
	if (ctx->has_valid_key) {
		if (ctx->key.mode != EXT4_ENCRYPTION_MODE_AES_256_CTS) {
		if (ctx->key.mode != EXT4_ENCRYPTION_MODE_AES_256_CTS) {
			printk_once(KERN_WARNING
			printk_once(KERN_WARNING
@@ -517,6 +471,7 @@ int ext4_fname_crypto_namelen_on_disk(struct ext4_fname_crypto_ctx *ctx,
				      u32 namelen)
				      u32 namelen)
{
{
	u32 ciphertext_len;
	u32 ciphertext_len;
	int padding = 4 << (ctx->flags & EXT4_POLICY_FLAGS_PAD_MASK);


	if (ctx == NULL)
	if (ctx == NULL)
		return -EIO;
		return -EIO;
@@ -524,6 +479,7 @@ int ext4_fname_crypto_namelen_on_disk(struct ext4_fname_crypto_ctx *ctx,
		return -EACCES;
		return -EACCES;
	ciphertext_len = (namelen < EXT4_CRYPTO_BLOCK_SIZE) ?
	ciphertext_len = (namelen < EXT4_CRYPTO_BLOCK_SIZE) ?
		EXT4_CRYPTO_BLOCK_SIZE : namelen;
		EXT4_CRYPTO_BLOCK_SIZE : namelen;
	ciphertext_len = ext4_fname_crypto_round_up(ciphertext_len, padding);
	ciphertext_len = (ciphertext_len > ctx->lim)
	ciphertext_len = (ciphertext_len > ctx->lim)
			? ctx->lim : ciphertext_len;
			? ctx->lim : ciphertext_len;
	return (int) ciphertext_len;
	return (int) ciphertext_len;
@@ -539,10 +495,13 @@ int ext4_fname_crypto_alloc_buffer(struct ext4_fname_crypto_ctx *ctx,
				   u32 ilen, struct ext4_str *crypto_str)
				   u32 ilen, struct ext4_str *crypto_str)
{
{
	unsigned int olen;
	unsigned int olen;
	int padding = 4 << (ctx->flags & EXT4_POLICY_FLAGS_PAD_MASK);


	if (!ctx)
	if (!ctx)
		return -EIO;
		return -EIO;
	olen = ext4_fname_crypto_round_up(ilen, EXT4_CRYPTO_BLOCK_SIZE);
	if (padding < EXT4_CRYPTO_BLOCK_SIZE)
		padding = EXT4_CRYPTO_BLOCK_SIZE;
	olen = ext4_fname_crypto_round_up(ilen, padding);
	crypto_str->len = olen;
	crypto_str->len = olen;
	if (olen < EXT4_FNAME_CRYPTO_DIGEST_SIZE*2)
	if (olen < EXT4_FNAME_CRYPTO_DIGEST_SIZE*2)
		olen = EXT4_FNAME_CRYPTO_DIGEST_SIZE*2;
		olen = EXT4_FNAME_CRYPTO_DIGEST_SIZE*2;
@@ -571,9 +530,13 @@ void ext4_fname_crypto_free_buffer(struct ext4_str *crypto_str)
 * ext4_fname_disk_to_usr() - converts a filename from disk space to user space
 * ext4_fname_disk_to_usr() - converts a filename from disk space to user space
 */
 */
int _ext4_fname_disk_to_usr(struct ext4_fname_crypto_ctx *ctx,
int _ext4_fname_disk_to_usr(struct ext4_fname_crypto_ctx *ctx,
			    struct dx_hash_info *hinfo,
			    const struct ext4_str *iname,
			    const struct ext4_str *iname,
			    struct ext4_str *oname)
			    struct ext4_str *oname)
{
{
	char buf[24];
	int ret;

	if (ctx == NULL)
	if (ctx == NULL)
		return -EIO;
		return -EIO;
	if (iname->len < 3) {
	if (iname->len < 3) {
@@ -587,18 +550,33 @@ int _ext4_fname_disk_to_usr(struct ext4_fname_crypto_ctx *ctx,
	}
	}
	if (ctx->has_valid_key)
	if (ctx->has_valid_key)
		return ext4_fname_decrypt(ctx, iname, oname);
		return ext4_fname_decrypt(ctx, iname, oname);
	else

		return ext4_fname_hash(ctx, iname, oname);
	if (iname->len <= EXT4_FNAME_CRYPTO_DIGEST_SIZE) {
		ret = digest_encode(iname->name, iname->len, oname->name);
		oname->len = ret;
		return ret;
	}
	if (hinfo) {
		memcpy(buf, &hinfo->hash, 4);
		memcpy(buf+4, &hinfo->minor_hash, 4);
	} else
		memset(buf, 0, 8);
	memcpy(buf + 8, iname->name + iname->len - 16, 16);
	oname->name[0] = '_';
	ret = digest_encode(buf, 24, oname->name+1);
	oname->len = ret + 1;
	return ret + 1;
}
}


int ext4_fname_disk_to_usr(struct ext4_fname_crypto_ctx *ctx,
int ext4_fname_disk_to_usr(struct ext4_fname_crypto_ctx *ctx,
			   struct dx_hash_info *hinfo,
			   const struct ext4_dir_entry_2 *de,
			   const struct ext4_dir_entry_2 *de,
			   struct ext4_str *oname)
			   struct ext4_str *oname)
{
{
	struct ext4_str iname = {.name = (unsigned char *) de->name,
	struct ext4_str iname = {.name = (unsigned char *) de->name,
				 .len = de->name_len };
				 .len = de->name_len };


	return _ext4_fname_disk_to_usr(ctx, &iname, oname);
	return _ext4_fname_disk_to_usr(ctx, hinfo, &iname, oname);
}
}




@@ -640,10 +618,11 @@ int ext4_fname_usr_to_hash(struct ext4_fname_crypto_ctx *ctx,
			    const struct qstr *iname,
			    const struct qstr *iname,
			    struct dx_hash_info *hinfo)
			    struct dx_hash_info *hinfo)
{
{
	struct ext4_str tmp, tmp2;
	struct ext4_str tmp;
	int ret = 0;
	int ret = 0;
	char buf[EXT4_FNAME_CRYPTO_DIGEST_SIZE+1];


	if (!ctx || !ctx->has_valid_key ||
	if (!ctx ||
	    ((iname->name[0] == '.') &&
	    ((iname->name[0] == '.') &&
	     ((iname->len == 1) ||
	     ((iname->len == 1) ||
	      ((iname->name[1] == '.') && (iname->len == 2))))) {
	      ((iname->name[1] == '.') && (iname->len == 2))))) {
@@ -651,59 +630,90 @@ int ext4_fname_usr_to_hash(struct ext4_fname_crypto_ctx *ctx,
		return 0;
		return 0;
	}
	}


	if (!ctx->has_valid_key && iname->name[0] == '_') {
		if (iname->len != 33)
			return -ENOENT;
		ret = digest_decode(iname->name+1, iname->len, buf);
		if (ret != 24)
			return -ENOENT;
		memcpy(&hinfo->hash, buf, 4);
		memcpy(&hinfo->minor_hash, buf + 4, 4);
		return 0;
	}

	if (!ctx->has_valid_key && iname->name[0] != '_') {
		if (iname->len > 43)
			return -ENOENT;
		ret = digest_decode(iname->name, iname->len, buf);
		ext4fs_dirhash(buf, ret, hinfo);
		return 0;
	}

	/* First encrypt the plaintext name */
	/* First encrypt the plaintext name */
	ret = ext4_fname_crypto_alloc_buffer(ctx, iname->len, &tmp);
	ret = ext4_fname_crypto_alloc_buffer(ctx, iname->len, &tmp);
	if (ret < 0)
	if (ret < 0)
		return ret;
		return ret;


	ret = ext4_fname_encrypt(ctx, iname, &tmp);
	ret = ext4_fname_encrypt(ctx, iname, &tmp);
	if (ret < 0)
	if (ret >= 0) {
		goto out;
		ext4fs_dirhash(tmp.name, tmp.len, hinfo);

		ret = 0;
	tmp2.len = (4 * ((EXT4_FNAME_CRYPTO_DIGEST_SIZE + 2) / 3)) + 1;
	tmp2.name = kmalloc(tmp2.len + 1, GFP_KERNEL);
	if (tmp2.name == NULL) {
		ret = -ENOMEM;
		goto out;
	}
	}


	ret = ext4_fname_hash(ctx, &tmp, &tmp2);
	if (ret > 0)
		ext4fs_dirhash(tmp2.name, tmp2.len, hinfo);
	ext4_fname_crypto_free_buffer(&tmp2);
out:
	ext4_fname_crypto_free_buffer(&tmp);
	ext4_fname_crypto_free_buffer(&tmp);
	return ret;
	return ret;
}
}


/**
int ext4_fname_match(struct ext4_fname_crypto_ctx *ctx, struct ext4_str *cstr,
 * ext4_fname_disk_to_htree() - converts a filename from disk space to htree-access string
		     int len, const char * const name,
 */
		     struct ext4_dir_entry_2 *de)
int ext4_fname_disk_to_hash(struct ext4_fname_crypto_ctx *ctx,
			    const struct ext4_dir_entry_2 *de,
			    struct dx_hash_info *hinfo)
{
{
	struct ext4_str iname = {.name = (unsigned char *) de->name,
	int ret = -ENOENT;
				 .len = de->name_len};
	int bigname = (*name == '_');
	struct ext4_str tmp;
	int ret;


	if (!ctx ||
	if (ctx->has_valid_key) {
	    ((iname.name[0] == '.') &&
		if (cstr->name == NULL) {
	     ((iname.len == 1) ||
			struct qstr istr;
	      ((iname.name[1] == '.') && (iname.len == 2))))) {
		ext4fs_dirhash(iname.name, iname.len, hinfo);
		return 0;
	}


	tmp.len = (4 * ((EXT4_FNAME_CRYPTO_DIGEST_SIZE + 2) / 3)) + 1;
			ret = ext4_fname_crypto_alloc_buffer(ctx, len, cstr);
	tmp.name = kmalloc(tmp.len + 1, GFP_KERNEL);
			if (ret < 0)
	if (tmp.name == NULL)
				goto errout;
			istr.name = name;
			istr.len = len;
			ret = ext4_fname_encrypt(ctx, &istr, cstr);
			if (ret < 0)
				goto errout;
		}
	} else {
		if (cstr->name == NULL) {
			cstr->name = kmalloc(32, GFP_KERNEL);
			if (cstr->name == NULL)
				return -ENOMEM;
				return -ENOMEM;

			if ((bigname && (len != 33)) ||
	ret = ext4_fname_hash(ctx, &iname, &tmp);
			    (!bigname && (len > 43)))
	if (ret > 0)
				goto errout;
		ext4fs_dirhash(tmp.name, tmp.len, hinfo);
			ret = digest_decode(name+bigname, len-bigname,
	ext4_fname_crypto_free_buffer(&tmp);
					    cstr->name);
			if (ret < 0) {
				ret = -ENOENT;
				goto errout;
			}
			cstr->len = ret;
		}
		if (bigname) {
			if (de->name_len < 16)
				return 0;
			ret = memcmp(de->name + de->name_len - 16,
				     cstr->name + 8, 16);
			return (ret == 0) ? 1 : 0;
		}
	}
	if (de->name_len != cstr->len)
		return 0;
	ret = memcmp(de->name, cstr->name, cstr->len);
	return (ret == 0) ? 1 : 0;
errout:
	kfree(cstr->name);
	cstr->name = NULL;
	return ret;
	return ret;
}
}
+1 −0
Original line number Original line Diff line number Diff line
@@ -110,6 +110,7 @@ int ext4_generate_encryption_key(struct inode *inode)
	}
	}
	res = 0;
	res = 0;


	ei->i_crypt_policy_flags = ctx.flags;
	if (S_ISREG(inode->i_mode))
	if (S_ISREG(inode->i_mode))
		crypt_key->mode = ctx.contents_encryption_mode;
		crypt_key->mode = ctx.contents_encryption_mode;
	else if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
	else if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
+9 −5
Original line number Original line Diff line number Diff line
@@ -37,6 +37,8 @@ static int ext4_is_encryption_context_consistent_with_policy(
		return 0;
		return 0;
	return (memcmp(ctx.master_key_descriptor, policy->master_key_descriptor,
	return (memcmp(ctx.master_key_descriptor, policy->master_key_descriptor,
			EXT4_KEY_DESCRIPTOR_SIZE) == 0 &&
			EXT4_KEY_DESCRIPTOR_SIZE) == 0 &&
		(ctx.flags ==
		 policy->flags) &&
		(ctx.contents_encryption_mode ==
		(ctx.contents_encryption_mode ==
		 policy->contents_encryption_mode) &&
		 policy->contents_encryption_mode) &&
		(ctx.filenames_encryption_mode ==
		(ctx.filenames_encryption_mode ==
@@ -56,25 +58,25 @@ static int ext4_create_encryption_context_from_policy(
		printk(KERN_WARNING
		printk(KERN_WARNING
		       "%s: Invalid contents encryption mode %d\n", __func__,
		       "%s: Invalid contents encryption mode %d\n", __func__,
			policy->contents_encryption_mode);
			policy->contents_encryption_mode);
		res = -EINVAL;
		return -EINVAL;
		goto out;
	}
	}
	if (!ext4_valid_filenames_enc_mode(policy->filenames_encryption_mode)) {
	if (!ext4_valid_filenames_enc_mode(policy->filenames_encryption_mode)) {
		printk(KERN_WARNING
		printk(KERN_WARNING
		       "%s: Invalid filenames encryption mode %d\n", __func__,
		       "%s: Invalid filenames encryption mode %d\n", __func__,
			policy->filenames_encryption_mode);
			policy->filenames_encryption_mode);
		res = -EINVAL;
		return -EINVAL;
		goto out;
	}
	}
	if (policy->flags & ~EXT4_POLICY_FLAGS_VALID)
		return -EINVAL;
	ctx.contents_encryption_mode = policy->contents_encryption_mode;
	ctx.contents_encryption_mode = policy->contents_encryption_mode;
	ctx.filenames_encryption_mode = policy->filenames_encryption_mode;
	ctx.filenames_encryption_mode = policy->filenames_encryption_mode;
	ctx.flags = policy->flags;
	BUILD_BUG_ON(sizeof(ctx.nonce) != EXT4_KEY_DERIVATION_NONCE_SIZE);
	BUILD_BUG_ON(sizeof(ctx.nonce) != EXT4_KEY_DERIVATION_NONCE_SIZE);
	get_random_bytes(ctx.nonce, EXT4_KEY_DERIVATION_NONCE_SIZE);
	get_random_bytes(ctx.nonce, EXT4_KEY_DERIVATION_NONCE_SIZE);


	res = ext4_xattr_set(inode, EXT4_XATTR_INDEX_ENCRYPTION,
	res = ext4_xattr_set(inode, EXT4_XATTR_INDEX_ENCRYPTION,
			     EXT4_XATTR_NAME_ENCRYPTION_CONTEXT, &ctx,
			     EXT4_XATTR_NAME_ENCRYPTION_CONTEXT, &ctx,
			     sizeof(ctx), 0);
			     sizeof(ctx), 0);
out:
	if (!res)
	if (!res)
		ext4_set_inode_flag(inode, EXT4_INODE_ENCRYPT);
		ext4_set_inode_flag(inode, EXT4_INODE_ENCRYPT);
	return res;
	return res;
@@ -115,6 +117,7 @@ int ext4_get_policy(struct inode *inode, struct ext4_encryption_policy *policy)
	policy->version = 0;
	policy->version = 0;
	policy->contents_encryption_mode = ctx.contents_encryption_mode;
	policy->contents_encryption_mode = ctx.contents_encryption_mode;
	policy->filenames_encryption_mode = ctx.filenames_encryption_mode;
	policy->filenames_encryption_mode = ctx.filenames_encryption_mode;
	policy->flags = ctx.flags;
	memcpy(&policy->master_key_descriptor, ctx.master_key_descriptor,
	memcpy(&policy->master_key_descriptor, ctx.master_key_descriptor,
	       EXT4_KEY_DESCRIPTOR_SIZE);
	       EXT4_KEY_DESCRIPTOR_SIZE);
	return 0;
	return 0;
@@ -176,6 +179,7 @@ int ext4_inherit_context(struct inode *parent, struct inode *child)
				EXT4_ENCRYPTION_MODE_AES_256_XTS;
				EXT4_ENCRYPTION_MODE_AES_256_XTS;
			ctx.filenames_encryption_mode =
			ctx.filenames_encryption_mode =
				EXT4_ENCRYPTION_MODE_AES_256_CTS;
				EXT4_ENCRYPTION_MODE_AES_256_CTS;
			ctx.flags = 0;
			memset(ctx.master_key_descriptor, 0x42,
			memset(ctx.master_key_descriptor, 0x42,
			       EXT4_KEY_DESCRIPTOR_SIZE);
			       EXT4_KEY_DESCRIPTOR_SIZE);
			res = 0;
			res = 0;
+1 −1
Original line number Original line Diff line number Diff line
@@ -249,7 +249,7 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx)
				} else {
				} else {
					/* Directory is encrypted */
					/* Directory is encrypted */
					err = ext4_fname_disk_to_usr(enc_ctx,
					err = ext4_fname_disk_to_usr(enc_ctx,
							de, &fname_crypto_str);
						NULL, de, &fname_crypto_str);
					if (err < 0)
					if (err < 0)
						goto errout;
						goto errout;
					if (!dir_emit(ctx,
					if (!dir_emit(ctx,
Loading