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

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/202


Signed-off-by: default avatarGustavo A. R. Silva <gustavoars@kernel.org>
Signed-off-by: default avatarMimi Zohar <zohar@linux.ibm.com>
parent cc293c84
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -61,7 +61,7 @@ extern int evm_hmac_attrs;
extern struct list_head evm_config_xattrnames;

struct evm_digest {
	struct ima_digest_data hdr;
	struct ima_digest_data_hdr hdr;
	char digest[IMA_MAX_DIGEST_SIZE];
} __packed;

+4 −2
Original line number Diff line number Diff line
@@ -246,6 +246,8 @@ int ima_collect_measurement(struct ima_iint_cache *iint, struct file *file,
	struct inode *inode = file_inode(file);
	struct inode *real_inode = d_real_inode(file_dentry(file));
	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 kstat stat;
	int result = 0;
@@ -286,9 +288,9 @@ int ima_collect_measurement(struct ima_iint_cache *iint, struct file *file,
			result = -ENODATA;
		}
	} else if (buf) {
		result = ima_calc_buffer_hash(buf, size, &hash.hdr);
		result = ima_calc_buffer_hash(buf, size, hash_hdr);
	} else {
		result = ima_calc_file_hash(file, &hash.hdr);
		result = ima_calc_file_hash(file, hash_hdr);
	}

	if (result && result != -EBADF && result != -EINVAL)
+3 −1
Original line number Diff line number Diff line
@@ -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,
				       iint->ima_hash->digest, &hash.hdr);
				       iint->ima_hash->digest,
				       container_of(&hash.hdr,
					       struct ima_digest_data, hdr));
		if (rc) {
			*cause = "sigv3-hashing-error";
			*status = INTEGRITY_FAIL;
+4 −2
Original line number Diff line number Diff line
@@ -48,12 +48,14 @@ static int __init ima_add_boot_aggregate(void)
	struct ima_event_data event_data = { .iint = iint,
					     .filename = boot_aggregate_name };
	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 violation = 0;

	memset(iint, 0, sizeof(*iint));
	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->length = hash_digest_size[ima_hash_algo];

@@ -70,7 +72,7 @@ static int __init ima_add_boot_aggregate(void)
	 * is not found.
	 */
	if (ima_tpm_chip) {
		result = ima_calc_boot_aggregate(&hash.hdr);
		result = ima_calc_boot_aggregate(hash_hdr);
		if (result < 0) {
			audit_cause = "hashing_error";
			goto err_out;
+4 −2
Original line number Diff line number Diff line
@@ -948,6 +948,8 @@ int process_buffer_measurement(struct mnt_idmap *idmap,
					    .buf_len = size};
	struct ima_template_desc *template;
	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];
	int digest_hash_len = hash_digest_size[ima_hash_algo];
	int violation = 0;
@@ -986,7 +988,7 @@ int process_buffer_measurement(struct mnt_idmap *idmap,
	if (!pcr)
		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->length = hash_digest_size[ima_hash_algo];

@@ -997,7 +999,7 @@ int process_buffer_measurement(struct mnt_idmap *idmap,
	}

	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,
					   iint.ima_hash);
Loading