Skip to content

Commit

Permalink
Add full SELinux support
Browse files Browse the repository at this point in the history
Four new dataset properties have been added to support SELinux.  They
are 'context', 'fscontext', 'defcontext' and 'rootcontext' which map
directly to the context options described in mount(8).  When one of
these properties is set to something other than 'none'.  That string
will be passed verbatim as a mount option for the given context when
the filesystem is mounted.

For example, if you wanted the rootcontext for a filesystem to be set
to 'system_u:object_r:fs_t' you would set the property as follows:

  $ zfs set rootcontext="system_u:object_r:fs_t" storage-pool/media

This will ensure the filesystem is automatically mounted with that
rootcontext.  It is equivalent to manually specifying the rootcontext
with the -o option like this:

  $ zfs mount -o rootcontext=system_u:object_r:fs_t storage-pool/media

By default all four contexts are set to 'none'.  Further information
on SELinux contexts is detailed in mount(8) and selinux(8) man pages.

Signed-off-by: Matthew Thode <prometheanfire@gentoo.org>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Richard Yao <ryao@gentoo.org>
Closes #1504
  • Loading branch information
prometheanfire authored and behlendorf committed Dec 19, 2013
1 parent d1d7e26 commit 11b9ec2
Show file tree
Hide file tree
Showing 10 changed files with 134 additions and 82 deletions.
2 changes: 0 additions & 2 deletions cmd/mount_zfs/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,3 @@ mount_zfs_LDADD = \
$(top_builddir)/lib/libzpool/libzpool.la \
$(top_builddir)/lib/libzfs/libzfs.la \
$(top_builddir)/lib/libzfs_core/libzfs_core.la

mount_zfs_LDADD += $(LIBSELINUX)
88 changes: 58 additions & 30 deletions cmd/mount_zfs/mount_zfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,6 @@
#include <sys/stat.h>
#include <libzfs.h>
#include <locale.h>
#ifdef HAVE_LIBSELINUX
#include <selinux/selinux.h>
#endif /* HAVE_LIBSELINUX */

libzfs_handle_t *g_zfs;

Expand Down Expand Up @@ -77,11 +74,10 @@ static const option_map_t option_map[] = {
#ifdef MS_STRICTATIME
{ MNTOPT_DFRATIME, MS_STRICTATIME, ZS_COMMENT },
#endif
{ MNTOPT_CONTEXT, MS_COMMENT, ZS_NOCONTEXT },
{ MNTOPT_NOCONTEXT, MS_COMMENT, ZS_NOCONTEXT },
{ MNTOPT_FSCONTEXT, MS_COMMENT, ZS_NOCONTEXT },
{ MNTOPT_DEFCONTEXT, MS_COMMENT, ZS_NOCONTEXT },
{ MNTOPT_ROOTCONTEXT, MS_COMMENT, ZS_NOCONTEXT },
{ MNTOPT_CONTEXT, MS_COMMENT, ZS_COMMENT },
{ MNTOPT_FSCONTEXT, MS_COMMENT, ZS_COMMENT },
{ MNTOPT_DEFCONTEXT, MS_COMMENT, ZS_COMMENT },
{ MNTOPT_ROOTCONTEXT, MS_COMMENT, ZS_COMMENT },
#ifdef MS_I_VERSION
{ MNTOPT_IVERSION, MS_I_VERSION, ZS_COMMENT },
#endif
Expand Down Expand Up @@ -338,11 +334,35 @@ mtab_update(char *dataset, char *mntpoint, char *type, char *mntopts)
return (MOUNT_SUCCESS);
}

static void
__zfs_selinux_setcontext(const char *name, const char *context, char *mntopts,
char *mtabopt)
{
char tmp[MNT_LINE_MAX];

snprintf(tmp, MNT_LINE_MAX, ",%s=\"%s\"", name, context);
strlcat(mntopts, tmp, MNT_LINE_MAX);
strlcat(mtabopt, tmp, MNT_LINE_MAX);
}

