Changeset View
Standalone View
sys/kern/vfs_mount.c
Show First 20 Lines • Show All 1,281 Lines • ▼ Show 20 Lines | vfs_domount_update( | ||||
if ((fsflags & MNT_RELOAD) != 0 && (flag & MNT_RDONLY) == 0) { | if ((fsflags & MNT_RELOAD) != 0 && (flag & MNT_RDONLY) == 0) { | ||||
vput(vp); | vput(vp); | ||||
return (EOPNOTSUPP); /* Needs translation */ | return (EOPNOTSUPP); /* Needs translation */ | ||||
} | } | ||||
/* | /* | ||||
* Only privileged root, or (if MNT_USER is set) the user that | * Only privileged root, or (if MNT_USER is set) the user that | ||||
* did the original mount is permitted to update it. | * did the original mount is permitted to update it. | ||||
*/ | */ | ||||
#ifdef VNET_NFSD | |||||
/* | |||||
* For the case of mountd doing exports in a jail, don't | |||||
* call vfs_suser(). vfs_domount() has already checked that | |||||
* "root" is doing this and vfs_suser() will fail when | |||||
bz: That sounds spooky to me as uid 15 inside the jail has nothing to do with uid 15 outside a jail… | |||||
Done Inline ActionsWell, it is exactly what is done in vfs_suser(), except that This code is only executed if doing exporting while in the What do you think is correct here? rmacklem: Well, it is exactly what is done in vfs_suser(), except that
vfs_suser() fails automatically if… | |||||
Done Inline ActionsI have changed this check to simply cr_uid == 0. rmacklem: I have changed this check to simply cr_uid == 0.
If there is a better check, please let me know. | |||||
* the file system has been mounted outside the jail. | |||||
*/ | |||||
error = 0; | |||||
if ((fsflags & MNT_EXPORTED) == 0 || !jailed(td->td_ucred) || | |||||
!prison_check_nfsd(td->td_ucred)) | |||||
#endif | |||||
error = vfs_suser(mp, td); | error = vfs_suser(mp, td); | ||||
if (error != 0) { | if (error != 0) { | ||||
vput(vp); | vput(vp); | ||||
return (error); | return (error); | ||||
} | } | ||||
if (vfs_busy(mp, MBF_NOWAIT)) { | if (vfs_busy(mp, MBF_NOWAIT)) { | ||||
vput(vp); | vput(vp); | ||||
return (EBUSY); | return (EBUSY); | ||||
} | } | ||||
Show All 28 Lines | #endif | ||||
mp->mnt_optnew = *optlist; | mp->mnt_optnew = *optlist; | ||||
vfs_mergeopts(mp->mnt_optnew, mp->mnt_opt); | vfs_mergeopts(mp->mnt_optnew, mp->mnt_opt); | ||||
/* | /* | ||||
* Mount the filesystem. | * Mount the filesystem. | ||||
* XXX The final recipients of VFS_MOUNT just overwrite the ndp they | * XXX The final recipients of VFS_MOUNT just overwrite the ndp they | ||||
* get. No freeing of cn_pnbuf. | * get. No freeing of cn_pnbuf. | ||||
*/ | */ | ||||
#ifdef VNET_NFSD | |||||
/* | |||||
* For the case of mountd doing exports from within a vnet prison, | |||||
* "from" is not set correctly such that VFS_MOUNT() will return ENOENT. | |||||
* It is not obvious that VFS_MOUNT() ever needs to be called when | |||||
* mountd is doing exports, but this check only applies to the | |||||
* specific case where it is running inside a vnet prison, for now. | |||||
*/ | |||||
error = 0; | |||||
if ((fsflags & MNT_EXPORTED) == 0 || !jailed(td->td_ucred) || | |||||
!prison_check_nfsd(td->td_ucred)) | |||||
#endif | |||||
error = VFS_MOUNT(mp); | error = VFS_MOUNT(mp); | ||||
export_error = 0; | export_error = 0; | ||||
/* Process the export option. */ | /* Process the export option. */ | ||||
if (error == 0 && vfs_getopt(mp->mnt_optnew, "export", &bufp, | if (error == 0 && vfs_getopt(mp->mnt_optnew, "export", &bufp, | ||||
&len) == 0) { | &len) == 0) { | ||||
/* Assume that there is only 1 ABI for each length. */ | /* Assume that there is only 1 ABI for each length. */ | ||||
switch (len) { | switch (len) { | ||||
case (sizeof(struct oexport_args)): | case (sizeof(struct oexport_args)): | ||||
▲ Show 20 Lines • Show All 138 Lines • ▼ Show 20 Lines | vfs_domount( | ||||
/* | /* | ||||
* Be ultra-paranoid about making sure the type and fspath | * Be ultra-paranoid about making sure the type and fspath | ||||
* variables will fit in our mp buffers, including the | * variables will fit in our mp buffers, including the | ||||
* terminating NUL. | * terminating NUL. | ||||
*/ | */ | ||||
if (strlen(fstype) >= MFSNAMELEN || strlen(fspath) >= MNAMELEN) | if (strlen(fstype) >= MFSNAMELEN || strlen(fspath) >= MNAMELEN) | ||||
return (ENAMETOOLONG); | return (ENAMETOOLONG); | ||||
#ifdef VNET_NFSD | |||||
if ((fsflags & MNT_EXPORTED) != 0 && jailed(td->td_ucred) && | |||||
prison_check_nfsd(td->td_ucred)) { | |||||
error = priv_check(td, PRIV_NFS_DAEMON); | |||||
if (error) | |||||
return (error); | |||||
} else | |||||
#endif | |||||
if (jailed(td->td_ucred) || usermount == 0) { | if (jailed(td->td_ucred) || usermount == 0) { | ||||
if ((error = priv_check(td, PRIV_VFS_MOUNT)) != 0) | if ((error = priv_check(td, PRIV_VFS_MOUNT)) != 0) | ||||
return (error); | return (error); | ||||
} | } | ||||
/* | /* | ||||
* Do not allow NFS export or MNT_SUIDDIR by unprivileged users. | * Do not allow NFS export or MNT_SUIDDIR by unprivileged users. | ||||
*/ | */ | ||||
if (fsflags & MNT_EXPORTED) { | if (fsflags & MNT_EXPORTED) { | ||||
error = priv_check(td, PRIV_VFS_MOUNT_EXPORTED); | error = priv_check(td, PRIV_VFS_MOUNT_EXPORTED); | ||||
Not Done Inline ActionsDoesn't this also need the usermount check? I don't admit I have looked but I don't understand as-to yet why we'll need two cases and two PRIVs. bz: Doesn't this also need the usermount check? I don't admit I have looked but I don't understand… | |||||
Done Inline ActionsThis is handling the case of setting exports (normally The hassle is that mountd uses nmount(2) to do exporting, I figured that PRIV_NFSD_VIMAGE could be used to allow If you think some other PRIV_xx is appropriate, please let rmacklem: This is handling the case of setting exports (normally
done by mountd) while in the jail.
I… | |||||
Done Inline ActionsI have gotten rid of PRIV_NFSD_VIMAGE and now rmacklem: I have gotten rid of PRIV_NFSD_VIMAGE and now
just use PRIV_NFS_DAEMON for the case of loading… | |||||
if (error) | if (error) | ||||
Done Inline ActionsI realized this is no different than PRIV_NFS_DAEMON, so I rmacklem: I realized this is no different than PRIV_NFS_DAEMON, so I
have replaced PRIV_NFSD_VIMAGE with… | |||||
return (error); | return (error); | ||||
Not Done Inline Actionsstray printf bz: stray printf | |||||
Done Inline ActionsI find it useful for testing at this time. It will go away before rmacklem: I find it useful for testing at this time. It will go away before
any commit to main, but I… | |||||
} | } | ||||
if (fsflags & MNT_SUIDDIR) { | if (fsflags & MNT_SUIDDIR) { | ||||
error = priv_check(td, PRIV_VFS_MOUNT_SUIDDIR); | error = priv_check(td, PRIV_VFS_MOUNT_SUIDDIR); | ||||
if (error) | if (error) | ||||
return (error); | return (error); | ||||
} | } | ||||
/* | /* | ||||
* Silently enforce MNT_NOSUID and MNT_USER for unprivileged users. | * Silently enforce MNT_NOSUID and MNT_USER for unprivileged users. | ||||
*/ | */ | ||||
if ((fsflags & (MNT_NOSUID | MNT_USER)) != (MNT_NOSUID | MNT_USER)) { | if ((fsflags & (MNT_NOSUID | MNT_USER)) != (MNT_NOSUID | MNT_USER)) { | ||||
if (priv_check(td, PRIV_VFS_MOUNT_NONUSER) != 0) | if (priv_check(td, PRIV_VFS_MOUNT_NONUSER) != 0) | ||||
fsflags |= MNT_NOSUID | MNT_USER; | fsflags |= MNT_NOSUID | MNT_USER; | ||||
} | } | ||||
/* Load KLDs before we lock the covered vnode to avoid reversals. */ | /* Load KLDs before we lock the covered vnode to avoid reversals. */ | ||||
vfsp = NULL; | vfsp = NULL; | ||||
if ((fsflags & MNT_UPDATE) == 0) { | if ((fsflags & MNT_UPDATE) == 0) { | ||||
Done Inline ActionsBy the way, I ifdef'd this because it was never being rmacklem: By the way, I ifdef'd this because it was never being
executed before (MNT_EXPORTED is never… | |||||
/* Don't try to load KLDs if we're mounting the root. */ | /* Don't try to load KLDs if we're mounting the root. */ | ||||
if (fsflags & MNT_ROOTFS) { | if (fsflags & MNT_ROOTFS) { | ||||
if ((vfsp = vfs_byname(fstype)) == NULL) | if ((vfsp = vfs_byname(fstype)) == NULL) | ||||
return (ENODEV); | return (ENODEV); | ||||
} else { | } else { | ||||
if ((vfsp = vfs_byname_kld(fstype, td, &error)) == NULL) | if ((vfsp = vfs_byname_kld(fstype, td, &error)) == NULL) | ||||
return (error); | return (error); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 1,490 Lines • Show Last 20 Lines |
That sounds spooky to me as uid 15 inside the jail has nothing to do with uid 15 outside a jail and uid 0 inside a jail definitively is not uid 0 outside the jail.