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

Commit 39d2c3b9 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'upstream-4.10-rc1' of git://git.infradead.org/linux-ubifs

Pull ubifs updates from Richard Weinberger:

 - file encryption for UBIFS using the fscrypt framework

 - a fix to honor the dirty_writeback_interval sysctl

 - removal of dead code

* tag 'upstream-4.10-rc1' of git://git.infradead.org/linux-ubifs: (30 commits)
  ubifs: Initialize fstr_real_len
  ubifs: Use fscrypt ioctl() helpers
  ubifs: Use FS_CFLG_OWN_PAGES
  ubifs: Raise write version to 5
  ubifs: Implement UBIFS_FLG_ENCRYPTION
  ubifs: Implement UBIFS_FLG_DOUBLE_HASH
  ubifs: Use a random number for cookies
  ubifs: Add full hash lookup support
  ubifs: Rename tnc_read_node_nm
  ubifs: Add support for encrypted symlinks
  ubifs: Implement encrypted filenames
  ubifs: Make r5 hash binary string aware
  ubifs: Relax checks in ubifs_validate_entry()
  ubifs: Implement encrypt/decrypt for all IO
  ubifs: Constify struct inode pointer in ubifs_crypt_is_encrypted()
  ubifs: Introduce new data node field, compr_size
  ubifs: Enforce crypto policy in mmap
  ubifs: Massage assert in ubifs_xattr_set() wrt. fscrypto
  ubifs: Preload crypto context in ->lookup()
  ubifs: Enforce crypto policy in ->link and ->rename
  ...
parents e18bf801 ba75d570
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -50,3 +50,14 @@ config UBIFS_ATIME_SUPPORT
	  strictatime is the "heavy", relatime is "lighter", etc.

	  If unsure, say 'N'

config UBIFS_FS_ENCRYPTION
	bool "UBIFS Encryption"
	depends on UBIFS_FS
	select FS_ENCRYPTION
	default n
	help
	  Enable encryption of UBIFS files and directories. This
	  feature is similar to ecryptfs, but it is more memory
	  efficient since it avoids caching the encrypted and
	  decrypted pages in the page cache.
+1 −0
Original line number Diff line number Diff line
@@ -5,3 +5,4 @@ ubifs-y += tnc.o master.o scan.o replay.o log.o commit.o gc.o orphan.o
ubifs-y += budget.o find.o tnc_commit.o compress.o lpt.o lprops.o
ubifs-y += recovery.o ioctl.o lpt_commit.o tnc_misc.o xattr.o debug.o
ubifs-y += misc.o
ubifs-$(CONFIG_UBIFS_FS_ENCRYPTION) += crypto.o

fs/ubifs/crypto.c

0 → 100644
+97 −0
Original line number Diff line number Diff line
#include "ubifs.h"

static int ubifs_crypt_get_context(struct inode *inode, void *ctx, size_t len)
{
	return ubifs_xattr_get(inode, UBIFS_XATTR_NAME_ENCRYPTION_CONTEXT,
			       ctx, len);
}

static int ubifs_crypt_set_context(struct inode *inode, const void *ctx,
				   size_t len, void *fs_data)
{
	return ubifs_xattr_set(inode, UBIFS_XATTR_NAME_ENCRYPTION_CONTEXT,
			       ctx, len, 0);
}

static bool ubifs_crypt_empty_dir(struct inode *inode)
{
	return ubifs_check_dir_empty(inode) == 0;
}

static unsigned int ubifs_crypt_max_namelen(struct inode *inode)
{
	if (S_ISLNK(inode->i_mode))
		return UBIFS_MAX_INO_DATA;
	else
		return UBIFS_MAX_NLEN;
}

static int ubifs_key_prefix(struct inode *inode, u8 **key)
{
	static char prefix[] = "ubifs:";

	*key = prefix;

	return sizeof(prefix) - 1;
}

