]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
dm-verity: fix a memory leak if some arguments are specified multiple times
authorMikulas Patocka <mpatocka@redhat.com>
Tue, 3 Jun 2025 16:55:50 +0000 (18:55 +0200)
committerMikulas Patocka <mpatocka@redhat.com>
Tue, 3 Jun 2025 17:01:42 +0000 (19:01 +0200)
If some of the arguments "check_at_most_once", "ignore_zero_blocks",
"use_fec_from_device", "root_hash_sig_key_desc" were specified more than
once on the target line, a memory leak would happen.

This commit fixes the memory leak. It also fixes error handling in
verity_verify_sig_parse_opt_args.

Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
Cc: stable@vger.kernel.org
drivers/md/dm-verity-fec.c
drivers/md/dm-verity-target.c
drivers/md/dm-verity-verify-sig.c

index 0c41949db784badb70b7dd61251d73f38538eb9c..631a887b487cc48c776eefa2c0f817d60dde4907 100644 (file)
@@ -593,6 +593,10 @@ int verity_fec_parse_opt_args(struct dm_arg_set *as, struct dm_verity *v,
        (*argc)--;
 
        if (!strcasecmp(arg_name, DM_VERITY_OPT_FEC_DEV)) {
+               if (v->fec->dev) {
+                       ti->error = "FEC device already specified";
+                       return -EINVAL;
+               }
                r = dm_get_device(ti, arg_value, BLK_OPEN_READ, &v->fec->dev);
                if (r) {
                        ti->error = "FEC device lookup failed";
index 34a9f9fbd0d189ee1045d0945217a54512d0df0d..81186bded1ce7bce06faefe1050841905eb19900 100644 (file)
@@ -1123,6 +1123,9 @@ static int verity_alloc_most_once(struct dm_verity *v)
 {
        struct dm_target *ti = v->ti;
 
+       if (v->validated_blocks)
+               return 0;
+
        /* the bitset can only handle INT_MAX blocks */
        if (v->data_blocks > INT_MAX) {
                ti->error = "device too large to use check_at_most_once";
@@ -1146,6 +1149,9 @@ static int verity_alloc_zero_digest(struct dm_verity *v)
        struct dm_verity_io *io;
        u8 *zero_data;
 
+       if (v->zero_digest)
+               return 0;
+
        v->zero_digest = kmalloc(v->digest_size, GFP_KERNEL);
 
        if (!v->zero_digest)
@@ -1580,7 +1586,7 @@ static int verity_ctr(struct dm_target *ti, unsigned int argc, char **argv)
                        goto bad;
        }
 
-       /* Root hash signature is  a optional parameter*/
+       /* Root hash signature is an optional parameter */
        r = verity_verify_root_hash(root_hash_digest_to_validate,
                                    strlen(root_hash_digest_to_validate),
                                    verify_args.sig,
index a9e2c6c0a33c6db8a3b5791f51e86f401350e614..d5261a0e4232e11f45fb7d0ec68586887bf0e256 100644 (file)
@@ -71,9 +71,14 @@ int verity_verify_sig_parse_opt_args(struct dm_arg_set *as,
                                     const char *arg_name)
 {
        struct dm_target *ti = v->ti;
-       int ret = 0;
+       int ret;
        const char *sig_key = NULL;
 
+       if (v->signature_key_desc) {
+               ti->error = DM_VERITY_VERIFY_ERR("root_hash_sig_key_desc already specified");
+               return -EINVAL;
+       }
+
        if (!*argc) {
                ti->error = DM_VERITY_VERIFY_ERR("Signature key not specified");
                return -EINVAL;
@@ -83,14 +88,18 @@ int verity_verify_sig_parse_opt_args(struct dm_arg_set *as,
        (*argc)--;
 
        ret = verity_verify_get_sig_from_key(sig_key, sig_opts);
-       if (ret < 0)
+       if (ret < 0) {
                ti->error = DM_VERITY_VERIFY_ERR("Invalid key specified");
+               return ret;
+       }
 
        v->signature_key_desc = kstrdup(sig_key, GFP_KERNEL);
-       if (!v->signature_key_desc)
+       if (!v->signature_key_desc) {
+               ti->error = DM_VERITY_VERIFY_ERR("Could not allocate memory for signature key");
                return -ENOMEM;
+       }
 
-       return ret;
+       return 0;
 }
 
 /*