1 /* 2 * 32bit Socket syscall emulation. Based on arch/sparc64/kernel/sys_sparc32.c. 3 * 4 * Copyright (C) 2000 VA Linux Co 5 * Copyright (C) 2000 Don Dugger <n0ano@valinux.com> 6 * Copyright (C) 1999 Arun Sharma <arun.sharma@intel.com> 7 * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) 8 * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) 9 * Copyright (C) 2000 Hewlett-Packard Co. 10 * Copyright (C) 2000 David Mosberger-Tang <davidm@hpl.hp.com> 11 * Copyright (C) 2000,2001 Andi Kleen, SuSE Labs 12 */ 13 14 #include <linux/kernel.h> 15 #include <linux/gfp.h> 16 #include <linux/fs.h> 17 #include <linux/types.h> 18 #include <linux/file.h> 19 #include <linux/icmpv6.h> 20 #include <linux/socket.h> 21 #include <linux/syscalls.h> 22 #include <linux/filter.h> 23 #include <linux/compat.h> 24 #include <linux/security.h> 25 #include <linux/export.h> 26 27 #include <net/scm.h> 28 #include <net/sock.h> 29 #include <net/ip.h> 30 #include <net/ipv6.h> 31 #include <asm/uaccess.h> 32 #include <net/compat.h> 33 34 ssize_t get_compat_msghdr(struct msghdr *kmsg, 35 struct compat_msghdr __user *umsg, 36 struct sockaddr __user **save_addr, 37 struct iovec **iov) 38 { 39 compat_uptr_t uaddr, uiov, tmp3; 40 compat_size_t nr_segs; 41 ssize_t err; 42 43 if (!access_ok(VERIFY_READ, umsg, sizeof(*umsg)) || 44 __get_user(uaddr, &umsg->msg_name) || 45 __get_user(kmsg->msg_namelen, &umsg->msg_namelen) || 46 __get_user(uiov, &umsg->msg_iov) || 47 __get_user(nr_segs, &umsg->msg_iovlen) || 48 __get_user(tmp3, &umsg->msg_control) || 49 __get_user(kmsg->msg_controllen, &umsg->msg_controllen) || 50 __get_user(kmsg->msg_flags, &umsg->msg_flags)) 51 return -EFAULT; 52 if (kmsg->msg_namelen > sizeof(struct sockaddr_storage)) 53 kmsg->msg_namelen = sizeof(struct sockaddr_storage); 54 kmsg->msg_control = compat_ptr(tmp3); 55 56 if (save_addr) 57 *save_addr = compat_ptr(uaddr); 58 59 if (uaddr && kmsg->msg_namelen) { 60 if (!save_addr) { 61 err = move_addr_to_kernel(compat_ptr(uaddr), 62 kmsg->msg_namelen, 63 kmsg->msg_name); 64 if (err < 0) 65 return err; 66 } 67 } else { 68 kmsg->msg_name = NULL; 69 kmsg->msg_namelen = 0; 70 } 71 72 if (nr_segs > UIO_MAXIOV) 73 return -EMSGSIZE; 74 75 err = compat_rw_copy_check_uvector(save_addr ? READ : WRITE, 76 compat_ptr(uiov), nr_segs, 77 UIO_FASTIOV, *iov, iov); 78 if (err >= 0) 79 iov_iter_init(&kmsg->msg_iter, save_addr ? READ : WRITE, 80 *iov, nr_segs, err); 81 return err; 82 } 83 84 /* Bleech... */ 85 #define CMSG_COMPAT_ALIGN(len) ALIGN((len), sizeof(s32)) 86 87 #define CMSG_COMPAT_DATA(cmsg) \ 88 ((void __user *)((char __user *)(cmsg) + CMSG_COMPAT_ALIGN(sizeof(struct compat_cmsghdr)))) 89 #define CMSG_COMPAT_SPACE(len) \ 90 (CMSG_COMPAT_ALIGN(sizeof(struct compat_cmsghdr)) + CMSG_COMPAT_ALIGN(len)) 91 #define CMSG_COMPAT_LEN(len) \ 92 (CMSG_COMPAT_ALIGN(sizeof(struct compat_cmsghdr)) + (len)) 93 94 #define CMSG_COMPAT_FIRSTHDR(msg) \ 95 (((msg)->msg_controllen) >= sizeof(struct compat_cmsghdr) ? \ 96 (struct compat_cmsghdr __user *)((msg)->msg_control) : \ 97 (struct compat_cmsghdr __user *)NULL) 98 99 #define CMSG_COMPAT_OK(ucmlen, ucmsg, mhdr) \ 100 ((ucmlen) >= sizeof(struct compat_cmsghdr) && \ 101 (ucmlen) <= (unsigned long) \ 102 ((mhdr)->msg_controllen - \ 103 ((char *)(ucmsg) - (char *)(mhdr)->msg_control))) 104 105 static inline struct compat_cmsghdr __user *cmsg_compat_nxthdr(struct msghdr *msg, 106 struct compat_cmsghdr __user *cmsg, int cmsg_len) 107 { 108 char __user *ptr = (char __user *)cmsg + CMSG_COMPAT_ALIGN(cmsg_len); 109 if ((unsigned long)(ptr + 1 - (char __user *)msg->msg_control) > 110 msg->msg_controllen) 111 return NULL; 112 return (struct compat_cmsghdr __user *)ptr; 113 } 114 115 /* There is a lot of hair here because the alignment rules (and 116 * thus placement) of cmsg headers and length are different for 117 * 32-bit apps. -DaveM 118 */ 119 int cmsghdr_from_user_compat_to_kern(struct msghdr *kmsg, struct sock *sk, 120 unsigned char *stackbuf, int stackbuf_size) 121 { 122 struct compat_cmsghdr __user *ucmsg; 123 struct cmsghdr *kcmsg, *kcmsg_base; 124 compat_size_t ucmlen; 125 __kernel_size_t kcmlen, tmp; 126 int err = -EFAULT; 127 128 kcmlen = 0; 129 kcmsg_base = kcmsg = (struct cmsghdr *)stackbuf; 130 ucmsg = CMSG_COMPAT_FIRSTHDR(kmsg); 131 while (ucmsg != NULL) { 132 if (get_user(ucmlen, &ucmsg->cmsg_len)) 133 return -EFAULT; 134 135 /* Catch bogons. */ 136 if (!CMSG_COMPAT_OK(ucmlen, ucmsg, kmsg)) 137 return -EINVAL; 138 139 tmp = ((ucmlen - CMSG_COMPAT_ALIGN(sizeof(*ucmsg))) + 140 CMSG_ALIGN(sizeof(struct cmsghdr))); 141 tmp = CMSG_ALIGN(tmp); 142 kcmlen += tmp; 143 ucmsg = cmsg_compat_nxthdr(kmsg, ucmsg, ucmlen); 144 } 145 if (kcmlen == 0) 146 return -EINVAL; 147 148 /* The kcmlen holds the 64-bit version of the control length. 149 * It may not be modified as we do not stick it into the kmsg 150 * until we have successfully copied over all of the data 151 * from the user. 152 */ 153 if (kcmlen > stackbuf_size) 154 kcmsg_base = kcmsg = sock_kmalloc(sk, kcmlen, GFP_KERNEL); 155 if (kcmsg == NULL) 156 return -ENOBUFS; 157 158 /* Now copy them over neatly. */ 159 memset(kcmsg, 0, kcmlen); 160 ucmsg = CMSG_COMPAT_FIRSTHDR(kmsg); 161 while (ucmsg != NULL) { 162 if (__get_user(ucmlen, &ucmsg->cmsg_len)) 163 goto Efault; 164 if (!CMSG_COMPAT_OK(ucmlen, ucmsg, kmsg)) 165 goto Einval; 166 tmp = ((ucmlen - CMSG_COMPAT_ALIGN(sizeof(*ucmsg))) + 167 CMSG_ALIGN(sizeof(struct cmsghdr))); 168 if ((char *)kcmsg_base + kcmlen - (char *)kcmsg < CMSG_ALIGN(tmp)) 169 goto Einval; 170 kcmsg->cmsg_len = tmp; 171 tmp = CMSG_ALIGN(tmp); 172 if (__get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level) || 173 __get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type) || 174 copy_from_user(CMSG_DATA(kcmsg), 175 CMSG_COMPAT_DATA(ucmsg), 176 (ucmlen - CMSG_COMPAT_ALIGN(sizeof(*ucmsg))))) 177 goto Efault; 178 179 /* Advance. */ 180 kcmsg = (struct cmsghdr *)((char *)kcmsg + tmp); 181 ucmsg = cmsg_compat_nxthdr(kmsg, ucmsg, ucmlen); 182 } 183 184 /* Ok, looks like we made it. Hook it up and return success. */ 185 kmsg->msg_control = kcmsg_base; 186 kmsg->msg_controllen = kcmlen; 187 return 0; 188 189 Einval: 190 err = -EINVAL; 191 Efault: 192 if (kcmsg_base != (struct cmsghdr *)stackbuf) 193 sock_kfree_s(sk, kcmsg_base, kcmlen); 194 return err; 195 } 196 197 int put_cmsg_compat(struct msghdr *kmsg, int level, int type, int len, void *data) 198 { 199 struct compat_cmsghdr __user *cm = (struct compat_cmsghdr __user *) kmsg->msg_control; 200 struct compat_cmsghdr cmhdr; 201 struct compat_timeval ctv; 202 struct compat_timespec cts[3]; 203 int cmlen; 204 205 if (cm == NULL || kmsg->msg_controllen < sizeof(*cm)) { 206 kmsg->msg_flags |= MSG_CTRUNC; 207 return 0; /* XXX: return error? check spec. */ 208 } 209 210 if (!COMPAT_USE_64BIT_TIME) { 211 if (level == SOL_SOCKET && type == SCM_TIMESTAMP) { 212 struct timeval *tv = (struct timeval *)data; 213 ctv.tv_sec = tv->tv_sec; 214 ctv.tv_usec = tv->tv_usec; 215 data = &ctv; 216 len = sizeof(ctv); 217 } 218 if (level == SOL_SOCKET && 219 (type == SCM_TIMESTAMPNS || type == SCM_TIMESTAMPING)) { 220 int count = type == SCM_TIMESTAMPNS ? 1 : 3; 221 int i; 222 struct timespec *ts = (struct timespec *)data; 223 for (i = 0; i < count; i++) { 224 cts[i].tv_sec = ts[i].tv_sec; 225 cts[i].tv_nsec = ts[i].tv_nsec; 226 } 227 data = &cts; 228 len = sizeof(cts[0]) * count; 229 } 230 } 231 232 cmlen = CMSG_COMPAT_LEN(len); 233 if (kmsg->msg_controllen < cmlen) { 234 kmsg->msg_flags |= MSG_CTRUNC; 235 cmlen = kmsg->msg_controllen; 236 } 237 cmhdr.cmsg_level = level; 238 cmhdr.cmsg_type = type; 239 cmhdr.cmsg_len = cmlen; 240 241 if (copy_to_user(cm, &cmhdr, sizeof cmhdr)) 242 return -EFAULT; 243 if (copy_to_user(CMSG_COMPAT_DATA(cm), data, cmlen - sizeof(struct compat_cmsghdr))) 244 return -EFAULT; 245 cmlen = CMSG_COMPAT_SPACE(len); 246 if (kmsg->msg_controllen < cmlen) 247 cmlen = kmsg->msg_controllen; 248 kmsg->msg_control += cmlen; 249 kmsg->msg_controllen -= cmlen; 250 return 0; 251 } 252 253 void scm_detach_fds_compat(struct msghdr *kmsg, struct scm_cookie *scm) 254 { 255 struct compat_cmsghdr __user *cm = (struct compat_cmsghdr __user *) kmsg->msg_control; 256 int fdmax = (kmsg->msg_controllen - sizeof(struct compat_cmsghdr)) / sizeof(int); 257 int fdnum = scm->fp->count; 258 struct file **fp = scm->fp->fp; 259 int __user *cmfptr; 260 int err = 0, i; 261 262 if (fdnum < fdmax) 263 fdmax = fdnum; 264 265 for (i = 0, cmfptr = (int __user *) CMSG_COMPAT_DATA(cm); i < fdmax; i++, cmfptr++) { 266 int new_fd; 267 err = security_file_receive(fp[i]); 268 if (err) 269 break; 270 err = get_unused_fd_flags(MSG_CMSG_CLOEXEC & kmsg->msg_flags 271 ? O_CLOEXEC : 0); 272 if (err < 0) 273 break; 274 new_fd = err; 275 err = put_user(new_fd, cmfptr); 276 if (err) { 277 put_unused_fd(new_fd); 278 break; 279 } 280 /* Bump the usage count and install the file. */ 281 fd_install(new_fd, get_file(fp[i])); 282 } 283 284 if (i > 0) { 285 int cmlen = CMSG_COMPAT_LEN(i * sizeof(int)); 286 err = put_user(SOL_SOCKET, &cm->cmsg_level); 287 if (!err) 288 err = put_user(SCM_RIGHTS, &cm->cmsg_type); 289 if (!err) 290 err = put_user(cmlen, &cm->cmsg_len); 291 if (!err) { 292 cmlen = CMSG_COMPAT_SPACE(i * sizeof(int)); 293 kmsg->msg_control += cmlen; 294 kmsg->msg_controllen -= cmlen; 295 } 296 } 297 if (i < fdnum) 298 kmsg->msg_flags |= MSG_CTRUNC; 299 300 /* 301 * All of the files that fit in the message have had their 302 * usage counts incremented, so we just free the list. 303 */ 304 __scm_destroy(scm); 305 } 306 307 static int do_set_attach_filter(struct socket *sock, int level, int optname, 308 char __user *optval, unsigned int optlen) 309 { 310 struct compat_sock_fprog __user *fprog32 = (struct compat_sock_fprog __user *)optval; 311 struct sock_fprog __user *kfprog = compat_alloc_user_space(sizeof(struct sock_fprog)); 312 compat_uptr_t ptr; 313 u16 len; 314 315 if (!access_ok(VERIFY_READ, fprog32, sizeof(*fprog32)) || 316 !access_ok(VERIFY_WRITE, kfprog, sizeof(struct sock_fprog)) || 317 __get_user(len, &fprog32->len) || 318 __get_user(ptr, &fprog32->filter) || 319 __put_user(len, &kfprog->len) || 320 __put_user(compat_ptr(ptr), &kfprog->filter)) 321 return -EFAULT; 322 323 return sock_setsockopt(sock, level, optname, (char __user *)kfprog, 324 sizeof(struct sock_fprog)); 325 } 326 327 static int do_set_sock_timeout(struct socket *sock, int level, 328 int optname, char __user *optval, unsigned int optlen) 329 { 330 struct compat_timeval __user *up = (struct compat_timeval __user *)optval; 331 struct timeval ktime; 332 mm_segment_t old_fs; 333 int err; 334 335 if (optlen < sizeof(*up)) 336 return -EINVAL; 337 if (!access_ok(VERIFY_READ, up, sizeof(*up)) || 338 __get_user(ktime.tv_sec, &up->tv_sec) || 339 __get_user(ktime.tv_usec, &up->tv_usec)) 340 return -EFAULT; 341 old_fs = get_fs(); 342 set_fs(KERNEL_DS); 343 err = sock_setsockopt(sock, level, optname, (char *)&ktime, sizeof(ktime)); 344 set_fs(old_fs); 345 346 return err; 347 } 348 349 static int compat_sock_setsockopt(struct socket *sock, int level, int optname, 350 char __user *optval, unsigned int optlen) 351 { 352 if (optname == SO_ATTACH_FILTER) 353 return do_set_attach_filter(sock, level, optname, 354 optval, optlen); 355 if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO) 356 return do_set_sock_timeout(sock, level, optname, optval, optlen); 357 358 return sock_setsockopt(sock, level, optname, optval, optlen); 359 } 360 361 COMPAT_SYSCALL_DEFINE5(setsockopt, int, fd, int, level, int, optname, 362 char __user *, optval, unsigned int, optlen) 363 { 364 int err; 365 struct socket *sock = sockfd_lookup(fd, &err); 366 367 if (sock) { 368 err = security_socket_setsockopt(sock, level, optname); 369 if (err) { 370 sockfd_put(sock); 371 return err; 372 } 373 374 if (level == SOL_SOCKET) 375 err = compat_sock_setsockopt(sock, level, 376 optname, optval, optlen); 377 else if (sock->ops->compat_setsockopt) 378 err = sock->ops->compat_setsockopt(sock, level, 379 optname, optval, optlen); 380 else 381 err = sock->ops->setsockopt(sock, level, 382 optname, optval, optlen); 383 sockfd_put(sock); 384 } 385 return err; 386 } 387 388 static int do_get_sock_timeout(struct socket *sock, int level, int optname, 389 char __user *optval, int __user *optlen) 390 { 391 struct compat_timeval __user *up; 392 struct timeval ktime; 393 mm_segment_t old_fs; 394 int len, err; 395 396 up = (struct compat_timeval __user *) optval; 397 if (get_user(len, optlen)) 398 return -EFAULT; 399 if (len < sizeof(*up)) 400 return -EINVAL; 401 len = sizeof(ktime); 402 old_fs = get_fs(); 403 set_fs(KERNEL_DS); 404 err = sock_getsockopt(sock, level, optname, (char *) &ktime, &len); 405 set_fs(old_fs); 406 407 if (!err) { 408 if (put_user(sizeof(*up), optlen) || 409 !access_ok(VERIFY_WRITE, up, sizeof(*up)) || 410 __put_user(ktime.tv_sec, &up->tv_sec) || 411 __put_user(ktime.tv_usec, &up->tv_usec)) 412 err = -EFAULT; 413 } 414 return err; 415 } 416 417 static int compat_sock_getsockopt(struct socket *sock, int level, int optname, 418 char __user *optval, int __user *optlen) 419 { 420 if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO) 421 return do_get_sock_timeout(sock, level, optname, optval, optlen); 422 return sock_getsockopt(sock, level, optname, optval, optlen); 423 } 424 425 int compat_sock_get_timestamp(struct sock *sk, struct timeval __user *userstamp) 426 { 427 struct compat_timeval __user *ctv; 428 int err; 429 struct timeval tv; 430 431 if (COMPAT_USE_64BIT_TIME) 432 return sock_get_timestamp(sk, userstamp); 433 434 ctv = (struct compat_timeval __user *) userstamp; 435 err = -ENOENT; 436 if (!sock_flag(sk, SOCK_TIMESTAMP)) 437 sock_enable_timestamp(sk, SOCK_TIMESTAMP); 438 tv = ktime_to_timeval(sk->sk_stamp); 439 if (tv.tv_sec == -1) 440 return err; 441 if (tv.tv_sec == 0) { 442 sk->sk_stamp = ktime_get_real(); 443 tv = ktime_to_timeval(sk->sk_stamp); 444 } 445 err = 0; 446 if (put_user(tv.tv_sec, &ctv->tv_sec) || 447 put_user(tv.tv_usec, &ctv->tv_usec)) 448 err = -EFAULT; 449 return err; 450 } 451 EXPORT_SYMBOL(compat_sock_get_timestamp); 452 453 int compat_sock_get_timestampns(struct sock *sk, struct timespec __user *userstamp) 454 { 455 struct compat_timespec __user *ctv; 456 int err; 457 struct timespec ts; 458 459 if (COMPAT_USE_64BIT_TIME) 460 return sock_get_timestampns (sk, userstamp); 461 462 ctv = (struct compat_timespec __user *) userstamp; 463 err = -ENOENT; 464 if (!sock_flag(sk, SOCK_TIMESTAMP)) 465 sock_enable_timestamp(sk, SOCK_TIMESTAMP); 466 ts = ktime_to_timespec(sk->sk_stamp); 467 if (ts.tv_sec == -1) 468 return err; 469 if (ts.tv_sec == 0) { 470 sk->sk_stamp = ktime_get_real(); 471 ts = ktime_to_timespec(sk->sk_stamp); 472 } 473 err = 0; 474 if (put_user(ts.tv_sec, &ctv->tv_sec) || 475 put_user(ts.tv_nsec, &ctv->tv_nsec)) 476 err = -EFAULT; 477 return err; 478 } 479 EXPORT_SYMBOL(compat_sock_get_timestampns); 480 481 COMPAT_SYSCALL_DEFINE5(getsockopt, int, fd, int, level, int, optname, 482 char __user *, optval, int __user *, optlen) 483 { 484 int err; 485 struct socket *sock = sockfd_lookup(fd, &err); 486 487 if (sock) { 488 err = security_socket_getsockopt(sock, level, optname); 489 if (err) { 490 sockfd_put(sock); 491 return err; 492 } 493 494 if (level == SOL_SOCKET) 495 err = compat_sock_getsockopt(sock, level, 496 optname, optval, optlen); 497 else if (sock->ops->compat_getsockopt) 498 err = sock->ops->compat_getsockopt(sock, level, 499 optname, optval, optlen); 500 else 501 err = sock->ops->getsockopt(sock, level, 502 optname, optval, optlen); 503 sockfd_put(sock); 504 } 505 return err; 506 } 507 508 struct compat_group_req { 509 __u32 gr_interface; 510 struct __kernel_sockaddr_storage gr_group 511 __attribute__ ((aligned(4))); 512 } __packed; 513 514 struct compat_group_source_req { 515 __u32 gsr_interface; 516 struct __kernel_sockaddr_storage gsr_group 517 __attribute__ ((aligned(4))); 518 struct __kernel_sockaddr_storage gsr_source 519 __attribute__ ((aligned(4))); 520 } __packed; 521 522 struct compat_group_filter { 523 __u32 gf_interface; 524 struct __kernel_sockaddr_storage gf_group 525 __attribute__ ((aligned(4))); 526 __u32 gf_fmode; 527 __u32 gf_numsrc; 528 struct __kernel_sockaddr_storage gf_slist[1] 529 __attribute__ ((aligned(4))); 530 } __packed; 531 532 #define __COMPAT_GF0_SIZE (sizeof(struct compat_group_filter) - \ 533 sizeof(struct __kernel_sockaddr_storage)) 534 535 536 int compat_mc_setsockopt(struct sock *sock, int level, int optname, 537 char __user *optval, unsigned int optlen, 538 int (*setsockopt)(struct sock *, int, int, char __user *, unsigned int)) 539 { 540 char __user *koptval = optval; 541 int koptlen = optlen; 542 543 switch (optname) { 544 case MCAST_JOIN_GROUP: 545 case MCAST_LEAVE_GROUP: 546 { 547 struct compat_group_req __user *gr32 = (void *)optval; 548 struct group_req __user *kgr = 549 compat_alloc_user_space(sizeof(struct group_req)); 550 u32 interface; 551 552 if (!access_ok(VERIFY_READ, gr32, sizeof(*gr32)) || 553 !access_ok(VERIFY_WRITE, kgr, sizeof(struct group_req)) || 554 __get_user(interface, &gr32->gr_interface) || 555 __put_user(interface, &kgr->gr_interface) || 556 copy_in_user(&kgr->gr_group, &gr32->gr_group, 557 sizeof(kgr->gr_group))) 558 return -EFAULT; 559 koptval = (char __user *)kgr; 560 koptlen = sizeof(struct group_req); 561 break; 562 } 563 case MCAST_JOIN_SOURCE_GROUP: 564 case MCAST_LEAVE_SOURCE_GROUP: 565 case MCAST_BLOCK_SOURCE: 566 case MCAST_UNBLOCK_SOURCE: 567 { 568 struct compat_group_source_req __user *gsr32 = (void *)optval; 569 struct group_source_req __user *kgsr = compat_alloc_user_space( 570 sizeof(struct group_source_req)); 571 u32 interface; 572 573 if (!access_ok(VERIFY_READ, gsr32, sizeof(*gsr32)) || 574 !access_ok(VERIFY_WRITE, kgsr, 575 sizeof(struct group_source_req)) || 576 __get_user(interface, &gsr32->gsr_interface) || 577 __put_user(interface, &kgsr->gsr_interface) || 578 copy_in_user(&kgsr->gsr_group, &gsr32->gsr_group, 579 sizeof(kgsr->gsr_group)) || 580 copy_in_user(&kgsr->gsr_source, &gsr32->gsr_source, 581 sizeof(kgsr->gsr_source))) 582 return -EFAULT; 583 koptval = (char __user *)kgsr; 584 koptlen = sizeof(struct group_source_req); 585 break; 586 } 587 case MCAST_MSFILTER: 588 { 589 struct compat_group_filter __user *gf32 = (void *)optval; 590 struct group_filter __user *kgf; 591 u32 interface, fmode, numsrc; 592 593 if (!access_ok(VERIFY_READ, gf32, __COMPAT_GF0_SIZE) || 594 __get_user(interface, &gf32->gf_interface) || 595 __get_user(fmode, &gf32->gf_fmode) || 596 __get_user(numsrc, &gf32->gf_numsrc)) 597 return -EFAULT; 598 koptlen = optlen + sizeof(struct group_filter) - 599 sizeof(struct compat_group_filter); 600 if (koptlen < GROUP_FILTER_SIZE(numsrc)) 601 return -EINVAL; 602 kgf = compat_alloc_user_space(koptlen); 603 if (!access_ok(VERIFY_WRITE, kgf, koptlen) || 604 __put_user(interface, &kgf->gf_interface) || 605 __put_user(fmode, &kgf->gf_fmode) || 606 __put_user(numsrc, &kgf->gf_numsrc) || 607 copy_in_user(&kgf->gf_group, &gf32->gf_group, 608 sizeof(kgf->gf_group)) || 609 (numsrc && copy_in_user(kgf->gf_slist, gf32->gf_slist, 610 numsrc * sizeof(kgf->gf_slist[0])))) 611 return -EFAULT; 612 koptval = (char __user *)kgf; 613 break; 614 } 615 616 default: 617 break; 618 } 619 return setsockopt(sock, level, optname, koptval, koptlen); 620 } 621 EXPORT_SYMBOL(compat_mc_setsockopt); 622 623 int compat_mc_getsockopt(struct sock *sock, int level, int optname, 624 char __user *optval, int __user *optlen, 625 int (*getsockopt)(struct sock *, int, int, char __user *, int __user *)) 626 { 627 struct compat_group_filter __user *gf32 = (void *)optval; 628 struct group_filter __user *kgf; 629 int __user *koptlen; 630 u32 interface, fmode, numsrc; 631 int klen, ulen, err; 632 633 if (optname != MCAST_MSFILTER) 634 return getsockopt(sock, level, optname, optval, optlen); 635 636 koptlen = compat_alloc_user_space(sizeof(*koptlen)); 637 if (!access_ok(VERIFY_READ, optlen, sizeof(*optlen)) || 638 __get_user(ulen, optlen)) 639 return -EFAULT; 640 641 /* adjust len for pad */ 642 klen = ulen + sizeof(*kgf) - sizeof(*gf32); 643 644 if (klen < GROUP_FILTER_SIZE(0)) 645 return -EINVAL; 646 647 if (!access_ok(VERIFY_WRITE, koptlen, sizeof(*koptlen)) || 648 __put_user(klen, koptlen)) 649 return -EFAULT; 650 651 /* have to allow space for previous compat_alloc_user_space, too */ 652 kgf = compat_alloc_user_space(klen+sizeof(*optlen)); 653 654 if (!access_ok(VERIFY_READ, gf32, __COMPAT_GF0_SIZE) || 655 __get_user(interface, &gf32->gf_interface) || 656 __get_user(fmode, &gf32->gf_fmode) || 657 __get_user(numsrc, &gf32->gf_numsrc) || 658 __put_user(interface, &kgf->gf_interface) || 659 __put_user(fmode, &kgf->gf_fmode) || 660 __put_user(numsrc, &kgf->gf_numsrc) || 661 copy_in_user(&kgf->gf_group, &gf32->gf_group, sizeof(kgf->gf_group))) 662 return -EFAULT; 663 664 err = getsockopt(sock, level, optname, (char __user *)kgf, koptlen); 665 if (err) 666 return err; 667 668 if (!access_ok(VERIFY_READ, koptlen, sizeof(*koptlen)) || 669 __get_user(klen, koptlen)) 670 return -EFAULT; 671 672 ulen = klen - (sizeof(*kgf)-sizeof(*gf32)); 673 674 if (!access_ok(VERIFY_WRITE, optlen, sizeof(*optlen)) || 675 __put_user(ulen, optlen)) 676 return -EFAULT; 677 678 if (!access_ok(VERIFY_READ, kgf, klen) || 679 !access_ok(VERIFY_WRITE, gf32, ulen) || 680 __get_user(interface, &kgf->gf_interface) || 681 __get_user(fmode, &kgf->gf_fmode) || 682 __get_user(numsrc, &kgf->gf_numsrc) || 683 __put_user(interface, &gf32->gf_interface) || 684 __put_user(fmode, &gf32->gf_fmode) || 685 __put_user(numsrc, &gf32->gf_numsrc)) 686 return -EFAULT; 687 if (numsrc) { 688 int copylen; 689 690 klen -= GROUP_FILTER_SIZE(0); 691 copylen = numsrc * sizeof(gf32->gf_slist[0]); 692 if (copylen > klen) 693 copylen = klen; 694 if (copy_in_user(gf32->gf_slist, kgf->gf_slist, copylen)) 695 return -EFAULT; 696 } 697 return err; 698 } 699 EXPORT_SYMBOL(compat_mc_getsockopt); 700 701 702 /* Argument list sizes for compat_sys_socketcall */ 703 #define AL(x) ((x) * sizeof(u32)) 704 static unsigned char nas[21] = { 705 AL(0), AL(3), AL(3), AL(3), AL(2), AL(3), 706 AL(3), AL(3), AL(4), AL(4), AL(4), AL(6), 707 AL(6), AL(2), AL(5), AL(5), AL(3), AL(3), 708 AL(4), AL(5), AL(4) 709 }; 710 #undef AL 711 712 COMPAT_SYSCALL_DEFINE3(sendmsg, int, fd, struct compat_msghdr __user *, msg, unsigned int, flags) 713 { 714 return __sys_sendmsg(fd, (struct user_msghdr __user *)msg, flags | MSG_CMSG_COMPAT); 715 } 716 717 COMPAT_SYSCALL_DEFINE4(sendmmsg, int, fd, struct compat_mmsghdr __user *, mmsg, 718 unsigned int, vlen, unsigned int, flags) 719 { 720 return __sys_sendmmsg(fd, (struct mmsghdr __user *)mmsg, vlen, 721 flags | MSG_CMSG_COMPAT); 722 } 723 724 COMPAT_SYSCALL_DEFINE3(recvmsg, int, fd, struct compat_msghdr __user *, msg, unsigned int, flags) 725 { 726 return __sys_recvmsg(fd, (struct user_msghdr __user *)msg, flags | MSG_CMSG_COMPAT); 727 } 728 729 COMPAT_SYSCALL_DEFINE4(recv, int, fd, void __user *, buf, compat_size_t, len, unsigned int, flags) 730 { 731 return sys_recv(fd, buf, len, flags | MSG_CMSG_COMPAT); 732 } 733 734 COMPAT_SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, buf, compat_size_t, len, 735 unsigned int, flags, struct sockaddr __user *, addr, 736 int __user *, addrlen) 737 { 738 return sys_recvfrom(fd, buf, len, flags | MSG_CMSG_COMPAT, addr, addrlen); 739 } 740 741 COMPAT_SYSCALL_DEFINE5(recvmmsg, int, fd, struct compat_mmsghdr __user *, mmsg, 742 unsigned int, vlen, unsigned int, flags, 743 struct compat_timespec __user *, timeout) 744 { 745 int datagrams; 746 struct timespec ktspec; 747 748 if (timeout == NULL) 749 return __sys_recvmmsg(fd, (struct mmsghdr __user *)mmsg, vlen, 750 flags | MSG_CMSG_COMPAT, NULL); 751 752 if (compat_get_timespec(&ktspec, timeout)) 753 return -EFAULT; 754 755 datagrams = __sys_recvmmsg(fd, (struct mmsghdr __user *)mmsg, vlen, 756 flags | MSG_CMSG_COMPAT, &ktspec); 757 if (datagrams > 0 && compat_put_timespec(&ktspec, timeout)) 758 datagrams = -EFAULT; 759 760 return datagrams; 761 } 762 763 COMPAT_SYSCALL_DEFINE2(socketcall, int, call, u32 __user *, args) 764 { 765 int ret; 766 u32 a[6]; 767 u32 a0, a1; 768 769 if (call < SYS_SOCKET || call > SYS_SENDMMSG) 770 return -EINVAL; 771 if (copy_from_user(a, args, nas[call])) 772 return -EFAULT; 773 a0 = a[0]; 774 a1 = a[1]; 775 776 switch (call) { 777 case SYS_SOCKET: 778 ret = sys_socket(a0, a1, a[2]); 779 break; 780 case SYS_BIND: 781 ret = sys_bind(a0, compat_ptr(a1), a[2]); 782 break; 783 case SYS_CONNECT: 784 ret = sys_connect(a0, compat_ptr(a1), a[2]); 785 break; 786 case SYS_LISTEN: 787 ret = sys_listen(a0, a1); 788 break; 789 case SYS_ACCEPT: 790 ret = sys_accept4(a0, compat_ptr(a1), compat_ptr(a[2]), 0); 791 break; 792 case SYS_GETSOCKNAME: 793 ret = sys_getsockname(a0, compat_ptr(a1), compat_ptr(a[2])); 794 break; 795 case SYS_GETPEERNAME: 796 ret = sys_getpeername(a0, compat_ptr(a1), compat_ptr(a[2])); 797 break; 798 case SYS_SOCKETPAIR: 799 ret = sys_socketpair(a0, a1, a[2], compat_ptr(a[3])); 800 break; 801 case SYS_SEND: 802 ret = sys_send(a0, compat_ptr(a1), a[2], a[3]); 803 break; 804 case SYS_SENDTO: 805 ret = sys_sendto(a0, compat_ptr(a1), a[2], a[3], compat_ptr(a[4]), a[5]); 806 break; 807 case SYS_RECV: 808 ret = compat_sys_recv(a0, compat_ptr(a1), a[2], a[3]); 809 break; 810 case SYS_RECVFROM: 811 ret = compat_sys_recvfrom(a0, compat_ptr(a1), a[2], a[3], 812 compat_ptr(a[4]), compat_ptr(a[5])); 813 break; 814 case SYS_SHUTDOWN: 815 ret = sys_shutdown(a0, a1); 816 break; 817 case SYS_SETSOCKOPT: 818 ret = compat_sys_setsockopt(a0, a1, a[2], 819 compat_ptr(a[3]), a[4]); 820 break; 821 case SYS_GETSOCKOPT: 822 ret = compat_sys_getsockopt(a0, a1, a[2], 823 compat_ptr(a[3]), compat_ptr(a[4])); 824 break; 825 case SYS_SENDMSG: 826 ret = compat_sys_sendmsg(a0, compat_ptr(a1), a[2]); 827 break; 828 case SYS_SENDMMSG: 829 ret = compat_sys_sendmmsg(a0, compat_ptr(a1), a[2], a[3]); 830 break; 831 case SYS_RECVMSG: 832 ret = compat_sys_recvmsg(a0, compat_ptr(a1), a[2]); 833 break; 834 case SYS_RECVMMSG: 835 ret = compat_sys_recvmmsg(a0, compat_ptr(a1), a[2], a[3], 836 compat_ptr(a[4])); 837 break; 838 case SYS_ACCEPT4: 839 ret = sys_accept4(a0, compat_ptr(a1), compat_ptr(a[2]), a[3]); 840 break; 841 default: 842 ret = -EINVAL; 843 break; 844 } 845 return ret; 846 } 847