]> git.neil.brown.name Git - history.git/commitdiff
[COMPAT]: Fix MSG_CMSG_COMPAT flag passing, kill cmsg_compat_recvmsg_fixup.
authorRandolph Chung <randolph@tausq.org>
Sun, 30 Mar 2003 21:19:33 +0000 (13:19 -0800)
committerDavid S. Miller <davem@nuts.ninka.net>
Sun, 30 Mar 2003 21:19:33 +0000 (13:19 -0800)
include/net/compat.h
net/compat.c
net/socket.c

index 890bd4c03daa3d44f5457f038d88c08a492edb80..2a72d0cbfd149054ff4db25ce7a1e1eb2c7543d4 100644 (file)
@@ -33,8 +33,6 @@ extern asmlinkage long compat_sys_sendmsg(int,struct compat_msghdr *,unsigned);
 extern asmlinkage long compat_sys_recvmsg(int,struct compat_msghdr *,unsigned);
 extern asmlinkage long compat_sys_getsockopt(int, int, int, char *, int *);
 extern int put_cmsg_compat(struct msghdr*, int, int, int, void *);
-extern int put_compat_msg_controllen(struct msghdr *, struct compat_msghdr *,
-               unsigned long);
 extern int cmsghdr_from_user_compat_to_kern(struct msghdr *, unsigned char *,
                int);
 
index 45691f12a0c378f9e8ff8b915ff439f1e5845f3b..f4f8a1c34a1b525599bfa4f9a5552579b7607b44 100644 (file)
@@ -296,108 +296,6 @@ void scm_detach_fds_compat(struct msghdr *kmsg, struct scm_cookie *scm)
        __scm_destroy(scm);
 }
 
