summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_jail.c
diff options
context:
space:
mode:
authormm <mm@FreeBSD.org>2012-01-15 12:08:20 +0000
committermm <mm@FreeBSD.org>2012-01-15 12:08:20 +0000
commit9f44ed5ca827811dd8729bb0ab4397c71161fa9c (patch)
tree7cb3e09e5396eca584100f0f0377b0dd5a33d1ba /sys/kern/kern_jail.c
parent4642718fb42bef8b06538195461ee680c22cd1f9 (diff)
downloadFreeBSD-src-9f44ed5ca827811dd8729bb0ab4397c71161fa9c.zip
FreeBSD-src-9f44ed5ca827811dd8729bb0ab4397c71161fa9c.tar.gz
Introduce vn_path_to_global_path()
This function updates path string to vnode's full global path and checks the size of the new path string against the pathlen argument. In vfs_domount(), sys_unmount() and kern_jail_set() this new function is used to update the supplied path argument to the respective global path. Unbreaks jailed zfs(8) with enforce_statfs set to 1. Reviewed by: kib MFC after: 1 month
Diffstat (limited to 'sys/kern/kern_jail.c')
-rw-r--r--sys/kern/kern_jail.c50
1 files changed, 31 insertions, 19 deletions
diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c
index 84f5575..de92dc4 100644
--- a/sys/kern/kern_jail.c
+++ b/sys/kern/kern_jail.c
@@ -531,6 +531,7 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
int gotchildmax, gotenforce, gothid, gotslevel;
int fi, jid, jsys, len, level;
int childmax, slevel, vfslocked;
+ int fullpath_disabled;
#if defined(INET) || defined(INET6)
int ii, ij;
#endif
@@ -897,30 +898,40 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
error = EINVAL;
goto done_free;
}
- if (len < 2 || (len == 2 && path[0] == '/'))
- path = NULL;
- else {
+ NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE, UIO_SYSSPACE,
+ path, td);
+ error = namei(&nd);
+ if (error)
+ goto done_free;
+ vfslocked = NDHASGIANT(&nd);
+ root = nd.ni_vp;
+ NDFREE(&nd, NDF_ONLY_PNBUF);
+ error = vn_path_to_global_path(td, root, path, MAXPATHLEN);
+ if (error == ENODEV) {
+ /* proceed if sysctl debug.disablefullpath == 1 */
+ fullpath_disabled = 1;
+ if (len < 2 || (len == 2 && path[0] == '/'))
+ path = NULL;
+ } else if (error != 0) {
+ /* exit on other errors */
+ VFS_UNLOCK_GIANT(vfslocked);
+ goto done_free;
+ }
+ if (root->v_type != VDIR) {
+ error = ENOTDIR;
+ vput(root);
+ VFS_UNLOCK_GIANT(vfslocked);
+ goto done_free;
+ }
+ VOP_UNLOCK(root, 0);
+ VFS_UNLOCK_GIANT(vfslocked);
+ if (fullpath_disabled) {
/* Leave room for a real-root full pathname. */
if (len + (path[0] == '/' && strcmp(mypr->pr_path, "/")
? strlen(mypr->pr_path) : 0) > MAXPATHLEN) {
error = ENAMETOOLONG;
goto done_free;
}
- NDINIT(&nd, LOOKUP, MPSAFE | FOLLOW, UIO_SYSSPACE,
- path, td);
- error = namei(&nd);
- if (error)
- goto done_free;
- vfslocked = NDHASGIANT(&nd);
- root = nd.ni_vp;
- NDFREE(&nd, NDF_ONLY_PNBUF);
- if (root->v_type != VDIR) {
- error = ENOTDIR;
- vrele(root);
- VFS_UNLOCK_GIANT(vfslocked);
- goto done_free;
- }
- VFS_UNLOCK_GIANT(vfslocked);
}
}
@@ -1583,7 +1594,8 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
}
if (path != NULL) {
/* Try to keep a real-rooted full pathname. */
- if (path[0] == '/' && strcmp(mypr->pr_path, "/"))
+ if (fullpath_disabled && path[0] == '/' &&
+ strcmp(mypr->pr_path, "/"))
snprintf(pr->pr_path, sizeof(pr->pr_path), "%s%s",
mypr->pr_path, path);
else
OpenPOWER on IntegriCloud