Add fsm and rpmfi machinery for file capabilities
authorPanu Matilainen <pmatilai@redhat.com>
Wed, 29 Oct 2008 09:49:38 +0000 (11:49 +0200)
committerPanu Matilainen <pmatilai@redhat.com>
Wed, 29 Oct 2008 09:49:38 +0000 (11:49 +0200)
- new rpmfiFCaps() API to retrieve the info from rpmfi set
- fsm internals quite similar to selinux handling
- plenty of #ifdef's, another possibility would be adding cap_foo dummies to
  system.h like for selinux

lib/cpio.c
lib/cpio.h
lib/fsm.c
lib/fsm.h
lib/rpmfi.c
lib/rpmfi.h
lib/rpmfi_internal.h
system.h

index f45644b..d4265d3 100644 (file)
@@ -209,6 +209,7 @@ const char * cpioStrerror(int rc)
     case CPIOERR_READ_FAILED:  s = "read";     break;
     case CPIOERR_COPY_FAILED:  s = "copy";     break;
     case CPIOERR_LSETFCON_FAILED: s = "lsetfilecon";   break;
+    case CPIOERR_SETCAP_FAILED: s = "cap_set_file";    break;
 
     case CPIOERR_HDR_SIZE:     s = _("Header size too big");   break;
     case CPIOERR_UNKNOWN_FILETYPE: s = _("Unknown file type"); break;
index 5259b03..fc6e92c 100644 (file)
@@ -52,7 +52,8 @@ enum cpioErrorReturns {
        CPIOERR_INTERNAL        = (28                   ),
        CPIOERR_UNMAPPED_FILE   = (29                   ),
        CPIOERR_ENOENT          = (30                   ),
-       CPIOERR_ENOTEMPTY       = (31                   )
+       CPIOERR_ENOTEMPTY       = (31                   ),
+       CPIOERR_SETCAP_FAILED   = (32   | CPIOERR_CHECK_ERRNO),
 };
 
 /*
index 8175f82..ecfb1f7 100644 (file)
--- a/lib/fsm.c
+++ b/lib/fsm.c
@@ -589,6 +589,22 @@ static int fsmMapFContext(FSM_t fsm)
     return 0;
 }
 
+#if WITH_CAP
+static int fsmMapFCaps(FSM_t fsm)
+{
+    rpmts ts = fsmGetTs(fsm);
+    rpmfi fi = fsmGetFi(fsm);
+    fsm->fcaps = NULL;
+    if (ts != NULL && fi->fcaps && *fi->fcaps[fsm->ix] != '\0') {
+       cap_t fcaps = cap_from_text(fi->fcaps[fsm->ix]);
+       if (fcaps) {
+          fsm->fcaps = fcaps;
+       }
+    } 
+    return 0;
+}
+#endif
+
 /**
  * Map next file path and action.
  * @param fsm          file state machine
@@ -1869,6 +1885,16 @@ if (!(fsm->mapFlags & CPIO_ALL_HARDLINKS)) break;
                    rc = fsmNext(fsm, FSM_UTIME);
                    st->st_mtime = mtime;
                }
+#if WITH_CAP
+               if (!rc && !S_ISDIR(st->st_mode) && !getuid()) {
+                   rc = fsmMapFCaps(fsm);
+                   if (!rc && fsm->fcaps) {
+                       rc = fsmNext(fsm, FSM_SETCAP);
+                       cap_free(fsm->fcaps);
+                   }
+                   fsm->fcaps = NULL;
+               }
+#endif /* WITH_CAP */
            }
        }
 
@@ -2077,6 +2103,14 @@ if (!(fsm->mapFlags & CPIO_ALL_HARDLINKS)) break;
            if (rc < 0) rc = CPIOERR_UTIME_FAILED;
        }
        break;
+#if WITH_CAP
+    case FSM_SETCAP:
+       rc = cap_set_file(fsm->path, fsm->fcaps);
+       if (rc < 0) {
+           rc = CPIOERR_SETCAP_FAILED;
+       }
+       break;
+#endif /* WITH_CAP */
     case FSM_SYMLINK:
        rc = symlink(fsm->opath, fsm->path);
        if (_fsm_debug && (stage & FSM_SYSCALL))
