From: Alexander Larsson <alexl@redhat.com>
To: miklos@szeredi.hu
Cc: linux-unionfs@vger.kernel.org, amir73il@gmail.com,
ebiggers@kernel.org, tytso@mit.edu, fsverity@lists.linux.dev,
Alexander Larsson <alexl@redhat.com>
Subject: [PATCH v4 2/4] ovl: Add versioned header for overlay.metacopy xattr
Date: Wed, 21 Jun 2023 13:18:26 +0200 [thread overview]
Message-ID: <b7a2dfb80e35dda04edd942ad715dc88b784c218.1687345663.git.alexl@redhat.com> (raw)
In-Reply-To: <cover.1687345663.git.alexl@redhat.com>
Historically overlay.metacopy was a zero-size xattr, and it's
existence marked a metacopy file. This change adds a versioned header
with a flag field, a length and a digest. The initial use-case of this
will be for validating a fs-verity digest, but the flags field could
also be used later for other new features.
ovl_check_metacopy_xattr() now returns the size of the xattr,
emulating a size of OVL_METACOPY_MIN_SIZE for empty xattrs to
distinguish it from the no-xattr case.
Signed-off-by: Alexander Larsson <alexl@redhat.com>
---
fs/overlayfs/namei.c | 10 +++++-----
fs/overlayfs/overlayfs.h | 24 +++++++++++++++++++++++-
fs/overlayfs/util.c | 37 +++++++++++++++++++++++++++++++++----
3 files changed, 61 insertions(+), 10 deletions(-)
diff --git a/fs/overlayfs/namei.c b/fs/overlayfs/namei.c
index 57adf911735f..3dd480253710 100644
--- a/fs/overlayfs/namei.c
+++ b/fs/overlayfs/namei.c
@@ -25,7 +25,7 @@ struct ovl_lookup_data {
bool stop;
bool last;
char *redirect;
- bool metacopy;
+ int metacopy;
/* Referring to last redirect xattr */
bool absolute_redirect;
};
@@ -270,7 +270,7 @@ static int ovl_lookup_single(struct dentry *base, struct ovl_lookup_data *d,
d->stop = true;
goto put_and_out;
}
- err = ovl_check_metacopy_xattr(OVL_FS(d->sb), &path);
+ err = ovl_check_metacopy_xattr(OVL_FS(d->sb), &path, NULL);
if (err < 0)
goto out_err;
@@ -963,7 +963,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
.stop = false,
.last = ovl_redirect_follow(ofs) ? false : !ovl_numlower(poe),
.redirect = NULL,
- .metacopy = false,
+ .metacopy = 0,
};
if (dentry->d_name.len > ofs->namelen)
@@ -1120,7 +1120,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
/* Defer lookup of lowerdata in data-only layers to first access */
if (d.metacopy && ctr && ofs->numdatalayer && d.absolute_redirect) {
- d.metacopy = false;
+ d.metacopy = 0;
ctr++;
}
@@ -1211,7 +1211,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
upperredirect = NULL;
goto out_free_oe;
}
- err = ovl_check_metacopy_xattr(ofs, &upperpath);
+ err = ovl_check_metacopy_xattr(ofs, &upperpath, NULL);
if (err < 0)
goto out_free_oe;
uppermetacopy = err;
diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h
index cf92a9aaf934..6d4e08df0dfe 100644
--- a/fs/overlayfs/overlayfs.h
+++ b/fs/overlayfs/overlayfs.h
@@ -7,6 +7,7 @@
#include <linux/kernel.h>
#include <linux/uuid.h>
#include <linux/fs.h>
+#include <linux/fsverity.h>
#include <linux/namei.h>
#include <linux/posix_acl.h>
#include <linux/posix_acl_xattr.h>
@@ -140,6 +141,26 @@ struct ovl_fh {
#define OVL_FH_FID_OFFSET (OVL_FH_WIRE_OFFSET + \
offsetof(struct ovl_fb, fid))
+/* On-disk format for "metacopy" xattr (if non-zero size) */
+struct ovl_metacopy {
+ u8 version; /* 0 */
+ u8 len; /* size of this header + used digest bytes */
+ u8 flags;
+ u8 digest_algo; /* FS_VERITY_HASH_ALG_* constant, 0 for no digest */
+ u8 digest[FS_VERITY_MAX_DIGEST_SIZE]; /* Only the used part on disk */
+} __packed;
+
+#define OVL_METACOPY_MAX_SIZE (sizeof(struct ovl_metacopy))
+#define OVL_METACOPY_MIN_SIZE (OVL_METACOPY_MAX_SIZE - FS_VERITY_MAX_DIGEST_SIZE)
+#define OVL_METACOPY_INIT { 0, OVL_METACOPY_MIN_SIZE }
+
+static inline int ovl_metadata_digest_size(const struct ovl_metacopy *metacopy)
+{
+ if (metacopy->len < OVL_METACOPY_MIN_SIZE)
+ return 0;
+ return (int)metacopy->len - OVL_METACOPY_MIN_SIZE;
+}
+
extern const char *const ovl_xattr_table[][2];
static inline const char *ovl_xattr(struct ovl_fs *ofs, enum ovl_xattr ox)
{
@@ -490,7 +511,8 @@ bool ovl_need_index(struct dentry *dentry);
int ovl_nlink_start(struct dentry *dentry);
void ovl_nlink_end(struct dentry *dentry);
int ovl_lock_rename_workdir(struct dentry *workdir, struct dentry *upperdir);
-int ovl_check_metacopy_xattr(struct ovl_fs *ofs, const struct path *path);
+int ovl_check_metacopy_xattr(struct ovl_fs *ofs, const struct path *path,
+ struct ovl_metacopy *data);
bool ovl_is_metacopy_dentry(struct dentry *dentry);
char *ovl_get_redirect_xattr(struct ovl_fs *ofs, const struct path *path, int padding);
int ovl_sync_status(struct ovl_fs *ofs);
diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c
index 7ef9e13c404a..921747223991 100644
--- a/fs/overlayfs/util.c
+++ b/fs/overlayfs/util.c
@@ -1054,8 +1054,12 @@ int ovl_lock_rename_workdir(struct dentry *workdir, struct dentry *upperdir)
return -EIO;
}
-/* err < 0, 0 if no metacopy xattr, 1 if metacopy xattr found */
-int ovl_check_metacopy_xattr(struct ovl_fs *ofs, const struct path *path)
+/*
+ * err < 0, 0 if no metacopy xattr, metacopy data size if xattr found.
+ * an empty xattr returns OVL_METACOPY_MIN_SIZE to distinguish from no xattr value.
+ */
+int ovl_check_metacopy_xattr(struct ovl_fs *ofs, const struct path *path,
+ struct ovl_metacopy *data)
{
int res;
@@ -1063,7 +1067,8 @@ int ovl_check_metacopy_xattr(struct ovl_fs *ofs, const struct path *path)
if (!S_ISREG(d_inode(path->dentry)->i_mode))
return 0;
- res = ovl_path_getxattr(ofs, path, OVL_XATTR_METACOPY, NULL, 0);
+ res = ovl_path_getxattr(ofs, path, OVL_XATTR_METACOPY,
+ data, data ? OVL_METACOPY_MAX_SIZE : 0);
if (res < 0) {
if (res == -ENODATA || res == -EOPNOTSUPP)
return 0;
@@ -1077,7 +1082,31 @@ int ovl_check_metacopy_xattr(struct ovl_fs *ofs, const struct path *path)
goto out;
}
- return 1;
+ if (res == 0) {
+ /* Emulate empty data for zero size metacopy xattr */
+ res = OVL_METACOPY_MIN_SIZE;
+ if (data) {
+ memset(data, 0, res);
+ data->len = res;
+ }
+ } else if (res < OVL_METACOPY_MIN_SIZE) {
+ pr_warn_ratelimited("metacopy file '%pd' has too small xattr\n",
+ path->dentry);
+ return -EIO;
+ } else if (data) {
+ if (data->version != 0) {
+ pr_warn_ratelimited("metacopy file '%pd' has unsupported version\n",
+ path->dentry);
+ return -EIO;
+ }
+ if (res != data->len) {
+ pr_warn_ratelimited("metacopy file '%pd' has invalid xattr size\n",
+ path->dentry);
+ return -EIO;
+ }
+ }
+
+ return res;
out:
pr_warn_ratelimited("failed to get metacopy (%i)\n", res);
return res;
--
2.40.1
next prev parent reply other threads:[~2023-06-21 11:20 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-06-21 11:18 [PATCH v5 0/4] ovl: Add support for fs-verity checking of lowerdata Alexander Larsson
2023-06-21 11:18 ` [PATCH v4 1/4] ovl: Add framework for verity support Alexander Larsson
2023-06-21 12:18 ` Amir Goldstein
2023-07-03 19:08 ` Eric Biggers
2023-06-21 11:18 ` Alexander Larsson [this message]
2023-06-21 12:21 ` [PATCH v4 2/4] ovl: Add versioned header for overlay.metacopy xattr Amir Goldstein
2023-07-03 19:13 ` Eric Biggers
2023-07-05 8:07 ` Alexander Larsson
2023-07-05 13:12 ` Amir Goldstein
2023-06-21 11:18 ` [PATCH v4 3/4] ovl: Validate verity xattr when resolving lowerdata Alexander Larsson
2023-06-21 12:24 ` Amir Goldstein
2023-07-03 19:24 ` Eric Biggers
2023-07-05 9:09 ` Alexander Larsson
2023-06-21 11:18 ` [PATCH v4 4/4] ovl: Handle verity during copy-up Alexander Larsson
2023-06-21 12:26 ` Amir Goldstein
2023-07-03 19:29 ` Eric Biggers
2023-07-05 9:11 ` Alexander Larsson
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=b7a2dfb80e35dda04edd942ad715dc88b784c218.1687345663.git.alexl@redhat.com \
--to=alexl@redhat.com \
--cc=amir73il@gmail.com \
--cc=ebiggers@kernel.org \
--cc=fsverity@lists.linux.dev \
--cc=linux-unionfs@vger.kernel.org \
--cc=miklos@szeredi.hu \
--cc=tytso@mit.edu \
/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