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/fs/sockfs/socksyscalls.c
          +++ new/usr/src/uts/common/fs/sockfs/socksyscalls.c
↓ open down ↓ 13 lines elided ↑ open up ↑
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  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 (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
  24      - */
  25      -
  26      -/* Copyright (c) 2013, OmniTI Computer Consulting, Inc. All rights reserved. */
  27      -/*
       24 + * Copyright 2015, Joyent, Inc.  All rights reserved.
       25 + * Copyright (c) 2013, OmniTI Computer Consulting, Inc. All rights reserved.
  28   26   * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
  29   27   */
  30   28  
  31   29  #include <sys/types.h>
  32   30  #include <sys/t_lock.h>
  33   31  #include <sys/param.h>
  34   32  #include <sys/systm.h>
  35   33  #include <sys/buf.h>
  36   34  #include <sys/conf.h>
  37   35  #include <sys/cred.h>
↓ open down ↓ 9 lines elided ↑ open up ↑
  47   45  #include <sys/stream.h>
  48   46  #include <sys/strsubr.h>
  49   47  #include <sys/strsun.h>
  50   48  #include <sys/sunddi.h>
  51   49  #include <sys/esunddi.h>
  52   50  #include <sys/flock.h>
  53   51  #include <sys/modctl.h>
  54   52  #include <sys/cmn_err.h>
  55   53  #include <sys/vmsystm.h>
  56   54  #include <sys/policy.h>
       55 +#include <sys/limits.h>
  57   56  
  58   57  #include <sys/socket.h>
  59   58  #include <sys/socketvar.h>
  60   59  
  61   60  #include <sys/isa_defs.h>
  62   61  #include <sys/inttypes.h>
  63   62  #include <sys/systm.h>
  64   63  #include <sys/cpuvar.h>
  65   64  #include <sys/filio.h>
  66   65  #include <sys/sendfile.h>
↓ open down ↓ 12 lines elided ↑ open up ↑
  79   78  #else
  80   79  #define do_useracc      1
  81   80  #endif /* SOCK_TEST */
  82   81  
  83   82  extern int      xnet_truncate_print;
  84   83  
  85   84  extern void     nl7c_init(void);
  86   85  extern int      sockfs_defer_nl7c_init;
  87   86  
  88   87  /*
  89      - * Note: DEF_IOV_MAX is defined and used as it is in "fs/vncalls.c"
  90      - *       as there isn't a formal definition of IOV_MAX ???
  91      - */
  92      -#define MSG_MAXIOVLEN   16
  93      -
  94      -/*
  95   88   * Kernel component of socket creation.
  96   89   *
  97   90   * The socket library determines which version number to use.
  98   91   * First the library calls this with a NULL devpath. If this fails
  99   92   * to find a transport (using solookup) the library will look in /etc/netconfig
 100   93   * for the appropriate transport. If one is found it will pass in the
 101   94   * devpath for the kernel to use.
 102   95   */
 103   96  int
 104   97  so_socket(int family, int type_w_flags, int protocol, char *devpath,
↓ open down ↓ 909 lines elided ↑ open up ↑
1014 1007   * Uses the MSG_XPG4_2 flag to determine if the caller is using
1015 1008   * struct omsghdr or struct nmsghdr.
1016 1009   */
1017 1010  ssize_t
1018 1011  recvmsg(int sock, struct nmsghdr *msg, int flags)
1019 1012  {
1020 1013          STRUCT_DECL(nmsghdr, u_lmsg);
1021 1014          STRUCT_HANDLE(nmsghdr, umsgptr);
1022 1015          struct nmsghdr lmsg;
1023 1016          struct uio auio;
1024      -        struct iovec aiov[MSG_MAXIOVLEN];
     1017 +        struct iovec buf[IOV_MAX_STACK], *aiov = buf;
     1018 +        ssize_t iovsize = 0;
1025 1019          int iovcnt;
1026      -        ssize_t len;
     1020 +        ssize_t len, rval;
1027 1021          int i;
1028 1022          int *flagsp;
1029 1023          model_t model;
1030 1024  
1031 1025          dprint(1, ("recvmsg(%d, %p, %d)\n",
1032 1026              sock, (void *)msg, flags));
1033 1027  
1034 1028          model = get_udatamodel();
1035 1029          STRUCT_INIT(u_lmsg, model);
1036 1030          STRUCT_SET_HANDLE(umsgptr, model, msg);
↓ open down ↓ 22 lines elided ↑ open up ↑
1059 1053          lmsg.msg_name = STRUCT_FGETP(u_lmsg, msg_name);
1060 1054          lmsg.msg_namelen = STRUCT_FGET(u_lmsg, msg_namelen);
1061 1055          lmsg.msg_iov = STRUCT_FGETP(u_lmsg, msg_iov);
1062 1056          lmsg.msg_iovlen = STRUCT_FGET(u_lmsg, msg_iovlen);
1063 1057          lmsg.msg_control = STRUCT_FGETP(u_lmsg, msg_control);
1064 1058          lmsg.msg_controllen = STRUCT_FGET(u_lmsg, msg_controllen);
1065 1059          lmsg.msg_flags = STRUCT_FGET(u_lmsg, msg_flags);
1066 1060  
1067 1061          iovcnt = lmsg.msg_iovlen;
1068 1062  
1069      -        if (iovcnt <= 0 || iovcnt > MSG_MAXIOVLEN) {
     1063 +        if (iovcnt <= 0 || iovcnt > IOV_MAX) {
1070 1064                  return (set_errno(EMSGSIZE));
1071 1065          }
1072 1066  
     1067 +        if (iovcnt > IOV_MAX_STACK) {
     1068 +                iovsize = iovcnt * sizeof (struct iovec);
     1069 +                aiov = kmem_alloc(iovsize, KM_SLEEP);
     1070 +        }
     1071 +
1073 1072  #ifdef _SYSCALL32_IMPL
1074 1073          /*
1075 1074           * 32-bit callers need to have their iovec expanded, while ensuring
1076 1075           * that they can't move more than 2Gbytes of data in a single call.
1077 1076           */
1078 1077          if (model == DATAMODEL_ILP32) {
1079      -                struct iovec32 aiov32[MSG_MAXIOVLEN];
     1078 +                struct iovec32 buf32[IOV_MAX_STACK], *aiov32 = buf32;
     1079 +                ssize_t iov32size;
1080 1080                  ssize32_t count32;
1081 1081  
1082      -                if (copyin((struct iovec32 *)lmsg.msg_iov, aiov32,
1083      -                    iovcnt * sizeof (struct iovec32)))
     1082 +                iov32size = iovcnt * sizeof (struct iovec32);
     1083 +                if (iovsize != 0)
     1084 +                        aiov32 = kmem_alloc(iov32size, KM_SLEEP);
     1085 +
     1086 +                if (copyin((struct iovec32 *)lmsg.msg_iov, aiov32, iov32size)) {
     1087 +                        if (iovsize != 0) {
     1088 +                                kmem_free(aiov32, iov32size);
     1089 +                                kmem_free(aiov, iovsize);
     1090 +                        }
     1091 +
1084 1092                          return (set_errno(EFAULT));
     1093 +                }
1085 1094  
1086 1095                  count32 = 0;
1087 1096                  for (i = 0; i < iovcnt; i++) {
1088 1097                          ssize32_t iovlen32;
1089 1098  
1090 1099                          iovlen32 = aiov32[i].iov_len;
1091 1100                          count32 += iovlen32;
1092      -                        if (iovlen32 < 0 || count32 < 0)
     1101 +                        if (iovlen32 < 0 || count32 < 0) {
     1102 +                                if (iovsize != 0) {
     1103 +                                        kmem_free(aiov32, iov32size);
     1104 +                                        kmem_free(aiov, iovsize);
     1105 +                                }
     1106 +
1093 1107                                  return (set_errno(EINVAL));
     1108 +                        }
     1109 +
1094 1110                          aiov[i].iov_len = iovlen32;
1095 1111                          aiov[i].iov_base =
1096 1112                              (caddr_t)(uintptr_t)aiov32[i].iov_base;
1097 1113                  }
     1114 +
     1115 +                if (iovsize != 0)
     1116 +                        kmem_free(aiov32, iov32size);
1098 1117          } else
1099 1118  #endif /* _SYSCALL32_IMPL */
1100 1119          if (copyin(lmsg.msg_iov, aiov, iovcnt * sizeof (struct iovec))) {
     1120 +                if (iovsize != 0)
     1121 +                        kmem_free(aiov, iovsize);
     1122 +
1101 1123                  return (set_errno(EFAULT));
1102 1124          }
1103 1125          len = 0;
1104 1126          for (i = 0; i < iovcnt; i++) {
1105 1127                  ssize_t iovlen = aiov[i].iov_len;
1106 1128                  len += iovlen;
1107 1129                  if (iovlen < 0 || len < 0) {
     1130 +                        if (iovsize != 0)
     1131 +                                kmem_free(aiov, iovsize);
     1132 +
1108 1133                          return (set_errno(EINVAL));
1109 1134                  }
1110 1135          }
1111 1136          auio.uio_loffset = 0;
1112 1137          auio.uio_iov = aiov;
1113 1138          auio.uio_iovcnt = iovcnt;
1114 1139          auio.uio_resid = len;
1115 1140          auio.uio_segflg = UIO_USERSPACE;
1116 1141          auio.uio_limit = 0;
1117 1142  
1118 1143          if (lmsg.msg_control != NULL &&
1119 1144              (do_useracc == 0 ||
1120 1145              useracc(lmsg.msg_control, lmsg.msg_controllen,
1121 1146              B_WRITE) != 0)) {
     1147 +                if (iovsize != 0)
     1148 +                        kmem_free(aiov, iovsize);
     1149 +
1122 1150                  return (set_errno(EFAULT));
1123 1151          }
1124 1152  
1125      -        return (recvit(sock, &lmsg, &auio, flags,
     1153 +        rval = recvit(sock, &lmsg, &auio, flags,
1126 1154              STRUCT_FADDR(umsgptr, msg_namelen),
1127      -            STRUCT_FADDR(umsgptr, msg_controllen), flagsp));
     1155 +            STRUCT_FADDR(umsgptr, msg_controllen), flagsp);
     1156 +
     1157 +        if (iovsize != 0)
     1158 +                kmem_free(aiov, iovsize);
     1159 +
     1160 +        return (rval);
1128 1161  }
1129 1162  
1130 1163  /*
1131 1164   * Common send function.
1132 1165   */
1133 1166  static ssize_t
1134 1167  sendit(int sock, struct nmsghdr *msg, struct uio *uiop, int flags)
1135 1168  {
1136 1169          struct sonode *so;
1137 1170          file_t *fp;
↓ open down ↓ 117 lines elided ↑ open up ↑
1255 1288  /*
1256 1289   * Uses the MSG_XPG4_2 flag to determine if the caller is using
1257 1290   * struct omsghdr or struct nmsghdr.
1258 1291   */
1259 1292  ssize_t
1260 1293  sendmsg(int sock, struct nmsghdr *msg, int flags)
1261 1294  {
1262 1295          struct nmsghdr lmsg;
1263 1296          STRUCT_DECL(nmsghdr, u_lmsg);
1264 1297          struct uio auio;
1265      -        struct iovec aiov[MSG_MAXIOVLEN];
     1298 +        struct iovec buf[IOV_MAX_STACK], *aiov = buf;
     1299 +        ssize_t iovsize = 0;
1266 1300          int iovcnt;
1267      -        ssize_t len;
     1301 +        ssize_t len, rval;
1268 1302          int i;
1269 1303          model_t model;
1270 1304  
1271 1305          dprint(1, ("sendmsg(%d, %p, %d)\n", sock, (void *)msg, flags));
1272 1306  
1273 1307          model = get_udatamodel();
1274 1308          STRUCT_INIT(u_lmsg, model);
1275 1309  
1276 1310          if (flags & MSG_XPG4_2) {
1277 1311                  if (copyin(msg, (char *)STRUCT_BUF(u_lmsg),
↓ open down ↓ 22 lines elided ↑ open up ↑
1300 1334          lmsg.msg_name = STRUCT_FGETP(u_lmsg, msg_name);
1301 1335          lmsg.msg_namelen = STRUCT_FGET(u_lmsg, msg_namelen);
1302 1336          lmsg.msg_iov = STRUCT_FGETP(u_lmsg, msg_iov);
1303 1337          lmsg.msg_iovlen = STRUCT_FGET(u_lmsg, msg_iovlen);
1304 1338          lmsg.msg_control = STRUCT_FGETP(u_lmsg, msg_control);
1305 1339          lmsg.msg_controllen = STRUCT_FGET(u_lmsg, msg_controllen);
1306 1340          lmsg.msg_flags = STRUCT_FGET(u_lmsg, msg_flags);
1307 1341  
1308 1342          iovcnt = lmsg.msg_iovlen;
1309 1343  
1310      -        if (iovcnt <= 0 || iovcnt > MSG_MAXIOVLEN) {
     1344 +        if (iovcnt <= 0 || iovcnt > IOV_MAX) {
1311 1345                  /*
1312 1346                   * Unless this is XPG 4.2 we allow iovcnt == 0 to
1313 1347                   * be compatible with SunOS 4.X and 4.4BSD.
1314 1348                   */
1315 1349                  if (iovcnt != 0 || (flags & MSG_XPG4_2))
1316 1350                          return (set_errno(EMSGSIZE));
1317 1351          }
1318 1352  
     1353 +        if (iovcnt > IOV_MAX_STACK) {
     1354 +                iovsize = iovcnt * sizeof (struct iovec);
     1355 +                aiov = kmem_alloc(iovsize, KM_SLEEP);
     1356 +        }
     1357 +
1319 1358  #ifdef _SYSCALL32_IMPL
1320 1359          /*
1321 1360           * 32-bit callers need to have their iovec expanded, while ensuring
1322 1361           * that they can't move more than 2Gbytes of data in a single call.
1323 1362           */
1324 1363          if (model == DATAMODEL_ILP32) {
1325      -                struct iovec32 aiov32[MSG_MAXIOVLEN];
     1364 +                struct iovec32 buf32[IOV_MAX_STACK], *aiov32 = buf32;
     1365 +                ssize_t iov32size;
1326 1366                  ssize32_t count32;
1327 1367  
     1368 +                iov32size = iovcnt * sizeof (struct iovec32);
     1369 +                if (iovsize != 0)
     1370 +                        aiov32 = kmem_alloc(iov32size, KM_SLEEP);
     1371 +
1328 1372                  if (iovcnt != 0 &&
1329      -                    copyin((struct iovec32 *)lmsg.msg_iov, aiov32,
1330      -                    iovcnt * sizeof (struct iovec32)))
     1373 +                    copyin((struct iovec32 *)lmsg.msg_iov, aiov32, iov32size)) {
     1374 +                        if (iovsize != 0) {
     1375 +                                kmem_free(aiov32, iov32size);
     1376 +                                kmem_free(aiov, iovsize);
     1377 +                        }
     1378 +
1331 1379                          return (set_errno(EFAULT));
     1380 +                }
1332 1381  
1333 1382                  count32 = 0;
1334 1383                  for (i = 0; i < iovcnt; i++) {
1335 1384                          ssize32_t iovlen32;
1336 1385  
1337 1386                          iovlen32 = aiov32[i].iov_len;
1338 1387                          count32 += iovlen32;
1339      -                        if (iovlen32 < 0 || count32 < 0)
     1388 +                        if (iovlen32 < 0 || count32 < 0) {
     1389 +                                if (iovsize != 0) {
     1390 +                                        kmem_free(aiov32, iov32size);
     1391 +                                        kmem_free(aiov, iovsize);
     1392 +                                }
     1393 +
1340 1394                                  return (set_errno(EINVAL));
     1395 +                        }
     1396 +
1341 1397                          aiov[i].iov_len = iovlen32;
1342 1398                          aiov[i].iov_base =
1343 1399                              (caddr_t)(uintptr_t)aiov32[i].iov_base;
1344 1400                  }
     1401 +
     1402 +                if (iovsize != 0)
     1403 +                        kmem_free(aiov32, iov32size);
1345 1404          } else
1346 1405  #endif /* _SYSCALL32_IMPL */
1347 1406          if (iovcnt != 0 &&
1348 1407              copyin(lmsg.msg_iov, aiov,
1349 1408              (unsigned)iovcnt * sizeof (struct iovec))) {
     1409 +                if (iovsize != 0)
     1410 +                        kmem_free(aiov, iovsize);
     1411 +
1350 1412                  return (set_errno(EFAULT));
1351 1413          }
1352 1414          len = 0;
1353 1415          for (i = 0; i < iovcnt; i++) {
1354 1416                  ssize_t iovlen = aiov[i].iov_len;
1355 1417                  len += iovlen;
1356 1418                  if (iovlen < 0 || len < 0) {
     1419 +                        if (iovsize != 0)
     1420 +                                kmem_free(aiov, iovsize);
     1421 +
1357 1422                          return (set_errno(EINVAL));
1358 1423                  }
1359 1424          }
1360 1425          auio.uio_loffset = 0;
1361 1426          auio.uio_iov = aiov;
1362 1427          auio.uio_iovcnt = iovcnt;
1363 1428          auio.uio_resid = len;
1364 1429          auio.uio_segflg = UIO_USERSPACE;
1365 1430          auio.uio_limit = 0;
1366 1431  
1367      -        return (sendit(sock, &lmsg, &auio, flags));
     1432 +        rval = sendit(sock, &lmsg, &auio, flags);
     1433 +
     1434 +        if (iovsize != 0)
     1435 +                kmem_free(aiov, iovsize);
     1436 +
     1437 +        return (rval);
1368 1438  }
1369 1439  
1370 1440  ssize_t
1371 1441  sendto(int sock, void *buffer, size_t len, int flags,
1372 1442      struct sockaddr *name, socklen_t namelen)
1373 1443  {
1374 1444          struct nmsghdr lmsg;
1375 1445          struct uio auio;
1376 1446          struct iovec aiov[1];
1377 1447  
↓ open down ↓ 1706 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX