possible memory leak in net/socket.c?

Bill Hawes (whawes@star.net)
Fri, 27 Mar 1998 12:53:42 -0500


This is a multi-part message in MIME format.
--------------06B55170D5F1D6AFB96425BB
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

In looking over the handling of control buffers in net/socket.c, it seems that
there may be a problem with the allocated buffer not being freed, or the memory
credited back to the socket. The msg.controllen field is used to decide when to
allocate a control buffer, and then used again when the buffer is freed. Buf
this field may be decremented when the message is processed, possibly leading to
the memory not being freed.

The attached patch keeps the allocated size in a local variable so that it can
be freed properly after use.

Regards,
Bill
--------------06B55170D5F1D6AFB96425BB
Content-Type: text/plain; charset=us-ascii; name="net_socket91-patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="net_socket91-patch"

--- linux-2.1.91/net/socket.c.old Thu Mar 26 23:17:44 1998
+++ linux-2.1.91/net/socket.c Thu Mar 26 23:53:56 1998
@@ -1144,7 +1144,7 @@
unsigned char ctl[sizeof(struct cmsghdr) + 20]; /* 20 is size of ipv6_pktinfo */
unsigned char *ctl_buf = ctl;
struct msghdr msg_sys;
- int err, total_len;
+ int err, ctl_len, total_len;

lock_kernel();

@@ -1161,16 +1161,16 @@
err = verify_iovec(&msg_sys, iov, address, VERIFY_READ);
if (err < 0)
goto out;
-
total_len=err;

sock = sockfd_lookup(fd, &err);
if (!sock)
goto out_freeiov;

- if (msg_sys.msg_controllen)
+ ctl_len = msg_sys.msg_controllen;
+ if (ctl_len)
{
- if (msg_sys.msg_controllen > sizeof(ctl))
+ if (ctl_len > sizeof(ctl))
{
/* Suggested by the Advanced Sockets API for IPv6 draft:
* Limit the msg_controllen size by the SO_SNDBUF size.
@@ -1179,15 +1179,13 @@
* SMP machines you have a race to fix here.
*/
err = -ENOBUFS;
- ctl_buf = sock_kmalloc(sock->sk, msg_sys.msg_controllen,
- GFP_KERNEL);
+ ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL);
if (ctl_buf == NULL)
- goto failed2;
+ goto out_put;
}
err = -EFAULT;
- if (copy_from_user(ctl_buf, msg_sys.msg_control,
- msg_sys.msg_controllen))
- goto failed;
+ if (copy_from_user(ctl_buf, msg_sys.msg_control, ctl_len))
+ goto out_freectl;
msg_sys.msg_control = ctl_buf;
}
msg_sys.msg_flags = flags;
@@ -1196,10 +1194,10 @@
msg_sys.msg_flags |= MSG_DONTWAIT;
err = sock_sendmsg(sock, &msg_sys, total_len);

-failed:
+out_freectl:
if (ctl_buf != ctl)
- sock_kfree_s(sock->sk, ctl_buf, msg_sys.msg_controllen);
-failed2:
+ sock_kfree_s(sock->sk, ctl_buf, ctl_len);
+out_put:
sockfd_put(sock);
out_freeiov:
if (msg_sys.msg_iov != iov)

--------------06B55170D5F1D6AFB96425BB--

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu