linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Al Viro <viro@zeniv.linux.org.uk>
To: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Guenter Roeck <linux@roeck-us.net>,
	Linux Kernel Mailing List <linux-kernel@vger.kernel.org>,
	linux-fsdevel <linux-fsdevel@vger.kernel.org>,
	Anton Blanchard <anton@ozlabs.org>
Subject: [RFC] csum_and_copy_from_user() semantics
Date: Fri, 18 Oct 2019 01:27:49 +0100	[thread overview]
Message-ID: <20191018002749.GA13188@ZenIV.linux.org.uk> (raw)
In-Reply-To: <20191016202540.GQ26530@ZenIV.linux.org.uk>

On Wed, Oct 16, 2019 at 09:25:40PM +0100, Al Viro wrote:

> 2) default csum_partial_copy_from_user().  What we need to do is
> turn it into default csum_and_copy_from_user().  This
> #ifndef _HAVE_ARCH_COPY_AND_CSUM_FROM_USER
> static inline
> __wsum csum_and_copy_from_user (const void __user *src, void *dst,
>                                       int len, __wsum sum, int *err_ptr)
> {
>         if (access_ok(src, len))
>                 return csum_partial_copy_from_user(src, dst, len, sum, err_ptr);
> 
>         if (len)
>                 *err_ptr = -EFAULT;
> 
>         return sum;
> }
> #endif
> in checksum.h is the only thing that calls that sucker and we can bloody
> well combine them and make the users of lib/checksum.h define
> _HAVE_ARCH_COPY_AND_CSUM_FROM_USER.  That puts us reasonably close
> to having _HAVE_ARCH_COPY_AND_CSUM_FROM_USER unconditional and in any
> case, __copy_from_user() in lib/checksum.h turns into copy_from_user().

Actually, that gets interesting.  First of all, csum_partial_copy_from_user()
has almost no callers other than csum_and_copy_from_user() - the only
exceptions are alpha and itanic, where csum_partial_copy_nocheck() instances
are using it.

Everything else goes through csum_and_copy_from_user().  And _that_ has
only two callers -  csum_and_copy_from_iter() and csum_and_copy_from_iter_full().
Both treat any failures as "discard the thing", for a good reason.  Namely,
neither csum_and_copy_from_user() nor csum_partial_copy_from_user() have any
means to tell the caller *where* has the fault happened.  So anything
that calls them has to treat a fault as "nothing copied".  That, of course,
goes both for data and csum.

Moreover, behaviour of instances on different architectures differs -
some zero the uncopied-over part of destination, some do not, some
just keep going treating every failed fetch as "got zero" (and returning
the error in the end).

We could, in theory, teach that thing to report the exact amount
copied, so that new users (when and if such appear) could make use
of that.  However, it means a lot of unpleasant work on e.g. sparc.
For raw_copy_from_user() we had to do that, but here I don't see
the point.

As it is, it's only suitable for "discard if anything fails, treat
the entire destination area as garbage in such case" uses.  Which is
all we have for it at the moment.

IOW, it might make sense to get rid of all the "memset the tail to
zero on failure" logics in there - it's not consistently done and
the callers have no way to make use of it anyway.

In any case, there's no point keeping csum_and_copy_from_user()
separate from csum_partial_copy_from_user().  As it is, the
only real difference is that the former does access_ok(), while
the latter might not (some instances do, in which case there's
no difference at all).

Questions from reviewing the instances:
	* mips csum_and_partial_copy_from_user() tries to check
if we are under KERNEL_DS, in which case it goes for kernel-to-kernel
copy.  That's pointless - the callers are reading from an
iovec-backed iov_iter, which can't be created under KERNEL_DS.
So we would have to have set iovec-backed iov_iter while under
USER_DS, then do set_fs(KERNEL_DS), then pass that iov_iter to
->sendmsg().  Which doesn't happen.  IOW, the calls of
__csum_partial_copy_kernel() never happen - neither for
csum_and_copy_from_kernel() for csum_and_copy_to_kernel().

	* ppc does something odd:
        csum = csum_partial_copy_generic((void __force *)src, dst,
                                         len, sum, err_ptr, NULL);

        if (unlikely(*err_ptr)) {
                int missing = __copy_from_user(dst, src, len);

                if (missing) {
                        memset(dst + len - missing, 0, missing);
                        *err_ptr = -EFAULT;
                } else {
                        *err_ptr = 0;
                }

                csum = csum_partial(dst, len, sum);
        }
and since that happens under their stac equivalent, we get it nested -
__copy_from_user() takes and drops it.  I would've said "don't bother
trying to be smart on failures", if I'd been certain that it's not
a fallback for e.g. csum_and_partial_copy_from_user() in misaligned
case.  Could ppc folks clarify that?

  parent reply	other threads:[~2019-10-18  0:27 UTC|newest]

