Print this page
5880 Increase IOV_MAX to at least 1024
Portions contributed by: Jerry Jelinek <jerry.jelinek@joyent.com>

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/syscall/rw.c
          +++ new/usr/src/uts/common/syscall/rw.c
↓ open down ↓ 14 lines elided ↑ open up ↑
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  
  22   22  /*
  23   23   * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  24   24   * Use is subject to license terms.
  25      - * Copyright (c) 2015, Joyent, Inc.  All rights reserved.
       25 + * Copyright 2015, Joyent, Inc.  All rights reserved.
  26   26   */
  27   27  
  28   28  /*      Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T     */
  29   29  /*        All Rights Reserved   */
  30   30  
  31   31  /*
  32   32   * Portions of this source code were derived from Berkeley 4.3 BSD
  33   33   * under license from the Regents of the University of California.
  34   34   */
  35   35  
↓ open down ↓ 7 lines elided ↑ open up ↑
  43   43  #include <sys/systm.h>
  44   44  #include <sys/errno.h>
  45   45  #include <sys/vnode.h>
  46   46  #include <sys/file.h>
  47   47  #include <sys/proc.h>
  48   48  #include <sys/cpuvar.h>
  49   49  #include <sys/uio.h>
  50   50  #include <sys/debug.h>
  51   51  #include <sys/rctl.h>
  52   52  #include <sys/nbmlock.h>
       53 +#include <sys/limits.h>
  53   54  
  54   55  #define COPYOUT_MAX_CACHE       (1<<17)         /* 128K */
  55   56  
  56   57  size_t copyout_max_cached = COPYOUT_MAX_CACHE;  /* global so it's patchable */
  57   58  
  58   59  /*
  59   60   * read, write, pread, pwrite, readv, and writev syscalls.
  60   61   *
  61   62   * 64-bit open: all open's are large file opens.
  62   63   * Large Files: the behaviour of read depends on whether the fd
↓ open down ↓ 537 lines elided ↑ open up ↑
 600  601                  error = 0;
 601  602  out:
 602  603          if (in_crit)
 603  604                  nbl_end_crit(vp);
 604  605          releasef(fdes);
 605  606          if (error)
 606  607                  return (set_errno(error));
 607  608          return (bcount);
 608  609  }
 609  610  
 610      -/*
 611      - * XXX -- The SVID refers to IOV_MAX, but doesn't define it.  Grrrr....
 612      - * XXX -- However, SVVS expects readv() and writev() to fail if
 613      - * XXX -- iovcnt > 16 (yes, it's hard-coded in the SVVS source),
 614      - * XXX -- so I guess that's the "interface".
 615      - */
 616      -#define DEF_IOV_MAX     16
 617      -
 618  611  ssize_t
 619  612  readv(int fdes, struct iovec *iovp, int iovcnt)
 620  613  {
 621  614          struct uio auio;
 622      -        struct iovec aiov[DEF_IOV_MAX];
      615 +        struct iovec buf[IOV_MAX_STACK], *aiov = buf;
      616 +        int aiovlen = 0;
 623  617          file_t *fp;
 624  618          register vnode_t *vp;
 625  619          struct cpu *cp;
 626  620          int fflag, ioflag, rwflag;
 627  621          ssize_t count, bcount;
 628  622          int error = 0;
 629  623          int i;
 630  624          u_offset_t fileoff;
 631  625          int in_crit = 0;
 632  626  
 633      -        if (iovcnt <= 0 || iovcnt > DEF_IOV_MAX)
      627 +        if (iovcnt <= 0 || iovcnt > IOV_MAX)
 634  628                  return (set_errno(EINVAL));
 635  629  
      630 +        if (iovcnt > IOV_MAX_STACK) {
      631 +                aiovlen = iovcnt * sizeof (iovec_t);
      632 +                aiov = kmem_alloc(aiovlen, KM_SLEEP);
      633 +        }
      634 +
 636  635  #ifdef _SYSCALL32_IMPL
 637  636          /*
 638  637           * 32-bit callers need to have their iovec expanded,
 639  638           * while ensuring that they can't move more than 2Gbytes
 640  639           * of data in a single call.
 641  640           */
 642  641          if (get_udatamodel() == DATAMODEL_ILP32) {
 643      -                struct iovec32 aiov32[DEF_IOV_MAX];
      642 +                struct iovec32 buf32[IOV_MAX_STACK], *aiov32 = buf32;
      643 +                int aiov32len;
 644  644                  ssize32_t count32;
 645  645  
 646      -                if (copyin(iovp, aiov32, iovcnt * sizeof (struct iovec32)))
      646 +                aiov32len = iovcnt * sizeof (iovec32_t);
      647 +                if (aiovlen != 0)
      648 +                        aiov32 = kmem_alloc(aiov32len, KM_SLEEP);
      649 +
      650 +                if (copyin(iovp, aiov32, aiov32len)) {
      651 +                        if (aiovlen != 0) {
      652 +                                kmem_free(aiov32, aiov32len);
      653 +                                kmem_free(aiov, aiovlen);
      654 +                        }
 647  655                          return (set_errno(EFAULT));
      656 +                }
 648  657  
 649  658                  count32 = 0;
 650  659                  for (i = 0; i < iovcnt; i++) {
 651  660                          ssize32_t iovlen32 = aiov32[i].iov_len;
 652  661                          count32 += iovlen32;
 653      -                        if (iovlen32 < 0 || count32 < 0)
      662 +                        if (iovlen32 < 0 || count32 < 0) {
      663 +                                if (aiovlen != 0) {
      664 +                                        kmem_free(aiov32, aiov32len);
      665 +                                        kmem_free(aiov, aiovlen);
      666 +                                }
 654  667                                  return (set_errno(EINVAL));
      668 +                        }
 655  669                          aiov[i].iov_len = iovlen32;
 656  670                          aiov[i].iov_base =
 657  671                              (caddr_t)(uintptr_t)aiov32[i].iov_base;
 658  672                  }
      673 +
      674 +                if (aiovlen != 0)
      675 +                        kmem_free(aiov32, aiov32len);
 659  676          } else
 660  677  #endif
 661      -        if (copyin(iovp, aiov, iovcnt * sizeof (struct iovec)))
      678 +        if (copyin(iovp, aiov, iovcnt * sizeof (iovec_t))) {
      679 +                if (aiovlen != 0)
      680 +                        kmem_free(aiov, aiovlen);
 662  681                  return (set_errno(EFAULT));
      682 +        }
 663  683  
 664  684          count = 0;
 665  685          for (i = 0; i < iovcnt; i++) {
 666  686                  ssize_t iovlen = aiov[i].iov_len;
 667  687                  count += iovlen;
 668      -                if (iovlen < 0 || count < 0)
      688 +                if (iovlen < 0 || count < 0) {
      689 +                        if (aiovlen != 0)
      690 +                                kmem_free(aiov, aiovlen);
 669  691                          return (set_errno(EINVAL));
      692 +                }
 670  693          }
 671      -        if ((fp = getf(fdes)) == NULL)
      694 +        if ((fp = getf(fdes)) == NULL) {
      695 +                if (aiovlen != 0)
      696 +                        kmem_free(aiov, aiovlen);
 672  697                  return (set_errno(EBADF));
      698 +        }
 673  699          if (((fflag = fp->f_flag) & FREAD) == 0) {
 674  700                  error = EBADF;
 675  701                  goto out;
 676  702          }
 677  703          vp = fp->f_vnode;
 678  704          if (vp->v_type == VREG && count == 0) {
 679  705                  goto out;
 680  706          }
 681  707  
 682  708          rwflag = 0;
↓ open down ↓ 78 lines elided ↑ open up ↑
 761  787                  fp->f_offset = auio.uio_loffset;
 762  788  
 763  789          VOP_RWUNLOCK(vp, rwflag, NULL);
 764  790  
 765  791          if (error == EINTR && count != 0)
 766  792                  error = 0;
 767  793  out:
 768  794          if (in_crit)
 769  795                  nbl_end_crit(vp);
 770  796          releasef(fdes);
      797 +        if (aiovlen != 0)
      798 +                kmem_free(aiov, aiovlen);
 771  799          if (error)
 772  800                  return (set_errno(error));
 773  801          return (count);
 774  802  }
 775  803  
 776  804  ssize_t
 777  805  writev(int fdes, struct iovec *iovp, int iovcnt)
 778  806  {
 779  807          struct uio auio;
 780      -        struct iovec aiov[DEF_IOV_MAX];
      808 +        struct iovec buf[IOV_MAX_STACK], *aiov = buf;
      809 +        int aiovlen = 0;
 781  810          file_t *fp;
 782  811          register vnode_t *vp;
 783  812          struct cpu *cp;
 784  813          int fflag, ioflag, rwflag;
 785  814          ssize_t count, bcount;
 786  815          int error = 0;
 787  816          int i;
 788  817          u_offset_t fileoff;
 789  818          int in_crit = 0;
 790  819  
 791      -        if (iovcnt <= 0 || iovcnt > DEF_IOV_MAX)
      820 +        if (iovcnt <= 0 || iovcnt > IOV_MAX)
 792  821                  return (set_errno(EINVAL));
 793  822  
      823 +        if (iovcnt > IOV_MAX_STACK) {
      824 +                aiovlen = iovcnt * sizeof (iovec_t);
      825 +                aiov = kmem_alloc(aiovlen, KM_SLEEP);
      826 +        }
      827 +
 794  828  #ifdef _SYSCALL32_IMPL
 795  829          /*
 796  830           * 32-bit callers need to have their iovec expanded,
 797  831           * while ensuring that they can't move more than 2Gbytes
 798  832           * of data in a single call.
 799  833           */
 800  834          if (get_udatamodel() == DATAMODEL_ILP32) {
 801      -                struct iovec32 aiov32[DEF_IOV_MAX];
      835 +                struct iovec32 buf32[IOV_MAX_STACK], *aiov32 = buf32;
      836 +                int aiov32len;
 802  837                  ssize32_t count32;
 803  838  
 804      -                if (copyin(iovp, aiov32, iovcnt * sizeof (struct iovec32)))
      839 +                aiov32len = iovcnt * sizeof (iovec32_t);
      840 +                if (aiovlen != 0)
      841 +                        aiov32 = kmem_alloc(aiov32len, KM_SLEEP);
      842 +
      843 +                if (copyin(iovp, aiov32, aiov32len)) {
      844 +                        if (aiovlen != 0) {
      845 +                                kmem_free(aiov32, aiov32len);
      846 +                                kmem_free(aiov, aiovlen);
      847 +                        }
 805  848                          return (set_errno(EFAULT));
      849 +                }
 806  850  
 807  851                  count32 = 0;
 808  852                  for (i = 0; i < iovcnt; i++) {
 809  853                          ssize32_t iovlen = aiov32[i].iov_len;
 810  854                          count32 += iovlen;
 811      -                        if (iovlen < 0 || count32 < 0)
      855 +                        if (iovlen < 0 || count32 < 0) {
      856 +                                if (aiovlen != 0) {
      857 +                                        kmem_free(aiov32, aiov32len);
      858 +                                        kmem_free(aiov, aiovlen);
      859 +                                }
 812  860                                  return (set_errno(EINVAL));
      861 +                        }
 813  862                          aiov[i].iov_len = iovlen;
 814  863                          aiov[i].iov_base =
 815  864                              (caddr_t)(uintptr_t)aiov32[i].iov_base;
 816  865                  }
      866 +                if (aiovlen != 0)
      867 +                        kmem_free(aiov32, aiov32len);
 817  868          } else
 818  869  #endif
 819      -        if (copyin(iovp, aiov, iovcnt * sizeof (struct iovec)))
      870 +        if (copyin(iovp, aiov, iovcnt * sizeof (iovec_t))) {
      871 +                if (aiovlen != 0)
      872 +                        kmem_free(aiov, aiovlen);
 820  873                  return (set_errno(EFAULT));
      874 +        }
 821  875  
 822  876          count = 0;
 823  877          for (i = 0; i < iovcnt; i++) {
 824  878                  ssize_t iovlen = aiov[i].iov_len;
 825  879                  count += iovlen;
 826      -                if (iovlen < 0 || count < 0)
      880 +                if (iovlen < 0 || count < 0) {
      881 +                        if (aiovlen != 0)
      882 +                                kmem_free(aiov, aiovlen);
 827  883                          return (set_errno(EINVAL));
      884 +                }
 828  885          }
 829      -        if ((fp = getf(fdes)) == NULL)
      886 +        if ((fp = getf(fdes)) == NULL) {
      887 +                if (aiovlen != 0)
      888 +                        kmem_free(aiov, aiovlen);
 830  889                  return (set_errno(EBADF));
      890 +        }
 831  891          if (((fflag = fp->f_flag) & FWRITE) == 0) {
 832  892                  error = EBADF;
 833  893                  goto out;
 834  894          }
 835  895          vp = fp->f_vnode;
 836  896          if (vp->v_type == VREG && count == 0) {
 837  897                  goto out;
 838  898          }
 839  899  
 840  900          rwflag = 1;
↓ open down ↓ 69 lines elided ↑ open up ↑
 910  970              (vp->v_type != VREG) || (bcount != 0))      /* POSIX */
 911  971                  fp->f_offset = auio.uio_loffset;
 912  972          VOP_RWUNLOCK(vp, rwflag, NULL);
 913  973  
 914  974          if (error == EINTR && count != 0)
 915  975                  error = 0;
 916  976  out:
 917  977          if (in_crit)
 918  978                  nbl_end_crit(vp);
 919  979          releasef(fdes);
      980 +        if (aiovlen != 0)
      981 +                kmem_free(aiov, aiovlen);
 920  982          if (error)
 921  983                  return (set_errno(error));
 922  984          return (count);
 923  985  }
 924  986  
 925  987  ssize_t
 926  988  preadv(int fdes, struct iovec *iovp, int iovcnt, off_t offset,
 927  989      off_t extended_offset)
 928  990  {
 929  991          struct uio auio;
 930      -        struct iovec aiov[DEF_IOV_MAX];
      992 +        struct iovec buf[IOV_MAX_STACK], *aiov = buf;
      993 +        int aiovlen = 0;
 931  994          file_t *fp;
 932  995          register vnode_t *vp;
 933  996          struct cpu *cp;
 934  997          int fflag, ioflag, rwflag;
 935  998          ssize_t count, bcount;
 936  999          int error = 0;
 937 1000          int i;
 938 1001  
 939 1002  #if defined(_SYSCALL32_IMPL) || defined(_ILP32)
 940 1003          u_offset_t fileoff = ((u_offset_t)extended_offset << 32) |
↓ open down ↓ 4 lines elided ↑ open up ↑
 945 1008  #ifdef _SYSCALL32_IMPL
 946 1009          const u_offset_t maxoff = get_udatamodel() == DATAMODEL_ILP32 &&
 947 1010              extended_offset == 0?
 948 1011              MAXOFF32_T : MAXOFFSET_T;
 949 1012  #else /* _SYSCALL32_IMPL */
 950 1013          const u_offset_t maxoff = MAXOFF32_T;
 951 1014  #endif /* _SYSCALL32_IMPL */
 952 1015  
 953 1016          int in_crit = 0;
 954 1017  
 955      -        if (iovcnt <= 0 || iovcnt > DEF_IOV_MAX)
     1018 +        if (iovcnt <= 0 || iovcnt > IOV_MAX)
 956 1019                  return (set_errno(EINVAL));
 957 1020  
     1021 +        if (iovcnt > IOV_MAX_STACK) {
     1022 +                aiovlen = iovcnt * sizeof (iovec_t);
     1023 +                aiov = kmem_alloc(aiovlen, KM_SLEEP);
     1024 +        }
     1025 +
 958 1026  #ifdef _SYSCALL32_IMPL
 959 1027          /*
 960 1028           * 32-bit callers need to have their iovec expanded,
 961 1029           * while ensuring that they can't move more than 2Gbytes
 962 1030           * of data in a single call.
 963 1031           */
 964 1032          if (get_udatamodel() == DATAMODEL_ILP32) {
 965      -                struct iovec32 aiov32[DEF_IOV_MAX];
     1033 +                struct iovec32 buf32[IOV_MAX_STACK], *aiov32 = buf32;
     1034 +                int aiov32len;
 966 1035                  ssize32_t count32;
 967 1036  
 968      -                if (copyin(iovp, aiov32, iovcnt * sizeof (struct iovec32)))
     1037 +                aiov32len = iovcnt * sizeof (iovec32_t);
     1038 +                if (aiovlen != 0)
     1039 +                        aiov32 = kmem_alloc(aiov32len, KM_SLEEP);
     1040 +
     1041 +                if (copyin(iovp, aiov32, aiov32len)) {
     1042 +                        if (aiovlen != 0) {
     1043 +                                kmem_free(aiov32, aiov32len);
     1044 +                                kmem_free(aiov, aiovlen);
     1045 +                        }
 969 1046                          return (set_errno(EFAULT));
     1047 +                }
 970 1048  
 971 1049                  count32 = 0;
 972 1050                  for (i = 0; i < iovcnt; i++) {
 973 1051                          ssize32_t iovlen32 = aiov32[i].iov_len;
 974 1052                          count32 += iovlen32;
 975      -                        if (iovlen32 < 0 || count32 < 0)
     1053 +                        if (iovlen32 < 0 || count32 < 0) {
     1054 +                                if (aiovlen != 0) {
     1055 +                                        kmem_free(aiov32, aiov32len);
     1056 +                                        kmem_free(aiov, aiovlen);
     1057 +                                }
 976 1058                                  return (set_errno(EINVAL));
     1059 +                        }
 977 1060                          aiov[i].iov_len = iovlen32;
 978 1061                          aiov[i].iov_base =
 979 1062                              (caddr_t)(uintptr_t)aiov32[i].iov_base;
 980 1063                  }
     1064 +                if (aiovlen != 0)
     1065 +                        kmem_free(aiov32, aiov32len);
 981 1066          } else
 982 1067  #endif /* _SYSCALL32_IMPL */
 983      -                if (copyin(iovp, aiov, iovcnt * sizeof (struct iovec)))
     1068 +                if (copyin(iovp, aiov, iovcnt * sizeof (iovec_t))) {
     1069 +                        if (aiovlen != 0)
     1070 +                                kmem_free(aiov, aiovlen);
 984 1071                          return (set_errno(EFAULT));
     1072 +                }
 985 1073  
 986 1074          count = 0;
 987 1075          for (i = 0; i < iovcnt; i++) {
 988 1076                  ssize_t iovlen = aiov[i].iov_len;
 989 1077                  count += iovlen;
 990      -                if (iovlen < 0 || count < 0)
     1078 +                if (iovlen < 0 || count < 0) {
     1079 +                        if (aiovlen != 0)
     1080 +                                kmem_free(aiov, aiovlen);
 991 1081                          return (set_errno(EINVAL));
     1082 +                }
 992 1083          }
 993 1084  
 994      -        if ((bcount = (ssize_t)count) < 0)
     1085 +        if ((bcount = (ssize_t)count) < 0) {
     1086 +                if (aiovlen != 0)
     1087 +                        kmem_free(aiov, aiovlen);
 995 1088                  return (set_errno(EINVAL));
 996      -        if ((fp = getf(fdes)) == NULL)
     1089 +        }
     1090 +        if ((fp = getf(fdes)) == NULL) {
     1091 +                if (aiovlen != 0)
     1092 +                        kmem_free(aiov, aiovlen);
 997 1093                  return (set_errno(EBADF));
     1094 +        }
 998 1095          if (((fflag = fp->f_flag) & FREAD) == 0) {
 999 1096                  error = EBADF;
1000 1097                  goto out;
1001 1098          }
1002 1099          vp = fp->f_vnode;
1003 1100          rwflag = 0;
1004 1101          if (vp->v_type == VREG) {
1005 1102  
1006 1103                  if (bcount == 0)
1007 1104                          goto out;
↓ open down ↓ 84 lines elided ↑ open up ↑
1092 1189          ttolwp(curthread)->lwp_ru.ioch += (ulong_t)count;
1093 1190  
1094 1191          VOP_RWUNLOCK(vp, rwflag, NULL);
1095 1192  
1096 1193          if (error == EINTR && count != 0)
1097 1194                  error = 0;
1098 1195  out:
1099 1196          if (in_crit)
1100 1197                  nbl_end_crit(vp);
1101 1198          releasef(fdes);
     1199 +        if (aiovlen != 0)
     1200 +                kmem_free(aiov, aiovlen);
1102 1201          if (error)
1103 1202                  return (set_errno(error));
1104 1203          return (count);
1105 1204  }
1106 1205  
1107 1206  ssize_t
1108 1207  pwritev(int fdes, struct iovec *iovp, int iovcnt, off_t offset,
1109 1208      off_t extended_offset)
1110 1209  {
1111 1210          struct uio auio;
1112      -        struct iovec aiov[DEF_IOV_MAX];
     1211 +        struct iovec buf[IOV_MAX_STACK], *aiov = buf;
     1212 +        int aiovlen = 0;
1113 1213          file_t *fp;
1114 1214          register vnode_t *vp;
1115 1215          struct cpu *cp;
1116 1216          int fflag, ioflag, rwflag;
1117 1217          ssize_t count, bcount;
1118 1218          int error = 0;
1119 1219          int i;
1120 1220  
1121 1221  #if defined(_SYSCALL32_IMPL) || defined(_ILP32)
1122 1222          u_offset_t fileoff = ((u_offset_t)extended_offset << 32) |
↓ open down ↓ 4 lines elided ↑ open up ↑
1127 1227  #ifdef _SYSCALL32_IMPL
1128 1228          const u_offset_t maxoff = get_udatamodel() == DATAMODEL_ILP32 &&
1129 1229              extended_offset == 0?
1130 1230              MAXOFF32_T : MAXOFFSET_T;
1131 1231  #else /* _SYSCALL32_IMPL */
1132 1232          const u_offset_t maxoff = MAXOFF32_T;
1133 1233  #endif /* _SYSCALL32_IMPL */
1134 1234  
1135 1235          int in_crit = 0;
1136 1236  
1137      -        if (iovcnt <= 0 || iovcnt > DEF_IOV_MAX)
     1237 +        if (iovcnt <= 0 || iovcnt > IOV_MAX)
1138 1238                  return (set_errno(EINVAL));
1139 1239  
     1240 +        if (iovcnt > IOV_MAX_STACK) {
     1241 +                aiovlen = iovcnt * sizeof (iovec_t);
     1242 +                aiov = kmem_alloc(aiovlen, KM_SLEEP);
     1243 +        }
     1244 +
1140 1245  #ifdef _SYSCALL32_IMPL
1141 1246          /*
1142 1247           * 32-bit callers need to have their iovec expanded,
1143 1248           * while ensuring that they can't move more than 2Gbytes
1144 1249           * of data in a single call.
1145 1250           */
1146 1251          if (get_udatamodel() == DATAMODEL_ILP32) {
1147      -                struct iovec32 aiov32[DEF_IOV_MAX];
     1252 +                struct iovec32 buf32[IOV_MAX_STACK], *aiov32 = buf32;
     1253 +                int aiov32len;
1148 1254                  ssize32_t count32;
1149 1255  
1150      -                if (copyin(iovp, aiov32, iovcnt * sizeof (struct iovec32)))
     1256 +                aiov32len = iovcnt * sizeof (iovec32_t);
     1257 +                if (aiovlen != 0)
     1258 +                        aiov32 = kmem_alloc(aiov32len, KM_SLEEP);
     1259 +
     1260 +                if (copyin(iovp, aiov32, aiov32len)) {
     1261 +                        if (aiovlen != 0) {
     1262 +                                kmem_free(aiov32, aiov32len);
     1263 +                                kmem_free(aiov, aiovlen);
     1264 +                        }
1151 1265                          return (set_errno(EFAULT));
     1266 +                }
1152 1267  
1153 1268                  count32 = 0;
1154 1269                  for (i = 0; i < iovcnt; i++) {
1155 1270                          ssize32_t iovlen32 = aiov32[i].iov_len;
1156 1271                          count32 += iovlen32;
1157      -                        if (iovlen32 < 0 || count32 < 0)
     1272 +                        if (iovlen32 < 0 || count32 < 0) {
     1273 +                                if (aiovlen != 0) {
     1274 +                                        kmem_free(aiov32, aiov32len);
     1275 +                                        kmem_free(aiov, aiovlen);
     1276 +                                }
1158 1277                                  return (set_errno(EINVAL));
     1278 +                        }
1159 1279                          aiov[i].iov_len = iovlen32;
1160 1280                          aiov[i].iov_base =
1161 1281                              (caddr_t)(uintptr_t)aiov32[i].iov_base;
1162 1282                  }
     1283 +                if (aiovlen != 0)
     1284 +                        kmem_free(aiov32, aiov32len);
1163 1285          } else
1164 1286  #endif /* _SYSCALL32_IMPL */
1165      -                if (copyin(iovp, aiov, iovcnt * sizeof (struct iovec)))
     1287 +                if (copyin(iovp, aiov, iovcnt * sizeof (iovec_t))) {
     1288 +                        if (aiovlen != 0)
     1289 +                                kmem_free(aiov, aiovlen);
1166 1290                          return (set_errno(EFAULT));
     1291 +                }
1167 1292  
1168 1293          count = 0;
1169 1294          for (i = 0; i < iovcnt; i++) {
1170 1295                  ssize_t iovlen = aiov[i].iov_len;
1171 1296                  count += iovlen;
1172      -                if (iovlen < 0 || count < 0)
     1297 +                if (iovlen < 0 || count < 0) {
     1298 +                        if (aiovlen != 0)
     1299 +                                kmem_free(aiov, aiovlen);
1173 1300                          return (set_errno(EINVAL));
     1301 +                }
1174 1302          }
1175 1303  
1176      -        if ((bcount = (ssize_t)count) < 0)
     1304 +        if ((bcount = (ssize_t)count) < 0) {
     1305 +                if (aiovlen != 0)
     1306 +                        kmem_free(aiov, aiovlen);
1177 1307                  return (set_errno(EINVAL));
1178      -        if ((fp = getf(fdes)) == NULL)
     1308 +        }
     1309 +        if ((fp = getf(fdes)) == NULL) {
     1310 +                if (aiovlen != 0)
     1311 +                        kmem_free(aiov, aiovlen);
1179 1312                  return (set_errno(EBADF));
     1313 +        }
1180 1314          if (((fflag = fp->f_flag) & FWRITE) == 0) {
1181 1315                  error = EBADF;
1182 1316                  goto out;
1183 1317          }
1184 1318          vp = fp->f_vnode;
1185 1319          rwflag = 1;
1186 1320          if (vp->v_type == VREG) {
1187 1321  
1188 1322                  if (bcount == 0)
1189 1323                          goto out;
↓ open down ↓ 111 lines elided ↑ open up ↑
1301 1435          ttolwp(curthread)->lwp_ru.ioch += (ulong_t)count;
1302 1436  
1303 1437          VOP_RWUNLOCK(vp, rwflag, NULL);
1304 1438  
1305 1439          if (error == EINTR && count != 0)
1306 1440                  error = 0;
1307 1441  out:
1308 1442          if (in_crit)
1309 1443                  nbl_end_crit(vp);
1310 1444          releasef(fdes);
     1445 +        if (aiovlen != 0)
     1446 +                kmem_free(aiov, aiovlen);
1311 1447          if (error)
1312 1448                  return (set_errno(error));
1313 1449          return (count);
1314 1450  }
1315 1451  
1316 1452  #if defined(_SYSCALL32_IMPL) || defined(_ILP32)
1317 1453  
1318 1454  /*
1319 1455   * This syscall supplies 64-bit file offsets to 32-bit applications only.
1320 1456   */
↓ open down ↓ 313 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX