aboutsummaryrefslogtreecommitdiffstats
path: root/net/socket.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/socket.c')
-rw-r--r--net/socket.c110
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
1339out:
1340 /* It may be already another descriptor 8) Not kernel problem. */
1341 return retval;
1342 1338
1343out_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
1427out_fput_both: 1426out:
1428 fput(newfile2);
1429 fput(newfile1);
1430 put_unused_fd(fd2);
1431 put_unused_fd(fd1);
1432 goto out;
1433
1434out_fput_1:
1435 fput(newfile1);
1436 put_unused_fd(fd2);
1437 put_unused_fd(fd1);
1438 sock_release(sock2);
1439 goto out;
1440
1441out_put_unused_both:
1442 put_unused_fd(fd2); 1427 put_unused_fd(fd2);
1443out_put_unused_1:
1444 put_unused_fd(fd1); 1428 put_unused_fd(fd1);
1445out_release_both:
1446 sock_release(sock2);
1447out_release_1:
1448 sock_release(sock1);
1449out:
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