Merge branch 'misc.compat' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 15 Jul 2017 18:06:17 +0000 (11:06 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 15 Jul 2017 18:06:17 +0000 (11:06 -0700)
Pull network field-by-field copy-in updates from Al Viro:
 "This part of the misc compat queue was held back for review from
  networking folks and since davem has jus ACKed those..."

* 'misc.compat' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
  get_compat_bpf_fprog(): don't copyin field-by-field
  get_compat_msghdr(): get rid of field-by-field copyin
  copy_msghdr_from_user(): get rid of field-by-field copyin

1  2 
net/socket.c

diff --combined net/socket.c
index 59e902b9df0928cbaf40949a40aa08195eed1ae8,af33d929135a5ebd4dab4747611bf77dc30cf8db..bf2122691fba25ae778d6fd68a179b1e9163defe
@@@ -461,7 -461,7 +461,7 @@@ EXPORT_SYMBOL(sock_from_file)
   *    @err: pointer to an error code return
   *
   *    The file handle passed in is locked and the socket it is bound
 - *    too is returned. If an error occurs the err pointer is overwritten
 + *    to is returned. If an error occurs the err pointer is overwritten
   *    with a negative errno code and NULL is returned. The function checks
   *    for both invalid handles and passing a handle which is not a socket.
   *
@@@ -662,40 -662,6 +662,40 @@@ static bool skb_is_err_queue(const stru
        return skb->pkt_type == PACKET_OUTGOING;
  }
  
 +/* On transmit, software and hardware timestamps are returned independently.
 + * As the two skb clones share the hardware timestamp, which may be updated
 + * before the software timestamp is received, a hardware TX timestamp may be
 + * returned only if there is no software TX timestamp. Ignore false software
 + * timestamps, which may be made in the __sock_recv_timestamp() call when the
 + * option SO_TIMESTAMP(NS) is enabled on the socket, even when the skb has a
 + * hardware timestamp.
 + */
 +static bool skb_is_swtx_tstamp(const struct sk_buff *skb, int false_tstamp)
 +{
 +      return skb->tstamp && !false_tstamp && skb_is_err_queue(skb);
 +}
 +
 +static void put_ts_pktinfo(struct msghdr *msg, struct sk_buff *skb)
 +{
 +      struct scm_ts_pktinfo ts_pktinfo;
 +      struct net_device *orig_dev;
 +
 +      if (!skb_mac_header_was_set(skb))
 +              return;
 +
 +      memset(&ts_pktinfo, 0, sizeof(ts_pktinfo));
 +
 +      rcu_read_lock();
 +      orig_dev = dev_get_by_napi_id(skb_napi_id(skb));
 +      if (orig_dev)
 +              ts_pktinfo.if_index = orig_dev->ifindex;
 +      rcu_read_unlock();
 +
 +      ts_pktinfo.pkt_length = skb->len - skb_mac_offset(skb);
 +      put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPING_PKTINFO,
 +               sizeof(ts_pktinfo), &ts_pktinfo);
 +}
 +
  /*
   * called from sock_recv_timestamp() if sock_flag(sk, SOCK_RCVTSTAMP)
   */
