mirror of
https://github.com/torvalds/linux.git
synced 2024-11-23 04:31:50 +00:00
ceph: don't allow access to MDS-private inodes
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>
This commit is contained in:
parent
2d6795fbb8
commit
d4f6b31d72
@ -129,6 +129,10 @@ static struct inode *__lookup_inode(struct super_block *sb, u64 ino)
|
|||||||
|
|
||||||
vino.ino = ino;
|
vino.ino = ino;
|
||||||
vino.snap = CEPH_NOSNAP;
|
vino.snap = CEPH_NOSNAP;
|
||||||
|
|
||||||
|
if (ceph_vino_is_reserved(vino))
|
||||||
|
return ERR_PTR(-ESTALE);
|
||||||
|
|
||||||
inode = ceph_find_inode(sb, vino);
|
inode = ceph_find_inode(sb, vino);
|
||||||
if (!inode) {
|
if (!inode) {
|
||||||
struct ceph_mds_request *req;
|
struct ceph_mds_request *req;
|
||||||
@ -214,6 +218,10 @@ static struct dentry *__snapfh_to_dentry(struct super_block *sb,
|
|||||||
vino.ino = sfh->ino;
|
vino.ino = sfh->ino;
|
||||||
vino.snap = sfh->snapid;
|
vino.snap = sfh->snapid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ceph_vino_is_reserved(vino))
|
||||||
|
return ERR_PTR(-ESTALE);
|
||||||
|
|
||||||
inode = ceph_find_inode(sb, vino);
|
inode = ceph_find_inode(sb, vino);
|
||||||
if (inode)
|
if (inode)
|
||||||
return d_obtain_alias(inode);
|
return d_obtain_alias(inode);
|
||||||
|
@ -56,6 +56,9 @@ struct inode *ceph_get_inode(struct super_block *sb, struct ceph_vino vino)
|
|||||||
{
|
{
|
||||||
struct inode *inode;
|
struct inode *inode;
|
||||||
|
|
||||||
|
if (ceph_vino_is_reserved(vino))
|
||||||
|
return ERR_PTR(-EREMOTEIO);
|
||||||
|
|
||||||
inode = iget5_locked(sb, (unsigned long)vino.ino, ceph_ino_compare,
|
inode = iget5_locked(sb, (unsigned long)vino.ino, ceph_ino_compare,
|
||||||
ceph_set_ino_cb, &vino);
|
ceph_set_ino_cb, &vino);
|
||||||
if (!inode)
|
if (!inode)
|
||||||
|
@ -440,6 +440,13 @@ static int ceph_parse_deleg_inos(void **p, void *end,
|
|||||||
|
|
||||||
ceph_decode_64_safe(p, end, start, bad);
|
ceph_decode_64_safe(p, end, start, bad);
|
||||||
ceph_decode_64_safe(p, end, len, bad);
|
ceph_decode_64_safe(p, end, len, bad);
|
||||||
|
|
||||||
|
/* Don't accept a delegation of system inodes */
|
||||||
|
if (start < CEPH_INO_SYSTEM_BASE) {
|
||||||
|
pr_warn_ratelimited("ceph: ignoring reserved inode range delegation (start=0x%llx len=0x%llx)\n",
|
||||||
|
start, len);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
while (len--) {
|
while (len--) {
|
||||||
int err = xa_insert(&s->s_delegated_inos, ino = start++,
|
int err = xa_insert(&s->s_delegated_inos, ino = start++,
|
||||||
DELEGATED_INO_AVAILABLE,
|
DELEGATED_INO_AVAILABLE,
|
||||||
|
@ -529,10 +529,34 @@ static inline int ceph_ino_compare(struct inode *inode, void *data)
|
|||||||
ci->i_vino.snap == pvino->snap;
|
ci->i_vino.snap == pvino->snap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The MDS reserves a set of inodes for its own usage. These should never
|
||||||
|
* be accessible by clients, and so the MDS has no reason to ever hand these
|
||||||
|
* out. The range is CEPH_MDS_INO_MDSDIR_OFFSET..CEPH_INO_SYSTEM_BASE.
|
||||||
|
*
|
||||||
|
* These come from src/mds/mdstypes.h in the ceph sources.
|
||||||
|
*/
|
||||||
|
#define CEPH_MAX_MDS 0x100
|
||||||
|
#define CEPH_NUM_STRAY 10
|
||||||
|
#define CEPH_MDS_INO_MDSDIR_OFFSET (1 * CEPH_MAX_MDS)
|
||||||
|
#define CEPH_INO_SYSTEM_BASE ((6*CEPH_MAX_MDS) + (CEPH_MAX_MDS * CEPH_NUM_STRAY))
|
||||||
|
|
||||||
|
static inline bool ceph_vino_is_reserved(const struct ceph_vino vino)
|
||||||
|
{
|
||||||
|
if (vino.ino < CEPH_INO_SYSTEM_BASE &&
|
||||||
|
vino.ino >= CEPH_MDS_INO_MDSDIR_OFFSET) {
|
||||||
|
WARN_RATELIMIT(1, "Attempt to access reserved inode number 0x%llx", vino.ino);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static inline struct inode *ceph_find_inode(struct super_block *sb,
|
static inline struct inode *ceph_find_inode(struct super_block *sb,
|
||||||
struct ceph_vino vino)
|
struct ceph_vino vino)
|
||||||
{
|
{
|
||||||
|
if (ceph_vino_is_reserved(vino))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NB: The hashval will be run through the fs/inode.c hash function
|
* NB: The hashval will be run through the fs/inode.c hash function
|
||||||
* anyway, so there is no need to squash the inode number down to
|
* anyway, so there is no need to squash the inode number down to
|
||||||
|
Loading…
Reference in New Issue
Block a user