Apply multiarch rules when loading plugins too.
This commit is contained in:
2
MANIFEST
2
MANIFEST
@@ -253,6 +253,7 @@ lib/util/mksiglist.c
|
|||||||
lib/util/mksigname.c
|
lib/util/mksigname.c
|
||||||
lib/util/mktemp.c
|
lib/util/mktemp.c
|
||||||
lib/util/mmap_alloc.c
|
lib/util/mmap_alloc.c
|
||||||
|
lib/util/multiarch.c
|
||||||
lib/util/nanosleep.c
|
lib/util/nanosleep.c
|
||||||
lib/util/openat.c
|
lib/util/openat.c
|
||||||
lib/util/parseln.c
|
lib/util/parseln.c
|
||||||
@@ -280,6 +281,7 @@ lib/util/regress/glob/globtest.c
|
|||||||
lib/util/regress/glob/globtest.in
|
lib/util/regress/glob/globtest.in
|
||||||
lib/util/regress/harness.in
|
lib/util/regress/harness.in
|
||||||
lib/util/regress/mktemp/mktemp_test.c
|
lib/util/regress/mktemp/mktemp_test.c
|
||||||
|
lib/util/regress/multiarch/multiarch_test.c
|
||||||
lib/util/regress/open_parent_dir/open_parent_dir_test.c
|
lib/util/regress/open_parent_dir/open_parent_dir_test.c
|
||||||
lib/util/regress/parse_gids/parse_gids_test.c
|
lib/util/regress/parse_gids/parse_gids_test.c
|
||||||
lib/util/regress/progname/progname_test.c
|
lib/util/regress/progname/progname_test.c
|
||||||
|
@@ -262,6 +262,10 @@ sudo_dso_public void sudo_mmap_free_v1(void *ptr);
|
|||||||
sudo_dso_public int sudo_mmap_protect_v1(void *ptr);
|
sudo_dso_public int sudo_mmap_protect_v1(void *ptr);
|
||||||
#define sudo_mmap_protect(_a) sudo_mmap_protect_v1(_a)
|
#define sudo_mmap_protect(_a) sudo_mmap_protect_v1(_a)
|
||||||
|
|
||||||
|
/* multiarch.c */
|
||||||
|
sudo_dso_public char *sudo_stat_multiarch_v1(const char *path, struct stat *sb);
|
||||||
|
#define sudo_stat_multiarch(_a, _b) sudo_stat_multiarch_v1((_a), (_b))
|
||||||
|
|
||||||
/* parseln.c */
|
/* parseln.c */
|
||||||
sudo_dso_public ssize_t sudo_parseln_v1(char **buf, size_t *bufsize, unsigned int *lineno, FILE *fp);
|
sudo_dso_public ssize_t sudo_parseln_v1(char **buf, size_t *bufsize, unsigned int *lineno, FILE *fp);
|
||||||
sudo_dso_public ssize_t sudo_parseln_v2(char **buf, size_t *bufsize, unsigned int *lineno, FILE *fp, int flags);
|
sudo_dso_public ssize_t sudo_parseln_v2(char **buf, size_t *bufsize, unsigned int *lineno, FILE *fp, int flags);
|
||||||
|
@@ -111,8 +111,8 @@ PVS_IGNORE = 'V707,V011,V002,V536'
|
|||||||
PVS_LOG_OPTS = -a 'GA:1,2' -e -t errorfile -d $(PVS_IGNORE)
|
PVS_LOG_OPTS = -a 'GA:1,2' -e -t errorfile -d $(PVS_IGNORE)
|
||||||
|
|
||||||
# Regression tests
|
# Regression tests
|
||||||
TEST_PROGS = conf_test hltq_test parseln_test progname_test \
|
TEST_PROGS = conf_test hltq_test parseln_test progname_test parse_gids_test \
|
||||||
parse_gids_test getgids getgrouplist_test open_parent_dir_test \
|
getgids getgrouplist_test multiarch_test open_parent_dir_test \
|
||||||
strsplit_test strtobool_test strtoid_test strtomode_test \
|
strsplit_test strtobool_test strtoid_test strtomode_test \
|
||||||
strtonum_test uuid_test @COMPAT_TEST_PROGS@
|
strtonum_test uuid_test @COMPAT_TEST_PROGS@
|
||||||
TEST_LIBS = @LIBS@
|
TEST_LIBS = @LIBS@
|
||||||
@@ -144,11 +144,11 @@ SHELL = @SHELL@
|
|||||||
|
|
||||||
LTOBJS = basename.lo @DIGEST@ event.lo fatal.lo key_val.lo gethostname.lo \
|
LTOBJS = basename.lo @DIGEST@ event.lo fatal.lo key_val.lo gethostname.lo \
|
||||||
gettime.lo getgrouplist.lo gidlist.lo json.lo lbuf.lo locking.lo \
|
gettime.lo getgrouplist.lo gidlist.lo json.lo lbuf.lo locking.lo \
|
||||||
logfac.lo logpri.lo mkdir_parents.lo mmap_alloc.lo parseln.lo \
|
logfac.lo logpri.lo mkdir_parents.lo mmap_alloc.lo multiarch.lo \
|
||||||
progname.lo rcstr.lo regex.lo roundup.lo secure_path.lo setgroups.lo \
|
parseln.lo progname.lo rcstr.lo regex.lo roundup.lo secure_path.lo \
|
||||||
strsplit.lo strtobool.lo strtoid.lo strtomode.lo strtonum.lo \
|
setgroups.lo strsplit.lo strtobool.lo strtoid.lo strtomode.lo \
|
||||||
sudo_conf.lo sudo_debug.lo sudo_dso.lo term.lo ttyname_dev.lo \
|
strtonum.lo sudo_conf.lo sudo_debug.lo sudo_dso.lo term.lo \
|
||||||
ttysize.lo uuid.lo @COMMON_OBJS@ @LTLIBOBJS@
|
ttyname_dev.lo ttysize.lo uuid.lo @COMMON_OBJS@ @LTLIBOBJS@
|
||||||
|
|
||||||
IOBJS = $(LTOBJS:.lo=.i)
|
IOBJS = $(LTOBJS:.lo=.i)
|
||||||
|
|
||||||
@@ -172,6 +172,8 @@ GLOBTEST_OBJS = globtest.lo glob.lo
|
|||||||
|
|
||||||
GETDELIM_TEST_OBJS = getdelim_test.lo getdelim.lo
|
GETDELIM_TEST_OBJS = getdelim_test.lo getdelim.lo
|
||||||
|
|
||||||
|
MULTIARCH_TEST_OBJS = multiarch_test.lo multiarch.lo
|
||||||
|
|
||||||
OPEN_PARENT_DIR_TEST_OBJS = open_parent_dir_test.lo mkdir_parents.lo
|
OPEN_PARENT_DIR_TEST_OBJS = open_parent_dir_test.lo mkdir_parents.lo
|
||||||
|
|
||||||
STRTOBOOL_TEST_OBJS = strtobool_test.lo strtobool.lo
|
STRTOBOOL_TEST_OBJS = strtobool_test.lo strtobool.lo
|
||||||
@@ -285,6 +287,9 @@ hltq_test: $(HLTQ_TEST_OBJS) libsudo_util.la
|
|||||||
mktemp_test: $(MKTEMP_TEST_OBJS) libsudo_util.la
|
mktemp_test: $(MKTEMP_TEST_OBJS) libsudo_util.la
|
||||||
$(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(MKTEMP_TEST_OBJS) libsudo_util.la $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(TEST_LDFLAGS) $(TEST_LIBS)
|
$(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(MKTEMP_TEST_OBJS) libsudo_util.la $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(TEST_LDFLAGS) $(TEST_LIBS)
|
||||||
|
|
||||||
|
multiarch_test: $(MULTIARCH_TEST_OBJS) libsudo_util.la
|
||||||
|
$(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(MULTIARCH_TEST_OBJS) libsudo_util.la $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(TEST_LDFLAGS) $(TEST_LIBS)
|
||||||
|
|
||||||
open_parent_dir_test: $(OPEN_PARENT_DIR_TEST_OBJS) libsudo_util.la
|
open_parent_dir_test: $(OPEN_PARENT_DIR_TEST_OBJS) libsudo_util.la
|
||||||
$(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(OPEN_PARENT_DIR_TEST_OBJS) libsudo_util.la $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(TEST_LDFLAGS) $(TEST_LIBS)
|
$(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(OPEN_PARENT_DIR_TEST_OBJS) libsudo_util.la $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(TEST_LDFLAGS) $(TEST_LIBS)
|
||||||
|
|
||||||
@@ -460,6 +465,7 @@ check: $(TEST_PROGS) check-fuzzer
|
|||||||
./strsig_test || rval=`expr $$rval + $$?`; \
|
./strsig_test || rval=`expr $$rval + $$?`; \
|
||||||
fi; \
|
fi; \
|
||||||
./getgrouplist_test || rval=`expr $$rval + $$?`; \
|
./getgrouplist_test || rval=`expr $$rval + $$?`; \
|
||||||
|
./multiarch_test || rval=`expr $$rval + $$?`; \
|
||||||
./open_parent_dir_test || rval=`expr $$rval + $$?`; \
|
./open_parent_dir_test || rval=`expr $$rval + $$?`; \
|
||||||
./strtobool_test || rval=`expr $$rval + $$?`; \
|
./strtobool_test || rval=`expr $$rval + $$?`; \
|
||||||
./strtoid_test || rval=`expr $$rval + $$?`; \
|
./strtoid_test || rval=`expr $$rval + $$?`; \
|
||||||
@@ -1111,6 +1117,28 @@ mmap_alloc.i: $(srcdir)/mmap_alloc.c $(incdir)/compat/stdbool.h \
|
|||||||
$(CC) -E -o $@ $(CPPFLAGS) $<
|
$(CC) -E -o $@ $(CPPFLAGS) $<
|
||||||
mmap_alloc.plog: mmap_alloc.i
|
mmap_alloc.plog: mmap_alloc.i
|
||||||
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/mmap_alloc.c --i-file $< --output-file $@
|
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/mmap_alloc.c --i-file $< --output-file $@
|
||||||
|
multiarch.lo: $(srcdir)/multiarch.c $(incdir)/compat/stdbool.h \
|
||||||
|
$(incdir)/sudo_compat.h $(incdir)/sudo_util.h \
|
||||||
|
$(top_builddir)/config.h
|
||||||
|
$(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/multiarch.c
|
||||||
|
multiarch.i: $(srcdir)/multiarch.c $(incdir)/compat/stdbool.h \
|
||||||
|
$(incdir)/sudo_compat.h $(incdir)/sudo_util.h \
|
||||||
|
$(top_builddir)/config.h
|
||||||
|
$(CC) -E -o $@ $(CPPFLAGS) $<
|
||||||
|
multiarch.plog: multiarch.i
|
||||||
|
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/multiarch.c --i-file $< --output-file $@
|
||||||
|
multiarch_test.lo: $(srcdir)/regress/multiarch/multiarch_test.c \
|
||||||
|
$(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
|
||||||
|
$(incdir)/sudo_fatal.h $(incdir)/sudo_plugin.h \
|
||||||
|
$(incdir)/sudo_util.h $(top_builddir)/config.h
|
||||||
|
$(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/multiarch/multiarch_test.c
|
||||||
|
multiarch_test.i: $(srcdir)/regress/multiarch/multiarch_test.c \
|
||||||
|
$(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
|
||||||
|
$(incdir)/sudo_fatal.h $(incdir)/sudo_plugin.h \
|
||||||
|
$(incdir)/sudo_util.h $(top_builddir)/config.h
|
||||||
|
$(CC) -E -o $@ $(CPPFLAGS) $<
|
||||||
|
multiarch_test.plog: multiarch_test.i
|
||||||
|
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/multiarch/multiarch_test.c --i-file $< --output-file $@
|
||||||
nanosleep.lo: $(srcdir)/nanosleep.c $(incdir)/compat/stdbool.h \
|
nanosleep.lo: $(srcdir)/nanosleep.c $(incdir)/compat/stdbool.h \
|
||||||
$(incdir)/sudo_compat.h $(incdir)/sudo_util.h \
|
$(incdir)/sudo_compat.h $(incdir)/sudo_util.h \
|
||||||
$(top_builddir)/config.h
|
$(top_builddir)/config.h
|
||||||
@@ -1527,11 +1555,13 @@ sudo_debug.i: $(srcdir)/sudo_debug.c $(incdir)/compat/stdbool.h \
|
|||||||
$(CC) -E -o $@ $(CPPFLAGS) $<
|
$(CC) -E -o $@ $(CPPFLAGS) $<
|
||||||
sudo_debug.plog: sudo_debug.i
|
sudo_debug.plog: sudo_debug.i
|
||||||
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/sudo_debug.c --i-file $< --output-file $@
|
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/sudo_debug.c --i-file $< --output-file $@
|
||||||
sudo_dso.lo: $(srcdir)/sudo_dso.c $(incdir)/sudo_compat.h $(incdir)/sudo_dso.h \
|
sudo_dso.lo: $(srcdir)/sudo_dso.c $(incdir)/compat/stdbool.h \
|
||||||
$(top_builddir)/config.h
|
$(incdir)/sudo_compat.h $(incdir)/sudo_dso.h \
|
||||||
|
$(incdir)/sudo_util.h $(top_builddir)/config.h
|
||||||
$(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/sudo_dso.c
|
$(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/sudo_dso.c
|
||||||
sudo_dso.i: $(srcdir)/sudo_dso.c $(incdir)/sudo_compat.h $(incdir)/sudo_dso.h \
|
sudo_dso.i: $(srcdir)/sudo_dso.c $(incdir)/compat/stdbool.h \
|
||||||
$(top_builddir)/config.h
|
$(incdir)/sudo_compat.h $(incdir)/sudo_dso.h \
|
||||||
|
$(incdir)/sudo_util.h $(top_builddir)/config.h
|
||||||
$(CC) -E -o $@ $(CPPFLAGS) $<
|
$(CC) -E -o $@ $(CPPFLAGS) $<
|
||||||
sudo_dso.plog: sudo_dso.i
|
sudo_dso.plog: sudo_dso.i
|
||||||
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/sudo_dso.c --i-file $< --output-file $@
|
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/sudo_dso.c --i-file $< --output-file $@
|
||||||
|
103
lib/util/multiarch.c
Normal file
103
lib/util/multiarch.c
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: ISC
|
||||||
|
*
|
||||||
|
* Copyright (c) 2022 Todd C. Miller <Todd.Miller@sudo.ws>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||||
|
* PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
# include <sys/utsname.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "sudo_compat.h"
|
||||||
|
#include "sudo_util.h"
|
||||||
|
|
||||||
|
# if defined(__linux__)
|
||||||
|
/*
|
||||||
|
* On Linux systems that use muti-arch, the actual DSO may be in a
|
||||||
|
* machine-specific subdirectory. If the specified path contains
|
||||||
|
* /lib/ or /libexec/, insert a multi-arch directory after it.
|
||||||
|
* If sb is non-NULL, stat(2) will be called on the new path, filling in sb.
|
||||||
|
* Returns a dynamically allocated string on success and NULL on failure.
|
||||||
|
*/
|
||||||
|
char *
|
||||||
|
sudo_stat_multiarch_v1(const char *path, struct stat *sb)
|
||||||
|
{
|
||||||
|
# if defined(__ILP32__)
|
||||||
|
const char *libdirs[] = { "/libx32/", "/lib/", "/libexec/", NULL };
|
||||||
|
# elif defined(__LP64__)
|
||||||
|
const char *libdirs[] = { "/lib64/", "/lib/", "/libexec/", NULL };
|
||||||
|
# else
|
||||||
|
const char *libdirs[] = { "/lib32/", "/lib/", "/libexec/", NULL };
|
||||||
|
# endif
|
||||||
|
const char **lp, *lib, *slash;
|
||||||
|
struct utsname unamebuf;
|
||||||
|
char *newpath = NULL;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
if (uname(&unamebuf) == -1)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
for (lp = libdirs; *lp != NULL; lp++) {
|
||||||
|
/* Replace lib64, lib32, libx32 with lib in new path. */
|
||||||
|
const char *newlib = lp == libdirs ? "/lib/" : *lp;
|
||||||
|
|
||||||
|
/* Search for lib dir in path, find the trailing slash. */
|
||||||
|
lib = strstr(path, *lp);
|
||||||
|
if (lib == NULL)
|
||||||
|
continue;
|
||||||
|
slash = lib + strlen(*lp) - 1;
|
||||||
|
|
||||||
|
/* Make sure there isn't already a machine-linux-gnu dir. */
|
||||||
|
len = strcspn(slash + 1, "/-");
|
||||||
|
if (strncmp(slash + 1 + len, "-linux-gnu/", 11) == 0) {
|
||||||
|
/* Multiarch already present. */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add machine-linux-gnu dir after /lib/ or /libexec/. */
|
||||||
|
len = asprintf(&newpath, "%.*s%s%s-linux-gnu%s",
|
||||||
|
(int)(lib - path), path, newlib, unamebuf.machine, slash);
|
||||||
|
if (len == -1) {
|
||||||
|
newpath = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If sb was set, use stat(2) to make sure newpath exists. */
|
||||||
|
if (sb == NULL || stat(newpath, sb) == 0)
|
||||||
|
break;
|
||||||
|
free(newpath);
|
||||||
|
newpath = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return newpath;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
char *
|
||||||
|
sudo_stat_multiarch_v1(const char *path, struct stat *sb)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#endif /* __linux__ */
|
178
lib/util/regress/multiarch/multiarch_test.c
Normal file
178
lib/util/regress/multiarch/multiarch_test.c
Normal file
@@ -0,0 +1,178 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: ISC
|
||||||
|
*
|
||||||
|
* Copyright (c) 2022 Todd C. Miller <Todd.Miller@sudo.ws>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#define SUDO_ERROR_WRAP 0
|
||||||
|
|
||||||
|
#include "sudo_compat.h"
|
||||||
|
#include "sudo_fatal.h"
|
||||||
|
#include "sudo_util.h"
|
||||||
|
|
||||||
|
sudo_dso_public int main(int argc, char *argv[]);
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
# include <sys/utsname.h>
|
||||||
|
|
||||||
|
# if defined(__ILP32__)
|
||||||
|
# define ARCH_LIB "libx32"
|
||||||
|
# elif defined(__LP64__)
|
||||||
|
# define ARCH_LIB "lib64"
|
||||||
|
# else
|
||||||
|
# define ARCH_LIB "lib32"
|
||||||
|
# endif
|
||||||
|
|
||||||
|
struct multiarch_test {
|
||||||
|
const char *inpath;
|
||||||
|
char *outpath;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct multiarch_test *
|
||||||
|
make_test_data(void)
|
||||||
|
{
|
||||||
|
struct multiarch_test *test_data;
|
||||||
|
struct utsname unamebuf;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (uname(&unamebuf) == -1)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
test_data = calloc(7, sizeof(*test_data));
|
||||||
|
if (test_data == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
test_data[0].inpath = "/usr/" ARCH_LIB "/libfoo.so";
|
||||||
|
i = asprintf(&test_data[0].outpath, "/usr/lib/%s-linux-gnu/libfoo.so",
|
||||||
|
unamebuf.machine);
|
||||||
|
if (i == -1) {
|
||||||
|
test_data[0].outpath = NULL;
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
|
||||||
|
test_data[1].inpath = "/usr/lib/something.so";
|
||||||
|
i = asprintf(&test_data[1].outpath, "/usr/lib/%s-linux-gnu/something.so",
|
||||||
|
unamebuf.machine);
|
||||||
|
if (i == -1) {
|
||||||
|
test_data[1].outpath = NULL;
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
|
||||||
|
test_data[2].inpath = "/usr/libexec/libbar.so";
|
||||||
|
i = asprintf(&test_data[2].outpath, "/usr/libexec/%s-linux-gnu/libbar.so",
|
||||||
|
unamebuf.machine);
|
||||||
|
if (i == -1) {
|
||||||
|
test_data[2].outpath = NULL;
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
|
||||||
|
test_data[3].inpath = "/usr/local/lib/sudo/libsudo_util.so";
|
||||||
|
i = asprintf(&test_data[3].outpath, "/usr/local/lib/%s-linux-gnu/sudo/libsudo_util.so",
|
||||||
|
unamebuf.machine);
|
||||||
|
if (i == -1) {
|
||||||
|
test_data[3].outpath = NULL;
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
|
||||||
|
test_data[4].inpath = "/opt/sudo/lib/sudoers.so";
|
||||||
|
i = asprintf(&test_data[4].outpath, "/opt/sudo/lib/%s-linux-gnu/sudoers.so",
|
||||||
|
unamebuf.machine);
|
||||||
|
if (i == -1) {
|
||||||
|
test_data[4].outpath = NULL;
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
|
||||||
|
i = asprintf(&test_data[5].outpath, "/usr/lib/%s-linux-gnu/something.so",
|
||||||
|
unamebuf.machine);
|
||||||
|
if (i == -1) {
|
||||||
|
test_data[5].outpath = NULL;
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
test_data[5].inpath = test_data[5].outpath;
|
||||||
|
test_data[5].outpath = NULL;
|
||||||
|
|
||||||
|
return test_data;
|
||||||
|
bad:
|
||||||
|
for (i = 0; test_data[i].outpath != NULL; i++)
|
||||||
|
free(test_data[i].outpath);
|
||||||
|
free(test_data);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#endif /* __linux__ */
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
int ch, errors = 0;
|
||||||
|
#ifdef __linux__
|
||||||
|
int ntests = 0;
|
||||||
|
struct multiarch_test *test_data;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
initprogname(argc > 0 ? argv[0] : "multiarch_test");
|
||||||
|
|
||||||
|
while ((ch = getopt(argc, argv, "v")) != -1) {
|
||||||
|
switch (ch) {
|
||||||
|
case 'v':
|
||||||
|
/* ignore */
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "usage: %s [-v]\n", getprogname());
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
argc -= optind;
|
||||||
|
argv += optind;
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
test_data = make_test_data();
|
||||||
|
if (test_data == NULL) {
|
||||||
|
sudo_warnx("%s", "failed to generate test data");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ch = 0; test_data[ch].inpath != NULL; ch++) {
|
||||||
|
char *outpath = sudo_stat_multiarch(test_data[ch].inpath, NULL);
|
||||||
|
ntests++;
|
||||||
|
if (outpath == NULL) {
|
||||||
|
if (test_data[ch].outpath != NULL) {
|
||||||
|
sudo_warnx("%s: sudo_stat_multiarch failed",
|
||||||
|
test_data[ch].inpath);
|
||||||
|
errors++;
|
||||||
|
}
|
||||||
|
} else if (strcmp(outpath, test_data[ch].outpath) != 0) {
|
||||||
|
sudo_warnx("%s: expected %s got %s", test_data[ch].inpath,
|
||||||
|
test_data[ch].outpath, outpath);
|
||||||
|
errors++;
|
||||||
|
free(outpath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ntests != 0) {
|
||||||
|
printf("%s: %d tests run, %d errors, %d%% success rate\n",
|
||||||
|
getprogname(), ntests, errors, (ntests - errors) * 100 / ntests);
|
||||||
|
}
|
||||||
|
#endif /* __linux__ */
|
||||||
|
return errors;
|
||||||
|
}
|
@@ -39,6 +39,7 @@
|
|||||||
|
|
||||||
#include "sudo_compat.h"
|
#include "sudo_compat.h"
|
||||||
#include "sudo_dso.h"
|
#include "sudo_dso.h"
|
||||||
|
#include "sudo_util.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Pointer for statically compiled symbols.
|
* Pointer for statically compiled symbols.
|
||||||
@@ -183,46 +184,26 @@ sudo_dso_strerror_v1(void)
|
|||||||
static void *
|
static void *
|
||||||
dlopen_multi_arch(const char *path, int flags)
|
dlopen_multi_arch(const char *path, int flags)
|
||||||
{
|
{
|
||||||
# if defined(__ILP32__)
|
|
||||||
const char *libdirs[] = { "/libx32/", "/lib/", "/libexec/", NULL };
|
|
||||||
# elif defined(__LP64__)
|
|
||||||
const char *libdirs[] = { "/lib64/", "/lib/", "/libexec/", NULL };
|
|
||||||
# else
|
|
||||||
const char *libdirs[] = { "/lib32/", "/lib/", "/libexec/", NULL };
|
|
||||||
# endif
|
|
||||||
const char **lp, *lib, *slash;
|
|
||||||
struct utsname unamebuf;
|
|
||||||
void *ret = NULL;
|
void *ret = NULL;
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
char *newpath;
|
char *newpath;
|
||||||
int len;
|
|
||||||
|
|
||||||
/* Only try multi-arch if the original path does not exist. */
|
/* Only try multi-arch if the original path does not exist. */
|
||||||
if (stat(path, &sb) == -1 && errno == ENOENT && uname(&unamebuf) == 0) {
|
if (stat(path, &sb) == -1 && errno == ENOENT) {
|
||||||
for (lp = libdirs; *lp != NULL; lp++) {
|
newpath = sudo_stat_multiarch(path, &sb);
|
||||||
/* Replace lib64, lib32, libx32 with lib in new path. */
|
if (newpath != NULL) {
|
||||||
const char *newlib = lp == libdirs ? "/lib/" : *lp;
|
|
||||||
|
|
||||||
/* Search for lib dir in path, find the trailing slash. */
|
|
||||||
lib = strstr(path, *lp);
|
|
||||||
if (lib == NULL)
|
|
||||||
continue;
|
|
||||||
slash = lib + strlen(*lp) - 1;
|
|
||||||
|
|
||||||
/* Add machine-linux-gnu dir after /lib/ or /libexec/. */
|
|
||||||
len = asprintf(&newpath, "%.*s%s%s-linux-gnu%s",
|
|
||||||
(int)(lib - path), path, newlib, unamebuf.machine, slash);
|
|
||||||
if (len == -1)
|
|
||||||
break;
|
|
||||||
if (stat(newpath, &sb) == 0)
|
|
||||||
ret = dlopen(newpath, flags);
|
ret = dlopen(newpath, flags);
|
||||||
free(newpath);
|
free(newpath);
|
||||||
if (ret != NULL)
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
# else
|
||||||
|
static void *
|
||||||
|
dlopen_multi_arch(const char *path, int flags)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
# endif /* __linux__ */
|
# endif /* __linux__ */
|
||||||
|
|
||||||
void *
|
void *
|
||||||
@@ -278,11 +259,10 @@ sudo_dso_load_v1(const char *path, int mode)
|
|||||||
ret = dlopen(path, flags);
|
ret = dlopen(path, flags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#elif defined(__linux__)
|
# endif /* RTLD_MEMBER */
|
||||||
/* On failure, try again with a muti-arch path where possible. */
|
/* On failure, try again with a muti-arch path where possible. */
|
||||||
if (ret == NULL)
|
if (ret == NULL)
|
||||||
ret = dlopen_multi_arch(path, flags);
|
ret = dlopen_multi_arch(path, flags);
|
||||||
#endif /* RTLD_MEMBER */
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@@ -131,6 +131,7 @@ sudo_secure_file_v1
|
|||||||
sudo_secure_open_dir_v1
|
sudo_secure_open_dir_v1
|
||||||
sudo_secure_open_file_v1
|
sudo_secure_open_file_v1
|
||||||
sudo_setgroups_v1
|
sudo_setgroups_v1
|
||||||
|
sudo_stat_multiarch_v1
|
||||||
sudo_str2logfac_v1
|
sudo_str2logfac_v1
|
||||||
sudo_str2logpri_v1
|
sudo_str2logpri_v1
|
||||||
sudo_strsplit_v1
|
sudo_strsplit_v1
|
||||||
|
@@ -43,6 +43,7 @@ sudo_stat_plugin(struct plugin_info *info, char *fullpath,
|
|||||||
size_t pathsize, struct stat *sb)
|
size_t pathsize, struct stat *sb)
|
||||||
{
|
{
|
||||||
int status = -1;
|
int status = -1;
|
||||||
|
size_t len;
|
||||||
debug_decl(sudo_stat_plugin, SUDO_DEBUG_PLUGIN);
|
debug_decl(sudo_stat_plugin, SUDO_DEBUG_PLUGIN);
|
||||||
|
|
||||||
if (info->path[0] == '/') {
|
if (info->path[0] == '/') {
|
||||||
@@ -52,8 +53,6 @@ sudo_stat_plugin(struct plugin_info *info, char *fullpath,
|
|||||||
}
|
}
|
||||||
status = stat(fullpath, sb);
|
status = stat(fullpath, sb);
|
||||||
} else {
|
} else {
|
||||||
int len;
|
|
||||||
|
|
||||||
#ifdef STATIC_SUDOERS_PLUGIN
|
#ifdef STATIC_SUDOERS_PLUGIN
|
||||||
/* Check static symbols. */
|
/* Check static symbols. */
|
||||||
if (strcmp(info->path, SUDOERS_PLUGIN) == 0) {
|
if (strcmp(info->path, SUDOERS_PLUGIN) == 0) {
|
||||||
@@ -77,20 +76,22 @@ sudo_stat_plugin(struct plugin_info *info, char *fullpath,
|
|||||||
|
|
||||||
len = snprintf(fullpath, pathsize, "%s%s", sudo_conf_plugin_dir_path(),
|
len = snprintf(fullpath, pathsize, "%s%s", sudo_conf_plugin_dir_path(),
|
||||||
info->path);
|
info->path);
|
||||||
if (len < 0 || (size_t)len >= pathsize) {
|
if (len >= pathsize) {
|
||||||
errno = ENAMETOOLONG;
|
errno = ENAMETOOLONG;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
/* Try parent dir for compatibility with old plugindir default. */
|
status = stat(fullpath, sb);
|
||||||
if ((status = stat(fullpath, sb)) != 0) {
|
|
||||||
char *cp = strrchr(fullpath, '/');
|
|
||||||
if (cp > fullpath + 4 && cp[-5] == '/' && cp[-4] == 's' &&
|
|
||||||
cp[-3] == 'u' && cp[-2] == 'd' && cp[-1] == 'o') {
|
|
||||||
int serrno = errno;
|
|
||||||
strlcpy(cp - 4, info->path, pathsize - (cp - 4 - fullpath));
|
|
||||||
if ((status = stat(fullpath, sb)) != 0)
|
|
||||||
errno = serrno;
|
|
||||||
}
|
}
|
||||||
|
if (status == -1) {
|
||||||
|
char *newpath = sudo_stat_multiarch(fullpath, sb);
|
||||||
|
if (newpath != NULL) {
|
||||||
|
len = strlcpy(fullpath, newpath, pathsize);
|
||||||
|
free(newpath);
|
||||||
|
if (len >= pathsize) {
|
||||||
|
errno = ENAMETOOLONG;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
status = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
done:
|
done:
|
||||||
|
Reference in New Issue
Block a user