@@@ -704,16 -670,14 +704,16 @@@ void __sock_recv_timestamp(struct msghd
  {
        int need_software_tstamp = sock_flag(sk, SOCK_RCVTSTAMP);
        struct scm_timestamping tss;
 -      int empty = 1;
 +      int empty = 1, false_tstamp = 0;
        struct skb_shared_hwtstamps *shhwtstamps =
                skb_hwtstamps(skb);
  
        /* Race occurred between timestamp enabling and packet
           receiving.  Fill in the current time for now. */
 -      if (need_software_tstamp && skb->tstamp == 0)
 +      if (need_software_tstamp && skb->tstamp == 0) {
                __net_timestamp(skb);
 +              false_tstamp = 1;
 +      }
  
        if (need_software_tstamp) {
                if (!sock_flag(sk, SOCK_RCVTSTAMPNS)) {
                empty = 0;
        if (shhwtstamps &&
            (sk->sk_tsflags & SOF_TIMESTAMPING_RAW_HARDWARE) &&
 -          ktime_to_timespec_cond(shhwtstamps->hwtstamp, tss.ts + 2))
 +          !skb_is_swtx_tstamp(skb, false_tstamp) &&
 +          ktime_to_timespec_cond(shhwtstamps->hwtstamp, tss.ts + 2)) {
                empty = 0;
 +              if ((sk->sk_tsflags & SOF_TIMESTAMPING_OPT_PKTINFO) &&
 +                  !skb_is_err_queue(skb))
 +                      put_ts_pktinfo(msg, skb);
 +      }
        if (!empty) {
                put_cmsg(msg, SOL_SOCKET,
                         SCM_TIMESTAMPING, sizeof(tss), &tss);
@@@ -991,7 -950,8 +991,7 @@@ static long sock_ioctl(struct file *fil
                        err = -EFAULT;
                        if (get_user(pid, (int __user *)argp))
                                break;
 -                      f_setown(sock->file, pid, 1);
 -                      err = 0;
 +                      err = f_setown(sock->file, pid, 1);
                        break;
                case FIOGETOWN:
                case SIOCGPGRP:
@@@ -1910,22 -1870,18 +1910,18 @@@ static int copy_msghdr_from_user(struc
                                 struct sockaddr __user **save_addr,
                                 struct iovec **iov)
  {
-       struct sockaddr __user *uaddr;
-       struct iovec __user *uiov;
-       size_t nr_segs;
+       struct user_msghdr msg;
        ssize_t err;
  
-       if (!access_ok(VERIFY_READ, umsg, sizeof(*umsg)) ||
-           __get_user(uaddr, &umsg->msg_name) ||
-           __get_user(kmsg->msg_namelen, &umsg->msg_namelen) ||
-           __get_user(uiov, &umsg->msg_iov) ||
-           __get_user(nr_segs, &umsg->msg_iovlen) ||
-           __get_user(kmsg->msg_control, &umsg->msg_control) ||
-           __get_user(kmsg->msg_controllen, &umsg->msg_controllen) ||
-           __get_user(kmsg->msg_flags, &umsg->msg_flags))
+       if (copy_from_user(&msg, umsg, sizeof(*umsg)))
                return -EFAULT;
  
-       if (!uaddr)
+       kmsg->msg_control = msg.msg_control;
+       kmsg->msg_controllen = msg.msg_controllen;
+       kmsg->msg_flags = msg.msg_flags;
+       kmsg->msg_namelen = msg.msg_namelen;
+       if (!msg.msg_name)
                kmsg->msg_namelen = 0;
  
        if (kmsg->msg_namelen < 0)
                kmsg->msg_namelen = sizeof(struct sockaddr_storage);
  
        if (save_addr)
-               *save_addr = uaddr;
+               *save_addr = msg.msg_name;
  
-       if (uaddr && kmsg->msg_namelen) {
+       if (msg.msg_name && kmsg->msg_namelen) {
                if (!save_addr) {
-                       err = move_addr_to_kernel(uaddr, kmsg->msg_namelen,
+                       err = move_addr_to_kernel(msg.msg_name, kmsg->msg_namelen,
                                                  kmsg->msg_name);
                        if (err < 0)
                                return err;
                kmsg->msg_namelen = 0;
        }
  
-       if (nr_segs > UIO_MAXIOV)
+       if (msg.msg_iovlen > UIO_MAXIOV)
                return -EMSGSIZE;
  
        kmsg->msg_iocb = NULL;
  
-       return import_iovec(save_addr ? READ : WRITE, uiov, nr_segs,
+       return import_iovec(save_addr ? READ : WRITE,
+                           msg.msg_iov, msg.msg_iovlen,
                            UIO_FASTIOV, iov, &kmsg->msg_iter);
  }