diff options
Diffstat (limited to 'net/socket.c')
-rw-r--r-- | net/socket.c | 68 |
1 files changed, 42 insertions, 26 deletions
diff --git a/net/socket.c b/net/socket.c index 80dc7e84b046..d92c490e66fa 100644 --- a/net/socket.c +++ b/net/socket.c | |||
@@ -347,17 +347,11 @@ static struct file_system_type sock_fs_type = { | |||
347 | * but we take care of internal coherence yet. | 347 | * but we take care of internal coherence yet. |
348 | */ | 348 | */ |
349 | 349 | ||
350 | static int sock_alloc_file(struct socket *sock, struct file **f, int flags, | 350 | struct file *sock_alloc_file(struct socket *sock, int flags, const char *dname) |
351 | const char *dname) | ||
352 | { | 351 | { |
353 | struct qstr name = { .name = "" }; | 352 | struct qstr name = { .name = "" }; |
354 | struct path path; | 353 | struct path path; |
355 | struct file *file; | 354 | struct file *file; |
356 | int fd; | ||
357 | |||
358 | fd = get_unused_fd_flags(flags); | ||
359 | if (unlikely(fd < 0)) | ||
360 | return fd; | ||
361 | 355 | ||
362 | if (dname) { | 356 | if (dname) { |
363 | name.name = dname; | 357 | name.name = dname; |
@@ -367,10 +361,8 @@ static int sock_alloc_file(struct socket *sock, struct file **f, int flags, | |||
367 | name.len = strlen(name.name); | 361 | name.len = strlen(name.name); |
368 | } | 362 | } |
369 | path.dentry = d_alloc_pseudo(sock_mnt->mnt_sb, &name); | 363 | path.dentry = d_alloc_pseudo(sock_mnt->mnt_sb, &name); |
370 | if (unlikely(!path.dentry)) { | 364 | if (unlikely(!path.dentry)) |
371 | put_unused_fd(fd); | 365 | return ERR_PTR(-ENOMEM); |
372 | return -ENOMEM; | ||
373 | } | ||
374 | path.mnt = mntget(sock_mnt); | 366 | path.mnt = mntget(sock_mnt); |
375 | 367 | ||
376 | d_instantiate(path.dentry, SOCK_INODE(sock)); | 368 | d_instantiate(path.dentry, SOCK_INODE(sock)); |
@@ -382,30 +374,33 @@ static int sock_alloc_file(struct socket *sock, struct file **f, int flags, | |||
382 | /* drop dentry, keep inode */ | 374 | /* drop dentry, keep inode */ |
383 | ihold(path.dentry->d_inode); | 375 | ihold(path.dentry->d_inode); |
384 | path_put(&path); | 376 | path_put(&path); |
385 | put_unused_fd(fd); | 377 | return ERR_PTR(-ENFILE); |
386 | return -ENFILE; | ||
387 | } | 378 | } |
388 | 379 | ||
389 | sock->file = file; | 380 | sock->file = file; |
390 | file->f_flags = O_RDWR | (flags & O_NONBLOCK); | 381 | file->f_flags = O_RDWR | (flags & O_NONBLOCK); |
391 | file->f_pos = 0; | 382 | file->f_pos = 0; |
392 | file->private_data = sock; | 383 | file->private_data = sock; |
393 | 384 | return file; | |
394 | *f = file; | ||
395 | return fd; | ||
396 | } | 385 | } |
386 | EXPORT_SYMBOL(sock_alloc_file); | ||
397 | 387 | ||
398 | int sock_map_fd(struct socket *sock, int flags) | 388 | static int sock_map_fd(struct socket *sock, int flags) |
399 | { | 389 | { |
400 | struct file *newfile; | 390 | struct file *newfile; |
401 | int fd = sock_alloc_file(sock, &newfile, flags, NULL); | 391 | int fd = get_unused_fd_flags(flags); |
392 | if (unlikely(fd < 0)) | ||
393 | return fd; | ||
402 | 394 | ||
403 | if (likely(fd >= 0)) | 395 | newfile = sock_alloc_file(sock, flags, NULL); |
396 | if (likely(!IS_ERR(newfile))) { | ||
404 | fd_install(fd, newfile); | 397 | fd_install(fd, newfile); |
398 | return fd; | ||
399 | } | ||
405 | 400 | ||
406 | return fd; | 401 | put_unused_fd(fd); |
402 | return PTR_ERR(newfile); | ||
407 | } | 403 | } |
408 | EXPORT_SYMBOL(sock_map_fd); | ||
409 | 404 | ||
410 | struct socket *sock_from_file(struct file *file, int *err) | 405 | struct socket *sock_from_file(struct file *file, int *err) |
411 | { | 406 | { |
@@ -1466,17 +1461,32 @@ SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol, | |||
1466 | if (err < 0) | 1461 | if (err < 0) |
1467 | goto out_release_both; | 1462 | goto out_release_both; |
1468 | 1463 | ||
1469 | fd1 = sock_alloc_file(sock1, &newfile1, flags, NULL); | 1464 | fd1 = get_unused_fd_flags(flags); |
1470 | if (unlikely(fd1 < 0)) { | 1465 | if (unlikely(fd1 < 0)) { |
1471 | err = fd1; | 1466 | err = fd1; |
1472 | goto out_release_both; | 1467 | goto out_release_both; |
1473 | } | 1468 | } |
1474 | 1469 | fd2 = get_unused_fd_flags(flags); | |
1475 | fd2 = sock_alloc_file(sock2, &newfile2, flags, NULL); | ||
1476 | if (unlikely(fd2 < 0)) { | 1470 | if (unlikely(fd2 < 0)) { |
1477 | err = fd2; | 1471 | err = fd2; |
1472 | put_unused_fd(fd1); | ||
1473 | goto out_release_both; | ||
1474 | } | ||
1475 | |||
1476 | newfile1 = sock_alloc_file(sock1, flags, NULL); | ||
1477 | if (unlikely(IS_ERR(newfile1))) { | ||
1478 | err = PTR_ERR(newfile1); | ||
1479 | put_unused_fd(fd1); | ||
1480 | put_unused_fd(fd2); | ||
1481 | goto out_release_both; | ||
1482 | } | ||
1483 | |||
1484 | newfile2 = sock_alloc_file(sock2, flags, NULL); | ||
1485 | if (IS_ERR(newfile2)) { | ||
1486 | err = PTR_ERR(newfile2); | ||
1478 | fput(newfile1); | 1487 | fput(newfile1); |
1479 | put_unused_fd(fd1); | 1488 | put_unused_fd(fd1); |
1489 | put_unused_fd(fd2); | ||
1480 | sock_release(sock2); | 1490 | sock_release(sock2); |
1481 | goto out; | 1491 | goto out; |
1482 | } | 1492 | } |
@@ -1608,13 +1618,19 @@ SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr, | |||
1608 | */ | 1618 | */ |
1609 | __module_get(newsock->ops->owner); | 1619 | __module_get(newsock->ops->owner); |
1610 | 1620 | ||
1611 | newfd = sock_alloc_file(newsock, &newfile, flags, | 1621 | newfd = get_unused_fd_flags(flags); |
1612 | sock->sk->sk_prot_creator->name); | ||
1613 | if (unlikely(newfd < 0)) { | 1622 | if (unlikely(newfd < 0)) { |
1614 | err = newfd; | 1623 | err = newfd; |
1615 | sock_release(newsock); | 1624 | sock_release(newsock); |
1616 | goto out_put; | 1625 | goto out_put; |
1617 | } | 1626 | } |
1627 | newfile = sock_alloc_file(newsock, flags, sock->sk->sk_prot_creator->name); | ||
1628 | if (unlikely(IS_ERR(newfile))) { | ||
1629 | err = PTR_ERR(newfile); | ||
1630 | put_unused_fd(newfd); | ||
1631 | sock_release(newsock); | ||
1632 | goto out_put; | ||
1633 | } | ||
1618 | 1634 | ||
1619 | err = security_socket_accept(sock, newsock); | 1635 | err = security_socket_accept(sock, newsock); |
1620 | if (err) | 1636 | if (err) |