Reported the cleared bytes in case of a partial clear_user instead
of -EFAULT, and remove a pointless conditional, as cleared must be
non-zero by the time we hit the signal_pending check.

Reported-by: Rasmus Villemoes <[email protected]>
Signed-off-by: Christoph Hellwig <[email protected]>
---
 drivers/char/mem.c | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 1dc99ab158457a..94c2b556cf9728 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -733,14 +733,20 @@ static ssize_t read_zero(struct file *file, char __user 
*buf,
 
        while (count) {
                size_t chunk = min_t(size_t, count, PAGE_SIZE);
+               size_t left;
 
-               if (clear_user(buf + cleared, chunk))
-                       return cleared ? cleared : -EFAULT;
+               left = clear_user(buf + cleared, chunk);
+               if (unlikely(left)) {
+                       cleared += (chunk - left);
+                       if (!cleared)
+                               return -EFAULT;
+                       break;
+               }
                cleared += chunk;
                count -= chunk;
 
                if (signal_pending(current))
-                       return cleared ? cleared : -ERESTARTSYS;
+                       break;
                cond_resched();
        }
 
-- 
2.28.0

Reply via email to