Skip to content

Commit c66120c

Browse files
dubeykoidryomov
authored andcommitted
ceph: cleanup in ceph_alloc_readdir_reply_buffer()
The Coverity Scan service has reported potential issue in ceph_alloc_readdir_reply_buffer() [1]. If order could be negative one, then it expects the issue in the logic: num_entries = (PAGE_SIZE << order) / size; Technically speaking, this logic [2] should prevent from making the order variable negative: if (!rinfo->dir_entries) return -ENOMEM; However, the allocation logic requires some cleanup. This patch makes sure that calculated bytes count will never exceed ULONG_MAX before get_order() calculation. And it adds the checking of order variable on negative value to guarantee that second half of the function's code will never operate by negative value of order variable even if something will be wrong or to be changed in the first half of the function's logic. v2 Alex Markuze suggested to add unlikely() macro for introduced condition checks. [1] https://scan5.scan.coverity.com/#/project-view/64304/10063?selectedIssue=1198252 [2] https://elixir.bootlin.com/linux/v6.17-rc3/source/fs/ceph/mds_client.c#L2553 Signed-off-by: Viacheslav Dubeyko <[email protected]> Reviewed-by: Alex Markuze <[email protected]> Signed-off-by: Ilya Dryomov <[email protected]>
1 parent 98a2850 commit c66120c

File tree

1 file changed

+7
-2
lines changed

1 file changed

+7
-2
lines changed

fs/ceph/mds_client.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2533,6 +2533,7 @@ int ceph_alloc_readdir_reply_buffer(struct ceph_mds_request *req,
25332533
struct ceph_mount_options *opt = req->r_mdsc->fsc->mount_options;
25342534
size_t size = sizeof(struct ceph_mds_reply_dir_entry);
25352535
unsigned int num_entries;
2536+
u64 bytes_count;
25362537
int order;
25372538

25382539
spin_lock(&ci->i_ceph_lock);
@@ -2541,7 +2542,11 @@ int ceph_alloc_readdir_reply_buffer(struct ceph_mds_request *req,
25412542
num_entries = max(num_entries, 1U);
25422543
num_entries = min(num_entries, opt->max_readdir);
25432544

2544-
order = get_order(size * num_entries);
2545+
bytes_count = (u64)size * num_entries;
2546+
if (unlikely(bytes_count > ULONG_MAX))
2547+
bytes_count = ULONG_MAX;
2548+
2549+
order = get_order((unsigned long)bytes_count);
25452550
while (order >= 0) {
25462551
rinfo->dir_entries = (void*)__get_free_pages(GFP_KERNEL |
25472552
__GFP_NOWARN |
@@ -2551,7 +2556,7 @@ int ceph_alloc_readdir_reply_buffer(struct ceph_mds_request *req,
25512556
break;
25522557
order--;
25532558
}
2554-
if (!rinfo->dir_entries)
2559+
if (!rinfo->dir_entries || unlikely(order < 0))
25552560
return -ENOMEM;
25562561

25572562
num_entries = (PAGE_SIZE << order) / size;

0 commit comments

Comments
 (0)