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

Commit 966859b9 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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

Pull UBIFS updates from Richard Weinberger:

 - Updates and fixes for the file encryption mode

 - Minor improvements

 - Random fixes

* tag 'upstream-4.13-rc1' of git://git.infradead.org/linux-ubifs:
  ubifs: Set double hash cookie also for RENAME_EXCHANGE
  ubifs: Massage assert in ubifs_xattr_set() wrt. init_xattrs
  ubifs: Don't leak kernel memory to the MTD
  ubifs: Change gfp flags in page allocation for bulk read
  ubifs: Fix oops when remounting with no_bulk_read.
  ubifs: Fail commit if TNC is obviously inconsistent
  ubifs: allow userspace to map mounts to volumes
  ubifs: Wire-up statx() support
  ubifs: Remove dead code from ubifs_get_link()
  ubifs: Massage debug prints wrt. fscrypt
  ubifs: Add assert to dent_key_init()
  ubifs: Fix unlink code wrt. double hash lookups
  ubifs: Fix data node size for truncating uncompressed nodes
  ubifs: Don't encrypt special files on creation
  ubifs: Fix memory leak in RENAME_WHITEOUT error path in do_rename
  ubifs: Fix inode data budget in ubifs_mknod
  ubifs: Correctly evict xattr inodes
  ubifs: Unexport ubifs_inode_slab
  ubifs: don't bother checking for encryption key in ->mmap()
  ubifs: require key for truncate(2) of encrypted file
parents e37a07e0 a6664433
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -9,8 +9,13 @@ static int ubifs_crypt_get_context(struct inode *inode, void *ctx, size_t len)
static int ubifs_crypt_set_context(struct inode *inode, const void *ctx,
				   size_t len, void *fs_data)
{
	/*
	 * Creating an encryption context is done unlocked since we
	 * operate on a new inode which is not visible to other users
	 * at this point. So, no need to check whether inode is locked.
	 */
	return ubifs_xattr_set(inode, UBIFS_XATTR_NAME_ENCRYPTION_CONTEXT,
			       ctx, len, 0);
			       ctx, len, 0, false);
}

