Use multilib rules to look for a 64-bit group plugin on failure.
If sudo_dso_load() fails on a 64-bit system, try to load a 64-bit native version of the file using system-dependent multilib rules. If we don't support multilib on the platform, check for a version of the file that ends in "64" before the .so suffix.
This commit is contained in:
@@ -25,7 +25,7 @@
|
||||
.nr BA @BAMAN@
|
||||
.nr LC @LCMAN@
|
||||
.nr PS @PSMAN@
|
||||
.TH "SUDOERS" "@mansectform@" "July 29, 2022" "Sudo @PACKAGE_VERSION@" "File Formats Manual"
|
||||
.TH "SUDOERS" "@mansectform@" "August 11, 2022" "Sudo @PACKAGE_VERSION@" "File Formats Manual"
|
||||
.nh
|
||||
.if n .ad l
|
||||
.SH "NAME"
|
||||
@@ -3410,7 +3410,7 @@ has completed but before the new command has had a chance to run.
|
||||
In the case of a path name or argument mismatch, the command will be sent a
|
||||
\fRSIGKILL\fR
|
||||
signal and terminated.
|
||||
This can help prevent a time of check vs. time of use issue with
|
||||
This can help prevent a time of check versus time of use issue with
|
||||
intercept mode where the
|
||||
execve(2)
|
||||
arguments could be altered after the
|
||||
@@ -4979,6 +4979,34 @@ These arguments (if any) will be passed to the plugin's initialization function.
|
||||
If arguments are present, the string must be enclosed in double quotes
|
||||
(\&"").
|
||||
.sp
|
||||
On 64-bit systems, if the plugin is present but cannot be loaded,
|
||||
\fBsudoers\fR
|
||||
will look for a 64-bit version and, if it exists, load that as a fallback.
|
||||
The exact rules for this vary by system.
|
||||
On Solaris, if the plugin is stored in a directory ending in
|
||||
\(lqlib\(rq,
|
||||
\fBsudoers\fR
|
||||
will create a fallback path by appending
|
||||
\(lq/64\(rq
|
||||
to the directory name;
|
||||
\fI/usr/lib/sudo_plugin.so\fR
|
||||
becomes
|
||||
\fI/usr/lib/64/sudo_plugin.so\fR.
|
||||
On Linux, a directory ending in
|
||||
\(lqlib\(rq
|
||||
will be transformed to
|
||||
\(lqlib64\(rq
|
||||
as the fallback path;
|
||||
\fI/usr/lib/sudo_plugin.so\fR
|
||||
becomes
|
||||
\fI/usr/lib64/sudo_plugin.so\fR.
|
||||
On all other systems, the fallback path is generated by adding a
|
||||
\(lq64\(rq
|
||||
before the file extension;
|
||||
\fIsudo_plugin.so\fR
|
||||
becomes
|
||||
\fIsudo_plugin64.so\fR.
|
||||
.sp
|
||||
For more information see
|
||||
\fIGROUP PROVIDER PLUGINS\fR.
|
||||
.TP 14n
|
||||
|
@@ -25,7 +25,7 @@
|
||||
.nr BA @BAMAN@
|
||||
.nr LC @LCMAN@
|
||||
.nr PS @PSMAN@
|
||||
.Dd July 29, 2022
|
||||
.Dd August 11, 2022
|
||||
.Dt SUDOERS @mansectform@
|
||||
.Os Sudo @PACKAGE_VERSION@
|
||||
.Sh NAME
|
||||
@@ -3231,7 +3231,7 @@ has completed but before the new command has had a chance to run.
|
||||
In the case of a path name or argument mismatch, the command will be sent a
|
||||
.Dv SIGKILL
|
||||
signal and terminated.
|
||||
This can help prevent a time of check vs. time of use issue with
|
||||
This can help prevent a time of check versus time of use issue with
|
||||
intercept mode where the
|
||||
.Xr execve 2
|
||||
arguments could be altered after the
|
||||
@@ -4690,6 +4690,34 @@ These arguments (if any) will be passed to the plugin's initialization function.
|
||||
If arguments are present, the string must be enclosed in double quotes
|
||||
.Pq \&"" .
|
||||
.Pp
|
||||
On 64-bit systems, if the plugin is present but cannot be loaded,
|
||||
.Nm
|
||||
will look for a 64-bit version and, if it exists, load that as a fallback.
|
||||
The exact rules for this vary by system.
|
||||
On Solaris, if the plugin is stored in a directory ending in
|
||||
.Dq lib ,
|
||||
.Nm
|
||||
will create a fallback path by appending
|
||||
.Dq /64
|
||||
to the directory name;
|
||||
.Pa /usr/lib/sudo_plugin.so
|
||||
becomes
|
||||
.Pa /usr/lib/64/sudo_plugin.so .
|
||||
On Linux, a directory ending in
|
||||
.Dq lib
|
||||
will be transformed to
|
||||
.Dq lib64
|
||||
as the fallback path;
|
||||
.Pa /usr/lib/sudo_plugin.so
|
||||
becomes
|
||||
.Pa /usr/lib64/sudo_plugin.so .
|
||||
On all other systems, the fallback path is generated by adding a
|
||||
.Dq 64
|
||||
before the file extension;
|
||||
.Pa sudo_plugin.so
|
||||
becomes
|
||||
.Pa sudo_plugin64.so .
|
||||
.Pp
|
||||
For more information see
|
||||
.Sx "GROUP PROVIDER PLUGINS" .
|
||||
.It lecture
|
||||
|
@@ -40,6 +40,90 @@ static void *group_handle;
|
||||
static struct sudoers_group_plugin *group_plugin;
|
||||
const char *path_plugin_dir = _PATH_SUDO_PLUGIN_DIR;
|
||||
|
||||
/*
|
||||
* Check for a fallback path when the original group plugin is not loadable.
|
||||
* Returns true on success, rewriting path and filling in sb, else false.
|
||||
*/
|
||||
static bool
|
||||
group_plugin_fallback(char *path, size_t pathsize, struct stat *sb)
|
||||
{
|
||||
#if defined(__LP64__)
|
||||
char newpath[PATH_MAX];
|
||||
bool ret = false;
|
||||
int len;
|
||||
debug_decl(group_plugin_fallback, SUDOERS_DEBUG_UTIL);
|
||||
|
||||
# if defined(__sun__) || defined(__linux__)
|
||||
/*
|
||||
* Solaris uses /lib/64 and /usr/lib/64 for 64-bit libraries.
|
||||
* Linux may use /lib64 and /usr/lib64 for 64-bit libraries.
|
||||
* If dirname(path) ends in /lib, try /lib/64 (Solaris) or /lib64 (Linux).
|
||||
*/
|
||||
# if defined(__sun__)
|
||||
const char *lib64 = "lib/64";
|
||||
# else
|
||||
const char *lib64 = "lib64";
|
||||
# endif
|
||||
const char *base, *slash;
|
||||
int dirlen;
|
||||
|
||||
slash = strrchr(path, '/');
|
||||
if (slash == NULL) {
|
||||
goto done;
|
||||
}
|
||||
base = slash + 1;
|
||||
|
||||
/* Collapse consecutive slashes. */
|
||||
while (slash > path && slash[-1] == '/') {
|
||||
slash--;
|
||||
}
|
||||
|
||||
/* If directory ends in /lib/, try again with /lib/64/ or /lib64/. */
|
||||
dirlen = slash - path;
|
||||
if (dirlen < 4 || strncmp(slash - 4, "/lib", 4) != 0) {
|
||||
goto done;
|
||||
}
|
||||
dirlen -= 4;
|
||||
len = snprintf(newpath, sizeof(newpath), "%.*s/%s/%s", dirlen, path, lib64,
|
||||
base);
|
||||
# else /* !__sun__ && !__linux__ */
|
||||
/*
|
||||
* Multilib not supported, check for a path of the form libfoo64.so.
|
||||
*/
|
||||
const char *dot;
|
||||
int plen;
|
||||
|
||||
dot = strrchr(path, '.');
|
||||
if (dot == NULL) {
|
||||
goto done;
|
||||
}
|
||||
plen = dot - path;
|
||||
|
||||
/* If basename(path) doesn't match libfoo64.so, try adding the 64. */
|
||||
if (plen >= 2 && strncmp(dot - 2, "64", 2) == 0) {
|
||||
goto done;
|
||||
}
|
||||
len = snprintf(newpath, sizeof(newpath), "%.*s64%s", plen, path, dot);
|
||||
# endif /* __sun__ || __linux__ */
|
||||
if (len < 0 || len >= ssizeof(newpath)) {
|
||||
errno = ENAMETOOLONG;
|
||||
goto done;
|
||||
}
|
||||
if (stat(newpath, sb) == -1) {
|
||||
goto done;
|
||||
}
|
||||
if (strlcpy(path, newpath, pathsize) >= pathsize) {
|
||||
errno = ENAMETOOLONG;
|
||||
goto done;
|
||||
}
|
||||
ret = true;
|
||||
done:
|
||||
debug_return_bool(ret);
|
||||
#else
|
||||
return false;
|
||||
#endif /* __LP64__ */
|
||||
}
|
||||
|
||||
/*
|
||||
* Load the specified plugin and run its init function.
|
||||
* Returns -1 if unable to open the plugin, else it returns
|
||||
@@ -52,6 +136,7 @@ group_plugin_load(const char *plugin_info)
|
||||
char *args, path[PATH_MAX];
|
||||
char **argv = NULL;
|
||||
int len, rc = -1;
|
||||
bool retry = true;
|
||||
debug_decl(group_plugin_load, SUDOERS_DEBUG_UTIL);
|
||||
|
||||
/*
|
||||
@@ -72,13 +157,14 @@ group_plugin_load(const char *plugin_info)
|
||||
(*plugin_info != '/') ? path_plugin_dir : "", plugin_info);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Check owner and mode of plugin path. */
|
||||
if (stat(path, &sb) != 0) {
|
||||
sudo_warn("%s", path);
|
||||
goto done;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
if (!sudo_conf_developer_mode()) {
|
||||
/* Check owner and mode of plugin path. */
|
||||
if (sb.st_uid != ROOT_UID) {
|
||||
sudo_warnx(U_("%s must be owned by uid %d"), path, ROOT_UID);
|
||||
goto done;
|
||||
@@ -89,14 +175,23 @@ group_plugin_load(const char *plugin_info)
|
||||
}
|
||||
}
|
||||
|
||||
/* Open plugin and map in symbol. */
|
||||
group_handle = sudo_dso_load(path, SUDO_DSO_LAZY|SUDO_DSO_GLOBAL);
|
||||
if (!group_handle) {
|
||||
if (group_handle != NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!retry || !group_plugin_fallback(path, sizeof(path), &sb)) {
|
||||
const char *errstr = sudo_dso_strerror();
|
||||
sudo_warnx(U_("unable to load %s: %s"), path,
|
||||
errstr ? errstr : "unknown error");
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Retry once with the fallback path. */
|
||||
retry = false;
|
||||
}
|
||||
|
||||
/* Map in symbol from group plugin. */
|
||||
group_plugin = sudo_dso_findsym(group_handle, "group_plugin");
|
||||
if (group_plugin == NULL) {
|
||||
sudo_warnx(U_("unable to find symbol \"group_plugin\" in %s"), path);
|
||||
|
Reference in New Issue
Block a user