summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/cpio.c1
-rw-r--r--lib/cpio.h3
-rw-r--r--lib/fsm.c35
-rw-r--r--lib/fsm.h2
-rw-r--r--lib/rpmfi.c12
-rw-r--r--lib/rpmfi.h9
-rw-r--r--lib/rpmfi_internal.h2
-rw-r--r--system.h2
8 files changed, 65 insertions, 1 deletions
diff --git a/lib/cpio.c b/lib/cpio.c
index f45644b21..d4265d3b7 100644
--- a/lib/cpio.c
+++ b/lib/cpio.c
@@ -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;
diff --git a/lib/cpio.h b/lib/cpio.h
index 5259b0325..fc6e92c61 100644
--- a/lib/cpio.h
+++ b/lib/cpio.h
@@ -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),
};
/*
diff --git a/lib/fsm.c b/lib/fsm.c
index 8175f825f..ecfb1f703 100644
--- 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";
diff --git a/lib/fsm.h b/lib/fsm.h
index 94fb8c3fd..89bc750a2 100644
--- 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. */
diff --git a/lib/rpmfi.c b/lib/rpmfi.c
index dfa15c318..bf037612c 100644
--- a/lib/rpmfi.c
+++ b/lib/rpmfi.c
@@ -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;
diff --git a/lib/rpmfi.h b/lib/rpmfi.h
index a96f627ae..f3498f643 100644
--- a/lib/rpmfi.h
+++ b/lib/rpmfi.h
@@ -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
diff --git a/lib/rpmfi_internal.h b/lib/rpmfi_internal.h
index c913a20e5..4e0180eb0 100644
--- a/lib/rpmfi_internal.h
+++ b/lib/rpmfi_internal.h
@@ -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) */
diff --git a/system.h b/system.h
index 3818e12dd..8c2f8150f 100644
--- 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