From 88342a897fa63702bbe8eef23e238ba9183a82a2 Mon Sep 17 00:00:00 2001 From: Xin LI Date: Fri, 2 Dec 2011 10:44:39 -0800 Subject: [PATCH 2/4] Add a new flag, RTLD_PARANOID for callers who wants the dynamic linker to check if the library being loaded is owned by root and have group, other write access blocked. --- include/dlfcn.h | 2 ++ lib/libc/gen/dlopen.3 | 11 ++++++++++- libexec/rtld-elf/rtld.c | 10 ++++++++++ libexec/rtld-elf/rtld.h | 2 ++ 4 files changed, 24 insertions(+), 1 deletions(-) diff --git a/include/dlfcn.h b/include/dlfcn.h index 794fde1..85e7dc7 100644 --- a/include/dlfcn.h +++ b/include/dlfcn.h @@ -45,6 +45,8 @@ #define RTLD_TRACE 0x200 /* Trace loaded objects and exit. */ #define RTLD_NODELETE 0x01000 /* Do not remove members. */ #define RTLD_NOLOAD 0x02000 /* Do not load if not already loaded. */ +#define RTLD_PARANOID 0x04000 /* Only load if library is owned by root and + can not be write by group or others */ /* * Request arguments for dlinfo(). diff --git a/lib/libc/gen/dlopen.3 b/lib/libc/gen/dlopen.3 index 3da9b6e..2173a11 100644 --- a/lib/libc/gen/dlopen.3 +++ b/lib/libc/gen/dlopen.3 @@ -32,7 +32,7 @@ .\" @(#) dlopen.3 1.6 90/01/31 SMI .\" $FreeBSD$ .\" -.Dd July 7, 2009 +.Dd December 3, 2011 .Dt DLOPEN 3 .Os .Sh NAME @@ -157,6 +157,15 @@ Other mode flags may be specified, which will be applied for promotion for the found object. .El .Pp +Optionally, the caller can choose to OR the following flags into the +.Fa mode +argument: +.Bl -tag -width RTLD_PARANOID +.It Dv RTLD_PARANOID +Only allow shared objects owned by root and is not writable by group +or others be loaded. +.El +.Pp If .Fn dlopen fails, it returns a null pointer, and sets an error condition which may diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c index 0d4e972..9302df7 100644 --- a/libexec/rtld-elf/rtld.c +++ b/libexec/rtld-elf/rtld.c @@ -1646,6 +1646,14 @@ load_object(const char *name, const Obj_Entry *refobj, int flags) free(path); return NULL; } + if (flags & RTLD_LO_PARANOID) { + if (sb.st_uid != 0 || (sb.st_mode & (S_IWGRP | S_IWOTH))) { + _rtld_error("Rejecting shared library %s\n", path); + free(path); + close(fd); + return NULL; + } + } for (obj = obj_list->next; obj != NULL; obj = obj->next) if (obj->ino == sb.st_ino && obj->dev == sb.st_dev) break; @@ -2165,6 +2173,8 @@ dlopen(const char *name, int mode) lo_flags |= RTLD_LO_NOLOAD; if (ld_tracing != NULL) lo_flags |= RTLD_LO_TRACE; + if (mode & RTLD_PARANOID) + lo_flags |= RTLD_LO_PARANOID; return (dlopen_object(name, obj_main, lo_flags, mode & (RTLD_MODEMASK | RTLD_GLOBAL))); diff --git a/libexec/rtld-elf/rtld.h b/libexec/rtld-elf/rtld.h index 011dcc3..8a6753a 100644 --- a/libexec/rtld-elf/rtld.h +++ b/libexec/rtld-elf/rtld.h @@ -255,6 +255,8 @@ typedef struct Struct_Obj_Entry { #define RTLD_LO_TRACE 0x04 /* Only tracing. */ #define RTLD_LO_NODELETE 0x08 /* Loaded object cannot be closed. */ #define RTLD_LO_FILTEES 0x10 /* Loading filtee. */ +#define RTLD_LO_PARANOID 0x20 /* Only load if library is owned by root and + can not be write by group or others */ /* * Symbol cache entry used during relocation to avoid multiple lookups -- 1.7.7.2