From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1MHFxF-0001bn-VP for qemu-devel@nongnu.org; Thu, 18 Jun 2009 07:38:54 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1MHFxE-0001bL-OU for qemu-devel@nongnu.org; Thu, 18 Jun 2009 07:38:53 -0400 Received: from [199.232.76.173] (port=58853 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1MHFxE-0001bF-JJ for qemu-devel@nongnu.org; Thu, 18 Jun 2009 07:38:52 -0400 Received: from lechat.rtp-net.org ([88.191.19.38]:43494) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1MHFxD-0004Fa-Do for qemu-devel@nongnu.org; Thu, 18 Jun 2009 07:38:52 -0400 Received: from lechat.rtp-net.org (localhost [127.0.0.1]) by lechat.rtp-net.org (Postfix) with ESMTP id 44F1110086 for ; Thu, 18 Jun 2009 13:43:38 +0200 (CEST) From: Arnaud Patard (Rtp) Date: Thu, 18 Jun 2009 13:43:38 +0200 Message-ID: <87ocslsr6d.fsf@lechat.rtp-net.org> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Subject: [Qemu-devel] [PATCH] linux-user/syscall: check some parameters for some socket syscalls. List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org --=-=-= 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 --=-=-= Content-Type: text/x-diff Content-Disposition: inline; filename=net_syscall_parameters_check.patch 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)); --=-=-=--