-/* In these cases we (currently) can just copy to data over verbatim
- * because all CMSGs created by the kernel have well defined types which
- * have the same layout in both the 32-bit and 64-bit API.  One must add
- * some special cased conversions here if we start sending control messages
- * with incompatible types.
- *
- * SCM_RIGHTS and SCM_CREDENTIALS are done by hand in recvmsg_compat right after
- * we do our work.  The remaining cases are:
- *
- * SOL_IP      IP_PKTINFO      struct in_pktinfo       32-bit clean
- *             IP_TTL          int                     32-bit clean
- *             IP_TOS          __u8                    32-bit clean
- *             IP_RECVOPTS     variable length         32-bit clean
- *             IP_RETOPTS      variable length         32-bit clean
- *             (these last two are clean because the types are defined
- *              by the IPv4 protocol)
- *             IP_RECVERR      struct sock_extended_err +
- *                             struct sockaddr_in      32-bit clean
- * SOL_IPV6    IPV6_RECVERR    struct sock_extended_err +
- *                             struct sockaddr_in6     32-bit clean
- *             IPV6_PKTINFO    struct in6_pktinfo      32-bit clean
- *             IPV6_HOPLIMIT   int                     32-bit clean
- *             IPV6_FLOWINFO   u32                     32-bit clean
- *             IPV6_HOPOPTS    ipv6 hop exthdr         32-bit clean
- *             IPV6_DSTOPTS    ipv6 dst exthdr(s)      32-bit clean
- *             IPV6_RTHDR      ipv6 routing exthdr     32-bit clean
- *             IPV6_AUTHHDR    ipv6 auth exthdr        32-bit clean
- */
-static void cmsg_compat_recvmsg_fixup(struct msghdr *kmsg, unsigned long orig_cmsg_uptr)
-{
-       unsigned char *workbuf, *wp;
-       unsigned long bufsz, space_avail;
-       struct cmsghdr *ucmsg;
-
-       bufsz = ((unsigned long)kmsg->msg_control) - orig_cmsg_uptr;
-       space_avail = kmsg->msg_controllen + bufsz;
-       wp = workbuf = kmalloc(bufsz, GFP_KERNEL);
-       if(workbuf == NULL)
-               goto fail;
-
-       /* To make this more sane we assume the kernel sends back properly
-        * formatted control messages.  Because of how the kernel will truncate
-        * the cmsg_len for MSG_TRUNC cases, we need not check that case either.
-        */
-       ucmsg = (struct cmsghdr *) orig_cmsg_uptr;
-       while(((unsigned long)ucmsg) <=
-             (((unsigned long)kmsg->msg_control) - sizeof(struct cmsghdr))) {
-               struct compat_cmsghdr *kcmsg_compat = (struct compat_cmsghdr *) wp;
-               int clen64, clen32;
-
-               /* UCMSG is the 64-bit format CMSG entry in user-space.
-                * KCMSG_COMPAT is within the kernel space temporary buffer
-                * we use to convert into a 32-bit style CMSG.
-                */
-               __get_user(kcmsg_compat->cmsg_len, &ucmsg->cmsg_len);
-               __get_user(kcmsg_compat->cmsg_level, &ucmsg->cmsg_level);
-               __get_user(kcmsg_compat->cmsg_type, &ucmsg->cmsg_type);
-
-               clen64 = kcmsg_compat->cmsg_len;
-               copy_from_user(CMSG_COMPAT_DATA(kcmsg_compat), CMSG_DATA(ucmsg),
-                              clen64 - CMSG_ALIGN(sizeof(*ucmsg)));
-               clen32 = ((clen64 - CMSG_ALIGN(sizeof(*ucmsg))) +
-                         CMSG_COMPAT_ALIGN(sizeof(struct compat_cmsghdr)));
-               kcmsg_compat->cmsg_len = clen32;
-
-               ucmsg = (struct cmsghdr *) (((char *)ucmsg) + CMSG_ALIGN(clen64));
-               wp = (((char *)kcmsg_compat) + CMSG_COMPAT_ALIGN(clen32));
-       }
-
-       /* Copy back fixed up data, and adjust pointers. */
-       bufsz = (wp - workbuf);
-       copy_to_user((void *)orig_cmsg_uptr, workbuf, bufsz);
-
-       kmsg->msg_control = (struct cmsghdr *)
-               (((char *)orig_cmsg_uptr) + bufsz);
-       kmsg->msg_controllen = space_avail - bufsz;
-
-       kfree(workbuf);
-       return;
-
-fail:
-       /* If we leave the 64-bit format CMSG chunks in there,
-        * the application could get confused and crash.  So to
-        * ensure greater recovery, we report no CMSGs.
-        */
-       kmsg->msg_controllen += bufsz;
-       kmsg->msg_control = (void *) orig_cmsg_uptr;
-}
-
-int put_compat_msg_controllen(struct msghdr *msg_sys,
-               struct compat_msghdr *msg_compat, unsigned long cmsg_ptr)
-{
-       unsigned long ucmsg_ptr;
-       compat_size_t uclen;
-
-       if ((unsigned long)msg_sys->msg_control != cmsg_ptr)
-               cmsg_compat_recvmsg_fixup(msg_sys, cmsg_ptr);
-       ucmsg_ptr = ((unsigned long)msg_sys->msg_control);
-       uclen = (compat_size_t) (ucmsg_ptr - cmsg_ptr);
-       return __put_user(uclen, &msg_compat->msg_controllen);
-}
-
 extern asmlinkage long sys_setsockopt(int fd, int level, int optname,
                                     char *optval, int optlen);
 
index 46af89b878ff01ac79c56a07e0fbf74089f34a45..02e380a96a099c3273c6b51db64420a6343b0638 100644 (file)
@@ -1692,6 +1692,8 @@ asmlinkage long sys_recvmsg(int fd, struct msghdr *msg, unsigned int flags)
 
        cmsg_ptr = (unsigned long)msg_sys.msg_control;
        msg_sys.msg_flags = 0;
+       if (MSG_CMSG_COMPAT & flags)
+               msg_sys.msg_flags = MSG_CMSG_COMPAT;
        
        if (sock->file->f_flags & O_NONBLOCK)
                flags |= MSG_DONTWAIT;
@@ -1709,7 +1711,8 @@ asmlinkage long sys_recvmsg(int fd, struct msghdr *msg, unsigned int flags)
        if (err)
                goto out_freeiov;
        if (MSG_CMSG_COMPAT & flags)
-               err = put_compat_msg_controllen(&msg_sys, msg_compat, cmsg_ptr);
+               err = __put_user((unsigned long)msg_sys.msg_control-cmsg_ptr, 
+                                &msg_compat->msg_controllen);
        else
                err = __put_user((unsigned long)msg_sys.msg_control-cmsg_ptr, 
                                 &msg->msg_controllen);