Thread overview: 75+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-10-06 22:20 [PATCH] Convert filldir[64]() from __put_user() to unsafe_put_user() Guenter Roeck
2019-10-06 23:06 ` Linus Torvalds
2019-10-06 23:35   ` Linus Torvalds
2019-10-07  0:04     ` Guenter Roeck
2019-10-07  1:17       ` Linus Torvalds
2019-10-07  1:24         ` Al Viro
2019-10-07  2:06           ` Linus Torvalds
2019-10-07  2:50             ` Al Viro
2019-10-07  3:11               ` Linus Torvalds
2019-10-07 15:40                 ` David Laight
2019-10-07 18:11                   ` Linus Torvalds
2019-10-08  9:58                     ` David Laight
2019-10-07 17:34                 ` Al Viro
2019-10-07 18:13                   ` Linus Torvalds
2019-10-07 18:22                     ` Al Viro
2019-10-07 18:26                 ` Linus Torvalds
2019-10-07 18:36                   ` Tony Luck
2019-10-07 19:08                     ` Linus Torvalds
2019-10-07 19:49                       ` Tony Luck
2019-10-07 20:04                         ` Linus Torvalds
2019-10-08  3:29                   ` Al Viro
2019-10-08  4:09                     ` Linus Torvalds
2019-10-08  4:14                       ` Linus Torvalds
2019-10-08  5:02                         ` Al Viro
2019-10-08  4:24                       ` Linus Torvalds
2019-10-10 19:55                         ` Al Viro
2019-10-10 22:12                           ` Linus Torvalds
2019-10-11  0:11                             ` Al Viro
2019-10-11  0:31                               ` Linus Torvalds
2019-10-13 18:13                                 ` Al Viro
2019-10-13 18:43                                   ` Linus Torvalds
2019-10-13 19:10                                     ` Al Viro
2019-10-13 19:22                                       ` Linus Torvalds
2019-10-13 19:59                                         ` Al Viro
2019-10-13 20:20                                           ` Linus Torvalds
2019-10-15  3:46                                             ` Michael Ellerman
2019-10-15 18:08                                           ` Al Viro
2019-10-15 19:00                                             ` Linus Torvalds
2019-10-15 19:40                                               ` Al Viro
2019-10-15 20:18                                                 ` Al Viro
2019-10-16 12:12                                             ` [RFC] change of calling conventions for arch_futex_atomic_op_inuser() Al Viro
2019-10-16 12:24                                               ` Thomas Gleixner
2019-10-16 20:25                                         ` [PATCH] Convert filldir[64]() from __put_user() to unsafe_put_user() Al Viro
2019-10-17 19:36                                           ` [RFC][PATCHES] drivers/scsi/sg.c uaccess cleanups/fixes Al Viro
2019-10-17 19:39                                             ` [RFC PATCH 1/8] sg_ioctl(): fix copyout handling Al Viro
2019-10-17 19:39                                               ` [RFC PATCH 2/8] sg_new_write(): replace access_ok() + __copy_from_user() with copy_from_user() Al Viro
2019-10-17 19:39                                               ` [RFC PATCH 3/8] sg_write(): __get_user() can fail Al Viro
2019-10-17 19:39                                               ` [RFC PATCH 4/8] sg_read(): simplify reading ->pack_id of userland sg_io_hdr_t Al Viro
2019-10-17 19:39                                               ` [RFC PATCH 5/8] sg_new_write(): don't bother with access_ok Al Viro
2019-10-17 19:39                                               ` [RFC PATCH 6/8] sg_read(): get rid of access_ok()/__copy_..._user() Al Viro
2019-10-17 19:39                                               ` [RFC PATCH 7/8] sg_write(): get rid of access_ok()/__copy_from_user()/__get_user() Al Viro
2019-10-17 19:39                                               ` [RFC PATCH 8/8] SG_IO: get rid of access_ok() Al Viro
2019-10-17 21:44                                             ` [RFC][PATCHES] drivers/scsi/sg.c uaccess cleanups/fixes Douglas Gilbert
2019-11-05  4:54                                             ` Martin K. Petersen
2019-11-05  5:25                                               ` Al Viro
2019-11-06  4:29                                                 ` Martin K. Petersen
2019-10-18  0:27                                           ` Al Viro [this message]
2019-10-25 14:01                                       ` [PATCH] Convert filldir[64]() from __put_user() to unsafe_put_user() Thomas Gleixner
2019-10-08  4:57                       ` Al Viro
2019-10-08 13:14                         ` Greg KH
2019-10-08 15:29                           ` Al Viro
2019-10-08 15:38                             ` Greg KH
2019-10-08 17:06                               ` Al Viro
2019-10-08 19:58                   ` Al Viro
2019-10-08 20:16                     ` Al Viro
2019-10-08 20:34                     ` Al Viro
2019-10-07  2:30         ` Guenter Roeck
2019-10-07  3:12           ` Linus Torvalds
2019-10-07  0:23   ` Guenter Roeck
2019-10-07  4:04 ` Max Filippov
2019-10-07 12:16   ` Guenter Roeck
2019-10-07 19:21 ` Linus Torvalds
2019-10-07 20:29   ` Guenter Roeck
2019-10-07 23:27   ` Guenter Roeck
2019-10-08  6:28     ` Geert Uytterhoeven

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20191018002749.GA13188@ZenIV.linux.org.uk \
    --to=viro@zeniv.linux.org.uk \
    --cc=anton@ozlabs.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux@roeck-us.net \
    --cc=torvalds@linux-foundation.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).