All of lore.kernel.org
 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 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.