diff --git a/CHANGES b/CHANGES index b976bad..2a05e98 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,9 @@ corrections: + user-late and group-late, when applied to a pty, affected the system + device /dev/ptmx instead of the pty (thanks to Matthew Cloke for + pointing me to this bug) + corrected the "fixed possible SIGSEGV" fix because SIGSEGV still might occur under those conditions. Thanks to Toni Mattila for first reporting this problem. diff --git a/test.sh b/test.sh index 055e9b4..a2e1531 100755 --- a/test.sh +++ b/test.sh @@ -10747,6 +10747,74 @@ N=$((N+1)) fi # false +############################################################################### +# here come tests that might affect your systems integrity. Put normal tests +# before this paragraph. +# tests must be explicitely selected by roottough or name (not number) + +NAME=PTYGROUPLATE +case "$TESTS" in +*%roottough%*|*%$NAME%*) +TEST="$NAME: pty with group-late works on pty" +# up to socat 1.7.1.1 address pty changed the ownership of /dev/ptmx instead of +# the pty with options user-late, group-late, or perm-late. +# here we check for correct behaviour. +# ATTENTION: in case of failure of this test the +# group of /dev/ptmx might be changed! +if ! eval $NUMCOND; then :; else +# save current /dev/ptmx properties +F= +for f in /dev/ptmx /dev/ptc; do + if [ -e $f ]; then + F=$(echo "$f" |tr / ..) + ls -l $f >"$td/test$N.$F.ls-l" + break + fi +done +printf "test $F_n $TEST... " $N +if [ -z "$F" ]; then + echo -e "${YELLOW}no /dev/ptmx or /dev/ptc${NORMAL}" +else +GROUP=daemon +tf="$td/test$N.stdout" +te="$td/test$N.stderr" +tl="$td/test$N.pty" +tdiff="$td/test$N.diff" +da="test$N $(date) $RANDOM" +CMD0="$SOCAT $opts pty,link=$tl,group-late=$GROUP,escape=0x1a PIPE" +CMD1="$SOCAT $opts - $tl,raw,echo=0" +$CMD0 >/dev/null 2>"${te}0" & +pid0=$! +waitfile $tl +(echo "$da"; usleep $MICROS; echo -e "\x1a") |$CMD1 >"${tf}1" 2>"${te}1" >"$tf" +rc1=$? +usleep $((2*MICROS)) +kill $pid0 2>/dev/null; wait +if [ $rc1 -ne 0 ]; then + $PRINTF "$FAILED\n" + echo "$CMD0 &" + echo "$CMD1" + cat "${te}0" + cat "${te}1" + numFAIL=$((numFAIL+1)) +elif echo "$da" |diff - "$tf" >$tdiff; then + $PRINTF "$OK\n" + numOK=$((numOK+1)) +else + $PRINTF "$FAILED\n" + cat "$tdiff" + numFAIL=$((numFAIL+1)) +fi +if ! ls -l $f |diff "$td/test$N.$F.ls-l" -; then + $PRINTF "${RED}this test changed properties of $f!${NORMAL}\n" +fi +fi # no /dev/ptmx +fi # NUMCOND + ;; +esac +N=$((N+1)) + + echo "summary: $((N-1)) tests; $numOK ok, $numFAIL failed, $numCANT could not be performed" if [ "$numFAIL" -gt 0 ]; then diff --git a/xio-pty.c b/xio-pty.c index dbbc1ba..367e738 100644 --- a/xio-pty.c +++ b/xio-pty.c @@ -1,5 +1,5 @@ /* source: xio-pty.c */ -/* Copyright Gerhard Rieger 2002-2009 */ +/* Copyright Gerhard Rieger 2002-2012 */ /* Published under the GNU General Public License V.2, see file COPYING */ /* this file contains the source for creating pty addresses */ @@ -182,7 +182,33 @@ static int xioopen_pty(const char *linkname, struct opt *opts, int xioflags, xio xfd->stream.dtype = XIODATA_PTY; applyopts(ptyfd, opts, PH_FD); - + + { + /* special handling of user-late etc.; with standard behaviour (up to + 1.7.1.1) they affected /dev/ptmx instead of /dev/pts/N */ + uid_t uid = -1, gid = -1; + mode_t perm; + + bool dont; + dont = retropt_uid(opts, OPT_USER_LATE, &uid); + dont &= retropt_gid(opts, OPT_GROUP_LATE, &gid); + + if (!dont) { + if (Chown(ptyname, uid, gid) < 0) { + Error4("chown(\"%s\", %d, %d): %s", + ptyname, uid, gid, strerror(errno)); + } + } + + if (retropt_mode(opts, OPT_PERM_LATE, &perm) == 0) { + if (Chmod(ptyname, perm) < 0) { + Error3("chmod(\"%s\", %03o): %s", + ptyname, perm, strerror(errno)); + } + } + + } + if (XIOWITHRD(rw)) xfd->stream.rfd = ptyfd; if (XIOWITHWR(rw)) xfd->stream.wfd = ptyfd; applyopts(ptyfd, opts, PH_LATE); diff --git a/xioopts.h b/xioopts.h index 2bbe729..a4e64bc 100644 --- a/xioopts.h +++ b/xioopts.h @@ -1,5 +1,5 @@ /* source: xioopts.h */ -/* Copyright Gerhard Rieger 2001-2009 */ +/* Copyright Gerhard Rieger 2001-2012 */ /* Published under the GNU General Public License V.2, see file COPYING */ #ifndef __xioopts_h_included @@ -944,4 +944,52 @@ extern int _groupbits(mode_t mode); extern int dropopts(struct opt *opts, unsigned int phase); extern int dropopts2(struct opt *opts, unsigned int from, unsigned int to); +#if HAVE_BASIC_UID_T==1 +# define retropt_uid(o,c,r) retropt_short(o,c,r) +#elif HAVE_BASIC_UID_T==2 +# define retropt_uid(o,c,r) retropt_ushort(o,c,r) +#elif HAVE_BASIC_UID_T==3 +# define retropt_uid(o,c,r) retropt_int(o,c,r) +#elif HAVE_BASIC_UID_T==4 +# define retropt_uid(o,c,r) retropt_uint(o,c,r) +#elif HAVE_BASIC_UID_T==5 +# define retropt_uid(o,c,r) retropt_long(o,c,r) +#elif HAVE_BASIC_UID_T==6 +# define retropt_uid(o,c,r) retropt_ulong(o,c,r) +#else +# error "HAVE_BASIC_UID_T is out of range: " HAVE_BASIC_UID_T +#endif + +#if HAVE_BASIC_GID_T==1 +# define retropt_gid(o,c,r) retropt_short(o,c,r) +#elif HAVE_BASIC_GID_T==2 +# define retropt_gid(o,c,r) retropt_ushort(o,c,r) +#elif HAVE_BASIC_GID_T==3 +# define retropt_gid(o,c,r) retropt_int(o,c,r) +#elif HAVE_BASIC_GID_T==4 +# define retropt_gid(o,c,r) retropt_uint(o,c,r) +#elif HAVE_BASIC_GID_T==5 +# define retropt_gid(o,c,r) retropt_long(o,c,r) +#elif HAVE_BASIC_GID_T==6 +# define retropt_gid(o,c,r) retropt_ulong(o,c,r) +#else +# error "HAVE_BASIC_GID_T is out of range: " HAVE_BASIC_GID_T +#endif + +#if HAVE_BASIC_MODE_T==1 +# define retropt_mode(o,c,r) retropt_short(o,c,r) +#elif HAVE_BASIC_MODE_T==2 +# define retropt_mode(o,c,r) retropt_ushort(o,c,r) +#elif HAVE_BASIC_MODE_T==3 +# define retropt_mode(o,c,r) retropt_int(o,c,r) +#elif HAVE_BASIC_MODE_T==4 +# define retropt_mode(o,c,r) retropt_uint(o,c,r) +#elif HAVE_BASIC_MODE_T==5 +# define retropt_mode(o,c,r) retropt_long(o,c,r) +#elif HAVE_BASIC_MODE_T==6 +# define retropt_mode(o,c,r) retropt_ulong(o,c,r) +#else +# error "HAVE_BASIC_MODE_T is out of range: " HAVE_BASIC_MODE_T +#endif + #endif /* !defined(__xioopts_h_included) */