Commit 8f7aeaf6b38fc0d4c8c3eb9292ae250579437724
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 { |