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;
CPIOERR_INTERNAL = (28 ),
CPIOERR_UNMAPPED_FILE = (29 ),
CPIOERR_ENOENT = (30 ),
- CPIOERR_ENOTEMPTY = (31 )
+ CPIOERR_ENOTEMPTY = (31 ),
+ CPIOERR_SETCAP_FAILED = (32 | CPIOERR_CHECK_ERRNO),
};
/*
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
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 */
}
}
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))
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";
FSM_STAT = _fs(49),
FSM_READLINK= _fs(50),
FSM_CHROOT = _fs(51),
+ FSM_SETCAP = _fs(52),
FSM_NEXT = _fd(65),
FSM_EAT = _fd(66),
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. */
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;
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);
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;
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
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) */
#if WITH_CAP
#include <sys/capability.h>
+#else
+typedef void * cap_t;
#endif
#if WITH_ACL