linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
From: Oleksandr Tymoshenko <ovt@google.com>
To: Jonathan Corbet <corbet@lwn.net>, Hugh Dickins <hughd@google.com>,
	 Andrew Morton <akpm@linux-foundation.org>
Cc: ovt@google.com, linux-doc@vger.kernel.org,
	linux-kernel@vger.kernel.org,  linux-mm@kvack.org
Subject: [PATCH] shmem: add support for user extended attributes
Date: Thu, 20 Jul 2023 06:54:27 +0000	[thread overview]
Message-ID: <20230720065430.2178136-1-ovt@google.com> (raw)

User extended attributes are not enabled in tmpfs because
the size of the value is not limited and the memory allocated
for it is not counted against any limit. Malicious
non-privileged user can exhaust kernel memory by creating
user.* extended attribute with very large value.

There are still situations when enabling suport for extended
user attributes on tmpfs is required and the attack vector
is not applicable, for instance batch jobs with trusted binaries.

This patch introduces two mount options to enable/disable
support for user.* extended attributes on tmpfs:

user_xattr    enable support for user extended aatributes
nouser_xattr  disable support for user extended attributes

The default behavior of the filesystem is not changed.

Signed-off-by: Oleksandr Tymoshenko <ovt@google.com>
---
 Documentation/filesystems/tmpfs.rst | 12 ++++++++
 include/linux/shmem_fs.h            |  1 +
 mm/shmem.c                          | 45 +++++++++++++++++++++++++++++
 3 files changed, 58 insertions(+)

diff --git a/Documentation/filesystems/tmpfs.rst b/Documentation/filesystems/tmpfs.rst
index f18f46be5c0c..5700ba72d095 100644
--- a/Documentation/filesystems/tmpfs.rst
+++ b/Documentation/filesystems/tmpfs.rst
@@ -215,6 +215,16 @@ will give you tmpfs instance on /mytmpfs which can allocate 10GB
 RAM/SWAP in 10240 inodes and it is only accessible by root.
 
 
+tmpfs, when compiled with CONFIG_TMPFS_XATTR, does not support
+Extended User Attributes for security reasons. The support can be
+enabled/disabled by two mount options:
+
+============  ===========================================
+user_xattr    Enable support for Extended User Attributes
+nouser_xattr  Disable upport for Extended User Attributes
+============  ===========================================
+
+
 :Author:
    Christoph Rohland <cr@sap.com>, 1.12.01
 :Updated:
@@ -223,3 +233,5 @@ RAM/SWAP in 10240 inodes and it is only accessible by root.
    KOSAKI Motohiro, 16 Mar 2010
 :Updated:
    Chris Down, 13 July 2020
+:Updated:
+   Oleksandr Tymoshenko, 19 July 2023
diff --git a/include/linux/shmem_fs.h b/include/linux/shmem_fs.h
index 9029abd29b1c..f06d18b9041c 100644
--- a/include/linux/shmem_fs.h
+++ b/include/linux/shmem_fs.h
@@ -53,6 +53,7 @@ struct shmem_sb_info {
 	spinlock_t shrinklist_lock;   /* Protects shrinklist */
 	struct list_head shrinklist;  /* List of shinkable inodes */
 	unsigned long shrinklist_len; /* Length of shrinklist */
+	bool user_xattr;	      /* user.* xattrs are allowed */
 };
 
 static inline struct shmem_inode_info *SHMEM_I(struct inode *inode)
diff --git a/mm/shmem.c b/mm/shmem.c
index 2f2e0e618072..4f7d46d65494 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -85,6 +85,7 @@ static struct vfsmount *shm_mnt;
 
 #define BLOCKS_PER_PAGE  (PAGE_SIZE/512)
 #define VM_ACCT(size)    (PAGE_ALIGN(size) >> PAGE_SHIFT)
+#define TMPFS_USER_XATTR_INDEX 1
 
 /* Pretend that each entry is of this size in directory's i_size */
 #define BOGO_DIRENT_SIZE 20
@@ -116,11 +117,13 @@ struct shmem_options {
 	int huge;
 	int seen;
 	bool noswap;
+	bool user_xattr;
 #define SHMEM_SEEN_BLOCKS 1
 #define SHMEM_SEEN_INODES 2
 #define SHMEM_SEEN_HUGE 4
 #define SHMEM_SEEN_INUMS 8
 #define SHMEM_SEEN_NOSWAP 16
+#define SHMEM_SEEN_USER_XATTR 32
 };
 
 #ifdef CONFIG_TMPFS