static void
zfs_selinux_setcontext(zfs_handle_t *zhp, zfs_prop_t zpt, const char *name,
char *mntopts, char *mtabopt)
{
char context[ZFS_MAXPROPLEN];

if (zfs_prop_get(zhp, zpt, context, sizeof (context),
NULL, NULL, 0, B_FALSE) == 0) {
if (strcmp(context, "none") != 0)
__zfs_selinux_setcontext(name, context, mntopts, mtabopt);
}
}

int
main(int argc, char **argv)
{
zfs_handle_t *zhp;
char legacy[ZFS_MAXPROPLEN];
char prop[ZFS_MAXPROPLEN];
char mntopts[MNT_LINE_MAX] = { '\0' };
char badopt[MNT_LINE_MAX] = { '\0' };
char mtabopt[MNT_LINE_MAX] = { '\0' };
Expand Down Expand Up @@ -437,22 +457,6 @@ main(int argc, char **argv)
}
}

#ifdef HAVE_LIBSELINUX
/*
* Automatically add the default zfs context when selinux is enabled
* and the caller has not specified their own context. This must be
* done until zfs is added to the default selinux policy configuration
* as a known filesystem type which supports xattrs.
*/
if (is_selinux_enabled() && !(zfsflags & ZS_NOCONTEXT)) {
(void) strlcat(mntopts, ",context=\"system_u:"
"object_r:file_t:s0\"", sizeof (mntopts));
(void) strlcat(mtabopt, ",context=\"system_u:"
"object_r:file_t:s0\"", sizeof (mtabopt));
}
#endif /* HAVE_LIBSELINUX */


if (verbose)
(void) fprintf(stdout, gettext("mount.zfs:\n"
" dataset: \"%s\"\n mountpoint: \"%s\"\n"
Expand Down Expand Up @@ -480,12 +484,36 @@ main(int argc, char **argv)
return (MOUNT_USAGE);
}

/*
* Checks to see if the ZFS_PROP_SELINUX_CONTEXT exists
* if it does, create a tmp variable in case it's needed
* checks to see if the selinux context is set to the default
* if it is, allow the setting of the other context properties
* this is needed because the 'context' property overrides others
* if it is not the default, set the 'context' property
*/
if (zfs_prop_get(zhp, ZFS_PROP_SELINUX_CONTEXT, prop, sizeof (prop),
NULL, NULL, 0, B_FALSE) == 0) {
if (strcmp(prop, "none") == 0) {
zfs_selinux_setcontext(zhp, ZFS_PROP_SELINUX_FSCONTEXT,
MNTOPT_FSCONTEXT, mntopts, mtabopt);
zfs_selinux_setcontext(zhp, ZFS_PROP_SELINUX_DEFCONTEXT,
MNTOPT_DEFCONTEXT, mntopts, mtabopt);
zfs_selinux_setcontext(zhp,
ZFS_PROP_SELINUX_ROOTCONTEXT, MNTOPT_ROOTCONTEXT,
mntopts, mtabopt);
} else {
__zfs_selinux_setcontext(MNTOPT_CONTEXT,
prop, mntopts, mtabopt);
}
}

/* treat all snapshots as legacy mount points */
if (zfs_get_type(zhp) == ZFS_TYPE_SNAPSHOT)
(void) strlcpy(legacy, ZFS_MOUNTPOINT_LEGACY, ZFS_MAXPROPLEN);
(void) strlcpy(prop, ZFS_MOUNTPOINT_LEGACY, ZFS_MAXPROPLEN);
else
(void) zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, legacy,
sizeof (legacy), NULL, NULL, 0, B_FALSE);
(void) zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, prop,
sizeof (prop), NULL, NULL, 0, B_FALSE);

