lkml.org 
[lkml]   [2021]   [Dec]   [6]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v3 08/16] ima: Move measurement list related variables into ima_namespace
    Date
    Move measurement list related variables into the ima_namespace. This way a
    front-end like SecurityFS can show the measurement list inside an IMA
    namespace.

    Implement ima_free_measurements() to free a list of measurements
    and call it when an IMA namespace is deleted.

    Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
    ---
    include/linux/ima.h | 2 ++
    security/integrity/ima/ima.h | 4 +--
    security/integrity/ima/ima_fs.c | 6 +++--
    security/integrity/ima/ima_init_ima_ns.c | 5 ++++
    security/integrity/ima/ima_ns.c | 1 +
    security/integrity/ima/ima_queue.c | 33 ++++++++++++++----------
    6 files changed, 33 insertions(+), 18 deletions(-)

    diff --git a/include/linux/ima.h b/include/linux/ima.h
    index 929bf87b1bbf..53f944469de7 100644
    --- a/include/linux/ima.h
    +++ b/include/linux/ima.h
    @@ -259,6 +259,8 @@ struct ima_namespace {
    int ima_policy_flag;

    struct ima_h_table ima_htable;
    + struct list_head ima_measurements;
    + unsigned long binary_runtime_size;
    };

    extern struct ima_namespace init_ima_ns;
    diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
    index a7e6c8fb152a..bb9763cd5fb1 100644
    --- a/security/integrity/ima/ima.h
    +++ b/security/integrity/ima/ima.h
    @@ -104,7 +104,6 @@ struct ima_queue_entry {
    struct list_head later; /* place in ima_measurements list */
    struct ima_template_entry *entry;
    };
    -extern struct list_head ima_measurements; /* list of all measurements */

    /* Some details preceding the binary serialized measurement list */
    struct ima_kexec_hdr {
    @@ -168,8 +167,9 @@ int ima_restore_measurement_entry(struct ima_namespace *ns,
    struct ima_template_entry *entry);
    int ima_restore_measurement_list(struct ima_namespace *ns,
    loff_t bufsize, void *buf);
    +void ima_free_measurements(struct ima_namespace *ns);
    int ima_measurements_show(struct seq_file *m, void *v);
    -unsigned long ima_get_binary_runtime_size(void);
    +unsigned long ima_get_binary_runtime_size(struct ima_namespace *ns);
    int ima_init_template(void);
    void ima_init_template_list(void);
    int __init ima_init_digests(void);
    diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c
    index 9df8648ad64d..c35e15fb313f 100644
    --- a/security/integrity/ima/ima_fs.c
    +++ b/security/integrity/ima/ima_fs.c
    @@ -80,12 +80,13 @@ static const struct file_operations ima_measurements_count_ops = {
    /* returns pointer to hlist_node */
    static void *ima_measurements_start(struct seq_file *m, loff_t *pos)
    {
    + struct ima_namespace *ns = get_current_ns();
    loff_t l = *pos;
    struct ima_queue_entry *qe;

    /* we need a lock since pos could point beyond last element */
    rcu_read_lock();
    - list_for_each_entry_rcu(qe, &ima_measurements, later) {
    + list_for_each_entry_rcu(qe, &ns->ima_measurements, later) {
    if (!l--) {
    rcu_read_unlock();
    return qe;
    @@ -97,6 +98,7 @@ static void *ima_measurements_start(struct seq_file *m, loff_t *pos)

    static void *ima_measurements_next(struct seq_file *m, void *v, loff_t *pos)
    {
    + struct ima_namespace *ns = get_current_ns();
    struct ima_queue_entry *qe = v;

    /* lock protects when reading beyond last element
    @@ -107,7 +109,7 @@ static void *ima_measurements_next(struct seq_file *m, void *v, loff_t *pos)
    rcu_read_unlock();
    (*pos)++;

    - return (&qe->later == &ima_measurements) ? NULL : qe;
    + return (&qe->later == &ns->ima_measurements) ? NULL : qe;
    }

    static void ima_measurements_stop(struct seq_file *m, void *v)
    diff --git a/security/integrity/ima/ima_init_ima_ns.c b/security/integrity/ima/ima_init_ima_ns.c
    index e13adc3287ed..57e46a10c001 100644
    --- a/security/integrity/ima/ima_init_ima_ns.c
    +++ b/security/integrity/ima/ima_init_ima_ns.c
    @@ -43,6 +43,11 @@ int ima_init_namespace(struct ima_namespace *ns)
    atomic_long_set(&ns->ima_htable.len, 0);
    atomic_long_set(&ns->ima_htable.violations, 0);
    memset(&ns->ima_htable.queue, 0, sizeof(ns->ima_htable.queue));
    + INIT_LIST_HEAD(&ns->ima_measurements);
    + if (IS_ENABLED(CONFIG_IMA_KEXEC) && ns == &init_ima_ns)
    + ns->binary_runtime_size = 0;
    + else
    + ns->binary_runtime_size = ULONG_MAX;

    return 0;
    }
    diff --git a/security/integrity/ima/ima_ns.c b/security/integrity/ima/ima_ns.c
    index efbf7087a8ee..debe863364fd 100644
    --- a/security/integrity/ima/ima_ns.c
    +++ b/security/integrity/ima/ima_ns.c
    @@ -69,6 +69,7 @@ static void destroy_ima_ns(struct ima_namespace *ns)
    pr_debug("DESTROY ima_ns: 0x%p\n", ns);
    ima_free_policy_rules(ns);
    free_ns_status_cache(ns);
    + ima_free_measurements(ns);
    kmem_cache_free(imans_cachep, ns);
    }

    diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c
    index 373154039b91..f15f776918ec 100644
    --- a/security/integrity/ima/ima_queue.c
    +++ b/security/integrity/ima/ima_queue.c
    @@ -25,13 +25,6 @@
    /* pre-allocated array of tpm_digest structures to extend a PCR */
    static struct tpm_digest *digests;

    -LIST_HEAD(ima_measurements); /* list of all measurements */
    -#ifdef CONFIG_IMA_KEXEC
    -static unsigned long binary_runtime_size;
    -#else
    -static unsigned long binary_runtime_size = ULONG_MAX;
    -#endif
    -
    /* mutex protects atomicity of extending measurement list
    * and extending the TPM PCR aggregate. Since tpm_extend can take
    * long (and the tpm driver uses a mutex), we can't use the spinlock.
    @@ -107,7 +100,7 @@ static int ima_add_digest_entry(struct ima_namespace *ns,
    qe->entry = entry;

    INIT_LIST_HEAD(&qe->later);
    - list_add_tail_rcu(&qe->later, &ima_measurements);
    + list_add_tail_rcu(&qe->later, &ns->ima_measurements);

    atomic_long_inc(&ns->ima_htable.len);
    if (update_htable) {
    @@ -116,12 +109,12 @@ static int ima_add_digest_entry(struct ima_namespace *ns,
    } else
    INIT_HLIST_NODE(&qe->hnext);

    - if (binary_runtime_size != ULONG_MAX) {
    + if (ns->binary_runtime_size != ULONG_MAX) {
    int size;

    size = get_binary_runtime_size(entry);
    - binary_runtime_size = (binary_runtime_size < ULONG_MAX - size) ?
    - binary_runtime_size + size : ULONG_MAX;
    + ns->binary_runtime_size = (ns->binary_runtime_size < ULONG_MAX - size) ?
    + ns->binary_runtime_size + size : ULONG_MAX;
    }
    return 0;
    }
    @@ -131,12 +124,12 @@ static int ima_add_digest_entry(struct ima_namespace *ns,
    * entire binary_runtime_measurement list, including the ima_kexec_hdr
    * structure.
    */
    -unsigned long ima_get_binary_runtime_size(void)
    +unsigned long ima_get_binary_runtime_size(struct ima_namespace *ns)
    {
    - if (binary_runtime_size >= (ULONG_MAX - sizeof(struct ima_kexec_hdr)))
    + if (ns->binary_runtime_size >= (ULONG_MAX - sizeof(struct ima_kexec_hdr)))
    return ULONG_MAX;
    else
    - return binary_runtime_size + sizeof(struct ima_kexec_hdr);
    + return ns->binary_runtime_size + sizeof(struct ima_kexec_hdr);
    }

    static int ima_pcr_extend(struct tpm_digest *digests_arg, int pcr)
    @@ -217,6 +210,18 @@ int ima_restore_measurement_entry(struct ima_namespace *ns,
    return result;
    }

    +void ima_free_measurements(struct ima_namespace *ns)
    +{
    + struct ima_queue_entry *qe, *tmp;
    +
    + list_for_each_entry_safe(qe, tmp, &ns->ima_measurements, later) {
    + list_del(&qe->later);
    + if (!hlist_unhashed(&qe->hnext))
    + hlist_del(&qe->hnext);
    + kfree(qe);
    + }
    +}
    +
    int __init ima_init_digests(void)
    {
    u16 digest_size;
    --
    2.31.1
    \
     
     \ /
      Last update: 2021-12-06 18:27    [W:5.607 / U:0.196 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site