]> err.no Git - util-linux/commitdiff
mount: add support for context, fscontext and defcontext selinux mount options
authorKarel Zak <kzak@redhat.com>
Fri, 4 May 2007 09:05:51 +0000 (11:05 +0200)
committerKarel Zak <kzak@redhat.com>
Fri, 4 May 2007 09:05:51 +0000 (11:05 +0200)
Signed-off-by: Karel Zak <kzak@redhat.com>
mount/Makefile.am
mount/mount.8
mount/mount.c

index 6f0d403d9ad764532d8c18b37b4b31a61b058787..bd2ff1c20b17765bbfbbf53eaf450689ddb59197 100644 (file)
@@ -62,6 +62,9 @@ swapargs.h:
 clean-local:
        rm -f swapargs.h
 
+if HAVE_SELINUX
+mount_LDADD += -lselinux
+endif
 
 install-exec-hook:
        chmod 4755 $(DESTDIR)$(bindir)/mount
index 4692a42b3487b8e0db6dc0b7d17cfd214e8aefc8..8ed5a11b77985c8da2dcac4602a67f8785a95070 100644 (file)
@@ -703,6 +703,50 @@ This option implies the options
 .BR noexec ", " nosuid ", and " nodev
 (unless overridden by subsequent options, as in the option line
 .BR users,exec,dev,suid ).
+.TP
+\fBcontext=\fP\fIcontext\fP, \fBfscontext=\fP\fIcontext\fP and \fBdefcontext=\fP\fIcontext\fP
+The
+.BR context=
+option is useful when mounting filesystems that do not support
+extended attributes, such as a floppy or hard disk formatted with VFAT, or
+systems that are not normally running under SELinux, such as an ext3 formatted
+disk from a non-SELinux workstation. You can also use
+.BR context=
+on filesystems you do not trust, such as a floppy. It also helps in compatibility with
+xattr-supporting filesystems on earlier 2.4.<x> kernel versions. Even where
+xattrs are supported, you can save time not having to label every file by
+assigning the entire disk one security context.
+
+A commonly used option for removable media is
+.BR context=system_u:object_r:removable_t .
+
+Two other options are
+.BR fscontext=
+and
+.BR defcontext= ,
+both of which are mutually exclusive of the context option. This means you
+can use fscontext and defcontext with each other, but neither can be used with
+context.
+
+The
+.BR fscontext=
+option works for all filesystems, regardless of their xattr
+support. The fscontext option sets the overarching filesystem label to a
+specific security context. This filesystem label is separate from the
+individual labels on the files. It represents the entire filesystem for
+certain kinds of permission checks, such as during mount or file creation.
+Individual file labels are still obtained from the xattrs on the files
+themselves. The context option actually sets the aggregate context that
+fscontext provides, in addition to supplying the same label for individual
+files.
+
+You can set the default security context for unlabeled files using
+.BR defcontext=
+option. This overrides the value set for unlabeled files in the policy and requires a
+file system that supports xattr labeling.
+
+For more details see
+.BR selinux (8)
 .RE
 .TP
 .B \-\-bind
index 495eaed67ad0644163110422c8c9c054c93a4ab8..be2e4bfc66663be1481e3d9dc65c2274ba7f20ed 100644 (file)
 #include <mntent.h>
 #include <paths.h>
 
+#ifdef HAVE_LIBSELINUX
+#include <selinux/selinux.h>
+#include <selinux/context.h>
+#endif
+
 #include "mount_blkid.h"
 #include "mount_constants.h"
 #include "sundries.h"
@@ -298,13 +303,71 @@ append_numopt(char *s, const char *opt, long num)
        return append_opt(s, opt, buf);
 }
 