@@ -2357,6 +2391,7 @@ static const char * fileStageString(fileStage a) {
     case FSM_STAT:     return "stat";
     case FSM_READLINK: return "readlink";
     case FSM_CHROOT:   return "chroot";
+    case FSM_SETCAP:   return "setcap";
 
     case FSM_NEXT:     return "next";
     case FSM_EAT:      return "eat";
index 94fb8c3..89bc750 100644 (file)
--- a/lib/fsm.h
+++ b/lib/fsm.h
@@ -64,6 +64,7 @@ typedef enum fileStage_e {
     FSM_STAT   =  _fs(49),
     FSM_READLINK=  _fs(50),
     FSM_CHROOT =  _fs(51),
+    FSM_SETCAP =  _fs(52),
 
     FSM_NEXT   =  _fd(65),
     FSM_EAT    =  _fd(66),
@@ -154,6 +155,7 @@ struct fsm_s {
     const char * baseName;     /*!< File base name. */
     const char * digest;       /*!< Binary checksum (NULL disables). */
     security_context_t fcontext;/*!< File security context (NULL disables). */
+    cap_t fcaps;               /*!< File capabilities */
     pgpHashAlgo digestalgo;    /*!< File checksum algorithm */
     
     unsigned fflags;           /*!< File flags. */
index dfa15c3..bf03761 100644 (file)
@@ -371,6 +371,15 @@ const char * rpmfiFGroup(rpmfi fi)
     return fgroup;
 }
 
+const char * rpmfiFCaps(rpmfi fi)
+{
+    const char *fcaps = NULL;
+    if (fi != NULL && fi->i >= 0 && fi->i < fi->fc) {
+       fcaps = fi->fcaps ? fi->fcaps[fi->i] : "";
+    }
+    return fcaps;
+}
+
 int rpmfiNext(rpmfi fi)
 {
     int i = -1;
@@ -1124,6 +1133,7 @@ fprintf(stderr, "*** fi %p\t%s[%d]\n", fi, fi->Type, fi->fc);
        fi->flinks = _free(fi->flinks);
        fi->flangs = _free(fi->flangs);
        fi->digests = _free(fi->digests);
+       fi->fcaps = _free(fi->fcaps);
 
        fi->cdict = _free(fi->cdict);
 
@@ -1261,6 +1271,8 @@ rpmfi rpmfiNew(const rpmts ts, Header h, rpmTag tagN, int scareMem)
     if (fi->fstates == NULL)
        fi->fstates = xcalloc(fi->fc, sizeof(*fi->fstates));
 
+    _hgfi(h, RPMTAG_FILECAPS, &td, defFlags, fi->fcaps);
+
     fi->action = FA_UNKNOWN;
     fi->flags = 0;
 
index a96f627..f3498f6 100644 (file)
@@ -328,6 +328,15 @@ const char * rpmfiFUser(rpmfi fi);
 const char * rpmfiFGroup(rpmfi fi);
 
 /** \ingroup rpmfi
+ * Return textual representation of current file capabilities 
+ * from file info set. See cap_from_text(3) for details.
+ * @param fi           file info set
+ * @return             file capability description, "" for no capabilities
+ *                     and NULL on invalid
+ */
+const char * rpmfiFCaps(rpmfi fi);
+
+/** \ingroup rpmfi
  * Return next file iterator index.
  * @param fi           file info set
  * @return             file iterator index, -1 on termination
index c913a20..4e0180e 100644 (file)
@@ -61,6 +61,8 @@ struct rpmfi_s {
 
     const char ** fcontexts;   /*! FIle security contexts. */
 
+    const char ** fcaps;       /*! File capabilities (header) */
+
     const char ** cdict;       /*!< File class dictionary (header) */
     rpm_count_t ncdict;                /*!< No. of class entries. */
     const uint32_t * fcdictx;  /*!< File class dictionary index (header) */
index 3818e12..8c2f815 100644 (file)
--- a/system.h
+++ b/system.h
@@ -229,6 +229,8 @@ void * _free(void * p)
 
 #if WITH_CAP
 #include <sys/capability.h>
+#else
+typedef void * cap_t;
 #endif
 
 #if WITH_ACL