@@ -3447,6 +3450,16 @@ static int shmem_xattr_handler_get(const struct xattr_handler *handler,
 				   const char *name, void *buffer, size_t size)
 {
 	struct shmem_inode_info *info = SHMEM_I(inode);
+	struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);
+
+	switch (handler->flags) {
+	case TMPFS_USER_XATTR_INDEX:
+		if (!sbinfo->user_xattr)
+			return -EOPNOTSUPP;
+		break;
+	default:
+		break;
+	}
 
 	name = xattr_full_name(handler, name);
 	return simple_xattr_get(&info->xattrs, name, buffer, size);
@@ -3459,8 +3472,18 @@ static int shmem_xattr_handler_set(const struct xattr_handler *handler,
 				   size_t size, int flags)
 {
 	struct shmem_inode_info *info = SHMEM_I(inode);
+	struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);
 	int err;
 
+	switch (handler->flags) {
+	case TMPFS_USER_XATTR_INDEX:
+		if (!sbinfo->user_xattr)
+			return -EOPNOTSUPP;
+		break;
+	default:
+		break;
+	}
+
 	name = xattr_full_name(handler, name);
 	err = simple_xattr_set(&info->xattrs, name, value, size, flags, NULL);
 	if (!err) {
@@ -3482,9 +3505,17 @@ static const struct xattr_handler shmem_trusted_xattr_handler = {
 	.set = shmem_xattr_handler_set,
 };
 
+static const struct xattr_handler shmem_user_xattr_handler = {
+	.prefix = XATTR_USER_PREFIX,
+	.flags = TMPFS_USER_XATTR_INDEX,
+	.get = shmem_xattr_handler_get,
+	.set = shmem_xattr_handler_set,
+};
+
 static const struct xattr_handler *shmem_xattr_handlers[] = {
 	&shmem_security_xattr_handler,
 	&shmem_trusted_xattr_handler,
+	&shmem_user_xattr_handler,
 	NULL
 };
 
@@ -3604,6 +3635,8 @@ enum shmem_param {
 	Opt_inode32,
 	Opt_inode64,
 	Opt_noswap,
+	Opt_user_xattr,
+	Opt_nouser_xattr,
 };
 
 static const struct constant_table shmem_param_enums_huge[] = {
@@ -3626,6 +3659,8 @@ const struct fs_parameter_spec shmem_fs_parameters[] = {
 	fsparam_flag  ("inode32",	Opt_inode32),
 	fsparam_flag  ("inode64",	Opt_inode64),
 	fsparam_flag  ("noswap",	Opt_noswap),
+	fsparam_flag  ("user_xattr",	Opt_user_xattr),
+	fsparam_flag  ("nouser_xattr",	Opt_nouser_xattr),
 	{}
 };
 
@@ -3717,6 +3752,14 @@ static int shmem_parse_one(struct fs_context *fc, struct fs_parameter *param)
 		ctx->noswap = true;
 		ctx->seen |= SHMEM_SEEN_NOSWAP;
 		break;
+	case Opt_user_xattr:
+		ctx->user_xattr = true;
+		ctx->seen |= SHMEM_SEEN_USER_XATTR;
+		break;
+	case Opt_nouser_xattr:
+		ctx->user_xattr = false;
+		ctx->seen |= SHMEM_SEEN_USER_XATTR;
+		break;
 	}
 	return 0;
 
@@ -3834,6 +3877,8 @@ static int shmem_reconfigure(struct fs_context *fc)
 		sbinfo->max_inodes  = ctx->inodes;
 		sbinfo->free_inodes = ctx->inodes - inodes;
 	}
+	if (ctx->seen & SHMEM_SEEN_USER_XATTR)
+		sbinfo->user_xattr = ctx->user_xattr;
 
 	/*
 	 * Preserve previous mempolicy unless mpol remount option was specified.
-- 
2.41.0.255.g8b1d071c50-goog



             reply	other threads:[~2023-07-20  6:55 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-07-20  6:54 Oleksandr Tymoshenko [this message]
2023-07-20 16:56 ` [PATCH] shmem: add support for user extended attributes Hugh Dickins
2023-07-20 17:09   ` Oleksandr Tymoshenko
2023-07-20 17:42     ` Hugh Dickins
2023-08-14  8:23   ` Snaipe
2023-08-15  3:51     ` Hugh Dickins
2023-08-15  7:46       ` Franklin “Snaipe” Mathieu
2023-08-15  8:23         ` Christian Brauner
2023-08-21 17:52           ` Hugh Dickins
2023-08-22  9:01             ` Christian Brauner
2023-08-22 17:50             ` Oleksandr Tymoshenko

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230720065430.2178136-1-ovt@google.com \
    --to=ovt@google.com \
    --cc=akpm@linux-foundation.org \
    --cc=corbet@lwn.net \
    --cc=hughd@google.com \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).