All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH] integrity : utils Add 2 more inode atributes to hash
@ 2020-04-05 20:13 Lev Olshvang
  0 siblings, 0 replies; only message in thread
From: Lev Olshvang @ 2020-04-05 20:13 UTC (permalink / raw)
  To: Dmitry Kasatkin, Vitaly Chikunov; +Cc: linux-integrity

From 0c48d5261ef653cc9ab73db7aa7bdf6bae4d9818 Mon Sep 17 00:00:00 2001
From: Lev Olshvang <levonshe@gmail.com>
Date: Sun, 5 Apr 2020 22:29:22 +0300
Subject: [RFC PATCH] integrity : utils Add 2 more inode atributes to hash

Added inode attr fields and  file size in to inode metadate hash.
Inode attr is importent because it may influence how filesystem
treats the file.
I think that some use cases relies on immutable attribute on files or
directories and some use cases marks encrypted files with a special
attribute
Therefore it is importent to check also integrity of inode->i_attr
Code refactored a bit to avoid duplicate code paths
I refactored also couple of very similar data types to avoid pointer conversions.

Signed-off-by: Lev Olshvang <levonshe@gmail.com>
---
 src/evmctl.c | 244 ++++++++++++++++++++++++---------------------------
 src/imaevm.h |  34 +++----
 2 files changed, 127 insertions(+), 151 deletions(-)

diff --git a/src/evmctl.c b/src/evmctl.c
index 3d2a10b..9a6c13c 100644
--- a/src/evmctl.c
+++ b/src/evmctl.c
@@ -117,7 +117,13 @@ static char *ino_str;
 static char *uid_str;
 static char *gid_str;
 static char *mode_str;
+static char *flags_str;
+static char *size_str;
+
+
+
 static char *generation_str;
+static uint32_t generation = 0;
 static char *caps_str;
 static char *ima_str;
 static char *selinux_str;
@@ -306,18 +312,24 @@ static int pack_uuid(const char *uuid_str, char *uuid)
 	return 0;
 }

-static int get_uuid(struct stat *st, char *uuid)
+static int get_uuid(const char *const file, char *uuid)
 {
 	uint32_t dev;
 	unsigned minor, major;
 	char path[PATH_MAX], _uuid[37];
 	FILE *fp;
 	size_t len;
+	struct stat st;

 	if (uuid_str)
 		return pack_uuid(uuid_str, uuid);

-	dev = st->st_dev;
+	if (lstat(file, &st)) {
+		log_err("Failed to stat: %s\n", file);
+		return -1;
+	}
+
+	dev = st.st_dev;
 	major = (dev & 0xfff00) >> 8;
 	minor = (dev & 0xff) | ((dev >> 12) & 0xfff00);

@@ -338,33 +350,42 @@ err:
 	log_err("Failed to read UUID. Root access might require.\n");
 	return -1;
 }
+static void store_inode_meta(uint32_t attr, file_common_t *hmac, const struct stat * const st) {
+	hmac->uid = st->st_uid;
+	hmac->gid = st->st_gid;
+	hmac->mode = st->st_mode;
+	hmac->attr = attr;
+	hmac->filesize = (uint32_t) st->st_size;
+}