zfs_close(zhp);
libzfs_fini(g_zfs);
Expand All @@ -501,7 +529,7 @@ main(int argc, char **argv)
* using zfs as your root file system both rc.sysinit/umountroot and
* systemd depend on 'mount -o remount <mountpoint>' to work.
*/
if (zfsutil && (strcmp(legacy, ZFS_MOUNTPOINT_LEGACY) == 0)) {
if (zfsutil && (strcmp(prop, ZFS_MOUNTPOINT_LEGACY) == 0)) {
(void) fprintf(stderr, gettext(
"filesystem '%s' cannot be mounted using 'zfs mount'.\n"
"Use 'zfs set mountpoint=%s' or 'mount -t zfs %s %s'.\n"
Expand All @@ -511,7 +539,7 @@ main(int argc, char **argv)
}

if (!zfsutil && !(remount || fake) &&
strcmp(legacy, ZFS_MOUNTPOINT_LEGACY)) {
strcmp(prop, ZFS_MOUNTPOINT_LEGACY)) {
(void) fprintf(stderr, gettext(
"filesystem '%s' cannot be mounted using 'mount'.\n"
"Use 'zfs set mountpoint=%s' or 'zfs mount %s'.\n"
Expand Down
36 changes: 0 additions & 36 deletions config/user-selinux.m4

This file was deleted.

1 change: 0 additions & 1 deletion config/user.m4
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,5 @@ AC_DEFUN([ZFS_AC_CONFIG_USER], [
ZFS_AC_CONFIG_USER_ZLIB
ZFS_AC_CONFIG_USER_LIBUUID
ZFS_AC_CONFIG_USER_LIBBLKID
ZFS_AC_CONFIG_USER_LIBSELINUX
ZFS_AC_CONFIG_USER_FRAME_LARGER_THAN
])
4 changes: 4 additions & 0 deletions include/sys/fs/zfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,10 @@ typedef enum {
ZFS_PROP_INCONSISTENT, /* not exposed to the user */
ZFS_PROP_SNAPDEV,
ZFS_PROP_ACLTYPE,
ZFS_PROP_SELINUX_CONTEXT,
ZFS_PROP_SELINUX_FSCONTEXT,
ZFS_PROP_SELINUX_DEFCONTEXT,
ZFS_PROP_SELINUX_ROOTCONTEXT,
ZFS_NUM_PROPS
} zfs_prop_t;

Expand Down
2 changes: 0 additions & 2 deletions lib/libspl/include/sys/mntent.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@
#define MNTOPT_AUTO "auto" /* automount */
#define MNTOPT_NOAUTO "noauto" /* do not automount */
#define MNTOPT_CONTEXT "context" /* selinux context */
#define MNTOPT_NOCONTEXT "nocontext" /* No selinux context (zfs-only) */
#define MNTOPT_FSCONTEXT "fscontext" /* selinux fscontext */
#define MNTOPT_DEFCONTEXT "defcontext" /* selinux defcontext */
#define MNTOPT_ROOTCONTEXT "rootcontext" /* selinux rootcontext */
Expand Down Expand Up @@ -99,6 +98,5 @@

#define ZS_COMMENT 0x00000000 /* comment */
#define ZS_ZFSUTIL 0x00000001 /* caller is zfs(8) */
#define ZS_NOCONTEXT 0x00000002 /* do not add selinux context */

#endif /* _SYS_MNTENT_H */
13 changes: 13 additions & 0 deletions man/man8/mount.zfs.8
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,19 @@ Increase verbosity.
.BI "\-h"
Print the usage message.
.TP
.BI "\-o context"
This flag sets the SELinux context for all files in the filesytem
under that mountpoint.
.TP
.BI "\-o fscontext"
This flag sets the SELinux context for the filesytem being mounted.
.TP
.BI "\-o defcontext"
This flag sets the SELinux context for unlabled files.
.TP
.BI "\-o rootcontext"
This flag sets the SELinux context for the root inode of the filesystem.
.TP
.BI "\-o legacy"
This private flag indicates that the
.I dataset
Expand Down
46 changes: 46 additions & 0 deletions man/man8/zfs.8
Original file line number Diff line number Diff line change
Expand Up @@ -1298,6 +1298,52 @@ Indicates whether the file system should reject file names that include characte
.sp
.LP
The \fBcasesensitivity\fR, \fBnormalization\fR, and \fButf8only\fR properties are also new permissions that can be assigned to non-privileged users by using the \fBZFS\fR delegated administration feature.
.RE

.sp
.ne 2
.mk
.na
\fB\fBcontext\fR=\fBSELinux_User:SElinux_Role:Selinux_Type:Sensitivity_Level\fR\fR
.ad
.sp .6
.RS 4n
This flag sets the SELinux context for all files in the filesytem under the mountpoint for that filesystem. See \fBselinux\fR(8) for more information.
.RE

.sp
.ne 2
.mk
.na
\fB\fBfscontext\fR=\fBSELinux_User:SElinux_Role:Selinux_Type:Sensitivity_Level\fR\fR
.ad
.sp .6
.RS 4n
This flag sets the SELinux context for the filesytem being mounted. See \fBselinux\fR(8) for more information.
.RE

.sp
.ne 2
.mk
.na
\fB\fBdefntext\fR=\fBSELinux_User:SElinux_Role:Selinux_Type:Sensitivity_Level\fR\fR
.ad
.sp .6
.RS 4n
This flag sets the SELinux context for unlabeled files. See \fBselinux\fR(8) for more information.
.RE

.sp
.ne 2
.mk
.na
\fB\fBrootcontext\fR=\fBSELinux_User:SElinux_Role:Selinux_Type:Sensitivity_Level\fR\fR
.ad
.sp .6
.RS 4n
This flag sets the SELinux context for the root inode of the filesystem. See \fBselinux\fR(8) for more information.
.RE

.SS "Temporary Mount Point Properties"
.LP
When a file system is mounted, either through \fBmount\fR(8) for legacy mounts or the \fBzfs mount\fR command for normal file systems, its mount options are set according to its properties. The correlation between properties and mount options is as follows:
Expand Down
12 changes: 12 additions & 0 deletions module/zcommon/zfs_prop.c
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,18 @@ zfs_prop_init(void)
zprop_register_string(ZFS_PROP_MLSLABEL, "mlslabel",
ZFS_MLSLABEL_DEFAULT, PROP_INHERIT, ZFS_TYPE_DATASET,
"<sensitivity label>", "MLSLABEL");
zprop_register_string(ZFS_PROP_SELINUX_CONTEXT, "context",
"none", PROP_DEFAULT, ZFS_TYPE_DATASET, "<selinux context>",
"CONTEXT");
zprop_register_string(ZFS_PROP_SELINUX_FSCONTEXT, "fscontext",
"none", PROP_DEFAULT, ZFS_TYPE_DATASET, "<selinux fscontext>",
"FSCONTEXT");
zprop_register_string(ZFS_PROP_SELINUX_DEFCONTEXT, "defcontext",
"none", PROP_DEFAULT, ZFS_TYPE_DATASET, "<selinux defcontext>",
"DEFCONTEXT");
zprop_register_string(ZFS_PROP_SELINUX_ROOTCONTEXT, "rootcontext",
"none", PROP_DEFAULT, ZFS_TYPE_DATASET, "<selinux rootcontext>",
"ROOTCONTEXT");

/* readonly number properties */
zprop_register_number(ZFS_PROP_USED, "used", 0, PROP_READONLY,
Expand Down
12 changes: 1 addition & 11 deletions rpm/generic/zfs.spec.in
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@

%bcond_with debug
%bcond_with blkid
%bcond_with selinux


Name: @PACKAGE@
Expand Down Expand Up @@ -38,9 +37,6 @@ BuildRequires: libuuid-devel
%if %{with blkid}
BuildRequires: libblkid-devel
%endif
%if %{with selinux}
BuildRequires: libselinux-devel
%endif
%endif

%description
Expand Down Expand Up @@ -89,11 +85,6 @@ image which is ZFS aware.
%else
%define blkid --without-blkid
%endif
%if %{with selinux}
%define selinux --with-selinux
%else
%define selinux --without-selinux
%endif

%setup -q

Expand All @@ -104,8 +95,7 @@ image which is ZFS aware.
--with-dracutdir=%{_dracutdir} \
--disable-static \
%{debug} \
%{blkid} \
%{selinux}
%{blkid}
make %{?_smp_mflags}

%install
Expand Down

0 comments on commit 11b9ec2

Please sign in to comment.