Add MD_VERIFY option to enable O_VERIFY in open for vnode type.

Add -o [no]verify option to mdconfig (and document in man page.)
Implement GEOM attribute MNT::verified to ask md if the backing vnode is
  verified.
Check for MNT::verified in cd9660 mount to flag the mount as MNT_VERIFIED if
  the underlying device has been verified.

Reviewed by:	rwatson
Approved by:	sjg (mentor)
Obtained from:	Juniper Networks, Inc.
Differential Revision:	https://reviews.freebsd.org/D2902
This commit is contained in:
Stephen J. Kiernan 2017-05-31 21:18:11 +00:00
parent 9a83b0971e
commit 9a81ba0f24
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=319358
8 changed files with 55 additions and 3 deletions

View file

@ -215,6 +215,14 @@ flag to forcibly destroy an
disk that is still in use.
.It Oo Cm no Oc Ns Cm readonly
Enable/disable readonly mode.
.It Oo Cm no Oc Ns Cm verify
For
.Cm vnode
backed devices: enable/disable requesting verification of the
file used for backing store.
The type of verification depends on which security features are available.
One example of verification is testing file integrity with
checksums or cryptographic signatures.
.El
.It Fl u Ar unit
Request a specific unit number or device name for the
@ -298,6 +306,7 @@ gnop create -o 512K md1
mount /dev/md1.nop /mnt
.Ed
.Sh SEE ALSO
.Xr open 2 ,
.Xr md 4 ,
.Xr ffs 7 ,
.Xr gpart 8 ,

View file

@ -193,6 +193,10 @@ main(int argc, char **argv)
mdio.md_options |= MD_RESERVE;
else if (!strcmp(optarg, "noreserve"))
mdio.md_options &= ~MD_RESERVE;
else if (!strcmp(optarg, "verify"))
mdio.md_options |= MD_VERIFY;
else if (!strcmp(optarg, "noverify"))
mdio.md_options &= ~MD_VERIFY;
else
errx(1, "unknown option: %s", optarg);
break;

View file

@ -115,6 +115,7 @@ static struct opt {
{ MNT_NFS4ACLS, "nfsv4acls" },
{ MNT_GJOURNAL, "gjournal" },
{ MNT_AUTOMOUNTED, "automounted" },
{ MNT_VERIFIED, "verified" },
{ 0, NULL }
};

View file

@ -88,6 +88,7 @@
#include <sys/sf_buf.h>
#include <sys/sysctl.h>
#include <sys/vnode.h>
#include <sys/disk.h>
#include <geom/geom.h>
#include <geom/geom_int.h>
@ -949,6 +950,8 @@ mdstart_vnode(struct md_s *sc, struct bio *bp)
sc->cred);
VOP_UNLOCK(vp, 0);
vn_finished_write(mp);
if (error == 0)
sc->flags &= ~MD_VERIFY;
}
if (pb != NULL) {
@ -1143,6 +1146,8 @@ md_kthread(void *arg)
}
mtx_unlock(&sc->queue_mtx);
if (bp->bio_cmd == BIO_GETATTR) {
int isv = ((sc->flags & MD_VERIFY) != 0);
if ((sc->fwsectors && sc->fwheads &&
(g_handleattr_int(bp, "GEOM::fwsectors",
sc->fwsectors) ||
@ -1150,6 +1155,8 @@ md_kthread(void *arg)
sc->fwheads))) ||
g_handleattr_int(bp, "GEOM::candelete", 1))
error = -1;
else if (g_handleattr_int(bp, "MNT::verified", isv))
error = -1;
else
error = EOPNOTSUPP;
} else {
@ -1352,7 +1359,8 @@ mdcreate_vnode(struct md_s *sc, struct md_ioctl *mdio, struct thread *td)
* If the user specified that this is a read only device, don't
* set the FWRITE mask before trying to open the backing store.
*/
flags = FREAD | ((mdio->md_options & MD_READONLY) ? 0 : FWRITE);
flags = FREAD | ((mdio->md_options & MD_READONLY) ? 0 : FWRITE) \
| ((mdio->md_options & MD_VERIFY) ? 0 : O_VERIFY);
NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, sc->file, td);
error = vn_open(&nd, &flags, 0, NULL);
if (error != 0)
@ -1380,7 +1388,7 @@ mdcreate_vnode(struct md_s *sc, struct md_ioctl *mdio, struct thread *td)
sc->fwsectors = mdio->md_fwsectors;
if (mdio->md_fwheads != 0)
sc->fwheads = mdio->md_fwheads;
sc->flags = mdio->md_options & (MD_FORCE | MD_ASYNC);
sc->flags = mdio->md_options & (MD_FORCE | MD_ASYNC | MD_VERIFY);
if (!(flags & FWRITE))
sc->flags |= MD_READONLY;
sc->vnode = nd.ni_vp;
@ -1523,6 +1531,8 @@ mdcreate_swap(struct md_s *sc, struct md_ioctl *mdio, struct thread *td)
* Note the truncation.
*/
if ((mdio->md_options & MD_VERIFY) != 0)
return (EINVAL);
npage = mdio->md_mediasize / PAGE_SIZE;
if (mdio->md_fwsectors != 0)
sc->fwsectors = mdio->md_fwsectors;

