Print this page
OS-3893 sendfile compat checks shouldn't be done in so_sendmblk
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>


  65 #include <inet/ip.h>
  66 #include <inet/ip6.h>
  67 #include <inet/tcp.h>
  68 
  69 extern int sosendfile64(file_t *, file_t *, const struct ksendfilevec64 *,
  70                 ssize32_t *);
  71 extern int nl7c_sendfilev(struct sonode *, u_offset_t *, struct sendfilevec *,
  72                 int, ssize_t *);
  73 extern int snf_segmap(file_t *, vnode_t *, u_offset_t, u_offset_t, ssize_t *,
  74                 boolean_t);
  75 extern sotpi_info_t *sotpi_sototpi(struct sonode *);
  76 
  77 #define SEND_MAX_CHUNK  16
  78 
  79 #if defined(_SYSCALL32_IMPL) || defined(_ILP32)
  80 /*
  81  * 64 bit offsets for 32 bit applications only running either on
  82  * 64 bit kernel or 32 bit kernel. For 32 bit apps, we can't transfer
  83  * more than 2GB of data.
  84  */
  85 int
  86 sendvec_chunk64(file_t *fp, u_offset_t *fileoff, struct ksendfilevec64 *sfv,
  87     int copy_cnt, ssize32_t *count)
  88 {
  89         struct vnode *vp;
  90         ushort_t fflag;
  91         int ioflag;
  92         size32_t cnt;
  93         ssize32_t sfv_len;
  94         ssize32_t tmpcount;
  95         u_offset_t sfv_off;
  96         struct uio auio;
  97         struct iovec aiov;
  98         int i, error;
  99 
 100         fflag = fp->f_flag;
 101         vp = fp->f_vnode;
 102         for (i = 0; i < copy_cnt; i++) {
 103 
 104                 if (ISSIG(curthread, JUSTLOOKING))
 105                         return (EINTR);


 326                                 if (vp->v_type == VREG)
 327                                         *fileoff += cnt;
 328                                 *count += cnt;
 329                                 if (error != 0) {
 330                                         kmem_free(ptr, size);
 331                                         VOP_RWUNLOCK(readvp, V_WRITELOCK_FALSE,
 332                                             NULL);
 333                                         releasef(sfv->sfv_fd);
 334                                         return (error);
 335                                 }
 336                         }
 337                         VOP_RWUNLOCK(readvp, V_WRITELOCK_FALSE, NULL);
 338                         releasef(sfv->sfv_fd);
 339                         kmem_free(ptr, size);
 340                 }
 341                 sfv++;
 342         }
 343         return (0);
 344 }
 345 
 346 ssize32_t
 347 sendvec64(file_t *fp, const struct ksendfilevec64 *vec, int sfvcnt,
 348         size32_t *xferred, int fildes)
 349 {
 350         u_offset_t              fileoff;
 351         int                     copy_cnt;
 352         const struct ksendfilevec64 *copy_vec;
 353         struct ksendfilevec64 sfv[SEND_MAX_CHUNK];
 354         struct vnode *vp;
 355         int error;
 356         ssize32_t count = 0;
 357 
 358         vp = fp->f_vnode;
 359         (void) VOP_RWLOCK(vp, V_WRITELOCK_TRUE, NULL);
 360 
 361         copy_vec = vec;
 362         fileoff = fp->f_offset;
 363 
 364         do {
 365                 copy_cnt = MIN(sfvcnt, SEND_MAX_CHUNK);
 366                 if (copyin(copy_vec, sfv, copy_cnt *


 373                 if (error != 0)
 374                         break;
 375 
 376                 copy_vec += copy_cnt;
 377                 sfvcnt -= copy_cnt;
 378         } while (sfvcnt > 0);
 379 
 380         if (vp->v_type == VREG)
 381                 fp->f_offset += count;
 382 
 383         VOP_RWUNLOCK(vp, V_WRITELOCK_TRUE, NULL);
 384         if (copyout(&count, xferred, sizeof (count)))
 385                 error = EFAULT;
 386         releasef(fildes);
 387         if (error != 0)
 388                 return (set_errno(error));
 389         return (count);
 390 }
 391 #endif
 392 
 393 int
 394 sendvec_small_chunk(file_t *fp, u_offset_t *fileoff, struct sendfilevec *sfv,
 395     int copy_cnt, ssize_t total_size, int maxblk, ssize_t *count)
 396 {
 397         struct vnode *vp;
 398         struct uio auio;
 399         struct iovec aiov;
 400         ushort_t fflag;
 401         int ioflag;
 402         int i, error;
 403         size_t cnt;
 404         ssize_t sfv_len;
 405         u_offset_t sfv_off;
 406 #ifdef _SYSCALL32_IMPL
 407         model_t model = get_udatamodel();
 408         u_offset_t maxoff = (model == DATAMODEL_ILP32) ?
 409             MAXOFF32_T : MAXOFFSET_T;
 410 #else
 411         const u_offset_t maxoff = MAXOFF32_T;
 412 #endif
 413         mblk_t *dmp = NULL;


 663                         VOP_RWUNLOCK(readvp, V_WRITELOCK_FALSE, NULL);
 664                         releasef(sfv->sfv_fd);
 665                 }
 666                 sfv++;
 667         }
 668 
 669         ASSERT(total_size == 0);
 670         error = socket_sendmblk(VTOSO(vp), &msg, fflag, CRED(), &head);
 671         if (error != 0) {
 672                 if (head != NULL)
 673                         freemsg(head);
 674                 return (error);
 675         }
 676         ttolwp(curthread)->lwp_ru.ioch += (ulong_t)size;
 677         *count += size;
 678 
 679         return (0);
 680 }
 681 
 682 
 683 int
 684 sendvec_chunk(file_t *fp, u_offset_t *fileoff, struct sendfilevec *sfv,
 685     int copy_cnt, ssize_t *count)
 686 {
 687         struct vnode *vp;
 688         struct uio auio;
 689         struct iovec aiov;
 690         ushort_t fflag;
 691         int ioflag;
 692         int i, error;
 693         size_t cnt;
 694         ssize_t sfv_len;
 695         u_offset_t sfv_off;
 696 #ifdef _SYSCALL32_IMPL
 697         model_t model = get_udatamodel();
 698         u_offset_t maxoff = (model == DATAMODEL_ILP32) ?
 699             MAXOFF32_T : MAXOFFSET_T;
 700 #else
 701         const u_offset_t maxoff = MAXOFF32_T;
 702 #endif
 703         mblk_t  *dmp = NULL;


1143         if ((fp = getf(fildes)) == NULL)
1144                 return (set_errno(EBADF));
1145 
1146         if (((fp->f_flag) & FWRITE) == 0) {
1147                 error = EBADF;
1148                 goto err;
1149         }
1150 
1151         fileoff = fp->f_offset;
1152         vp = fp->f_vnode;
1153 
1154         switch (vp->v_type) {
1155         case VSOCK:
1156                 so = VTOSO(vp);
1157                 is_sock = B_TRUE;
1158                 if (SOCK_IS_NONSTR(so)) {
1159                         maxblk = so->so_proto_props.sopp_maxblk;
1160                 } else {
1161                         maxblk = (int)vp->v_stream->sd_maxblk;
1162                 }











1163                 break;
1164         case VREG:
1165                 break;
1166         default:
1167                 error = EINVAL;
1168                 goto err;
1169         }
1170 
1171         switch (opcode) {
1172         case SENDFILEV :
1173                 break;
1174 #if defined(_SYSCALL32_IMPL) || defined(_ILP32)
1175         case SENDFILEV64 :
1176                 return (sendvec64(fp, (struct ksendfilevec64 *)vec, sfvcnt,
1177                     (size32_t *)xferred, fildes));
1178 #endif
1179         default :
1180                 error = ENOSYS;
1181                 break;
1182         }




  65 #include <inet/ip.h>
  66 #include <inet/ip6.h>
  67 #include <inet/tcp.h>
  68 
  69 extern int sosendfile64(file_t *, file_t *, const struct ksendfilevec64 *,
  70                 ssize32_t *);
  71 extern int nl7c_sendfilev(struct sonode *, u_offset_t *, struct sendfilevec *,
  72                 int, ssize_t *);
  73 extern int snf_segmap(file_t *, vnode_t *, u_offset_t, u_offset_t, ssize_t *,
  74                 boolean_t);
  75 extern sotpi_info_t *sotpi_sototpi(struct sonode *);
  76 
  77 #define SEND_MAX_CHUNK  16
  78 
  79 #if defined(_SYSCALL32_IMPL) || defined(_ILP32)
  80 /*
  81  * 64 bit offsets for 32 bit applications only running either on
  82  * 64 bit kernel or 32 bit kernel. For 32 bit apps, we can't transfer
  83  * more than 2GB of data.
  84  */
  85 static int
  86 sendvec_chunk64(file_t *fp, u_offset_t *fileoff, struct ksendfilevec64 *sfv,
  87     int copy_cnt, ssize32_t *count)
  88 {
  89         struct vnode *vp;
  90         ushort_t fflag;
  91         int ioflag;
  92         size32_t cnt;
  93         ssize32_t sfv_len;
  94         ssize32_t tmpcount;
  95         u_offset_t sfv_off;
  96         struct uio auio;
  97         struct iovec aiov;
  98         int i, error;
  99 
 100         fflag = fp->f_flag;
 101         vp = fp->f_vnode;
 102         for (i = 0; i < copy_cnt; i++) {
 103 
 104                 if (ISSIG(curthread, JUSTLOOKING))
 105                         return (EINTR);


 326                                 if (vp->v_type == VREG)
 327                                         *fileoff += cnt;
 328                                 *count += cnt;
 329                                 if (error != 0) {
 330                                         kmem_free(ptr, size);
 331                                         VOP_RWUNLOCK(readvp, V_WRITELOCK_FALSE,
 332                                             NULL);
 333                                         releasef(sfv->sfv_fd);
 334                                         return (error);
 335                                 }
 336                         }
 337                         VOP_RWUNLOCK(readvp, V_WRITELOCK_FALSE, NULL);
 338                         releasef(sfv->sfv_fd);
 339                         kmem_free(ptr, size);
 340                 }
 341                 sfv++;
 342         }
 343         return (0);
 344 }
 345 
 346 static ssize32_t
 347 sendvec64(file_t *fp, const struct ksendfilevec64 *vec, int sfvcnt,
 348         size32_t *xferred, int fildes)
 349 {
 350         u_offset_t              fileoff;
 351         int                     copy_cnt;
 352         const struct ksendfilevec64 *copy_vec;
 353         struct ksendfilevec64 sfv[SEND_MAX_CHUNK];
 354         struct vnode *vp;
 355         int error;
 356         ssize32_t count = 0;
 357 
 358         vp = fp->f_vnode;
 359         (void) VOP_RWLOCK(vp, V_WRITELOCK_TRUE, NULL);
 360 
 361         copy_vec = vec;
 362         fileoff = fp->f_offset;
 363 
 364         do {
 365                 copy_cnt = MIN(sfvcnt, SEND_MAX_CHUNK);
 366                 if (copyin(copy_vec, sfv, copy_cnt *


 373                 if (error != 0)
 374                         break;
 375 
 376                 copy_vec += copy_cnt;
 377                 sfvcnt -= copy_cnt;
 378         } while (sfvcnt > 0);
 379 
 380         if (vp->v_type == VREG)
 381                 fp->f_offset += count;
 382 
 383         VOP_RWUNLOCK(vp, V_WRITELOCK_TRUE, NULL);
 384         if (copyout(&count, xferred, sizeof (count)))
 385                 error = EFAULT;
 386         releasef(fildes);
 387         if (error != 0)
 388                 return (set_errno(error));
 389         return (count);
 390 }
 391 #endif
 392 
 393 static int
 394 sendvec_small_chunk(file_t *fp, u_offset_t *fileoff, struct sendfilevec *sfv,
 395     int copy_cnt, ssize_t total_size, int maxblk, ssize_t *count)
 396 {
 397         struct vnode *vp;
 398         struct uio auio;
 399         struct iovec aiov;
 400         ushort_t fflag;
 401         int ioflag;
 402         int i, error;
 403         size_t cnt;
 404         ssize_t sfv_len;
 405         u_offset_t sfv_off;
 406 #ifdef _SYSCALL32_IMPL
 407         model_t model = get_udatamodel();
 408         u_offset_t maxoff = (model == DATAMODEL_ILP32) ?
 409             MAXOFF32_T : MAXOFFSET_T;
 410 #else
 411         const u_offset_t maxoff = MAXOFF32_T;
 412 #endif
 413         mblk_t *dmp = NULL;


 663                         VOP_RWUNLOCK(readvp, V_WRITELOCK_FALSE, NULL);
 664                         releasef(sfv->sfv_fd);
 665                 }
 666                 sfv++;
 667         }
 668 
 669         ASSERT(total_size == 0);
 670         error = socket_sendmblk(VTOSO(vp), &msg, fflag, CRED(), &head);
 671         if (error != 0) {
 672                 if (head != NULL)
 673                         freemsg(head);
 674                 return (error);
 675         }
 676         ttolwp(curthread)->lwp_ru.ioch += (ulong_t)size;
 677         *count += size;
 678 
 679         return (0);
 680 }
 681 
 682 
 683 static int
 684 sendvec_chunk(file_t *fp, u_offset_t *fileoff, struct sendfilevec *sfv,
 685     int copy_cnt, ssize_t *count)
 686 {
 687         struct vnode *vp;
 688         struct uio auio;
 689         struct iovec aiov;
 690         ushort_t fflag;
 691         int ioflag;
 692         int i, error;
 693         size_t cnt;
 694         ssize_t sfv_len;
 695         u_offset_t sfv_off;
 696 #ifdef _SYSCALL32_IMPL
 697         model_t model = get_udatamodel();
 698         u_offset_t maxoff = (model == DATAMODEL_ILP32) ?
 699             MAXOFF32_T : MAXOFFSET_T;
 700 #else
 701         const u_offset_t maxoff = MAXOFF32_T;
 702 #endif
 703         mblk_t  *dmp = NULL;


1143         if ((fp = getf(fildes)) == NULL)
1144                 return (set_errno(EBADF));
1145 
1146         if (((fp->f_flag) & FWRITE) == 0) {
1147                 error = EBADF;
1148                 goto err;
1149         }
1150 
1151         fileoff = fp->f_offset;
1152         vp = fp->f_vnode;
1153 
1154         switch (vp->v_type) {
1155         case VSOCK:
1156                 so = VTOSO(vp);
1157                 is_sock = B_TRUE;
1158                 if (SOCK_IS_NONSTR(so)) {
1159                         maxblk = so->so_proto_props.sopp_maxblk;
1160                 } else {
1161                         maxblk = (int)vp->v_stream->sd_maxblk;
1162                 }
1163 
1164                 /*
1165                  * We need to make sure that the socket that we're sending on
1166                  * supports sendfile behavior. sockfs doesn't know that the APIs
1167                  * we want to use are coming from sendfile, so we can't rely on
1168                  * it to check for us.
1169                  */
1170                 if ((so->so_mode & SM_SENDFILESUPP) == 0) {
1171                         error = EOPNOTSUPP;
1172                         goto err;
1173                 }
1174                 break;
1175         case VREG:
1176                 break;
1177         default:
1178                 error = EINVAL;
1179                 goto err;
1180         }
1181 
1182         switch (opcode) {
1183         case SENDFILEV :
1184                 break;
1185 #if defined(_SYSCALL32_IMPL) || defined(_ILP32)
1186         case SENDFILEV64 :
1187                 return (sendvec64(fp, (struct ksendfilevec64 *)vec, sfvcnt,
1188                     (size32_t *)xferred, fildes));
1189 #endif
1190         default :
1191                 error = ENOSYS;
1192                 break;
1193         }