diff --git a/net/compat.c b/net/compat.c index ec24d9e..1a6fcb1 100644 --- a/net/compat.c +++ b/net/compat.c @@ -213,6 +213,7 @@ Efault: sock_kfree_s(sk, kcmsg_base, kcmlen); return err; } +EXPORT_SYMBOL(cmsghdr_from_user_compat_to_kern); int put_cmsg_compat(struct msghdr *kmsg, int level, int type, int len, void *data) { diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index 33f60fc..3907ce4 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c @@ -422,6 +422,11 @@ sticky_done: struct msghdr msg; struct flowi fl; int junk; +#if 1 + int compat_alloc = optlen; +#else + int compat_alloc = 0; +#endif fl.fl6_flowlabel = 0; fl.oif = sk->sk_bound_dev_if; @@ -436,13 +441,29 @@ sticky_done: retv = -EINVAL; if (optlen > 64*1024) break; - - opt = sock_kmalloc(sk, sizeof(*opt) + optlen, GFP_KERNEL); + opt = sock_kmalloc(sk, sizeof(*opt) + optlen + compat_alloc, + GFP_KERNEL); retv = -ENOBUFS; if (opt == NULL) break; memset(opt, 0, sizeof(*opt)); +#if 1 + msg.msg_controllen = optlen; + msg.msg_control = optval; + retv = cmsghdr_from_user_compat_to_kern(&msg, sk, (void*)(opt+1), + optlen + compat_alloc ); + + printk( KERN_ERR "Cmsghdr conver ret %d len from %d to %d\n", + retv, (int)optlen, (int)msg.msg_controllen ); + if (retv) + goto done; + if ( msg.msg_control != (opt+1) ){ + printk( KERN_ERR "cmsg realloc issue???" ); + /*Screwed*/ + } + opt->tot_len = sizeof(*opt) + msg.msg_controllen; +#else opt->tot_len = sizeof(*opt) + optlen; retv = -EFAULT; if (copy_from_user(opt+1, optval, optlen)) @@ -450,6 +471,7 @@ sticky_done: msg.msg_controllen = optlen; msg.msg_control = (void*)(opt+1); +#endif retv = datagram_send_ctl(net, &msg, &fl, opt, &junk, &junk); if (retv)