summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--contrib/telnet/libtelnet/encrypt.c3
-rw-r--r--crypto/heimdal/appl/telnet/libtelnet/encrypt.c3
-rw-r--r--include/unistd.h1
-rw-r--r--lib/libc/gen/Makefile.inc1
-rw-r--r--lib/libc/gen/Symbol.map4
-rw-r--r--lib/libc/gen/libc_dlopen.c61
-rw-r--r--lib/libc/iconv/citrus_module.c3
-rw-r--r--lib/libc/include/libc_private.h11
-rw-r--r--lib/libc/net/nsdispatch.c4
-rw-r--r--libexec/ftpd/ftpd.c1
-rw-r--r--libexec/ftpd/popen.c3
11 files changed, 92 insertions, 3 deletions
diff --git a/contrib/telnet/libtelnet/encrypt.c b/contrib/telnet/libtelnet/encrypt.c
index 8bdf672..f8e9194 100644
--- a/contrib/telnet/libtelnet/encrypt.c
+++ b/contrib/telnet/libtelnet/encrypt.c
@@ -721,6 +721,9 @@ encrypt_keyid(struct key_info *kp, unsigned char *keyid, int len)
int dir = kp->dir;
int ret = 0;
+ if (len > MAXKEYLEN)
+ len = MAXKEYLEN;
+
if (!(ep = (*kp->getcrypt)(*kp->modep))) {
if (len == 0)
return;
diff --git a/crypto/heimdal/appl/telnet/libtelnet/encrypt.c b/crypto/heimdal/appl/telnet/libtelnet/encrypt.c
index 04dbe83..a4669d2 100644
--- a/crypto/heimdal/appl/telnet/libtelnet/encrypt.c
+++ b/crypto/heimdal/appl/telnet/libtelnet/encrypt.c
@@ -736,6 +736,9 @@ encrypt_keyid(struct key_info *kp, unsigned char *keyid, int len)
int dir = kp->dir;
int ret = 0;
+ if (len > MAXKEYLEN)
+ len = MAXKEYLEN;
+
if (!(ep = (*kp->getcrypt)(*kp->modep))) {
if (len == 0)
return;
diff --git a/include/unistd.h b/include/unistd.h
index f073f8d..90694ed 100644
--- a/include/unistd.h
+++ b/include/unistd.h
@@ -511,6 +511,7 @@ int initgroups(const char *, gid_t);
int iruserok(unsigned long, int, const char *, const char *);
int iruserok_sa(const void *, int, int, const char *, const char *);
int issetugid(void);
+void __FreeBSD_libc_enter_restricted_mode(void);
long lpathconf(const char *, int);
#ifndef _MKDTEMP_DECLARED
char *mkdtemp(char *);
diff --git a/lib/libc/gen/Makefile.inc b/lib/libc/gen/Makefile.inc
index d3ccf0a..1e068a5 100644
--- a/lib/libc/gen/Makefile.inc
+++ b/lib/libc/gen/Makefile.inc
@@ -20,6 +20,7 @@ SRCS+= __getosreldate.c __xuname.c \
getpeereid.c getprogname.c getpwent.c getttyent.c \
getusershell.c getutxent.c getvfsbyname.c glob.c \
initgroups.c isatty.c isinf.c isnan.c jrand48.c lcong48.c \
+ libc_dlopen.c \
lockf.c lrand48.c mrand48.c nftw.c nice.c \
nlist.c nrand48.c opendir.c \
pause.c pmadvise.c popen.c posix_spawn.c \
diff --git a/lib/libc/gen/Symbol.map b/lib/libc/gen/Symbol.map
index c62e016..adc5964 100644
--- a/lib/libc/gen/Symbol.map
+++ b/lib/libc/gen/Symbol.map
@@ -381,6 +381,10 @@ FBSD_1.2 {
setutxent;
};
+FBSD_1.3 {
+ __FreeBSD_libc_enter_restricted_mode;
+};
+
FBSDprivate_1.0 {
/* needed by thread libraries */
__thr_jtable;
diff --git a/lib/libc/gen/libc_dlopen.c b/lib/libc/gen/libc_dlopen.c
new file mode 100644
index 0000000..2b1aa9e
--- /dev/null
+++ b/lib/libc/gen/libc_dlopen.c
@@ -0,0 +1,61 @@
+/*-
+ * Copyright (c) 2011 Xin Li <delphij@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <dlfcn.h>
+#include <stddef.h>
+#include <unistd.h>
+
+#include "libc_private.h"
+
+/*
+ * Whether we want to restrict dlopen()s.
+ */
+static int __libc_restricted_mode = 0;
+
+void *
+libc_dlopen(const char *path, int mode)
+{
+
+ if (__libc_restricted_mode) {
+ _rtld_error("Service unavailable -- libc in restricted mode");
+ return (NULL);
+ } else
+ return (dlopen(path, mode));
+}
+
+void
+__FreeBSD_libc_enter_restricted_mode(void)
+{
+
+ __libc_restricted_mode = 1;
+ return;
+}
+
diff --git a/lib/libc/iconv/citrus_module.c b/lib/libc/iconv/citrus_module.c
index aa96aba..32b7e6e 100644
--- a/lib/libc/iconv/citrus_module.c
+++ b/lib/libc/iconv/citrus_module.c
@@ -109,6 +109,7 @@
#include "citrus_namespace.h"
#include "citrus_bcs.h"
#include "citrus_module.h"
+#include "libc_private.h"
static int _getdewey(int[], char *);
static int _cmpndewey(int[], int, int[], int);
@@ -294,7 +295,7 @@ _citrus_load_module(_citrus_module_t *rhandle, const char *encname)
p = _findshlib(path, &maj, &min);
if (!p)
return (EINVAL);
- handle = dlopen(p, RTLD_LAZY);
+ handle = libc_dlopen(p, RTLD_LAZY);
if (!handle) {
printf("%s", dlerror());
return (EINVAL);
diff --git a/lib/libc/include/libc_private.h b/lib/libc/include/libc_private.h
index a4737fe..c7284cc 100644
--- a/lib/libc/include/libc_private.h
+++ b/lib/libc/include/libc_private.h
@@ -44,6 +44,17 @@
extern int __isthreaded;
/*
+ * libc should use libc_dlopen internally, which respects a global
+ * flag where loading of new shared objects can be restricted.
+ */
+void *libc_dlopen(const char *, int);
+
+/*
+ * For dynamic linker.
+ */
+void _rtld_error(const char *fmt, ...);
+
+/*
* File lock contention is difficult to diagnose without knowing
* where locks were set. Allow a debug library to be built which
* records the source file and line number of each lock call.
diff --git a/lib/libc/net/nsdispatch.c b/lib/libc/net/nsdispatch.c
index 6b7bd02..f9d787a 100644
--- a/lib/libc/net/nsdispatch.c
+++ b/lib/libc/net/nsdispatch.c
@@ -384,7 +384,7 @@ nss_configure(void)
confmod = statbuf.st_mtime;
#ifdef NS_CACHING
- handle = dlopen(NULL, RTLD_LAZY | RTLD_GLOBAL);
+ handle = libc_dlopen(NULL, RTLD_LAZY | RTLD_GLOBAL);
if (handle != NULL) {
nss_cache_cycle_prevention_func = dlsym(handle,
"_nss_cache_cycle_prevention_function");
@@ -497,7 +497,7 @@ nss_load_module(const char *source, nss_module_register_fn reg_fn)
if (snprintf(buf, sizeof(buf), "nss_%s.so.%d", mod.name,
NSS_MODULE_INTERFACE_VERSION) >= (int)sizeof(buf))
goto fin;
- mod.handle = dlopen(buf, RTLD_LOCAL|RTLD_LAZY);
+ mod.handle = libc_dlopen(buf, RTLD_LOCAL|RTLD_LAZY);
if (mod.handle == NULL) {
#ifdef _NSS_DEBUG
/* This gets pretty annoying since the built-in
diff --git a/libexec/ftpd/ftpd.c b/libexec/ftpd/ftpd.c
index 5894f3c..00570d6 100644
--- a/libexec/ftpd/ftpd.c
+++ b/libexec/ftpd/ftpd.c
@@ -1562,6 +1562,7 @@ skip:
reply(550, "Can't change root.");
goto bad;
}
+ __FreeBSD_libc_enter_restricted_mode();
} else /* real user w/o chroot */
homedir = pw->pw_dir;
/*
diff --git a/libexec/ftpd/popen.c b/libexec/ftpd/popen.c
index 8a739dc..9f80507 100644
--- a/libexec/ftpd/popen.c
+++ b/libexec/ftpd/popen.c
@@ -143,6 +143,9 @@ ftpd_popen(char *program, char *type)
}
(void)close(pdes[1]);
}
+ /* Drop privileges before proceeding */
+ if (getuid() != geteuid() && setuid(geteuid()) < 0)
+ _exit(1);
if (strcmp(gargv[0], _PATH_LS) == 0) {
/* Reset getopt for ls_main() */
optreset = optind = optopt = 1;
OpenPOWER on IntegriCloud