+ if ( !(vcb->vcbAtrb & kHFSVolumeHardwareLockMask) ) // if the disk is not write protected
+ {
+ MarkVCBDirty( vcb ); // mark VCB dirty so it will be written
+ }
+
+ /*
+ * Distinguish 3 potential cases involving content protection:
+ * 1. mount point bit set; vcbAtrb does not support it. Fail.
+ * 2. mount point bit set; vcbattrb supports it. we're good.
+ * 3. mount point bit not set; vcbatrb supports it, turn bit on, then good.
+ */
+ if (vfs_flags(hfsmp->hfs_mp) & MNT_CPROTECT) {
+ /* Does the mount point support it ? */
+ if ((vcb->vcbAtrb & kHFSContentProtectionMask) == 0) {
+ /* Case 1 above */
+ retval = EINVAL;
+ goto ErrorExit;
+ }
+ }
+ else {
+ /* not requested in the mount point. Is it in FS? */
+ if (vcb->vcbAtrb & kHFSContentProtectionMask) {
+ /* Case 3 above */
+ vfs_setflags (hfsmp->hfs_mp, MNT_CPROTECT);
+ }
+ }
+
+ /* At this point, if the mount point flag is set, we can enable it. */
+ if (vfs_flags(hfsmp->hfs_mp) & MNT_CPROTECT) {
+ /* Cases 2+3 above */
+#if CONFIG_PROTECT
+ /* Get the EAs as needed. */
+ int cperr = 0;
+ uint16_t majorversion;
+ uint16_t minorversion;
+
+ struct cp_root_xattr *xattr = NULL;
+ MALLOC (xattr, struct cp_root_xattr*, sizeof(struct cp_root_xattr), M_TEMP, M_WAITOK);
+ if (xattr == NULL) {
+ retval = ENOMEM;
+ goto ErrorExit;
+ }
+ bzero (xattr, sizeof(struct cp_root_xattr));
+
+ /* go get the EA to get the version information */
+ cperr = cp_getrootxattr (hfsmp, xattr);
+ /*
+ * If there was no EA there, then write one out.
+ * Assuming EA is not present on the root means
+ * this is an erase install or a very old FS
+ */
+
+ if (cperr == 0) {
+ /* Have to run a valid CP version. */
+ if ((xattr->major_version < CP_PREV_MAJOR_VERS) || (xattr->major_version > CP_NEW_MAJOR_VERS)) {
+ cperr = EINVAL;
+ }
+ }
+ else if (cperr == ENOATTR) {
+ printf("No root EA set, creating new EA with new version: %d\n", CP_NEW_MAJOR_VERS);
+ bzero(xattr, sizeof(struct cp_root_xattr));
+ xattr->major_version = CP_NEW_MAJOR_VERS;
+ xattr->minor_version = CP_MINOR_VERS;
+ xattr->flags = 0;
+ cperr = cp_setrootxattr (hfsmp, xattr);
+ }
+ majorversion = xattr->major_version;
+ minorversion = xattr->minor_version;
+ if (xattr) {
+ FREE(xattr, M_TEMP);
+ }
+
+ /* Recheck for good status */
+ if (cperr == 0) {
+ /* If we got here, then the CP version is valid. Set it in the mount point */
+ hfsmp->hfs_running_cp_major_vers = majorversion;
+ printf("Running with CP root xattr: %d.%d\n", majorversion, minorversion);
+
+ /*
+ * Acquire the boot-arg for the AKS default key.
+ * Ensure that the boot-arg's value is valid for FILES (not directories),
+ * since only files are actually protected for now.
+ */
+ PE_parse_boot_argn("aks_default_class", &hfsmp->default_cp_class, sizeof(hfsmp->default_cp_class));
+ if (cp_is_valid_class(0, hfsmp->default_cp_class) == 0) {
+ hfsmp->default_cp_class = PROTECTION_CLASS_D;
+ }
+ }
+ else {
+ retval = EPERM;
+ goto ErrorExit;
+ }
+#else
+ /* If CONFIG_PROTECT not built, ignore CP */
+ vfs_clearflags(hfsmp->hfs_mp, MNT_CPROTECT);
+#endif
+ }
+