summaryrefslogtreecommitdiff
path: root/usr/src/cmd/zoneadmd
diff options
context:
space:
mode:
authorRic Aleshire <Ric.Aleshire@Sun.COM>2009-11-05 16:04:34 -0800
committerRic Aleshire <Ric.Aleshire@Sun.COM>2009-11-05 16:04:34 -0800
commit4201a95e0468170d576f82c3aa63afecf718497a (patch)
tree4c5de4303038a3c31e30020e4b0a51ece5332076 /usr/src/cmd/zoneadmd
parente8dc8350fed16771b8b46518216b74a2ff1a6c7b (diff)
downloadillumos-joyent-4201a95e0468170d576f82c3aa63afecf718497a.tar.gz
PSARC 2009/348 Security Labels for ZFS
6795907 Add label attribute to ZFS datasets --HG-- rename : usr/src/lib/libtsol/common/ltos.c => usr/src/common/tsol/ltos.c rename : usr/src/lib/libtsol/common/stol.c => usr/src/common/tsol/stol.c
Diffstat (limited to 'usr/src/cmd/zoneadmd')
-rw-r--r--usr/src/cmd/zoneadmd/vplat.c130
1 files changed, 130 insertions, 0 deletions
diff --git a/usr/src/cmd/zoneadmd/vplat.c b/usr/src/cmd/zoneadmd/vplat.c
index aa2d2fdc46..4911839ed6 100644
--- a/usr/src/cmd/zoneadmd/vplat.c
+++ b/usr/src/cmd/zoneadmd/vplat.c
@@ -3141,6 +3141,134 @@ validate_datasets(zlog_t *zlogp)
}
/*
+ * Return true if the path is its own zfs file system. We determine this
+ * by stat-ing the path to see if it is zfs and stat-ing the parent to see
+ * if it is a different fs.
+ */
+boolean_t
+is_zonepath_zfs(char *zonepath)
+{
+ int res;
+ char *path;
+ char *parent;
+ struct statvfs64 buf1, buf2;
+
+ if (statvfs64(zonepath, &buf1) != 0)
+ return (B_FALSE);
+
+ if (strcmp(buf1.f_basetype, "zfs") != 0)
+ return (B_FALSE);
+
+ if ((path = strdup(zonepath)) == NULL)
+ return (B_FALSE);
+
+ parent = dirname(path);
+ res = statvfs64(parent, &buf2);
+ free(path);
+
+ if (res != 0)
+ return (B_FALSE);
+
+ if (buf1.f_fsid == buf2.f_fsid)
+ return (B_FALSE);
+
+ return (B_TRUE);
+}
+
+/*
+ * Verify the MAC label in the root dataset for the zone.
+ * If the label exists, it must match the label configured for the zone.
+ * Otherwise if there's no label on the dataset, create one here.
+ */
+
+static int
+validate_rootds_label(zlog_t *zlogp, char *rootpath, m_label_t *zone_sl)
+{
+ int error = -1;
+ zfs_handle_t *zhp;
+ libzfs_handle_t *hdl;
+ m_label_t ds_sl;
+ char zonepath[MAXPATHLEN];
+ char ds_hexsl[MAXNAMELEN];
+
+ if (!is_system_labeled())
+ return (0);
+
+ if (zone_get_zonepath(zone_name, zonepath, sizeof (zonepath)) != Z_OK) {
+ zerror(zlogp, B_TRUE, "unable to determine zone path");
+ return (-1);
+ }
+
+ if (!is_zonepath_zfs(zonepath))
+ return (0);
+
+ if ((hdl = libzfs_init()) == NULL) {
+ zerror(zlogp, B_FALSE, "opening ZFS library");
+ return (-1);
+ }
+
+ if ((zhp = zfs_path_to_zhandle(hdl, rootpath,
+ ZFS_TYPE_FILESYSTEM)) == NULL) {
+ zerror(zlogp, B_FALSE, "cannot open ZFS dataset for path '%s'",
+ rootpath);
+ libzfs_fini(hdl);
+ return (-1);
+ }
+
+ /* Get the mlslabel property if it exists. */
+ if ((zfs_prop_get(zhp, ZFS_PROP_MLSLABEL, ds_hexsl, MAXNAMELEN,
+ NULL, NULL, 0, B_TRUE) != 0) ||
+ (strcmp(ds_hexsl, ZFS_MLSLABEL_DEFAULT) == 0)) {
+ char *str2 = NULL;
+
+ /*
+ * No label on the dataset (or default only); create one.
+ * (Only do this automatic labeling for the labeled brand.)
+ */
+ if (strcmp(brand_name, LABELED_BRAND_NAME) != 0) {
+ error = 0;
+ goto out;
+ }
+
+ error = l_to_str_internal(zone_sl, &str2);
+ if (error)
+ goto out;
+ if (str2 == NULL) {
+ error = -1;
+ goto out;
+ }
+ if ((error = zfs_prop_set(zhp,
+ zfs_prop_to_name(ZFS_PROP_MLSLABEL), str2)) != 0) {
+ zerror(zlogp, B_FALSE, "cannot set 'mlslabel' "
+ "property for root dataset at '%s'\n", rootpath);
+ }
+ free(str2);
+ goto out;
+ }
+
+ /* Convert the retrieved dataset label to binary form. */
+ error = hexstr_to_label(ds_hexsl, &ds_sl);
+ if (error) {
+ zerror(zlogp, B_FALSE, "invalid 'mlslabel' "
+ "property on root dataset at '%s'\n", rootpath);
+ goto out; /* exit with error */
+ }
+
+ /*
+ * Perform a MAC check by comparing the zone label with the
+ * dataset label.
+ */
+ error = (!blequal(zone_sl, &ds_sl));
+ if (error)
+ zerror(zlogp, B_FALSE, "Rootpath dataset has mismatched label");
+out:
+ zfs_close(zhp);
+ libzfs_fini(hdl);
+
+ return (error);
+}
+
+/*
* Mount lower level home directories into/from current zone
* Share exported directories specified in dfstab for zone
*/
@@ -4013,6 +4141,8 @@ vplat_create(zlog_t *zlogp, zone_mnt_t mount_cmd)
} else {
goto error;
}
+ if (validate_rootds_label(zlogp, rootpath, zlabel) != 0)
+ goto error;
}
kzone = zone_name;