* setsockopt with cmsghdr needs COMPAT support?
@ 2010-04-22 4:45 Andrew May
0 siblings, 0 replies; only message in thread
From: Andrew May @ 2010-04-22 4:45 UTC (permalink / raw)
To: netdev; +Cc: Florian Westphal
[-- Attachment #1: Type: text/plain, Size: 895 bytes --]
I have a userspace app that is doing an IPv6 IPV6_2292PKTOPTIONS
setsockopt to add an Extension header in a mixed 64 bit/32 bit setup.
It is failing with an EINVAL because it seems the cmsghdr doesn't get
the proper fixup.
This isn't stuff I really look at much but I came up with this hack to
at least get past the error. All my userspace is 32 bits so I just
put in the "#if 1" rather than attempting a runtime check on the socket.
I am not sure if the userspace app is doing something wrong, but it
seems like this is a real problem. The "on the stack" assumption by
the fixup helper seems like it really should be reworked, but I have no
idea how it should be done. And I didn't bother to handle the the
getsockopt function.
Doing a grep I didn't find any other offenders, but I can't say for
sure.
Does anyone have any ideas on the "right" way to fix this, or point out
my flaw?
Thanks.
[-- Attachment #2: compat.patch --]
[-- Type: text/x-patch, Size: 1821 bytes --]
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)
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2010-04-22 6:03 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-04-22 4:45 setsockopt with cmsghdr needs COMPAT support? Andrew May
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.