PERFORCE change 16342 for review
Robert Watson
rwatson at freebsd.org
Tue Aug 20 17:28:15 GMT 2002
http://people.freebsd.org/~peter/p4db/chv.cgi?CH=16342
Change 16342 by rwatson at rwatson_tislabs on 2002/08/20 10:27:18
Move a chunk of vnode-related label management code to a more
logical location away from label initialization/destruction/...
Affected files ...
.. //depot/projects/trustedbsd/mac/sys/kern/kern_mac.c#255 edit
Differences ...
==== //depot/projects/trustedbsd/mac/sys/kern/kern_mac.c#255 (text+ko) ====
@@ -196,7 +196,6 @@
#endif
static int error_select(int error1, int error2);
-static int mac_externalize(struct label *label, struct mac *mac);
static int mac_policy_register(struct mac_policy_conf *mpc);
static int mac_policy_unregister(struct mac_policy_conf *mpc);
@@ -962,287 +961,6 @@
return (error2);
}
-void
-mac_update_devfsdirent(struct devfs_dirent *de, struct vnode *vp)
-{
-
- MAC_PERFORM(update_devfsdirent, de, &de->de_label, vp, &vp->v_label);
-}
-
-void
-mac_update_procfsvnode(struct vnode *vp, struct ucred *cred)
-{
-
- MAC_PERFORM(update_procfsvnode, vp, &vp->v_label, cred);
-}
-
-/*
- * Support callout for policies that manage their own externalization
- * using extended attributes.
- */
-static int
-mac_update_vnode_from_extattr(struct vnode *vp, struct mount *mp)
-{
- int error;
-
- MAC_CHECK(update_vnode_from_extattr, vp, &vp->v_label, mp,
- &mp->mnt_fslabel);
-
- return (error);
-}
-
-/*
- * Given an externalized mac label, internalize it and stamp it on a
- * vnode.
- */
-static int
-mac_update_vnode_from_externalized(struct vnode *vp, struct mac *extmac)
-{
- int error;
-
- MAC_CHECK(update_vnode_from_externalized, vp, &vp->v_label, extmac);
-
- return (error);
-}
-
-/*
- * Call out to individual policies to update the label in a vnode from
- * the mountpoint.
- */
-void
-mac_update_vnode_from_mount(struct vnode *vp, struct mount *mp)
-{
-
- MAC_PERFORM(update_vnode_from_mount, vp, &vp->v_label, mp,
- &mp->mnt_fslabel);
-
- ASSERT_VOP_LOCKED(vp, "mac_update_vnode_from_mount");
- if (mac_cache_fslabel_in_vnode)
- vp->v_vflag |= VV_CACHEDLABEL;
-}
-
-/*
- * Implementation of VOP_REFRESHLABEL() that relies on extended attributes
- * to store label data. Can be referenced by filesystems supporting
- * extended attributes.
- */
-int
-vop_stdrefreshlabel_ea(struct vop_refreshlabel_args *ap)
-{
- struct vnode *vp = ap->a_vp;
- struct mac extmac;
- int buflen, error;
-
- ASSERT_VOP_LOCKED(vp, "vop_stdrefreshlabel_ea");
-
- /*
- * Call out to external policies first. Order doesn't really
- * matter, as long as failure of one assures failure of all.
- */
- error = mac_update_vnode_from_extattr(vp, vp->v_mount);
- if (error)
- return (error);
-
- buflen = sizeof(extmac);
- error = vn_extattr_get(vp, IO_NODELOCKED,
- FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME, &buflen,
- (char *)&extmac, curthread);
- switch (error) {
- case 0:
- /* Got it */
- break;
-
- case ENOATTR:
- /*
- * Use the label from the mount point.
- */
- mac_update_vnode_from_mount(vp, vp->v_mount);
- return (0);
-
- case EOPNOTSUPP:
- default:
- /* Fail horribly. */
- return (error);
- }
-
- if (buflen != sizeof(extmac))
- error = EPERM; /* Fail very closed. */
- if (error == 0)
- error = mac_update_vnode_from_externalized(vp, &extmac);
- if (error == 0)
- vp->v_vflag |= VV_CACHEDLABEL;
- else {
- struct vattr va;
-
- printf("Corrupted label on %s",
- vp->v_mount->mnt_stat.f_mntonname);
- if (VOP_GETATTR(vp, &va, curthread->td_ucred, curthread) == 0)
- printf(" inum %ld", va.va_fileid);
- if (mac_debug_label_fallback) {
- printf(", falling back.\n");
- mac_update_vnode_from_mount(vp, vp->v_mount);
- error = 0;
- } else {
- printf(".\n");
- error = EPERM;
- }
- }
-
- return (error);
-}
-
-/*
- * Make sure the vnode label is up-to-date. If EOPNOTSUPP, then we handle
- * the labeling activity outselves. Filesystems should be careful not
- * to change their minds regarding whether they support vop_refreshlabel()
- * for a vnode or not. Don't cache the vnode here, allow the file
- * system code to determine if it's safe to cache. If we update from
- * the mount, don't cache since a change to the mount label should affect
- * all vnodes.
- */
-static int
-vn_refreshlabel(struct vnode *vp, struct ucred *cred)
-{
- int error;
-
- ASSERT_VOP_LOCKED(vp, "vn_refreshlabel");
-
- if (vp->v_mount == NULL) {
-/*
- Eventually, we probably want to special-case refreshing
- of deadfs vnodes, and if there's a lock-free race somewhere,
- that case might be handled here.
-
- mac_update_vnode_deadfs(vp);
- return (0);
- */
- /* printf("vn_refreshlabel: null v_mount\n"); */
- if (vp->v_tag != VT_NON)
- printf(
- "vn_refreshlabel: null v_mount with non-VT_NON\n");
- return (EBADF);
- }
-
- if (vp->v_vflag & VV_CACHEDLABEL) {
- mac_vnode_label_cache_hits++;
- return (0);
- } else
- mac_vnode_label_cache_misses++;
-
- if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) {
- mac_update_vnode_from_mount(vp, vp->v_mount);
- return (0);
- }
-
- error = VOP_REFRESHLABEL(vp, cred, curthread);
- switch (error) {
- case EOPNOTSUPP:
- /*
- * If labels are not supported on this vnode, fall back to
- * the label in the mount and propagate it to the vnode.
- * There should probably be some sort of policy/flag/decision
- * about doing this.
- */
- mac_update_vnode_from_mount(vp, vp->v_mount);
- error = 0;
- default:
- return (error);
- }
-}
-
-/*
- * Helper function for file systems using the vop_std*_ea() calls. This
- * function must be called after EA service is available for the vnode,
- * but before it's hooked up to the namespace so that the node persists
- * if there's a crash, or before it can be accessed. On successful
- * commit of the label to disk (etc), do cache the label.
- */
-int
-vop_stdcreatevnode_ea(struct vnode *dvp, struct vnode *tvp, struct ucred *cred)
-{
- struct mac extmac;
- int error;
-
- ASSERT_VOP_LOCKED(tvp, "vop_stdcreatevnode_ea");
- if ((dvp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) {
- mac_update_vnode_from_mount(tvp, tvp->v_mount);
- } else {
- error = vn_refreshlabel(dvp, cred);
- if (error)
- return (error);
-
- /*
- * Stick the label in the vnode. Then try to write to
- * disk. If we fail, return a failure to abort the
- * create operation. Really, this failure shouldn't
- * happen except in fairly unusual circumstances (out
- * of disk, etc).
- */
- mac_create_vnode(cred, dvp, tvp);
-
- error = mac_stdcreatevnode_ea(tvp);
- if (error)
- return (error);
-
- /*
- * XXX: Eventually this will go away and all policies will
- * directly manage their extended attributes.
- */
- error = mac_externalize(&tvp->v_label, &extmac);
- if (error)
- return (error);
-
- error = vn_extattr_set(tvp, IO_NODELOCKED,
- FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME,
- sizeof(extmac), (char *)&extmac, curthread);
- if (error == 0)
- tvp->v_vflag |= VV_CACHEDLABEL;
- else {
-#if 0
- /*
- * In theory, we could have fall-back behavior here.
- * It would probably be incorrect.
- */
-#endif
- return (error);
- }
- }
-
- return (0);
-}
-
-void
-mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp)
-{
- int error;
-
- ASSERT_VOP_LOCKED(vp, "mac_execve_transition");
-
- error = vn_refreshlabel(vp, old);
- if (error) {
- printf("mac_execve_transition: vn_refreshlabel returned %d\n",
- error);
- printf("mac_execve_transition: using old vnode label\n");
- }
-
- MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label);
-}
-
-int
-mac_execve_will_transition(struct ucred *old, struct vnode *vp)
-{
- int error, result;
-
- error = vn_refreshlabel(vp, old);
- if (error)
- return (error);
-
- result = 0;
- MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label);
-
- return (result);
-}
-
static void
mac_init_label(struct label *label)
{
@@ -1584,6 +1302,287 @@
MAC_PERFORM(create_cred, parent_cred, child_cred);
}
+void
+mac_update_devfsdirent(struct devfs_dirent *de, struct vnode *vp)
+{
+
+ MAC_PERFORM(update_devfsdirent, de, &de->de_label, vp, &vp->v_label);
+}
+
+void
+mac_update_procfsvnode(struct vnode *vp, struct ucred *cred)
+{
+
+ MAC_PERFORM(update_procfsvnode, vp, &vp->v_label, cred);
+}
+
+/*
+ * Support callout for policies that manage their own externalization
+ * using extended attributes.
+ */
+static int
+mac_update_vnode_from_extattr(struct vnode *vp, struct mount *mp)
+{
+ int error;
+
+ MAC_CHECK(update_vnode_from_extattr, vp, &vp->v_label, mp,
+ &mp->mnt_fslabel);
+
+ return (error);
+}
+
+/*
+ * Given an externalized mac label, internalize it and stamp it on a
+ * vnode.
+ */
+static int
+mac_update_vnode_from_externalized(struct vnode *vp, struct mac *extmac)
+{
+ int error;
+
+ MAC_CHECK(update_vnode_from_externalized, vp, &vp->v_label, extmac);
+
+ return (error);
+}
+
+/*
+ * Call out to individual policies to update the label in a vnode from
+ * the mountpoint.
+ */
+void
+mac_update_vnode_from_mount(struct vnode *vp, struct mount *mp)
+{
+
+ MAC_PERFORM(update_vnode_from_mount, vp, &vp->v_label, mp,
+ &mp->mnt_fslabel);
+
+ ASSERT_VOP_LOCKED(vp, "mac_update_vnode_from_mount");
+ if (mac_cache_fslabel_in_vnode)
+ vp->v_vflag |= VV_CACHEDLABEL;
+}
+
+/*
+ * Implementation of VOP_REFRESHLABEL() that relies on extended attributes
+ * to store label data. Can be referenced by filesystems supporting
+ * extended attributes.
+ */
+int
+vop_stdrefreshlabel_ea(struct vop_refreshlabel_args *ap)
+{
+ struct vnode *vp = ap->a_vp;
+ struct mac extmac;
+ int buflen, error;
+
+ ASSERT_VOP_LOCKED(vp, "vop_stdrefreshlabel_ea");
+
+ /*
+ * Call out to external policies first. Order doesn't really
+ * matter, as long as failure of one assures failure of all.
+ */
+ error = mac_update_vnode_from_extattr(vp, vp->v_mount);
+ if (error)
+ return (error);
+
+ buflen = sizeof(extmac);
+ error = vn_extattr_get(vp, IO_NODELOCKED,
+ FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME, &buflen,
+ (char *)&extmac, curthread);
+ switch (error) {
+ case 0:
+ /* Got it */
+ break;
+
+ case ENOATTR:
+ /*
+ * Use the label from the mount point.
+ */
+ mac_update_vnode_from_mount(vp, vp->v_mount);
+ return (0);
+
+ case EOPNOTSUPP:
+ default:
+ /* Fail horribly. */
+ return (error);
+ }
+
+ if (buflen != sizeof(extmac))
+ error = EPERM; /* Fail very closed. */
+ if (error == 0)
+ error = mac_update_vnode_from_externalized(vp, &extmac);
+ if (error == 0)
+ vp->v_vflag |= VV_CACHEDLABEL;
+ else {
+ struct vattr va;
+
+ printf("Corrupted label on %s",
+ vp->v_mount->mnt_stat.f_mntonname);
+ if (VOP_GETATTR(vp, &va, curthread->td_ucred, curthread) == 0)
+ printf(" inum %ld", va.va_fileid);
+ if (mac_debug_label_fallback) {
+ printf(", falling back.\n");
+ mac_update_vnode_from_mount(vp, vp->v_mount);
+ error = 0;
+ } else {
+ printf(".\n");
+ error = EPERM;
+ }
+ }
+
+ return (error);
+}
+
+/*
+ * Make sure the vnode label is up-to-date. If EOPNOTSUPP, then we handle
+ * the labeling activity outselves. Filesystems should be careful not
+ * to change their minds regarding whether they support vop_refreshlabel()
+ * for a vnode or not. Don't cache the vnode here, allow the file
+ * system code to determine if it's safe to cache. If we update from
+ * the mount, don't cache since a change to the mount label should affect
+ * all vnodes.
+ */
+static int
+vn_refreshlabel(struct vnode *vp, struct ucred *cred)
+{
+ int error;
+
+ ASSERT_VOP_LOCKED(vp, "vn_refreshlabel");
+
+ if (vp->v_mount == NULL) {
+/*
+ Eventually, we probably want to special-case refreshing
+ of deadfs vnodes, and if there's a lock-free race somewhere,
+ that case might be handled here.
+
+ mac_update_vnode_deadfs(vp);
+ return (0);
+ */
+ /* printf("vn_refreshlabel: null v_mount\n"); */
+ if (vp->v_tag != VT_NON)
+ printf(
+ "vn_refreshlabel: null v_mount with non-VT_NON\n");
+ return (EBADF);
+ }
+
+ if (vp->v_vflag & VV_CACHEDLABEL) {
+ mac_vnode_label_cache_hits++;
+ return (0);
+ } else
+ mac_vnode_label_cache_misses++;
+
+ if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) {
+ mac_update_vnode_from_mount(vp, vp->v_mount);
+ return (0);
+ }
+
+ error = VOP_REFRESHLABEL(vp, cred, curthread);
+ switch (error) {
+ case EOPNOTSUPP:
+ /*
+ * If labels are not supported on this vnode, fall back to
+ * the label in the mount and propagate it to the vnode.
+ * There should probably be some sort of policy/flag/decision
+ * about doing this.
+ */
+ mac_update_vnode_from_mount(vp, vp->v_mount);
+ error = 0;
+ default:
+ return (error);
+ }
+}
+
+/*
+ * Helper function for file systems using the vop_std*_ea() calls. This
+ * function must be called after EA service is available for the vnode,
+ * but before it's hooked up to the namespace so that the node persists
+ * if there's a crash, or before it can be accessed. On successful
+ * commit of the label to disk (etc), do cache the label.
+ */
+int
+vop_stdcreatevnode_ea(struct vnode *dvp, struct vnode *tvp, struct ucred *cred)
+{
+ struct mac extmac;
+ int error;
+
+ ASSERT_VOP_LOCKED(tvp, "vop_stdcreatevnode_ea");
+ if ((dvp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) {
+ mac_update_vnode_from_mount(tvp, tvp->v_mount);
+ } else {
+ error = vn_refreshlabel(dvp, cred);
+ if (error)
+ return (error);
+
+ /*
+ * Stick the label in the vnode. Then try to write to
+ * disk. If we fail, return a failure to abort the
+ * create operation. Really, this failure shouldn't
+ * happen except in fairly unusual circumstances (out
+ * of disk, etc).
+ */
+ mac_create_vnode(cred, dvp, tvp);
+
+ error = mac_stdcreatevnode_ea(tvp);
+ if (error)
+ return (error);
+
+ /*
+ * XXX: Eventually this will go away and all policies will
+ * directly manage their extended attributes.
+ */
+ error = mac_externalize(&tvp->v_label, &extmac);
+ if (error)
+ return (error);
+
+ error = vn_extattr_set(tvp, IO_NODELOCKED,
+ FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME,
+ sizeof(extmac), (char *)&extmac, curthread);
+ if (error == 0)
+ tvp->v_vflag |= VV_CACHEDLABEL;
+ else {
+#if 0
+ /*
+ * In theory, we could have fall-back behavior here.
+ * It would probably be incorrect.
+ */
+#endif
+ return (error);
+ }
+ }
+
+ return (0);
+}
+
+void
+mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp)
+{
+ int error;
+
+ ASSERT_VOP_LOCKED(vp, "mac_execve_transition");
+
+ error = vn_refreshlabel(vp, old);
+ if (error) {
+ printf("mac_execve_transition: vn_refreshlabel returned %d\n",
+ error);
+ printf("mac_execve_transition: using old vnode label\n");
+ }
+
+ MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label);
+}
+
+int
+mac_execve_will_transition(struct ucred *old, struct vnode *vp)
+{
+ int error, result;
+
+ error = vn_refreshlabel(vp, old);
+ if (error)
+ return (error);
+
+ result = 0;
+ MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label);
+
+ return (result);
+}
+
int
mac_check_vnode_access(struct ucred *cred, struct vnode *vp, int flags)
{
To Unsubscribe: send mail to majordomo at trustedbsd.org
with "unsubscribe trustedbsd-cvs" in the body of the message
More information about the trustedbsd-cvs
mailing list