View file

@ -215,6 +215,7 @@ iso_mountfs(devvp, mp)
int iso_bsize;
int iso_blknum;
int joliet_level;
int isverified = 0;
struct iso_volume_descriptor *vdp = NULL;
struct iso_primary_descriptor *pri = NULL;
struct iso_sierra_primary_descriptor *pri_sierra = NULL;
@ -229,6 +230,8 @@ iso_mountfs(devvp, mp)
dev_ref(dev);
g_topology_lock();
error = g_vfs_open(devvp, &cp, "cd9660", 0);
if (error == 0)
g_getattr("MNT::verified", cp, &isverified);
g_topology_unlock();
VOP_UNLOCK(devvp, 0);
if (error)
@ -377,6 +380,8 @@ iso_mountfs(devvp, mp)
mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
mp->mnt_maxsymlinklen = 0;
MNT_ILOCK(mp);
if (isverified)
mp->mnt_flag |= MNT_VERIFIED;
mp->mnt_flag |= MNT_LOCAL;
mp->mnt_kern_flag |= MNTK_LOOKUP_SHARED | MNTK_EXTENDED_SHARED;
MNT_IUNLOCK(mp);

View file

@ -464,6 +464,27 @@ g_uzip_start(struct bio *bp)
sc = gp->softc;
sc->req_total++;
if (bp->bio_cmd == BIO_GETATTR) {
struct bio *bp2;
struct g_consumer *cp;
struct g_geom *gp;
struct g_provider *pp;
/* pass on MNT:* requests and ignore others */
if (strncmp(bp->bio_attribute, "MNT:", 4) == 0) {
bp2 = g_clone_bio(bp);
if (bp2 == NULL) {
g_io_deliver(bp, ENOMEM);
return;
}
bp2->bio_done = g_std_done;
pp = bp->bio_to;
gp = pp->geom;
cp = LIST_FIRST(&gp->consumer);
g_io_request(bp2, cp);
return;
}
}
if (bp->bio_cmd != BIO_READ) {
g_io_deliver(bp, EOPNOTSUPP);
return;

View file

@ -88,5 +88,6 @@ struct md_ioctl {
#define MD_COMPRESS 0x10 /* Compression mode */
#define MD_FORCE 0x20 /* Don't try to prevent foot-shooting */
#define MD_ASYNC 0x40 /* Asynchronous mode */
#define MD_VERIFY 0x80 /* Open file with O_VERIFY (vnode only) */
#endif /* _SYS_MDIOCTL_H_*/

View file

@ -314,6 +314,7 @@ void __mnt_vnode_markerfree_active(struct vnode **mvp, struct mount *);
#define MNT_ROOTFS 0x0000000000004000ULL /* identifies the root fs */
#define MNT_USER 0x0000000000008000ULL /* mounted by a user */
#define MNT_IGNORE 0x0000000000800000ULL /* do not show entry in df */
#define MNT_VERIFIED 0x0000000400000000ULL /* filesystem is verified */
/*
* Mask of flags that are visible to statfs().
@ -329,7 +330,7 @@ void __mnt_vnode_markerfree_active(struct vnode **mvp, struct mount *);
MNT_NOCLUSTERW | MNT_SUIDDIR | MNT_SOFTDEP | \
MNT_IGNORE | MNT_EXPUBLIC | MNT_NOSYMFOLLOW | \
MNT_GJOURNAL | MNT_MULTILABEL | MNT_ACLS | \
MNT_NFS4ACLS | MNT_AUTOMOUNTED)
MNT_NFS4ACLS | MNT_AUTOMOUNTED | MNT_VERIFIED)
/* Mask of flags that can be updated. */
#define MNT_UPDATEMASK (MNT_NOSUID | MNT_NOEXEC | \