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