static bool ubifs_crypt_empty_dir(struct inode *inode)
+22 −10
Original line number Diff line number Diff line
@@ -143,6 +143,7 @@ struct inode *ubifs_new_inode(struct ubifs_info *c, struct inode *dir,
	case S_IFBLK:
	case S_IFCHR:
		inode->i_op  = &ubifs_file_inode_operations;
		encrypted = false;
		break;
	default:
		BUG();
@@ -1061,7 +1062,6 @@ static int ubifs_mknod(struct inode *dir, struct dentry *dentry,
	int sz_change;
	int err, devlen = 0;
	struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1,
					.new_ino_d = ALIGN(devlen, 8),
					.dirtied_ino = 1 };
	struct fscrypt_name nm;

@@ -1079,6 +1079,7 @@ static int ubifs_mknod(struct inode *dir, struct dentry *dentry,
		devlen = ubifs_encode_dev(dev, rdev);
	}

	req.new_ino_d = ALIGN(devlen, 8);
	err = ubifs_budget_space(c, &req);
	if (err) {
		kfree(dev);
@@ -1396,17 +1397,14 @@ static int do_rename(struct inode *old_dir, struct dentry *old_dentry,

		dev = kmalloc(sizeof(union ubifs_dev_desc), GFP_NOFS);
		if (!dev) {
			ubifs_release_budget(c, &req);
			ubifs_release_budget(c, &ino_req);
			return -ENOMEM;
			err = -ENOMEM;
			goto out_release;
		}

		err = do_tmpfile(old_dir, old_dentry, S_IFCHR | WHITEOUT_MODE, &whiteout);
		if (err) {
			ubifs_release_budget(c, &req);
			ubifs_release_budget(c, &ino_req);
			kfree(dev);
			return err;
			goto out_release;
		}

		whiteout->i_state |= I_LINKABLE;
@@ -1494,12 +1492,10 @@ static int do_rename(struct inode *old_dir, struct dentry *old_dentry,

		err = ubifs_budget_space(c, &wht_req);
		if (err) {
			ubifs_release_budget(c, &req);
			ubifs_release_budget(c, &ino_req);
			kfree(whiteout_ui->data);
			whiteout_ui->data_len = 0;
			iput(whiteout);
			return err;
			goto out_release;
		}

		inc_nlink(whiteout);
@@ -1554,6 +1550,7 @@ static int do_rename(struct inode *old_dir, struct dentry *old_dentry,
		iput(whiteout);
	}
	unlock_4_inodes(old_dir, new_dir, new_inode, whiteout);
out_release:
	ubifs_release_budget(c, &ino_req);
	ubifs_release_budget(c, &req);
	fscrypt_free_filename(&old_nm);
@@ -1647,6 +1644,21 @@ int ubifs_getattr(const struct path *path, struct kstat *stat,
	struct ubifs_inode *ui = ubifs_inode(inode);

	mutex_lock(&ui->ui_mutex);

	if (ui->flags & UBIFS_APPEND_FL)
		stat->attributes |= STATX_ATTR_APPEND;
	if (ui->flags & UBIFS_COMPR_FL)
		stat->attributes |= STATX_ATTR_COMPRESSED;
	if (ui->flags & UBIFS_CRYPT_FL)
		stat->attributes |= STATX_ATTR_ENCRYPTED;
	if (ui->flags & UBIFS_IMMUTABLE_FL)
		stat->attributes |= STATX_ATTR_IMMUTABLE;

	stat->attributes_mask |= (STATX_ATTR_APPEND |
				STATX_ATTR_COMPRESSED |
				STATX_ATTR_ENCRYPTED |
				STATX_ATTR_IMMUTABLE);

	generic_fillattr(inode, stat);
	stat->blksize = UBIFS_BLOCK_SIZE;
	stat->size = ui->ui_size;
+10 −17
Original line number Diff line number Diff line
@@ -735,6 +735,7 @@ static int ubifs_do_bulk_read(struct ubifs_info *c, struct bu_info *bu,
	int err, page_idx, page_cnt, ret = 0, n = 0;
	int allocate = bu->buf ? 0 : 1;
	loff_t isize;
	gfp_t ra_gfp_mask = readahead_gfp_mask(mapping) & ~__GFP_FS;

	err = ubifs_tnc_get_bu_keys(c, bu);
	if (err)
@@ -796,8 +797,7 @@ static int ubifs_do_bulk_read(struct ubifs_info *c, struct bu_info *bu,

		if (page_offset > end_index)
			break;
		page = find_or_create_page(mapping, page_offset,
					   GFP_NOFS | __GFP_COLD);
		page = find_or_create_page(mapping, page_offset, ra_gfp_mask);
		if (!page)
			break;
		if (!PageUptodate(page))
@@ -1284,6 +1284,14 @@ int ubifs_setattr(struct dentry *dentry, struct iattr *attr)
	if (err)
		return err;

	if (ubifs_crypt_is_encrypted(inode) && (attr->ia_valid & ATTR_SIZE)) {
		err = fscrypt_get_encryption_info(inode);
		if (err)
			return err;
		if (!fscrypt_has_encryption_key(inode))
			return -ENOKEY;
	}

	if ((attr->ia_valid & ATTR_SIZE) && attr->ia_size < inode->i_size)
		/* Truncation to a smaller size */
		err = do_truncation(c, inode, attr);
@@ -1607,15 +1615,6 @@ static const struct vm_operations_struct ubifs_file_vm_ops = {
static int ubifs_file_mmap(struct file *file, struct vm_area_struct *vma)
{
	int err;
	struct inode *inode = file->f_mapping->host;

	if (ubifs_crypt_is_encrypted(inode)) {
		err = fscrypt_get_encryption_info(inode);
		if (err)
			return -EACCES;
		if (!fscrypt_has_encryption_key(inode))
			return -ENOKEY;
	}

	err = generic_file_mmap(file, vma);
	if (err)
@@ -1698,12 +1697,6 @@ static const char *ubifs_get_link(struct dentry *dentry,

	pstr.name[pstr.len] = '\0';

	// XXX this probably won't happen anymore...
	if (pstr.name[0] == '\0') {
		fscrypt_fname_free_buffer(&pstr);
		return ERR_PTR(-ENOENT);
	}

	set_delayed_call(done, kfree_link, pstr.name);
	return pstr.name;
}
+18 −18
Original line number Diff line number Diff line
@@ -549,8 +549,6 @@ int ubifs_jnl_update(struct ubifs_info *c, const struct inode *dir,
	struct ubifs_ino_node *ino;
	union ubifs_key dent_key, ino_key;

	//dbg_jnl("ino %lu, dent '%.*s', data len %d in dir ino %lu",
	//	inode->i_ino, nm->len, nm->name, ui->data_len, dir->i_ino);
	ubifs_assert(mutex_is_locked(&host_ui->ui_mutex));

	dlen = UBIFS_DENT_NODE_SZ + fname_len(nm) + 1;
@@ -574,7 +572,7 @@ int ubifs_jnl_update(struct ubifs_info *c, const struct inode *dir,
	/* Make sure to also account for extended attributes */
	len += host_ui->data_len;

	dent = kmalloc(len, GFP_NOFS);
	dent = kzalloc(len, GFP_NOFS);
	if (!dent)
		return -ENOMEM;

@@ -585,6 +583,9 @@ int ubifs_jnl_update(struct ubifs_info *c, const struct inode *dir,

	if (!xent) {
		dent->ch.node_type = UBIFS_DENT_NODE;
		if (nm->hash)
			dent_key_init_hash(c, &dent_key, dir->i_ino, nm->hash);
		else
			dent_key_init(c, &dent_key, dir->i_ino, nm);
	} else {
		dent->ch.node_type = UBIFS_XENT_NODE;
@@ -629,6 +630,9 @@ int ubifs_jnl_update(struct ubifs_info *c, const struct inode *dir,
	kfree(dent);

	if (deletion) {
		if (nm->hash)
			err = ubifs_tnc_remove_dh(c, &dent_key, nm->minor_hash);
		else
			err = ubifs_tnc_remove_nm(c, &dent_key, nm);
		if (err)
			goto out_ro;
@@ -950,9 +954,6 @@ int ubifs_jnl_xrename(struct ubifs_info *c, const struct inode *fst_dir,
	int twoparents = (fst_dir != snd_dir);
	void *p;

	//dbg_jnl("dent '%pd' in dir ino %lu between dent '%pd' in dir ino %lu",
	//	fst_dentry, fst_dir->i_ino, snd_dentry, snd_dir->i_ino);

	ubifs_assert(ubifs_inode(fst_dir)->data_len == 0);
	ubifs_assert(ubifs_inode(snd_dir)->data_len == 0);
	ubifs_assert(mutex_is_locked(&ubifs_inode(fst_dir)->ui_mutex));
@@ -967,7 +968,7 @@ int ubifs_jnl_xrename(struct ubifs_info *c, const struct inode *fst_dir,
	if (twoparents)
		len += plen;

	dent1 = kmalloc(len, GFP_NOFS);
	dent1 = kzalloc(len, GFP_NOFS);
	if (!dent1)
		return -ENOMEM;

@@ -984,6 +985,7 @@ int ubifs_jnl_xrename(struct ubifs_info *c, const struct inode *fst_dir,
	dent1->nlen = cpu_to_le16(fname_len(snd_nm));
	memcpy(dent1->name, fname_name(snd_nm), fname_len(snd_nm));
	dent1->name[fname_len(snd_nm)] = '\0';
	set_dent_cookie(c, dent1);
	zero_dent_node_unused(dent1);
	ubifs_prep_grp_node(c, dent1, dlen1, 0);

@@ -996,6 +998,7 @@ int ubifs_jnl_xrename(struct ubifs_info *c, const struct inode *fst_dir,
	dent2->nlen = cpu_to_le16(fname_len(fst_nm));
	memcpy(dent2->name, fname_name(fst_nm), fname_len(fst_nm));
	dent2->name[fname_len(fst_nm)] = '\0';
	set_dent_cookie(c, dent2);
	zero_dent_node_unused(dent2);
	ubifs_prep_grp_node(c, dent2, dlen2, 0);

@@ -1094,8 +1097,6 @@ int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir,
	int move = (old_dir != new_dir);
	struct ubifs_inode *uninitialized_var(new_ui);

	//dbg_jnl("dent '%pd' in dir ino %lu to dent '%pd' in dir ino %lu",
	//	old_dentry, old_dir->i_ino, new_dentry, new_dir->i_ino);
	ubifs_assert(ubifs_inode(old_dir)->data_len == 0);
	ubifs_assert(ubifs_inode(new_dir)->data_len == 0);
	ubifs_assert(mutex_is_locked(&ubifs_inode(old_dir)->ui_mutex));
@@ -1117,7 +1118,7 @@ int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir,
	len = aligned_dlen1 + aligned_dlen2 + ALIGN(ilen, 8) + ALIGN(plen, 8);
	if (move)
		len += plen;
	dent = kmalloc(len, GFP_NOFS);
	dent = kzalloc(len, GFP_NOFS);
	if (!dent)
		return -ENOMEM;

@@ -1298,7 +1299,9 @@ static int truncate_data_node(const struct ubifs_info *c, const struct inode *in
			goto out;
	}

	if (compr_type != UBIFS_COMPR_NONE) {
	if (compr_type == UBIFS_COMPR_NONE) {
		out_len = *new_len;
	} else {
		err = ubifs_decompress(c, &dn->data, dlen, buf, &out_len, compr_type);
		if (err)
			goto out;
@@ -1485,9 +1488,6 @@ int ubifs_jnl_delete_xattr(struct ubifs_info *c, const struct inode *host,
	int sync = IS_DIRSYNC(host);
	struct ubifs_inode *host_ui = ubifs_inode(host);

	//dbg_jnl("host %lu, xattr ino %lu, name '%s', data len %d",
	//	host->i_ino, inode->i_ino, nm->name,
	//	ubifs_inode(inode)->data_len);
	ubifs_assert(inode->i_nlink == 0);
	ubifs_assert(mutex_is_locked(&host_ui->ui_mutex));

@@ -1500,7 +1500,7 @@ int ubifs_jnl_delete_xattr(struct ubifs_info *c, const struct inode *host,
	hlen = host_ui->data_len + UBIFS_INO_NODE_SZ;
	len = aligned_xlen + UBIFS_INO_NODE_SZ + ALIGN(hlen, 8);

	xent = kmalloc(len, GFP_NOFS);
	xent = kzalloc(len, GFP_NOFS);
	if (!xent)
		return -ENOMEM;

@@ -1607,7 +1607,7 @@ int ubifs_jnl_change_xattr(struct ubifs_info *c, const struct inode *inode,
	aligned_len1 = ALIGN(len1, 8);
	aligned_len = aligned_len1 + ALIGN(len2, 8);

	ino = kmalloc(aligned_len, GFP_NOFS);
	ino = kzalloc(aligned_len, GFP_NOFS);
	if (!ino)
		return -ENOMEM;

+1 −0
Original line number Diff line number Diff line
@@ -162,6 +162,7 @@ static inline void dent_key_init(const struct ubifs_info *c,
	uint32_t hash = c->key_hash(fname_name(nm), fname_len(nm));

	ubifs_assert(!(hash & ~UBIFS_S_KEY_HASH_MASK));
	ubifs_assert(!nm->hash && !nm->minor_hash);
	key->u32[0] = inum;
	key->u32[1] = hash | (UBIFS_DENT_KEY << UBIFS_S_KEY_HASH_BITS);
}
Loading