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 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 1146 /* do_bind() Must return target values and target errnos. */
1144 1147 static abi_long do_bind(int sockfd, abi_ulong target_addr,
1145 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 1157 target_to_host_sockaddr(addr, target_addr, addrlen);
1150 1158 return get_errno(bind(sockfd, addr, addrlen));
... ... @@ -1154,7 +1162,12 @@ static abi_long do_bind(int sockfd, abi_ulong target_addr,
1154 1162 static abi_long do_connect(int sockfd, abi_ulong target_addr,
1155 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 1172 target_to_host_sockaddr(addr, target_addr, addrlen);
1160 1173 return get_errno(connect(sockfd, addr, addrlen));
... ... @@ -1226,6 +1239,9 @@ static abi_long do_accept(int fd, abi_ulong target_addr,
1226 1239 if (get_user_u32(addrlen, target_addrlen_addr))
1227 1240 return -TARGET_EFAULT;
1228 1241  
  1242 + if (addrlen < 0 || addrlen > MAX_SOCK_ADDR)
  1243 + return -TARGET_EINVAL;
  1244 +
1229 1245 addr = alloca(addrlen);
1230 1246  
1231 1247 ret = get_errno(accept(fd, addr, &addrlen));
... ... @@ -1248,6 +1264,9 @@ static abi_long do_getpeername(int fd, abi_ulong target_addr,
1248 1264 if (get_user_u32(addrlen, target_addrlen_addr))
1249 1265 return -TARGET_EFAULT;
1250 1266  
  1267 + if (addrlen < 0 || addrlen > MAX_SOCK_ADDR)
  1268 + return -TARGET_EINVAL;
  1269 +
1251 1270 addr = alloca(addrlen);
1252 1271  
1253 1272 ret = get_errno(getpeername(fd, addr, &addrlen));
... ... @@ -1273,6 +1292,9 @@ static abi_long do_getsockname(int fd, abi_ulong target_addr,
1273 1292 if (get_user_u32(addrlen, target_addrlen_addr))
1274 1293 return -TARGET_EFAULT;
1275 1294  
  1295 + if (addrlen < 0 || addrlen > MAX_SOCK_ADDR)
  1296 + return -TARGET_EINVAL;
  1297 +
1276 1298 addr = alloca(addrlen);
1277 1299  
1278 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 1330 void *host_msg;
1309 1331 abi_long ret;
1310 1332  
  1333 + if (addrlen < 0 || addrlen > MAX_SOCK_ADDR)
  1334 + return -TARGET_EINVAL;
  1335 +
1311 1336 host_msg = lock_user(VERIFY_READ, msg, len, 1);
1312 1337 if (!host_msg)
1313 1338 return -TARGET_EFAULT;
... ... @@ -1340,6 +1365,10 @@ static abi_long do_recvfrom(int fd, abi_ulong msg, size_t len, int flags,
1340 1365 ret = -TARGET_EFAULT;
1341 1366 goto fail;
1342 1367 }
  1368 + if (addrlen < 0 || addrlen > MAX_SOCK_ADDR) {
  1369 + ret = -TARGET_EINVAL;
  1370 + goto fail;
  1371 + }
1343 1372 addr = alloca(addrlen);
1344 1373 ret = get_errno(recvfrom(fd, host_msg, len, flags, addr, &addrlen));
1345 1374 } else {
... ...