Blame plugins/ima.c

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