diff options
-rw-r--r-- | sys/kern/kern_jail.c | 20 | ||||
-rw-r--r-- | sys/kern/vfs_extattr.c | 8 | ||||
-rw-r--r-- | sys/kern/vfs_syscalls.c | 8 | ||||
-rw-r--r-- | sys/sys/jail.h | 3 |
4 files changed, 39 insertions, 0 deletions
diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c index 79be249..8d19dcb 100644 --- a/sys/kern/kern_jail.c +++ b/sys/kern/kern_jail.c @@ -54,6 +54,11 @@ SYSCTL_INT(_security_jail, OID_AUTO, sysvipc_allowed, CTLFLAG_RW, &jail_sysvipc_allowed, 0, "Processes in jail can use System V IPC primitives"); +int jail_getfsstatroot_only = 1; +SYSCTL_INT(_security_jail, OID_AUTO, getfsstate_getfsstatroot_only, CTLFLAG_RW, + &jail_getfsstatroot_only, 0, + "Processes see only their root file system in getfsstat()"); + /* allprison, lastprid, and prisoncount are protected by allprison_mtx. */ struct prisonlist allprison; struct mtx allprison_mtx; @@ -418,6 +423,21 @@ getcredhostname(struct ucred *cred, char *buf, size_t size) strlcpy(buf, hostname, size); } +/* + * Return 1 if the passed credential can "see" the passed mountpoint + * when performing a getfsstat(); otherwise, 0. + */ +int +prison_check_mount(struct ucred *cred, struct mount *mp) +{ + + if (jail_getfsstatroot_only) { + if (cred->cr_prison->pr_root->v_mount != mp) + return (0); + } + return (1); +} + static int sysctl_jail_list(SYSCTL_HANDLER_ARGS) { diff --git a/sys/kern/vfs_extattr.c b/sys/kern/vfs_extattr.c index fac2e2f..5115e1a 100644 --- a/sys/kern/vfs_extattr.c +++ b/sys/kern/vfs_extattr.c @@ -341,6 +341,10 @@ getfsstat(td, uap) count = 0; mtx_lock(&mountlist_mtx); for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) { + if (!prison_check_mount(td->td_ucred, mp)) { + nmp = TAILQ_NEXT(mp, mnt_list); + continue; + } #ifdef MAC if (mac_check_mount_stat(td->td_ucred, mp) != 0) { nmp = TAILQ_NEXT(mp, mnt_list); @@ -519,6 +523,10 @@ freebsd4_getfsstat(td, uap) count = 0; mtx_lock(&mountlist_mtx); for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) { + if (!prison_check_mount(td->td_ucred, mp)) { + nmp = TAILQ_NEXT(mp, mnt_list); + continue; + } #ifdef MAC if (mac_check_mount_stat(td->td_ucred, mp) != 0) { nmp = TAILQ_NEXT(mp, mnt_list); diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index fac2e2f..5115e1a 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -341,6 +341,10 @@ getfsstat(td, uap) count = 0; mtx_lock(&mountlist_mtx); for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) { + if (!prison_check_mount(td->td_ucred, mp)) { + nmp = TAILQ_NEXT(mp, mnt_list); + continue; + } #ifdef MAC if (mac_check_mount_stat(td->td_ucred, mp) != 0) { nmp = TAILQ_NEXT(mp, mnt_list); @@ -519,6 +523,10 @@ freebsd4_getfsstat(td, uap) count = 0; mtx_lock(&mountlist_mtx); for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) { + if (!prison_check_mount(td->td_ucred, mp)) { + nmp = TAILQ_NEXT(mp, mnt_list); + continue; + } #ifdef MAC if (mac_check_mount_stat(td->td_ucred, mp) != 0) { nmp = TAILQ_NEXT(mp, mnt_list); diff --git a/sys/sys/jail.h b/sys/sys/jail.h index 9779363..576d2fd 100644 --- a/sys/sys/jail.h +++ b/sys/sys/jail.h @@ -81,6 +81,7 @@ struct prison { extern int jail_set_hostname_allowed; extern int jail_socket_unixiproute_only; extern int jail_sysvipc_allowed; +extern int jail_getfsstat_jailrootonly; LIST_HEAD(prisonlist, prison); extern struct prisonlist allprison; @@ -89,10 +90,12 @@ extern struct prisonlist allprison; * Kernel support functions for jail(). */ struct ucred; +struct mount; struct sockaddr; int jailed(struct ucred *cred); void getcredhostname(struct ucred *cred, char *, size_t); int prison_check(struct ucred *cred1, struct ucred *cred2); +int prison_check_mount(struct ucred *cred, struct mount *mp); void prison_free(struct prison *pr); u_int32_t prison_getip(struct ucred *cred); void prison_hold(struct prison *pr); |