Skip to content

Commit 3611ce2

Browse files
jtlaytongregkh
authored andcommitted
ceph: don't allow access to MDS-private inodes
[ Upstream commit d4f6b31 ] The MDS reserves a set of inodes for its own usage, and these should never be accessible to clients. Add a new helper to vet a proposed inode number against that range, and complain loudly and refuse to create or look it up if it's in it. Also, ensure that the MDS doesn't try to delegate inodes that are in that range or lower. Print a warning if it does, and don't save the range in the xarray. URL: https://tracker.ceph.com/issues/49922 Signed-off-by: Jeff Layton <jlayton@kernel.org> Reviewed-by: Xiubo Li <xiubli@redhat.com> Signed-off-by: Ilya Dryomov <idryomov@gmail.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent db27571 commit 3611ce2

4 files changed

Lines changed: 42 additions & 0 deletions

File tree

fs/ceph/export.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,10 @@ static struct inode *__lookup_inode(struct super_block *sb, u64 ino)
129129

130130
vino.ino = ino;
131131
vino.snap = CEPH_NOSNAP;
132+
133+
if (ceph_vino_is_reserved(vino))
134+
return ERR_PTR(-ESTALE);
135+
132136
inode = ceph_find_inode(sb, vino);
133137
if (!inode) {
134138
struct ceph_mds_request *req;
@@ -214,6 +218,10 @@ static struct dentry *__snapfh_to_dentry(struct super_block *sb,
214218
vino.ino = sfh->ino;
215219
vino.snap = sfh->snapid;
216220
}
221+
222+
if (ceph_vino_is_reserved(vino))
223+
return ERR_PTR(-ESTALE);
224+
217225
inode = ceph_find_inode(sb, vino);
218226
if (inode)
219227
return d_obtain_alias(inode);

fs/ceph/inode.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ struct inode *ceph_get_inode(struct super_block *sb, struct ceph_vino vino)
5656
{
5757
struct inode *inode;
5858

59+
if (ceph_vino_is_reserved(vino))
60+
return ERR_PTR(-EREMOTEIO);
61+
5962
inode = iget5_locked(sb, (unsigned long)vino.ino, ceph_ino_compare,
6063
ceph_set_ino_cb, &vino);
6164
if (!inode)

fs/ceph/mds_client.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,13 @@ static int ceph_parse_deleg_inos(void **p, void *end,
433433

434434
ceph_decode_64_safe(p, end, start, bad);
435435
ceph_decode_64_safe(p, end, len, bad);
436+
437+
/* Don't accept a delegation of system inodes */
438+
if (start < CEPH_INO_SYSTEM_BASE) {
439+
pr_warn_ratelimited("ceph: ignoring reserved inode range delegation (start=0x%llx len=0x%llx)\n",
440+
start, len);
441+
continue;
442+
}
436443
while (len--) {
437444
int err = xa_insert(&s->s_delegated_inos, ino = start++,
438445
DELEGATED_INO_AVAILABLE,

fs/ceph/super.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -529,10 +529,34 @@ static inline int ceph_ino_compare(struct inode *inode, void *data)
529529
ci->i_vino.snap == pvino->snap;
530530
}
531531

532+
/*
533+
* The MDS reserves a set of inodes for its own usage. These should never
534+
* be accessible by clients, and so the MDS has no reason to ever hand these
535+
* out. The range is CEPH_MDS_INO_MDSDIR_OFFSET..CEPH_INO_SYSTEM_BASE.
536+
*
537+
* These come from src/mds/mdstypes.h in the ceph sources.
538+
*/
539+
#define CEPH_MAX_MDS 0x100
540+
#define CEPH_NUM_STRAY 10
541+
#define CEPH_MDS_INO_MDSDIR_OFFSET (1 * CEPH_MAX_MDS)
542+
#define CEPH_INO_SYSTEM_BASE ((6*CEPH_MAX_MDS) + (CEPH_MAX_MDS * CEPH_NUM_STRAY))
543+
544+
static inline bool ceph_vino_is_reserved(const struct ceph_vino vino)
545+
{
546+
if (vino.ino < CEPH_INO_SYSTEM_BASE &&
547+
vino.ino >= CEPH_MDS_INO_MDSDIR_OFFSET) {
548+
WARN_RATELIMIT(1, "Attempt to access reserved inode number 0x%llx", vino.ino);
549+
return true;
550+
}
551+
return false;
552+
}
532553

533554
static inline struct inode *ceph_find_inode(struct super_block *sb,
534555
struct ceph_vino vino)
535556
{
557+
if (ceph_vino_is_reserved(vino))
558+
return NULL;
559+
536560
/*
537561
* NB: The hashval will be run through the fs/inode.c hash function
538562
* anyway, so there is no need to squash the inode number down to

0 commit comments

Comments
 (0)