From: Jeff Layton <jlayton@kernel.org>
To: ceph-devel@vger.kernel.org
Cc: linux-fscrypt@vger.kernel.org, linux-fsdevel@vger.kernel.org
Subject: [RFC PATCH v5 12/19] ceph: send altname in MClientRequest
Date: Fri, 26 Mar 2021 13:32:20 -0400 [thread overview]
Message-ID: <20210326173227.96363-13-jlayton@kernel.org> (raw)
In-Reply-To: <20210326173227.96363-1-jlayton@kernel.org>
In the event that we have a filename longer than CEPH_NOHASH_NAME_MAX,
we'll need to hash the tail of the filename. The client however will
still need to know the full name of the file if it has a key.
To support this, the MClientRequest field has grown a new alternate_name
field that we populate with the full (binary) crypttext of the filename.
This is then transmitted to the clients in readdir or traces as part of
the dentry lease.
Add support for populating this field when the filenames are very long.
Signed-off-by: Jeff Layton <jlayton@kernel.org>
---
fs/ceph/mds_client.c | 79 +++++++++++++++++++++++++++++++++++++++++---
fs/ceph/mds_client.h | 2 ++
2 files changed, 76 insertions(+), 5 deletions(-)
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
index 31a4c9674681..a2c25292c4b1 100644
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -858,6 +858,7 @@ void ceph_mdsc_release_request(struct kref *kref)
put_cred(req->r_cred);
if (req->r_pagelist)
ceph_pagelist_release(req->r_pagelist);
+ kfree(req->r_altname);
put_request_session(req);
ceph_unreserve_caps(req->r_mdsc, &req->r_caps_reservation);
WARN_ON_ONCE(!list_empty(&req->r_wait));
@@ -2382,11 +2383,66 @@ static int encode_encrypted_fname(const struct inode *parent, struct dentry *den
dout("base64-encoded ciphertext name = %.*s\n", len, buf);
return elen;
}
+
+static u8 *get_fscrypt_altname(const struct ceph_mds_request *req, u32 *plen)
+{
+ struct inode *dir = req->r_parent;
+ struct dentry *dentry = req->r_dentry;
+ u8 *cryptbuf = NULL;
+ u32 len = 0;
+ int ret = 0;
+
+ /* only encode if we have parent and dentry */
+ if (!dir || !dentry)
+ goto success;
+
+ /* No-op unless this is encrypted */
+ if (!IS_ENCRYPTED(dir))
+ goto success;
+
+ ret = __fscrypt_prepare_readdir(dir);
+ if (ret)
+ return ERR_PTR(ret);
+
+ /* No key? Just ignore it. */
+ if (!fscrypt_has_encryption_key(dir))
+ goto success;
+
+ if (!fscrypt_fname_encrypted_size(dir, dentry->d_name.len, NAME_MAX, &len)) {
+ WARN_ON_ONCE(1);
+ return ERR_PTR(-ENAMETOOLONG);
+ }
+
+ /* No need to append altname if name is short enough */
+ if (len <= CEPH_NOHASH_NAME_MAX) {
+ len = 0;
+ goto success;
+ }
+
+ cryptbuf = kmalloc(len, GFP_KERNEL);
+ if (!cryptbuf)
+ return ERR_PTR(-ENOMEM);
+
+ ret = fscrypt_fname_encrypt(dir, &dentry->d_name, cryptbuf, len);
+ if (ret) {
+ kfree(cryptbuf);
+ return ERR_PTR(ret);
+ }
+success:
+ *plen = len;
+ return cryptbuf;
+}
#else
static int encode_encrypted_fname(const struct inode *parent, struct dentry *dentry, char *buf)
{
return -EOPNOTSUPP;
}
+
+static u8 *get_fscrypt_altname(const struct ceph_mds_request *req, u32 *plen)
+{
+ *plen = 0;
+ return NULL;
+}
#endif
/**
@@ -2601,7 +2657,7 @@ static int set_request_path_attr(struct inode *rinode, struct dentry *rdentry,
return r;
}
-static void encode_timestamp_and_gids(void **p,
+static void encode_mclientrequest_tail(void **p,
const struct ceph_mds_request *req)
{
struct ceph_timespec ts;
@@ -2610,11 +2666,16 @@ static void encode_timestamp_and_gids(void **p,
ceph_encode_timespec64(&ts, &req->r_stamp);
ceph_encode_copy(p, &ts, sizeof(ts));
- /* gid_list */
+ /* v4: gid_list */
ceph_encode_32(p, req->r_cred->group_info->ngroups);
for (i = 0; i < req->r_cred->group_info->ngroups; i++)
ceph_encode_64(p, from_kgid(&init_user_ns,
req->r_cred->group_info->gid[i]));
+
+ /* v5: altname */
+ ceph_encode_32(p, req->r_altname_len);
+ if (req->r_altname_len)
+ ceph_encode_copy(p, req->r_altname, req->r_altname_len);
}
/*
@@ -2659,10 +2720,18 @@ static struct ceph_msg *create_request_message(struct ceph_mds_session *session,
goto out_free1;
}
+ req->r_altname = get_fscrypt_altname(req, &req->r_altname_len);
+ if (IS_ERR(req->r_altname)) {
+ msg = ERR_CAST(req->r_altname);
+ req->r_altname = NULL;
+ goto out_free2;
+ }
+
len = legacy ? sizeof(*head) : sizeof(struct ceph_mds_request_head);
len += pathlen1 + pathlen2 + 2*(1 + sizeof(u32) + sizeof(u64)) +
sizeof(struct ceph_timespec);
len += sizeof(u32) + (sizeof(u64) * req->r_cred->group_info->ngroups);
+ len += sizeof(u32) + req->r_altname_len;
/* calculate (max) length for cap releases */
len += sizeof(struct ceph_mds_request_release) *
@@ -2693,7 +2762,7 @@ static struct ceph_msg *create_request_message(struct ceph_mds_session *session,
} else {
struct ceph_mds_request_head *new_head = msg->front.iov_base;
- msg->hdr.version = cpu_to_le16(4);
+ msg->hdr.version = cpu_to_le16(5);
new_head->version = cpu_to_le16(CEPH_MDS_REQUEST_HEAD_VERSION);
head = (struct ceph_mds_request_head_old *)&new_head->oldest_client_tid;
p = msg->front.iov_base + sizeof(*new_head);
@@ -2744,7 +2813,7 @@ static struct ceph_msg *create_request_message(struct ceph_mds_session *session,
head->num_releases = cpu_to_le16(releases);
- encode_timestamp_and_gids(&p, req);
+ encode_mclientrequest_tail(&p, req);
if (WARN_ON_ONCE(p > end)) {
ceph_msg_put(msg);
@@ -2853,7 +2922,7 @@ static int __prepare_send_request(struct ceph_mds_session *session,
rhead->num_releases = 0;
p = msg->front.iov_base + req->r_request_release_offset;
- encode_timestamp_and_gids(&p, req);
+ encode_mclientrequest_tail(&p, req);
msg->front.iov_len = p - msg->front.iov_base;
msg->hdr.front_len = cpu_to_le32(msg->front.iov_len);
diff --git a/fs/ceph/mds_client.h b/fs/ceph/mds_client.h
index b6aeca9b241b..33b8dba7a44e 100644
--- a/fs/ceph/mds_client.h
+++ b/fs/ceph/mds_client.h
@@ -278,6 +278,8 @@ struct ceph_mds_request {
struct mutex r_fill_mutex;
union ceph_mds_request_args r_args;
+ u8 *r_altname; /* fscrypt binary crypttext for long filenames */
+ u32 r_altname_len; /* length of r_altname */
int r_fmode; /* file mode, if expecting cap */
const struct cred *r_cred;
int r_request_release_offset;
--
2.30.2
next prev parent reply other threads:[~2021-03-26 17:33 UTC|newest]
Thread overview: 39+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-03-26 17:32 [RFC PATCH v5 00/19] ceph+fscrypt: context, filename and symlink support Jeff Layton
2021-03-26 17:32 ` [RFC PATCH v5 01/19] vfs: export new_inode_pseudo Jeff Layton
2021-04-08 1:08 ` Eric Biggers
2021-04-08 16:18 ` Jeff Layton
2021-03-26 17:32 ` [RFC PATCH v5 02/19] fscrypt: export fscrypt_base64_encode and fscrypt_base64_decode Jeff Layton
2021-04-08 1:06 ` Eric Biggers
2021-04-08 16:22 ` Jeff Layton
2021-03-26 17:32 ` [RFC PATCH v5 03/19] fscrypt: export fscrypt_fname_encrypt and fscrypt_fname_encrypted_size Jeff Layton
2021-04-08 1:19 ` Eric Biggers
2021-03-26 17:32 ` [RFC PATCH v5 04/19] fscrypt: add fscrypt_context_for_new_inode Jeff Layton
2021-04-08 1:21 ` Eric Biggers
2021-04-08 16:27 ` Jeff Layton
2021-03-26 17:32 ` [RFC PATCH v5 05/19] ceph: crypto context handling for ceph Jeff Layton
2021-03-26 17:32 ` [RFC PATCH v5 06/19] ceph: implement -o test_dummy_encryption mount option Jeff Layton
2021-03-26 17:32 ` [RFC PATCH v5 07/19] ceph: preallocate inode for ops that may create one Jeff Layton
2021-03-26 17:32 ` [RFC PATCH v5 08/19] ceph: add routine to create fscrypt context prior to RPC Jeff Layton
2021-03-26 17:32 ` [RFC PATCH v5 09/19] ceph: make ceph_msdc_build_path use ref-walk Jeff Layton
2021-03-26 17:32 ` [RFC PATCH v5 10/19] ceph: add encrypted fname handling to ceph_mdsc_build_path Jeff Layton
2021-03-26 17:32 ` [RFC PATCH v5 11/19] ceph: decode alternate_name in lease info Jeff Layton
2021-03-26 17:32 ` Jeff Layton [this message]
2021-03-26 17:32 ` [RFC PATCH v5 13/19] ceph: properly set DCACHE_NOKEY_NAME flag in lookup Jeff Layton
2021-03-26 17:32 ` [RFC PATCH v5 14/19] ceph: make d_revalidate call fscrypt revalidator for encrypted dentries Jeff Layton
2021-03-26 17:32 ` [RFC PATCH v5 15/19] ceph: add helpers for converting names for userland presentation Jeff Layton
2021-03-26 17:32 ` [RFC PATCH v5 16/19] ceph: add fscrypt support to ceph_fill_trace Jeff Layton
2021-03-26 17:32 ` [RFC PATCH v5 17/19] ceph: add support to readdir for encrypted filenames Jeff Layton
2021-03-26 17:32 ` [RFC PATCH v5 18/19] ceph: create symlinks with encrypted and base64-encoded targets Jeff Layton
2021-03-26 17:32 ` [RFC PATCH v5 19/19] ceph: add fscrypt ioctls Jeff Layton
2021-04-06 15:38 ` Luis Henriques
2021-04-06 16:03 ` Jeff Layton
2021-04-06 16:24 ` Luis Henriques
2021-04-06 17:27 ` Jeff Layton
2021-04-06 18:04 ` Luis Henriques
2021-04-07 12:47 ` Jeff Layton
2021-03-26 18:38 ` [RFC PATCH v5 00/19] ceph+fscrypt: context, filename and symlink support Jeff Layton
2021-03-31 20:35 ` [RFC PATCH v5 20/19] ceph: make ceph_get_name decrypt filenames Jeff Layton
2021-04-01 11:14 ` Luis Henriques
2021-04-01 12:15 ` Jeff Layton
2021-04-01 13:05 ` Luis Henriques
2021-04-01 13:12 ` Jeff Layton
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=20210326173227.96363-13-jlayton@kernel.org \
--to=jlayton@kernel.org \
--cc=ceph-devel@vger.kernel.org \
--cc=linux-fscrypt@vger.kernel.org \
--cc=linux-fsdevel@vger.kernel.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).