From nobody Fri Dec 19 17:16:08 2025 Received: from mail-io1-f44.google.com (mail-io1-f44.google.com [209.85.166.44]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C57DF1D3715 for ; Thu, 11 Apr 2024 15:39:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.166.44 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712849988; cv=none; b=rWx/83FeMnHgsAo25plm/q89nIa+d5NWyNXnA0swK57g1KjtFDAy/EMYruT++fnqH53zs2CT1TvgY1wFiydoSQBtYAkUTk/s7EO6GcKFr/8kD3MvSYSXAX9km6C84c0ZTRBPaSyor20aIfcfzmL88b04/p+X9v/j89n3bwzzjck= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712849988; c=relaxed/simple; bh=RXUlDOLuNF/HHMmDhiKlgGCW6A93WhnZ1njUSN+7FP4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=n98WQs4RmrMtDlxKWKTMLG/mGzuJRrppY8F9W2tMX+EUAdzQO+F+7NFABf4rGPXosAatrAiGedgZHhyztEMFxbiyXLHd7J9y2yoZBjRR8+IWS4nPPKk1dVkDw6DtB4MhrAmHBiOsV49yqg+XW1qvZusJVZrbkcFM8SairyixCmw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=kernel.dk; spf=pass smtp.mailfrom=kernel.dk; dkim=pass (2048-bit key) header.d=kernel-dk.20230601.gappssmtp.com header.i=@kernel-dk.20230601.gappssmtp.com header.b=kc/WGvPH; arc=none smtp.client-ip=209.85.166.44 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=kernel.dk Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=kernel.dk Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel-dk.20230601.gappssmtp.com header.i=@kernel-dk.20230601.gappssmtp.com header.b="kc/WGvPH" Received: by mail-io1-f44.google.com with SMTP id ca18e2360f4ac-7c8e4c0412dso69641939f.1 for ; Thu, 11 Apr 2024 08:39:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel-dk.20230601.gappssmtp.com; s=20230601; t=1712849984; x=1713454784; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=0DfTI2DpINtENEVOMzZkNWy1YEK4tmII71QpZm5OrVg=; b=kc/WGvPH628XPxr1aUtSLtuVryhXSBlsctCxvsOtp2iT4F7xFiqfJKijvrs54CyTP4 maZfCxXeOEcvas6B2IW4gUcvZvV6zesaEYEFDdRV8JOp2Ex1j3tftF0OhYNMzXOH2YuV Q06uiteWWOKnjHZZ+VpCcUCF2XtJ3ZSYkTfIHa08PYwd/cyWUghOlEMsVAoFQbtOiXHY 4ZUPjmjCBfsjkgjvKDUl5NbmZn5xbTs66z5szQmVKB+r+Havj1ypOy3MDzwPy5LIzpe1 yIilQ54Wo8WcNLzVDk9IgVJksI1gQYWI1trpPqhaCvBvkafoXYrNy0yaCWyrXZWvkgpY sndg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1712849984; x=1713454784; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=0DfTI2DpINtENEVOMzZkNWy1YEK4tmII71QpZm5OrVg=; b=esLRwPAPje6XpB9HouAy42PCQxbLCy8exj0KaaARxrQYR5wVXEXDyE5EIX2s08GAiE PTjIilu+1R9KpYei2obn0Dk9CpnnowgZO8lr4GGWSx5Dxq+JuTw2kfY2GtqWRwCzIgcF bny45GMFTfCO4qXDoiLyAjJsRpUbiaZP28m/G1J8jg5HUSbMGNjpApMl0RKGxJ7MD+vy DdsLIjPtVO8h6FHs7124wqL/9q98FZ6iWkwVquKxDw/lK7zjXw0xzT2zEaen2dP4oQCr Fi6r+UE2Z79x5LztJ57AMHUaHl3SK4xKoy9puibI8cYl3kztgAQZ6SBJKzTH1iqT7t0y L6+g== X-Gm-Message-State: AOJu0Yxy419E2xJGnNyRDubKiZKhbGJGOVTZim+Vfbbd+v+rDFMXyunv TtsZpgS6uOb5OIbKNjsYZSQXBwvmqKlRhxPK0+ihx8YB8MqiyfPUpcJBpmK+piN/xndRM7QRA5m F X-Google-Smtp-Source: AGHT+IEYDUj3JvPKraxejtWRtkJHMkOS7p5ypbE+pOyLK5tsOI8e0rgiKevEx6Pk7wqxWupTA16XVA== X-Received: by 2002:a6b:7b05:0:b0:7d6:60dc:bc8e with SMTP id l5-20020a6b7b05000000b007d660dcbc8emr202278iop.1.1712849984049; Thu, 11 Apr 2024 08:39:44 -0700 (PDT) Received: from localhost.localdomain ([96.43.243.2]) by smtp.gmail.com with ESMTPSA id jc25-20020a056638891900b0047f14b7f6c0sm457056jab.5.2024.04.11.08.39.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 11 Apr 2024 08:39:43 -0700 (PDT) From: Jens Axboe To: linux-kernel@vger.kernel.org Cc: Jens Axboe Subject: [PATCH 292/437] fs/proc: convert to read/write iterators Date: Thu, 11 Apr 2024 09:17:12 -0600 Message-ID: <20240411153126.16201-293-axboe@kernel.dk> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240411153126.16201-1-axboe@kernel.dk> References: <20240411153126.16201-1-axboe@kernel.dk> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Signed-off-by: Jens Axboe --- fs/proc/base.c | 316 ++++++++++++++++----------------- fs/proc/fd.c | 2 +- fs/proc/inode.c | 18 +- fs/proc/task_mmu.c | 37 ++-- fs/proc/task_nommu.c | 2 +- include/linux/user_namespace.h | 10 +- kernel/user_namespace.c | 39 ++-- 7 files changed, 214 insertions(+), 210 deletions(-) diff --git a/fs/proc/base.c b/fs/proc/base.c index 4c6a7aafe66a..d810ede0e399 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -373,9 +373,10 @@ static ssize_t proc_pid_cmdline_read(struct file *file= , char __user *buf, *pos +=3D ret; return ret; } +FOPS_READ_ITER_HELPER(proc_pid_cmdline_read); =20 static const struct file_operations proc_pid_cmdline_ops =3D { - .read =3D proc_pid_cmdline_read, + .read_iter =3D proc_pid_cmdline_read_iter, .llseek =3D generic_file_llseek, }; =20 @@ -525,23 +526,22 @@ static int lstats_open(struct inode *inode, struct fi= le *file) return single_open(file, lstats_show_proc, inode); } =20 -static ssize_t lstats_write(struct file *file, const char __user *buf, - size_t count, loff_t *offs) +static ssize_t lstats_write(struct kiocb *iocb, struct iov_iter *from) { - struct task_struct *task =3D get_proc_task(file_inode(file)); + struct task_struct *task =3D get_proc_task(file_inode(iocb->ki_filp)); =20 if (!task) return -ESRCH; clear_tsk_latency_tracing(task); put_task_struct(task); =20 - return count; + return iov_iter_count(from); } =20 static const struct file_operations proc_lstats_operations =3D { .open =3D lstats_open, - .read =3D seq_read, - .write =3D lstats_write, + .read_iter =3D seq_read_iter, + .write_iter =3D lstats_write, .llseek =3D seq_lseek, .release =3D single_release, }; @@ -788,7 +788,7 @@ static int proc_single_open(struct inode *inode, struct= file *filp) =20 static const struct file_operations proc_single_file_operations =3D { .open =3D proc_single_open, - .read =3D seq_read, + .read_iter =3D seq_read_iter, .llseek =3D seq_lseek, .release =3D single_release, }; @@ -835,11 +835,11 @@ static int mem_open(struct inode *inode, struct file = *file) return ret; } =20 -static ssize_t mem_rw(struct file *file, char __user *buf, - size_t count, loff_t *ppos, int write) +static ssize_t mem_rw(struct kiocb *iocb, struct iov_iter *iov, int write) { - struct mm_struct *mm =3D file->private_data; - unsigned long addr =3D *ppos; + struct mm_struct *mm =3D iocb->ki_filp->private_data; + size_t count =3D iov_iter_count(iov); + unsigned long addr =3D iocb->ki_pos; ssize_t copied; char *page; unsigned int flags; @@ -860,7 +860,7 @@ static ssize_t mem_rw(struct file *file, char __user *b= uf, while (count > 0) { size_t this_len =3D min_t(size_t, count, PAGE_SIZE); =20 - if (write && copy_from_user(page, buf, this_len)) { + if (write && !copy_from_iter_full(page, this_len, iov)) { copied =3D -EFAULT; break; } @@ -872,17 +872,16 @@ static ssize_t mem_rw(struct file *file, char __user = *buf, break; } =20 - if (!write && copy_to_user(buf, page, this_len)) { + if (!write && !copy_to_iter_full(page, this_len, iov)) { copied =3D -EFAULT; break; } =20 - buf +=3D this_len; addr +=3D this_len; copied +=3D this_len; count -=3D this_len; } - *ppos =3D addr; + iocb->ki_pos =3D addr; =20 mmput(mm); free: @@ -890,16 +889,14 @@ static ssize_t mem_rw(struct file *file, char __user = *buf, return copied; } =20 -static ssize_t mem_read(struct file *file, char __user *buf, - size_t count, loff_t *ppos) +static ssize_t mem_read(struct kiocb *iocb, struct iov_iter *to) { - return mem_rw(file, buf, count, ppos, 0); + return mem_rw(iocb, to, 0); } =20 -static ssize_t mem_write(struct file *file, const char __user *buf, - size_t count, loff_t *ppos) +static ssize_t mem_write(struct kiocb *iocb, struct iov_iter *from) { - return mem_rw(file, (char __user*)buf, count, ppos, 1); + return mem_rw(iocb, from, 1); } =20 loff_t mem_lseek(struct file *file, loff_t offset, int orig) @@ -928,8 +925,8 @@ static int mem_release(struct inode *inode, struct file= *file) =20 static const struct file_operations proc_mem_operations =3D { .llseek =3D mem_lseek, - .read =3D mem_read, - .write =3D mem_write, + .read_iter =3D mem_read, + .write_iter =3D mem_write, .open =3D mem_open, .release =3D mem_release, }; @@ -939,13 +936,13 @@ static int environ_open(struct inode *inode, struct f= ile *file) return __mem_open(inode, file, PTRACE_MODE_READ); } =20 -static ssize_t environ_read(struct file *file, char __user *buf, - size_t count, loff_t *ppos) +static ssize_t environ_read(struct kiocb *iocb, struct iov_iter *to) { + size_t count =3D iov_iter_count(to); char *page; - unsigned long src =3D *ppos; + unsigned long src =3D iocb->ki_pos; int ret =3D 0; - struct mm_struct *mm =3D file->private_data; + struct mm_struct *mm =3D iocb->ki_filp->private_data; unsigned long env_start, env_end; =20 /* Ensure the process spawned far enough to have an environment. */ @@ -984,17 +981,16 @@ static ssize_t environ_read(struct file *file, char _= _user *buf, break; } =20 - if (copy_to_user(buf, page, retval)) { + if (!copy_to_iter_full(page, retval, to)) { ret =3D -EFAULT; break; } =20 ret +=3D retval; src +=3D retval; - buf +=3D retval; count -=3D retval; } - *ppos =3D src; + iocb->ki_pos =3D src; mmput(mm); =20 free: @@ -1004,7 +1000,7 @@ static ssize_t environ_read(struct file *file, char _= _user *buf, =20 static const struct file_operations proc_environ_operations =3D { .open =3D environ_open, - .read =3D environ_read, + .read_iter =3D environ_read, .llseek =3D generic_file_llseek, .release =3D mem_release, }; @@ -1014,10 +1010,9 @@ static int auxv_open(struct inode *inode, struct fil= e *file) return __mem_open(inode, file, PTRACE_MODE_READ_FSCREDS); } =20 -static ssize_t auxv_read(struct file *file, char __user *buf, - size_t count, loff_t *ppos) +static ssize_t auxv_read(struct kiocb *iocb, struct iov_iter *to) { - struct mm_struct *mm =3D file->private_data; + struct mm_struct *mm =3D iocb->ki_filp->private_data; unsigned int nwords =3D 0; =20 if (!mm) @@ -1025,21 +1020,20 @@ static ssize_t auxv_read(struct file *file, char __= user *buf, do { nwords +=3D 2; } while (mm->saved_auxv[nwords - 2] !=3D 0); /* AT_NULL */ - return simple_read_from_buffer(buf, count, ppos, mm->saved_auxv, - nwords * sizeof(mm->saved_auxv[0])); + return simple_copy_to_iter(mm->saved_auxv, &iocb->ki_pos, + nwords * sizeof(mm->saved_auxv[0]), to); } =20 static const struct file_operations proc_auxv_operations =3D { .open =3D auxv_open, - .read =3D auxv_read, + .read_iter =3D auxv_read, .llseek =3D generic_file_llseek, .release =3D mem_release, }; =20 -static ssize_t oom_adj_read(struct file *file, char __user *buf, size_t co= unt, - loff_t *ppos) +static ssize_t oom_adj_read(struct kiocb *iocb, struct iov_iter *to) { - struct task_struct *task =3D get_proc_task(file_inode(file)); + struct task_struct *task =3D get_proc_task(file_inode(iocb->ki_filp)); char buffer[PROC_NUMBUF]; int oom_adj =3D OOM_ADJUST_MIN; size_t len; @@ -1055,7 +1049,7 @@ static ssize_t oom_adj_read(struct file *file, char _= _user *buf, size_t count, if (oom_adj > OOM_ADJUST_MAX) oom_adj =3D OOM_ADJUST_MAX; len =3D snprintf(buffer, sizeof(buffer), "%d\n", oom_adj); - return simple_read_from_buffer(buf, count, ppos, buffer, len); + return simple_copy_to_iter(buffer, &iocb->ki_pos, len, to); } =20 static int __set_oom_adj(struct file *file, int oom_adj, bool legacy) @@ -1151,16 +1145,16 @@ static int __set_oom_adj(struct file *file, int oom= _adj, bool legacy) * * oom_adj cannot be removed since existing userspace binaries use it. */ -static ssize_t oom_adj_write(struct file *file, const char __user *buf, - size_t count, loff_t *ppos) +static ssize_t oom_adj_write(struct kiocb *iocb, struct iov_iter *from) { + size_t count =3D iov_iter_count(from); char buffer[PROC_NUMBUF] =3D {}; int oom_adj; int err; =20 if (count > sizeof(buffer) - 1) count =3D sizeof(buffer) - 1; - if (copy_from_user(buffer, buf, count)) { + if (!copy_from_iter_full(buffer, count, from)) { err =3D -EFAULT; goto out; } @@ -1183,21 +1177,20 @@ static ssize_t oom_adj_write(struct file *file, con= st char __user *buf, else oom_adj =3D (oom_adj * OOM_SCORE_ADJ_MAX) / -OOM_DISABLE; =20 - err =3D __set_oom_adj(file, oom_adj, true); + err =3D __set_oom_adj(iocb->ki_filp, oom_adj, true); out: return err < 0 ? err : count; } =20 static const struct file_operations proc_oom_adj_operations =3D { - .read =3D oom_adj_read, - .write =3D oom_adj_write, + .read_iter =3D oom_adj_read, + .write_iter =3D oom_adj_write, .llseek =3D generic_file_llseek, }; =20 -static ssize_t oom_score_adj_read(struct file *file, char __user *buf, - size_t count, loff_t *ppos) +static ssize_t oom_score_adj_read(struct kiocb *iocb, struct iov_iter *to) { - struct task_struct *task =3D get_proc_task(file_inode(file)); + struct task_struct *task =3D get_proc_task(file_inode(iocb->ki_filp)); char buffer[PROC_NUMBUF]; short oom_score_adj =3D OOM_SCORE_ADJ_MIN; size_t len; @@ -1207,19 +1200,19 @@ static ssize_t oom_score_adj_read(struct file *file= , char __user *buf, oom_score_adj =3D task->signal->oom_score_adj; put_task_struct(task); len =3D snprintf(buffer, sizeof(buffer), "%hd\n", oom_score_adj); - return simple_read_from_buffer(buf, count, ppos, buffer, len); + return simple_copy_to_iter(buffer, &iocb->ki_pos, len, to); } =20 -static ssize_t oom_score_adj_write(struct file *file, const char __user *b= uf, - size_t count, loff_t *ppos) +static ssize_t oom_score_adj_write(struct kiocb *iocb, struct iov_iter *fr= om) { + size_t count =3D iov_iter_count(from); char buffer[PROC_NUMBUF] =3D {}; int oom_score_adj; int err; =20 if (count > sizeof(buffer) - 1) count =3D sizeof(buffer) - 1; - if (copy_from_user(buffer, buf, count)) { + if (!copy_from_iter_full(buffer, count, from)) { err =3D -EFAULT; goto out; } @@ -1233,23 +1226,22 @@ static ssize_t oom_score_adj_write(struct file *fil= e, const char __user *buf, goto out; } =20 - err =3D __set_oom_adj(file, oom_score_adj, false); + err =3D __set_oom_adj(iocb->ki_filp, oom_score_adj, false); out: return err < 0 ? err : count; } =20 static const struct file_operations proc_oom_score_adj_operations =3D { - .read =3D oom_score_adj_read, - .write =3D oom_score_adj_write, + .read_iter =3D oom_score_adj_read, + .write_iter =3D oom_score_adj_write, .llseek =3D default_llseek, }; =20 #ifdef CONFIG_AUDIT #define TMPBUFLEN 11 -static ssize_t proc_loginuid_read(struct file * file, char __user * buf, - size_t count, loff_t *ppos) +static ssize_t proc_loginuid_read(struct kiocb *iocb, struct iov_iter *to) { - struct inode * inode =3D file_inode(file); + struct inode * inode =3D file_inode(iocb->ki_filp); struct task_struct *task =3D get_proc_task(inode); ssize_t length; char tmpbuf[TMPBUFLEN]; @@ -1257,16 +1249,16 @@ static ssize_t proc_loginuid_read(struct file * fil= e, char __user * buf, if (!task) return -ESRCH; length =3D scnprintf(tmpbuf, TMPBUFLEN, "%u", - from_kuid(file->f_cred->user_ns, + from_kuid(iocb->ki_filp->f_cred->user_ns, audit_get_loginuid(task))); put_task_struct(task); - return simple_read_from_buffer(buf, count, ppos, tmpbuf, length); + return simple_copy_to_iter(tmpbuf, &iocb->ki_pos, length, to); } =20 -static ssize_t proc_loginuid_write(struct file * file, const char __user *= buf, - size_t count, loff_t *ppos) +static ssize_t proc_loginuid_write(struct kiocb *iocb, struct iov_iter *fr= om) { - struct inode * inode =3D file_inode(file); + struct inode * inode =3D file_inode(iocb->ki_filp); + size_t count =3D iov_iter_count(from); uid_t loginuid; kuid_t kloginuid; int rv; @@ -1282,12 +1274,12 @@ static ssize_t proc_loginuid_write(struct file * fi= le, const char __user * buf, } rcu_read_unlock(); =20 - if (*ppos !=3D 0) { + if (iocb->ki_pos !=3D 0) { /* No partial writes. */ return -EINVAL; } =20 - rv =3D kstrtou32_from_user(buf, count, 10, &loginuid); + rv =3D kstrtou32_from_iter(from, count, 10, &loginuid); if (rv < 0) return rv; =20 @@ -1295,7 +1287,7 @@ static ssize_t proc_loginuid_write(struct file * file= , const char __user * buf, if (loginuid =3D=3D AUDIT_UID_UNSET) { kloginuid =3D INVALID_UID; } else { - kloginuid =3D make_kuid(file->f_cred->user_ns, loginuid); + kloginuid =3D make_kuid(iocb->ki_filp->f_cred->user_ns, loginuid); if (!uid_valid(kloginuid)) return -EINVAL; } @@ -1307,15 +1299,14 @@ static ssize_t proc_loginuid_write(struct file * fi= le, const char __user * buf, } =20 static const struct file_operations proc_loginuid_operations =3D { - .read =3D proc_loginuid_read, - .write =3D proc_loginuid_write, + .read_iter =3D proc_loginuid_read, + .write_iter =3D proc_loginuid_write, .llseek =3D generic_file_llseek, }; =20 -static ssize_t proc_sessionid_read(struct file * file, char __user * buf, - size_t count, loff_t *ppos) +static ssize_t proc_sessionid_read(struct kiocb *iocb, struct iov_iter *to) { - struct inode * inode =3D file_inode(file); + struct inode * inode =3D file_inode(iocb->ki_filp); struct task_struct *task =3D get_proc_task(inode); ssize_t length; char tmpbuf[TMPBUFLEN]; @@ -1325,20 +1316,19 @@ static ssize_t proc_sessionid_read(struct file * fi= le, char __user * buf, length =3D scnprintf(tmpbuf, TMPBUFLEN, "%u", audit_get_sessionid(task)); put_task_struct(task); - return simple_read_from_buffer(buf, count, ppos, tmpbuf, length); + return simple_copy_to_iter(tmpbuf, &iocb->ki_pos, length, to); } =20 static const struct file_operations proc_sessionid_operations =3D { - .read =3D proc_sessionid_read, + .read_iter =3D proc_sessionid_read, .llseek =3D generic_file_llseek, }; #endif =20 #ifdef CONFIG_FAULT_INJECTION -static ssize_t proc_fault_inject_read(struct file * file, char __user * bu= f, - size_t count, loff_t *ppos) +static ssize_t proc_fault_inject_read(struct kiocb *iocb, struct iov_iter = *to) { - struct task_struct *task =3D get_proc_task(file_inode(file)); + struct task_struct *task =3D get_proc_task(file_inode(iocb->ki_filp)); char buffer[PROC_NUMBUF]; size_t len; int make_it_fail; @@ -1349,13 +1339,12 @@ static ssize_t proc_fault_inject_read(struct file *= file, char __user * buf, put_task_struct(task); =20 len =3D snprintf(buffer, sizeof(buffer), "%i\n", make_it_fail); - - return simple_read_from_buffer(buf, count, ppos, buffer, len); + return simple_copy_to_iter(buffer, &iocb->ki_pos, len, to); } =20 -static ssize_t proc_fault_inject_write(struct file * file, - const char __user * buf, size_t count, loff_t *ppos) +static ssize_t proc_fault_inject_write(struct kiocb *iocb, struct iov_iter= *from) { + size_t count =3D iov_iter_count(from); struct task_struct *task; char buffer[PROC_NUMBUF] =3D {}; int make_it_fail; @@ -1366,7 +1355,7 @@ static ssize_t proc_fault_inject_write(struct file * = file, =20 if (count > sizeof(buffer) - 1) count =3D sizeof(buffer) - 1; - if (copy_from_user(buffer, buf, count)) + if (!copy_from_iter_full(buffer, count, from)) return -EFAULT; rv =3D kstrtoint(strstrip(buffer), 0, &make_it_fail); if (rv < 0) @@ -1374,7 +1363,7 @@ static ssize_t proc_fault_inject_write(struct file * = file, if (make_it_fail < 0 || make_it_fail > 1) return -EINVAL; =20 - task =3D get_proc_task(file_inode(file)); + task =3D get_proc_task(file_inode(iocb->ki_filp)); if (!task) return -ESRCH; task->make_it_fail =3D make_it_fail; @@ -1384,23 +1373,23 @@ static ssize_t proc_fault_inject_write(struct file = * file, } =20 static const struct file_operations proc_fault_inject_operations =3D { - .read =3D proc_fault_inject_read, - .write =3D proc_fault_inject_write, + .read_iter =3D proc_fault_inject_read, + .write_iter =3D proc_fault_inject_write, .llseek =3D generic_file_llseek, }; =20 -static ssize_t proc_fail_nth_write(struct file *file, const char __user *b= uf, - size_t count, loff_t *ppos) +static ssize_t proc_fail_nth_write(struct kiocb *iocb, struct iov_iter *fr= om) { + size_t count =3D iov_iter_count(from); struct task_struct *task; int err; unsigned int n; =20 - err =3D kstrtouint_from_user(buf, count, 0, &n); + err =3D kstrtouint_from_iter(from, count, 0, &n); if (err) return err; =20 - task =3D get_proc_task(file_inode(file)); + task =3D get_proc_task(file_inode(iocb->ki_filp)); if (!task) return -ESRCH; task->fail_nth =3D n; @@ -1409,24 +1398,23 @@ static ssize_t proc_fail_nth_write(struct file *fil= e, const char __user *buf, return count; } =20 -static ssize_t proc_fail_nth_read(struct file *file, char __user *buf, - size_t count, loff_t *ppos) +static ssize_t proc_fail_nth_read(struct kiocb *iocb, struct iov_iter *to) { struct task_struct *task; char numbuf[PROC_NUMBUF]; ssize_t len; =20 - task =3D get_proc_task(file_inode(file)); + task =3D get_proc_task(file_inode(iocb->ki_filp)); if (!task) return -ESRCH; len =3D snprintf(numbuf, sizeof(numbuf), "%u\n", task->fail_nth); put_task_struct(task); - return simple_read_from_buffer(buf, count, ppos, numbuf, len); + return simple_copy_to_iter(numbuf, &iocb->ki_pos, len, to); } =20 static const struct file_operations proc_fail_nth_operations =3D { - .read =3D proc_fail_nth_read, - .write =3D proc_fail_nth_write, + .read_iter =3D proc_fail_nth_read, + .write_iter =3D proc_fail_nth_write, }; #endif =20 @@ -1451,11 +1439,9 @@ static int sched_show(struct seq_file *m, void *v) return 0; } =20 -static ssize_t -sched_write(struct file *file, const char __user *buf, - size_t count, loff_t *offset) +static ssize_t sched_write(struct kiocb *iocb, struct iov_iter *from) { - struct inode *inode =3D file_inode(file); + struct inode *inode =3D file_inode(iocb->ki_filp); struct task_struct *p; =20 p =3D get_proc_task(inode); @@ -1465,7 +1451,7 @@ sched_write(struct file *file, const char __user *buf, =20 put_task_struct(p); =20 - return count; + return iov_iter_count(from); } =20 static int sched_open(struct inode *inode, struct file *filp) @@ -1475,8 +1461,8 @@ static int sched_open(struct inode *inode, struct fil= e *filp) =20 static const struct file_operations proc_pid_sched_operations =3D { .open =3D sched_open, - .read =3D seq_read, - .write =3D sched_write, + .read_iter =3D seq_read_iter, + .write_iter =3D sched_write, .llseek =3D seq_lseek, .release =3D single_release, }; @@ -1502,11 +1488,10 @@ static int sched_autogroup_show(struct seq_file *m,= void *v) return 0; } =20 -static ssize_t -sched_autogroup_write(struct file *file, const char __user *buf, - size_t count, loff_t *offset) +static ssize_t sched_autogroup_write(struct kiocb *iocb, struct iov_iter *= from) { - struct inode *inode =3D file_inode(file); + struct inode *inode =3D file_inode(iocb->ki_filp); + size_t count =3D iov_iter_count(from); struct task_struct *p; char buffer[PROC_NUMBUF] =3D {}; int nice; @@ -1514,7 +1499,7 @@ sched_autogroup_write(struct file *file, const char _= _user *buf, =20 if (count > sizeof(buffer) - 1) count =3D sizeof(buffer) - 1; - if (copy_from_user(buffer, buf, count)) + if (!copy_from_iter_full(buffer, count, from)) return -EFAULT; =20 err =3D kstrtoint(strstrip(buffer), 0, &nice); @@ -1549,8 +1534,8 @@ static int sched_autogroup_open(struct inode *inode, = struct file *filp) =20 static const struct file_operations proc_pid_sched_autogroup_operations = =3D { .open =3D sched_autogroup_open, - .read =3D seq_read, - .write =3D sched_autogroup_write, + .read_iter =3D seq_read_iter, + .write_iter =3D sched_autogroup_write, .llseek =3D seq_lseek, .release =3D single_release, }; @@ -1572,21 +1557,21 @@ static int timens_offsets_show(struct seq_file *m, = void *v) return 0; } =20 -static ssize_t timens_offsets_write(struct file *file, const char __user *= buf, - size_t count, loff_t *ppos) +static ssize_t timens_offsets_write(struct kiocb *iocb, struct iov_iter *f= rom) { - struct inode *inode =3D file_inode(file); + struct inode *inode =3D file_inode(iocb->ki_filp); + size_t count =3D iov_iter_count(from); struct proc_timens_offset offsets[2]; char *kbuf =3D NULL, *pos, *next_line; struct task_struct *p; int ret, noffsets; =20 /* Only allow < page size writes at the beginning of the file */ - if ((*ppos !=3D 0) || (count >=3D PAGE_SIZE)) + if ((iocb->ki_pos !=3D 0) || (count >=3D PAGE_SIZE)) return -EINVAL; =20 /* Slurp in the user data */ - kbuf =3D memdup_user_nul(buf, count); + kbuf =3D iterdup_nul(from, count); if (IS_ERR(kbuf)) return PTR_ERR(kbuf); =20 @@ -1634,7 +1619,7 @@ static ssize_t timens_offsets_write(struct file *file= , const char __user *buf, p =3D get_proc_task(inode); if (!p) goto out; - ret =3D proc_timens_set_offset(file, p, offsets, noffsets); + ret =3D proc_timens_set_offset(iocb->ki_filp, p, offsets, noffsets); put_task_struct(p); if (ret) goto out; @@ -1652,22 +1637,22 @@ static int timens_offsets_open(struct inode *inode,= struct file *filp) =20 static const struct file_operations proc_timens_offsets_operations =3D { .open =3D timens_offsets_open, - .read =3D seq_read, - .write =3D timens_offsets_write, + .read_iter =3D seq_read_iter, + .write_iter =3D timens_offsets_write, .llseek =3D seq_lseek, .release =3D single_release, }; #endif /* CONFIG_TIME_NS */ =20 -static ssize_t comm_write(struct file *file, const char __user *buf, - size_t count, loff_t *offset) +static ssize_t comm_write(struct kiocb *iocb, struct iov_iter *from) { - struct inode *inode =3D file_inode(file); + struct inode *inode =3D file_inode(iocb->ki_filp); + size_t count =3D iov_iter_count(from); struct task_struct *p; char buffer[TASK_COMM_LEN] =3D {}; const size_t maxlen =3D sizeof(buffer) - 1; =20 - if (copy_from_user(buffer, buf, count > maxlen ? maxlen : count)) + if (!copy_from_iter_full(buffer, count > maxlen ? maxlen : count, from)) return -EFAULT; =20 p =3D get_proc_task(inode); @@ -1710,8 +1695,8 @@ static int comm_open(struct inode *inode, struct file= *filp) =20 static const struct file_operations proc_pid_set_comm_operations =3D { .open =3D comm_open, - .read =3D seq_read, - .write =3D comm_write, + .read_iter =3D seq_read_iter, + .write_iter =3D comm_write, .llseek =3D seq_lseek, .release =3D single_release, }; @@ -2530,21 +2515,21 @@ static int proc_timers_open(struct inode *inode, st= ruct file *file) =20 static const struct file_operations proc_timers_operations =3D { .open =3D proc_timers_open, - .read =3D seq_read, + .read_iter =3D seq_read_iter, .llseek =3D seq_lseek, .release =3D seq_release_private, }; #endif =20 -static ssize_t timerslack_ns_write(struct file *file, const char __user *b= uf, - size_t count, loff_t *offset) +static ssize_t timerslack_ns_write(struct kiocb *iocb, struct iov_iter *fr= om) { - struct inode *inode =3D file_inode(file); + struct inode *inode =3D file_inode(iocb->ki_filp); + size_t count =3D iov_iter_count(from); struct task_struct *p; u64 slack_ns; int err; =20 - err =3D kstrtoull_from_user(buf, count, 10, &slack_ns); + err =3D kstrtoull_from_iter(from, count, 10, &slack_ns); if (err < 0) return err; =20 @@ -2622,8 +2607,8 @@ static int timerslack_ns_open(struct inode *inode, st= ruct file *filp) =20 static const struct file_operations proc_pid_set_timerslack_ns_operations = =3D { .open =3D timerslack_ns_open, - .read =3D seq_read, - .write =3D timerslack_ns_write, + .read_iter =3D seq_read_iter, + .write_iter =3D timerslack_ns_write, .llseek =3D seq_lseek, .release =3D single_release, }; @@ -2714,10 +2699,9 @@ static int proc_pid_attr_open(struct inode *inode, s= truct file *file) return 0; } =20 -static ssize_t proc_pid_attr_read(struct file * file, char __user * buf, - size_t count, loff_t *ppos) +static ssize_t proc_pid_attr_read(struct kiocb *iocb, struct iov_iter *to) { - struct inode * inode =3D file_inode(file); + struct inode * inode =3D file_inode(iocb->ki_filp); char *p =3D NULL; ssize_t length; struct task_struct *task =3D get_proc_task(inode); @@ -2726,25 +2710,25 @@ static ssize_t proc_pid_attr_read(struct file * fil= e, char __user * buf, return -ESRCH; =20 length =3D security_getprocattr(task, PROC_I(inode)->op.lsmid, - file->f_path.dentry->d_name.name, + iocb->ki_filp->f_path.dentry->d_name.name, &p); put_task_struct(task); if (length > 0) - length =3D simple_read_from_buffer(buf, count, ppos, p, length); + length =3D simple_copy_to_iter(p, &iocb->ki_pos, length, to); kfree(p); return length; } =20 -static ssize_t proc_pid_attr_write(struct file * file, const char __user *= buf, - size_t count, loff_t *ppos) +static ssize_t proc_pid_attr_write(struct kiocb *iocb, struct iov_iter *fr= om) { - struct inode * inode =3D file_inode(file); + struct inode * inode =3D file_inode(iocb->ki_filp); + size_t count =3D iov_iter_count(from); struct task_struct *task; void *page; int rv; =20 /* A task may only write when it was the opener. */ - if (file->private_data !=3D current->mm) + if (iocb->ki_filp->private_data !=3D current->mm) return -EPERM; =20 rcu_read_lock(); @@ -2769,10 +2753,10 @@ static ssize_t proc_pid_attr_write(struct file * fi= le, const char __user * buf, count =3D PAGE_SIZE; =20 /* No partial writes. */ - if (*ppos !=3D 0) + if (iocb->ki_pos !=3D 0) return -EINVAL; =20 - page =3D memdup_user(buf, count); + page =3D iterdup(from, count); if (IS_ERR(page)) { rv =3D PTR_ERR(page); goto out; @@ -2784,8 +2768,8 @@ static ssize_t proc_pid_attr_write(struct file * file= , const char __user * buf, goto out_free; =20 rv =3D security_setprocattr(PROC_I(inode)->op.lsmid, - file->f_path.dentry->d_name.name, page, - count); + iocb->ki_filp->f_path.dentry->d_name.name, + page, count); mutex_unlock(¤t->signal->cred_guard_mutex); out_free: kfree(page); @@ -2795,8 +2779,8 @@ static ssize_t proc_pid_attr_write(struct file * file= , const char __user * buf, =20 static const struct file_operations proc_pid_attr_operations =3D { .open =3D proc_pid_attr_open, - .read =3D proc_pid_attr_read, - .write =3D proc_pid_attr_write, + .read_iter =3D proc_pid_attr_read, + .write_iter =3D proc_pid_attr_write, .llseek =3D generic_file_llseek, .release =3D mem_release, }; @@ -2892,10 +2876,9 @@ static const struct inode_operations proc_attr_dir_i= node_operations =3D { #endif =20 #ifdef CONFIG_ELF_CORE -static ssize_t proc_coredump_filter_read(struct file *file, char __user *b= uf, - size_t count, loff_t *ppos) +static ssize_t proc_coredump_filter_read(struct kiocb *iocb, struct iov_it= er *to) { - struct task_struct *task =3D get_proc_task(file_inode(file)); + struct task_struct *task =3D get_proc_task(file_inode(iocb->ki_filp)); struct mm_struct *mm; char buffer[PROC_NUMBUF]; size_t len; @@ -2911,7 +2894,7 @@ static ssize_t proc_coredump_filter_read(struct file = *file, char __user *buf, ((mm->flags & MMF_DUMP_FILTER_MASK) >> MMF_DUMP_FILTER_SHIFT)); mmput(mm); - ret =3D simple_read_from_buffer(buf, count, ppos, buffer, len); + ret =3D simple_copy_to_iter(buffer, &iocb->ki_pos, len, to); } =20 put_task_struct(task); @@ -2919,11 +2902,10 @@ static ssize_t proc_coredump_filter_read(struct fil= e *file, char __user *buf, return ret; } =20 -static ssize_t proc_coredump_filter_write(struct file *file, - const char __user *buf, - size_t count, - loff_t *ppos) +static ssize_t proc_coredump_filter_write(struct kiocb *iocb, + struct iov_iter *from) { + size_t count =3D iov_iter_count(from); struct task_struct *task; struct mm_struct *mm; unsigned int val; @@ -2931,12 +2913,12 @@ static ssize_t proc_coredump_filter_write(struct fi= le *file, int i; unsigned long mask; =20 - ret =3D kstrtouint_from_user(buf, count, 0, &val); + ret =3D kstrtouint_from_iter(from, count, 0, &val); if (ret < 0) return ret; =20 ret =3D -ESRCH; - task =3D get_proc_task(file_inode(file)); + task =3D get_proc_task(file_inode(iocb->ki_filp)); if (!task) goto out_no_task; =20 @@ -2962,8 +2944,8 @@ static ssize_t proc_coredump_filter_write(struct file= *file, } =20 static const struct file_operations proc_coredump_filter_operations =3D { - .read =3D proc_coredump_filter_read, - .write =3D proc_coredump_filter_write, + .read_iter =3D proc_coredump_filter_read, + .write_iter =3D proc_coredump_filter_write, .llseek =3D generic_file_llseek, }; #endif @@ -3098,24 +3080,24 @@ static int proc_projid_map_open(struct inode *inode= , struct file *file) =20 static const struct file_operations proc_uid_map_operations =3D { .open =3D proc_uid_map_open, - .write =3D proc_uid_map_write, - .read =3D seq_read, + .write_iter =3D proc_uid_map_write_iter, + .read_iter =3D seq_read_iter, .llseek =3D seq_lseek, .release =3D proc_id_map_release, }; =20 static const struct file_operations proc_gid_map_operations =3D { .open =3D proc_gid_map_open, - .write =3D proc_gid_map_write, - .read =3D seq_read, + .write_iter =3D proc_gid_map_write_iter, + .read_iter =3D seq_read_iter, .llseek =3D seq_lseek, .release =3D proc_id_map_release, }; =20 static const struct file_operations proc_projid_map_operations =3D { .open =3D proc_projid_map_open, - .write =3D proc_projid_map_write, - .read =3D seq_read, + .write_iter =3D proc_projid_map_write_iter, + .read_iter =3D seq_read_iter, .llseek =3D seq_lseek, .release =3D proc_id_map_release, }; @@ -3165,8 +3147,8 @@ static int proc_setgroups_release(struct inode *inode= , struct file *file) =20 static const struct file_operations proc_setgroups_operations =3D { .open =3D proc_setgroups_open, - .write =3D proc_setgroups_write, - .read =3D seq_read, + .write_iter =3D proc_setgroups_write, + .read_iter =3D seq_read_iter, .llseek =3D seq_lseek, .release =3D proc_setgroups_release, }; diff --git a/fs/proc/fd.c b/fs/proc/fd.c index 63a3aebdf223..ee3f608559e5 100644 --- a/fs/proc/fd.c +++ b/fs/proc/fd.c @@ -103,7 +103,7 @@ static int seq_fdinfo_open(struct inode *inode, struct = file *file) =20 static const struct file_operations proc_fdinfo_file_operations =3D { .open =3D seq_fdinfo_open, - .read =3D seq_read, + .read_iter =3D seq_read_iter, .llseek =3D seq_lseek, .release =3D single_release, }; diff --git a/fs/proc/inode.c b/fs/proc/inode.c index dcd513dccf55..092164889e74 100644 --- a/fs/proc/inode.c +++ b/fs/proc/inode.c @@ -325,6 +325,11 @@ static ssize_t proc_reg_read(struct file *file, char _= _user *buf, size_t count, return rv; } =20 +static ssize_t __proc_reg_read_iter(struct kiocb *iocb, struct iov_iter *t= o) +{ + return vfs_read_iter(iocb, to, proc_reg_read); +} + static ssize_t pde_write(struct proc_dir_entry *pde, struct file *file, co= nst char __user *buf, size_t count, loff_t *ppos) { typeof_member(struct proc_ops, proc_write) write; @@ -348,6 +353,7 @@ static ssize_t proc_reg_write(struct file *file, const = char __user *buf, size_t } return rv; } +FOPS_WRITE_ITER_HELPER(proc_reg_write); =20 static __poll_t pde_poll(struct proc_dir_entry *pde, struct file *file, st= ruct poll_table_struct *pts) { @@ -571,8 +577,8 @@ static int proc_reg_release(struct inode *inode, struct= file *file) =20 static const struct file_operations proc_reg_file_ops =3D { .llseek =3D proc_reg_llseek, - .read =3D proc_reg_read, - .write =3D proc_reg_write, + .read_iter =3D __proc_reg_read_iter, + .write_iter =3D proc_reg_write_iter, .poll =3D proc_reg_poll, .unlocked_ioctl =3D proc_reg_unlocked_ioctl, .mmap =3D proc_reg_mmap, @@ -584,7 +590,7 @@ static const struct file_operations proc_reg_file_ops = =3D { static const struct file_operations proc_iter_file_ops =3D { .llseek =3D proc_reg_llseek, .read_iter =3D proc_reg_read_iter, - .write =3D proc_reg_write, + .write_iter =3D proc_reg_write_iter, .splice_read =3D copy_splice_read, .poll =3D proc_reg_poll, .unlocked_ioctl =3D proc_reg_unlocked_ioctl, @@ -597,8 +603,8 @@ static const struct file_operations proc_iter_file_ops = =3D { #ifdef CONFIG_COMPAT static const struct file_operations proc_reg_file_ops_compat =3D { .llseek =3D proc_reg_llseek, - .read =3D proc_reg_read, - .write =3D proc_reg_write, + .read_iter =3D proc_reg_read_iter, + .write_iter =3D proc_reg_write_iter, .poll =3D proc_reg_poll, .unlocked_ioctl =3D proc_reg_unlocked_ioctl, .compat_ioctl =3D proc_reg_compat_ioctl, @@ -612,7 +618,7 @@ static const struct file_operations proc_iter_file_ops_= compat =3D { .llseek =3D proc_reg_llseek, .read_iter =3D proc_reg_read_iter, .splice_read =3D copy_splice_read, - .write =3D proc_reg_write, + .write_iter =3D proc_reg_write_iter, .poll =3D proc_reg_poll, .unlocked_ioctl =3D proc_reg_unlocked_ioctl, .compat_ioctl =3D proc_reg_compat_ioctl, diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 23fbab954c20..ff86fe94fcba 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -360,7 +360,7 @@ static int pid_maps_open(struct inode *inode, struct fi= le *file) =20 const struct file_operations proc_pid_maps_operations =3D { .open =3D pid_maps_open, - .read =3D seq_read, + .read_iter =3D seq_read_iter, .llseek =3D seq_lseek, .release =3D proc_map_release, }; @@ -1049,14 +1049,14 @@ static int smaps_rollup_release(struct inode *inode= , struct file *file) =20 const struct file_operations proc_pid_smaps_operations =3D { .open =3D pid_smaps_open, - .read =3D seq_read, + .read_iter =3D seq_read_iter, .llseek =3D seq_lseek, .release =3D proc_map_release, }; =20 const struct file_operations proc_pid_smaps_rollup_operations =3D { .open =3D smaps_rollup_open, - .read =3D seq_read, + .read_iter =3D seq_read_iter, .llseek =3D seq_lseek, .release =3D smaps_rollup_release, }; @@ -1242,9 +1242,9 @@ static const struct mm_walk_ops clear_refs_walk_ops = =3D { .walk_lock =3D PGWALK_WRLOCK, }; =20 -static ssize_t clear_refs_write(struct file *file, const char __user *buf, - size_t count, loff_t *ppos) +static ssize_t clear_refs_write(struct kiocb *iocb, struct iov_iter *from) { + size_t count =3D iov_iter_count(from); struct task_struct *task; char buffer[PROC_NUMBUF] =3D {}; struct mm_struct *mm; @@ -1255,7 +1255,7 @@ static ssize_t clear_refs_write(struct file *file, co= nst char __user *buf, =20 if (count > sizeof(buffer) - 1) count =3D sizeof(buffer) - 1; - if (copy_from_user(buffer, buf, count)) + if (!copy_from_iter_full(buffer, count, from)) return -EFAULT; rv =3D kstrtoint(strstrip(buffer), 10, &itype); if (rv < 0) @@ -1264,7 +1264,7 @@ static ssize_t clear_refs_write(struct file *file, co= nst char __user *buf, if (type < CLEAR_REFS_ALL || type >=3D CLEAR_REFS_LAST) return -EINVAL; =20 - task =3D get_proc_task(file_inode(file)); + task =3D get_proc_task(file_inode(iocb->ki_filp)); if (!task) return -ESRCH; mm =3D get_task_mm(task); @@ -1318,7 +1318,7 @@ static ssize_t clear_refs_write(struct file *file, co= nst char __user *buf, } =20 const struct file_operations proc_clear_refs_operations =3D { - .write =3D clear_refs_write, + .write_iter =3D clear_refs_write, .llseek =3D noop_llseek, }; =20 @@ -1645,10 +1645,10 @@ static const struct mm_walk_ops pagemap_ops =3D { * determine which areas of memory are actually mapped and llseek to * skip over unmapped regions. */ -static ssize_t pagemap_read(struct file *file, char __user *buf, - size_t count, loff_t *ppos) +static ssize_t pagemap_read(struct kiocb *iocb, struct iov_iter *to) { - struct mm_struct *mm =3D file->private_data; + struct mm_struct *mm =3D iocb->ki_filp->private_data; + size_t count =3D iov_iter_count(to); struct pagemapread pm; unsigned long src; unsigned long svpfn; @@ -1661,7 +1661,7 @@ static ssize_t pagemap_read(struct file *file, char _= _user *buf, =20 ret =3D -EINVAL; /* file position must be aligned */ - if ((*ppos % PM_ENTRY_BYTES) || (count % PM_ENTRY_BYTES)) + if ((iocb->ki_pos % PM_ENTRY_BYTES) || (count % PM_ENTRY_BYTES)) goto out_mm; =20 ret =3D 0; @@ -1669,7 +1669,7 @@ static ssize_t pagemap_read(struct file *file, char _= _user *buf, goto out_mm; =20 /* do not disclose physical addresses: attack vector */ - pm.show_pfn =3D file_ns_capable(file, &init_user_ns, CAP_SYS_ADMIN); + pm.show_pfn =3D file_ns_capable(iocb->ki_filp, &init_user_ns, CAP_SYS_ADM= IN); =20 pm.len =3D (PAGEMAP_WALK_SIZE >> PAGE_SHIFT); pm.buffer =3D kmalloc_array(pm.len, PM_ENTRY_BYTES, GFP_KERNEL); @@ -1677,7 +1677,7 @@ static ssize_t pagemap_read(struct file *file, char _= _user *buf, if (!pm.buffer) goto out_mm; =20 - src =3D *ppos; + src =3D iocb->ki_pos; svpfn =3D src / PM_ENTRY_BYTES; end_vaddr =3D mm->task_size; =20 @@ -1719,15 +1719,14 @@ static ssize_t pagemap_read(struct file *file, char= __user *buf, start_vaddr =3D end; =20 len =3D min(count, PM_ENTRY_BYTES * pm.pos); - if (copy_to_user(buf, pm.buffer, len)) { + if (!copy_to_iter_full(pm.buffer, len, to)) { ret =3D -EFAULT; goto out_free; } copied +=3D len; - buf +=3D len; count -=3D len; } - *ppos +=3D copied; + iocb->ki_pos +=3D copied; if (!ret || ret =3D=3D PM_END_OF_BUFFER) ret =3D copied; =20 @@ -2518,7 +2517,7 @@ static long do_pagemap_cmd(struct file *file, unsigne= d int cmd, =20 const struct file_operations proc_pagemap_operations =3D { .llseek =3D mem_lseek, /* borrow this */ - .read =3D pagemap_read, + .read_iter =3D pagemap_read, .open =3D pagemap_open, .release =3D pagemap_release, .unlocked_ioctl =3D do_pagemap_cmd, @@ -2787,7 +2786,7 @@ static int pid_numa_maps_open(struct inode *inode, st= ruct file *file) =20 const struct file_operations proc_pid_numa_maps_operations =3D { .open =3D pid_numa_maps_open, - .read =3D seq_read, + .read_iter =3D seq_read_iter, .llseek =3D seq_lseek, .release =3D proc_map_release, }; diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c index bce674533000..b1385bf8dd05 100644 --- a/fs/proc/task_nommu.c +++ b/fs/proc/task_nommu.c @@ -289,7 +289,7 @@ static int pid_maps_open(struct inode *inode, struct fi= le *file) =20 const struct file_operations proc_pid_maps_operations =3D { .open =3D pid_maps_open, - .read =3D seq_read, + .read_iter =3D seq_read_iter, .llseek =3D seq_lseek, .release =3D map_release, }; diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h index 6030a8235617..181ba788a56b 100644 --- a/include/linux/user_namespace.h +++ b/include/linux/user_namespace.h @@ -174,13 +174,15 @@ static inline void put_user_ns(struct user_namespace = *ns) } =20 struct seq_operations; +struct kiocb; +struct iov_iter; extern const struct seq_operations proc_uid_seq_operations; extern const struct seq_operations proc_gid_seq_operations; extern const struct seq_operations proc_projid_seq_operations; -extern ssize_t proc_uid_map_write(struct file *, const char __user *, size= _t, loff_t *); -extern ssize_t proc_gid_map_write(struct file *, const char __user *, size= _t, loff_t *); -extern ssize_t proc_projid_map_write(struct file *, const char __user *, s= ize_t, loff_t *); -extern ssize_t proc_setgroups_write(struct file *, const char __user *, si= ze_t, loff_t *); +ssize_t proc_uid_map_write_iter(struct kiocb *iocb, struct iov_iter *from); +ssize_t proc_gid_map_write_iter(struct kiocb *iocb, struct iov_iter *from); +ssize_t proc_projid_map_write_iter(struct kiocb *iocb, struct iov_iter *fr= om); +ssize_t proc_setgroups_write(struct kiocb *iocb, struct iov_iter *from); extern int proc_setgroups_show(struct seq_file *m, void *v); extern bool userns_may_setgroups(const struct user_namespace *ns); extern bool in_userns(const struct user_namespace *ancestor, diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c index 0b0b95418b16..05ec5be1c2d7 100644 --- a/kernel/user_namespace.c +++ b/kernel/user_namespace.c @@ -1108,8 +1108,8 @@ static ssize_t map_write(struct file *file, const cha= r __user *buf, return ret; } =20 -ssize_t proc_uid_map_write(struct file *file, const char __user *buf, - size_t size, loff_t *ppos) +static ssize_t proc_uid_map_write(struct file *file, const char __user *bu= f, + size_t size, loff_t *ppos) { struct seq_file *seq =3D file->private_data; struct user_namespace *ns =3D seq->private; @@ -1125,8 +1125,13 @@ ssize_t proc_uid_map_write(struct file *file, const = char __user *buf, &ns->uid_map, &ns->parent->uid_map); } =20 -ssize_t proc_gid_map_write(struct file *file, const char __user *buf, - size_t size, loff_t *ppos) +ssize_t proc_uid_map_write_iter(struct kiocb *iocb, struct iov_iter *from) +{ + return vfs_write_iter(iocb, from, proc_uid_map_write); +} + +static ssize_t proc_gid_map_write(struct file *file, const char __user *bu= f, + size_t size, loff_t *ppos) { struct seq_file *seq =3D file->private_data; struct user_namespace *ns =3D seq->private; @@ -1142,8 +1147,13 @@ ssize_t proc_gid_map_write(struct file *file, const = char __user *buf, &ns->gid_map, &ns->parent->gid_map); } =20 -ssize_t proc_projid_map_write(struct file *file, const char __user *buf, - size_t size, loff_t *ppos) +ssize_t proc_gid_map_write_iter(struct kiocb *iocb, struct iov_iter *from) +{ + return vfs_write_iter(iocb, from, proc_gid_map_write); +} + +static ssize_t proc_projid_map_write(struct file *file, const char __user = *buf, + size_t size, loff_t *ppos) { struct seq_file *seq =3D file->private_data; struct user_namespace *ns =3D seq->private; @@ -1160,6 +1170,11 @@ ssize_t proc_projid_map_write(struct file *file, con= st char __user *buf, &ns->projid_map, &ns->parent->projid_map); } =20 +ssize_t proc_projid_map_write_iter(struct kiocb *iocb, struct iov_iter *fr= om) +{ + return vfs_write_iter(iocb, from, proc_projid_map_write); +} + static bool new_idmap_permitted(const struct file *file, struct user_namespace *ns, int cap_setid, struct uid_gid_map *new_map) @@ -1213,23 +1228,23 @@ int proc_setgroups_show(struct seq_file *seq, void = *v) return 0; } =20 -ssize_t proc_setgroups_write(struct file *file, const char __user *buf, - size_t count, loff_t *ppos) +ssize_t proc_setgroups_write(struct kiocb *iocb, struct iov_iter *from) { - struct seq_file *seq =3D file->private_data; + struct seq_file *seq =3D iocb->ki_filp->private_data; struct user_namespace *ns =3D seq->private; + size_t count =3D iov_iter_count(from); char kbuf[8], *pos; bool setgroups_allowed; ssize_t ret; =20 /* Only allow a very narrow range of strings to be written */ ret =3D -EINVAL; - if ((*ppos !=3D 0) || (count >=3D sizeof(kbuf))) + if ((iocb->ki_pos !=3D 0) || (count >=3D sizeof(kbuf))) goto out; =20 /* What was written? */ ret =3D -EFAULT; - if (copy_from_user(kbuf, buf, count)) + if (!copy_from_iter_full(kbuf, count, from)) goto out; kbuf[count] =3D '\0'; pos =3D kbuf; @@ -1271,7 +1286,7 @@ ssize_t proc_setgroups_write(struct file *file, const= char __user *buf, mutex_unlock(&userns_state_mutex); =20 /* Report a successful write */ - *ppos =3D count; + iocb->ki_pos =3D count; ret =3D count; out: return ret; --=20 2.43.0