+#ifdef HAVE_LIBSELINUX
+/* strip quotes from a "string"
+ * Warning: This function modify the "str" argument.
+ */
+static char *
+strip_quotes(char *str)
+{
+       char *end = NULL;
+
+       if (*str != '"')
+               return str;
+
+       end = strrchr(str, '"');
+       if (end == NULL || end == str)
+               die (EX_USAGE, _("mount: improperly quoted option string '%s'"), str);
+
+       *end = '\0';
+       return str+1;
+}
+
+/* translates SELinux context from human to raw format and
+ * appends it to the mount extra options.
+ *
+ * returns -1 on error and 0 on success
+ */
+static int
+append_context(const char *optname, char *optdata, char **extra_opts)
+{
+       security_context_t raw = NULL;
+       char *data = NULL;
+
+       if (!is_selinux_enabled())
+               /* ignore the option if we running without selinux */
+               return 0;
+
+       if (optdata==NULL || *optdata=='\0' || optname==NULL)
+               return -1;
+
+       /* TODO: use strip_quotes() for all mount options? */
+       data = *optdata =='"' ? strip_quotes(optdata) : optdata;
+
+       if (selinux_trans_to_raw_context(
+                       (security_context_t) data, &raw)==-1 ||
+                       raw==NULL)
+               return -1;
+
+       if (verbose)
+               printf(_("mount: translated %s '%s' to '%s'\n"),
+                               optname, data, (char *) raw);
+
+       *extra_opts = append_opt(*extra_opts, optname, NULL);
+       *extra_opts = xstrconcat4(*extra_opts, "\"", (char *) raw, "\"");
+
+       freecon(raw);
+       return 0;
+}
+#endif
+
 /*
  * Look for OPT in opt_map table and return mask value.
  * If OPT isn't found, tack it onto extra_opts (which is non-NULL).
  * For the options uid= and gid= replace user or group name by its value.
  */
 static inline void
-parse_opt(const char *opt, int *mask, char **extra_opts) {
+parse_opt(char *opt, int *mask, char **extra_opts) {
        const struct opt_map *om;
 
        for (om = opt_map; om->opt != NULL; om++)
@@ -348,6 +411,20 @@ parse_opt(const char *opt, int *mask, char **extra_opts) {
                }
        }
 
+#ifdef HAVE_LIBSELINUX
+       if (strncmp(opt, "context=", 8) == 0 && *(opt+8)) {
+               if (append_context("context=", opt+8, extra_opts) == 0)
+                       return;
+       }
+       if (strncmp(opt, "fscontext=", 10) == 0 && *(opt+10)) {
+               if (append_context("fscontext=", opt+10, extra_opts) == 0)
+                       return;
+       }
+       if (strncmp(opt, "defcontext=", 11) == 0 && *(opt+11)) {
+               if (append_context("defcontext=", opt+11, extra_opts) == 0)
+                       return;
+       }
+#endif
        *extra_opts = append_opt(*extra_opts, opt, NULL);
 }
 
@@ -362,12 +439,25 @@ parse_opts (const char *options, int *flags, char **extra_opts) {
 
        if (options != NULL) {
                char *opts = xstrdup(options);
-               char *opt;
-
-               for (opt = strtok(opts, ","); opt; opt = strtok(NULL, ","))
-                       if (!parse_string_opt(opt))
-                               parse_opt(opt, flags, extra_opts);
-
+               int open_quote = 0;
+               char *opt, *p;
+
+               for (p=opts, opt=NULL; p && *p; p++) {
+                       if (!opt)
+                               opt = p;                /* begin of the option item */
+                       if (*p == '"')
+                               open_quote ^= 1;        /* reverse the status */
+                       if (open_quote)
+                               continue;               /* still in quoted block */
+                       if (*p == ',')
+                               *p = '\0';              /* terminate the option item */
+                       /* end of option item or last item */
+                       if (*p == '\0' || *(p+1) == '\0') {
+                               if (!parse_string_opt(opt))
+                                       parse_opt(opt, flags, extra_opts);
+                               opt = NULL;
+                       }
+               }
                free(opts);
        }
 
@@ -490,8 +580,8 @@ do_mount_syscall (struct mountargs *args) {
        if ((flags & MS_MGC_MSK) == 0)
                flags |= MS_MGC_VAL;
 
-       mnt_debug(1, "mount(2) syscall: source=\"%s\" target=\"%s\" "
-                       "filesystemtype=\"%s\" mountflags=%lu data=\"%s\"",
+       mnt_debug(1, "mount(2) syscall: source: \"%s\", target: \"%s\", "
+                       "filesystemtype: \"%s\", mountflags: %lu, data: %s",
                        args->spec, args->node, args->type, flags, (char *) args->data);
 
        ret = mount (args->spec, args->node, args->type, flags, args->data);