The branch, master has been updated via 27195b3 socket_wrapper: correctly handle dup()/dup2() ref counting via a110d05 socket_wrapper: pass down the fd explictly from the swrap_*() to the real_*() calls from ea00f0e s3:smb2_server: SMB2_OP_CANCEL requests don't have to be signed
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 27195b3ac5970037445e8d05efb77b39cbfdd9ba Author: Stefan Metzmacher <me...@samba.org> Date: Wed Sep 28 23:09:49 2011 +0200 socket_wrapper: correctly handle dup()/dup2() ref counting metze Autobuild-User: Stefan Metzmacher <me...@samba.org> Autobuild-Date: Thu Sep 29 13:13:56 CEST 2011 on sn-devel-104 commit a110d05f679e216fed7b1b1724ac17898024e834 Author: Stefan Metzmacher <me...@samba.org> Date: Wed Sep 28 23:04:51 2011 +0200 socket_wrapper: pass down the fd explictly from the swrap_*() to the real_*() calls metze ----------------------------------------------------------------------- Summary of changes: lib/socket_wrapper/socket_wrapper.c | 187 +++++++++++++++++------------------ 1 files changed, 92 insertions(+), 95 deletions(-) Changeset truncated at 500 lines: diff --git a/lib/socket_wrapper/socket_wrapper.c b/lib/socket_wrapper/socket_wrapper.c index ddfc74f..a54f50f 100644 --- a/lib/socket_wrapper/socket_wrapper.c +++ b/lib/socket_wrapper/socket_wrapper.c @@ -212,11 +212,14 @@ static size_t socket_length(int family) return 0; } - +struct socket_info_fd { + struct socket_info_fd *prev, *next; + int fd; +}; struct socket_info { - int fd; + struct socket_info_fd *fds; int family; int type; @@ -585,8 +588,12 @@ static struct socket_info *find_socket_info(int fd) { struct socket_info *i; for (i = sockets; i; i = i->next) { - if (i->fd == fd) - return i; + struct socket_info_fd *f; + for (f = i->fds; f; f = f->next) { + if (f->fd == fd) { + return i; + } + } } return NULL; @@ -1405,6 +1412,7 @@ static void swrap_dump_packet(struct socket_info *si, _PUBLIC_ int swrap_socket(int family, int type, int protocol) { struct socket_info *si; + struct socket_info_fd *fi; int fd; int real_type = type; #ifdef SOCK_CLOEXEC @@ -1466,6 +1474,10 @@ _PUBLIC_ int swrap_socket(int family, int type, int protocol) if (fd == -1) return -1; si = (struct socket_info *)calloc(1, sizeof(struct socket_info)); + if (si == NULL) { + errno = ENOMEM; + return -1; + } si->family = family; @@ -1473,16 +1485,26 @@ _PUBLIC_ int swrap_socket(int family, int type, int protocol) * the type, not the flags */ si->type = real_type; si->protocol = protocol; - si->fd = fd; + fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd)); + if (fi == NULL) { + free(si); + errno = ENOMEM; + return -1; + } + + fi->fd = fd; + + SWRAP_DLIST_ADD(si->fds, fi); SWRAP_DLIST_ADD(sockets, si); - return si->fd; + return fd; } _PUBLIC_ int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen) { struct socket_info *parent_si, *child_si; + struct socket_info_fd *child_fi; int fd; struct sockaddr_un un_addr; socklen_t un_addrlen = sizeof(un_addr); @@ -1535,7 +1557,19 @@ _PUBLIC_ int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen) child_si = (struct socket_info *)malloc(sizeof(struct socket_info)); memset(child_si, 0, sizeof(*child_si)); - child_si->fd = fd; + child_fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd)); + if (child_fi == NULL) { + free(child_si); + free(my_addr); + close(fd); + errno = ENOMEM; + return -1; + } + + child_fi->fd = fd; + + SWRAP_DLIST_ADD(child_si->fds, child_fi); + child_si->family = parent_si->family; child_si->type = parent_si->type; child_si->protocol = parent_si->protocol; @@ -1557,6 +1591,7 @@ _PUBLIC_ int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen) ret = real_getsockname(fd, (struct sockaddr *)(void *)&un_my_addr, &un_my_addrlen); if (ret == -1) { + free(child_fi); free(child_si); close(fd); return ret; @@ -1566,6 +1601,7 @@ _PUBLIC_ int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen) ret = sockaddr_convert_from_un(child_si, &un_my_addr, un_my_addrlen, child_si->family, my_addr, &len); if (ret == -1) { + free(child_fi); free(child_si); free(my_addr); close(fd); @@ -1594,7 +1630,7 @@ static int autobind_start; assign it here. Note: this might change the family from ipv6 to ipv4 */ -static int swrap_auto_bind(struct socket_info *si, int family) +static int swrap_auto_bind(int fd, struct socket_info *si, int family) { struct sockaddr_un un_addr; int i; @@ -1683,7 +1719,7 @@ static int swrap_auto_bind(struct socket_info *si, int family) type, socket_wrapper_default_iface(), port); if (stat(un_addr.sun_path, &st) == 0) continue; - ret = real_bind(si->fd, (struct sockaddr *)(void *)&un_addr, + ret = real_bind(fd, (struct sockaddr *)(void *)&un_addr, sizeof(un_addr)); if (ret == -1) return ret; @@ -1716,7 +1752,7 @@ _PUBLIC_ int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t ad } if (si->bound == 0) { - ret = swrap_auto_bind(si, serv_addr->sa_family); + ret = swrap_auto_bind(s, si, serv_addr->sa_family); if (ret == -1) return -1; } @@ -1906,7 +1942,8 @@ _PUBLIC_ int swrap_ioctl(int s, int r, void *p) return ret; } -static ssize_t swrap_sendmsg_before(struct socket_info *si, +static ssize_t swrap_sendmsg_before(int fd, + struct socket_info *si, struct msghdr *msg, struct iovec *tmp_iov, struct sockaddr_un *tmp_un, @@ -1991,7 +2028,7 @@ static ssize_t swrap_sendmsg_before(struct socket_info *si, } if (si->bound == 0) { - ret = swrap_auto_bind(si, si->family); + ret = swrap_auto_bind(fd, si, si->family); if (ret == -1) return -1; } @@ -2003,7 +2040,7 @@ static ssize_t swrap_sendmsg_before(struct socket_info *si, tmp_un, 0, NULL); if (ret == -1) return -1; - ret = real_connect(si->fd, (struct sockaddr *)(void *)tmp_un, + ret = real_connect(fd, (struct sockaddr *)(void *)tmp_un, sizeof(*tmp_un)); /* to give better errors */ @@ -2168,7 +2205,7 @@ _PUBLIC_ ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, con msg.msg_flags = 0; /* flags on received message */ #endif - ret = swrap_sendmsg_before(si, &msg, &tmp, &un_addr, &to_un, &to, &bcast); + ret = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast); if (ret == -1) return -1; buf = msg.msg_iov[0].iov_base; @@ -2289,7 +2326,7 @@ _PUBLIC_ ssize_t swrap_send(int s, const void *buf, size_t len, int flags) msg.msg_flags = 0; /* flags on received message */ #endif - ret = swrap_sendmsg_before(si, &msg, &tmp, &un_addr, NULL, NULL, NULL); + ret = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL); if (ret == -1) return -1; buf = msg.msg_iov[0].iov_base; @@ -2332,7 +2369,7 @@ _PUBLIC_ ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags) msg.msg_flags = omsg->msg_flags; /* flags on received message */ #endif - ret = swrap_sendmsg_before(si, &msg, &tmp, &un_addr, &to_un, &to, &bcast); + ret = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast); if (ret == -1) return -1; if (bcast) { @@ -2493,7 +2530,7 @@ int swrap_writev(int s, const struct iovec *vector, size_t count) msg.msg_flags = 0; /* flags on received message */ #endif - ret = swrap_sendmsg_before(si, &msg, &tmp, &un_addr, NULL, NULL, NULL); + ret = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL); if (ret == -1) return -1; ret = real_writev(s, msg.msg_iov, msg.msg_iovlen); @@ -2506,12 +2543,26 @@ int swrap_writev(int s, const struct iovec *vector, size_t count) _PUBLIC_ int swrap_close(int fd) { struct socket_info *si = find_socket_info(fd); + struct socket_info_fd *fi; int ret; if (!si) { return real_close(fd); } + for (fi = si->fds; fi; fi = fi->next) { + if (fi->fd == fd) { + SWRAP_DLIST_REMOVE(si->fds, fi); + free(fi); + break; + } + } + + if (si->fds) { + /* there are still references left */ + return real_close(fd); + } + SWRAP_DLIST_REMOVE(sockets, si); if (si->myname && si->peername) { @@ -2538,8 +2589,8 @@ _PUBLIC_ int swrap_close(int fd) _PUBLIC_ int swrap_dup(int fd) { - struct socket_info *si, *si2; - int fd2; + struct socket_info *si; + struct socket_info_fd *fi; si = find_socket_info(fd); @@ -2547,55 +2598,28 @@ _PUBLIC_ int swrap_dup(int fd) return real_dup(fd); } - if (si->tmp_path) { - /* we would need reference counting to handle this */ - errno = EINVAL; - return -1; - } - - fd2 = real_dup(fd); - if (fd2 == -1) { - return -1; - } - - si2 = (struct socket_info *)malloc(sizeof(struct socket_info)); - if (si2 == NULL) { - real_close(fd2); + fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd)); + if (fi == NULL) { errno = ENOMEM; return -1; } - /* copy the whole structure, then duplicate pointer elements */ - *si2 = *si; - - si2->fd = fd2; - - if (si2->myname) { - si2->myname = sockaddr_dup(si2->myname, si2->myname_len); - if (si2->myname == NULL) { - real_close(fd2); - errno = ENOMEM; - return -1; - } - } - - if (si2->peername) { - si2->peername = sockaddr_dup(si2->peername, si2->peername_len); - if (si2->peername == NULL) { - real_close(fd2); - errno = ENOMEM; - return -1; - } + fi->fd = real_dup(fd); + if (fi->fd == -1) { + int saved_errno = errno; + free(fi); + errno = saved_errno; + return -1; } - SWRAP_DLIST_ADD(sockets, si2); - return fd2; + SWRAP_DLIST_ADD(si->fds, fi); + return fi->fd; } _PUBLIC_ int swrap_dup2(int fd, int newfd) { - struct socket_info *si, *si2; - int fd2; + struct socket_info *si; + struct socket_info_fd *fi; si = find_socket_info(fd); @@ -2603,53 +2627,26 @@ _PUBLIC_ int swrap_dup2(int fd, int newfd) return real_dup2(fd, newfd); } - if (si->tmp_path) { - /* we would need reference counting to handle this */ - errno = EINVAL; - return -1; - } - if (find_socket_info(newfd)) { /* dup2() does an implicit close of newfd, which we * need to emulate */ swrap_close(newfd); } - fd2 = real_dup2(fd, newfd); - if (fd2 == -1) { - return -1; - } - - si2 = (struct socket_info *)malloc(sizeof(struct socket_info)); - if (si2 == NULL) { - real_close(fd2); + fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd)); + if (fi == NULL) { errno = ENOMEM; return -1; } - /* copy the whole structure, then duplicate pointer elements */ - *si2 = *si; - - si2->fd = fd2; - - if (si2->myname) { - si2->myname = sockaddr_dup(si2->myname, si2->myname_len); - if (si2->myname == NULL) { - real_close(fd2); - errno = ENOMEM; - return -1; - } - } - - if (si2->peername) { - si2->peername = sockaddr_dup(si2->peername, si2->peername_len); - if (si2->peername == NULL) { - real_close(fd2); - errno = ENOMEM; - return -1; - } + fi->fd = real_dup2(fd, newfd); + if (fi->fd == -1) { + int saved_errno = errno; + free(fi); + errno = saved_errno; + return -1; } - SWRAP_DLIST_ADD(sockets, si2); - return fd2; + SWRAP_DLIST_ADD(si->fds, fi); + return fi->fd; } -- Samba Shared Repository