when UNIX-LISTEN was applied to an existing file it failed as expected but removed the file

This commit is contained in:
Gerhard Rieger 2012-07-22 15:09:45 +02:00
parent 51d9b5d76a
commit ad200da8fd
4 changed files with 50 additions and 13 deletions

View file

@ -30,6 +30,10 @@ corrections:
endian systems due to wrong byte order (thanks to Peter M. Galbavy for endian systems due to wrong byte order (thanks to Peter M. Galbavy for
bug report and patch) 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 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 socket using address GOPEN. Thanks to Martin Forssen for bug report and
patch. patch.

31
test.sh
View file

@ -10755,6 +10755,37 @@ esac
N=$((N+1)) 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 # socat up to 1.7.2.0 and 2.0.0-b4 had a bug in xioscan_readline() that could
# be exploited # be exploited
# to overflow a heap based buffer (socat security advisory 3) # to overflow a heap based buffer (socat security advisory 3)

View file

@ -308,12 +308,6 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl
level = E_ERROR; level = E_ERROR;
#endif /* WITH_RETRY */ #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; break;
} }

View file

@ -1,5 +1,5 @@
/* source: xio-unix.c */ /* 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 */ /* Published under the GNU General Public License V.2, see file COPYING */
/* this file contains the source for opening addresses of UNIX socket type */ /* 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; socklen_t uslen;
bool tight = true; bool tight = true;
struct opt *opts0 = NULL; struct opt *opts0 = NULL;
pid_t pid = Getpid();
bool opt_unlink_early = false; bool opt_unlink_early = false;
bool opt_unlink_close = true; bool opt_unlink_close = true;
int result; 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 */ /* 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_EARLY, &opt_unlink_early);
retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close); 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; 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)) opts, opts0, pf, socktype, protocol))
!= 0) != 0)
return result; 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; return 0;
} }
#endif /* WITH_LISTEN */ #endif /* WITH_LISTEN */