Commit 38aa3f5a authored by Gustavo A. R. Silva's avatar Gustavo A. R. Silva Committed by Mimi Zohar

integrity: Avoid -Wflex-array-member-not-at-end warnings

-Wflex-array-member-not-at-end is coming in GCC-14, and we are getting
ready to enable it globally.

There is currently an object (`hdr)` in `struct ima_max_digest_data`
that contains a flexible structure (`struct ima_digest_data`):

 struct ima_max_digest_data {
        struct ima_digest_data hdr;
        u8 digest[HASH_MAX_DIGESTSIZE];
 } __packed;

So, in order to avoid ending up with a flexible-array member in the
middle of a struct, we use the `__struct_group()` helper to separate
the flexible array from the rest of the members in the flexible
structure:

struct ima_digest_data {
        __struct_group(ima_digest_data_hdr, hdr, __packed,

        ... the rest of the members

        );
        u8 digest[];
} __packed;

And similarly for `struct evm_ima_xattr_data`.

With the change described above, we can now declare an object of the
type of the tagged `struct ima_digest_data_hdr`, without embedding the
flexible array in the middle of another struct:

 struct ima_max_digest_data {
        struct ima_digest_data_hdr hdr;
        u8 digest[HASH_MAX_DIGESTSIZE];
 } __packed;

And similarly for `struct evm_digest` and `struct evm_xattr`.

We also use `container_of()` whenever we need to retrieve a pointer to
the flexible structure.

So, with these changes, fix the following warnings:

security/integrity/evm/evm.h:64:32: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
security/integrity/evm/../integrity.h:40:35: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
security/integrity/evm/../integrity.h:68:32: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
security/integrity/ima/../integrity.h:40:35: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
security/integrity/ima/../integrity.h:68:32: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
security/integrity/integrity.h:40:35: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
security/integrity/integrity.h:68:32: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
security/integrity/platform_certs/../integrity.h:40:35: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
security/integrity/platform_certs/../integrity.h:68:32: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]

