|
|
2ff057 |
#include "system.h"
|
|
|
2ff057 |
|
|
|
2ff057 |
#include <errno.h>
|
|
|
2ff057 |
#include <sys/xattr.h>
|
|
|
2ff057 |
|
|
|
2ff057 |
#include <rpm/rpmfi.h>
|
|
|
2ff057 |
#include <rpm/rpmte.h>
|
|
|
2ff057 |
#include <rpm/rpmfiles.h>
|
|
|
2ff057 |
#include <rpm/rpmtypes.h>
|
|
|
2ff057 |
#include <rpm/rpmlog.h>
|
|
|
2ff057 |
#include <rpmio/rpmstring.h>
|
|
|
2ff057 |
|
|
|
2ff057 |
#include "lib/rpmfs.h"
|
|
|
2ff057 |
#include "lib/rpmplugin.h"
|
|
|
2ff057 |
#include "lib/rpmte_internal.h"
|
|
|
2ff057 |
|
|
|
2ff057 |
#define XATTR_NAME_IMA "security.ima"
|
|
|
2ff057 |
|
|
|
2ff057 |
/*
|
|
|
2ff057 |
* check_zero_hdr: Check the signature for a zero header
|
|
|
2ff057 |
*
|
|
|
2ff057 |
* Check whether the given signature has a header with all zeros
|
|
|
2ff057 |
*
|
|
|
2ff057 |
* Returns -1 in case the signature is too short to compare
|
|
|
2ff057 |
* (invalid signature), 0 in case the header is not only zeroes,
|
|
|
2ff057 |
* and 1 if it is only zeroes.
|
|
|
2ff057 |
*/
|
|
|
2ff057 |
static int check_zero_hdr(const unsigned char *fsig, size_t siglen)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
/*
|
|
|
2ff057 |
* Every signature has a header signature_v2_hdr as defined in
|
|
|
2ff057 |
* Linux's (4.5) security/integrity/integtrity.h. The following
|
|
|
2ff057 |
* 9 bytes represent this header in front of the signature.
|
|
|
2ff057 |
*/
|
|
|
2ff057 |
static const uint8_t zero_hdr[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
|
|
|
2ff057 |
|
|
|
2ff057 |
if (siglen < sizeof(zero_hdr))
|
|
|
2ff057 |
return -1;
|
|
|
2ff057 |
return (memcmp(fsig, &zero_hdr, sizeof(zero_hdr)) == 0);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
static rpmRC ima_fsm_file_prepare(rpmPlugin plugin, rpmfi fi,
|
|
|
2ff057 |
const char *path,
|
|
|
2ff057 |
const char *dest,
|
|
|
2ff057 |
mode_t file_mode, rpmFsmOp op)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
const unsigned char * fsig = NULL;
|
|
|
2ff057 |
size_t len;
|
|
|
2ff057 |
int rc = RPMRC_OK;
|
|
|
2ff057 |
rpmFileAction action = XFO_ACTION(op);
|
|
|
2ff057 |
|
|
|
2ff057 |
/* Ignore skipped files and unowned directories */
|
|
|
2ff057 |
if (XFA_SKIPPING(action) || (op & FAF_UNOWNED))
|
|
|
2ff057 |
goto exit;
|
|
|
2ff057 |
|
|
|
2ff057 |
/* Don't install signatures for (mutable) files marked
|
|
|
2ff057 |
* as config files unless they are also executable.
|
|
|
2ff057 |
*/
|
|
|
2ff057 |
if (rpmfiFFlags(fi) & RPMFILE_CONFIG) {
|
|
|
2ff057 |
if (!(rpmfiFMode(fi) & (S_IXUSR|S_IXGRP|S_IXOTH)))
|
|
|
2ff057 |
goto exit;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
fsig = rpmfiFSignature(fi, &len;;
|
|
|
2ff057 |
if (fsig && (check_zero_hdr(fsig, len) == 0)) {
|
|
|
2ff057 |
if (lsetxattr(path, XATTR_NAME_IMA, fsig, len, 0) < 0) {
|
|
|
2ff057 |
rpmlog(RPMLOG_ERR,
|
|
|
2ff057 |
"ima: could not apply signature on '%s': %s\n",
|
|
|
2ff057 |
path, strerror(errno));
|
|
|
2ff057 |
rc = RPMRC_FAIL;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
exit:
|
|
|
2ff057 |
return rc;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
struct rpmPluginHooks_s ima_hooks = {
|
|
|
2ff057 |
.fsm_file_prepare = ima_fsm_file_prepare,
|
|
|
2ff057 |
};
|