Based on Xorg upstream git commit b07602014061cb41540f6a7e74e4132e67aa1117 From: Alan Coopersmith Date: Mon, 22 Aug 2005 21:47:59 +0000 If MAKE_XKM_OUTPUT_DIR is defined, call trans_mkdir to create directory if it doesn't already exist. (ported from Solaris Xsun bug #5039004) [Xorg has since dropped upstream, but we still use.] Updated to include changes to ensure xkb directory & files are writable by gid 0, to fix bug: 6916317 Changing xkb settings after login not working on snv130 diff --git a/xkb/Makefile.am b/xkb/Makefile.am index fb3ccbf..5a82e09 100644 --- a/xkb/Makefile.am +++ b/xkb/Makefile.am @@ -1,6 +1,7 @@ noinst_LTLIBRARIES = libxkb.la libxkbstubs.la AM_CFLAGS = $(DIX_CFLAGS) +AM_CFLAGS += -DMAKE_XKM_OUTPUT_DIR DDX_SRCS = \ ddxBeep.c \ diff --git a/xkb/ddxLoad.c b/xkb/ddxLoad.c index d462957..9338a1c 100644 --- a/xkb/ddxLoad.c +++ b/xkb/ddxLoad.c @@ -68,14 +68,30 @@ THE USE OR PERFORMANCE OF THIS SOFTWARE. #define PATHSEPARATOR "/" #endif +#ifdef MAKE_XKM_OUTPUT_DIR +/* Borrow trans_mkdir from Xtransutil.c to more safely make directories */ +# undef X11_t +# define TRANS_SERVER +# define prmsg(lvl,...) \ + if (lvl <= 1) { LogMessage(X_ERROR, __VA_ARGS__); } else ((void)0) +# include +# ifndef XKM_OUTPUT_DIR_MODE +# define XKM_OUTPUT_DIR_MODE 0775 +# endif +#endif + static void OutputDirectory(char *outdir, size_t size) { #ifndef WIN32 +#ifdef MAKE_XKM_OUTPUT_DIR + if (geteuid() == 0 && trans_mkdir(XKM_OUTPUT_DIR, XKM_OUTPUT_DIR_MODE) == 0 && (strlen(XKM_OUTPUT_DIR) < size)) { +#else /* Can we write an xkm and then open it too? */ if (access(XKM_OUTPUT_DIR, W_OK | X_OK) == 0 && (strlen(XKM_OUTPUT_DIR) < size)) { - (void) strcpy(outdir, XKM_OUTPUT_DIR); +#endif + (void) strcpy (outdir, XKM_OUTPUT_DIR); } else #else @@ -113,6 +129,15 @@ XkbDDXCompileKeymapByNames(XkbDescPtr xkb, const char *xkmfile = "-"; #endif + /* save gid and reset to gid 0 before making xkm_output_dir or + running xkbcomp to create the xkm file in it. */ + gid_t usr_gid = getgid(); + + if (setregid(0, usr_gid) < 0) + ErrorF("Error in setting regid to 0: %s\n", strerror(errno)); + if (setegid(0) < 0) + ErrorF("Error in setting egid to 0: %s\n", strerror(errno)); + snprintf(keymap, sizeof(keymap), "server-%s", display); OutputDirectory(xkm_output_dir, sizeof(xkm_output_dir)); @@ -164,6 +189,11 @@ XkbDDXCompileKeymapByNames(XkbDescPtr xkb, out = fopen(tmpname, "w"); #endif + if (setregid(usr_gid, 0) < 0) + ErrorF("Error in resetting regid: %s\n", strerror(errno)); + if (setegid(usr_gid) < 0) + ErrorF("Error in resetting egid: %s\n", strerror(errno)); + if (out != NULL) { #ifdef DEBUG if (xkbDebugFlags) {