Link: https://github.com/KSPP/linux/issues/202Signed-off-by: default avatarGustavo A. R. Silva <gustavoars@kernel.org>
Signed-off-by: default avatarMimi Zohar <zohar@linux.ibm.com>
parent cc293c84
...@@ -61,7 +61,7 @@ extern int evm_hmac_attrs; ...@@ -61,7 +61,7 @@ extern int evm_hmac_attrs;
extern struct list_head evm_config_xattrnames; extern struct list_head evm_config_xattrnames;
struct evm_digest { struct evm_digest {
struct ima_digest_data hdr; struct ima_digest_data_hdr hdr;
char digest[IMA_MAX_DIGEST_SIZE]; char digest[IMA_MAX_DIGEST_SIZE];
} __packed; } __packed;
......
...@@ -246,6 +246,8 @@ int ima_collect_measurement(struct ima_iint_cache *iint, struct file *file, ...@@ -246,6 +246,8 @@ int ima_collect_measurement(struct ima_iint_cache *iint, struct file *file,
struct inode *inode = file_inode(file); struct inode *inode = file_inode(file);
struct inode *real_inode = d_real_inode(file_dentry(file)); struct inode *real_inode = d_real_inode(file_dentry(file));
struct ima_max_digest_data hash; struct ima_max_digest_data hash;
struct ima_digest_data *hash_hdr = container_of(&hash.hdr,
struct ima_digest_data, hdr);
struct name_snapshot filename; struct name_snapshot filename;
struct kstat stat; struct kstat stat;
int result = 0; int result = 0;
...@@ -286,9 +288,9 @@ int ima_collect_measurement(struct ima_iint_cache *iint, struct file *file, ...@@ -286,9 +288,9 @@ int ima_collect_measurement(struct ima_iint_cache *iint, struct file *file,
result = -ENODATA; result = -ENODATA;
} }
} else if (buf) { } else if (buf) {
result = ima_calc_buffer_hash(buf, size, &hash.hdr); result = ima_calc_buffer_hash(buf, size, hash_hdr);
} else { } else {
result = ima_calc_file_hash(file, &hash.hdr); result = ima_calc_file_hash(file, hash_hdr);
} }
if (result && result != -EBADF && result != -EINVAL) if (result && result != -EBADF && result != -EINVAL)
......
...@@ -378,7 +378,9 @@ static int xattr_verify(enum ima_hooks func, struct ima_iint_cache *iint, ...@@ -378,7 +378,9 @@ static int xattr_verify(enum ima_hooks func, struct ima_iint_cache *iint,
} }
rc = calc_file_id_hash(IMA_VERITY_DIGSIG, iint->ima_hash->algo, rc = calc_file_id_hash(IMA_VERITY_DIGSIG, iint->ima_hash->algo,
iint->ima_hash->digest, &hash.hdr); iint->ima_hash->digest,
container_of(&hash.hdr,
struct ima_digest_data, hdr));
if (rc) { if (rc) {
*cause = "sigv3-hashing-error"; *cause = "sigv3-hashing-error";
*status = INTEGRITY_FAIL; *status = INTEGRITY_FAIL;
......
...@@ -48,12 +48,14 @@ static int __init ima_add_boot_aggregate(void) ...@@ -48,12 +48,14 @@ static int __init ima_add_boot_aggregate(void)
struct ima_event_data event_data = { .iint = iint, struct ima_event_data event_data = { .iint = iint,
.filename = boot_aggregate_name }; .filename = boot_aggregate_name };
struct ima_max_digest_data hash; struct ima_max_digest_data hash;
struct ima_digest_data *hash_hdr = container_of(&hash.hdr,
struct ima_digest_data, hdr);
int result = -ENOMEM; int result = -ENOMEM;
int violation = 0; int violation = 0;
memset(iint, 0, sizeof(*iint)); memset(iint, 0, sizeof(*iint));
memset(&hash, 0, sizeof(hash)); memset(&hash, 0, sizeof(hash));
iint->ima_hash = &hash.hdr; iint->ima_hash = hash_hdr;
iint->ima_hash->algo = ima_hash_algo; iint->ima_hash->algo = ima_hash_algo;
iint->ima_hash->length = hash_digest_size[ima_hash_algo]; iint->ima_hash->length = hash_digest_size[ima_hash_algo];
...@@ -70,7 +72,7 @@ static int __init ima_add_boot_aggregate(void) ...@@ -70,7 +72,7 @@ static int __init ima_add_boot_aggregate(void)
* is not found. * is not found.
*/ */
if (ima_tpm_chip) { if (ima_tpm_chip) {
result = ima_calc_boot_aggregate(&hash.hdr); result = ima_calc_boot_aggregate(hash_hdr);
if (result < 0) { if (result < 0) {
audit_cause = "hashing_error"; audit_cause = "hashing_error";
goto err_out; goto err_out;
......
...@@ -948,6 +948,8 @@ int process_buffer_measurement(struct mnt_idmap *idmap, ...@@ -948,6 +948,8 @@ int process_buffer_measurement(struct mnt_idmap *idmap,
.buf_len = size}; .buf_len = size};
struct ima_template_desc *template; struct ima_template_desc *template;
struct ima_max_digest_data hash; struct ima_max_digest_data hash;
struct ima_digest_data *hash_hdr = container_of(&hash.hdr,
struct ima_digest_data, hdr);
char digest_hash[IMA_MAX_DIGEST_SIZE]; char digest_hash[IMA_MAX_DIGEST_SIZE];
int digest_hash_len = hash_digest_size[ima_hash_algo]; int digest_hash_len = hash_digest_size[ima_hash_algo];
int violation = 0; int violation = 0;
...@@ -986,7 +988,7 @@ int process_buffer_measurement(struct mnt_idmap *idmap, ...@@ -986,7 +988,7 @@ int process_buffer_measurement(struct mnt_idmap *idmap,
if (!pcr) if (!pcr)
pcr = CONFIG_IMA_MEASURE_PCR_IDX; pcr = CONFIG_IMA_MEASURE_PCR_IDX;
iint.ima_hash = &hash.hdr; iint.ima_hash = hash_hdr;
iint.ima_hash->algo = ima_hash_algo; iint.ima_hash->algo = ima_hash_algo;
iint.ima_hash->length = hash_digest_size[ima_hash_algo]; iint.ima_hash->length = hash_digest_size[ima_hash_algo];
...@@ -997,7 +999,7 @@ int process_buffer_measurement(struct mnt_idmap *idmap, ...@@ -997,7 +999,7 @@ int process_buffer_measurement(struct mnt_idmap *idmap,
} }
if (buf_hash) { if (buf_hash) {
memcpy(digest_hash, hash.hdr.digest, digest_hash_len); memcpy(digest_hash, hash_hdr->digest, digest_hash_len);
ret = ima_calc_buffer_hash(digest_hash, digest_hash_len, ret = ima_calc_buffer_hash(digest_hash, digest_hash_len,
iint.ima_hash); iint.ima_hash);
......
...@@ -339,6 +339,8 @@ int ima_eventdigest_init(struct ima_event_data *event_data, ...@@ -339,6 +339,8 @@ int ima_eventdigest_init(struct ima_event_data *event_data,
struct ima_field_data *field_data) struct ima_field_data *field_data)
{ {
struct ima_max_digest_data hash; struct ima_max_digest_data hash;
struct ima_digest_data *hash_hdr = container_of(&hash.hdr,
struct ima_digest_data, hdr);
u8 *cur_digest = NULL; u8 *cur_digest = NULL;
u32 cur_digestsize = 0; u32 cur_digestsize = 0;
struct inode *inode; struct inode *inode;
...@@ -358,7 +360,7 @@ int ima_eventdigest_init(struct ima_event_data *event_data, ...@@ -358,7 +360,7 @@ int ima_eventdigest_init(struct ima_event_data *event_data,
if ((const char *)event_data->filename == boot_aggregate_name) { if ((const char *)event_data->filename == boot_aggregate_name) {
if (ima_tpm_chip) { if (ima_tpm_chip) {
hash.hdr.algo = HASH_ALGO_SHA1; hash.hdr.algo = HASH_ALGO_SHA1;
result = ima_calc_boot_aggregate(&hash.hdr); result = ima_calc_boot_aggregate(hash_hdr);
/* algo can change depending on available PCR banks */ /* algo can change depending on available PCR banks */
if (!result && hash.hdr.algo != HASH_ALGO_SHA1) if (!result && hash.hdr.algo != HASH_ALGO_SHA1)
...@@ -368,7 +370,7 @@ int ima_eventdigest_init(struct ima_event_data *event_data, ...@@ -368,7 +370,7 @@ int ima_eventdigest_init(struct ima_event_data *event_data,
memset(&hash, 0, sizeof(hash)); memset(&hash, 0, sizeof(hash));
} }
cur_digest = hash.hdr.digest; cur_digest = hash_hdr->digest;
cur_digestsize = hash_digest_size[HASH_ALGO_SHA1]; cur_digestsize = hash_digest_size[HASH_ALGO_SHA1];
goto out; goto out;
} }
...@@ -379,14 +381,14 @@ int ima_eventdigest_init(struct ima_event_data *event_data, ...@@ -379,14 +381,14 @@ int ima_eventdigest_init(struct ima_event_data *event_data,
inode = file_inode(event_data->file); inode = file_inode(event_data->file);
hash.hdr.algo = ima_template_hash_algo_allowed(ima_hash_algo) ? hash.hdr.algo = ima_template_hash_algo_allowed(ima_hash_algo) ?
ima_hash_algo : HASH_ALGO_SHA1; ima_hash_algo : HASH_ALGO_SHA1;
result = ima_calc_file_hash(event_data->file, &hash.hdr); result = ima_calc_file_hash(event_data->file, hash_hdr);
if (result) { if (result) {
integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode,
event_data->filename, "collect_data", event_data->filename, "collect_data",
"failed", result, 0); "failed", result, 0);
return result; return result;
} }
cur_digest = hash.hdr.digest; cur_digest = hash_hdr->digest;
cur_digestsize = hash.hdr.length; cur_digestsize = hash.hdr.length;
out: out:
return ima_eventdigest_init_common(cur_digest, cur_digestsize, return ima_eventdigest_init_common(cur_digest, cur_digestsize,
......
...@@ -31,19 +31,24 @@ enum evm_ima_xattr_type { ...@@ -31,19 +31,24 @@ enum evm_ima_xattr_type {
}; };
struct evm_ima_xattr_data { struct evm_ima_xattr_data {
u8 type; /* New members must be added within the __struct_group() macro below. */
__struct_group(evm_ima_xattr_data_hdr, hdr, __packed,
u8 type;
);
u8 data[]; u8 data[];
} __packed; } __packed;
/* Only used in the EVM HMAC code. */ /* Only used in the EVM HMAC code. */
struct evm_xattr { struct evm_xattr {
struct evm_ima_xattr_data data; struct evm_ima_xattr_data_hdr data;
u8 digest[SHA1_DIGEST_SIZE]; u8 digest[SHA1_DIGEST_SIZE];
} __packed; } __packed;
#define IMA_MAX_DIGEST_SIZE HASH_MAX_DIGESTSIZE #define IMA_MAX_DIGEST_SIZE HASH_MAX_DIGESTSIZE
struct ima_digest_data { struct ima_digest_data {
/* New members must be added within the __struct_group() macro below. */
__struct_group(ima_digest_data_hdr, hdr, __packed,
u8 algo; u8 algo;
u8 length; u8 length;
union { union {
...@@ -57,6 +62,7 @@ struct ima_digest_data { ...@@ -57,6 +62,7 @@ struct ima_digest_data {
} ng; } ng;
u8 data[2]; u8 data[2];
} xattr; } xattr;
);
u8 digest[]; u8 digest[];
} __packed; } __packed;
...@@ -65,7 +71,7 @@ struct ima_digest_data { ...@@ -65,7 +71,7 @@ struct ima_digest_data {
* with the maximum hash size, define ima_max_digest_data struct. * with the maximum hash size, define ima_max_digest_data struct.
*/ */
struct ima_max_digest_data { struct ima_max_digest_data {
struct ima_digest_data hdr; struct ima_digest_data_hdr hdr;
u8 digest[HASH_MAX_DIGESTSIZE]; u8 digest[HASH_MAX_DIGESTSIZE];
} __packed; } __packed;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment