From: Andrew Deason Date: Thu, 5 Jul 2018 22:16:48 +0000 (-0500) Subject: LINUX: Detect NULL page during write_begin X-Git-Tag: upstream/1.8.1^2~5 X-Git-Url: https://git.michaelhowe.org/gitweb/?a=commitdiff_plain;h=6fed86775ba9ac7edc9444986c75a60771927411;p=packages%2Fo%2Fopenafs.git LINUX: Detect NULL page during write_begin In afs_linux_write_begin, we call grab_cache_page_write_begin to get a page to use for writing data when servicing a write into AFS. Under low-memory conditions, this can return NULL if Linux cannot find a free page to use. Currently, we always try to reference the page returned, and so this causes a BUG. To avoid this, check if grab_cache_page_write_begin returns NULL, and just return -ENOMEM, like other callers of grab_cache_page_write_begin do. Linux's fault injection framework is useful for testing code paths like these. The following settings made it possible to somewhat-reliably exercise the relevant code path on a test RHEL7 system: # grep ^ /sys/kernel/debug/fail_page_alloc/* /sys/kernel/debug/fail_page_alloc/ignore-gfp-highmem:Y /sys/kernel/debug/fail_page_alloc/ignore-gfp-wait:N /sys/kernel/debug/fail_page_alloc/interval:1 /sys/kernel/debug/fail_page_alloc/min-order:0 /sys/kernel/debug/fail_page_alloc/probability:100 /sys/kernel/debug/fail_page_alloc/space:90 /sys/kernel/debug/fail_page_alloc/task-filter:Y /sys/kernel/debug/fail_page_alloc/times:-1 [...] Reviewed-on: https://gerrit.openafs.org/13242 Tested-by: BuildBot Reviewed-by: Benjamin Kaduk (cherry picked from commit 89e80c354c404dedc0e5197f99710db0e5e08767) Change-Id: I37b4d1ebb1b76e435bb1c56a76d7e475f47f33de Reviewed-on: https://gerrit.openafs.org/13243 Tested-by: BuildBot Reviewed-by: Michael Meffie Reviewed-by: Mark Vitale Reviewed-by: Andrew Deason Reviewed-by: Benjamin Kaduk --- diff --git a/src/afs/LINUX/osi_vnodeops.c b/src/afs/LINUX/osi_vnodeops.c index 9a070f28f..966e98a9d 100644 --- a/src/afs/LINUX/osi_vnodeops.c +++ b/src/afs/LINUX/osi_vnodeops.c @@ -3082,6 +3082,10 @@ afs_linux_write_begin(struct file *file, struct address_space *mapping, int code; page = grab_cache_page_write_begin(mapping, index, flags); + if (!page) { + return -ENOMEM; + } + *pagep = page; code = afs_linux_prepare_write(file, page, from, from + len);