Skip to content

Commit 4ce718f

Browse files
Stefan Roeschakpm00
authored andcommitted
mm: fix div by zero in bdi_ratio_from_pages
During testing it has been detected, that it is possible to get div by zero error in bdi_set_min_bytes. The error is caused by the function bdi_ratio_from_pages(). bdi_ratio_from_pages() calls global_dirty_limits. If the dirty threshold is 0, the div by zero is raised. This can happen if the root user is setting: echo 0 > /proc/sys/vm/dirty_ratio The following is a test case: echo 0 > /proc/sys/vm/dirty_ratio cd /sys/class/bdi/<device> echo 1 > strict_limit echo 8192 > min_bytes ==> error is raised. The problem is addressed by returning -EINVAL if dirty_ratio or dirty_bytes is set to 0. [[email protected]: check for -EINVAL in bdi_set_min_bytes() and bdi_set_max_bytes()] Link: https://lkml.kernel.org/r/[email protected] [[email protected]: v3] Link: https://lkml.kernel.org/r/[email protected] Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Stefan Roesch <[email protected]> Reported-by: cheung wall <[email protected]> Closes: https://lore.kernel.org/linux-mm/[email protected]/T/#t Acked-by: David Hildenbrand <[email protected]> Cc: Matthew Wilcox (Oracle) <[email protected]> Cc: Qiang Zhang <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent 59f5910 commit 4ce718f

File tree

1 file changed

+8
-2
lines changed

1 file changed

+8
-2
lines changed

mm/page-writeback.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -692,6 +692,8 @@ static unsigned long bdi_ratio_from_pages(unsigned long pages)
692692
unsigned long ratio;
693693

694694
global_dirty_limits(&background_thresh, &dirty_thresh);
695+
if (!dirty_thresh)
696+
return -EINVAL;
695697
ratio = div64_u64(pages * 100ULL * BDI_RATIO_SCALE, dirty_thresh);
696698

697699
return ratio;
@@ -790,13 +792,15 @@ int bdi_set_min_bytes(struct backing_dev_info *bdi, u64 min_bytes)
790792
{
791793
int ret;
792794
unsigned long pages = min_bytes >> PAGE_SHIFT;
793-
unsigned long min_ratio;
795+
long min_ratio;
794796

795797
ret = bdi_check_pages_limit(pages);
796798
if (ret)
797799
return ret;
798800

799801
min_ratio = bdi_ratio_from_pages(pages);
802+
if (min_ratio < 0)
803+
return min_ratio;
800804
return __bdi_set_min_ratio(bdi, min_ratio);
801805
}
802806

@@ -809,13 +813,15 @@ int bdi_set_max_bytes(struct backing_dev_info *bdi, u64 max_bytes)
809813
{
810814
int ret;
811815
unsigned long pages = max_bytes >> PAGE_SHIFT;
812-
unsigned long max_ratio;
816+
long max_ratio;
813817

814818
ret = bdi_check_pages_limit(pages);
815819
if (ret)
816820
return ret;
817821

818822
max_ratio = bdi_ratio_from_pages(pages);
823+
if (max_ratio < 0)
824+
return max_ratio;
819825
return __bdi_set_max_ratio(bdi, max_ratio);
820826
}
821827

0 commit comments

Comments
 (0)