Print this page
OS-3752 Increase IOV_MAX to at least 1024
OS-3404 lx brand must support sendmsg() with IOV_MAX of 1024

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