diff options
author | pjd <pjd@FreeBSD.org> | 2005-06-09 18:49:19 +0000 |
---|---|---|
committer | pjd <pjd@FreeBSD.org> | 2005-06-09 18:49:19 +0000 |
commit | 47f442bcb9bd412e8e5d053dc5bf1d4c97d93b81 (patch) | |
tree | 4920e7fa66313114f8e377130095e6f5050c167e /sys/kern/kern_jail.c | |
parent | 45eec321507d3992b03d03933268aefd7ac48dfa (diff) | |
download | FreeBSD-src-47f442bcb9bd412e8e5d053dc5bf1d4c97d93b81.zip FreeBSD-src-47f442bcb9bd412e8e5d053dc5bf1d4c97d93b81.tar.gz |
Rename sysctl security.jail.getfsstatroot_only to security.jail.enforce_statfs
and extend its functionality:
value policy
0 show all mount-points without any restrictions
1 show only mount-points below jail's chroot and show only part of the
mount-point's path (if jail's chroot directory is /jails/foo and
mount-point is /jails/foo/usr/home only /usr/home will be shown)
2 show only mount-point where jail's chroot directory is placed.
Default value is 2.
Discussed with: rwatson
Diffstat (limited to 'sys/kern/kern_jail.c')
-rw-r--r-- | sys/kern/kern_jail.c | 97 |
1 files changed, 86 insertions, 11 deletions
diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c index e125622..9ca85c6 100644 --- a/sys/kern/kern_jail.c +++ b/sys/kern/kern_jail.c @@ -26,6 +26,7 @@ __FBSDID("$FreeBSD$"); #include <sys/lock.h> #include <sys/mutex.h> #include <sys/namei.h> +#include <sys/mount.h> #include <sys/queue.h> #include <sys/socket.h> #include <sys/syscallsubr.h> @@ -55,10 +56,10 @@ 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, getfsstatroot_only, CTLFLAG_RW, - &jail_getfsstatroot_only, 0, - "Processes see only their root file system in getfsstat()"); +static int jail_enforce_statfs = 2; +SYSCTL_INT(_security_jail, OID_AUTO, enforce_statfs, CTLFLAG_RW, + &jail_enforce_statfs, 0, + "Processes in jail cannot see all mounted file systems"); int jail_allow_raw_sockets = 0; SYSCTL_INT(_security_jail, OID_AUTO, allow_raw_sockets, CTLFLAG_RW, @@ -435,18 +436,92 @@ getcredhostname(struct ucred *cred, char *buf, size_t size) } /* - * Return 1 if the passed credential can "see" the passed mountpoint - * when performing a getfsstat(); otherwise, 0. + * Determine whether the subject represented by cred can "see" + * status of a mount point. + * Returns: 0 for permitted, ENOENT otherwise. + * XXX: This function should be called cr_canseemount() and should be + * placed in kern_prot.c. */ int -prison_check_mount(struct ucred *cred, struct mount *mp) +prison_canseemount(struct ucred *cred, struct mount *mp) { + struct prison *pr; + struct statfs *sp; + size_t len; - if (jail_getfsstatroot_only && cred->cr_prison != NULL) { - if (cred->cr_prison->pr_root->v_mount != mp) - return (0); + if (!jailed(cred) || jail_enforce_statfs == 0) + return (0); + pr = cred->cr_prison; + if (pr->pr_root->v_mount == mp) + return (0); + if (jail_enforce_statfs == 2) + return (ENOENT); + /* + * If jail's chroot directory is set to "/" we should be able to see + * all mount-points from inside a jail. + * This is ugly check, but this is the only situation when jail's + * directory ends with '/'. + */ + if (strcmp(pr->pr_path, "/") == 0) + return (0); + len = strlen(pr->pr_path); + sp = &mp->mnt_stat; + if (strncmp(pr->pr_path, sp->f_mntonname, len) != 0) + return (ENOENT); + /* + * Be sure that we don't have situation where jail's root directory + * is "/some/path" and mount point is "/some/pathpath". + */ + if (sp->f_mntonname[len] != '\0' && sp->f_mntonname[len] != '/') + return (ENOENT); + return (0); +} + +void +prison_enforce_statfs(struct ucred *cred, struct mount *mp, struct statfs *sp) +{ + char jpath[MAXPATHLEN]; + struct prison *pr; + size_t len; + + if (!jailed(cred) || jail_enforce_statfs == 0) + return; + pr = cred->cr_prison; + if (prison_canseemount(cred, mp) != 0) { + /* Should never happen. */ + bzero(sp->f_mntonname, sizeof(sp->f_mntonname)); + strlcpy(sp->f_mntonname, "[restricted]", + sizeof(sp->f_mntonname)); + return; + } + if (pr->pr_root->v_mount == mp) { + /* + * Clear current buffer data, so we are sure nothing from + * the valid path left there. + */ + bzero(sp->f_mntonname, sizeof(sp->f_mntonname)); + *sp->f_mntonname = '/'; + return; + } + /* + * If jail's chroot directory is set to "/" we should be able to see + * all mount-points from inside a jail. + */ + if (strcmp(pr->pr_path, "/") == 0) + return; + len = strlen(pr->pr_path); + strlcpy(jpath, sp->f_mntonname + len, sizeof(jpath)); + /* + * Clear current buffer data, so we are sure nothing from + * the valid path left there. + */ + bzero(sp->f_mntonname, sizeof(sp->f_mntonname)); + if (*jpath == '\0') { + /* Should never happen. */ + *sp->f_mntonname = '/'; + } else { + strlcpy(sp->f_mntonname, jpath, sizeof(sp->f_mntonname)); } - return (1); } static int |