[PATCH] ceph: cleanup in check_new_map() method

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Viacheslav Dubeyko <Slava.Dubeyko@xxxxxxx>

The Coverity Scan service has reported a potential issue
in check_new_map() method [1]. The check_new_map() executes
checking of newmap->m_info on NULL in the beginning of
the method. However, it operates by newmap->m_info later
in the method without any check on NULL. Analysis of the code
flow shows that ceph_mdsmap_decode() guarantees the allocation
of m_info array. And check_new_map() never will be called
with newmap->m_info not allocated.

This patch exchanges checking of newmap->m_info on BUG_ON()
pattern because the situation of having NULL in newmap->m_info
during check_new_map() is not expecting event. Also, this patch
reworks logic of __open_export_target_sessions(),
ceph_mdsmap_get_addr(), ceph_mdsmap_get_state(), and
ceph_mdsmap_is_laggy() by checking mdsmap->m_info on NULL value.

[1] https://scan5.scan.coverity.com/#/project-view/64304/10063?selectedIssue=1491799

Signed-off-by: Viacheslav Dubeyko <Slava.Dubeyko@xxxxxxx>
cc: Alex Markuze <amarkuze@xxxxxxxxxx>
cc: Ilya Dryomov <idryomov@xxxxxxxxx>
cc: Ceph Development <ceph-devel@xxxxxxxxxxxxxxx>
---
 fs/ceph/debugfs.c    | 11 +++++++++--
 fs/ceph/mds_client.c | 14 +++++++++-----
 fs/ceph/mdsmap.h     |  6 +++++-
 3 files changed, 23 insertions(+), 8 deletions(-)

diff --git a/fs/ceph/debugfs.c b/fs/ceph/debugfs.c
index fdd404fc8112..f1c49232eee0 100644
--- a/fs/ceph/debugfs.c
+++ b/fs/ceph/debugfs.c
@@ -37,8 +37,15 @@ static int mdsmap_show(struct seq_file *s, void *p)
 	seq_printf(s, "session_timeout %d\n", mdsmap->m_session_timeout);
 	seq_printf(s, "session_autoclose %d\n", mdsmap->m_session_autoclose);
 	for (i = 0; i < mdsmap->possible_max_rank; i++) {
-		struct ceph_entity_addr *addr = &mdsmap->m_info[i].addr;
-		int state = mdsmap->m_info[i].state;
+		struct ceph_entity_addr *addr;
+		int state;
+
+		if (unlikely(!mdsmap->m_info))
+			break;
+
+		addr = &mdsmap->m_info[i].addr;
+		state = mdsmap->m_info[i].state;
+
 		seq_printf(s, "\tmds%d\t%s\t(%s)\n", i,
 			       ceph_pr_addr(addr),
 			       ceph_mds_state_name(state));
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
index 0f497c39ff82..501b78f9de56 100644
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -1737,6 +1737,9 @@ static void __open_export_target_sessions(struct ceph_mds_client *mdsc,
 	if (mds >= mdsc->mdsmap->possible_max_rank)
 		return;
 
+	if (unlikely(!mdsc->mdsmap->m_info))
+		return;
+
 	mi = &mdsc->mdsmap->m_info[mds];
 	doutc(cl, "for mds%d (%d targets)\n", session->s_mds,
 	      mi->num_export_targets);
@@ -5015,11 +5018,12 @@ static void check_new_map(struct ceph_mds_client *mdsc,
 
 	doutc(cl, "new %u old %u\n", newmap->m_epoch, oldmap->m_epoch);
 
-	if (newmap->m_info) {
-		for (i = 0; i < newmap->possible_max_rank; i++) {
-			for (j = 0; j < newmap->m_info[i].num_export_targets; j++)
-				set_bit(newmap->m_info[i].export_targets[j], targets);
-		}
+	/* ceph_mdsmap_decode() should guarantee m_info allocation */
+	BUG_ON(!newmap->m_info);
+
+	for (i = 0; i < newmap->possible_max_rank; i++) {
+		for (j = 0; j < newmap->m_info[i].num_export_targets; j++)
+			set_bit(newmap->m_info[i].export_targets[j], targets);
 	}
 
 	for (i = 0; i < oldmap->possible_max_rank && i < mdsc->max_sessions; i++) {
diff --git a/fs/ceph/mdsmap.h b/fs/ceph/mdsmap.h
index 1f2171dd01bf..12530f25a63b 100644
--- a/fs/ceph/mdsmap.h
+++ b/fs/ceph/mdsmap.h
@@ -52,6 +52,8 @@ ceph_mdsmap_get_addr(struct ceph_mdsmap *m, int w)
 {
 	if (w >= m->possible_max_rank)
 		return NULL;
+	if (unlikely(!m->m_info))
+		return NULL;
 	return &m->m_info[w].addr;
 }
 
@@ -60,12 +62,14 @@ static inline int ceph_mdsmap_get_state(struct ceph_mdsmap *m, int w)
 	BUG_ON(w < 0);
 	if (w >= m->possible_max_rank)
 		return CEPH_MDS_STATE_DNE;
+	if (unlikely(!m->m_info))
+		return CEPH_MDS_STATE_DNE;
 	return m->m_info[w].state;
 }
 
 static inline bool ceph_mdsmap_is_laggy(struct ceph_mdsmap *m, int w)
 {
-	if (w >= 0 && w < m->possible_max_rank)
+	if (w >= 0 && w < m->possible_max_rank && m->m_info)
 		return m->m_info[w].laggy;
 	return false;
 }
-- 
2.51.0





[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [NTFS 3]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [NTFS 3]     [Samba]     [Device Mapper]     [CEPH Development]

  Powered by Linux