int ubifs_encrypt(const struct inode *inode, struct ubifs_data_node *dn,
		  unsigned int in_len, unsigned int *out_len, int block)
{
	struct ubifs_info *c = inode->i_sb->s_fs_info;
	void *p = &dn->data;
	struct page *ret;
	unsigned int pad_len = round_up(in_len, UBIFS_CIPHER_BLOCK_SIZE);

	ubifs_assert(pad_len <= *out_len);
	dn->compr_size = cpu_to_le16(in_len);

	/* pad to full block cipher length */
	if (pad_len != in_len)
		memset(p + in_len, 0, pad_len - in_len);

	ret = fscrypt_encrypt_page(inode, virt_to_page(&dn->data), pad_len,
			offset_in_page(&dn->data), block, GFP_NOFS);
	if (IS_ERR(ret)) {
		ubifs_err(c, "fscrypt_encrypt_page failed: %ld", PTR_ERR(ret));
		return PTR_ERR(ret);
	}
	*out_len = pad_len;

	return 0;
}

int ubifs_decrypt(const struct inode *inode, struct ubifs_data_node *dn,
		  unsigned int *out_len, int block)
{
	struct ubifs_info *c = inode->i_sb->s_fs_info;
	int err;
	unsigned int clen = le16_to_cpu(dn->compr_size);
	unsigned int dlen = *out_len;

	if (clen <= 0 || clen > UBIFS_BLOCK_SIZE || clen > dlen) {
		ubifs_err(c, "bad compr_size: %i", clen);
		return -EINVAL;
	}

	ubifs_assert(dlen <= UBIFS_BLOCK_SIZE);
	err = fscrypt_decrypt_page(inode, virt_to_page(&dn->data), dlen,
			offset_in_page(&dn->data), block);
	if (err) {
		ubifs_err(c, "fscrypt_decrypt_page failed: %i", err);
		return err;
	}
	*out_len = clen;

	return 0;
}

struct fscrypt_operations ubifs_crypt_operations = {
	.flags			= FS_CFLG_OWN_PAGES,
	.get_context		= ubifs_crypt_get_context,
	.set_context		= ubifs_crypt_set_context,
	.is_encrypted		= __ubifs_crypt_is_encrypted,
	.empty_dir		= ubifs_crypt_empty_dir,
	.max_namelen		= ubifs_crypt_max_namelen,
	.key_prefix		= ubifs_key_prefix,
};
+7 −7
Original line number Diff line number Diff line
@@ -233,7 +233,7 @@ static void dump_ch(const struct ubifs_ch *ch)
void ubifs_dump_inode(struct ubifs_info *c, const struct inode *inode)
{
	const struct ubifs_inode *ui = ubifs_inode(inode);
	struct qstr nm = { .name = NULL };
	struct fscrypt_name nm = {0};
	union ubifs_key key;
	struct ubifs_dent_node *dent, *pdent = NULL;
	int count = 2;
@@ -289,8 +289,8 @@ void ubifs_dump_inode(struct ubifs_info *c, const struct inode *inode)
		pr_err("\t%d: %s (%s)\n",
		       count++, dent->name, get_dent_type(dent->type));

		nm.name = dent->name;
		nm.len = le16_to_cpu(dent->nlen);
		fname_name(&nm) = dent->name;
		fname_len(&nm) = le16_to_cpu(dent->nlen);
		kfree(pdent);
		pdent = dent;
		key_read(c, &dent->key, &key);
@@ -1107,7 +1107,7 @@ int dbg_check_dir(struct ubifs_info *c, const struct inode *dir)
	unsigned int nlink = 2;
	union ubifs_key key;
	struct ubifs_dent_node *dent, *pdent = NULL;
	struct qstr nm = { .name = NULL };
	struct fscrypt_name nm = {0};
	loff_t size = UBIFS_INO_NODE_SZ;

	if (!dbg_is_chk_gen(c))
@@ -1128,9 +1128,9 @@ int dbg_check_dir(struct ubifs_info *c, const struct inode *dir)
			return err;
		}

		nm.name = dent->name;
		nm.len = le16_to_cpu(dent->nlen);
		size += CALC_DENT_SIZE(nm.len);
		fname_name(&nm) = dent->name;
		fname_len(&nm) = le16_to_cpu(dent->nlen);
		size += CALC_DENT_SIZE(fname_len(&nm));
		if (dent->type == UBIFS_ITYPE_DIR)
			nlink += 1;
		kfree(pdent);
+408 −70

File changed.

Preview size limit exceeded, changes collapsed.

Loading