All of lore.kernel.org
 help / color / mirror / Atom feed
From: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
To: Roberto Sassu <roberto.sassu@huawei.com>
Cc: <zohar@linux.ibm.com>, <gregkh@linuxfoundation.org>,
	<linux-integrity@vger.kernel.org>,
	<linux-security-module@vger.kernel.org>,
	<linux-doc@vger.kernel.org>, <linux-kselftest@vger.kernel.org>,
	<linux-kernel@vger.kernel.org>
Subject: Re: [RFC][PATCH v2 06/12] diglim: Interfaces - digest_list_add, digest_list_del
Date: Wed, 28 Jul 2021 14:38:42 +0200	[thread overview]
Message-ID: <20210728143842.2db6e28c@sal.lan> (raw)
In-Reply-To: <20210726163700.2092768-7-roberto.sassu@huawei.com>

Em Mon, 26 Jul 2021 18:36:54 +0200
Roberto Sassu <roberto.sassu@huawei.com> escreveu:

> Introduce <securityfs>/integrity/diglim/digest_list_add, which can be used
> to upload a digest list and add the digests to the hash table; passed data
> are interpreted as file path if the first byte is / or as the digest list
> itself otherwise. ima_measure_critical_data() is called to calculate the
> digest of the digest list and eventually, if an appropriate rule is set in
> the IMA policy, to measure it.
> 
> Also introduce <securityfs>/integrity/diglim/digest_list_del, which can be
> used to upload a digest list and delete the digests from the hash table;
> data are interpreted in the same way as described for digest_list_add.

LGTM.

