[rh8,4/9] ext4: Don't show the active balloon to user

Submitted by Konstantin Khorenko on March 3, 2021, 4:31 p.m.

Details

Message ID 20210303163118.294216-5-khorenko@virtuozzo.com
State New
Series "ext4: Port balloon code and other ext4 fixes"
Headers show

Commit Message

Konstantin Khorenko March 3, 2021, 4:31 p.m.
From: "Maxim V. Patlasov" <mpatlasov@parallels.com>

This is a port of
e123b6d ext4: Don't show the active balloon to user

Fix the readdir and lookup. The former one pretends the inode doesn't
exists, the latter one denies an access to on. Reporting negative dentry
in lookup is pointless, as in that case smth will have to be don the
ext4_create callback :\

[VvS RH79 rebase vz7.170.x]: minor context changes

(cherry picked from vz7 commit c231c40a93927f3080067e5d880ef11841de278c)
Signed-off-by: Konstantin Khorenko <khorenko@virtuozzo.com>
---
 fs/ext4/dir.c   | 15 ++++++++++++++-
 fs/ext4/namei.c |  9 +++++++++
 2 files changed, 23 insertions(+), 1 deletion(-)

Patch hide | download patch | download mbox

diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
index 92cfd690b64f..3a4158c60e47 100644
--- a/fs/ext4/dir.c
+++ b/fs/ext4/dir.c
@@ -103,6 +103,14 @@  int __ext4_check_dir_entry(const char *function, unsigned int line,
 	return 1;
 }
 
+static inline int ext4_balloon(struct super_block *sb, unsigned ino)
+{
+	struct ext4_sb_info *sbi;
+
+	sbi = EXT4_SB(sb);
+	return sbi->s_balloon_ino && (sbi->s_balloon_ino->i_ino == ino);
+}
+
 static int ext4_readdir(struct file *file, struct dir_context *ctx)
 {
 	unsigned int offset;
@@ -250,7 +258,8 @@  static int ext4_readdir(struct file *file, struct dir_context *ctx)
 			}
 			offset += ext4_rec_len_from_disk(de->rec_len,
 					sb->s_blocksize);
-			if (le32_to_cpu(de->inode)) {
+			if (le32_to_cpu(de->inode) &&
+			    !ext4_balloon(sb, le32_to_cpu(de->inode))) {
 				if (!IS_ENCRYPTED(inode)) {
 					if (!dir_emit(ctx, de->name,
 					    de->name_len,
@@ -518,6 +527,9 @@  static int call_filldir(struct file *file, struct dir_context *ctx,
 	}
 	ctx->pos = hash2pos(file, fname->hash, fname->minor_hash);
 	while (fname) {
+		if (ext4_balloon(sb, fname->inode))
+			goto skip;
+
 		if (!dir_emit(ctx, fname->name,
 				fname->name_len,
 				fname->inode,
@@ -525,6 +537,7 @@  static int call_filldir(struct file *file, struct dir_context *ctx,
 			info->extra_fname = fname;
 			return 1;
 		}
+skip:
 		fname = fname->next;
 	}
 	return 0;
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index 1a38715145e0..953e882b1d61 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -1595,6 +1595,11 @@  static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsi
 			iput(inode);
 			return ERR_PTR(-EPERM);
 		}
+		if (!IS_ERR(inode) &&
+		    inode == EXT4_SB(inode->i_sb)->s_balloon_ino) {
+			iput(inode);
+			return ERR_PTR(-EPERM);
+		}
 	}
 	return d_splice_alias(inode, dentry);
 }
@@ -3062,6 +3067,10 @@  static int ext4_unlink(struct inode *dir, struct dentry *dentry)
 	if (IS_DIRSYNC(dir))
 		ext4_handle_sync(handle);
 
+	retval = -EPERM;
+	if (inode == EXT4_SB(dir->i_sb)->s_balloon_ino)
+		goto end_unlink;
+
 	retval = ext4_delete_entry(handle, dir, de, bh);
 	if (retval)
 		goto end_unlink;