Add fsm and rpmfi machinery for file capabilities
- 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
This commit is contained in:
parent
a792c55ffa
commit
97ab15cc9e
|
@ -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;
|
||||
|
|
|
@ -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),
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
35
lib/fsm.c
35
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";
|
||||
|
|
|
@ -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. */
|
||||
|
|
12
lib/rpmfi.c
12
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;
|
||||
|
||||
|
|
|
@ -327,6 +327,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
|
||||
|
|
|
@ -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) */
|
||||
|
|
Loading…
Reference in New Issue