Subject: xsrc/7260: proposed fix for xtrans vulnerability
To: None <gnats-bugs@gnats.netbsd.org>
From: Matthieu Herrb <matthieu@bluenote.laas.fr>
List: netbsd-bugs
Date: 03/27/1999 17:21:52
>Number: 7260
>Category: xsrc
>Synopsis: proposed fix for xtrans vulnerability
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: gnats-admin (GNATS administrator)
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Sat Mar 27 08:35:01 1999
>Last-Modified:
>Originator: Matthieu Herrb
>Organization:
>Release: NetBSD-current 03/23/1999
>Environment:
System: NetBSD bluenote 1.3K NetBSD 1.3K (BLUENOTE) #0: Thu Mar 25 20:50:46 CET 1999 matthieu@bluenote:/local/NetBSD/src/sys/arch/i386/compile/BLUENOTE i386
>Description:
"in.telnetd" <telnetd@DOEMILL.SHOCKING.COM> has reported on
bugtraq a vulnerability in xtrans, which allow any user to
change the modes of any directory to 1777.
The included patch is a proposed fix. I also sent it to XFree86
developper's list.
>How-To-Repeat:
ln -s /root /tmp/.X11-unix
xinit
>Fix:
Index: xc/lib/xtrans/Xtransint.h
===================================================================
RCS file: /cvs/X11/xc/lib/xtrans/Xtransint.h,v
retrieving revision 1.1.1.2
diff -u -r1.1.1.2 Xtransint.h
--- xc/lib/xtrans/Xtransint.h 1998/11/28 08:26:08 1.1.1.2
+++ xc/lib/xtrans/Xtransint.h 1999/03/26 08:20:27
@@ -455,6 +455,12 @@
#endif
);
+static int trans_mkdir (
+#if NeedFunctionPrototypes
+ char *, /* path */
+ int /* mode */
+#endif
+);
/*
* Some XTRANSDEBUG stuff
Index: xc/lib/xtrans/Xtranslcl.c
===================================================================
RCS file: /cvs/X11/xc/lib/xtrans/Xtranslcl.c,v
retrieving revision 1.1.1.4
diff -u -r1.1.1.4 Xtranslcl.c
--- xc/lib/xtrans/Xtranslcl.c 1999/01/08 17:31:44 1.1.1.4
+++ xc/lib/xtrans/Xtranslcl.c 1999/03/26 08:20:32
@@ -444,9 +444,11 @@
#else
mode = 0777;
#endif
-
- mkdir(X_STREAMS_DIR, mode);
- chmod(X_STREAMS_DIR, mode);
+ if (trans_mkdir(X_STREAMS_DIR, mode) == -1) {
+ PRMSG (1, "PTSOpenServer: mkdir(%s) failed, errno = %d\n",
+ X_STREAMS_DIR, errno, 0);
+ return(-1);
+ }
if( (fd=open(server_path, O_RDWR)) >= 0 ) {
#if 0
@@ -724,9 +726,11 @@
#else
mode = 0777;
#endif
-
- mkdir(X_STREAMS_DIR, mode);
- chmod(X_STREAMS_DIR, mode);
+ if (trans_mkdir(X_STREAMS_DIR, mode) == -1) {
+ PRMSG (1, "NAMEDOpenServer: mkdir(%s) failed, errno = %d\n",
+ X_STREAMS_DIR, errno, 0);
+ return(-1);
+ }
if(stat(server_path, &sbuf) != 0) {
if (errno == ENOENT) {
@@ -1044,10 +1048,18 @@
mode = 0777;
#endif
- mkdir(X_STREAMS_DIR, mode); /* "/dev/X" */
- chmod(X_STREAMS_DIR, mode);
- mkdir(X_ISC_DIR, mode); /* "/dev/X/ISCCONN" */
- chmod(X_ISC_DIR, mode);
+ /* "/dev/X" */
+ if (trans_mkdir(X_STREAMS_DIR, mode) == -1) {
+ PRMSG (1, "ISCOpenServer: mkdir(%s) failed, errno = %d\n",
+ X_STREAMS_DIR, errno, 0);
+ return(-1);
+ }
+ /* "/dev/X/ISCCONN" */
+ if (trans_mkdir(X_ISC_DIR, mode) == -1) {
+ PRMSG (1, "ISCOpenServer: mkdir(%s) failed, errno = %d\n",
+ X_ISC_DIR, errno, 0);
+ return(-1);
+ }
unlink(server_path);
@@ -1072,8 +1084,11 @@
*/
#define X_UNIX_DIR "/tmp/.X11-unix"
- mkdir(X_UNIX_DIR, mode);
- chmod(X_UNIX_DIR, mode);
+ if (trans_mkdir(X_UNIX_DIR, mode) == -1) {
+ PRMSG (1, "ISCOpenServer: mkdir(%s) failed, errno = %d\n",
+ X_UNIX_DIR, errno, 0);
+ return(-1);
+ }
unlink(server_unix_path);
Index: xc/lib/xtrans/Xtranssock.c
===================================================================
RCS file: /cvs/X11/xc/lib/xtrans/Xtranssock.c,v
retrieving revision 1.1.1.4
diff -u -r1.1.1.4 Xtranssock.c
--- xc/lib/xtrans/Xtranssock.c 1999/01/08 17:31:46 1.1.1.4
+++ xc/lib/xtrans/Xtranssock.c 1999/03/26 08:20:38
@@ -946,8 +946,11 @@
#else
mode = 0777;
#endif
- mkdir (UNIX_DIR, mode);
- chmod (UNIX_DIR, mode);
+ if (trans_mkdir(UNIX_DIR, mode) == -1) {
+ PRMSG (1, "SocketUNIXCreateListener: mkdir(%s) failed, errno = %d\n",
+ UNIX_DIR, errno, 0);
+ return TRANS_CREATE_LISTENER_FAILED;
+ }
#endif
sockname.sun_family = AF_UNIX;
@@ -1041,8 +1044,11 @@
#else
mode = 0777;
#endif
- mkdir (UNIX_DIR, mode);
- chmod (UNIX_DIR, mode);
+ if (trans_mkdir(UNIX_DIR, mode) == -1) {
+ PRMSG (1, "SocketUNIXResetListener: mkdir(%s) failed, errno = %d\n",
+ UNIX_DIR, errno, 0);
+ return TRANS_RESET_FAILURE;
+ }
#endif
close (ciptr->fd);
Index: xc/lib/xtrans/Xtransutil.c
===================================================================
RCS file: /cvs/X11/xc/lib/xtrans/Xtransutil.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 Xtransutil.c
--- xc/lib/xtrans/Xtransutil.c 1997/09/05 09:02:43 1.1.1.1
+++ xc/lib/xtrans/Xtransutil.c 1999/03/26 08:20:40
@@ -465,3 +465,32 @@
return (1);
}
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+static int
+trans_mkdir(char *path, int mode)
+{
+ struct stat buf;
+
+ if (mkdir(path, mode) == 0) {
+ /* I don't know why this is done, but it was in the original
+ xtrans code */
+ chmod(path, mode);
+ return 0;
+ }
+ /* If mkdir failed with EEXIST, test if it is a directory with
+ the right modes, else fail */
+ if (errno == EEXIST) {
+ if (stat(path, &buf) != 0) {
+ return -1;
+ }
+ if (S_ISDIR(buf.st_mode) && ((buf.st_mode & ~S_IFMT) == mode)) {
+ return 0;
+ }
+ }
+ /* In all other cases, fail */
+ return -1;
+}
>Audit-Trail:
>Unformatted: