diff --git a/CHANGES b/CHANGES index f1583cf..4bf62a9 100644 --- a/CHANGES +++ b/CHANGES @@ -30,6 +30,10 @@ corrections: endian systems due to wrong byte order (thanks to Peter M. Galbavy for bug report and patch) + 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 12f0f1c..d258831 100755 --- a/test.sh +++ b/test.sh @@ -10755,6 +10755,37 @@ esac N=$((N+1)) +# 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)) + + # socat up to 1.7.2.0 and 2.0.0-b4 had a bug in xioscan_readline() that could # be exploited # to overflow a heap based buffer (socat security advisory 3) diff --git a/xio-listen.c b/xio-listen.c index 88c21a6..f1ab523 100644 --- a/xio-listen.c +++ b/xio-listen.c @@ -308,12 +308,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 2b71de3..27c6451 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-2012 */ /* Published under the GNU General Public License V.2, see file COPYING */ /* this file contains the source for opening addresses of UNIX socket type */ @@ -142,6 +142,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; @@ -161,12 +162,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; @@ -197,6 +192,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 */