From 1ce2bc91878f97dd46980d21a2b9c9d283e05e13 Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Mon, 2 Apr 2007 19:15:47 +0000 Subject: [PATCH] Fix a fd leak in socketpair(): - Close the new file objects created during socketpair() if the copyout of the new file descriptors fails. - Add a test to the socketpair regression test for this edge case. --- sys/kern/uipc_syscalls.c | 9 +++-- .../sockets/socketpair/socketpair.c | 33 +++++++++++++++++++ 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c index 5f6479c17c0e..fd2a2083a1db 100644 --- a/sys/kern/uipc_syscalls.c +++ b/sys/kern/uipc_syscalls.c @@ -664,7 +664,10 @@ socketpair(td, uap) fp2->f_ops = &socketops; fp2->f_type = DTYPE_SOCKET; FILE_UNLOCK(fp2); + so1 = so2 = NULL; error = copyout(sv, uap->rsv, 2 * sizeof (int)); + if (error) + goto free4; fdrop(fp1, td); fdrop(fp2, td); goto done2; @@ -675,9 +678,11 @@ socketpair(td, uap) fdclose(fdp, fp1, sv[0], td); fdrop(fp1, td); free2: - (void)soclose(so2); + if (so2 != NULL) + (void)soclose(so2); free1: - (void)soclose(so1); + if (so1 != NULL) + (void)soclose(so1); done2: NET_UNLOCK_GIANT(); return (error); diff --git a/tools/regression/sockets/socketpair/socketpair.c b/tools/regression/sockets/socketpair/socketpair.c index a1d0946c7b58..5f4647614f99 100644 --- a/tools/regression/sockets/socketpair/socketpair.c +++ b/tools/regression/sockets/socketpair/socketpair.c @@ -49,6 +49,7 @@ int main(int argc, char *argv[]) { + int fd1, fd2, fd3; int sv[2]; /* @@ -123,6 +124,38 @@ main(int argc, char *argv[]) fprintf(stderr, "FAIL\n"); } + /* + * Check for sequential fd allocation, and give up early if not. + */ + fd1 = dup(STDIN_FILENO); + fd2 = dup(STDIN_FILENO); + if (fd2 != fd1 + 1) { + fprintf(stderr, "Non-sequential fd allocation\n"); + fprintf(stderr, "FAIL\n"); + exit(-1); + } + + /* Allocate a socketpair using a bad destination address. */ + if (socketpair(PF_UNIX, SOCK_DGRAM, 0, NULL) == 0) { + fprintf(stderr, "socketpair(PF_UNIX, SOCK_DGRAM, NULL): opened\n"); + fprintf(stderr, "FAIL\n"); + exit(-1); + } + if (errno != EFAULT) { + fprintf(stderr, "socketpair(PF_UNIX, SOCK_DGRAM, NULL): %s\n", + strerror(errno)); + fprintf(stderr, "FAIL\n"); + exit(-1); + } + + /* Allocate a file descriptor and make sure it's fd2+1. */ + fd3 = dup(STDIN_FILENO); + if (fd3 != fd2 + 1) { + fprintf(stderr, "socketpair(..., NULL) allocated descriptors\n"); + fprintf(stderr, "FAIL\n"); + exit(-1); + } + fprintf(stderr, "PASS\n"); exit(0); }