qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH] linux-user/syscall: check some parameters for some socket syscalls.
@ 2009-06-18 11:43 Arnaud Patard
  0 siblings, 0 replies; only message in thread
From: Arnaud Patard @ 2009-06-18 11:43 UTC (permalink / raw)
  To: qemu-devel

[-- Attachment #1: Type: text/plain, Size: 527 bytes --]


This patch is fixing following issues :

- commit 8fea36025b9d6d360ff3b78f88a84ccf221807e8 was applied to
  do_getsockname instead of do_accept.
- Some syscalls were not checking properly the memory addresses passed
  as argument
- Add check before syscalls made for cases like do_getpeername() where
  we're using the address parameter after doing the syscall
- Fix do_accept to return EINVAL instead of EFAULT when parameters
  invalid to match with linux behaviour

Signed-off-by: Arnaud Patard <arnaud.patard@rtp-net.org>

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: net_syscall_parameters_check.patch --]
[-- Type: text/x-diff, Size: 3505 bytes --]

Index: qemu/linux-user/syscall.c
===================================================================
--- qemu.orig/linux-user/syscall.c
+++ qemu/linux-user/syscall.c
@@ -1499,13 +1499,17 @@ static abi_long do_bind(int sockfd, abi_
                         socklen_t addrlen)
 {
     void *addr;
+    abi_long ret;
 
     if (addrlen < 0)
         return -TARGET_EINVAL;
 
     addr = alloca(addrlen+1);
 
-    target_to_host_sockaddr(addr, target_addr, addrlen);
+    ret = target_to_host_sockaddr(addr, target_addr, addrlen);
+    if (ret)
+	    return ret;
+
     return get_errno(bind(sockfd, addr, addrlen));
 }
 
@@ -1514,13 +1518,17 @@ static abi_long do_connect(int sockfd, a
                            socklen_t addrlen)
 {
     void *addr;
+    abi_long ret;
 
     if (addrlen < 0)
         return -TARGET_EINVAL;
 
     addr = alloca(addrlen);
 
-    target_to_host_sockaddr(addr, target_addr, addrlen);
+    ret = target_to_host_sockaddr(addr, target_addr, addrlen);
+    if (ret)
+	    return ret;
+
     return get_errno(connect(sockfd, addr, addrlen));
 }
 
@@ -1544,8 +1552,12 @@ static abi_long do_sendrecvmsg(int fd, a
     if (msgp->msg_name) {
         msg.msg_namelen = tswap32(msgp->msg_namelen);
         msg.msg_name = alloca(msg.msg_namelen);
-        target_to_host_sockaddr(msg.msg_name, tswapl(msgp->msg_name),
+        ret = target_to_host_sockaddr(msg.msg_name, tswapl(msgp->msg_name),
                                 msg.msg_namelen);
+	if (ret) {
+		unlock_user_struct(msgp, target_msg, send ? 0 : 1);
+		return ret;
+	}
     } else {
         msg.msg_name = NULL;
         msg.msg_namelen = 0;
@@ -1587,12 +1599,19 @@ static abi_long do_accept(int fd, abi_ul
     void *addr;
     abi_long ret;
 
+    if (target_addr == 0)
+       return get_errno(accept(fd, NULL, NULL));
+
+    /* linux returns EINVAL if addrlen pointer is invalid */
     if (get_user_u32(addrlen, target_addrlen_addr))
-        return -TARGET_EFAULT;
+        return -TARGET_EINVAL;
 
     if (addrlen < 0)
         return -TARGET_EINVAL;
 
+    if (!access_ok(VERIFY_WRITE, target_addr, addrlen))
+	    return -TARGET_EINVAL;
+
     addr = alloca(addrlen);
 
     ret = get_errno(accept(fd, addr, &addrlen));
@@ -1618,6 +1637,9 @@ static abi_long do_getpeername(int fd, a
     if (addrlen < 0)
         return -TARGET_EINVAL;
 
+    if (!access_ok(VERIFY_WRITE, target_addr, addrlen))
+	    return -TARGET_EFAULT;
+
     addr = alloca(addrlen);
 
     ret = get_errno(getpeername(fd, addr, &addrlen));
@@ -1637,15 +1659,15 @@ static abi_long do_getsockname(int fd, a
     void *addr;
     abi_long ret;
 
-    if (target_addr == 0)
-       return get_errno(accept(fd, NULL, NULL));
-
     if (get_user_u32(addrlen, target_addrlen_addr))
         return -TARGET_EFAULT;
 
     if (addrlen < 0)
         return -TARGET_EINVAL;
 
+    if (!access_ok(VERIFY_WRITE, target_addr, addrlen))
+	    return -TARGET_EFAULT;
+
     addr = alloca(addrlen);
 
     ret = get_errno(getsockname(fd, addr, &addrlen));
@@ -1689,7 +1711,11 @@ static abi_long do_sendto(int fd, abi_ul
         return -TARGET_EFAULT;
     if (target_addr) {
         addr = alloca(addrlen);
-        target_to_host_sockaddr(addr, target_addr, addrlen);
+        ret = target_to_host_sockaddr(addr, target_addr, addrlen);
+	if (ret) {
+		unlock_user(host_msg, msg, 0);
+		return ret;
+	}
         ret = get_errno(sendto(fd, host_msg, len, flags, addr, addrlen));
     } else {
         ret = get_errno(send(fd, host_msg, len, flags));

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2009-06-18 11:38 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-06-18 11:43 [Qemu-devel] [PATCH] linux-user/syscall: check some parameters for some socket syscalls Arnaud Patard

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).