<div dir="ltr"><div><div><div><div>Sent that a little too soon; please consider "Reviewed-by: Ben Crocker <<a href="mailto:bcrocker@redhat.com">bcrocker@redhat.com</a>>" to be<br></div>added after each of the "Signed-off-by: Nicolai Haehnle <<a href="mailto:nicolai.haehnle@amd.com">nicolai.haehnle@amd.com</a>>" lines.<br><br></div>Also please note that I rebased Nicolai's original patch, <a href="https://patchwork.freedesktop.org/series/18684/">https://patchwork.freedesktop.org/series/18684/</a>,<br></div>against a very recent copy of master.<br><br></div> Thanks,<br><div> Ben<br><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Mar 8, 2018 at 4:53 PM, Ben Crocker <span dir="ltr"><<a href="mailto:bcrocker@redhat.com" target="_blank">bcrocker@redhat.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">From: Nicolai Hähnle <<a href="mailto:nhaehnle@gmail.com">nhaehnle@gmail.com</a>><br>
<div><div class="h5"><br>
From: Nicolai Hähnle <<a href="mailto:nicolai.haehnle@amd.com">nicolai.haehnle@amd.com</a>><br>
<br>
Having different types of code all trying to check for elevated privileges<br>
is a bad idea. This implementation is the most thorough one.<br>
<br>
Signed-off-by: Nicolai Hähnle <<a href="mailto:nicolai.haehnle@amd.com">nicolai.haehnle@amd.com</a>><br>
---<br>
hw/xfree86/common/xf86Init.c | 59 +-----------------------------<wbr>-----------<br>
include/os.h | 3 +++<br>
os/utils.c | 63 ++++++++++++++++++++++++++++++<wbr>++++++++++++++<br>
3 files changed, 67 insertions(+), 58 deletions(-)<br>
<br>
diff --git a/hw/xfree86/common/xf86Init.c b/hw/xfree86/common/xf86Init.c<br>
index e61fe66..758b926 100644<br>
--- a/hw/xfree86/common/xf86Init.c<br>
+++ b/hw/xfree86/common/xf86Init.c<br>
@@ -230,78 +230,21 @@ xf86PrintBanner(void)<br>
xf86ErrorFVerb(0, "Current version of pixman: %s\n",<br>
pixman_version_string());<br>
xf86ErrorFVerb(0, "\tBefore reporting problems, check "<br>
"" __VENDORDWEBSUPPORT__ "\n"<br>
"\tto make sure that you have the latest version.\n");<br>
}<br>
<br>
Bool<br>
xf86PrivsElevated(void)<br>
{<br>
- static Bool privsTested = FALSE;<br>
- static Bool privsElevated = TRUE;<br>
-<br>
- if (!privsTested) {<br>
-#if defined(WIN32)<br>
- privsElevated = FALSE;<br>
-#else<br>
- if ((getuid() != geteuid()) || (getgid() != getegid())) {<br>
- privsElevated = TRUE;<br>
- }<br>
- else {<br>
-#if defined(HAVE_ISSETUGID)<br>
- privsElevated = issetugid();<br>
-#elif defined(HAVE_GETRESUID)<br>
- uid_t ruid, euid, suid;<br>
- gid_t rgid, egid, sgid;<br>
-<br>
- if ((getresuid(&ruid, &euid, &suid) == 0) &&<br>
- (getresgid(&rgid, &egid, &sgid) == 0)) {<br>
- privsElevated = (euid != suid) || (egid != sgid);<br>
- }<br>
- else {<br>
- printf("Failed getresuid or getresgid");<br>
- /* Something went wrong, make defensive assumption */<br>
- privsElevated = TRUE;<br>
- }<br>
-#else<br>
- if (getuid() == 0) {<br>
- /* running as root: uid==euid==0 */<br>
- privsElevated = FALSE;<br>
- }<br>
- else {<br>
- /*<br>
- * If there are saved ID's the process might still be privileged<br>
- * even though the above test succeeded. If issetugid() and<br>
- * getresgid() aren't available, test this by trying to set<br>
- * euid to 0.<br>
- */<br>
- unsigned int oldeuid;<br>
-<br>
- oldeuid = geteuid();<br>
-<br>
- if (seteuid(0) != 0) {<br>
- privsElevated = FALSE;<br>
- }<br>
- else {<br>
- if (seteuid(oldeuid) != 0) {<br>
- FatalError("Failed to drop privileges. Exiting\n");<br>
- }<br>
- privsElevated = TRUE;<br>
- }<br>
- }<br>
-#endif<br>
- }<br>
-#endif<br>
- privsTested = TRUE;<br>
- }<br>
- return privsElevated;<br>
+ return PrivsElevated();<br>
}<br>
<br>
static void<br>
</div></div> TrapSignals(void)<br>
{<br>
if (xf86Info.notrapSignals) {<br>
OsSignal(SIGSEGV, SIG_DFL);<br>
OsSignal(SIGABRT, SIG_DFL);<br>
OsSignal(SIGILL, SIG_DFL);<br>
#ifdef SIGEMT<br>
<div><div class="h5">diff --git a/include/os.h b/include/os.h<br>
index d2c41b4..686f6d6 100644<br>
--- a/include/os.h<br>
+++ b/include/os.h<br>
@@ -355,20 +355,23 @@ Fclose(void *);<br>
extern const char *<br>
Win32TempDir(void);<br>
<br>
extern int<br>
System(const char *cmdline);<br>
<br>
#define Fopen(a,b) fopen(a,b)<br>
#define Fclose(a) fclose(a)<br>
#endif<br>
<br>
+extern _X_EXPORT Bool<br>
+PrivsElevated(void);<br>
+<br>
extern _X_EXPORT void<br>
CheckUserParameters(int argc, char **argv, char **envp);<br>
extern _X_EXPORT void<br>
CheckUserAuthorization(void);<br>
<br>
extern _X_EXPORT int<br>
AddHost(ClientPtr /*client */ ,<br>
int /*family */ ,<br>
unsigned /*length */ ,<br>
const void * /*pAddr */ );<br>
diff --git a/os/utils.c b/os/utils.c<br>
index ac55cd7..024989e 100644<br>
--- a/os/utils.c<br>
+++ b/os/utils.c<br>
@@ -1717,20 +1717,83 @@ System(const char *cmdline)<br>
<br>
/* Close process and thread handles. */<br>
CloseHandle(pi.hProcess);<br>
CloseHandle(pi.hThread);<br>
free(cmd);<br>
<br>
return dwExitCode;<br>
}<br>
#endif<br>
<br>
+Bool<br>
+PrivsElevated(void)<br>
+{<br>
+ static Bool privsTested = FALSE;<br>
+ static Bool privsElevated = TRUE;<br>
+<br>
+ if (!privsTested) {<br>
+#if defined(WIN32)<br>
+ privsElevated = FALSE;<br>
+#else<br>
+ if ((getuid() != geteuid()) || (getgid() != getegid())) {<br>
+ privsElevated = TRUE;<br>
+ }<br>
+ else {<br>
+#if defined(HAVE_ISSETUGID)<br>
+ privsElevated = issetugid();<br>
+#elif defined(HAVE_GETRESUID)<br>
+ uid_t ruid, euid, suid;<br>
+ gid_t rgid, egid, sgid;<br>
+<br>
+ if ((getresuid(&ruid, &euid, &suid) == 0) &&<br>
+ (getresgid(&rgid, &egid, &sgid) == 0)) {<br>
+ privsElevated = (euid != suid) || (egid != sgid);<br>
+ }<br>
+ else {<br>
+ printf("Failed getresuid or getresgid");<br>
+ /* Something went wrong, make defensive assumption */<br>
+ privsElevated = TRUE;<br>
+ }<br>
+#else<br>
+ if (getuid() == 0) {<br>
+ /* running as root: uid==euid==0 */<br>
+ privsElevated = FALSE;<br>
+ }<br>
+ else {<br>
+ /*<br>
+ * If there are saved ID's the process might still be privileged<br>
+ * even though the above test succeeded. If issetugid() and<br>
+ * getresgid() aren't available, test this by trying to set<br>
+ * euid to 0.<br>
+ */<br>
+ unsigned int oldeuid;<br>
+<br>
+ oldeuid = geteuid();<br>
+<br>
+ if (seteuid(0) != 0) {<br>
+ privsElevated = FALSE;<br>
+ }<br>
+ else {<br>
+ if (seteuid(oldeuid) != 0) {<br>
+ FatalError("Failed to drop privileges. Exiting\n");<br>
+ }<br>
+ privsElevated = TRUE;<br>
+ }<br>
+ }<br>
+#endif<br>
+ }<br>
+#endif<br>
+ privsTested = TRUE;<br>
+ }<br>
+ return privsElevated;<br>
+}<br>
+<br>
/*<br>
* CheckUserParameters: check for long command line arguments and long<br>
* environment variables. By default, these checks are only done when<br>
* the server's euid != ruid. In 3.3.x, these checks were done in an<br>
* external wrapper utility.<br>
*/<br>
<br>
/* Consider LD* variables insecure? */<br>
#ifndef REMOVE_ENV_LD<br>
#define REMOVE_ENV_LD 1<br>
<br>
</div></div>From patchwork Fri Jan 27 13:37:36 2017<br>
Content-Type: text/plain; charset="utf-8"<br>
MIME-Version: 1.0<br>
Content-Transfer-Encoding: 8bit<br>
Subject: [xserver,2/4] os: use PrivsElevated instead of a manual check<br>
From: =?utf-8?q?Nicolai_H=C3=A4hnle?<wbr>= <<a href="mailto:nhaehnle@gmail.com">nhaehnle@gmail.com</a>><br>
X-Patchwork-Id: 135711<br>
Message-Id: <<a href="mailto:1485524258-6482-3-git-send-email-nhaehnle@gmail.com">1485524258-6482-3-git-send-<wbr>email-nhaehnle@gmail.com</a>><br>
To: <a href="mailto:xorg-devel@lists.x.org">xorg-devel@lists.x.org</a><br>
Cc: =?UTF-8?q?Nicolai=20H=C3=<wbr>A4hnle?= <<a href="mailto:nicolai.haehnle@amd.com">nicolai.haehnle@amd.com</a>><br>
Date: Fri, 27 Jan 2017 14:37:36 +0100<br>
<br>
From: Nicolai Hähnle <<a href="mailto:nicolai.haehnle@amd.com">nicolai.haehnle@amd.com</a>><br>
<span class=""><br>
Signed-off-by: Nicolai Hähnle <<a href="mailto:nicolai.haehnle@amd.com">nicolai.haehnle@amd.com</a>><br>
---<br>
</span> os/utils.c | 2 +-<br>
1 file changed, 1 insertion(+), 1 deletion(-)<br>
<br>
diff --git a/os/utils.c b/os/utils.c<br>
index 024989e..05733b0 100644<br>
--- a/os/utils.c<br>
+++ b/os/utils.c<br>
@@ -1861,21 +1861,21 @@ enum BadCode {<br>
#endif<br>
<span class=""><br>
void<br>
CheckUserParameters(int argc, char **argv, char **envp)<br>
</span> {<br>
enum BadCode bad = NotBad;<br>
int i = 0, j;<br>
char *a, *e = NULL;<br>
<br>
#if CHECK_EUID<br>
- if (geteuid() == 0 && getuid() != geteuid())<br>
+ if (PrivsElevated())<br>
#endif<br>
{<br>
/* Check each argv[] */<br>
for (i = 1; i < argc; i++) {<br>
if (strcmp(argv[i], "-fp") == 0) {<br>
i++; /* continue with next argument. skip the length check */<br>
if (i >= argc)<br>
break;<br>
}<br>
else {<br>
<br>
>From patchwork Fri Jan 27 13:37:37 2017<br>
Content-Type: text/plain; charset="utf-8"<br>
MIME-Version: 1.0<br>
Content-Transfer-Encoding: 8bit<br>
Subject: [xserver, 3/4] xfree86: replace all uses of xf86PrivsElevated with<br>
PrivsElevated<br>
From: =?utf-8?q?Nicolai_H=C3=A4hnle?<wbr>= <<a href="mailto:nhaehnle@gmail.com">nhaehnle@gmail.com</a>><br>
X-Patchwork-Id: 135712<br>
Message-Id: <<a href="mailto:1485524258-6482-4-git-send-email-nhaehnle@gmail.com">1485524258-6482-4-git-send-<wbr>email-nhaehnle@gmail.com</a>><br>
To: <a href="mailto:xorg-devel@lists.x.org">xorg-devel@lists.x.org</a><br>
Cc: =?UTF-8?q?Nicolai=20H=C3=<wbr>A4hnle?= <<a href="mailto:nicolai.haehnle@amd.com">nicolai.haehnle@amd.com</a>><br>
Date: Fri, 27 Jan 2017 14:37:37 +0100<br>
<br>
From: Nicolai Hähnle <<a href="mailto:nicolai.haehnle@amd.com">nicolai.haehnle@amd.com</a>><br>
<span class=""><br>
Signed-off-by: Nicolai Hähnle <<a href="mailto:nicolai.haehnle@amd.com">nicolai.haehnle@amd.com</a>><br>
---<br>
</span> hw/xfree86/common/xf86Config.c | 2 +-<br>
hw/xfree86/common/xf86Init.c | 12 +++---------<br>
hw/xfree86/common/xf86Priv.h | 2 --<br>
3 files changed, 4 insertions(+), 12 deletions(-)<br>
<br>
diff --git a/hw/xfree86/common/<wbr>xf86Config.c b/hw/xfree86/common/<wbr>xf86Config.c<br>
index f03acf3..5d2cf0a 100644<br>
--- a/hw/xfree86/common/<wbr>xf86Config.c<br>
+++ b/hw/xfree86/common/<wbr>xf86Config.c<br>
@@ -2309,21 +2309,21 @@ xf86HandleConfigFile(Bool autoconfig)<br>
#endif<br>
Bool implicit_layout = FALSE;<br>
XF86ConfLayoutPtr layout;<br>
<br>
if (!autoconfig) {<br>
char *filename, *dirname, *sysdirname;<br>
const char *filesearch, *dirsearch;<br>
MessageType filefrom = X_DEFAULT;<br>
MessageType dirfrom = X_DEFAULT;<br>
<br>
- if (!xf86PrivsElevated()) {<br>
+ if (!PrivsElevated()) {<br>
filesearch = ALL_CONFIGPATH;<br>
dirsearch = ALL_CONFIGDIRPATH;<br>
}<br>
else {<br>
filesearch = RESTRICTED_CONFIGPATH;<br>
dirsearch = RESTRICTED_CONFIGDIRPATH;<br>
}<br>
<br>
if (xf86ConfigFile)<br>
filefrom = X_CMDLINE;<br>
diff --git a/hw/xfree86/common/xf86Init.c b/hw/xfree86/common/xf86Init.c<br>
index 758b926..deed91f 100644<br>
--- a/hw/xfree86/common/xf86Init.c<br>
+++ b/hw/xfree86/common/xf86Init.c<br>
@@ -227,26 +227,20 @@ xf86PrintBanner(void)<br>
#if defined(BUILDERSTRING)<br>
xf86ErrorFVerb(0, "%s \n", BUILDERSTRING);<br>
#endif<br>
<span class=""> xf86ErrorFVerb(0, "Current version of pixman: %s\n",<br>
pixman_version_string());<br>
xf86ErrorFVerb(0, "\tBefore reporting problems, check "<br>
"" __VENDORDWEBSUPPORT__ "\n"<br>
"\tto make sure that you have the latest version.\n");<br>
}<br>
<br>
</span>-Bool<br>
-xf86PrivsElevated(void)<br>
-{<br>
- return PrivsElevated();<br>
-}<br>
-<br>
static void<br>
TrapSignals(void)<br>
{<br>
if (xf86Info.notrapSignals) {<br>
OsSignal(SIGSEGV, SIG_DFL);<br>
OsSignal(SIGABRT, SIG_DFL);<br>
OsSignal(SIGILL, SIG_DFL);<br>
#ifdef SIGEMT<br>
OsSignal(SIGEMT, SIG_DFL);<br>
#endif<br>
@@ -886,21 +880,21 @@ OsVendorInit(void)<br>
/* Set stderr to non-blocking. */<br>
#ifndef O_NONBLOCK<br>
#if defined(FNDELAY)<br>
#define O_NONBLOCK FNDELAY<br>
#elif defined(O_NDELAY)<br>
#define O_NONBLOCK O_NDELAY<br>
#endif<br>
<br>
#ifdef O_NONBLOCK<br>
if (!beenHere) {<br>
- if (xf86PrivsElevated()) {<br>
+ if (PrivsElevated()) {<br>
int status;<br>
<br>
status = fcntl(fileno(stderr), F_GETFL, 0);<br>
if (status != -1) {<br>
fcntl(fileno(stderr), F_SETFL, status | O_NONBLOCK);<br>
}<br>
}<br>
}<br>
#endif<br>
#endif<br>
@@ -1041,21 +1035,21 @@ xf86PrintDefaultModulePath(<wbr>void)<br>
<br>
static void<br>
xf86PrintDefaultLibraryPath(<wbr>void)<br>
{<br>
ErrorF("%s\n", DEFAULT_LIBRARY_PATH);<br>
}<br>
<br>
static void<br>
xf86CheckPrivs(const char *option, const char *arg)<br>
{<br>
- if (xf86PrivsElevated() && !xf86PathIsSafe(arg)) {<br>
+ if (PrivsElevated() && !xf86PathIsSafe(arg)) {<br>
FatalError("\nInvalid argument for %s - \"%s\"\n"<br>
"\tWith elevated privileges %s must specify a relative path\n"<br>
"\twithout any \"..\" elements.\n\n", option, arg, option);<br>
}<br>
}<br>
<br>
/*<br>
* ddxProcessArgument --<br>
* Process device-dependent command line args. Returns 0 if argument is<br>
* not device dependent, otherwise Count of number of elements of argv<br>
@@ -1342,21 +1336,21 @@ ddxProcessArgument(int argc, char **argv, int i)<br>
* Print out correct use of device dependent commandline options.<br>
* Maybe the user now knows what really to do ...<br>
*/<br>
<br>
void<br>
ddxUseMsg(void)<br>
{<br>
ErrorF("\n");<br>
ErrorF("\n");<br>
ErrorF("Device Dependent Usage\n");<br>
- if (!xf86PrivsElevated()) {<br>
+ if (!PrivsElevated()) {<br>
ErrorF("-modulepath paths specify the module search path\n");<br>
ErrorF("-logfile file specify a log file name\n");<br>
ErrorF("-configure probe for devices and write an "<br>
XCONFIGFILE "\n");<br>
ErrorF<br>
("-showopts print available options for all installed drivers\n");<br>
}<br>
ErrorF<br>
("-config file specify a configuration file, relative to the\n");<br>
ErrorF(" " XCONFIGFILE<br>
diff --git a/hw/xfree86/common/xf86Priv.h b/hw/xfree86/common/xf86Priv.h<br>
index c1f8a18..d78e8f6 100644<br>
--- a/hw/xfree86/common/xf86Priv.h<br>
+++ b/hw/xfree86/common/xf86Priv.h<br>
@@ -154,16 +154,14 @@ xf86CloseLog(enum ExitCode error);<br>
<br>
/* xf86Init.c */<br>
extern _X_EXPORT Bool<br>
xf86LoadModules(const char **list, void **optlist);<br>
extern _X_EXPORT int<br>
xf86SetVerbosity(int verb);<br>
extern _X_EXPORT int<br>
xf86SetLogVerbosity(int verb);<br>
extern _X_EXPORT Bool<br>
xf86CallDriverProbe(struct _DriverRec *drv, Bool detect_only);<br>
-extern _X_EXPORT Bool<br>
-xf86PrivsElevated(void);<br>
<br>
#endif /* _NO_XF86_PROTOTYPES */<br>
<br>
#endif /* _XF86PRIV_H */<br>
<br>
>From patchwork Fri Jan 27 13:37:38 2017<br>
Content-Type: text/plain; charset="utf-8"<br>
MIME-Version: 1.0<br>
Content-Transfer-Encoding: 8bit<br>
Subject: [xserver,4/4] glx: honor LIBGL_DRIVERS_PATH when loading DRI drivers<br>
From: =?utf-8?q?Nicolai_H=C3=A4hnle?<wbr>= <<a href="mailto:nhaehnle@gmail.com">nhaehnle@gmail.com</a>><br>
X-Patchwork-Id: 135713<br>
Message-Id: <<a href="mailto:1485524258-6482-5-git-send-email-nhaehnle@gmail.com">1485524258-6482-5-git-send-<wbr>email-nhaehnle@gmail.com</a>><br>
To: <a href="mailto:xorg-devel@lists.x.org">xorg-devel@lists.x.org</a><br>
Cc: =?UTF-8?q?Nicolai=20H=C3=<wbr>A4hnle?= <<a href="mailto:nicolai.haehnle@amd.com">nicolai.haehnle@amd.com</a>><br>
Date: Fri, 27 Jan 2017 14:37:38 +0100<br>
<br>
From: Nicolai Hähnle <<a href="mailto:nicolai.haehnle@amd.com">nicolai.haehnle@amd.com</a>><br>
<br>
Allow switching to another driver build without a full installation.<br>
<br>
Glamor already takes LIBGL_DRIVERS_PATH into account, so this change<br>
makes sure that the same driver is used in both parts of the server.<br>
<span class=""><br>
Signed-off-by: Nicolai Hähnle <<a href="mailto:nicolai.haehnle@amd.com">nicolai.haehnle@amd.com</a>><br>
---<br>
</span> glx/glxdricommon.c | 38 ++++++++++++++++++++++++++++++<wbr>++++----<br>
1 file changed, 34 insertions(+), 4 deletions(-)<br>
<br>
diff --git a/glx/glxdricommon.c b/glx/glxdricommon.c<br>
index f6c6fcd..a370845 100644<br>
--- a/glx/glxdricommon.c<br>
+++ b/glx/glxdricommon.c<br>
@@ -241,28 +241,58 @@ static const char dri_driver_path[] = DRI_DRIVER_PATH;<br>
void *<br>
glxProbeDriver(const char *driverName,<br>
void **coreExt, const char *coreName, int coreVersion,<br>
void **renderExt, const char *renderName, int renderVersion)<br>
{<br>
int i;<br>
void *driver;<br>
char filename[PATH_MAX];<br>
char *get_extensions_name;<br>
const __DRIextension **extensions = NULL;<br>
+ const char *path = NULL;<br>
+<br>
+ /* Search in LIBGL_DRIVERS_PATH if we're not setuid. */<br>
+ if (!PrivsElevated())<br>
+ path = getenv("LIBGL_DRIVERS_PATH");<br>
+<br>
+ if (!path)<br>
+ path = dri_driver_path;<br>
+<br>
+ do {<br>
+ const char *next;<br>
+ int path_len;<br>
+<br>
+ next = strchr(path, ':');<br>
+ if (next) {<br>
+ path_len = next - path;<br>
+ next++;<br>
+ } else {<br>
+ path_len = strlen(path);<br>
+ next = NULL;<br>
+ }<br>
<br>
- snprintf(filename, sizeof filename, "%s/%s_dri.so",<br>
- dri_driver_path, driverName);<br>
+ snprintf(filename, sizeof filename, "%.*s/%s_dri.so", path_len, path,<br>
+ driverName);<br>
+<br>
+ driver = dlopen(filename, RTLD_LAZY | RTLD_LOCAL);<br>
+ if (driver != NULL)<br>
+ break;<br>
<br>
- driver = dlopen(filename, RTLD_LAZY | RTLD_LOCAL);<br>
- if (driver == NULL) {<br>
LogMessage(X_ERROR, "AIGLX error: dlopen of %s failed (%s)\n",<br>
filename, dlerror());<br>
+<br>
+ path = next;<br>
+ } while (path);<br>
+<br>
+ if (driver == NULL) {<br>
+ LogMessage(X_ERROR, "AIGLX error: unable to load driver %s\n",<br>
+ driverName);<br>
goto cleanup_failure;<br>
}<br>
<br>
if (asprintf(&get_extensions_<wbr>name, "%s_%s",<br>
__DRI_DRIVER_GET_EXTENSIONS, driverName) != -1) {<br>
const __DRIextension **(*get_extensions)(void);<br>
<br>
get_extensions = dlsym(driver, get_extensions_name);<br>
if (get_extensions)<br>
extensions = get_extensions();<br>
</blockquote></div><br></div>