coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] ls: with -Z, show SMACK context for each file


From: Jarkko Sakkinen
Subject: [PATCH] ls: with -Z, show SMACK context for each file
Date: Mon, 3 Jun 2013 12:19:15 +0300

Enable showing of file SMACK labels with -Z command-line switch.

* src/ls.c (gobble_file): Output the smack context if available.
* src/ls.c: New function getsmackcon_cache() for grabbing SMACK label.
---
 src/local.mk |   1 +
 src/ls.c     | 113 ++++++++++++++++++++++++++++++++++++++++++++++-------------
 2 files changed, 89 insertions(+), 25 deletions(-)

diff --git a/src/local.mk b/src/local.mk
index efb0038..626d580 100644
--- a/src/local.mk
+++ b/src/local.mk
@@ -230,6 +230,7 @@ src_ginstall_LDADD += $(LIB_SELINUX)
 src_id_LDADD += $(LIB_SELINUX)
 src_id_LDADD += $(LIB_SMACK)
 src_ls_LDADD += $(LIB_SELINUX)
+src_ls_LDADD += $(LIB_SMACK)
 src_mkdir_LDADD += $(LIB_SELINUX)
 src_mkfifo_LDADD += $(LIB_SELINUX)
 src_mknod_LDADD += $(LIB_SELINUX)
diff --git a/src/ls.c b/src/ls.c
index 72aee99..7149148 100644
--- a/src/ls.c
+++ b/src/ls.c
@@ -115,6 +115,11 @@
 # include <sys/capability.h>
 #endif
 
+#ifdef HAVE_SMACK
+# include <sys/smack.h>
+# include <attr/xattr.h>
+#endif
+
 #define PROGRAM_NAME (ls_mode == LS_LS ? "ls" \
                       : (ls_mode == LS_MULTI_COL \
                          ? "dir" : "vdir"))
@@ -350,7 +355,16 @@ static struct pending *pending_dirs;
 
 static struct timespec current_time;
 
-static bool print_scontext;
+enum scontext_type
+  {
+  no_context = 0,
+  selinux_context,
+#ifdef HAVE_SMACK
+  smack_context,
+#endif
+  };
+
+static enum scontext_type print_scontext;
 static char UNKNOWN_SECURITY_CONTEXT[] = "?";
 
 /* Whether any of the files has an ACL.  This affects the width of the
@@ -1371,7 +1385,7 @@ main (int argc, char **argv)
 
   format_needs_stat = sort_type == sort_time || sort_type == sort_size
     || format == long_format
-    || print_scontext
+    || print_scontext != no_context
     || print_block_size;
   format_needs_type = (! format_needs_stat
                        && (recursive
@@ -1573,7 +1587,7 @@ decode_switches (int argc, char **argv)
   ignore_mode = IGNORE_DEFAULT;
   ignore_patterns = NULL;
   hide_patterns = NULL;
-  print_scontext = false;
+  print_scontext = no_context;
 
   /* FIXME: put this in a function.  */
   {
@@ -1949,7 +1963,11 @@ decode_switches (int argc, char **argv)
           break;
 
         case 'Z':
-          print_scontext = true;
+          print_scontext = selinux_context;
+#ifdef HAVE_SMACK
+          if (smack_smackfs_path ())
+            print_scontext = smack_context;
+#endif
           break;
 
         case_GETOPT_HELP_CHAR;
@@ -2820,6 +2838,26 @@ getfilecon_cache (char const *file, struct fileinfo *f, 
bool deref)
   return r;
 }
 
+static int
+getsmackcon_cache (char const *file, struct fileinfo *f, bool deref)
+{
+  /* st_dev of the most recently processed device for which we've
+     found that [l]getsmackcon fails indicating lack of support.  */
+  static dev_t unsupported_device;
+
+  if (f->stat.st_dev == unsupported_device)
+    {
+      errno = ENOTSUP;
+      return -1;
+    }
+  int r = smack_new_label_from_path (file, "security.SMACK64", deref,
+                                     &f->scontext);
+  if (r < 0 && errno_unsupported (errno))
+    unsupported_device = f->stat.st_dev;
+  return r;
+}
+
+
 /* Cache file_has_acl failure, when it's trivial to do.
    Like file_has_acl, but when F's st_dev says it's on a file
    system lacking ACL support, return 0 with ENOTSUP immediately.  */
@@ -3003,26 +3041,51 @@ gobble_file (char const *name, enum filetype type, 
ino_t inode,
           && print_with_color && is_colored (C_CAP))
         f->has_capability = has_capability_cache (absolute_name, f);
 
