diff options
Diffstat (limited to 'net/socket.c')
-rw-r--r-- | net/socket.c | 110 |
1 files changed, 44 insertions, 66 deletions
diff --git a/net/socket.c b/net/socket.c index 42d8e9c9ccd5..05f361faec45 100644 --- a/net/socket.c +++ b/net/socket.c | |||
@@ -406,8 +406,10 @@ struct file *sock_alloc_file(struct socket *sock, int flags, const char *dname) | |||
406 | name.len = strlen(name.name); | 406 | name.len = strlen(name.name); |
407 | } | 407 | } |
408 | path.dentry = d_alloc_pseudo(sock_mnt->mnt_sb, &name); | 408 | path.dentry = d_alloc_pseudo(sock_mnt->mnt_sb, &name); |
409 | if (unlikely(!path.dentry)) | 409 | if (unlikely(!path.dentry)) { |
410 | sock_release(sock); | ||
410 | return ERR_PTR(-ENOMEM); | 411 | return ERR_PTR(-ENOMEM); |
412 | } | ||
411 | path.mnt = mntget(sock_mnt); | 413 | path.mnt = mntget(sock_mnt); |
412 | 414 | ||
413 | d_instantiate(path.dentry, SOCK_INODE(sock)); | 415 | d_instantiate(path.dentry, SOCK_INODE(sock)); |
@@ -415,9 +417,11 @@ struct file *sock_alloc_file(struct socket *sock, int flags, const char *dname) | |||
415 | file = alloc_file(&path, FMODE_READ | FMODE_WRITE, | 417 | file = alloc_file(&path, FMODE_READ | FMODE_WRITE, |
416 | &socket_file_ops); | 418 | &socket_file_ops); |
417 | if (IS_ERR(file)) { | 419 | if (IS_ERR(file)) { |
418 | /* drop dentry, keep inode */ | 420 | /* drop dentry, keep inode for a bit */ |
419 | ihold(d_inode(path.dentry)); | 421 | ihold(d_inode(path.dentry)); |
420 | path_put(&path); | 422 | path_put(&path); |
423 | /* ... and now kill it properly */ | ||
424 | sock_release(sock); | ||
421 | return file; | 425 | return file; |
422 | } | 426 | } |
423 | 427 | ||
@@ -1330,19 +1334,9 @@ SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol) | |||
1330 | 1334 | ||
1331 | retval = sock_create(family, type, protocol, &sock); | 1335 | retval = sock_create(family, type, protocol, &sock); |
1332 | if (retval < 0) | 1336 | if (retval < 0) |
1333 | goto out; | 1337 | return retval; |
1334 | |||
1335 | retval = sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK)); | ||
1336 | if (retval < 0) | ||
1337 | goto out_release; | ||
1338 | |||
1339 | out: | ||
1340 | /* It may be already another descriptor 8) Not kernel problem. */ | ||
1341 | return retval; | ||
1342 | 1338 | ||
1343 | out_release: | 1339 | return sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK)); |
1344 | sock_release(sock); | ||
1345 | return retval; | ||
1346 | } | 1340 | } |
1347 | 1341 | ||
1348 | /* | 1342 | /* |
@@ -1366,87 +1360,72 @@ SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol, | |||
1366 | flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK; | 1360 | flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK; |
1367 | 1361 | ||
1368 | /* | 1362 | /* |
1363 | * reserve descriptors and make sure we won't fail | ||
1364 | * to return them to userland. | ||
1365 | */ | ||
1366 | fd1 = get_unused_fd_flags(flags); | ||
1367 | if (unlikely(fd1 < 0)) | ||
1368 | return fd1; | ||
1369 | |||
1370 | fd2 = get_unused_fd_flags(flags); | ||
1371 | if (unlikely(fd2 < 0)) { | ||
1372 | put_unused_fd(fd1); | ||
1373 | return fd2; | ||
1374 | } | ||
1375 | |||
1376 | err = put_user(fd1, &usockvec[0]); | ||
1377 | if (err) | ||
1378 | goto out; | ||
1379 | |||
1380 | err = put_user(fd2, &usockvec[1]); | ||
1381 | if (err) | ||
1382 | goto out; | ||
1383 | |||
1384 | /* | ||
1369 | * Obtain the first socket and check if the underlying protocol | 1385 | * Obtain the first socket and check if the underlying protocol |
1370 | * supports the socketpair call. | 1386 | * supports the socketpair call. |
1371 | */ | 1387 | */ |
1372 | 1388 | ||
1373 | err = sock_create(family, type, protocol, &sock1); | 1389 | err = sock_create(family, type, protocol, &sock1); |
1374 | if (err < 0) | 1390 | if (unlikely(err < 0)) |
1375 | goto out; | 1391 | goto out; |
1376 | 1392 | ||
1377 | err = sock_create(family, type, protocol, &sock2); | 1393 | err = sock_create(family, type, protocol, &sock2); |
1378 | if (err < 0) | 1394 | if (unlikely(err < 0)) { |
1379 | goto out_release_1; | 1395 | sock_release(sock1); |
1380 | 1396 | goto out; | |
1381 | err = sock1->ops->socketpair(sock1, sock2); | ||
1382 | if (err < 0) | ||
1383 | goto out_release_both; | ||
1384 | |||
1385 | fd1 = get_unused_fd_flags(flags); | ||
1386 | if (unlikely(fd1 < 0)) { | ||
1387 | err = fd1; | ||
1388 | goto out_release_both; | ||
1389 | } | 1397 | } |
1390 | 1398 | ||
1391 | fd2 = get_unused_fd_flags(flags); | 1399 | err = sock1->ops->socketpair(sock1, sock2); |
1392 | if (unlikely(fd2 < 0)) { | 1400 | if (unlikely(err < 0)) { |
1393 | err = fd2; | 1401 | sock_release(sock2); |
1394 | goto out_put_unused_1; | 1402 | sock_release(sock1); |
1403 | goto out; | ||
1395 | } | 1404 | } |
1396 | 1405 | ||
1397 | newfile1 = sock_alloc_file(sock1, flags, NULL); | 1406 | newfile1 = sock_alloc_file(sock1, flags, NULL); |
1398 | if (IS_ERR(newfile1)) { | 1407 | if (IS_ERR(newfile1)) { |
1399 | err = PTR_ERR(newfile1); | 1408 | err = PTR_ERR(newfile1); |
1400 | goto out_put_unused_both; | 1409 | sock_release(sock2); |
1410 | goto out; | ||
1401 | } | 1411 | } |
1402 | 1412 | ||
1403 | newfile2 = sock_alloc_file(sock2, flags, NULL); | 1413 | newfile2 = sock_alloc_file(sock2, flags, NULL); |
1404 | if (IS_ERR(newfile2)) { | 1414 | if (IS_ERR(newfile2)) { |
1405 | err = PTR_ERR(newfile2); | 1415 | err = PTR_ERR(newfile2); |
1406 | goto out_fput_1; | 1416 | fput(newfile1); |
1417 | goto out; | ||
1407 | } | 1418 | } |
1408 | 1419 | ||
1409 | err = put_user(fd1, &usockvec[0]); | ||
1410 | if (err) | ||
1411 | goto out_fput_both; | ||
1412 | |||
1413 | err = put_user(fd2, &usockvec[1]); | ||
1414 | if (err) | ||
1415 | goto out_fput_both; | ||
1416 | |||
1417 | audit_fd_pair(fd1, fd2); | 1420 | audit_fd_pair(fd1, fd2); |
1418 | 1421 | ||
1419 | fd_install(fd1, newfile1); | 1422 | fd_install(fd1, newfile1); |
1420 | fd_install(fd2, newfile2); | 1423 | fd_install(fd2, newfile2); |
1421 | /* fd1 and fd2 may be already another descriptors. | ||
1422 | * Not kernel problem. | ||
1423 | */ | ||
1424 | |||
1425 | return 0; | 1424 | return 0; |
1426 | 1425 | ||
1427 | out_fput_both: | 1426 | out: |
1428 | fput(newfile2); | ||
1429 | fput(newfile1); | ||
1430 | put_unused_fd(fd2); | ||
1431 | put_unused_fd(fd1); | ||
1432 | goto out; | ||
1433 | |||
1434 | out_fput_1: | ||
1435 | fput(newfile1); | ||
1436 | put_unused_fd(fd2); | ||
1437 | put_unused_fd(fd1); | ||
1438 | sock_release(sock2); | ||
1439 | goto out; | ||
1440 | |||
1441 | out_put_unused_both: | ||
1442 | put_unused_fd(fd2); | 1427 | put_unused_fd(fd2); |
1443 | out_put_unused_1: | ||
1444 | put_unused_fd(fd1); | 1428 | put_unused_fd(fd1); |
1445 | out_release_both: | ||
1446 | sock_release(sock2); | ||
1447 | out_release_1: | ||
1448 | sock_release(sock1); | ||
1449 | out: | ||
1450 | return err; | 1429 | return err; |
1451 | } | 1430 | } |
1452 | 1431 | ||
@@ -1562,7 +1541,6 @@ SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr, | |||
1562 | if (IS_ERR(newfile)) { | 1541 | if (IS_ERR(newfile)) { |
1563 | err = PTR_ERR(newfile); | 1542 | err = PTR_ERR(newfile); |
1564 | put_unused_fd(newfd); | 1543 | put_unused_fd(newfd); |
1565 | sock_release(newsock); | ||
1566 | goto out_put; | 1544 | goto out_put; |
1567 | } | 1545 | } |
1568 | 1546 | ||