提交 2963a9f7 编写于 作者: R Rich Felker

halt dynamic linker library search on errors resolving $ORIGIN in rpath

this change hardens the dynamic linker against the possibility of
loading the wrong library due to inability to expand $ORIGIN in rpath.
hard failures such as excessively long paths or absence of /proc (when
resolving /proc/self/exe for the main executable's origin) do not stop
the path search, but memory allocation failures and any other
potentially transient failures do.

to implement this change, the meaning of the return value of
fixup_rpath function is changed. returning zero no longer indicates
that the dso's rpath string pointer is non-null; instead, the caller
needs to check. a return value of -1 indicates a failure that should
stop further path search.
上级 5e25d87b
...@@ -599,8 +599,7 @@ static int fixup_rpath(struct dso *p, char *buf, size_t buf_size) ...@@ -599,8 +599,7 @@ static int fixup_rpath(struct dso *p, char *buf, size_t buf_size)
size_t n, l; size_t n, l;
const char *s, *t, *origin; const char *s, *t, *origin;
char *d; char *d;
if (p->rpath) return 0; if (p->rpath || !p->rpath_orig) return 0;
if (!p->rpath_orig) return -1;
if (!strchr(p->rpath_orig, '$')) { if (!strchr(p->rpath_orig, '$')) {
p->rpath = p->rpath_orig; p->rpath = p->rpath_orig;
return 0; return 0;
...@@ -609,11 +608,11 @@ static int fixup_rpath(struct dso *p, char *buf, size_t buf_size) ...@@ -609,11 +608,11 @@ static int fixup_rpath(struct dso *p, char *buf, size_t buf_size)
s = p->rpath_orig; s = p->rpath_orig;
while ((t=strchr(s, '$'))) { while ((t=strchr(s, '$'))) {
if (strncmp(t, "$ORIGIN", 7) && strncmp(t, "${ORIGIN}", 9)) if (strncmp(t, "$ORIGIN", 7) && strncmp(t, "${ORIGIN}", 9))
return -1; return 0;
s = t+1; s = t+1;
n++; n++;
} }
if (n > SSIZE_MAX/PATH_MAX) return -1; if (n > SSIZE_MAX/PATH_MAX) return 0;
if (p->kernel_mapped) { if (p->kernel_mapped) {
/* $ORIGIN searches cannot be performed for the main program /* $ORIGIN searches cannot be performed for the main program
...@@ -623,10 +622,18 @@ static int fixup_rpath(struct dso *p, char *buf, size_t buf_size) ...@@ -623,10 +622,18 @@ static int fixup_rpath(struct dso *p, char *buf, size_t buf_size)
* since the library's pathname came from a trusted source * since the library's pathname came from a trusted source
* (either system paths or a call to dlopen). */ * (either system paths or a call to dlopen). */
if (libc.secure) if (libc.secure)
return -1; return 0;
l = readlink("/proc/self/exe", buf, buf_size); l = readlink("/proc/self/exe", buf, buf_size);
if (l >= buf_size) if (l == -1) switch (errno) {
case ENOENT:
case ENOTDIR:
case EACCES:
break;
default:
return -1; return -1;
}
if (l >= buf_size)
return 0;
buf[l] = 0; buf[l] = 0;
origin = buf; origin = buf;
} else { } else {
...@@ -735,9 +742,12 @@ static struct dso *load_library(const char *name, struct dso *needed_by) ...@@ -735,9 +742,12 @@ static struct dso *load_library(const char *name, struct dso *needed_by)
if (strlen(name) > NAME_MAX) return 0; if (strlen(name) > NAME_MAX) return 0;
fd = -1; fd = -1;
if (env_path) fd = path_open(name, env_path, buf, sizeof buf); if (env_path) fd = path_open(name, env_path, buf, sizeof buf);
for (p=needed_by; fd == -1 && p; p=p->needed_by) for (p=needed_by; fd == -1 && p; p=p->needed_by) {
if (!fixup_rpath(p, buf, sizeof buf)) if (fixup_rpath(p, buf, sizeof buf) < 0)
fd = -2; /* Inhibit further search. */
if (p->rpath)
fd = path_open(name, p->rpath, buf, sizeof buf); fd = path_open(name, p->rpath, buf, sizeof buf);
}
if (fd == -1) { if (fd == -1) {
if (!sys_path) { if (!sys_path) {
char *prefix = 0; char *prefix = 0;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册