-static int calc_evm_hash(const char *file, unsigned char *hash)
-{
-        const EVP_MD *md;
+static int fill_hmac(const char * const file,  file_meta_t * hmac_misc) {
+	uint16_t hmac_size = sizeof(*hmac_misc);
+	uint32_t attr = 0;
 	struct stat st;
-	int err;
-	uint32_t generation = 0;
-	EVP_MD_CTX *pctx;
-	unsigned int mdlen;
-	char **xattrname;
-	char xattr_value[1024];
-	char list[1024];
-	ssize_t list_size;
-	char uuid[16];
-	struct h_misc_64 hmac_misc;
-	int hmac_size;
-#if OPENSSL_VERSION_NUMBER < 0x10100000
-	EVP_MD_CTX ctx;
-	pctx = &ctx;
-#else
-	pctx = EVP_MD_CTX_new();
-#endif
+
+	generation = 0;

 	if (lstat(file, &st)) {
 		log_err("Failed to stat: %s\n", file);
 		return -1;
 	}
+	if ( st.st_size > 0xFFFFFFFF) {
+		log_err("File too big %s\n", file);
+		return -E2BIG;
+	}
+	int fd = open(file, 0);
+	if (fd < 0) {
+				log_err("Failed to open: %s\n", file);
+				return -1;
+	}
+	int rc = ioctl(fd, FS_IOC_GETFLAGS, &attr);
+	if (rc) {
+			log_err("ioctl() FS_IOC_GETFLAGS failed, rc=%d\n", rc);
+			close(fd);
+			return -1;
+		}
+	close(fd);
+	log_info("attr: %x\n", attr);

 	if (generation_str)
 		generation = strtoul(generation_str, NULL, 10);
@@ -376,6 +397,10 @@ static int calc_evm_hash(const char *file, unsigned char *hash)
 		st.st_gid = strtoul(gid_str, NULL, 10);
 	if (mode_str)
 		st.st_mode = strtoul(mode_str, NULL, 10);
+	if (size_str)
+		st.st_size = strtoul(size_str, NULL, 10);
+	if (flags_str)
+		st.st_size = strtoul(flags_str, NULL, 10);

 	if (!evm_immutable) {
 		if ((S_ISREG(st.st_mode) || S_ISDIR(st.st_mode)) && !generation_str) {
@@ -396,6 +421,57 @@ static int calc_evm_hash(const char *file, unsigned char *hash)
 		}
 		log_info("generation: %u\n", generation);
 	}
+
+	memset(hmac_misc, 0, hmac_size);
+
+	if (evm_immutable) {
+		// hmac_dig_sig, portable
+		file_common_t *hmac = &(hmac_misc->portable_fstat);
+
+		hmac_size = sizeof(*hmac);
+		store_inode_meta(attr, hmac, &st);
+
+	} else {
+		file_extra_t *hmac = &(hmac_misc->non_portable_fstat);
+		hmac_size = sizeof(*hmac);
+		if (!evm_portable) {
+			hmac->ino = st.st_ino;
+			hmac->generation = generation;
+		}
+		file_common_t *hmac_p = &(hmac_misc->portable_fstat);
+		store_inode_meta(attr, hmac_p, &st);
+	}
+	return hmac_size;
+}
+
+static int calc_evm_hash(const char *file, unsigned char *hash)
+{
+    const EVP_MD *md;
+	int err;
+	uint16_t hmac_size;
+	EVP_MD_CTX *pctx;
+	unsigned int mdlen;
+	char **xattrname;
+	char xattr_value[1024];
+	char list[1024];
+	ssize_t list_size;
+	char uuid[16];
+	file_meta_t hmac_misc;
+
+	err = fill_hmac(file, &hmac_misc);
+	if  (err < 0) {
+		return err;
+	}
+	hmac_size = (uint16_t) err;
+	log_debug("hmac_misc (%d): ", hmac_size);
+	log_debug_dump(&hmac_misc, hmac_size);
+
+#if OPENSSL_VERSION_NUMBER < 0x10100000
+	EVP_MD_CTX ctx;
+	pctx = &ctx;
+#else
+	pctx = EVP_MD_CTX_new();
+#endif

 	list_size = llistxattr(file, list, sizeof(list));
 	if (list_size < 0) {
@@ -464,51 +540,8 @@ static int calc_evm_hash(const char *file, unsigned char *hash)
 		}
 	}

-	memset(&hmac_misc, 0, sizeof(hmac_misc));
-
-	if (evm_immutable) {
-		struct h_misc_digsig *hmac = (struct h_misc_digsig *)&hmac_misc;
-
-		hmac_size = sizeof(*hmac);
-		hmac->uid = st.st_uid;
-		hmac->gid = st.st_gid;
-		hmac->mode = st.st_mode;
-	} else if (msize == 0) {
-		struct h_misc *hmac = (struct h_misc *)&hmac_misc;

-		hmac_size = sizeof(*hmac);
-		if (!evm_portable) {
-			hmac->ino = st.st_ino;
-			hmac->generation = generation;
-		}
-		hmac->uid = st.st_uid;
-		hmac->gid = st.st_gid;
-		hmac->mode = st.st_mode;
-	} else if (msize == 64) {
-		struct h_misc_64 *hmac = (struct h_misc_64 *)&hmac_misc;
-
-		hmac_size = sizeof(*hmac);
-		if (!evm_portable) {
-			hmac->ino = st.st_ino;
-			hmac->generation = generation;
-		}
-		hmac->uid = st.st_uid;
-		hmac->gid = st.st_gid;
-		hmac->mode = st.st_mode;
-	} else {
-		struct h_misc_32 *hmac = (struct h_misc_32 *)&hmac_misc;
-
-		hmac_size = sizeof(*hmac);
-		if (!evm_portable) {
-			hmac->ino = st.st_ino;
-			hmac->generation = generation;
-		}
-		hmac->uid = st.st_uid;
-		hmac->gid = st.st_gid;
-		hmac->mode = st.st_mode;
-	}
-
-	log_debug("hmac_misc (%d): ", hmac_size);
+	log_debug("hmac_misc (%u): ", hmac_size);
 	log_debug_dump(&hmac_misc, hmac_size);

 	err = EVP_DigestUpdate(pctx, &hmac_misc, hmac_size);
@@ -519,7 +552,7 @@ static int calc_evm_hash(const char *file, unsigned char *hash)

 	if (!evm_immutable && !evm_portable &&
 	    !(hmac_flags & HMAC_FLAG_NO_UUID)) {
-		err = get_uuid(&st, uuid);
+		err = get_uuid(file, uuid);
 		if (err)
 			return -1;

@@ -1064,10 +1097,9 @@ static int cmd_setxattr_ima(struct command *cmd)

 static int calc_evm_hmac(const char *file, const char *keyfile, unsigned char *hash)
 {
-        const EVP_MD *md;
-	struct stat st;
+    const EVP_MD *md;
+
 	int err = -1;
-	uint32_t generation = 0;
 	HMAC_CTX *pctx;
 	unsigned int mdlen;
 	char **xattrname;
@@ -1077,8 +1109,19 @@ static int calc_evm_hmac(const char *file, const char *keyfile, unsigned char *h
 	unsigned char evmkey[MAX_KEY_SIZE];
 	char list[1024];
 	ssize_t list_size;
-	struct h_misc_64 hmac_misc;
+	file_meta_t hmac_misc;
 	int hmac_size;
+
+
+	hmac_size = fill_hmac(file, &hmac_misc);
+	if  (hmac_size < 0) {
+		return hmac_size;
+	}
+
+	log_debug("hmac_misc (%d): ", hmac_size);
+	log_debug_dump(&hmac_misc, hmac_size);
+
+
 #if OPENSSL_VERSION_NUMBER < 0x10100000
 	HMAC_CTX ctx;
 	pctx = &ctx;
@@ -1101,30 +1144,7 @@ static int calc_evm_hmac(const char *file, const char *keyfile, unsigned char *h
 	memcpy(evmkey, key, keylen);
 	memset(evmkey + keylen, 0, sizeof(evmkey) - keylen);

-	if (lstat(file, &st)) {
-		log_err("Failed to stat: %s\n", file);
-		goto out;
-	}
-
-	if (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode)) {
-		/* we cannot at the momement to get generation of special files..
-		 * kernel API does not support it */
-		int fd = open(file, 0);
-
-		if (fd < 0) {
-			log_err("Failed to open %s\n", file);
-			goto out;
-		}
-		if (ioctl(fd, FS_IOC_GETVERSION, &generation)) {
-			log_err("ioctl() failed\n");
-			close(fd);
-			goto out;
-		}
-		close(fd);
-	}
-
-	log_info("generation: %u\n", generation);
-
+
 	list_size = llistxattr(file, list, sizeof(list));
 	if (list_size <= 0) {
 		log_err("llistxattr() failed: %s\n", file);
@@ -1164,40 +1184,6 @@ static int calc_evm_hmac(const char *file, const char *keyfile, unsigned char *h
 		}
 	}

-	memset(&hmac_misc, 0, sizeof(hmac_misc));
-
-	if (msize == 0) {
-		struct h_misc *hmac = (struct h_misc *)&hmac_misc;
-
-		hmac_size = sizeof(*hmac);
-		hmac->ino = st.st_ino;
-		hmac->generation = generation;
-		hmac->uid = st.st_uid;
-		hmac->gid = st.st_gid;
-		hmac->mode = st.st_mode;
-	} else if (msize == 64) {
-		struct h_misc_64 *hmac = (struct h_misc_64 *)&hmac_misc;
-
-		hmac_size = sizeof(*hmac);
-		hmac->ino = st.st_ino;
-		hmac->generation = generation;
-		hmac->uid = st.st_uid;
-		hmac->gid = st.st_gid;
-		hmac->mode = st.st_mode;
-	} else {
-		struct h_misc_32 *hmac = (struct h_misc_32 *)&hmac_misc;
-
-		hmac_size = sizeof(*hmac);
-		hmac->ino = st.st_ino;
-		hmac->generation = generation;
-		hmac->uid = st.st_uid;
-		hmac->gid = st.st_gid;
-		hmac->mode = st.st_mode;
-	}
-
-	log_debug("hmac_misc (%d): ", hmac_size);
-	log_debug_dump(&hmac_misc, hmac_size);
-
 	err = !HMAC_Update(pctx, (const unsigned char *)&hmac_misc, hmac_size);
 	if (err) {
 		log_err("HMAC_Update() failed\n");
diff --git a/src/imaevm.h b/src/imaevm.h
index b881d92..6bc66e8 100644
--- a/src/imaevm.h
+++ b/src/imaevm.h
@@ -90,35 +90,25 @@ enum evm_ima_xattr_type {
 	EVM_XATTR_PORTABLE_DIGSIG,
 };

-struct h_misc {
-	unsigned long ino;
-	uint32_t generation;
+typedef struct _common {
 	uid_t uid;
 	gid_t gid;
 	unsigned short mode;
-};
+	uint32_t attr;
+	uint32_t filesize;
+} file_common_t;

-struct h_misc_32 {
-	uint32_t ino;
+typedef struct _extra {
+	file_common_t inode_common;
 	uint32_t generation;
-	uid_t uid;
-	gid_t gid;
-	unsigned short mode;
-};
-
-struct h_misc_64 {
 	uint64_t ino;
-	uint32_t generation;
-	uid_t uid;
-	gid_t gid;
-	unsigned short mode;
-};
+} file_extra_t;
+
+typedef union _extended {
+	file_common_t portable_fstat;
+	file_extra_t  non_portable_fstat;
+} file_meta_t;

-struct h_misc_digsig {
-	uid_t uid;
-	gid_t gid;
-	unsigned short mode;
-};

 enum pubkey_algo {
 	PUBKEY_ALGO_RSA,
--
2.17.1


^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2020-04-05 20:13 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2020-04-05 20:13 [RFC PATCH] integrity : utils Add 2 more inode atributes to hash Lev Olshvang

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.