Commit 8f7aeaf6b38fc0d4c8c3eb9292ae250579437724

Authored by aurel32
1 parent 8fea3602

linux-user: return EINVAL on incorrect sockaddr

From: Lauro Ramos Venancio <lauro.venancio@gmail.com>

Fixes ltp test accept01

Signed-off-by: Riku Voipio <riku.voipio@iki.fi>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6479 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 31 additions and 2 deletions
linux-user/syscall.c
@@ -1140,11 +1140,19 @@ static abi_long do_socket(int domain, int type, int protocol) @@ -1140,11 +1140,19 @@ static abi_long do_socket(int domain, int type, int protocol)
1140 return get_errno(socket(domain, type, protocol)); 1140 return get_errno(socket(domain, type, protocol));
1141 } 1141 }
1142 1142
  1143 +/* MAX_SOCK_ADDR from linux/net/socket.c */
  1144 +#define MAX_SOCK_ADDR 128
  1145 +
1143 /* do_bind() Must return target values and target errnos. */ 1146 /* do_bind() Must return target values and target errnos. */
1144 static abi_long do_bind(int sockfd, abi_ulong target_addr, 1147 static abi_long do_bind(int sockfd, abi_ulong target_addr,
1145 socklen_t addrlen) 1148 socklen_t addrlen)
1146 { 1149 {
1147 - void *addr = alloca(addrlen); 1150 + void *addr;
  1151 +
  1152 + if (addrlen < 0 || addrlen > MAX_SOCK_ADDR)
  1153 + return -TARGET_EINVAL;
  1154 +
  1155 + addr = alloca(addrlen);
1148 1156
1149 target_to_host_sockaddr(addr, target_addr, addrlen); 1157 target_to_host_sockaddr(addr, target_addr, addrlen);
1150 return get_errno(bind(sockfd, addr, addrlen)); 1158 return get_errno(bind(sockfd, addr, addrlen));
@@ -1154,7 +1162,12 @@ static abi_long do_bind(int sockfd, abi_ulong target_addr, @@ -1154,7 +1162,12 @@ static abi_long do_bind(int sockfd, abi_ulong target_addr,
1154 static abi_long do_connect(int sockfd, abi_ulong target_addr, 1162 static abi_long do_connect(int sockfd, abi_ulong target_addr,
1155 socklen_t addrlen) 1163 socklen_t addrlen)
1156 { 1164 {
1157 - void *addr = alloca(addrlen); 1165 + void *addr;
  1166 +
  1167 + if (addrlen < 0 || addrlen > MAX_SOCK_ADDR)
  1168 + return -TARGET_EINVAL;
  1169 +
  1170 + addr = alloca(addrlen);
1158 1171
1159 target_to_host_sockaddr(addr, target_addr, addrlen); 1172 target_to_host_sockaddr(addr, target_addr, addrlen);
1160 return get_errno(connect(sockfd, addr, addrlen)); 1173 return get_errno(connect(sockfd, addr, addrlen));
@@ -1226,6 +1239,9 @@ static abi_long do_accept(int fd, abi_ulong target_addr, @@ -1226,6 +1239,9 @@ static abi_long do_accept(int fd, abi_ulong target_addr,
1226 if (get_user_u32(addrlen, target_addrlen_addr)) 1239 if (get_user_u32(addrlen, target_addrlen_addr))
1227 return -TARGET_EFAULT; 1240 return -TARGET_EFAULT;
1228 1241
  1242 + if (addrlen < 0 || addrlen > MAX_SOCK_ADDR)
  1243 + return -TARGET_EINVAL;
  1244 +
1229 addr = alloca(addrlen); 1245 addr = alloca(addrlen);
1230 1246
1231 ret = get_errno(accept(fd, addr, &addrlen)); 1247 ret = get_errno(accept(fd, addr, &addrlen));
@@ -1248,6 +1264,9 @@ static abi_long do_getpeername(int fd, abi_ulong target_addr, @@ -1248,6 +1264,9 @@ static abi_long do_getpeername(int fd, abi_ulong target_addr,
1248 if (get_user_u32(addrlen, target_addrlen_addr)) 1264 if (get_user_u32(addrlen, target_addrlen_addr))
1249 return -TARGET_EFAULT; 1265 return -TARGET_EFAULT;
1250 1266
  1267 + if (addrlen < 0 || addrlen > MAX_SOCK_ADDR)
  1268 + return -TARGET_EINVAL;
  1269 +
1251 addr = alloca(addrlen); 1270 addr = alloca(addrlen);
1252 1271
1253 ret = get_errno(getpeername(fd, addr, &addrlen)); 1272 ret = get_errno(getpeername(fd, addr, &addrlen));
@@ -1273,6 +1292,9 @@ static abi_long do_getsockname(int fd, abi_ulong target_addr, @@ -1273,6 +1292,9 @@ static abi_long do_getsockname(int fd, abi_ulong target_addr,
1273 if (get_user_u32(addrlen, target_addrlen_addr)) 1292 if (get_user_u32(addrlen, target_addrlen_addr))
1274 return -TARGET_EFAULT; 1293 return -TARGET_EFAULT;
1275 1294
  1295 + if (addrlen < 0 || addrlen > MAX_SOCK_ADDR)
  1296 + return -TARGET_EINVAL;
  1297 +
1276 addr = alloca(addrlen); 1298 addr = alloca(addrlen);
1277 1299
1278 ret = get_errno(getsockname(fd, addr, &addrlen)); 1300 ret = get_errno(getsockname(fd, addr, &addrlen));
@@ -1308,6 +1330,9 @@ static abi_long do_sendto(int fd, abi_ulong msg, size_t len, int flags, @@ -1308,6 +1330,9 @@ static abi_long do_sendto(int fd, abi_ulong msg, size_t len, int flags,
1308 void *host_msg; 1330 void *host_msg;
1309 abi_long ret; 1331 abi_long ret;
1310 1332
  1333 + if (addrlen < 0 || addrlen > MAX_SOCK_ADDR)
  1334 + return -TARGET_EINVAL;
  1335 +
1311 host_msg = lock_user(VERIFY_READ, msg, len, 1); 1336 host_msg = lock_user(VERIFY_READ, msg, len, 1);
1312 if (!host_msg) 1337 if (!host_msg)
1313 return -TARGET_EFAULT; 1338 return -TARGET_EFAULT;
@@ -1340,6 +1365,10 @@ static abi_long do_recvfrom(int fd, abi_ulong msg, size_t len, int flags, @@ -1340,6 +1365,10 @@ static abi_long do_recvfrom(int fd, abi_ulong msg, size_t len, int flags,
1340 ret = -TARGET_EFAULT; 1365 ret = -TARGET_EFAULT;
1341 goto fail; 1366 goto fail;
1342 } 1367 }
  1368 + if (addrlen < 0 || addrlen > MAX_SOCK_ADDR) {
  1369 + ret = -TARGET_EINVAL;
  1370 + goto fail;
  1371 + }
1343 addr = alloca(addrlen); 1372 addr = alloca(addrlen);
1344 ret = get_errno(recvfrom(fd, host_msg, len, flags, addr, &addrlen)); 1373 ret = get_errno(recvfrom(fd, host_msg, len, flags, addr, &addrlen));
1345 } else { 1374 } else {