summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaszlo Valko <valko@linux.karinthy.hu>2003-01-15 07:25:42 -0800
committerDavid S. Miller <davem@nuts.ninka.net>2003-01-15 07:25:42 -0800
commitd142cd23328e4357d2748cf059ff38511334963f (patch)
treee7ac3258f52ca7f8d9a6956cc8e2374518978163
parentbb36f487c7943955c73bac7380093deaf7262e76 (diff)
[SPARC64]: Handle SO_TIMESTAMP properly in compat recvmsg.
-rw-r--r--arch/sparc64/kernel/sys_sparc32.c25
1 files changed, 21 insertions, 4 deletions
diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c
index 8b51679f8430..1dd8bebcda4e 100644
--- a/arch/sparc64/kernel/sys_sparc32.c
+++ b/arch/sparc64/kernel/sys_sparc32.c
@@ -2298,10 +2298,27 @@ static void cmsg32_recvmsg_fixup(struct msghdr *kmsg, unsigned long orig_cmsg_up
__get_user(kcmsg32->cmsg_type, &ucmsg->cmsg_type);
clen64 = kcmsg32->cmsg_len;
- copy_from_user(CMSG32_DATA(kcmsg32), CMSG_DATA(ucmsg),
- clen64 - CMSG_ALIGN(sizeof(*ucmsg)));
- clen32 = ((clen64 - CMSG_ALIGN(sizeof(*ucmsg))) +
- CMSG32_ALIGN(sizeof(struct cmsghdr32)));
+ if (kcmsg32->cmsg_level == SOL_SOCKET &&
+ kcmsg32->cmsg_type == SO_TIMESTAMP) {
+ struct timeval tv;
+ struct compat_timeval *tv32;
+
+ if (clen64 != CMSG_LEN(sizeof(struct timeval))) {
+ kfree(workbuf);
+ goto fail;
+ }
+ copy_from_user(&tv, CMSG_DATA(ucmsg), sizeof(tv));
+ tv32 = (struct compat_timeval *) CMSG32_DATA(kcmsg32);
+ tv32->tv_sec = tv.tv_sec;
+ tv32->tv_usec = tv.tv_usec;
+ clen32 = sizeof(*tv32) +
+ CMSG32_ALIGN(sizeof(struct cmsghdr32));
+ } else {
+ copy_from_user(CMSG32_DATA(kcmsg32), CMSG_DATA(ucmsg),
+ clen64 - CMSG_ALIGN(sizeof(*ucmsg)));
+ clen32 = ((clen64 - CMSG_ALIGN(sizeof(*ucmsg))) +
+ CMSG32_ALIGN(sizeof(struct cmsghdr32)));
+ }
kcmsg32->cmsg_len = clen32;
ucmsg = (struct cmsghdr *) (((char *)ucmsg) + CMSG_ALIGN(clen64));