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:
Panu Matilainen 2008-10-29 11:49:38 +02:00
parent a792c55ffa
commit 97ab15cc9e
8 changed files with 65 additions and 1 deletions

View 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;

View 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),
};
/*

View File

@ -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";

View File

@ -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. */

View 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;

View File

@ -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

View 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) */

View File

@ -229,6 +229,8 @@ void * _free(void * p)
#if WITH_CAP
#include <sys/capability.h>
#else
typedef void * cap_t;
#endif
#if WITH_ACL