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