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