From cb913fbc0cc1f10b19e9f30789db54cd4cadc983 Mon Sep 17 00:00:00 2001 From: Gerhard Rieger Date: Sun, 3 Oct 2010 16:28:06 +0200 Subject: [PATCH] when UNIX-LISTEN was applied to an existing file it failed as expected but removed the file --- CHANGES | 4 ++++ test.sh | 32 +++++++++++++++++++++++++++++++- xio-listen.c | 8 +------- xio-unix.c | 22 +++++++++++++++------- 4 files changed, 51 insertions(+), 15 deletions(-) diff --git a/CHANGES b/CHANGES index fc5e1d8..0968d37 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,9 @@ corrections: + when UNIX-LISTEN was applied to an existing file it failed as expected + but removed the file. Thanks to Bjoern Bosselmann for reporting this + problem + fixed a bug where socat might crash when connecting to a unix domain socket using address GOPEN. Thanks to Martin Forssen for bug report and patch. diff --git a/test.sh b/test.sh index 7ac6563..7285ae0 100755 --- a/test.sh +++ b/test.sh @@ -10297,7 +10297,37 @@ fi # NUMCOND ;; esac N=$((N+1)) -set +vx + + +# test if socat keeps an existing file where it wanted to create a UNIX socket +NAME=UNIXLISTEN_KEEPFILE +case "$TESTS" in +*%functions%*|*%bugs%*|*%unix%*|*%socket%*|*%$NAME%*) +TEST="$NAME: socat keeps an existing file where it wanted to create a UNIX socket" +# we create a file and start socat with UNIX-LISTEN on this file. expected +# behaviour: socat exits immediately with error, but keeps the file +# up to 1.7.1.3, it removed the file +if ! eval $NUMCOND; then :; else +tf="$td/test$N.file" +te="$td/test$N.stderr" +CMD0="$SOCAT $opts -u UNIX-LISTEN:$tf /dev/null" +printf "test $F_n $TEST... " $N +rm -f "$tf"; touch "$tf" +$CMD0 >/dev/null 2>"${te}0" +rc0=$? +if [ $rc0 -ne 0 -a -f "$tf" ]; then + $PRINTF "$OK\n" + numOK=$((numOK+1)) +else + $PRINTF "$FAILED\n" + echo "$CMD0" + cat "${te}0" + numFAIL=$((numFAIL+1)) +fi +fi # NUMCOND + ;; +esac +N=$((N+1)) ############################################################################### diff --git a/xio-listen.c b/xio-listen.c index b72ba60..60ab4a4 100644 --- a/xio-listen.c +++ b/xio-listen.c @@ -1,5 +1,5 @@ /* source: xio-listen.c */ -/* Copyright Gerhard Rieger 2001-2009 */ +/* Copyright Gerhard Rieger 2001-2010 */ /* Published under the GNU General Public License V.2, see file COPYING */ /* this file contains the source for listen socket options */ @@ -299,12 +299,6 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl level = E_ERROR; #endif /* WITH_RETRY */ -#if WITH_UNIX - /* with UNIX sockets: only listening parent is allowed to remove - the socket file */ - xfd->opt_unlink_close = false; -#endif /* WITH_UNIX */ - break; } diff --git a/xio-unix.c b/xio-unix.c index e45a3fa..43398c4 100644 --- a/xio-unix.c +++ b/xio-unix.c @@ -1,5 +1,5 @@ /* source: xio-unix.c */ -/* Copyright Gerhard Rieger 2001-2009 */ +/* Copyright Gerhard Rieger 2001-2010 */ /* Published under the GNU General Public License V.2, see file COPYING */ /* this file contains the source for opening addresses of UNIX socket type */ @@ -126,6 +126,7 @@ static int xioopen_unix_listen(int argc, const char *argv[], struct opt *opts, i socklen_t uslen; bool tight = true; struct opt *opts0 = NULL; + pid_t pid = Getpid(); bool opt_unlink_early = false; bool opt_unlink_close = true; int result; @@ -147,12 +148,6 @@ static int xioopen_unix_listen(int argc, const char *argv[], struct opt *opts, i /* only for non abstract because abstract do not work in file system */ retropt_bool(opts, OPT_UNLINK_EARLY, &opt_unlink_early); retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close); - if (opt_unlink_close) { - if ((xfd->unlink_close = strdup(name)) == NULL) { - Error1("strdup(\"%s\"): out of memory", name); - } - xfd->opt_unlink_close = true; - } } if (applyopts_single(xfd, opts, PH_INIT) < 0) return STAT_NORETRY; @@ -183,6 +178,19 @@ static int xioopen_unix_listen(int argc, const char *argv[], struct opt *opts, i opts, opts0, pf, socktype, protocol)) != 0) return result; + + /* we set this option as late as now because we should not remove an + existing entry when bind() failed */ + if (!(ABSTRACT && abstract)) { + if (opt_unlink_close) { + if (pid == Getpid()) { + if ((xfd->unlink_close = strdup(name)) == NULL) { + Error1("strdup(\"%s\"): out of memory", name); + } + xfd->opt_unlink_close = true; + } + } + } return 0; } #endif /* WITH_LISTEN */