summaryrefslogtreecommitdiffstats
path: root/sys/compat
diff options
context:
space:
mode:
authorrwatson <rwatson@FreeBSD.org>2001-12-03 16:12:27 +0000
committerrwatson <rwatson@FreeBSD.org>2001-12-03 16:12:27 +0000
commitb5de44291122e0fc2bf68540749f66b3992d3ea2 (patch)
tree8f9d530e63e21e0286cad851a18efd4acdd6bd28 /sys/compat
parentc55fbd48a87bd450592bb317754a6bf3961674ff (diff)
downloadFreeBSD-src-b5de44291122e0fc2bf68540749f66b3992d3ea2.zip
FreeBSD-src-b5de44291122e0fc2bf68540749f66b3992d3ea2.tar.gz
o Introduce pr_mtx into struct prison, providing protection for the
mutable contents of struct prison (hostname, securelevel, refcount, pr_linux, ...) o Generally introduce mtx_lock()/mtx_unlock() calls throughout kern/ so as to enforce these protections, in particular, in kern_mib.c protection sysctl access to the hostname and securelevel, as well as kern_prot.c access to the securelevel for access control purposes. o Rewrite linux emulator abstractions for accessing per-jail linux mib entries (osname, osrelease, osversion) so that they don't return a pointer to the text in the struct linux_prison, rather, a copy to an array passed into the calls. Likewise, update linprocfs to use these primitives. o Update in_pcb.c to always use prison_getip() rather than directly accessing struct prison. Reviewed by: jhb
Diffstat (limited to 'sys/compat')
-rw-r--r--sys/compat/linprocfs/linprocfs.c11
-rw-r--r--sys/compat/linux/linux_mib.c132
-rw-r--r--sys/compat/linux/linux_mib.h4
-rw-r--r--sys/compat/linux/linux_misc.c7
4 files changed, 111 insertions, 43 deletions
diff --git a/sys/compat/linprocfs/linprocfs.c b/sys/compat/linprocfs/linprocfs.c
index c64bf11..a23e561 100644
--- a/sys/compat/linprocfs/linprocfs.c
+++ b/sys/compat/linprocfs/linprocfs.c
@@ -90,6 +90,7 @@ extern int ncpus;
#include <machine/md_var.h>
#endif /* __i386__ */
+#include <machine/../linux/linux.h>
#include <compat/linux/linux_ioctl.h>
#include <compat/linux/linux_mib.h>
#include <compat/linux/linux_util.h>
@@ -444,11 +445,15 @@ linprocfs_douptime(PFS_FILL_ARGS)
static int
linprocfs_doversion(PFS_FILL_ARGS)
{
+ char osname[LINUX_MAX_UTSNAME];
+ char osrelease[LINUX_MAX_UTSNAME];
+
+ linux_get_osname(td->td_proc, osname);
+ linux_get_osrelease(td->td_proc, osrelease);
+
sbuf_printf(sb,
"%s version %s (des@freebsd.org) (gcc version " __VERSION__ ")"
- " #4 Sun Dec 18 04:30:00 CET 1977\n",
- linux_get_osname(td->td_proc),
- linux_get_osrelease(td->td_proc));
+ " #4 Sun Dec 18 04:30:00 CET 1977\n", osname, osrelease);
return (0);
}
diff --git a/sys/compat/linux/linux_mib.c b/sys/compat/linux/linux_mib.c
index 98ea4f0..5ebb35c 100644
--- a/sys/compat/linux/linux_mib.c
+++ b/sys/compat/linux/linux_mib.c
@@ -35,6 +35,8 @@
#include <sys/proc.h>
#include <sys/malloc.h>
#include <sys/jail.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
#include <machine/../linux/linux.h>
#include <compat/linux/linux_mib.h>
@@ -56,7 +58,7 @@ linux_sysctl_osname(SYSCTL_HANDLER_ARGS)
char osname[LINUX_MAX_UTSNAME];
int error;
- strcpy(osname, linux_get_osname(req->td->td_proc));
+ linux_get_osname(req->td->td_proc, osname);
error = sysctl_handle_string(oidp, osname, LINUX_MAX_UTSNAME, req);
if (error || req->newptr == NULL)
return (error);
@@ -77,7 +79,7 @@ linux_sysctl_osrelease(SYSCTL_HANDLER_ARGS)
char osrelease[LINUX_MAX_UTSNAME];
int error;
- strcpy(osrelease, linux_get_osrelease(req->td->td_proc));
+ linux_get_osrelease(req->td->td_proc, osrelease);
error = sysctl_handle_string(oidp, osrelease, LINUX_MAX_UTSNAME, req);
if (error || req->newptr == NULL)
return (error);
@@ -111,8 +113,11 @@ SYSCTL_PROC(_compat_linux, OID_AUTO, oss_version,
0, 0, linux_sysctl_oss_version, "I",
"Linux OSS version");
+/*
+ * Returns holding the prison mutex if return non-NULL.
+ */
static struct linux_prison *
-get_prison(struct proc *p)
+linux_get_prison(struct proc *p)
{
register struct prison *pr;
register struct linux_prison *lpr;
@@ -122,30 +127,58 @@ get_prison(struct proc *p)
pr = p->p_ucred->cr_prison;
+ /*
+ * Rather than hold the prison mutex during allocation, check to
+ * see if we need to allocate while holding the mutex, release it,
+ * allocate, then once we've allocated the memory, check again to
+ * see if it's still needed, and set if appropriate. If it's not,
+ * we release the mutex again to FREE(), and grab it again so as
+ * to release holding the lock.
+ */
+ mtx_lock(&pr->pr_mtx);
if (pr->pr_linux == NULL) {
+ mtx_unlock(&pr->pr_mtx);
MALLOC(lpr, struct linux_prison *, sizeof *lpr,
M_PRISON, M_WAITOK|M_ZERO);
- pr->pr_linux = lpr;
+ mtx_lock(&pr->pr_mtx);
+ if (pr->pr_linux == NULL) {
+ pr->pr_linux = lpr;
+ } else {
+ mtx_unlock(&pr->pr_mtx);
+ FREE(lpr, M_PRISON);
+ mtx_lock(&pr->pr_mtx);
+ }
}
return (pr->pr_linux);
}
-char *
-linux_get_osname(p)
+void
+linux_get_osname(p, dst)
struct proc *p;
+ char *dst;
{
register struct prison *pr;
register struct linux_prison *lpr;
- pr = p->p_ucred->cr_prison;
- if (pr != NULL && pr->pr_linux != NULL) {
- lpr = pr->pr_linux;
- if (lpr->pr_osname[0])
- return (lpr->pr_osname);
+ if (p->p_ucred->cr_prison == NULL) {
+ bcopy(linux_osname, dst, LINUX_MAX_UTSNAME);
+ return;
}
- return (linux_osname);
+ pr = p->p_ucred->cr_prison;
+
+ mtx_lock(&pr->pr_mtx);
+ if (pr->pr_linux != NULL) {
+ lpr = (struct linux_prison *)pr->pr_linux;
+ if (lpr->pr_osname[0]) {
+ bcopy(lpr->pr_osname, dst, LINUX_MAX_UTSNAME);
+ mtx_unlock(&pr->pr_mtx);
+ return;
+ }
+ }
+ mtx_unlock(&pr->pr_mtx);
+ bcopy(linux_osname, dst, LINUX_MAX_UTSNAME);
}
int
@@ -155,30 +188,43 @@ linux_set_osname(p, osname)
{
register struct linux_prison *lpr;
- lpr = get_prison(p);
- if (lpr != NULL)
+ lpr = linux_get_prison(p);
+ if (lpr != NULL) {
strcpy(lpr->pr_osname, osname);
- else
+ mtx_unlock(&p->p_ucred->cr_prison->pr_mtx);
+ } else {
strcpy(linux_osname, osname);
+ }
return (0);
}
-char *
-linux_get_osrelease(p)
+void
+linux_get_osrelease(p, dst)
struct proc *p;
+ char *dst;
{
register struct prison *pr;
- register struct linux_prison *lpr;
+ struct linux_prison *lpr;
- pr = p->p_ucred->cr_prison;
- if (pr != NULL && pr->pr_linux != NULL) {
- lpr = pr->pr_linux;
- if (lpr->pr_osrelease[0])
- return (lpr->pr_osrelease);
+ if (p->p_ucred->cr_prison == NULL) {
+ bcopy(linux_osrelease, dst, LINUX_MAX_UTSNAME);
+ return;
}
- return (linux_osrelease);
+ pr = p->p_ucred->cr_prison;
+
+ mtx_lock(&pr->pr_mtx);
+ if (pr->pr_linux != NULL) {
+ lpr = (struct linux_prison *) pr->pr_linux;
+ if (lpr->pr_osrelease[0]) {
+ bcopy(lpr->pr_osrelease, dst, LINUX_MAX_UTSNAME);
+ mtx_unlock(&pr->pr_mtx);
+ return;
+ }
+ }
+ mtx_unlock(&pr->pr_mtx);
+ bcopy(linux_osrelease, dst, LINUX_MAX_UTSNAME);
}
int
@@ -188,11 +234,13 @@ linux_set_osrelease(p, osrelease)
{
register struct linux_prison *lpr;
- lpr = get_prison(p);
- if (lpr != NULL)
+ lpr = linux_get_prison(p);
+ if (lpr != NULL) {
strcpy(lpr->pr_osrelease, osrelease);
- else
+ mtx_unlock(&p->p_ucred->cr_prison->pr_mtx);
+ } else {
strcpy(linux_osrelease, osrelease);
+ }
return (0);
}
@@ -203,15 +251,27 @@ linux_get_oss_version(p)
{
register struct prison *pr;
register struct linux_prison *lpr;
+ int version;
+
+ if (p->p_ucred->cr_prison == NULL)
+ return (linux_oss_version);
pr = p->p_ucred->cr_prison;
- if (pr != NULL && pr->pr_linux != NULL) {
- lpr = pr->pr_linux;
- if (lpr->pr_oss_version)
- return (lpr->pr_oss_version);
+
+ mtx_lock(&pr->pr_mtx);
+ if (pr->pr_linux != NULL) {
+ lpr = (struct linux_prison *) pr->pr_linux;
+ if (lpr->pr_oss_version) {
+ version = lpr->pr_oss_version;
+ } else {
+ version = linux_oss_version;
+ }
+ } else {
+ version = linux_oss_version;
}
+ mtx_unlock(&pr->pr_mtx);
- return (linux_oss_version);
+ return (version);
}
int
@@ -221,11 +281,13 @@ linux_set_oss_version(p, oss_version)
{
register struct linux_prison *lpr;
- lpr = get_prison(p);
- if (lpr != NULL)
+ lpr = linux_get_prison(p);
+ if (lpr != NULL) {
lpr->pr_oss_version = oss_version;
- else
+ mtx_unlock(&p->p_ucred->cr_prison->pr_mtx);
+ } else {
linux_oss_version = oss_version;
+ }
return (0);
}
diff --git a/sys/compat/linux/linux_mib.h b/sys/compat/linux/linux_mib.h
index 34f5a4e..4bed667 100644
--- a/sys/compat/linux/linux_mib.h
+++ b/sys/compat/linux/linux_mib.h
@@ -31,10 +31,10 @@
#ifndef _LINUX_MIB_H_
#define _LINUX_MIB_H_
-char* linux_get_osname __P((struct proc *p));
+void linux_get_osname __P((struct proc *p, char *dst));
int linux_set_osname __P((struct proc *p, char *osname));
-char* linux_get_osrelease __P((struct proc *p));
+void linux_get_osrelease __P((struct proc *p, char *dst));
int linux_set_osrelease __P((struct proc *p, char *osrelease));
int linux_get_oss_version __P((struct proc *p));
diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c
index 96fc6dc..605b6ed 100644
--- a/sys/compat/linux/linux_misc.c
+++ b/sys/compat/linux/linux_misc.c
@@ -688,15 +688,16 @@ int
linux_newuname(struct thread *td, struct linux_newuname_args *args)
{
struct l_new_utsname utsname;
- char *osrelease, *osname;
+ char osname[LINUX_MAX_UTSNAME];
+ char osrelease[LINUX_MAX_UTSNAME];
#ifdef DEBUG
if (ldebug(newuname))
printf(ARGS(newuname, "*"));
#endif
- osname = linux_get_osname(td->td_proc);
- osrelease = linux_get_osrelease(td->td_proc);
+ linux_get_osname(td->td_proc, osname);
+ linux_get_osrelease(td->td_proc, osrelease);
bzero(&utsname, sizeof(utsname));
strncpy(utsname.sysname, osname, LINUX_MAX_UTSNAME-1);
OpenPOWER on IntegriCloud