> 
> Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
> ---
>  .../security/diglim/implementation.rst        |   9 +
>  MAINTAINERS                                   |   1 +
>  include/linux/kernel_read_file.h              |   1 +
>  security/integrity/diglim/Makefile            |   2 +-
>  security/integrity/diglim/diglim.h            |   2 +
>  security/integrity/diglim/fs.c                | 239 ++++++++++++++++++
>  security/integrity/integrity.h                |   4 +
>  7 files changed, 257 insertions(+), 1 deletion(-)
>  create mode 100644 security/integrity/diglim/fs.c
> 
> diff --git a/Documentation/security/diglim/implementation.rst b/Documentation/security/diglim/implementation.rst
> index 9d679567a037..fc0cd8810a80 100644
> --- a/Documentation/security/diglim/implementation.rst
> +++ b/Documentation/security/diglim/implementation.rst
> @@ -244,3 +244,12 @@ back when one of the steps fails.
>  
>  #. digest_list_parse() deletes the struct digest_list_item on unsuccessful
>     add or successful delete.
> +
> +
> +Interfaces
> +----------
> +
> +This section introduces the interfaces in
> +``<securityfs>/integrity/diglim`` necessary to interact with DIGLIM.
> +
> +.. kernel-doc:: security/integrity/diglim/fs.c
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 77c3613c600a..0672128fae7f 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -5464,6 +5464,7 @@ F:	Documentation/security/diglim/introduction.rst
>  F:	include/linux/diglim.h
>  F:	include/uapi/linux/diglim.h
>  F:	security/integrity/diglim/diglim.h
> +F:	security/integrity/diglim/fs.c
>  F:	security/integrity/diglim/methods.c
>  F:	security/integrity/diglim/parser.c
>  
> diff --git a/include/linux/kernel_read_file.h b/include/linux/kernel_read_file.h
> index 575ffa1031d3..636ecdfdc616 100644
> --- a/include/linux/kernel_read_file.h
> +++ b/include/linux/kernel_read_file.h
> @@ -14,6 +14,7 @@
>  	id(KEXEC_INITRAMFS, kexec-initramfs)	\
>  	id(POLICY, security-policy)		\
>  	id(X509_CERTIFICATE, x509-certificate)	\
> +	id(DIGEST_LIST, digest-list)	\
>  	id(MAX_ID, )
>  
>  #define __fid_enumify(ENUM, dummy) READING_ ## ENUM,
> diff --git a/security/integrity/diglim/Makefile b/security/integrity/diglim/Makefile
> index 34e4e154fff3..ac345afdf5dd 100644
> --- a/security/integrity/diglim/Makefile
> +++ b/security/integrity/diglim/Makefile
> @@ -5,4 +5,4 @@
>  
>  obj-$(CONFIG_DIGLIM) += diglim.o
>  
> -diglim-y := methods.o parser.o
> +diglim-y := methods.o parser.o fs.o
> diff --git a/security/integrity/diglim/diglim.h b/security/integrity/diglim/diglim.h
> index 3adc218a0325..819703175eda 100644
> --- a/security/integrity/diglim/diglim.h
> +++ b/security/integrity/diglim/diglim.h
> @@ -22,6 +22,8 @@
>  #include <linux/hash_info.h>
>  #include <linux/diglim.h>
>  
> +#include "../integrity.h"
> +
>  #define MAX_DIGEST_SIZE 64
>  #define HASH_BITS 10
>  #define DIGLIM_HTABLE_SIZE (1 << HASH_BITS)
> diff --git a/security/integrity/diglim/fs.c b/security/integrity/diglim/fs.c
> new file mode 100644
> index 000000000000..07a0d75a0e33
> --- /dev/null
> +++ b/security/integrity/diglim/fs.c
> @@ -0,0 +1,239 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (C) 2005,2006,2007,2008 IBM Corporation
> + * Copyright (C) 2017-2021 Huawei Technologies Duesseldorf GmbH
> + *
> + * Author: Roberto Sassu <roberto.sassu@huawei.com>
> + *
> + * Functions for the interfaces exposed in securityfs.
> + */
> +
> +#include <linux/fcntl.h>
> +#include <linux/kernel_read_file.h>
> +#include <linux/slab.h>
> +#include <linux/init.h>
> +#include <linux/seq_file.h>
> +#include <linux/rculist.h>
> +#include <linux/rcupdate.h>
> +#include <linux/parser.h>
> +#include <linux/vmalloc.h>
> +#include <linux/namei.h>
> +#include <linux/ima.h>
> +
> +#include "diglim.h"
> +
> +#define MAX_DIGEST_LIST_SIZE (64 * 1024 * 1024 - 1)
> +
> +static struct dentry *diglim_dir;
> +/**
> + * DOC: digest_list_add
> + *
> + * digest_list_add can be used to upload a digest list and add the digests
> + * to the hash table; passed data are interpreted as file path if the first
> + * byte is ``/`` or as the digest list itself otherwise.
> + *
> + * ima_measure_critical_data() is called to calculate the digest of the
> + * digest list and eventually, if an appropriate rule is set in the IMA
> + * policy, to measure it.
> + */
> +static struct dentry *digest_list_add_dentry;
> +/**
> + * DOC: digest_list_del
> + *
> + * digest_list_del can be used to upload a digest list and delete the
> + * digests from the hash table; data are interpreted in the same way as
> + * described for digest_list_add.
> + */
> +static struct dentry *digest_list_del_dentry;
> +char digest_label[NAME_MAX + 1];
> +
> +/*
> + * digest_list_read: read and parse the digest list from the path
> + */
> +static ssize_t digest_list_read(char *path, enum ops op)
> +{
> +	void *data = NULL;
> +	char *datap;
> +	size_t size;
> +	u8 actions = 0;
> +	struct file *file;
> +	char event_name[NAME_MAX + 9 + 1];
> +	u8 digest[IMA_MAX_DIGEST_SIZE] = { 0 };
> +	enum hash_algo algo;
> +	int rc, pathlen = strlen(path);
> +
> +	/* Remove \n. */
> +	datap = path;
> +	strsep(&datap, "\n");
> +
> +	file = filp_open(path, O_RDONLY, 0);
> +	if (IS_ERR(file)) {
> +		pr_err("unable to open file: %s (%ld)", path, PTR_ERR(file));
> +		return PTR_ERR(file);
> +	}
> +
> +	rc = kernel_read_file(file, 0, &data, INT_MAX, NULL,
> +			      READING_DIGEST_LIST);
> +	if (rc < 0) {
> +		pr_err("unable to read file: %s (%d)", path, rc);
> +		goto out;
> +	}
> +
> +	size = rc;
> +
> +	snprintf(event_name, sizeof(event_name), "%s_file_%s",
> +		 op == DIGEST_LIST_ADD ? "add" : "del",
> +		 file_dentry(file)->d_name.name);
> +
> +	rc = ima_measure_critical_data("diglim", event_name, data, size, false,
> +				       digest, sizeof(digest));
> +	if (rc < 0 && rc != -EEXIST)
> +		goto out_vfree;
> +
> +	algo = ima_get_current_hash_algo();
> +
> +	if (!rc || rc == -EEXIST)
> +		actions |= (1 << COMPACT_ACTION_IMA_MEASURED);
> +
> +	rc = digest_list_parse(size, data, op, actions, digest, algo, "");
> +	if (rc < 0)
> +		pr_err("unable to upload digest list %s (%d)\n", path, rc);
> +out_vfree:
> +	vfree(data);
> +out:
> +	fput(file);
> +
> +	if (rc < 0)
> +		return rc;
> +
> +	return pathlen;
> +}
> +
> +/*
> + * digest_list_write: write the digest list path or the digest list itself
> + */
> +static ssize_t digest_list_write(struct file *file, const char __user *buf,
> +				 size_t datalen, loff_t *ppos)
> +{
> +	char *data;
> +	ssize_t result;
> +	enum ops op = DIGEST_LIST_ADD;
> +	struct dentry *dentry = file_dentry(file);
> +	u8 digest[IMA_MAX_DIGEST_SIZE];
> +	char event_name[NAME_MAX + 11 + 1];
> +	enum hash_algo algo;
> +	u8 actions = 0;
> +
> +	/* No partial writes. */
> +	result = -EINVAL;
> +	if (*ppos != 0)
> +		goto out;
> +
> +	result = -EFBIG;
> +	if (datalen > MAX_DIGEST_LIST_SIZE)
> +		goto out;
> +
> +	data = memdup_user_nul(buf, datalen);
> +	if (IS_ERR(data)) {
> +		result = PTR_ERR(data);
> +		goto out;
> +	}
> +
> +	if (dentry == digest_list_del_dentry)
> +		op = DIGEST_LIST_DEL;
> +
> +	result = -EPERM;
> +
> +	if (data[0] == '/') {
> +		result = digest_list_read(data, op);
> +	} else {
> +		snprintf(event_name, sizeof(event_name), "%s_buffer_%s",
> +			 op == DIGEST_LIST_ADD ? "add" : "del", digest_label);
> +
> +		result = ima_measure_critical_data("diglim", event_name, data,
> +						   datalen, false, digest,
> +						   sizeof(digest));
> +		if (result < 0 && result != -EEXIST) {
> +			pr_err("failed to measure buffer digest (%ld)\n",
> +			       result);
> +			goto out_kfree;
> +		}
> +
> +		algo = ima_get_current_hash_algo();
> +
> +		if (!result || result == -EEXIST)
> +			actions |= (1 << COMPACT_ACTION_IMA_MEASURED);
> +
> +		result = digest_list_parse(datalen, data, op, actions, digest,
> +					   algo, "");
> +		if (result != datalen) {
> +			pr_err("unable to upload generated digest list\n");
> +			result = -EINVAL;
> +		}
> +	}
> +out_kfree:
> +	kfree(data);
> +out:
> +	return result;
> +}
> +
> +static unsigned long flags;
> +
> +/*
> + * digest_list_open: sequentialize access to the add/del files
> + */
> +static int digest_list_open(struct inode *inode, struct file *filp)
> +{
> +	if ((filp->f_flags & O_ACCMODE) != O_WRONLY)
> +		return -EACCES;
> +
> +	if (test_and_set_bit(0, &flags))
> +		return -EBUSY;
> +
> +	return 0;
> +}
> +
> +/*
> + * digest_list_release - release the add/del files
> + */
> +static int digest_list_release(struct inode *inode, struct file *file)
> +{
> +	clear_bit(0, &flags);
> +	return 0;
> +}
> +
> +static const struct file_operations digest_list_upload_ops = {
> +	.open = digest_list_open,
> +	.write = digest_list_write,
> +	.read = seq_read,
> +	.release = digest_list_release,
> +	.llseek = generic_file_llseek,
> +};
> +
> +static int __init diglim_fs_init(void)
> +{
> +	diglim_dir = securityfs_create_dir("diglim", integrity_dir);
> +	if (IS_ERR(diglim_dir))
> +		return -1;
> +
> +	digest_list_add_dentry = securityfs_create_file("digest_list_add", 0200,
> +						diglim_dir, NULL,
> +						&digest_list_upload_ops);
> +	if (IS_ERR(digest_list_add_dentry))
> +		goto out;
> +
> +	digest_list_del_dentry = securityfs_create_file("digest_list_del", 0200,
> +						diglim_dir, NULL,
> +						&digest_list_upload_ops);
> +	if (IS_ERR(digest_list_del_dentry))
> +		goto out;
> +
> +	return 0;
> +out:
> +	securityfs_remove(digest_list_del_dentry);
> +	securityfs_remove(digest_list_add_dentry);
> +	securityfs_remove(diglim_dir);
> +	return -1;
> +}
> +
> +late_initcall(diglim_fs_init);
> diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h
> index 547425c20e11..ac45e1599c2d 100644
> --- a/security/integrity/integrity.h
> +++ b/security/integrity/integrity.h
> @@ -6,6 +6,9 @@
>   * Mimi Zohar <zohar@us.ibm.com>
>   */
>  
> +#ifndef __INTEGRITY_H
> +#define __INTEGRITY_H
> +
>  #ifdef pr_fmt
>  #undef pr_fmt
>  #endif
> @@ -283,3 +286,4 @@ static inline void __init add_to_platform_keyring(const char *source,
>  {
>  }
>  #endif
> +#endif /*__INTEGRITY_H*/

  reply	other threads:[~2021-07-28 12:40 UTC|newest]

Thread overview: 47+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-07-26 16:36 [RFC][PATCH v2 00/12] integrity: Introduce DIGLIM Roberto Sassu
2021-07-26 16:36 ` [RFC][PATCH v2 01/12] diglim: Overview Roberto Sassu
2021-07-28 11:10   ` Mauro Carvalho Chehab
2021-07-28 11:40     ` Roberto Sassu
2021-07-26 16:36 ` [RFC][PATCH v2 02/12] diglim: Basic definitions Roberto Sassu
2021-07-27 14:43   ` Greg KH
2021-07-27 15:35     ` Roberto Sassu
2021-07-27 15:44       ` Greg KH
2021-07-27 16:09         ` Roberto Sassu
2021-07-27 16:13           ` Greg KH
2021-07-28  6:59             ` Roberto Sassu
2021-07-28 11:31   ` Mauro Carvalho Chehab
2021-07-28 11:45     ` Roberto Sassu
2021-07-28 13:08       ` Mauro Carvalho Chehab
2021-07-28 13:47         ` Roberto Sassu
2021-07-26 16:36 ` [RFC][PATCH v2 03/12] diglim: Objects Roberto Sassu
2021-07-28 11:38   ` Mauro Carvalho Chehab
2021-07-28 11:47     ` Roberto Sassu
2021-07-26 16:36 ` [RFC][PATCH v2 04/12] diglim: Methods Roberto Sassu
2021-07-28 12:18   ` Mauro Carvalho Chehab
2021-07-28 12:30     ` Roberto Sassu
2021-07-26 16:36 ` [RFC][PATCH v2 05/12] diglim: Parser Roberto Sassu
2021-07-28 12:35   ` Mauro Carvalho Chehab
2021-07-26 16:36 ` [RFC][PATCH v2 06/12] diglim: Interfaces - digest_list_add, digest_list_del Roberto Sassu
2021-07-28 12:38   ` Mauro Carvalho Chehab [this message]
2021-07-29 21:20   ` Mimi Zohar
2021-07-30  7:16     ` Roberto Sassu
2021-07-30 12:39       ` Mimi Zohar
2021-07-30 13:16         ` Roberto Sassu
2021-07-30 14:03           ` Mimi Zohar
2021-07-30 14:24             ` Roberto Sassu
2021-08-02  8:14               ` Roberto Sassu
2021-08-02 15:01                 ` Mimi Zohar
2021-08-02 14:42           ` Mimi Zohar
2021-08-02 15:12             ` Roberto Sassu
2021-08-02 16:54             ` Roberto Sassu
2021-08-05 15:38               ` Mimi Zohar
2021-08-05 17:04                 ` Roberto Sassu
2021-07-26 16:36 ` [RFC][PATCH v2 07/12] diglim: Interfaces - digest_lists_loaded Roberto Sassu
2021-07-26 16:36 ` [RFC][PATCH v2 08/12] diglim: Interfaces - digest_label Roberto Sassu
2021-07-26 16:36 ` [RFC][PATCH v2 09/12] diglim: Interfaces - digest_query Roberto Sassu
2021-07-26 16:36 ` [RFC][PATCH v2 10/12] diglim: Interfaces - digests_count Roberto Sassu
2021-07-28 12:45   ` Mauro Carvalho Chehab
2021-07-26 16:36 ` [RFC][PATCH v2 11/12] diglim: Remote Attestation Roberto Sassu
2021-07-28 12:47   ` Mauro Carvalho Chehab
2021-07-28 12:54     ` Roberto Sassu
2021-07-26 16:37 ` [RFC][PATCH v2 12/12] diglim: Tests Roberto Sassu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210728143842.2db6e28c@sal.lan \
    --to=mchehab+huawei@kernel.org \
    --cc=gregkh@linuxfoundation.org \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-integrity@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=linux-security-module@vger.kernel.org \
    --cc=roberto.sassu@huawei.com \
    --cc=zohar@linux.ibm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.