-      if (format == long_format || print_scontext)
+      if (format == long_format || print_scontext != no_context)
         {
-          bool have_selinux = false;
+          bool have_context = false;
           bool have_acl = false;
-          int attr_len = getfilecon_cache (absolute_name, f, do_deref);
-          err = (attr_len < 0);
 
-          if (err == 0)
-            have_selinux = ! STREQ ("unlabeled", f->scontext);
+          if (print_scontext == selinux_context)
+            {
+              int attr_len = getfilecon_cache (absolute_name, f, do_deref);
+              err = (attr_len < 0);
+
+              if (err == 0)
+                have_context = ! STREQ ("unlabeled", f->scontext);
+              else
+                {
+                f->scontext = UNKNOWN_SECURITY_CONTEXT;
+
+                /* When requesting security context information, don't make
+                   ls fail just because the file (even a command line argument)
+                   isn't on the right type of file system.  I.e., a getfilecon
+                   failure isn't in the same class as a stat failure.  */
+                if (errno == ENOTSUP || errno == EOPNOTSUPP || errno == 
ENODATA)
+                  err = 0;
+                }
+            }
+#ifdef HAVE_SMACK
           else
             {
-              f->scontext = UNKNOWN_SECURITY_CONTEXT;
-
-              /* When requesting security context information, don't make
-                 ls fail just because the file (even a command line argument)
-                 isn't on the right type of file system.  I.e., a getfilecon
-                 failure isn't in the same class as a stat failure.  */
-              if (errno == ENOTSUP || errno == EOPNOTSUPP || errno == ENODATA)
-                err = 0;
+              int attr_len = getsmackcon_cache (absolute_name, f, do_deref);
+              err = (attr_len < 0);
+
+              if (err == 0)
+                have_context = ! STREQ ("_", f->scontext);
+              else
+                {
+                f->scontext = UNKNOWN_SECURITY_CONTEXT;
+
+                /* When requesting security context information, don't make
+                   ls fail just because the file (even a command line argument)
+                   isn't on the right type of file system.  I.e., a getsmackcon
+                   failure isn't in the same class as a stat failure.  */
+                if (errno == ENOTSUP || errno == EOPNOTSUPP || errno == 
ENODATA)
+                  err = 0;
+                }
             }
+#endif
 
           if (err == 0 && format == long_format)
             {
@@ -3031,9 +3094,9 @@ gobble_file (char const *name, enum filetype type, ino_t 
inode,
               have_acl = (0 < n);
             }
 
-          f->acl_type = (!have_selinux && !have_acl
+          f->acl_type = (!have_context && !have_acl
                          ? ACL_T_NONE
-                         : (have_selinux && !have_acl
+                         : (have_context && !have_acl
                             ? ACL_T_SELINUX_ONLY
                             : ACL_T_YES));
           any_has_acl |= f->acl_type != ACL_T_NONE;
@@ -3119,7 +3182,7 @@ gobble_file (char const *name, enum filetype type, ino_t 
inode,
             }
         }
 
-      if (print_scontext)
+      if (print_scontext != no_context)
         {
           int len = strlen (f->scontext);
           if (scontext_width < len)
@@ -3854,7 +3917,7 @@ print_long_format (const struct fileinfo *f)
 
   DIRED_INDENT ();
 
-  if (print_owner || print_group || print_author || print_scontext)
+  if (print_owner || print_group || print_author || print_scontext != 
no_context)
     {
       DIRED_FPUTS (buf, stdout, p - buf);
 
@@ -3867,7 +3930,7 @@ print_long_format (const struct fileinfo *f)
       if (print_author)
         format_user (f->stat.st_author, author_width, f->stat_ok);
 
-      if (print_scontext)
+      if (print_scontext != no_context)
         format_user_or_group (f->scontext, 0, scontext_width);
 
       p = buf;
@@ -4215,7 +4278,7 @@ print_file_name_and_frills (const struct fileinfo *f, 
size_t start_col)
             : human_readable (ST_NBLOCKS (f->stat), buf, human_output_opts,
                               ST_NBLOCKSIZE, output_block_size));
 
-  if (print_scontext)
+  if (print_scontext != no_context)
     printf ("%*s ", format == with_commas ? 0 : scontext_width, f->scontext);
 
   size_t width = print_name_with_quoting (f, false, NULL, start_col);
@@ -4425,7 +4488,7 @@ length_of_file_name_and_frills (const struct fileinfo *f)
                                             output_block_size))
                 : block_size_width);
 
-  if (print_scontext)
+  if (print_scontext != no_context)
     len += 1 + (format == with_commas ? strlen (f->scontext) : scontext_width);
 
   quote_name (NULL, f->name, filename_quoting_options, &name_width);
-- 
1.8.1.2




reply via email to

[Prev in Thread] Current Thread [Next in Thread]