Commit a29443da authored by Sridhar Samudrala's avatar Sridhar Samudrala

o net/socket: fix bug in sys_accept

module_put() gets called twice on error. Once via the explicit module_put and
the second via sock_release(). Also i think we should do a __module_get() with
newsock's owner(although same as the original listening sock).
parent f8d0801f
...@@ -1280,26 +1280,26 @@ asmlinkage long sys_accept(int fd, struct sockaddr *upeer_sockaddr, int *upeer_a ...@@ -1280,26 +1280,26 @@ asmlinkage long sys_accept(int fd, struct sockaddr *upeer_sockaddr, int *upeer_a
* We don't need try_module_get here, as the listening socket (sock) * We don't need try_module_get here, as the listening socket (sock)
* has the protocol module (sock->ops->owner) held. * has the protocol module (sock->ops->owner) held.
*/ */
__module_get(sock->ops->owner); __module_get(newsock->ops->owner);
err = sock->ops->accept(sock, newsock, sock->file->f_flags); err = sock->ops->accept(sock, newsock, sock->file->f_flags);
if (err < 0) if (err < 0)
goto out_module_put; goto out_release;
if (upeer_sockaddr) { if (upeer_sockaddr) {
if(newsock->ops->getname(newsock, (struct sockaddr *)address, &len, 2)<0) { if(newsock->ops->getname(newsock, (struct sockaddr *)address, &len, 2)<0) {
err = -ECONNABORTED; err = -ECONNABORTED;
goto out_module_put; goto out_release;
} }
err = move_addr_to_user(address, len, upeer_sockaddr, upeer_addrlen); err = move_addr_to_user(address, len, upeer_sockaddr, upeer_addrlen);
if (err < 0) if (err < 0)
goto out_module_put; goto out_release;
} }
/* File flags are not inherited via accept() unlike another OSes. */ /* File flags are not inherited via accept() unlike another OSes. */
if ((err = sock_map_fd(newsock)) < 0) if ((err = sock_map_fd(newsock)) < 0)
goto out_module_put; goto out_release;
security_socket_post_accept(sock, newsock); security_socket_post_accept(sock, newsock);
...@@ -1307,8 +1307,6 @@ asmlinkage long sys_accept(int fd, struct sockaddr *upeer_sockaddr, int *upeer_a ...@@ -1307,8 +1307,6 @@ asmlinkage long sys_accept(int fd, struct sockaddr *upeer_sockaddr, int *upeer_a
sockfd_put(sock); sockfd_put(sock);
out: out:
return err; return err;
out_module_put:
module_put(sock->ops->owner);
out_release: out_release:
sock_release(newsock); sock_release(newsock);
goto out_put; goto out_put;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment